Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ mv /workspace/examples/welcome.md /workspace/examples/README.md
screen -L -Logfile /tmp/direnv.log -S direnv-setup -dm \
sh -c "find /workspace/examples -mindepth 1 -type d -exec sh -c 'echo show_readme > {}/.envrc' \;"

# Start localstack in the background, since it can take a little bit to start up
cd /workspace/examples/demo-localstack
screen -L -Logfile /tmp/localstack.log -S localstack -dm sh -c 'docker compose up'
# Start Floci (LocalStack-compatible AWS emulator) in the background, since it can take a little bit to start up
cd /workspace/examples/demo-floci
screen -L -Logfile /tmp/floci.log -S floci -dm sh -c 'docker compose up'

# Start k3s in the background, since it can take a little bit to start up
# Note, it will mount . to the container and write the kubeconfig.yaml file
Expand Down
32 changes: 12 additions & 20 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -311,34 +311,26 @@ jobs:
category: hadolint
wait-for-processing: true

# run localstack demo tests
localstack:
name: "[localstack] ${{ matrix.demo-folder }}"
# Run the AWS-emulator demo tests against Floci (a free, LocalStack-compatible emulator;
# LocalStack Community Edition was EOL'd in March 2026).
# NOTE: "[floci] demo-floci" must be kept in sync with the required status checks in
# branch protection on main (previously "[localstack] demo-localstack").
floci:
name: "[floci] ${{ matrix.demo-folder }}"
needs: build
runs-on: ubuntu-latest

services:
localstack:
image: public.ecr.aws/localstack/localstack:1.4.0
floci:
image: floci/floci:1.5.23
ports:
- 4566:4566
- 4510-4559:4510-4559
env:
SERVICES: s3, iam, lambda, dynamodb, sts, account, ec2
DEBUG: 0
DOCKER_HOST: unix:///var/run/docker.sock
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_REGION: us-east-1
volumes:
- /var/run/docker.sock:/var/run/docker.sock

strategy:
fail-fast: false
matrix:
demo-folder:
- demo-localstack
- demo-floci

timeout-minutes: 20
steps:
Expand Down Expand Up @@ -564,7 +556,7 @@ jobs:
# - demo-custom-command
# - demo-json-validation
# - demo-library
# - demo-localstack
# - demo-floci
# - demo-opa-validation
# - demo-opentofu
# - demo-project
Expand Down Expand Up @@ -621,7 +613,7 @@ jobs:
matrix:
demo-folder:
- demo-context
- demo-localstack
- demo-floci
- demo-stacks
- demo-helmfile
- quick-start-advanced
Expand All @@ -647,7 +639,7 @@ jobs:
}

release:
needs: [test, lint, mock, k3s, localstack, docker, validate]
needs: [test, lint, mock, k3s, floci, docker, validate]
if: github.event_name == 'push'
uses: cloudposse/.github/.github/workflows/shared-go-auto-release.yml@main
with:
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Think of each demo folder as representing an example of a standalone repository.
2. ├── demo-library/ # Explore a reusable component library designed for seamless vendoring.
3. ├── demo-vendoring/ # Learn how to use vendoring to download and integrate remote dependencies from the `demo-library`.
4. ├── demo-validation/ # Validate your configurations to ensure correctness and compliance.
5. ├── demo-localstack/ # Leverage LocalStack to provision an S3 bucket using Atmos and Terraform.
5. ├── demo-floci/ # Leverage Floci (LocalStack-compatible AWS emulator) to provision an S3 bucket using Atmos and Terraform.
6. ├── demo-helmfile/ # Deploy NGINX on a local lightweight Kubernetes cluster (k3s) using Helm.
7. ├── custom-commands/ # Learn how to extend Atmos with your own custom CLI commands.
8. ├── demo-component-versions/ # Discover how to manage and use multiple versions of components effectively.
Expand Down
File renamed without changes.
29 changes: 29 additions & 0 deletions examples/demo-floci/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

## Notes

This example provisions an S3 bucket against [Floci](https://github.com/floci-io/floci), a free, MIT-licensed AWS emulator that is a drop-in replacement for LocalStack Community Edition (which was EOL'd in March 2026). Floci listens on the same `4566` edge port and accepts the same `test`/`test` credentials.

When running Terraform with Floci, this example uses path-style S3 on `http://localhost:4566` and enables `skip_requesting_account_id` so the AWS provider does not block on account identity lookups or wildcard DNS/TLS resolution in CI. Without these settings, Terraform can hang before printing the first plan when emulator-backed provider setup is slow or incomplete.

The following Terraform warning is expected with this setting:

```console
Warning: AWS account ID not found for provider
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on providers.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
│ See
│ https://registry.terraform.io/providers/hashicorp/aws/latest/docs#skip_requesting_account_id
│ for implications.
```

Start and stop the emulator with the demo's custom commands:

```shell
atmos floci up # start Floci in the background
atmos floci status # show emulator status
atmos floci reset # wipe all emulator state
atmos floci down # stop Floci
```
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ logs:
file: "/dev/stderr"
level: Info

# Authentication configuration with LocalStack support
# Authentication configuration with Floci support
auth:
identities:
localstack-superuser:
floci-superuser:
kind: aws/user
credentials:
access_key_id: test
Expand Down Expand Up @@ -60,45 +60,45 @@ commands:
- atmos terraform destroy demo -s prod -auto-approve

# Use Nested Custom Commands to provide easier interface for Docker Compose
- name: "localstack"
- name: "floci"
commands:
- name: "up"
description: Start lockstack in the background
description: Start Floci in the background
steps:
- |
container_running=$(docker ps -q -f "name=localstack")
container_running=$(docker ps -q -f "name=floci")
if [ -n "$container_running" ]; then
echo "LocalStack is already running; run \`atmos localstack down\` to stop it"
echo "Floci is already running; run \`atmos floci down\` to stop it"
else
docker compose up -d --wait
fi

- name: "down"
description: Stop localstack
description: Stop Floci
steps:
- docker compose down

- name: "restart"
description: Restart localstack
description: Restart Floci
steps:
- docker compose restart

- name: "reset"
description: Reset localstack (delete all data)
description: Reset Floci (delete all data)
steps:
- docker compose down
- rm -rf volume/
- docker compose up -d

- name: "status"
description: Show the status of LocalStack
description: Show the status of Floci
steps:
- |
container_running=$(docker ps -q -f "name=localstack")
container_running=$(docker ps -q -f "name=floci")
if [ -n "$container_running" ]; then
docker compose ps --format "{{`{{.Service}} is {{.State}}`}}"
else
echo "LocalStack is not running; run \`atmos localstack up\` to start it"
echo "Floci is not running; run \`atmos floci up\` to start it"
fi

- name: "terraform"
Expand Down
17 changes: 17 additions & 0 deletions examples/demo-floci/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
services:
floci:
container_name: floci
image: floci/floci:1.5.23
ports:
- "0.0.0.0:4566:4566" # Floci Gateway (LocalStack-compatible edge port)
networks:
- floci
environment:
- FLOCI_STORAGE_MODE=persistent
- FLOCI_STORAGE_PERSISTENT_PATH=/data
volumes:
- "${FLOCI_VOLUME_DIR:-./volume}:/data"

networks:
floci:
driver: bridge
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# yaml-language-server: $schema=https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

import:
- mixins/localstack
- mixins/floci
- catalog/demo

vars:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# yaml-language-server: $schema=https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

import:
- mixins/localstack
- mixins/floci
- catalog/demo

vars:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# yaml-language-server: $schema=https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

import:
- mixins/localstack
- mixins/floci
- catalog/demo

vars:
Expand Down
43 changes: 43 additions & 0 deletions examples/demo-floci/stacks/mixins/floci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# yaml-language-server: $schema=https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

env:
# We need to ensure no profile is set when using Floci, or the AWS SDK will try to use it
AWS_PROFILE: ""
TF_CLI_ARGS_plan: "-compact-warnings"
TF_CLI_ARGS_apply: "-compact-warnings"

terraform:
providers:
aws:
region: "us-east-1"
access_key: "test"
secret_key: "test"
s3_use_path_style: true
skip_credentials_validation: true
skip_metadata_api_check: true
skip_requesting_account_id: true
endpoints:
# An alias for the default Floci URL exposed by the GitHub Actions service.
sts: &floci_url "http://localhost:4566"

# Use path-style S3 on localhost to avoid wildcard DNS/TLS flakiness in CI.
s3: *floci_url

# Everything else can use HTTP on localhost
apigateway: *floci_url
apigatewayv2: *floci_url
cloudformation: *floci_url
cloudwatch: *floci_url
dynamodb: *floci_url
ec2: *floci_url
es: *floci_url
elasticache: *floci_url
iam: *floci_url
lambda: *floci_url
rds: *floci_url
route53: *floci_url
secretsmanager: *floci_url
ses: *floci_url
sns: *floci_url
sqs: *floci_url
ssm: *floci_url
18 changes: 0 additions & 18 deletions examples/demo-localstack/README.md

This file was deleted.

22 changes: 0 additions & 22 deletions examples/demo-localstack/docker-compose.yml

This file was deleted.

43 changes: 0 additions & 43 deletions examples/demo-localstack/stacks/mixins/localstack.yaml

This file was deleted.

4 changes: 2 additions & 2 deletions internal/exec/copy_glob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ func TestGetMatchesForPattern_RecursiveMatch(t *testing.T) {

// TestIsShallowPattern ensures shallow pattern detection works.
func TestIsShallowPattern(t *testing.T) {
if !isShallowPattern("**/demo-localstack/*") {
t.Errorf("Expected '**/demo-localstack/*' to be shallow")
if !isShallowPattern("**/demo-helmfile/*") {
t.Errorf("Expected '**/demo-helmfile/*' to be shallow")
}
if isShallowPattern("**/demo-library/**") {
t.Errorf("Expected '**/demo-library/**' not to be shallow")
Expand Down
6 changes: 3 additions & 3 deletions pkg/auth/cloud/aws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ The custom endpoint resolver is automatically applied when:

All AWS SDK calls will be directed to the configured endpoint URL.

### LocalStack Example
### Floci Example

For a complete LocalStack example, see:
- `/examples/demo-localstack/atmos.yaml`
For a complete AWS emulator example, see:
- `/examples/demo-floci/atmos.yaml`

### Implementation Details

Expand Down
Loading
Loading