Stelvio Framework

repository·main·Indexed 43 days ago

https://github.com/stelviodev/stelvio

An open-source framework for building and deploying AWS applications using pure Python. Stelvio abstracts infrastructure tasks like IAM roles, networking, and YAML configuration, providing high-level abstractions for AWS Lambda, DynamoDB, API Gateway, AppSync, S3, SQS, SNS, and more. It includes the stlv CLI for project initialization, deployment, and a Live Dev Mode for instant code synchronization.

Tokens
82.7K
Snippets
251
Records
311
Agent score
52%

What's inside Stelvio

  1. Overview of Stelvio

    main

    Stelvio is a Python framework designed to simplify AWS development. It allows developers to build and deploy AWS applications using pure Python code and a simple CLI, abstracting away complex infrastructure tools like YAML/JSON configurations, IAM role management, and manual AWS console interactions.

    Supported AWS Components:

    • Lambda
    • API Gateway (REST, HTTP, and Websocket APIs)
    • DynamoDB
    • S3
    • SQS
    • SNS
    • SES
    • Custom domains and CloudFront routing
    • Cron (EventBridge)
    • AppSync
    • Cognito

    Note: Stelvio is currently in beta. While core features are stable, APIs may evolve.

  2. Working with AppSync in Stelvio

    main

    Stelvio provides the AppSync component to create and manage AWS AppSync GraphQL APIs. AppSync acts as a managed GraphQL service that connects your API to various data sources like Lambda functions, DynamoDB, or HTTP endpoints.

    When to use AppSync vs API Gateway

    Use AppSync for...Use API Gateway for...
    GraphQL API with schema-first designREST endpoints
    Real-time subscriptions (WebSockets)Simple request/response patterns
    Multiple data sources in one queryCustom WebSocket protocols
    Per-field authorization via directives
  3. What is Linking in Stelvio?

    main

    Linking is a mechanism that automates IAM permission management and environment variable configuration between AWS resources. A Link represents a connection between two resources and defines two key aspects:

    1. Permissions: The IAM policies that allow one resource to interact with another (e.g., a Lambda function accessing a DynamoDB table).
    2. Properties: Key-value pairs shared between resources (e.g., environment variables passed to a Lambda function).

    Resources that support linking implement the Linkable protocol, which provides a link() method returning a Link object containing appropriate default permissions and properties.

  4. Configure Auto-tags

    main

    Stelvio automatically applies two specific tags to every resource created. You do not need to configure these manually; they are always present.

    TagValueDescription
    stelvio:appThe app name from StelvioApp("name")Identifies the application
    stelvio:envThe current deployment environmente.g., dev, staging, prod
  5. Default Link Permissions for DynamoDB and Lambda

    main

    When you link a DynamoTable to a Lambda function or an API route, Stelvio automatically configures the following:

    IAM Permissions:

    • dynamodb:Scan
    • dynamodb:Query
    • dynamodb:GetItem
    • dynamodb:PutItem
    • dynamodb:UpdateItem
    • dynamodb:DeleteItem

    Environment Variables:

    • STLV_{TABLE_NAME}_TABLE_ARN
    • STLV_{TABLE_NAME}_TABLE_NAME
  6. Override DNS provider for the Email component

    main
    While most components use the global DNS provider defined in StelvioAppConfig, the Email component allows a per-component DNS override via the dns parameter. This is useful if your email sender domain is managed by a different provider (e.g., Route 53) than your main application domain (e.g., Cloudflare).
  7. Choose between Regional and Edge-optimized endpoints

    main

    The endpoint_type configuration determines how your API is distributed:

    • "regional": Best for applications serving users in a specific AWS region. Offers lower latency for regional users and simpler configuration.
    • "edge": Best for global applications. Uses CloudFront to cache responses at edge locations worldwide for better global performance.
    # Regional endpoint (default)
    api = RestApi('my-api', endpoint_type='regional')
    
    # Edge-optimized endpoint
    api = RestApi('my-api', endpoint_type='edge')
  8. Define infrastructure in the @app.run block

    main

    All infrastructure definitions (like DynamoDB tables and REST APIs) must be placed inside the function decorated with @app.run.

    When you run stlv diff or stlv deploy, Stelvio generates a stlv_resources.py file. This file contains a Resources class that provides type-safe access to your infrastructure's metadata (like table names or ARNs) within your Lambda function code.

    from stelvio.app import StelvioApp
    from stelvio.aws.dynamo_db import DynamoTable, FieldType
    from stelvio.aws.api_gateway import RestApi
    
    app = StelvioApp("stelvio-app")
    
    @app.run
    def run() -> None:
        # Define a DynamoDB table
        table = DynamoTable(
            name="todos",
            fields={
                "username": FieldType.STRING,
                "created": FieldType.STRING,
            },
            partition_key="username",
            sort_key='created'
        )
        
        # Define a REST API and its routes
        api = RestApi("todo-api")
        # The 'links' argument automates IAM permissions and env vars for the handler
        api.route("POST", "/todos", handler="functions/todos.post", links=[table])
        api.route("GET", "/todos/{username}", handler="functions/todos.get")
  9. How the CloudFront Router works

    main

    The CloudFront Router is a component used to expose multiple Stelvio components (like S3 Buckets or APIs) under a single domain. It acts as a gateway that maps incoming request paths to specific origins.

    Key behaviors:

    • Path Stripping: When a route is defined (e.g., router.route("/api", api)), the router strips the prefix before forwarding the request. A request to /api/users reaches the API at /users.
    • Automatic Path Specificity: Stelvio automatically sorts routes by specificity. Longer, more specific paths take precedence over shorter ones, regardless of the order they are defined in your code.
    • Catch-all: The root path / acts as a catch-all. If no root path is defined, unmatched requests return a 404.
    • Origin Uniqueness: Each component or external URL can only be routed to a single path. You cannot point multiple routes to the same origin.
    @app.run
    def run() -> None:
        domain_name = "example.com"
    
        bucket = Bucket("static-files-bucket")
        api = RestApi("my-api")
        api.route("GET", "/", "functions/hello.handler")
    
        # Creating the CloudFront Router
        router = Router("rtr-test", custom_domain=domain_name)
        
        # Mapping paths to components
        router.route("/files", bucket)
        router.route("/api", api)
  10. Understand Tag Precedence

    main

    When the same tag key is defined at multiple levels, Stelvio follows a specific order of precedence. Higher-specificity layers override lower-priority ones:

    1. customize overrides (highest priority)
    2. Component tags (tags=... on a component)
    3. Global tags (StelvioAppConfig.tags)
    4. Auto-tags (stelvio:app, stelvio:env) (lowest priority)

    Example of precedence behavior: If a Global tag sets Shared=global and a Component tag sets Shared=component, the resulting resource will have Shared=component.

    from stelvio.aws.queue import Queue
    from stelvio.config import StelvioAppConfig
    
    @app.config
    def config(env: str) -> StelvioAppConfig:
        # Sets 'Shared=global'
        return StelvioAppConfig(tags={"Shared": "global", "GlobalOnly": "yes"})
    
    @app.run
    def run() -> None:
        # Sets 'Shared=component' (overriding global) and 'ComponentOnly=yes'
        Queue("jobs", tags={"Shared": "component", "ComponentOnly": "yes"})
  11. How AWS resource tagging works in Stelvio

    main

    Stelvio uses a layered tagging system to attach key-value pairs to AWS resources. This allows for cost tracking, resource identification, and policy enforcement in the AWS console and Cost Explorer.

    There are three primary layers of tags:

    1. Auto-tags: Automatically applied to every resource by Stelvio.
    2. Global tags: Defined in StelvioAppConfig and applied to all components in the application.
    3. Component tags: Defined on a per-component basis for fine-grained control.

    Tags are applied via the AWS provider's default_tags mechanism where possible, ensuring broad coverage across taggable resources.

    from stelvio.app import StelvioApp
    from stelvio.config import StelvioAppConfig
    from stelvio.aws.queue import Queue
    
    app = StelvioApp("my-app")
    
    # 1. Global Tags
    @app.config
    def config(env: str) -> StelvioAppConfig:
        return StelvioAppConfig(
            tags={
                "Team": "platform",
                "CostCenter": "infra",
            }
        )
    
    # 2. Component Tags
    orders = Queue(
        "orders",
        tags={
            "Service": "checkout",
            "Owner": "payments-team",
        },
    )
  12. Configure route precedence and ordering

    main

    Stelvio handles route precedence automatically based on path length. You do not need to worry about the order in which you call .route(); the most specific path will always win.

    Important Rule: All routes must be added to the Router instance before its resources are created. Attempting to add routes after the CloudFront distribution has been provisioned will raise a RuntimeError.

    router = Router("MyRouter")
    # Even if defined second, this more specific path takes priority
    router.route("/api", api)           
    router.route("/api/admin", admin)