diff --git a/README.md b/README.md index 0885bbf..ad47e59 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE) [![LocalStack Dagger Module Tests](https://github.com/localstack/localstack-dagger-module/actions/workflows/test.yml/badge.svg)](https://github.com/localstack/localstack-dagger-module/actions/workflows/test.yml) -A [Dagger](https://dagger.io/) module for running [LocalStack](https://github.com/localstack/localstack) (Community and Pro image) as a service within your Dagger pipelines. +A [Dagger](https://dagger.io/) module for running [LocalStack](https://github.com/localstack/localstack) as a service within your Dagger pipelines. This module simplifies integrating LocalStack into your development and testing workflows by: -- Starting LocalStack Community or Pro editions as a Dagger service. +- Starting LocalStack as a Dagger service. - Securely handling LocalStack Auth Tokens using Dagger secrets. -- Automatically exposing standard LocalStack ports (`4566` for Community/Pro, `443` for Pro). +- Automatically exposing standard LocalStack ports (`4566` and `443`). - Allowing customization of the LocalStack container via environment variables. - Optionally mounting the Docker socket for tests interacting with external containers. - Managing LocalStack state using [Cloud Pods](https://docs.localstack.cloud/user-guide/state-management/cloud-pods/) (`save`/`load`/`reset`). @@ -19,7 +19,7 @@ This module simplifies integrating LocalStack into your development and testing - [Dagger CLI installed](https://docs.dagger.io/install) - Docker or a compatible container runtime -- LocalStack Auth Token (required for Pro features, Cloud Pods, and Ephemeral Instances) +- LocalStack Auth Token (required) ## Installation @@ -33,31 +33,19 @@ You can then call its functions from the Dagger CLI or your Dagger SDK code. ## Usage -### Start LocalStack Community +### Start LocalStack -This is the simplest way to start the default LocalStack Community edition. - -```bash -dagger -m github.com/localstack/localstack-dagger-module call start up -``` - -LocalStack will run and be accessible at `localhost:4566` and with any integration that LocalStack supports. - -### Start LocalStack Pro - -To use LocalStack Pro features, Cloud Pods, or Ephemeral Instances, you need an Auth Token. - -```bash -# 1. Set your LocalStack Pro auth token as an environment variable -export LOCALSTACK_AUTH_TOKEN="your-pro-token" +```bash +# 1. Set your LocalStack auth token as an environment variable +export LOCALSTACK_AUTH_TOKEN="your-token" -# 2. Start LocalStack Pro using the token from the environment +# 2. Start LocalStack using the token from the environment dagger -m github.com/localstack/localstack-dagger-module \ call start --auth-token=env:LOCALSTACK_AUTH_TOKEN \ up ``` -If the token is invalid or missing when Pro usage is implied, LocalStack might behave unexpectedly or functionality might be limited. +LocalStack will run and be accessible at `localhost:4566` and with any integration that LocalStack supports. ### Customizing LocalStack @@ -74,7 +62,7 @@ dagger -m github.com/localstack/localstack-dagger-module call start \ To run emulated AWS services that rely on a container, like Lambda or ECS, you would need to mount Docker Socket into the LocalStack container. -```bash +```bash dagger -m github.com/localstack/localstack-dagger-module call start \ --auth-token=env:LOCALSTACK_AUTH_TOKEN \ --docker-sock /var/run/docker.sock \ @@ -83,11 +71,11 @@ dagger -m github.com/localstack/localstack-dagger-module call start \ ### Managing State with Cloud Pods -Cloud pods are persistent state snapshots of your LocalStack instance that can easily be stored, versioned, shared, and restored. Cloud Pods require a LocalStack Auth Token. +Cloud pods are persistent state snapshots of your LocalStack instance that can easily be stored, versioned, shared, and restored. -```bash +```bash # Set your auth token -export LOCALSTACK_AUTH_TOKEN="your-pro-token" +export LOCALSTACK_AUTH_TOKEN="your-token" # Save the current state of your running LocalStack instance to a Cloud Pod # Assumes you have a running instance started via 'dagger call start ... up' @@ -108,11 +96,11 @@ dagger -m github.com/localstack/localstack-dagger-module call state \ ### Managing Ephemeral Instances -Ephemeral Instances allows you to run a LocalStack instance in the cloud. Ephemeral Instances require a LocalStack Pro Auth Token. +Ephemeral Instances allows you to run a LocalStack instance in the cloud. ```bash # Set your auth token -export LOCALSTACK_AUTH_TOKEN="your-pro-token" +export LOCALSTACK_AUTH_TOKEN="your-token" # Create a new Ephemeral Instance in LocalStack Cloud dagger -m github.com/localstack/localstack-dagger-module call ephemeral \ @@ -141,24 +129,24 @@ dagger -m github.com/localstack/localstack-dagger-module call ephemeral \ ## Inputs -### `start` +### `start` Used to configure and start the main LocalStack service. -| Input | Description | Default | Example | -| --------------- | --------------------------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------- | -| `auth-token` | LocalStack Pro auth token (as Dagger `Secret`). Required for Pro features. | `None` | `dagger call start --auth-token=env:LOCALSTACK_AUTH_TOKEN` | -| `configuration` | Comma-separated `KEY=VALUE` pairs for LocalStack environment variables. | `None` | `dagger call start --configuration='DEBUG=1,PERSISTENCE=1'` | -| `docker-sock` | Path to the Unix socket for the Docker daemon to mount into the container. | `None` | `dagger call start --docker-sock=/var/run/docker.sock` | -| `image-name` | Custom LocalStack Docker image name and tag. | `localstack/localstack:latest` | `dagger call start --image-name=localstack/snowflake:latest` | +| Input | Description | Default | Example | +| --------------- | --------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------ | +| `auth-token` | LocalStack Auth Token (as Dagger `Secret`). Required. | Required | `dagger call start --auth-token=env:LOCALSTACK_AUTH_TOKEN` | +| `configuration` | Comma-separated `KEY=VALUE` pairs for LocalStack environment variables. | `None` | `dagger call start --configuration='DEBUG=1,PERSISTENCE=1'` | +| `docker-sock` | Path to the Unix socket for the Docker daemon to mount into the container. | `None` | `dagger call start --docker-sock=/var/run/docker.sock` | +| `image-name` | Custom LocalStack Docker image name and tag. | `localstack/localstack:latest` | `dagger call start --image-name=localstack/snowflake:latest` | ### `state` -Used to manage the state of a running LocalStack instance using Cloud Pods (Pro only). +Used to manage the state of a running LocalStack instance using Cloud Pods. -| Input | Description | Default | Example | -| ------------ | ------------------------------------------------------------------------------------ | ---------------------------- | ------------------------------------------------ | -| `auth-token` | LocalStack Pro Auth Token (as Dagger `Secret`). Required for `save` and `load`. | `None` | `dagger call state --auth-token=env:LOCALSTACK_AUTH_TOKEN` | +| Input | Description | Default | Example | +| ------------ | ------------------------------------------------------------------------------- | ---------------------------- | ------------------------------------------------ | +| `auth-token` | LocalStack Auth Token (as Dagger `Secret`). Required for `save` and `load`. | `None` | `dagger call state --auth-token=env:LOCALSTACK_AUTH_TOKEN` | | `load` | Name of the LocalStack Cloud Pod to load into the running instance. | `None` | `dagger call state --load=my-pod` | | `save` | Name under which to save the current state as a LocalStack Cloud Pod. | `None` | `dagger call state --save=my-pod` | | `reset` | If `true`, resets the state of the running LocalStack instance. | `False` | `dagger call state --reset` | @@ -166,11 +154,11 @@ Used to manage the state of a running LocalStack instance using Cloud Pods (Pro ### `ephemeral` -Used to manage LocalStack Ephemeral Instances in LocalStack Cloud (Pro only). +Used to manage LocalStack Ephemeral Instances in LocalStack Cloud. | Input | Description | Default | Example | | ------------------------ | ---------------------------------------------------------------------------------------------------------- | --------- | -------------------------------------------------------- | -| `auth-token` | LocalStack Pro Auth Token (as Dagger `Secret`). Required for all operations. | Required | `dagger call ephemeral --auth-token=env:LOCALSTACK_AUTH_TOKEN` | +| `auth-token` | LocalStack Auth Token (as Dagger `Secret`). Required for all operations. | Required | `dagger call ephemeral --auth-token=env:LOCALSTACK_AUTH_TOKEN` | | `operation` | Action to perform: `create`, `list`, `delete`, `logs`. | Required | `dagger call ephemeral --operation=create` | | `name` | Name of the ephemeral instance. Required for `create`, `delete`, `logs`. | `None` | `dagger call ephemeral --name=my-instance` | | `lifetime` | Lifetime of the instance in minutes (only for `create` operation). | `60` | `dagger call ephemeral --lifetime=120` | diff --git a/examples/golang/main.go b/examples/golang/main.go index 132aa32..5b9e760 100644 --- a/examples/golang/main.go +++ b/examples/golang/main.go @@ -23,8 +23,8 @@ import ( type Golang struct{} // Starts LocalStack and performs example S3 operations -func (m *Golang) LocalstackQuickstart(ctx context.Context) (string, error) { - service := dag.Localstack().Start() +func (m *Golang) LocalstackQuickstart(ctx context.Context, authToken *dagger.Secret) (string, error) { + service := dag.Localstack().Start(authToken) // Start the service and get endpoint if _, err := service.Start(ctx); err != nil { @@ -103,16 +103,14 @@ S3 object content: %s`, endpoint, string(data)) return output, nil } -// Starts LocalStack Pro with custom configuration and creates an ECR repository +// Starts LocalStack with custom configuration and creates an ECR repository func (m *Golang) LocalstackPro(ctx context.Context, authToken *dagger.Secret) (string, error) { - // Start LocalStack Pro using the module with custom configuration - service := dag.Localstack().Start(dagger.LocalstackStartOpts{ - AuthToken: authToken, - }) + // Start LocalStack using the module with custom configuration + service := dag.Localstack().Start(authToken) // Start the service and wait for it to be ready if _, err := service.Start(ctx); err != nil { - return "", fmt.Errorf("failed to start LocalStack Pro: %w", err) + return "", fmt.Errorf("failed to start LocalStack: %w", err) } endpoint, err := service.Endpoint(ctx) @@ -152,7 +150,7 @@ func (m *Golang) LocalstackPro(ctx context.Context, authToken *dagger.Secret) (s return "", fmt.Errorf("failed to create ECR repository: %w", err) } - output := fmt.Sprintf(`LocalStack Pro is running at %s + output := fmt.Sprintf(`LocalStack is running at %s ECR repository '%s' created`, endpoint, repositoryName) return output, nil @@ -160,14 +158,12 @@ ECR repository '%s' created`, endpoint, repositoryName) // Demonstrates LocalStack state management using Cloud Pods func (m *Golang) LocalstackState(ctx context.Context, authToken *dagger.Secret) (string, error) { - // Start LocalStack Pro - service := dag.Localstack().Start(dagger.LocalstackStartOpts{ - AuthToken: authToken, - }) + // Start LocalStack + service := dag.Localstack().Start(authToken) // Start the service and wait for it to be ready if _, err := service.Start(ctx); err != nil { - return "", fmt.Errorf("failed to start LocalStack Pro: %w", err) + return "", fmt.Errorf("failed to start LocalStack: %w", err) } endpoint, err := service.Endpoint(ctx) diff --git a/examples/python/src/example/main.py b/examples/python/src/example/main.py index 14a8a84..921a856 100644 --- a/examples/python/src/example/main.py +++ b/examples/python/src/example/main.py @@ -6,9 +6,9 @@ @object_type class Example: @function - async def localstack__quickstart(self) -> str: - """Example showing how to start LocalStack Community edition.""" - service = dag.localstack().start() + async def localstack__quickstart(self, auth_token: dagger.Secret) -> str: + """Example showing how to start LocalStack.""" + service = dag.localstack().start(auth_token=auth_token) await service.start() endpoint = await service.endpoint() @@ -41,8 +41,8 @@ async def localstack__quickstart(self) -> str: @function async def localstack__pro(self, auth_token: dagger.Secret) -> str: - """Example showing how to start LocalStack Pro with custom configuration.""" - # Start LocalStack Pro using the module + """Example showing how to start LocalStack with custom configuration.""" + # Start LocalStack using the module service = dag.localstack().start( auth_token=auth_token, configuration="DEBUG=1,SERVICES=ecr" @@ -50,7 +50,7 @@ async def localstack__pro(self, auth_token: dagger.Secret) -> str: await service.start() endpoint = await service.endpoint() - print(f"LocalStack Pro is running at {endpoint}") + print(f"LocalStack is running at {endpoint}") # Create a test ECR repository ecr = boto3.client( diff --git a/examples/shell/localstack_dagger_module_ephemeral.sh b/examples/shell/localstack_dagger_module_ephemeral.sh index 8084628..7a7fd86 100644 --- a/examples/shell/localstack_dagger_module_ephemeral.sh +++ b/examples/shell/localstack_dagger_module_ephemeral.sh @@ -3,7 +3,7 @@ # Check if LOCALSTACK_AUTH_TOKEN is set if [ -z "$LOCALSTACK_AUTH_TOKEN" ]; then echo "Error: LOCALSTACK_AUTH_TOKEN environment variable is not set" - echo "Please set your LocalStack Pro auth token:" + echo "Please set your LocalStack auth token:" echo "export LOCALSTACK_AUTH_TOKEN='your-token-here'" exit 1 fi diff --git a/examples/shell/localstack_dagger_module_pro.sh b/examples/shell/localstack_dagger_module_pro.sh index 6c0f23d..7efcff0 100644 --- a/examples/shell/localstack_dagger_module_pro.sh +++ b/examples/shell/localstack_dagger_module_pro.sh @@ -3,12 +3,12 @@ # Check if LOCALSTACK_AUTH_TOKEN is set if [ -z "$LOCALSTACK_AUTH_TOKEN" ]; then echo "Error: LOCALSTACK_AUTH_TOKEN environment variable is not set" - echo "Please set your LocalStack Pro auth token:" + echo "Please set your LocalStack auth token:" echo "export LOCALSTACK_AUTH_TOKEN='your-token-here'" exit 1 fi -# Start LocalStack Pro with custom configuration +# Start LocalStack with custom configuration dagger -m github.com/localstack/localstack-dagger-module \ call start \ --auth-token=env:LOCALSTACK_AUTH_TOKEN \ @@ -17,11 +17,11 @@ dagger -m github.com/localstack/localstack-dagger-module \ up # Wait for LocalStack to be ready -echo "Waiting for LocalStack Pro to be ready..." +echo "Waiting for LocalStack to be ready..." sleep 5 # Test the deployment by checking LocalStack health curl http://localhost:4566/_localstack/health -echo "LocalStack Pro is now running!" +echo "LocalStack is now running!" echo "Access your AWS services at: http://localhost:4566" diff --git a/examples/shell/localstack_dagger_module_quickstart.sh b/examples/shell/localstack_dagger_module_quickstart.sh index 35e0d82..1bc06ae 100644 --- a/examples/shell/localstack_dagger_module_quickstart.sh +++ b/examples/shell/localstack_dagger_module_quickstart.sh @@ -1,7 +1,18 @@ #!/bin/bash -# Start LocalStack Community edition -dagger -m github.com/localstack/localstack-dagger-module call start up +# Check if LOCALSTACK_AUTH_TOKEN is set +if [ -z "$LOCALSTACK_AUTH_TOKEN" ]; then + echo "Error: LOCALSTACK_AUTH_TOKEN environment variable is not set" + echo "Please set your LocalStack auth token:" + echo "export LOCALSTACK_AUTH_TOKEN='your-token-here'" + exit 1 +fi + +# Start LocalStack +dagger -m github.com/localstack/localstack-dagger-module \ + call start \ + --auth-token=env:LOCALSTACK_AUTH_TOKEN \ + up # Wait for LocalStack to be ready echo "Waiting for LocalStack to be ready..." @@ -10,5 +21,5 @@ sleep 5 # Test the deployment by checking LocalStack health curl http://localhost:4566/_localstack/health -echo "LocalStack Community edition is now running!" +echo "LocalStack is now running!" echo "Access your AWS services at: http://localhost:4566" diff --git a/examples/shell/localstack_dagger_module_state.sh b/examples/shell/localstack_dagger_module_state.sh index a7be7c5..dcb70c3 100644 --- a/examples/shell/localstack_dagger_module_state.sh +++ b/examples/shell/localstack_dagger_module_state.sh @@ -7,12 +7,12 @@ export AWS_REGION=us-east-1 # Check if LOCALSTACK_AUTH_TOKEN is set if [ -z "$LOCALSTACK_AUTH_TOKEN" ]; then echo "Error: LOCALSTACK_AUTH_TOKEN environment variable is not set" - echo "Please set your LocalStack Pro auth token:" + echo "Please set your LocalStack auth token:" echo "export LOCALSTACK_AUTH_TOKEN='your-token-here'" exit 1 fi -# Start LocalStack Pro +# Start LocalStack dagger -m github.com/localstack/localstack-dagger-module \ call start \ --auth-token=env:LOCALSTACK_AUTH_TOKEN \ diff --git a/examples/typescript/src/index.ts b/examples/typescript/src/index.ts index 87db93f..cb37ef7 100644 --- a/examples/typescript/src/index.ts +++ b/examples/typescript/src/index.ts @@ -10,16 +10,17 @@ import { Readable } from "stream" @object() export class Example { /** - * Demonstrates basic LocalStack functionality using the community edition. + * Demonstrates basic LocalStack functionality. * Creates an S3 bucket and object to verify the setup is working correctly. - * + * + * @param authToken - LocalStack authentication token * @returns Promise */ @func() - async localstack__quickstart() { + async localstack__quickstart(authToken: Secret) { await connect(async (client) => { // Start LocalStack using the module - const service = client.localstack().start() + const service = client.localstack().start({ authToken }) await service.start() const endpoint = await service.endpoint() @@ -62,10 +63,10 @@ export class Example { } /** - * Demonstrates LocalStack Pro functionality by starting a Pro instance + * Demonstrates LocalStack functionality with custom configuration * and creating an ECR repository. - * - * @param authToken - LocalStack Pro authentication token + * + * @param authToken - LocalStack authentication token * @returns Promise */ @func() @@ -78,7 +79,7 @@ export class Example { await service.start() const endpoint = await service.endpoint() - console.log(`LocalStack Pro is running at ${endpoint}`) + console.log(`LocalStack is running at ${endpoint}`) // Create ECR client const ecr = new ECRClient({ @@ -102,8 +103,8 @@ export class Example { /** * Demonstrates LocalStack state management functionality using Cloud Pods. * Creates a test bucket, saves state to a pod, resets state, and loads it back. - * - * @param authToken - LocalStack Pro authentication token + * + * @param authToken - LocalStack authentication token * @returns Promise */ @func() @@ -163,8 +164,8 @@ export class Example { * Demonstrates LocalStack ephemeral instance management. * Creates an ephemeral instance, lists instances, retrieves logs, * and cleans up by deleting the instance. - * - * @param authToken - LocalStack Pro authentication token + * + * @param authToken - LocalStack authentication token * @returns Promise */ @func() diff --git a/src/localstack/__init__.py b/src/localstack/__init__.py index f856265..92c10fc 100644 --- a/src/localstack/__init__.py +++ b/src/localstack/__init__.py @@ -2,7 +2,7 @@ This module provides functions to start LocalStack containers, manage state through Cloud Pods, and handle ephemeral LocalStack instances in the cloud using LocalStack Cloud and an auth token. -This module supports both Community and Pro versions of LocalStack. +This module requires a LocalStack Auth Token for authentication. """ from .main import Localstack as Localstack diff --git a/src/localstack/main.py b/src/localstack/main.py index aeda42f..d35014a 100644 --- a/src/localstack/main.py +++ b/src/localstack/main.py @@ -14,47 +14,40 @@ class Localstack: @function def start( - self, - auth_token: Annotated[Optional[dagger.Secret], Doc("LocalStack Pro Auth Token for authentication")] = None, + self, + auth_token: Annotated[dagger.Secret, Doc("LocalStack Auth Token for authentication")], configuration: Annotated[Optional[str], Doc("Configuration variables in format 'KEY1=value1,KEY2=value2'")] = None, docker_sock: Annotated[Optional[dagger.Socket], Doc("Docker socket for container interactions")] = None, image_name: Annotated[Optional[str], Doc("Custom LocalStack image name to use")] = None ) -> dagger.Service: """Start a LocalStack service with appropriate configuration.""" # Determine image based on parameters - if image_name: - image = image_name - else: - image = "localstack/localstack-pro:latest" if auth_token else "localstack/localstack:latest" - + image = image_name if image_name else "localstack/localstack:latest" + # Start with base container config container = dag.container().from_(image) - + # Mount Docker socket if provided if docker_sock: container = container.with_unix_socket("/var/run/docker.sock", docker_sock) - - # Add Auth Token if provided - if auth_token: - container = container.with_secret_variable("LOCALSTACK_AUTH_TOKEN", auth_token) - + + # Add Auth Token + container = container.with_secret_variable("LOCALSTACK_AUTH_TOKEN", auth_token) + # Add configuration variables if provided if configuration: for config_pair in configuration.split(','): if '=' in config_pair: key, value = config_pair.strip().split('=', 1) container = container.with_env_variable(key, value) - - # Add common ports (4566) + + # Add common ports (4566 and 443) container = ( container .with_exposed_port(4566) + .with_exposed_port(443) ) - - # Add port 443 for Pro edition - if auth_token: - container = container.with_exposed_port(443) - + # Return as service return container.as_service() diff --git a/tests/src/tests/main.py b/tests/src/tests/main.py index 0f3fe26..234fdfd 100644 --- a/tests/src/tests/main.py +++ b/tests/src/tests/main.py @@ -13,16 +13,16 @@ class Tests: @function async def all(self, auth_token: dagger.Secret) -> str: """Run all tests""" - await self.test_localstack_health() + await self.test_localstack_health(auth_token=auth_token) await self.test_localstack_pro(auth_token=auth_token) await self.test_state_operations(auth_token=auth_token) await self.test_ephemeral_operations(auth_token=auth_token) @function - async def test_localstack_health(self) -> str: + async def test_localstack_health(self, auth_token: dagger.Secret) -> str: """Test if LocalStack starts and responds to /_localstack/info endpoint""" # Start LocalStack using the module - service = dag.localstack().start() + service = dag.localstack().start(auth_token=auth_token) await service.start() endpoint = await service.endpoint() @@ -46,7 +46,7 @@ async def test_localstack_health(self) -> str: @function async def test_localstack_pro(self, auth_token: dagger.Secret) -> str: """Test if LocalStack starts with Pro services available""" - # Start LocalStack Pro using the module + # Start LocalStack using the module service = dag.localstack().start(auth_token=auth_token) await service.start() @@ -75,7 +75,7 @@ async def test_localstack_pro(self, auth_token: dagger.Secret) -> str: @function async def test_state_operations(self, auth_token: dagger.Secret) -> str: """Test LocalStack state operations (save/load/reset) with AWS resources""" - # Start LocalStack Pro + # Start LocalStack service = dag.localstack().start(auth_token=auth_token) await service.start() endpoint = await service.endpoint()