From b53d696375a6716b2fd0bc024fb1861b46c78bb5 Mon Sep 17 00:00:00 2001 From: "Erik Osterman (CEO @ Cloud Posse)" Date: Tue, 25 Jun 2024 09:51:58 -0500 Subject: [PATCH] Reorganize Documentation For a Better Learning Journey (#612) --- .devcontainer/Dockerfile | 51 + .devcontainer/devcontainer.json | 80 + .devcontainer/post-create.sh | 28 + .../home/vscode/.config/direnv/direnvrc | 11 + .../rootfs/home/vscode/.config/starship.toml | 48 + .../first-run-notice-already-displayed | 0 .devcontainer/rootfs/home/vscode/.zsh_history | 12 + .devcontainer/rootfs/home/vscode/.zshrc | 37 + .github/workflows/test.yml | 211 +- .gitignore | 3 + README.md | 89 +- README.yaml | 27 +- atmos.yaml | 6 +- cmd/cmd_utils.go | 2 +- examples/.gitignore | 1 + examples/.tflint.hcl | 4 + examples/README.md | 61 + examples/demo-atlantis/.gitignore | 1 + examples/demo-atlantis/atmos.yaml | 103 + .../demo-atlantis/stacks/deploy/demo.yaml | 0 examples/demo-component-versions/.gitignore | 1 + examples/demo-component-versions/atmos.yaml | 28 + .../stacks/deploy/demo-v1.yaml | 0 examples/demo-component-versions/vendor.yaml | 38 + examples/demo-context/README.md | 0 examples/demo-context/atmos.yaml | 46 + .../components/terraform/petset/README.md | 1 + .../components/terraform/petset/main.tf | 21 + .../terraform/petset/modules/instance/main.tf | 30 + .../petset/modules/instance/outputs.tf | 12 + .../petset/modules/instance/variables.tf | 9 + .../petset/modules/instance/versions.tf | 10 + .../components/terraform/petset/outputs.tf | 23 + .../components/terraform/petset/providers.tf | 2 + .../components/terraform/petset/variables.tf | 11 + .../components/terraform/petset/versions.tf | 10 + .../schemas}/atmos-manifest.json | 0 .../demo-context/stacks/catalog/demo.yaml | 12 + .../demo-context/stacks/deploy/_defaults.yaml | 40 + .../demo-context/stacks/deploy/dev/demo.yaml | 19 + .../demo-context/stacks/deploy/prod/demo.yaml | 21 + .../stacks/deploy/staging/demo.yaml | 20 + .../stacks/mixins/east-coast.yaml | 5 + .../stacks/mixins/west-coast.yaml | 5 + examples/demo-custom-command/README.md | 46 + examples/demo-custom-command/atmos.yaml | 72 + examples/demo-helmfile/.gitignore | 1 + examples/demo-helmfile/atmos.yaml | 86 + .../components/helmfile/nginx/helmfile.yaml | 32 + .../helmfile/nginx/manifests/configmap.yaml | 38 + examples/demo-helmfile/docker-compose.yml | 62 + .../demo-helmfile/schemas/atmos-manifest.json | 822 +++ .../demo-helmfile/stacks/catalog/demo.yaml | 40 + .../demo-helmfile/stacks/deploy/dev/demo.yaml | 12 + .../stacks/deploy/prod/demo.yaml | 12 + .../stacks/deploy/staging/demo.yaml | 12 + examples/demo-helmfile/stacks/mixins/k3s.yaml | 4 + examples/demo-library/README.md | 30 + .../demo-library/github/stargazers/README.md | 13 + .../demo-library/github/stargazers/main.tf | 3 + .../demo-library/github/stargazers/outputs.tf | 4 + .../github/stargazers/providers.tf | 3 + .../github/stargazers/variables.tf | 4 + .../github/stargazers/versions.tf | 5 + examples/demo-library/ipinfo/README.md | 13 + examples/demo-library/ipinfo/main.tf | 7 + examples/demo-library/ipinfo/outputs.tf | 4 + examples/demo-library/ipinfo/providers.tf | 1 + examples/demo-library/ipinfo/variables.tf | 5 + examples/demo-library/ipinfo/versions.tf | 5 + examples/demo-library/weather/README.md | 50 + examples/demo-library/weather/main.tf | 22 + examples/demo-library/weather/outputs.tf | 27 + examples/demo-library/weather/providers.tf | 1 + examples/demo-library/weather/variables.tf | 34 + examples/demo-library/weather/versions.tf | 5 + examples/demo-localstack/.gitignore | 13 + examples/demo-localstack/README.md | 16 + examples/demo-localstack/atmos.yaml | 97 + .../components/terraform/bucket/main.tf | 3 + .../components/terraform/bucket/outputs.tf | 4 + .../components/terraform/bucket/providers.tf | 2 + .../components/terraform/bucket/variables.tf | 3 + examples/demo-localstack/docker-compose.yml | 22 + .../schemas/atmos-manifest.json | 822 +++ .../demo-localstack/stacks/catalog/demo.yaml | 7 + .../stacks/deploy/dev/demo.yaml | 12 + .../stacks/deploy/prod/demo.yaml | 12 + .../stacks/deploy/staging/demo.yaml | 12 + .../stacks/mixins/localstack.yaml | 41 + .../components/terraform/myapp/main.tf | 2 +- .../components/terraform/myapp/outputs.tf | 2 +- examples/demo-vendoring/atmos.yaml | 21 + examples/demo-vendoring/vendor.yaml | 38 + examples/demo-workflows/atmos.yaml | 24 + .../demo-workflows/components/myapp/main.tf | 0 .../components/myapp/outputs.tf | 0 .../components/myapp/variables.tf | 0 .../demo-workflows/stacks/catalog/myapp.yaml | 0 .../demo-workflows/stacks/deploy/dev.yaml | 0 .../demo-workflows/stacks/deploy/prod.yaml | 0 .../demo-workflows/stacks/deploy/staging.yaml | 0 .../.dockerignore | 0 .../.gitignore | 0 .../Dockerfile | 0 .../Makefile | 0 .../README.md | 0 .../atmos.yaml | 6 +- .../terraform/vpc-flow-logs-bucket/context.tf | 0 .../terraform/vpc-flow-logs-bucket/main.tf | 0 .../terraform/vpc-flow-logs-bucket/outputs.tf | 0 .../vpc-flow-logs-bucket/providers.tf | 0 .../vpc-flow-logs-bucket/variables.tf | 0 .../vpc-flow-logs-bucket/versions.tf | 0 .../components/terraform/vpc/context.tf | 0 .../components/terraform/vpc/main.tf | 0 .../components/terraform/vpc/outputs.tf | 0 .../components/terraform/vpc/providers.tf | 0 .../components/terraform/vpc/remote-state.tf | 0 .../components/terraform/vpc/variables.tf | 0 .../components/terraform/vpc/versions.tf | 0 .../components/terraform/vpc/vpc-flow-logs.tf | 0 .../rootfs/usr/local/etc/atmos/atmos.yaml | 6 +- .../vpc-flow-logs-bucket/defaults.yaml | 0 .../vpc-flow-logs-bucket/disabled.yaml | 0 .../stacks/catalog/vpc/defaults.yaml | 0 .../stacks/catalog/vpc/dev.yaml | 0 .../stacks/catalog/vpc/disabled.yaml | 0 .../stacks/catalog/vpc/prod.yaml | 0 .../stacks/catalog/vpc/staging.yaml | 0 .../stacks/catalog/vpc/ue2.yaml | 0 .../stacks/catalog/vpc/uw2.yaml | 0 .../stacks/mixins/region/global-region.yaml | 0 .../stacks/mixins/region/us-east-2.yaml | 0 .../stacks/mixins/region/us-west-2.yaml | 0 .../stacks/mixins/stage/dev.yaml | 0 .../stacks/mixins/stage/prod.yaml | 0 .../stacks/mixins/stage/staging.yaml | 0 .../stacks/mixins/tenant/core.yaml | 0 .../stacks/mixins/tenant/plat.yaml | 0 .../stacks/orgs/acme/_defaults.yaml | 6 +- .../stacks/orgs/acme/core/_defaults.yaml | 0 .../stacks/orgs/acme/plat/_defaults.yaml | 0 .../stacks/orgs/acme/plat/dev/_defaults.yaml | 0 .../orgs/acme/plat/dev/global-region.yaml | 0 .../stacks/orgs/acme/plat/dev/us-east-2.yaml | 0 .../stacks/orgs/acme/plat/dev/us-west-2.yaml | 0 .../stacks/orgs/acme/plat/prod/_defaults.yaml | 0 .../orgs/acme/plat/prod/global-region.yaml | 0 .../stacks/orgs/acme/plat/prod/us-east-2.yaml | 0 .../stacks/orgs/acme/plat/prod/us-west-2.yaml | 0 .../orgs/acme/plat/staging/_defaults.yaml | 0 .../orgs/acme/plat/staging/global-region.yaml | 0 .../orgs/acme/plat/staging/us-east-2.yaml | 0 .../orgs/acme/plat/staging/us-west-2.yaml | 0 .../atmos-manifest/1.0/atmos-manifest.json | 822 +++ .../vpc/validate-vpc-component.json | 0 .../opa/catalog/constants/constants.rego | 0 .../opa/vpc/validate-vpc-component.rego | 0 .../stacks/workflows/networking.yaml | 0 .../stacks/workflows/validation.yaml | 0 .../vendor.yaml | 0 examples/quick-start-simple/.gitignore | 10 + examples/quick-start-simple/atmos.yaml | 21 + .../components/terraform/weather/README.md | 50 + .../components/terraform/weather/main.tf | 22 + .../components/terraform/weather/outputs.tf | 27 + .../components/terraform/weather/variables.tf | 34 + .../components/terraform/weather/versions.tf | 5 + .../stacks/catalog/station.yaml | 11 + .../quick-start-simple/stacks/deploy/dev.yaml | 12 + .../stacks/deploy/prod.yaml | 12 + .../stacks/deploy/staging.yaml | 12 + examples/tests/atmos.yaml | 6 +- .../rootfs/usr/local/etc/atmos/atmos.yaml | 6 +- examples/tests/stacks/orgs/cp/_defaults.yaml | 4 +- examples/welcome.md | 12 + internal/exec/describe_stacks.go | 4 +- internal/exec/utils.go | 2 +- internal/exec/validate_stacks.go | 2 +- pkg/atlantis/atmos.yaml | 6 +- pkg/aws/atmos.yaml | 6 +- pkg/component/atmos.yaml | 6 +- pkg/config/config.go | 2 +- pkg/describe/atmos.yaml | 6 +- pkg/generate/atmos.yaml | 6 +- pkg/spacelift/atmos.yaml | 6 +- pkg/validate/atmos.yaml | 6 +- pkg/vender/atmos.yaml | 6 +- pkg/workflow/atmos.yaml | 6 +- .../docs/best-practices/best-practices.mdx | 17 + website/docs/best-practices/components.mdx | 170 + website/docs/best-practices/stacks.mdx | 96 + website/docs/best-practices/terraform.mdx | 54 + .../commands.mdx} | 2 +- .../cheatsheet.mdx => cheatsheets/common.mdx} | 6 +- .../components.mdx} | 45 +- website/docs/cheatsheets/stacks.mdx | 84 + .../vendoring.mdx} | 6 +- website/docs/cli/cli.mdx | 2 +- .../atlantis-generate-repo-config.mdx | 17 +- website/docs/cli/commands/atlantis/usage.mdx | 7 +- .../aws/aws-eks-update-kubeconfig.mdx | 11 +- website/docs/cli/commands/commands.mdx | 5 +- website/docs/cli/commands/completion.mdx | 8 - .../commands/describe/describe-affected.mdx | 21 - .../commands/describe/describe-component.mdx | 46 +- .../cli/commands/describe/describe-config.mdx | 4 +- .../commands/describe/describe-dependents.mdx | 16 +- .../cli/commands/describe/describe-stacks.mdx | 2 - .../commands/describe/describe-workflows.mdx | 12 - website/docs/cli/commands/docs.mdx | 2 - .../helmfile/helmfile-generate-varfile.mdx | 2 - website/docs/cli/commands/helmfile/usage.mdx | 10 - website/docs/cli/commands/help.mdx | 2 - .../cli/commands/terraform/_category_.json | 2 +- .../commands/terraform/terraform-clean.mdx | 2 - .../commands/terraform/terraform-deploy.mdx | 6 - .../terraform/terraform-generate-backend.mdx | 4 - .../terraform/terraform-generate-backends.mdx | 4 - .../terraform/terraform-generate-varfile.mdx | 2 - .../terraform/terraform-generate-varfiles.mdx | 2 - .../commands/terraform/terraform-shell.mdx | 4 - .../terraform/terraform-workspace.mdx | 4 - website/docs/cli/commands/terraform/usage.mdx | 9 +- website/docs/cli/commands/validate/usage.mdx | 2 - .../commands/validate/validate-component.mdx | 4 - .../cli/commands/validate/validate-stacks.mdx | 18 +- website/docs/cli/commands/vendor/usage.mdx | 2 - .../docs/cli/commands/vendor/vendor-pull.mdx | 15 +- website/docs/cli/commands/version.mdx | 10 +- website/docs/cli/commands/workflow.mdx | 11 - website/docs/cli/configuration/commands.mdx | 211 + website/docs/cli/configuration/components.mdx | 159 + .../cli/{ => configuration}/configuration.mdx | 513 +- website/docs/cli/configuration/stacks.mdx | 147 + website/docs/{reference => cli}/schemas.mdx | 28 +- .../versioning.md => cli/versioning.mdx} | 3 + website/docs/community/community.mdx | 30 + website/docs/community/office-hours.mdx | 19 + website/docs/community/slack.mdx | 26 + .../coc.md => contribute/coc.mdx} | 7 +- .../contributing.mdx | 5 +- .../how-to-contribute.md | 6 +- ...onent-library.md => component-library.mdx} | 8 +- .../component-oriented-programming.md | 44 - .../components/component-validation.mdx | 454 -- .../core-concepts/components/components.mdx | 189 +- .../components/describe-component.mdx | 29 - .../components/helmfile.mdx} | 11 +- .../backends.mdx} | 98 +- .../brownfield.mdx} | 154 +- .../providers.mdx} | 31 +- .../{ => terraform}/remote-state.mdx | 148 +- .../components/terraform/state-backend.mdx | 85 + .../components/terraform/terraform.mdx | 183 + .../workspaces.mdx} | 25 +- website/docs/core-concepts/core-concepts.mdx | 11 +- .../custom-commands/custom-commands.mdx | 12 +- website/docs/core-concepts/deploy/deploy.mdx | 46 + .../core-concepts/describe/components.mdx | 32 + .../docs/core-concepts/describe/describe.mdx | 19 + .../stacks.mdx} | 30 +- .../projects/configuration/configuration.mdx | 258 + .../projects/configuration}/opentofu.mdx | 28 +- .../projects/configuration/terraform.mdx} | 61 +- .../docs/core-concepts/projects/layout.mdx | 69 + .../docs/core-concepts/projects/projects.mdx | 29 + .../core-concepts/share-data/share-data.mdx | 177 + .../stacks/{catalogs.md => catalogs.mdx} | 14 +- .../stacks/define-components.mdx | 148 + .../core-concepts/stacks/dependencies.mdx | 86 + website/docs/core-concepts/stacks/imports.mdx | 65 +- .../inheritance/inheritance.mdx} | 155 +- .../stacks/{ => inheritance}/mixins.mdx | 28 +- .../overrides.mdx} | 46 +- website/docs/core-concepts/stacks/stacks.mdx | 121 +- .../stacks/templates/datasources.mdx | 432 ++ .../templates/functions/atmos.Component.mdx | 168 + .../stacks/templates/functions/functions.mdx | 33 + .../templates.mdx} | 576 +- .../docs/core-concepts/stacks/validation.mdx | 68 - .../template-functions/atmos.Component.mdx | 157 - .../template-functions/template-functions.mdx | 17 - .../core-concepts/validate/json-schema.mdx | 51 + website/docs/core-concepts/validate/opa.mdx | 169 + .../docs/core-concepts/validate/validate.mdx | 96 + .../components-manifest.mdx} | 59 +- .../vendor-manifest.mdx} | 251 +- website/docs/core-concepts/vendor/vendor.mdx | 77 + .../core-concepts/workflows/workflows.mdx | 94 +- .../design-patterns/abstract-component.mdx | 29 +- .../component-catalog-template.mdx | 12 +- .../component-catalog-with-mixins.mdx | 17 +- .../design-patterns/component-catalog.mdx | 12 +- .../design-patterns/component-inheritance.mdx | 22 +- .../design-patterns/component-overrides.mdx | 31 +- .../docs/design-patterns/design-patterns.mdx | 72 +- .../inline-component-configuration.mdx | 13 +- .../inline-component-customization.mdx | 13 +- .../layered-stack-configuration.mdx | 25 +- .../multiple-component-instances.mdx | 19 +- ...organizational-structure-configuration.mdx | 23 +- .../partial-component-configuration.mdx | 20 +- .../partial-stack-configuration.mdx | 35 +- .../{summary.md => summary.mdx} | 13 +- .../{reference => }/glossary/_category_.json | 0 .../glossary/abstract-component.md | 0 .../docs/{reference => }/glossary/catalog.md | 0 .../glossary/component-instance.md | 0 .../{reference => }/glossary/component.md | 0 .../glossary/concrete-component.md | 0 .../{reference => }/glossary/environment.md | 0 website/docs/glossary/framework.mdx | 6 + .../docs/{reference => }/glossary/imports.md | 0 .../docs/{reference => }/glossary/index.mdx | 3 +- .../{reference => }/glossary/inheritance.md | 0 .../{reference => }/glossary/integration.md | 0 .../glossary/kubernetes-namespace.mdx | 0 .../docs/{reference => }/glossary/library.md | 0 .../docs/{reference => }/glossary/mixins.md | 0 .../glossary/multiple-inheritance.md | 0 .../{reference => }/glossary/namespace.md | 0 .../{reference => }/glossary/parent-stack.md | 0 .../glossary/real-component.md | 0 .../glossary/spacelift-stack.md | 0 .../glossary/stack-manifest.md | 0 .../docs/{reference => }/glossary/stack.mdx | 0 .../docs/{reference => }/glossary/stage.md | 0 .../docs/{reference => }/glossary/tenant.md | 0 .../glossary/terraform-child-module.md | 0 website/docs/glossary/terralith.mdx | 36 + .../{reference => }/glossary/vendoring.md | 0 website/docs/integrations/atlantis.mdx | 48 +- website/docs/integrations/aws.mdx | 158 - .../github-actions/affected-stacks.mdx | 11 +- .../github-actions/atmos-terraform-apply.mdx | 8 +- .../atmos-terraform-drift-detection.mdx | 11 +- .../atmos-terraform-drift-remediation.mdx | 129 + .../github-actions/atmos-terraform-plan.mdx | 159 +- .../github-actions/component-updater.mdx | 19 +- .../github-actions/github-actions.mdx | 52 +- .../github-actions/setup-atmos.mdx | 9 +- website/docs/integrations/integrations.mdx | 19 +- .../{spacelift.md => spacelift.mdx} | 21 +- website/docs/introduction/faq.mdx | 13 +- .../{features.md => features.mdx} | 12 +- website/docs/introduction/index.mdx | 60 +- .../{use-cases.md => use-cases.mdx} | 17 +- .../docs/introduction/why-atmos/nirvana.mdx | 51 + .../docs/introduction/why-atmos/stage-0.mdx | 44 + .../docs/introduction/why-atmos/stage-1.mdx | 38 + .../docs/introduction/why-atmos/stage-10.mdx | 66 + .../docs/introduction/why-atmos/stage-2.mdx | 45 + .../docs/introduction/why-atmos/stage-3.mdx | 38 + .../docs/introduction/why-atmos/stage-4.mdx | 38 + .../docs/introduction/why-atmos/stage-5.mdx | 40 + .../docs/introduction/why-atmos/stage-6.mdx | 38 + .../docs/introduction/why-atmos/stage-7.mdx | 63 + .../docs/introduction/why-atmos/stage-8.mdx | 38 + .../docs/introduction/why-atmos/stage-9.mdx | 48 + .../docs/introduction/why-atmos/why-atmos.mdx | 37 + .../{ => advanced}/add-custom-commands.mdx | 0 .../docs/quick-start/advanced/advanced.mdx | 56 + .../{ => advanced}/configure-cli.mdx | 85 +- .../{ => advanced}/configure-repository.md | 20 +- .../configure-terraform-backend.mdx | 23 +- .../{ => advanced}/configure-validation.mdx | 40 +- .../{ => advanced}/create-atmos-stacks.mdx | 28 +- .../{ => advanced}/create-workflows.mdx | 16 +- .../{ => advanced}/final-notes.mdx | 3 - .../quick-start/{ => advanced}/next-steps.md | 14 +- .../quick-start/{ => advanced}/provision.md | 4 +- .../{ => advanced}/vendor-components.mdx | 62 +- website/docs/quick-start/install-atmos.mdx | 41 +- website/docs/quick-start/introduction.md | 59 - website/docs/quick-start/introduction.mdx | 34 + website/docs/quick-start/mindset.mdx | 252 + website/docs/quick-start/quick-start.mdx | 25 - .../docs/quick-start/simple/configure-cli.mdx | 183 + .../quick-start/simple/configure-project.mdx | 123 + .../quick-start/simple/configure-stacks.mdx | 166 + .../simple/extra-credit/_category_.json | 6 + .../extra-credit/add-another-component.mdx | 68 + .../extra-credit/add-custom-commands.mdx | 66 + .../simple/extra-credit/create-workflows.mdx | 113 + .../simple/extra-credit/extra-credit.mdx | 24 + .../simple/extra-credit/vendor-components.mdx | 157 + website/docs/quick-start/simple/provision.mdx | 68 + website/docs/quick-start/simple/simple.mdx | 79 + website/docs/quick-start/simple/summary.mdx | 35 + .../quick-start/simple/write-components.mdx | 129 + website/docs/reference/alternatives.md | 126 - website/docs/reference/alternatives.mdx | 161 + website/docs/reference/reference.mdx | 7 +- website/docs/reference/slides.mdx | 2 +- .../docs/reference/terraform-limitations.md | 295 - .../debugging.md | 1 + .../errors.mdx | 10 +- .../docs/troubleshooting/troubleshooting.mdx | 14 - .../atmos-component-migrations-in-yaml.mdx | 4 +- .../docs/tutorials/atmos-example-infra.mdx | 22 +- website/docs/tutorials/tutorials.mdx | 2 +- website/docusaurus.config.js | 101 +- website/examples | 1 + website/package-lock.json | 5457 ++++++++--------- website/package.json | 8 + website/plugins/custom-loaders/index.js | 13 +- website/plugins/fetch-latest-release/index.js | 32 + .../plugins/fetch-latest-release/package.json | 5 + website/sidebars.js | 206 +- website/src/components/ActionCard/index.css | 43 + website/src/components/ActionCard/index.js | 37 + .../components/{Card.tsx => Card/index.tsx} | 0 .../src/components/CardGroup/cheatsheet.css | 63 + .../{CardGroup.tsx => CardGroup/index.tsx} | 1 + .../src/components/CollapsibleText/index.css | 57 + .../src/components/CollapsibleText/index.js | 23 + website/src/components/Definition/index.css | 35 + website/src/components/Definition/index.js | 50 + website/src/components/EmbedFile/index.js | 47 + website/src/components/File/index.css | 102 + .../components/{File.tsx => File/index.tsx} | 12 +- .../{glossary => Glossary}/Glossary.tsx | 0 website/src/components/Intro/index.css | 6 + website/src/components/Intro/index.js | 10 + website/src/components/KeyPoints/index.css | 29 + website/src/components/KeyPoints/index.js | 13 + website/src/components/LatestRelease/index.js | 12 + website/src/components/Note/index.css | 19 + website/src/components/Note/index.tsx | 14 + website/src/components/PillBox/index.css | 18 + website/src/components/PillBox/index.tsx | 12 + website/src/components/PrimaryCTA/index.css | 0 website/src/components/PrimaryCTA/index.js | 11 + .../{Screengrab.tsx => Screengrab/index.tsx} | 2 +- .../atmos--help.html | 0 .../atmos-atlantis--help.html | 0 .../atmos-atlantis-generate--help.html | 0 ...s-atlantis-generate-repo-config--help.html | 0 .../atmos-aws--help.html | 0 .../atmos-aws-eks--help.html | 0 ...atmos-aws-eks-update-kubeconfig--help.html | 0 .../atmos-completion--help.html | 0 .../atmos-completion-bash.html | 0 .../atmos-completion-fish.html | 0 .../atmos-completion-powershell.html | 0 .../atmos-completion-zsh.html | 0 .../atmos-describe--help.html | 0 .../atmos-describe-affected--help.html | 0 .../atmos-describe-component--help.html | 0 .../atmos-describe-config--help.html | 0 .../atmos-describe-dependents--help.html | 0 .../atmos-describe-stacks--help.html | 0 .../atmos-describe-workflows--help.html | 0 .../atmos-docs--help.html | 0 .../atmos-helmfile--help.html | 0 .../atmos-helmfile-generate--help.html | 0 ...atmos-helmfile-generate-varfile--help.html | 0 .../atmos-terraform--help.html | 0 .../atmos-terraform-clean--help.html | 0 .../atmos-terraform-deploy--help.html | 0 .../atmos-terraform-generate--help.html | 0 ...tmos-terraform-generate-backend--help.html | 0 ...mos-terraform-generate-backends--help.html | 0 ...tmos-terraform-generate-varfile--help.html | 0 ...mos-terraform-generate-varfiles--help.html | 0 .../atmos-terraform-shell--help.html | 0 .../atmos-terraform-workspace--help.html | 0 .../atmos-validate--help.html | 0 .../atmos-validate-component--help.html | 0 .../atmos-validate-stacks--help.html | 0 .../atmos-vendor--help.html | 0 .../atmos-vendor-pull--help.html | 0 .../atmos-version.html | 2 +- .../atmos-workflow--help.html | 0 .../demo-stacks/define-your-stacks.html | 0 .../demo-stacks/deploy-dev.ansi | 0 .../demo-stacks/deploy-dev.html | 0 .../demo-stacks/deploy-prod.html | 0 .../demo-stacks/deploy-staging.html | 0 .../demo-stacks/deploy.html | 0 .../demo-stacks/start-your-project.html | 0 .../demo-stacks/write-your-components.html | 0 .../tree-CAF--gitignore.html | 0 .../{screengrabs => Screengrabs}/tree.html | 0 website/src/components/SecondaryCTA/index.css | 0 website/src/components/SecondaryCTA/index.js | 11 + .../{slides/slides.js => Slides/index.js} | 4 +- .../index.module.css} | 0 website/src/components/Step/index.css | 22 + website/src/components/Step/index.js | 31 + website/src/components/StepNumber/index.js | 9 + website/src/components/Terminal.tsx | 20 - website/src/components/Terminal/index.css | 155 + website/src/components/Terminal/index.tsx | 22 + website/src/components/Typewriter/index.css | 37 + .../{Typewriter.tsx => Typewriter/index.tsx} | 14 +- website/src/css/custom.css | 749 +-- website/src/css/landing-page.css | 275 + website/src/pages/index.js | 51 +- website/src/theme/DocItem/Layout/index.js | 15 + website/src/theme/NavbarItem.js | 21 + 503 files changed, 16275 insertions(+), 7915 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100755 .devcontainer/post-create.sh create mode 100644 .devcontainer/rootfs/home/vscode/.config/direnv/direnvrc create mode 100644 .devcontainer/rootfs/home/vscode/.config/starship.toml create mode 100644 .devcontainer/rootfs/home/vscode/.config/vscode-dev-containers/first-run-notice-already-displayed create mode 100644 .devcontainer/rootfs/home/vscode/.zsh_history create mode 100644 .devcontainer/rootfs/home/vscode/.zshrc create mode 100644 examples/.gitignore create mode 100644 examples/.tflint.hcl create mode 100644 examples/README.md create mode 100644 examples/demo-atlantis/.gitignore create mode 100644 examples/demo-atlantis/atmos.yaml create mode 100644 examples/demo-atlantis/stacks/deploy/demo.yaml create mode 100644 examples/demo-component-versions/.gitignore create mode 100644 examples/demo-component-versions/atmos.yaml create mode 100644 examples/demo-component-versions/stacks/deploy/demo-v1.yaml create mode 100644 examples/demo-component-versions/vendor.yaml create mode 100644 examples/demo-context/README.md create mode 100644 examples/demo-context/atmos.yaml create mode 100644 examples/demo-context/components/terraform/petset/README.md create mode 100644 examples/demo-context/components/terraform/petset/main.tf create mode 100644 examples/demo-context/components/terraform/petset/modules/instance/main.tf create mode 100644 examples/demo-context/components/terraform/petset/modules/instance/outputs.tf create mode 100644 examples/demo-context/components/terraform/petset/modules/instance/variables.tf create mode 100644 examples/demo-context/components/terraform/petset/modules/instance/versions.tf create mode 100644 examples/demo-context/components/terraform/petset/outputs.tf create mode 100644 examples/demo-context/components/terraform/petset/providers.tf create mode 100644 examples/demo-context/components/terraform/petset/variables.tf create mode 100644 examples/demo-context/components/terraform/petset/versions.tf rename examples/{quick-start/stacks/schemas/atmos/atmos-manifest/1.0 => demo-context/schemas}/atmos-manifest.json (100%) create mode 100644 examples/demo-context/stacks/catalog/demo.yaml create mode 100644 examples/demo-context/stacks/deploy/_defaults.yaml create mode 100644 examples/demo-context/stacks/deploy/dev/demo.yaml create mode 100644 examples/demo-context/stacks/deploy/prod/demo.yaml create mode 100644 examples/demo-context/stacks/deploy/staging/demo.yaml create mode 100644 examples/demo-context/stacks/mixins/east-coast.yaml create mode 100644 examples/demo-context/stacks/mixins/west-coast.yaml create mode 100644 examples/demo-custom-command/README.md create mode 100644 examples/demo-custom-command/atmos.yaml create mode 100644 examples/demo-helmfile/.gitignore create mode 100644 examples/demo-helmfile/atmos.yaml create mode 100644 examples/demo-helmfile/components/helmfile/nginx/helmfile.yaml create mode 100644 examples/demo-helmfile/components/helmfile/nginx/manifests/configmap.yaml create mode 100644 examples/demo-helmfile/docker-compose.yml create mode 100644 examples/demo-helmfile/schemas/atmos-manifest.json create mode 100644 examples/demo-helmfile/stacks/catalog/demo.yaml create mode 100644 examples/demo-helmfile/stacks/deploy/dev/demo.yaml create mode 100644 examples/demo-helmfile/stacks/deploy/prod/demo.yaml create mode 100644 examples/demo-helmfile/stacks/deploy/staging/demo.yaml create mode 100644 examples/demo-helmfile/stacks/mixins/k3s.yaml create mode 100644 examples/demo-library/README.md create mode 100644 examples/demo-library/github/stargazers/README.md create mode 100644 examples/demo-library/github/stargazers/main.tf create mode 100644 examples/demo-library/github/stargazers/outputs.tf create mode 100644 examples/demo-library/github/stargazers/providers.tf create mode 100644 examples/demo-library/github/stargazers/variables.tf create mode 100644 examples/demo-library/github/stargazers/versions.tf create mode 100644 examples/demo-library/ipinfo/README.md create mode 100644 examples/demo-library/ipinfo/main.tf create mode 100644 examples/demo-library/ipinfo/outputs.tf create mode 100644 examples/demo-library/ipinfo/providers.tf create mode 100644 examples/demo-library/ipinfo/variables.tf create mode 100644 examples/demo-library/ipinfo/versions.tf create mode 100644 examples/demo-library/weather/README.md create mode 100644 examples/demo-library/weather/main.tf create mode 100644 examples/demo-library/weather/outputs.tf create mode 100644 examples/demo-library/weather/providers.tf create mode 100644 examples/demo-library/weather/variables.tf create mode 100644 examples/demo-library/weather/versions.tf create mode 100644 examples/demo-localstack/.gitignore create mode 100644 examples/demo-localstack/README.md create mode 100644 examples/demo-localstack/atmos.yaml create mode 100644 examples/demo-localstack/components/terraform/bucket/main.tf create mode 100644 examples/demo-localstack/components/terraform/bucket/outputs.tf create mode 100644 examples/demo-localstack/components/terraform/bucket/providers.tf create mode 100644 examples/demo-localstack/components/terraform/bucket/variables.tf create mode 100644 examples/demo-localstack/docker-compose.yml create mode 100644 examples/demo-localstack/schemas/atmos-manifest.json create mode 100644 examples/demo-localstack/stacks/catalog/demo.yaml create mode 100644 examples/demo-localstack/stacks/deploy/dev/demo.yaml create mode 100644 examples/demo-localstack/stacks/deploy/prod/demo.yaml create mode 100644 examples/demo-localstack/stacks/deploy/staging/demo.yaml create mode 100644 examples/demo-localstack/stacks/mixins/localstack.yaml create mode 100644 examples/demo-vendoring/atmos.yaml create mode 100644 examples/demo-vendoring/vendor.yaml create mode 100644 examples/demo-workflows/atmos.yaml create mode 100644 examples/demo-workflows/components/myapp/main.tf create mode 100644 examples/demo-workflows/components/myapp/outputs.tf create mode 100644 examples/demo-workflows/components/myapp/variables.tf create mode 100644 examples/demo-workflows/stacks/catalog/myapp.yaml create mode 100644 examples/demo-workflows/stacks/deploy/dev.yaml create mode 100644 examples/demo-workflows/stacks/deploy/prod.yaml create mode 100644 examples/demo-workflows/stacks/deploy/staging.yaml rename examples/{quick-start => quick-start-advanced}/.dockerignore (100%) rename examples/{quick-start => quick-start-advanced}/.gitignore (100%) rename examples/{quick-start => quick-start-advanced}/Dockerfile (100%) rename examples/{quick-start => quick-start-advanced}/Makefile (100%) rename examples/{quick-start => quick-start-advanced}/README.md (100%) rename examples/{quick-start => quick-start-advanced}/atmos.yaml (98%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc-flow-logs-bucket/context.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc-flow-logs-bucket/main.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc-flow-logs-bucket/outputs.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc-flow-logs-bucket/providers.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc-flow-logs-bucket/variables.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc-flow-logs-bucket/versions.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/context.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/main.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/outputs.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/providers.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/remote-state.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/variables.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/versions.tf (100%) rename examples/{quick-start => quick-start-advanced}/components/terraform/vpc/vpc-flow-logs.tf (100%) rename examples/{quick-start => quick-start-advanced}/rootfs/usr/local/etc/atmos/atmos.yaml (98%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc-flow-logs-bucket/defaults.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc-flow-logs-bucket/disabled.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc/defaults.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc/dev.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc/disabled.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc/prod.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc/staging.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc/ue2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/catalog/vpc/uw2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/region/global-region.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/region/us-east-2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/region/us-west-2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/stage/dev.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/stage/prod.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/stage/staging.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/tenant/core.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/mixins/tenant/plat.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/_defaults.yaml (91%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/core/_defaults.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/_defaults.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/dev/_defaults.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/dev/global-region.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/dev/us-east-2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/dev/us-west-2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/prod/_defaults.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/prod/global-region.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/prod/us-east-2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/prod/us-west-2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/staging/_defaults.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/staging/global-region.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/staging/us-east-2.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/orgs/acme/plat/staging/us-west-2.yaml (100%) create mode 100644 examples/quick-start-advanced/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json rename examples/{quick-start => quick-start-advanced}/stacks/schemas/jsonschema/vpc/validate-vpc-component.json (100%) rename examples/{quick-start => quick-start-advanced}/stacks/schemas/opa/catalog/constants/constants.rego (100%) rename examples/{quick-start => quick-start-advanced}/stacks/schemas/opa/vpc/validate-vpc-component.rego (100%) rename examples/{quick-start => quick-start-advanced}/stacks/workflows/networking.yaml (100%) rename examples/{quick-start => quick-start-advanced}/stacks/workflows/validation.yaml (100%) rename examples/{quick-start => quick-start-advanced}/vendor.yaml (100%) create mode 100644 examples/quick-start-simple/.gitignore create mode 100644 examples/quick-start-simple/atmos.yaml create mode 100644 examples/quick-start-simple/components/terraform/weather/README.md create mode 100644 examples/quick-start-simple/components/terraform/weather/main.tf create mode 100644 examples/quick-start-simple/components/terraform/weather/outputs.tf create mode 100644 examples/quick-start-simple/components/terraform/weather/variables.tf create mode 100644 examples/quick-start-simple/components/terraform/weather/versions.tf create mode 100644 examples/quick-start-simple/stacks/catalog/station.yaml create mode 100644 examples/quick-start-simple/stacks/deploy/dev.yaml create mode 100644 examples/quick-start-simple/stacks/deploy/prod.yaml create mode 100644 examples/quick-start-simple/stacks/deploy/staging.yaml create mode 100644 examples/welcome.md create mode 100644 website/docs/best-practices/best-practices.mdx create mode 100644 website/docs/best-practices/components.mdx create mode 100644 website/docs/best-practices/stacks.mdx create mode 100644 website/docs/best-practices/terraform.mdx rename website/docs/{cli/cheatsheet.mdx => cheatsheets/commands.mdx} (99%) rename website/docs/{introduction/cheatsheet.mdx => cheatsheets/common.mdx} (98%) rename website/docs/{core-concepts/components/component-cheatsheet.mdx => cheatsheets/components.mdx} (71%) create mode 100644 website/docs/cheatsheets/stacks.mdx rename website/docs/{core-concepts/vendoring/cheatsheet.mdx => cheatsheets/vendoring.mdx} (96%) create mode 100644 website/docs/cli/configuration/commands.mdx create mode 100644 website/docs/cli/configuration/components.mdx rename website/docs/cli/{ => configuration}/configuration.mdx (59%) create mode 100644 website/docs/cli/configuration/stacks.mdx rename website/docs/{reference => cli}/schemas.mdx (94%) rename website/docs/{reference/versioning.md => cli/versioning.mdx} (96%) create mode 100644 website/docs/community/community.mdx create mode 100644 website/docs/community/office-hours.mdx create mode 100644 website/docs/community/slack.mdx rename website/docs/{contributing/coc.md => contribute/coc.mdx} (63%) rename website/docs/{contributing => contribute}/contributing.mdx (59%) rename website/docs/{contributing => contribute}/how-to-contribute.md (94%) rename website/docs/core-concepts/components/{component-library.md => component-library.mdx} (94%) delete mode 100644 website/docs/core-concepts/components/component-oriented-programming.md delete mode 100644 website/docs/core-concepts/components/component-validation.mdx delete mode 100644 website/docs/core-concepts/components/describe-component.mdx rename website/docs/{integrations/helmfile.md => core-concepts/components/helmfile.mdx} (81%) rename website/docs/core-concepts/components/{terraform-backends.mdx => terraform/backends.mdx} (89%) rename website/docs/core-concepts/components/{remote-state-backend.mdx => terraform/brownfield.mdx} (53%) rename website/docs/core-concepts/components/{terraform-providers.mdx => terraform/providers.mdx} (94%) rename website/docs/core-concepts/components/{ => terraform}/remote-state.mdx (72%) create mode 100644 website/docs/core-concepts/components/terraform/state-backend.mdx create mode 100644 website/docs/core-concepts/components/terraform/terraform.mdx rename website/docs/core-concepts/components/{terraform-workspaces.mdx => terraform/workspaces.mdx} (97%) create mode 100644 website/docs/core-concepts/deploy/deploy.mdx create mode 100644 website/docs/core-concepts/describe/components.mdx create mode 100644 website/docs/core-concepts/describe/describe.mdx rename website/docs/core-concepts/{stacks/describe-stacks.mdx => describe/stacks.mdx} (89%) create mode 100644 website/docs/core-concepts/projects/configuration/configuration.mdx rename website/docs/{integrations => core-concepts/projects/configuration}/opentofu.mdx (75%) rename website/docs/{integrations/terraform.md => core-concepts/projects/configuration/terraform.mdx} (66%) create mode 100644 website/docs/core-concepts/projects/layout.mdx create mode 100644 website/docs/core-concepts/projects/projects.mdx create mode 100644 website/docs/core-concepts/share-data/share-data.mdx rename website/docs/core-concepts/stacks/{catalogs.md => catalogs.mdx} (90%) create mode 100644 website/docs/core-concepts/stacks/define-components.mdx create mode 100644 website/docs/core-concepts/stacks/dependencies.mdx rename website/docs/core-concepts/{components/component-inheritance.mdx => stacks/inheritance/inheritance.mdx} (83%) rename website/docs/core-concepts/stacks/{ => inheritance}/mixins.mdx (77%) rename website/docs/core-concepts/{components/component-overrides.mdx => stacks/overrides.mdx} (84%) create mode 100644 website/docs/core-concepts/stacks/templates/datasources.mdx create mode 100644 website/docs/core-concepts/stacks/templates/functions/atmos.Component.mdx create mode 100644 website/docs/core-concepts/stacks/templates/functions/functions.mdx rename website/docs/core-concepts/stacks/{templating.mdx => templates/templates.mdx} (58%) delete mode 100644 website/docs/core-concepts/stacks/validation.mdx delete mode 100644 website/docs/core-concepts/template-functions/atmos.Component.mdx delete mode 100644 website/docs/core-concepts/template-functions/template-functions.mdx create mode 100644 website/docs/core-concepts/validate/json-schema.mdx create mode 100644 website/docs/core-concepts/validate/opa.mdx create mode 100644 website/docs/core-concepts/validate/validate.mdx rename website/docs/core-concepts/{components/component-vendoring.md => vendor/components-manifest.mdx} (72%) rename website/docs/core-concepts/{vendoring/vendoring.mdx => vendor/vendor-manifest.mdx} (58%) create mode 100644 website/docs/core-concepts/vendor/vendor.mdx rename website/docs/design-patterns/{summary.md => summary.mdx} (86%) rename website/docs/{reference => }/glossary/_category_.json (100%) rename website/docs/{reference => }/glossary/abstract-component.md (100%) rename website/docs/{reference => }/glossary/catalog.md (100%) rename website/docs/{reference => }/glossary/component-instance.md (100%) rename website/docs/{reference => }/glossary/component.md (100%) rename website/docs/{reference => }/glossary/concrete-component.md (100%) rename website/docs/{reference => }/glossary/environment.md (100%) create mode 100644 website/docs/glossary/framework.mdx rename website/docs/{reference => }/glossary/imports.md (100%) rename website/docs/{reference => }/glossary/index.mdx (94%) rename website/docs/{reference => }/glossary/inheritance.md (100%) rename website/docs/{reference => }/glossary/integration.md (100%) rename website/docs/{reference => }/glossary/kubernetes-namespace.mdx (100%) rename website/docs/{reference => }/glossary/library.md (100%) rename website/docs/{reference => }/glossary/mixins.md (100%) rename website/docs/{reference => }/glossary/multiple-inheritance.md (100%) rename website/docs/{reference => }/glossary/namespace.md (100%) rename website/docs/{reference => }/glossary/parent-stack.md (100%) rename website/docs/{reference => }/glossary/real-component.md (100%) rename website/docs/{reference => }/glossary/spacelift-stack.md (100%) rename website/docs/{reference => }/glossary/stack-manifest.md (100%) rename website/docs/{reference => }/glossary/stack.mdx (100%) rename website/docs/{reference => }/glossary/stage.md (100%) rename website/docs/{reference => }/glossary/tenant.md (100%) rename website/docs/{reference => }/glossary/terraform-child-module.md (100%) create mode 100644 website/docs/glossary/terralith.mdx rename website/docs/{reference => }/glossary/vendoring.md (100%) delete mode 100644 website/docs/integrations/aws.mdx create mode 100644 website/docs/integrations/github-actions/atmos-terraform-drift-remediation.mdx rename website/docs/integrations/{spacelift.md => spacelift.mdx} (91%) rename website/docs/introduction/{features.md => features.mdx} (82%) rename website/docs/introduction/{use-cases.md => use-cases.mdx} (72%) create mode 100644 website/docs/introduction/why-atmos/nirvana.mdx create mode 100644 website/docs/introduction/why-atmos/stage-0.mdx create mode 100644 website/docs/introduction/why-atmos/stage-1.mdx create mode 100644 website/docs/introduction/why-atmos/stage-10.mdx create mode 100644 website/docs/introduction/why-atmos/stage-2.mdx create mode 100644 website/docs/introduction/why-atmos/stage-3.mdx create mode 100644 website/docs/introduction/why-atmos/stage-4.mdx create mode 100644 website/docs/introduction/why-atmos/stage-5.mdx create mode 100644 website/docs/introduction/why-atmos/stage-6.mdx create mode 100644 website/docs/introduction/why-atmos/stage-7.mdx create mode 100644 website/docs/introduction/why-atmos/stage-8.mdx create mode 100644 website/docs/introduction/why-atmos/stage-9.mdx create mode 100644 website/docs/introduction/why-atmos/why-atmos.mdx rename website/docs/quick-start/{ => advanced}/add-custom-commands.mdx (100%) create mode 100644 website/docs/quick-start/advanced/advanced.mdx rename website/docs/quick-start/{ => advanced}/configure-cli.mdx (56%) rename website/docs/quick-start/{ => advanced}/configure-repository.md (92%) rename website/docs/quick-start/{ => advanced}/configure-terraform-backend.mdx (98%) rename website/docs/quick-start/{ => advanced}/configure-validation.mdx (83%) rename website/docs/quick-start/{ => advanced}/create-atmos-stacks.mdx (97%) rename website/docs/quick-start/{ => advanced}/create-workflows.mdx (98%) rename website/docs/quick-start/{ => advanced}/final-notes.mdx (99%) rename website/docs/quick-start/{ => advanced}/next-steps.md (56%) rename website/docs/quick-start/{ => advanced}/provision.md (92%) rename website/docs/quick-start/{ => advanced}/vendor-components.mdx (92%) delete mode 100644 website/docs/quick-start/introduction.md create mode 100644 website/docs/quick-start/introduction.mdx create mode 100644 website/docs/quick-start/mindset.mdx delete mode 100644 website/docs/quick-start/quick-start.mdx create mode 100644 website/docs/quick-start/simple/configure-cli.mdx create mode 100644 website/docs/quick-start/simple/configure-project.mdx create mode 100644 website/docs/quick-start/simple/configure-stacks.mdx create mode 100644 website/docs/quick-start/simple/extra-credit/_category_.json create mode 100644 website/docs/quick-start/simple/extra-credit/add-another-component.mdx create mode 100644 website/docs/quick-start/simple/extra-credit/add-custom-commands.mdx create mode 100644 website/docs/quick-start/simple/extra-credit/create-workflows.mdx create mode 100644 website/docs/quick-start/simple/extra-credit/extra-credit.mdx create mode 100644 website/docs/quick-start/simple/extra-credit/vendor-components.mdx create mode 100644 website/docs/quick-start/simple/provision.mdx create mode 100644 website/docs/quick-start/simple/simple.mdx create mode 100644 website/docs/quick-start/simple/summary.mdx create mode 100644 website/docs/quick-start/simple/write-components.mdx delete mode 100644 website/docs/reference/alternatives.md create mode 100644 website/docs/reference/alternatives.mdx delete mode 100644 website/docs/reference/terraform-limitations.md rename website/docs/{troubleshooting => troubleshoot}/debugging.md (76%) rename website/docs/{troubleshooting => troubleshoot}/errors.mdx (98%) delete mode 100644 website/docs/troubleshooting/troubleshooting.mdx create mode 120000 website/examples create mode 100644 website/plugins/fetch-latest-release/index.js create mode 100644 website/plugins/fetch-latest-release/package.json create mode 100644 website/src/components/ActionCard/index.css create mode 100644 website/src/components/ActionCard/index.js rename website/src/components/{Card.tsx => Card/index.tsx} (100%) create mode 100644 website/src/components/CardGroup/cheatsheet.css rename website/src/components/{CardGroup.tsx => CardGroup/index.tsx} (90%) create mode 100644 website/src/components/CollapsibleText/index.css create mode 100644 website/src/components/CollapsibleText/index.js create mode 100644 website/src/components/Definition/index.css create mode 100644 website/src/components/Definition/index.js create mode 100644 website/src/components/EmbedFile/index.js create mode 100644 website/src/components/File/index.css rename website/src/components/{File.tsx => File/index.tsx} (94%) rename website/src/components/{glossary => Glossary}/Glossary.tsx (100%) create mode 100644 website/src/components/Intro/index.css create mode 100644 website/src/components/Intro/index.js create mode 100644 website/src/components/KeyPoints/index.css create mode 100644 website/src/components/KeyPoints/index.js create mode 100644 website/src/components/LatestRelease/index.js create mode 100644 website/src/components/Note/index.css create mode 100644 website/src/components/Note/index.tsx create mode 100644 website/src/components/PillBox/index.css create mode 100644 website/src/components/PillBox/index.tsx create mode 100644 website/src/components/PrimaryCTA/index.css create mode 100644 website/src/components/PrimaryCTA/index.js rename website/src/components/{Screengrab.tsx => Screengrab/index.tsx} (94%) rename website/src/components/{screengrabs => Screengrabs}/atmos--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-atlantis--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-atlantis-generate--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-atlantis-generate-repo-config--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-aws--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-aws-eks--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-aws-eks-update-kubeconfig--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-completion--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-completion-bash.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-completion-fish.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-completion-powershell.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-completion-zsh.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-describe--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-describe-affected--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-describe-component--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-describe-config--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-describe-dependents--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-describe-stacks--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-describe-workflows--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-docs--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-helmfile--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-helmfile-generate--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-helmfile-generate-varfile--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-clean--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-deploy--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-generate--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-generate-backend--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-generate-backends--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-generate-varfile--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-generate-varfiles--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-shell--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-terraform-workspace--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-validate--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-validate-component--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-validate-stacks--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-vendor--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-vendor-pull--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/atmos-version.html (99%) rename website/src/components/{screengrabs => Screengrabs}/atmos-workflow--help.html (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/define-your-stacks.html (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/deploy-dev.ansi (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/deploy-dev.html (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/deploy-prod.html (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/deploy-staging.html (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/deploy.html (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/start-your-project.html (100%) rename website/src/components/{screengrabs => Screengrabs}/demo-stacks/write-your-components.html (100%) rename website/src/components/{screengrabs => Screengrabs}/tree-CAF--gitignore.html (100%) rename website/src/components/{screengrabs => Screengrabs}/tree.html (100%) create mode 100644 website/src/components/SecondaryCTA/index.css create mode 100644 website/src/components/SecondaryCTA/index.js rename website/src/components/{slides/slides.js => Slides/index.js} (91%) rename website/src/components/{slides/slides.module.css => Slides/index.module.css} (100%) create mode 100644 website/src/components/Step/index.css create mode 100644 website/src/components/Step/index.js create mode 100644 website/src/components/StepNumber/index.js delete mode 100644 website/src/components/Terminal.tsx create mode 100644 website/src/components/Terminal/index.css create mode 100644 website/src/components/Terminal/index.tsx create mode 100644 website/src/components/Typewriter/index.css rename website/src/components/{Typewriter.tsx => Typewriter/index.tsx} (67%) create mode 100644 website/src/css/landing-page.css create mode 100644 website/src/theme/DocItem/Layout/index.js create mode 100644 website/src/theme/NavbarItem.js diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..a3515d1b3 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,51 @@ +FROM golang:1.22 AS confetty + +# Set the working directory +WORKDIR /app + +# Install the confetty application +RUN go install github.com/maaslalani/confetty@latest + +FROM mcr.microsoft.com/vscode/devcontainers/base:debian + +# Copy the binary from the builder stage +COPY --from=confetty /go/bin/confetty /usr/local/bin/confetty + +# Install Docker CLI and Docker Compose plugin +RUN apt-get update && \ + apt-get install -y ca-certificates curl gnupg lsb-release apt-utils direnv screen && \ + mkdir -p /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ + $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \ + apt-get update && \ + apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && \ + rm -rf /var/lib/apt/lists/* + +# Ensure the vscode user can access the Docker socket, and change the shell to zsh +RUN usermod -aG docker vscode && \ + chsh -s /bin/zsh vscode + +# Install the starship prompt +RUN curl -sS https://starship.rs/install.sh | sh -s -- -y + +# Install OpenTofu +RUN curl -1sSLf 'https://get.opentofu.org/install-opentofu.sh' | bash -s -- --root-method none --install-method deb + +# Install Kustomize binary (required by Helmfile) +RUN curl -1sSLf "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash -s -- /usr/local/bin + +# Install the cloudposse Debian repository +RUN curl -1sLf 'https://dl.cloudsmith.io/public/cloudposse/packages/cfg/setup/bash.deb.sh' | bash + +RUN apt-get -y install atmos terraform kubectl helmfile helm k9s stern && \ + su - vscode -c "helm plugin install https://github.com/databus23/helm-diff" + +# Install the rootfs/ configurations +COPY rootfs/ / + +# Direnv permissions +RUN chown -R vscode:vscode /home/vscode/.config && \ + chmod -R 755 /home/vscode/.config && \ + chmod 644 /home/vscode/.config/direnv/direnvrc diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..3de764f57 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,80 @@ +{ + "name": "Atmos Demo Lab", + "forwardPorts": [80, 443], + "portsAttributes": { + "80": { + "label": "Kubernetes Ingress" + }, + "443": { + "label": "Kubernetes Ingress (TLS)" + } + }, + "security.workspace.trust.emptyWindow": true, + "security.workspace.trust.untrustedFiles": "prompt", + "security.workspace.trust.domain": { + "*.github.com": true, + "*.app.github.dev": true, + "localhost": true + }, + "build": { + "dockerfile": "Dockerfile", + "context": "." + }, + "hostRequirements": { + "cpus": 8, + "memory": "16gb", + "storage": "32gb" + }, + "runArgs": ["-v", "/var/run/docker.sock:/var/run/docker.sock"], + "postCreateCommand": "/workspace/.devcontainer/post-create.sh", + "service": "localstack", + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker": {}, + /*"ghcr.io/devcontainers/features/go:1": { + "version": "1.22" + },*/ + }, + "workspaceFolder": "/workspace/examples", + "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind", + + "customizations": { + "vscode": { + "extensions": [ + "ms-azuretools.vscode-docker", + "bierner.github-markdown-preview", + "tomasdahlqvist.markdown-admonitions", + "HashiCorp.terraform", + "redhat.vscode-yaml", + "casualjim.gotemplate", + "EditorConfig.EditorConfig" + ], + "settings": { + "git.openRepositoryInParentFolders": "always", + "git.autofetch": true, + "git.showProgress": true, + "workbench.startupEditor": "readme", + "workbench.editor.autoLockGroups": { + "readme": "/welcome.md" + }, + "workbench.editorAssociations": { + "*.md": "vscode.markdown.preview.editor" + }, + "terminal.integrated.tabs.title": "Atmos (${process})", + "terminal.integrated.tabs.description": "${task}${separator}${local}${separator}${cwdFolder}", + "terminal.integrated.shell.linux": "/bin/zsh", + "terminal.integrated.allowWorkspaceConfiguration": true, + "terminal.integrated.commandsToSkipShell": [], + "yaml.schemaStore.enable": true, + "json.schemas": [ + ], + "yaml.schemas": { + "https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json": [ + "**/stacks/**/*.yaml", + "!**/stacks/workflows/**/*.yaml", + "!**/stacks/schemas/**/*.yaml" + ] + } + } + } + } + } diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100755 index 000000000..50701de7f --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,28 @@ +#!/bin/zsh + +# Let's not show what commands the script is running +set +x + +# Display a different welcome message for Codespaces +mv /workspace/examples/welcome.md /workspace/examples/README.md + +# Use screen to run the following commands in the background so they don’t block startup time +# Note that this also means errors won’t fail the bootstrapping of the container, which can mask issues. + +# Install a .envrc file in each example directory (it's ignored in .gitignore) +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 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 +# This should used as the file for KUBECONFIG +cd /workspace/examples/demo-helmfile +screen -L -Logfile /tmp/k3s.log -S k3s -dm sh -c 'docker compose up' + +# Since we cannot mount volumes inside of compose, we need to copy the kubeconfig.yaml file to the workspace +export KUBECONFIG=${KUBECONFIG:-/workspace/examples/demo-helmfile/kubeconfig.yaml} +screen -L -Logfile /tmp/kubeconfig.log -S kubeconfig -dm sh -c 'until test -f ${KUBECONFIG}; do docker cp demo-helmfile-server-1:/output/kubeconfig.yaml ${KUBECONFIG}; sleep 1; done; chmod 600 ${KUBECONFIG}' diff --git a/.devcontainer/rootfs/home/vscode/.config/direnv/direnvrc b/.devcontainer/rootfs/home/vscode/.config/direnv/direnvrc new file mode 100644 index 000000000..e3ad926a9 --- /dev/null +++ b/.devcontainer/rootfs/home/vscode/.config/direnv/direnvrc @@ -0,0 +1,11 @@ +show_readme() { + if [ -f "./README.md" ]; then + # Check if the README.md file has been touched in the last 60 seconds + last_modified=$(stat -c %Y "./README.md") + current_time=$(date +%s) + if [ $((current_time - last_modified)) -gt 60 ]; then + code "./README.md" + touch "./README.md" + fi + fi +} diff --git a/.devcontainer/rootfs/home/vscode/.config/starship.toml b/.devcontainer/rootfs/home/vscode/.config/starship.toml new file mode 100644 index 000000000..00de8eea9 --- /dev/null +++ b/.devcontainer/rootfs/home/vscode/.config/starship.toml @@ -0,0 +1,48 @@ +format = """ +$username\ +$hostname\ +$directory\ +$git_branch\ +$git_state\ +$git_status\ +$cmd_duration\ +$line_break\ +$python\ +$character""" + +command_timeout = 2000 + +[directory] +style = "blue" + +[character] +success_symbol = "[❯](purple)" +error_symbol = "[❯](red)" +vimcmd_symbol = "[❮](green)" + +[git_branch] +format = "[$branch]($style)" +style = "bright-black" + +[git_status] +format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](218) ($ahead_behind$stashed)]($style)" +style = "cyan" +conflicted = "​" +untracked = "​" +modified = "​" +staged = "​" +renamed = "​" +deleted = "​" +stashed = "≡" + +[git_state] +format = '\([$state( $progress_current/$progress_total)]($style)\) ' +style = "bright-black" + +[cmd_duration] +format = "[$duration]($style) " +style = "yellow" + +[python] +format = "[$virtualenv]($style) " +style = "bright-black" diff --git a/.devcontainer/rootfs/home/vscode/.config/vscode-dev-containers/first-run-notice-already-displayed b/.devcontainer/rootfs/home/vscode/.config/vscode-dev-containers/first-run-notice-already-displayed new file mode 100644 index 000000000..e69de29bb diff --git a/.devcontainer/rootfs/home/vscode/.zsh_history b/.devcontainer/rootfs/home/vscode/.zsh_history new file mode 100644 index 000000000..d31812387 --- /dev/null +++ b/.devcontainer/rootfs/home/vscode/.zsh_history @@ -0,0 +1,12 @@ +: 1640995200:0;atmos terraform plan myapp --stack dev +: 1640995201:0;atmos terraform plan myapp --stack staging +: 1640995202:0;atmos terraform plan myapp --stack prod +: 1640995203:0;atmos terraform apply myapp --stack dev +: 1640995204:0;atmos terraform apply myapp --stack staging +: 1640995205:0;atmos terraform apply myapp --stack prod +: 1640995206:0;atmos terraform plan myapp --stack dev +: 1640995207:0;atmos terraform plan myapp --stack staging +: 1640995208:0;atmos terraform plan myapp --stack prod +: 1640995209:0;atmos terraform deploy myapp --stack dev +: 1640995210:0;atmos terraform deploy myapp --stack staging +: 1640995211:0;atmos terraform deploy myapp --stack prod diff --git a/.devcontainer/rootfs/home/vscode/.zshrc b/.devcontainer/rootfs/home/vscode/.zshrc new file mode 100644 index 000000000..43c5db598 --- /dev/null +++ b/.devcontainer/rootfs/home/vscode/.zshrc @@ -0,0 +1,37 @@ +eval "$(direnv hook zsh)" + +# VSCode shell integration +[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path zsh)" + +export KUBECONFIG=${KUBECONFIG:-/workspace/examples/demo-helmfile/kubeconfig.yaml} + +export CODESPACE_HOSTNAME="${CODESPACE_NAME}-80.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}" +export CODESPACE_HTTP_HOSTNAME="${CODESPACE_NAME}-80.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}" +export CODESPACE_HTTPS_HOSTNAME="${CODESPACE_NAME}-443.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}" + +export CODESPACE_URL="http://${CODESPACE_HOSTNAME}" +export CODESPACE_HTTP_URL="http://${CODESPACE_HTTP_HOSTNAME}" +export CODESPACE_HTTPS_URL="http://${CODESPACE_HTTPS_HOSTNAME}" + +# Install atmos completion +eval $(atmos completion zsh) + +# Setup some aliases +alias tree='tree -CAF --gitignore -I ".git" -I "terraform.tfstate*"' +alias bat='bat --style header,numbers --theme="GitHub"' + +# Disable directory entry messages +export DIRENV_LOG_FORMAT="" + +find /workspace/examples -name '.envrc' -execdir direnv allow \; + +# Enable Starship prompt +eval "$(starship init zsh)" + +# Celebrate! 🎉 +if [ "${TERM}" != "screen.xterm-256color" ]; then + timeout --preserve-status 2 confetty +fi + +# Show the version of atmos installed +atmos version diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8cb8bb356..c57646f57 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -45,9 +45,16 @@ jobs: run: | make version + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: build-artifacts + path: | + ./build/ + # run acceptance tests test: - name: Test + name: Acceptance Tests needs: build runs-on: ubuntu-latest timeout-minutes: 15 @@ -78,3 +85,205 @@ jobs: publish: false format: binary secrets: inherit + + # run localstack demo tests + localstack: + name: "[localstack] ${{ matrix.demo-folder }}" + needs: build + runs-on: ubuntu-latest + + services: + localstack: + image: localstack/localstack:1.4.0 + 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: + matrix: + demo-folder: + - demo-localstack + + timeout-minutes: 20 + steps: + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts + path: /usr/local/bin + + - name: Set execute permissions on atmos + run: chmod +x /usr/local/bin/atmos + + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + + - name: Run tests for ${{ matrix.demo-folder }} + run: | + cd examples/${{ matrix.demo-folder }} + atmos test + + # run k3s demo tests + k3s: + name: "[k3s] ${{ matrix.demo-folder }}" + needs: build + runs-on: ubuntu-latest + env: + KUBECONFIG: ${{github.workspace}}/examples/${{ matrix.demo-folder }}/kubeconfig.yaml + ATMOS_LOGS_LEVEL: Debug + strategy: + matrix: + demo-folder: + - demo-helmfile + + timeout-minutes: 20 + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + + - name: Start Docker Compose + working-directory: examples/${{ matrix.demo-folder }} + run: docker compose up -d --wait + + - name: Wait for k3s to start + working-directory: examples/${{ matrix.demo-folder }} + run: | + until kubectl get pods --all-namespaces >/dev/null 2>&1; do + echo "Retrying..." + sleep 1 + done + kubectl get pods --all-namespaces + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts + path: /usr/local/bin + + - name: Set execute permissions on atmos + run: chmod +x /usr/local/bin/atmos + + - name: Install the Cloud Posse package repository + run: curl -1sLf 'https://dl.cloudsmith.io/public/cloudposse/packages/cfg/setup/bash.deb.sh' | sudo bash + + - name: Install kubectl, helmfile, and helm + run: sudo apt-get -y install kubectl helmfile helm + + - name: Install helm-diff plugin + run: helm plugin install https://github.com/databus23/helm-diff + + - name: Write a default AWS profile to the AWS config file + run: | + mkdir -p ~/.aws + echo '[default]' > ~/.aws/config + + - name: Run tests for ${{ matrix.demo-folder }} + run: | + cd examples/${{ matrix.demo-folder }} + atmos test + + # run other demo tests + mock: + name: "[mock] ${{ matrix.demo-folder }}" + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + demo-folder: + - demo-atlantis + # - demo-component-manifest + - demo-component-versions + - demo-context + # - demo-custom-command + # - demo-json-validation + # - demo-opa-validation + # - demo-opentofu + # - demo-project + # - demo-stacks + # - demo-terraform + # - demo-terraform-overrides + # - demo-workflows + # - demo-yaml-anchors + # - demo-mock-architecture + # - demo-stack-templating + # - demo-multi-cloud + # - demo-vendoring + + timeout-minutes: 20 + steps: + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts + path: /usr/local/bin + + - name: Set execute permissions on atmos + run: chmod +x /usr/local/bin/atmos + + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + + - name: Run tests for ${{ matrix.demo-folder }} + run: | + cd examples/${{ matrix.demo-folder }} + atmos test + + # run other demo tests + lint: + name: "[lint] ${{ matrix.demo-folder }}" + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + demo-folder: + # - demo-component-manifest + - demo-context + # - demo-custom-command + # - demo-json-validation + # - demo-library + # - demo-localstack + # - demo-opa-validation + # - demo-opentofu + # - demo-project + # - demo-stacks + # - demo-terraform + # - demo-terraform-overrides + # - demo-workflows + # - demo-yaml-anchors + # - demo-mock-architecture + # - demo-stack-templating + # - demo-multi-cloud + + timeout-minutes: 20 + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + + - name: Install Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ steps.config.outputs.terraform-version }} + terraform_wrapper: false + + - name: Lint examples/${{ matrix.demo-folder }}/components/terraform + uses: reviewdog/action-tflint@v1 + with: + github_token: ${{ secrets.github_token }} + working_directory: examples/${{ matrix.demo-folder }}/components/terraform + flags: >- + --enable-rule=terraform_unused_declarations + --disable-rule=terraform_typed_variables + --minimum-failure-severity=warning + --recursive + --config=${{ github.workspace }}/examples/.tflint.hcl + fail_on_error: true diff --git a/.gitignore b/.gitignore index e36f7056e..f231eff31 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ **/.terraform/* *.tfstate *.tfstate.* +**/*.tf.json **/planfile **/*.planfile **/*.kubeconfig @@ -10,6 +11,8 @@ **/*.helmfile.vars.yaml **/.terraform.lock.hcl .vscode/ +**/nohup.out +**/kubeconfig.yaml # Module directory .terraform diff --git a/README.md b/README.md index 677c43035..2e21f6a59 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ + + -Project Banner
+Project Banner

Latest ReleaseLast UpdatedTestsSlack Community

@@ -25,31 +27,26 @@ --> -> ### Automated Terraform Management & Orchestration Software (ATMOS) +## Use Atmos to break your architecture into reusable [Components](https://atmos.tools/core-concepts/components) that you implement using [Terraform "root modules"](https://atmos.tools/core-concepts/components/terraform). Then tie everything together using [Stack](https://atmos.tools/core-concepts/stacks) configurations defined in YAML. + +Atmos can change how you think about the Terraform code you write to build your infrastructure. Atmos is a framework that simplifies complex cloud architectures and DevOps workflows into intuitive CLI commands. +Its strength in managing DRY configurations at scale for Terraform and is supported by robust design patterns, comprehensive documentation, and a passionate community, making it a versatile tool for both startups and enterprises. +Atmos is extensible to accommodate any tooling, including enterprise-scale Terraform, and includes custom policy controls, vendoring, and GitOps capabilities out of the box. Everything is open source and free. + -Atmos simplifies complex cloud architectures and DevOps workflows into [intuitive CLI commands](https://atmos.tools/category/cli). -Its strength in managing [DRY configurations at scale](https://atmos.tools/core-concepts/) is supported by robust -[design patterns](https://atmos.tools/design-patterns/), comprehensive [documentation](https://atmos.tools/), and a -[passionate community](https://slack.cloudposse.com/), making it a versatile [tool for both startups and enterprises](https://cloudposse.com/). -Atmos is extensible to accommodate any tooling, including enterprise-scale Terraform, and includes -[policy controls](https://atmos.tools/core-concepts/components/validation), [vendoring](https://atmos.tools/core-concepts/vendoring/), -and [GitOps capabilities](https://atmos.tools/integrations/github-actions) out of the box. Everything is open source and free. +> [!TIP] +> ### You can try out `atmos` directly in your browser using GitHub Codespaces +> +> [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=reorg&repo=cloudposse/atmos&skip_quickstart=true) +> +> Already start one? Find it [here](https://github.com/codespaces). +> ## Screenshots Demo*
Example of running atmos to describe infrastructure.* ---- -> [!NOTE] -> This project is part of Cloud Posse's comprehensive ["SweetOps"](https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/atmos&utm_content=) approach towards DevOps. ->
Learn More -> -> It's 100% Open Source and licensed under the [APACHE2](LICENSE). -> ->
- - ## Introduction @@ -85,7 +82,7 @@ indispensable asset for managing complex infrastructures with confidence. - [**Native Terraform Support:**](https://atmos.tools/cli/commands/terraform/usage) Orchestration, backend generation, varfile generation, ensuring compatibility with vanilla Terraform. - [**Stacks:**](https://atmos.tools/core-concepts/stacks) Powerful abstraction layer defined in YAML for orchestrating and deploying components. - [**Components:**](https://atmos.tools/core-concepts/components) A generic abstraction for deployable units, such as Terraform "root" modules. -- [**Vendoring:**](https://atmos.tools/core-concepts/vendoring) Pulls dependencies from remote sources, supporting immutable infrastructure practices. +- [**Vendoring:**](https://atmos.tools/core-concepts/vendor) Pulls dependencies from remote sources, supporting immutable infrastructure practices. - [**Custom Commands:**](https://atmos.tools/core-concepts/custom-commands) Extends Atmos's functionality, allowing integration of any command with stack configurations. - [**Workflow Orchestration:**](https://atmos.tools/core-concepts/workflows) Comprehensive support for managing the lifecycle of cloud infrastructure from initiation to maintenance. @@ -105,11 +102,11 @@ strength in the cloud infrastructure and DevOps domains: configuration, bypassing the need for further code development. - **Efficient Multi-Region Deployments:** Atmos facilitates streamlined multi-region deployments by enabling businesses to define baseline configurations with [stacks](https://atmos.tools/core-concepts/stacks/) and extend them across regions with DRY principles through - [imports](https://atmos.tools/core-concepts/stacks/imports) and [inheritance](https://atmos.tools/core-concepts/components/inheritance). + [imports](https://atmos.tools/core-concepts/stacks/imports) and [inheritance](https://atmos.tools/core-concepts/stacks/inheritance). - **Compliant Infrastructure for Regulated Industries:** Atmos empowers DevOps and SecOps teams to create vetted configurations that comply with SOC2, HIPAA, HITRUST, PCI, and other regulatory standards. These configurations can then be efficiently shared and reused across the organization via [service catalogs](https://atmos.tools/core-concepts/stacks/catalogs), [component libraries](https://atmos.tools/core-concepts/components/library), - [vendoring](https://atmos.tools/core-concepts/vendoring), and [OPA policies](https://atmos.tools/core-concepts/components/validation), + [vendoring](https://atmos.tools/core-concepts/vendor), and [OPA policies](https://atmos.tools/core-concepts/validate/opa), simplifying the process of achieving and maintaining rigorous compliance. - **Empowering Teams with Self-Service Infrastructure:** Allows teams to manage their infrastructure needs independently, using predefined templates and policies. @@ -143,23 +140,21 @@ Find all documentation at: [atmos.tools](https://atmos.tools) + + ## ✨ Contributing This project is under active development, and we encourage contributions from our community. + + + Many thanks to our outstanding contributors: -### 🐛 Bug Reports & Feature Requests - -Please use the [issue tracker](https://github.com/cloudposse/atmos/issues) to report any bugs or file feature requests. - -### 💻 Developing - -If you are interested in being a contributor and want to get involved in developing this project or help out with Cloud Posse's other projects, we would love to hear from you! -Hit us up in [Slack](https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/atmos&utm_content=slack), in the `#cloudposse` channel. +For 🐛 bug reports & feature requests, please use the [issue tracker](https://github.com/cloudposse/atmos/issues). In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. 1. Review our [Code of Conduct](https://github.com/cloudposse/atmos/?tab=coc-ov-file#code-of-conduct) and [Contributor Guidelines](https://github.com/cloudposse/.github/blob/main/CONTRIBUTING.md). @@ -184,38 +179,6 @@ Dropped straight into your Inbox every week — and usually a 5-minute read. [Join us every Wednesday via Zoom](https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/atmos&utm_content=office_hours) for your weekly dose of insider DevOps trends, AWS news and Terraform insights, all sourced from our SweetOps community, plus a _live Q&A_ that you can’t find anywhere else. It's **FREE** for everyone! - -## About - -This project is maintained by Cloud Posse, LLC. - - -We are a [**DevOps Accelerator**](https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/atmos&utm_content=commercial_support) for funded startups and enterprises. -Use our ready-to-go terraform architecture blueprints for AWS to get up and running quickly. -We build it with you. You own everything. Your team wins. Plus, we stick around until you succeed. - -Learn More - -*Your team can operate like a pro today.* - -Ensure that your team succeeds by using our proven process and turnkey blueprints. Plus, we stick around until you succeed. - -
- 📚 See What's Included - -- **Reference Architecture.** You'll get everything you need from the ground up built using 100% infrastructure as code. -- **Deployment Strategy.** You'll have a battle-tested deployment strategy using GitHub Actions that's automated and repeatable. -- **Site Reliability Engineering.** You'll have total visibility into your apps and microservices. -- **Security Baseline.** You'll have built-in governance with accountability and audit logs for all changes. -- **GitOps.** You'll be able to operate your infrastructure via Pull Requests. -- **Training.** You'll receive hands-on training so your team can operate what we build. -- **Questions.** You'll have a direct line of communication between our teams via a Shared Slack channel. -- **Troubleshooting.** You'll get help to triage when things aren't working. -- **Code Reviews.** You'll receive constructive feedback on Pull Requests. -- **Bug Fixes.** We'll rapidly work with you to fix any bugs in our projects. -
- - ## License License @@ -250,6 +213,8 @@ under the License. ## Trademarks All other trademarks referenced herein are the property of their respective owners. + + --- Copyright © 2017-2024 [Cloud Posse, LLC](https://cpco.io/copyright) diff --git a/README.yaml b/README.yaml index 5200e89f3..e55d6334e 100644 --- a/README.yaml +++ b/README.yaml @@ -39,15 +39,20 @@ screenshots: url: "docs/demo.gif" description: |- - > ### Automated Terraform Management & Orchestration Software (ATMOS) + ## Use Atmos to break your architecture into reusable [Components](https://atmos.tools/core-concepts/components) that you implement using [Terraform "root modules"](https://atmos.tools/core-concepts/components/terraform). Then tie everything together using [Stack](https://atmos.tools/core-concepts/stacks) configurations defined in YAML. - Atmos simplifies complex cloud architectures and DevOps workflows into [intuitive CLI commands](https://atmos.tools/category/cli). - Its strength in managing [DRY configurations at scale](https://atmos.tools/core-concepts/) is supported by robust - [design patterns](https://atmos.tools/design-patterns/), comprehensive [documentation](https://atmos.tools/), and a - [passionate community](https://slack.cloudposse.com/), making it a versatile [tool for both startups and enterprises](https://cloudposse.com/). - Atmos is extensible to accommodate any tooling, including enterprise-scale Terraform, and includes - [policy controls](https://atmos.tools/core-concepts/components/validation), [vendoring](https://atmos.tools/core-concepts/vendoring/), - and [GitOps capabilities](https://atmos.tools/integrations/github-actions) out of the box. Everything is open source and free. + Atmos can change how you think about the Terraform code you write to build your infrastructure. Atmos is a framework that simplifies complex cloud architectures and DevOps workflows into intuitive CLI commands. + Its strength in managing DRY configurations at scale for Terraform and is supported by robust design patterns, comprehensive documentation, and a passionate community, making it a versatile tool for both startups and enterprises. + Atmos is extensible to accommodate any tooling, including enterprise-scale Terraform, and includes custom policy controls, vendoring, and GitOps capabilities out of the box. Everything is open source and free. + + + > [!TIP] + > ### You can try out `atmos` directly in your browser using GitHub Codespaces + > + > [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=reorg&repo=cloudposse/atmos&skip_quickstart=true) + > + > Already start one? Find it [here](https://github.com/codespaces). + > introduction: |- @@ -81,7 +86,7 @@ introduction: |- - [**Native Terraform Support:**](https://atmos.tools/cli/commands/terraform/usage) Orchestration, backend generation, varfile generation, ensuring compatibility with vanilla Terraform. - [**Stacks:**](https://atmos.tools/core-concepts/stacks) Powerful abstraction layer defined in YAML for orchestrating and deploying components. - [**Components:**](https://atmos.tools/core-concepts/components) A generic abstraction for deployable units, such as Terraform "root" modules. - - [**Vendoring:**](https://atmos.tools/core-concepts/vendoring) Pulls dependencies from remote sources, supporting immutable infrastructure practices. + - [**Vendoring:**](https://atmos.tools/core-concepts/vendor) Pulls dependencies from remote sources, supporting immutable infrastructure practices. - [**Custom Commands:**](https://atmos.tools/core-concepts/custom-commands) Extends Atmos's functionality, allowing integration of any command with stack configurations. - [**Workflow Orchestration:**](https://atmos.tools/core-concepts/workflows) Comprehensive support for managing the lifecycle of cloud infrastructure from initiation to maintenance. @@ -101,11 +106,11 @@ introduction: |- configuration, bypassing the need for further code development. - **Efficient Multi-Region Deployments:** Atmos facilitates streamlined multi-region deployments by enabling businesses to define baseline configurations with [stacks](https://atmos.tools/core-concepts/stacks/) and extend them across regions with DRY principles through - [imports](https://atmos.tools/core-concepts/stacks/imports) and [inheritance](https://atmos.tools/core-concepts/components/inheritance). + [imports](https://atmos.tools/core-concepts/stacks/imports) and [inheritance](https://atmos.tools/core-concepts/stacks/inheritance). - **Compliant Infrastructure for Regulated Industries:** Atmos empowers DevOps and SecOps teams to create vetted configurations that comply with SOC2, HIPAA, HITRUST, PCI, and other regulatory standards. These configurations can then be efficiently shared and reused across the organization via [service catalogs](https://atmos.tools/core-concepts/stacks/catalogs), [component libraries](https://atmos.tools/core-concepts/components/library), - [vendoring](https://atmos.tools/core-concepts/vendoring), and [OPA policies](https://atmos.tools/core-concepts/components/validation), + [vendoring](https://atmos.tools/core-concepts/vendor), and [OPA policies](https://atmos.tools/core-concepts/validate/opa), simplifying the process of achieving and maintaining rigorous compliance. - **Empowering Teams with Self-Service Infrastructure:** Allows teams to manage their infrastructure needs independently, using predefined templates and policies. diff --git a/atmos.yaml b/atmos.yaml index daf33b02d..559f623f9 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -310,9 +310,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -323,7 +323,7 @@ schemas: manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/cmd/cmd_utils.go b/cmd/cmd_utils.go index e59ef46d5..93188ca75 100644 --- a/cmd/cmd_utils.go +++ b/cmd/cmd_utils.go @@ -383,5 +383,5 @@ func printMessageToUpgradeToAtmosLatestRelease(latestVersion string) { u.PrintMessage("https://github.com/cloudposse/atmos/releases\n") u.PrintMessageInColor("Install Atmos:\n", c2) - u.PrintMessage("https://atmos.tools/quick-start/install-atmos\n") + u.PrintMessage("https://atmos.tools/install\n") } diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 000000000..ea289fc8a --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1 @@ +**/.envrc diff --git a/examples/.tflint.hcl b/examples/.tflint.hcl new file mode 100644 index 000000000..427121c3e --- /dev/null +++ b/examples/.tflint.hcl @@ -0,0 +1,4 @@ +plugin "terraform" { + enabled = true + preset = "recommended" +} diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 000000000..d11939411 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,61 @@ +# Examples + +> [!TIP] + > ### You can try `atmos` directly in your browser using GitHub Codespaces! + > + > [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=cloudposse/atmos&skip_quickstart=true) + > + > Already start one? Find it [here](https://github.com/codespaces). + > + +## Try it Locally + +To play with these demos locally, start by [installing `atmos`](https://atmos.tools/install). + +Then run the following commands (Note, these commands requires that you have `curl` and `tar` installed on your system.) + +```shell +atmos demo download +``` + +For example, the following command will download the `demo-stacks` example. +```shell +atmos demo download demo-stacks +``` + +> [!TIP] +> #### Fun Fact +> +> The `download` command is a [custom command](https://atmos.tools/core-concepts/custom-commands) added to the default `atmos.yaml`. +> + + +## Demos + +We designed the demos to be basic examples showcasing functionality. Expect some redundancies and overlap since we reuse examples to demonstrate specific behaviors. Each demo focuses on one area to reduce complexity and make it easier to grasp the concepts. + +Think of each demo folder as representing an example of a standalone repository. To make it easier, we put all the demos in one place. + +```shell +1. ├── demo-stacks/ # Start your journey here +2. ├── demo-library/ # +3. ├── demo-validation/ # +4. ├── demo-vendoring/ # +5. ├── demo-custom-commands/ # +6. └── demo-workflows/ # +``` + +## Playground + + +## Quick Start (Simple) + +The [`demo-stacks`](demo-stacks/) contains code for the [simple quick start](https://atmos.tools/quick-start/advanced). This requires no special permissions and is the fastest way to grasp [atmos concepts](https://atmos.tools/core-concepts). + +## Quick Start (Advanced) + +The [`quick-start`](quick-start/) contains code for the [advanced quick start](https://atmos.tools/quick-start/advanced). Please note that it requires an AWS organization with administrative credentials. + +## Tests + +The [`tests/`](tests/) folder includes a variety of patterns and configurations that we use for CI tests. They are not intended to serve as examples or best practices. We deliberately break some of them for testing purposes. These configurations implement every function of Atmos in some shape or form, but they are not necessarily exemplars of design. diff --git a/examples/demo-atlantis/.gitignore b/examples/demo-atlantis/.gitignore new file mode 100644 index 000000000..4abbe18a1 --- /dev/null +++ b/examples/demo-atlantis/.gitignore @@ -0,0 +1 @@ +atlantis.yaml diff --git a/examples/demo-atlantis/atmos.yaml b/examples/demo-atlantis/atmos.yaml new file mode 100644 index 000000000..922c01460 --- /dev/null +++ b/examples/demo-atlantis/atmos.yaml @@ -0,0 +1,103 @@ +# atmos.yaml CLI config +base_path: "./" + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "deploy/**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +logs: + file: "/dev/stderr" + level: Info + +commands: +- name: "test" + description: "Run all tests" + steps: + - atmos atlantis build-all + +- name: "atlantis" + commands: + - name: "build-all" + description: "Build all configurations for Atlantis" + steps: + - echo "Building Atlantis config..." + - atmos atlantis generate repo-config --config-template config-1 --project-template project-1 + - echo "Generating varfiles..." + - >- + atmos terraform generate varfiles \ + --file-template={component-path}/varfiles/{namespace}-{environment}-{component}.tfvars.json + - echo "Generating varfiles..." + - >- + atmos terraform generate backends \ + --format=backend-config \ + --file-template={component-path}/backends/{namespace}-{environment}-{component}.backend + + +# Integrations +integrations: + + # Atlantis integration + # https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html + atlantis: + # Path and name of the Atlantis config file `atlantis.yaml` + path: "atlantis.yaml" + + # Config templates + # Select a template by using the `--config-template ` command-line argument in `atmos atlantis generate repo-config` command + config_templates: + config-1: + version: 3 + automerge: true + delete_source_branch_on_merge: true + parallel_plan: true + parallel_apply: true + allowed_regexp_prefixes: + - dev/ + - staging/ + - prod/ + + # Project templates + # Select a template by using the `--project-template ` command-line argument in `atmos atlantis generate repo-config` command + project_templates: + project-1: + # generate a project entry for each component in every stack + name: "{tenant}-{environment}-{stage}-{component}" + workspace: "{workspace}" + dir: "{component-path}" + terraform_version: v1.8 + delete_source_branch_on_merge: true + autoplan: + enabled: true + when_modified: + - "**/*.tf" + - "varfiles/$PROJECT_NAME.tfvars" + apply_requirements: + - "approved" + + # Workflow templates + # https://www.runatlantis.io/docs/custom-workflows.html#custom-init-plan-apply-commands + # https://www.runatlantis.io/docs/custom-workflows.html#custom-run-command + workflow_templates: + workflow-1: + plan: + steps: + - run: atmos terraform init -input=false + # When using workspaces, you need to select the workspace using the $WORKSPACE environment variable + - run: atmos terraform workspace select $WORKSPACE + # You must output the plan using `-out $PLANFILE` because Atlantis expects plans to be in a specific location + - run: terraform plan -input=false -refresh -out $PLANFILE -var-file varfiles/$PROJECT_NAME.tfvars + apply: + steps: + - run: terraform apply $PLANFILE diff --git a/examples/demo-atlantis/stacks/deploy/demo.yaml b/examples/demo-atlantis/stacks/deploy/demo.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-component-versions/.gitignore b/examples/demo-component-versions/.gitignore new file mode 100644 index 000000000..590d8f699 --- /dev/null +++ b/examples/demo-component-versions/.gitignore @@ -0,0 +1 @@ +components/terraform/** diff --git a/examples/demo-component-versions/atmos.yaml b/examples/demo-component-versions/atmos.yaml new file mode 100644 index 000000000..e24b091f4 --- /dev/null +++ b/examples/demo-component-versions/atmos.yaml @@ -0,0 +1,28 @@ +# atmos.yaml CLI config +base_path: "./" + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "deploy/**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +logs: + file: "/dev/stderr" + level: Info + +commands: +- name: "test" + description: "Run all tests" + steps: + - atmos vendor pull diff --git a/examples/demo-component-versions/stacks/deploy/demo-v1.yaml b/examples/demo-component-versions/stacks/deploy/demo-v1.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-component-versions/vendor.yaml b/examples/demo-component-versions/vendor.yaml new file mode 100644 index 000000000..1fcb5b4d2 --- /dev/null +++ b/examples/demo-component-versions/vendor.yaml @@ -0,0 +1,38 @@ +apiVersion: atmos/v1 +kind: AtmosVendorConfig +metadata: + name: demo-yaml-anchors + description: Example of using YAML anchors with an Atmos vendoring manifest +spec: + # Import other vendor manifests, if necessary + imports: [] + bases: + - &library + source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" + version: "reorg" + targets: + - "components/terraform/{{ .Component }}/{{.Version}}" + included_paths: + - "**/*.tf" + - "**/*.tfvars" + - "**/*.md" + tags: + - demo + + - &main + <<: *library + version: "main" + + - &v1 + <<: *library + version: "reorg" + + sources: + - <<: *v1 + component: "github/stargazers" + + - <<: *v1 + component: "weather" + + - <<: *v1 + component: "ipinfo" diff --git a/examples/demo-context/README.md b/examples/demo-context/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-context/atmos.yaml b/examples/demo-context/atmos.yaml new file mode 100644 index 000000000..5a1bb7487 --- /dev/null +++ b/examples/demo-context/atmos.yaml @@ -0,0 +1,46 @@ +base_path: "./" + +schemas: + atmos: + manifest: "schemas/atmos-manifest.json" + +# https://pkg.go.dev/text/template +templates: + settings: + enabled: true + evaluations: 2 + sprig: + enabled: true + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "**/*" + excluded_paths: + - "**/_defaults.yaml" + + name_template: "{{.providers.context.values.product}}-{{.providers.context.values.region}}-{{.providers.context.values.environment}}" + +logs: + file: "/dev/stderr" + level: Info + +commands: +- name: "test" + description: "Run all tests" + steps: + - atmos validate stacks + - atmos terraform plan demo -s acme-west-dev + - atmos terraform plan demo -s acme-west-staging + - atmos terraform plan demo -s acme-west-prod + - atmos terraform apply demo -s acme-west-dev -auto-approve + - atmos terraform apply demo -s acme-west-staging -auto-approve + - atmos terraform apply demo -s acme-west-prod -auto-approve diff --git a/examples/demo-context/components/terraform/petset/README.md b/examples/demo-context/components/terraform/petset/README.md new file mode 100644 index 000000000..49c8ce2b8 --- /dev/null +++ b/examples/demo-context/components/terraform/petset/README.md @@ -0,0 +1 @@ +This demo showcases our [Terraform context provider’s](https://github.com/cloudposse/terraform-provider-context) capability to assign unique names to resources based on their context, all without the need to pass any variables -- even between nested modules. diff --git a/examples/demo-context/components/terraform/petset/main.tf b/examples/demo-context/components/terraform/petset/main.tf new file mode 100644 index 000000000..f175dbb99 --- /dev/null +++ b/examples/demo-context/components/terraform/petset/main.tf @@ -0,0 +1,21 @@ +# Get the context so we can read properties (enabled) from it +data "context_config" "this" {} + +# Create a label based on the context +data "context_label" "this" { +} + +# Create tags based on the context. Add the value of the name label to the tags +data "context_tags" "this" { + values = { + "type" = var.pet + } +} + +module "pet_set" { + source = "./modules/instance" + for_each = {for i in range(var.size) : i => var.pet} + + pet = each.value + instance = each.key + 1 +} diff --git a/examples/demo-context/components/terraform/petset/modules/instance/main.tf b/examples/demo-context/components/terraform/petset/modules/instance/main.tf new file mode 100644 index 000000000..7f2d40bb2 --- /dev/null +++ b/examples/demo-context/components/terraform/petset/modules/instance/main.tf @@ -0,0 +1,30 @@ +# Create a label based on the context +data "context_label" "this" { + values = { + "instance" = var.instance + } +} + +# Create tags based on the context. Add the value of the name label to the tags +data "context_tags" "this" { + values = { + "instance" = var.instance + } +} + +locals { + instance_types = { + "alien" = "👽" # Alien + "ant" = "🐜" # Ant + "dog" = "🐶" # Dog + "cat" = "🐱" # Cat + "elephant" = "🐘" # Elephant + "tiger" = "🐯" # Tiger + "fox" = "🦊" # Fox + "monkey" = "🐵" # Monkey + "whale" = "🐳" # Whale + "dragon" = "🐉" # Dragon + } + + instance_type = lookup(local.instance_types, var.pet, "❓") +} diff --git a/examples/demo-context/components/terraform/petset/modules/instance/outputs.tf b/examples/demo-context/components/terraform/petset/modules/instance/outputs.tf new file mode 100644 index 000000000..bf17043c7 --- /dev/null +++ b/examples/demo-context/components/terraform/petset/modules/instance/outputs.tf @@ -0,0 +1,12 @@ +output "tags" { + description = "Generated Resource Tags" + value = data.context_tags.this.tags +} + +output "instance_type" { + value = local.instance_type +} + +output "name" { + value = format("%s %s", local.instance_type, data.context_label.this.rendered) +} diff --git a/examples/demo-context/components/terraform/petset/modules/instance/variables.tf b/examples/demo-context/components/terraform/petset/modules/instance/variables.tf new file mode 100644 index 000000000..04c705e4a --- /dev/null +++ b/examples/demo-context/components/terraform/petset/modules/instance/variables.tf @@ -0,0 +1,9 @@ +variable "pet" { + description = "The type of pet to include in the PetSet" + type = string +} + +variable "instance" { + description = "The instance number of the pet" + type = string +} diff --git a/examples/demo-context/components/terraform/petset/modules/instance/versions.tf b/examples/demo-context/components/terraform/petset/modules/instance/versions.tf new file mode 100644 index 000000000..3dbd1638c --- /dev/null +++ b/examples/demo-context/components/terraform/petset/modules/instance/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + context = { + source = "cloudposse/context" + version = "0.4.0" + } + } + + required_version = ">= 1.5.7" +} diff --git a/examples/demo-context/components/terraform/petset/outputs.tf b/examples/demo-context/components/terraform/petset/outputs.tf new file mode 100644 index 000000000..6a03b5804 --- /dev/null +++ b/examples/demo-context/components/terraform/petset/outputs.tf @@ -0,0 +1,23 @@ +output "size" { + description = "Size of deployment" + value = var.size +} + +output "tags" { + description = "Generated Resource Tags" + value = data.context_tags.this.tags +} + +output "label" { + description = "Generated Resource Label" + value = data.context_label.this.rendered +} + +output "pet_set" { + value = [for k, v in module.pet_set : v.name] +} + +output "delimiter" { + description = "Delimiter used in the context" + value = data.context_config.this.delimiter +} diff --git a/examples/demo-context/components/terraform/petset/providers.tf b/examples/demo-context/components/terraform/petset/providers.tf new file mode 100644 index 000000000..60a7e38f6 --- /dev/null +++ b/examples/demo-context/components/terraform/petset/providers.tf @@ -0,0 +1,2 @@ +provider "context" { +} diff --git a/examples/demo-context/components/terraform/petset/variables.tf b/examples/demo-context/components/terraform/petset/variables.tf new file mode 100644 index 000000000..dc0e6c1ed --- /dev/null +++ b/examples/demo-context/components/terraform/petset/variables.tf @@ -0,0 +1,11 @@ +variable "pet" { + description = "The type of instance to include in the PetSet" + type = string + default = "dog" +} + +variable "size" { + description = "The number of pet instances to create" + type = number + default = 3 +} diff --git a/examples/demo-context/components/terraform/petset/versions.tf b/examples/demo-context/components/terraform/petset/versions.tf new file mode 100644 index 000000000..3dbd1638c --- /dev/null +++ b/examples/demo-context/components/terraform/petset/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + context = { + source = "cloudposse/context" + version = "0.4.0" + } + } + + required_version = ">= 1.5.7" +} diff --git a/examples/quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json b/examples/demo-context/schemas/atmos-manifest.json similarity index 100% rename from examples/quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json rename to examples/demo-context/schemas/atmos-manifest.json diff --git a/examples/demo-context/stacks/catalog/demo.yaml b/examples/demo-context/stacks/catalog/demo.yaml new file mode 100644 index 000000000..e55af898a --- /dev/null +++ b/examples/demo-context/stacks/catalog/demo.yaml @@ -0,0 +1,12 @@ +components: + terraform: + demo: + metadata: + type: abstract + component: petset + providers: + context: + values: + name: petset + vars: + pet: "dog" diff --git a/examples/demo-context/stacks/deploy/_defaults.yaml b/examples/demo-context/stacks/deploy/_defaults.yaml new file mode 100644 index 000000000..5a4229d07 --- /dev/null +++ b/examples/demo-context/stacks/deploy/_defaults.yaml @@ -0,0 +1,40 @@ +terraform: + backend_type: local + + providers: + # Configure the context provider + context: + enabled: true + delimiter: "-" + property_order: + - product + - region + - environment + - name + - instance + properties: + product: + required: true + region: + required: true + validation_regex: "^(east|west)$" + environment: + required: true + max_length: 7 + name: + required: true + instance: {} + component: {} + type: {} + repo: {} + stack: {} + stack_file: {} + support_email: + required: true + validation_regex: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" + tags_key_case: title + values: + product: "acme" + component: "{{.atmos_component}}" + stack: "{{.atmos_stack}}" + stack_file: "{{.atmos_stack_file}}" diff --git a/examples/demo-context/stacks/deploy/dev/demo.yaml b/examples/demo-context/stacks/deploy/dev/demo.yaml new file mode 100644 index 000000000..cb1acecb4 --- /dev/null +++ b/examples/demo-context/stacks/deploy/dev/demo.yaml @@ -0,0 +1,19 @@ +import: +- deploy/_defaults +- catalog/demo +- mixins/west-coast + +terraform: + providers: + context: + values: + environment: dev + support_email: dev-support@acme.com + +components: + terraform: + demo: + metadata: + type: real + vars: + size: 3 diff --git a/examples/demo-context/stacks/deploy/prod/demo.yaml b/examples/demo-context/stacks/deploy/prod/demo.yaml new file mode 100644 index 000000000..e8893c6c9 --- /dev/null +++ b/examples/demo-context/stacks/deploy/prod/demo.yaml @@ -0,0 +1,21 @@ +import: +- deploy/_defaults +- catalog/demo +- mixins/east-coast + + +terraform: + providers: + context: + values: + environment: prod + support_email: prod-support@acme.com + +components: + terraform: + demo: + metadata: + type: real + vars: + size: 10 + pet: "alien" diff --git a/examples/demo-context/stacks/deploy/staging/demo.yaml b/examples/demo-context/stacks/deploy/staging/demo.yaml new file mode 100644 index 000000000..e53c5586d --- /dev/null +++ b/examples/demo-context/stacks/deploy/staging/demo.yaml @@ -0,0 +1,20 @@ +import: +- deploy/_defaults +- catalog/demo +- mixins/east-coast + +terraform: + providers: + context: + values: + environment: staging + support_email: staging-support@acme.com + +components: + terraform: + demo: + metadata: + type: real + vars: + size: 5 + pet: "whale" diff --git a/examples/demo-context/stacks/mixins/east-coast.yaml b/examples/demo-context/stacks/mixins/east-coast.yaml new file mode 100644 index 000000000..fd2fbdf17 --- /dev/null +++ b/examples/demo-context/stacks/mixins/east-coast.yaml @@ -0,0 +1,5 @@ +terraform: + providers: + context: + values: + region: west diff --git a/examples/demo-context/stacks/mixins/west-coast.yaml b/examples/demo-context/stacks/mixins/west-coast.yaml new file mode 100644 index 000000000..fd2fbdf17 --- /dev/null +++ b/examples/demo-context/stacks/mixins/west-coast.yaml @@ -0,0 +1,5 @@ +terraform: + providers: + context: + values: + region: west diff --git a/examples/demo-custom-command/README.md b/examples/demo-custom-command/README.md new file mode 100644 index 000000000..f1ddf7e2e --- /dev/null +++ b/examples/demo-custom-command/README.md @@ -0,0 +1,46 @@ +# Custom Commands + +Customize Atmos to run any command you want to make it easier for teams to use your toolchain. + +## Examples + +Examples in this demo are all defined in the [`atmos.yaml`](atmos.yaml) configuration under the `commands` section. + +### Help + +Custom Commands are available via the `atmos --help` command, just like all the other commands in Atmos. This makes discovery +easier for developers, as they get a single pane of glass to your DevOps tooling. + +Run the following command to get the help menu. + +```shell +atmos --help +``` + +Notice that a few custom commands are available: +- `atmos hello` +- `atmos github` +- `atmos weather` + +### Hello World! + +This is the most basic example that shows how easy it is to add a command to atmos. + +Run run the following command: + +```shell + atmos hello +``` + +### Check GitHub Status + +We all depend on GitHub these days! Let's make it easy to check the status of GitHub from the command line. + +Just run this command: + +```shell +atmos github status +``` + +- `atmos github stargazers cloudposse/atmos` +- `atmos weather --location LAX` diff --git a/examples/demo-custom-command/atmos.yaml b/examples/demo-custom-command/atmos.yaml new file mode 100644 index 000000000..9323748eb --- /dev/null +++ b/examples/demo-custom-command/atmos.yaml @@ -0,0 +1,72 @@ +base_path: "./" + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "deploy/**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +logs: + file: "/dev/stderr" + level: Info + +# Custom CLI commands + +# No arguments or flags are required +commands: +- name: hello + description: This command says Hello world + steps: + - "echo Hello world!" + +# No arguments or flags are required +- name: ip + description: Return my current IP + steps: + - curl -s https://ifconfig.me + - echo + +# Use Nested Custom Commands +- name: "github" + commands: + - name: "status" + description: This command returns the number of stargazers for a GitHub repository + steps: + - curl -s https://www.githubstatus.com/api/v2/status.json | jq -r .status.description + + # Use positional arguments + - name: "stargazers" + description: This command returns the number of stargazers for a GitHub repository + arguments: + - name: repo + description: >- + The GitHub repository to fetch the stargazers count for. + e.g. cloudposse/atmos + required: true + default: cloudposse/atmos + steps: + - curl -s https://api.github.com/repos/{{ .Arguments.repo }} | jq -r .stargazers_count + +# Use flags +- name: weather + description: This command fetches the weather + flags: + - name: location + shorthand: l + description: >- + Fetch the weather for a specific location. Works with airport codes. + Make sure to properly URL encode the location, if not using an airport code. + --location "LAX" + required: true + steps: + - curl -s https://wttr.in/{{ .Flags.location }} diff --git a/examples/demo-helmfile/.gitignore b/examples/demo-helmfile/.gitignore new file mode 100644 index 000000000..791e44afc --- /dev/null +++ b/examples/demo-helmfile/.gitignore @@ -0,0 +1 @@ +**/kubeconfig.yaml diff --git a/examples/demo-helmfile/atmos.yaml b/examples/demo-helmfile/atmos.yaml new file mode 100644 index 000000000..97dc1b202 --- /dev/null +++ b/examples/demo-helmfile/atmos.yaml @@ -0,0 +1,86 @@ +base_path: "./" + +schemas: + atmos: + manifest: "schemas/atmos-manifest.json" + +components: + helmfile: + base_path: "components/helmfile" + kubeconfig_path: "{{ .Env.KUBECONFIG }}" + helm_aws_profile_pattern: default + cluster_name_pattern: 'demo' + +stacks: + base_path: "stacks" + included_paths: + - "**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +logs: + file: "/dev/stderr" + level: Info + +# Custom CLI commands + +# No arguments or flags are required +commands: +- name: "test" + description: "Run all tests" + steps: + - atmos validate stacks + # FIXME: `atmos helmfile apply` assumes EKS + #- atmos helmfile apply demo -s dev + - atmos helmfile generate varfile demo -s dev + - helmfile -f components/helmfile/nginx/helmfile.yaml apply --values dev-demo.helmfile.vars.yaml + +# Use Nested Custom Commands to provide easier interface for Docker Compose +- name: "k3s" + commands: + - name: "up" + description: Start k3s in the background + steps: + - | + container_running=$(docker ps -q -f "name=k3s") + if [ -n "$container_running" ]; then + echo "k3s is already running; run \`atmos k3s down\` to stop it" + else + docker compose up -d --wait + fi + + - name: "down" + description: Stop k3s + steps: + - docker compose down + + - name: "restart" + description: Restart k3s + steps: + - docker compose restart + + - name: "reset" + description: Reset k3s (delete all data) + steps: + - docker compose down --volumes + + - name: "status" + description: Show the status of k3s + steps: + - | + container_running=$(docker ps -q -f "name=k3s") + if [ -n "$container_running" ]; then + docker compose ps --format "{{`{{.Service}} is {{.State}}`}}" + else + echo "k3s is not running; run \`atmos k3s up\` to start it" + fi + +- name: "terraform" + commands: + - name: "reset" + description: Delete all local state files + steps: + - find . -type f -name "*.tfstate" -delete + - echo "Deleted all state files" + diff --git a/examples/demo-helmfile/components/helmfile/nginx/helmfile.yaml b/examples/demo-helmfile/components/helmfile/nginx/helmfile.yaml new file mode 100644 index 000000000..5e8fb3166 --- /dev/null +++ b/examples/demo-helmfile/components/helmfile/nginx/helmfile.yaml @@ -0,0 +1,32 @@ +repositories: + - name: bitnami + url: https://charts.bitnami.com/bitnami + +releases: + - name: nginx + namespace: default + chart: bitnami/nginx + force: true + hooks: + - events: ["presync"] + command: "kubectl" + args: ["apply", "-f", "manifests/"] + - events: ["postuninstall"] + command: "kubectl" + args: ["delete", "-f", "manifests/"] + - events: ["postsync"] + command: "bash" + showlogs: true + args: ["-c", 'echo -n "Success! We have taken over fbi.com ;)"'] + transformers: + - apiVersion: builtin + kind: AnnotationsTransformer + metadata: + name: notImportantHere + annotations: + redeploy: '{{ now }}' + fieldSpecs: + - path: spec/template/metadata/annotations + create: true + values: + diff --git a/examples/demo-helmfile/components/helmfile/nginx/manifests/configmap.yaml b/examples/demo-helmfile/components/helmfile/nginx/manifests/configmap.yaml new file mode 100644 index 000000000..ff77d9d36 --- /dev/null +++ b/examples/demo-helmfile/components/helmfile/nginx/manifests/configmap.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: custom-html +data: + index.html: | + + + + + + Rickroll + + + +

Brought to you by Atmos

+ + + diff --git a/examples/demo-helmfile/docker-compose.yml b/examples/demo-helmfile/docker-compose.yml new file mode 100644 index 000000000..c709a8903 --- /dev/null +++ b/examples/demo-helmfile/docker-compose.yml @@ -0,0 +1,62 @@ +# to run define K3S_TOKEN, K3S_VERSION is optional, eg: +# K3S_TOKEN=${RANDOM}${RANDOM}${RANDOM} docker-compose up + +x-environment: &default-env + K3S_TOKEN: ${K3S_TOKEN:-test} + +services: + server: + image: "rancher/k3s:${K3S_VERSION:-latest}" + command: + - 'server' + tmpfs: + - /run + - /var/run + ulimits: + nproc: 65535 + nofile: + soft: 65535 + hard: 65535 + privileged: true + restart: always + environment: + <<: *default-env + K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml + K3S_KUBECONFIG_MODE: 666 + volumes: + - k3s-server:/var/lib/rancher/k3s + # Output is where the `kubeconfig.yaml` file will be written + - .:/output + ports: + - 6443:6443 # Kubernetes API Server + - 80:80 # Ingress controller port 80, localhost:8000 + - 443:443 # Ingress controller port 443, localhost:8443 + networks: + - k3s + + agent: + image: "rancher/k3s:${K3S_VERSION:-latest}" + tmpfs: + - /run + - /var/run + ulimits: + nproc: 65535 + nofile: + soft: 65535 + hard: 65535 + privileged: true + restart: always + environment: + <<: *default-env + K3S_URL: https://server:6443 + volumes: + - k3s-agent:/var/lib/rancher/k3s + networks: + - k3s +volumes: + k3s-server: {} + k3s-agent: {} + +networks: + k3s: + driver: bridge diff --git a/examples/demo-helmfile/schemas/atmos-manifest.json b/examples/demo-helmfile/schemas/atmos-manifest.json new file mode 100644 index 000000000..012ad9559 --- /dev/null +++ b/examples/demo-helmfile/schemas/atmos-manifest.json @@ -0,0 +1,822 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json.schemastore.org/atmos-manifest.json", + "title": "JSON Schema for Atmos Stack Manifest files. Version 1.0. https://atmos.tools", + "type": "object", + "properties": { + "import": { + "$ref": "#/definitions/import" + }, + "terraform": { + "$ref": "#/definitions/terraform" + }, + "helmfile": { + "$ref": "#/definitions/helmfile" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "components": { + "$ref": "#/definitions/components" + }, + "overrides": { + "$ref": "#/definitions/overrides" + }, + "workflows": { + "$ref": "#/definitions/workflows" + } + }, + "additionalProperties": true, + "oneOf": [ + { + "required": [ + "workflows" + ] + }, + { + "anyOf": [ + { + "additionalProperties": true, + "not": { + "required": [ + "workflows" + ] + } + }, + { + "required": [ + "import" + ] + }, + { + "required": [ + "terraform" + ] + }, + { + "required": [ + "helmfile" + ] + }, + { + "required": [ + "vars" + ] + }, + { + "required": [ + "env" + ] + }, + { + "required": [ + "settings" + ] + }, + { + "required": [ + "components" + ] + }, + { + "required": [ + "overrides" + ] + } + ] + } + ], + "definitions": { + "import": { + "type": "array", + "description": "Import section", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "path": { + "type": "string" + }, + "skip_templates_processing": { + "type": "boolean" + }, + "ignore_missing_template_values": { + "type": "boolean" + }, + "skip_if_missing": { + "type": "boolean" + }, + "context": { + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "path" + ] + } + ] + } + }, + "components": { + "type": "object", + "description": "Components section", + "additionalProperties": false, + "properties": { + "terraform": { + "$ref": "#/definitions/terraform_components" + }, + "helmfile": { + "$ref": "#/definitions/helmfile_components" + } + }, + "required": [], + "title": "components" + }, + "terraform": { + "type": "object", + "description": "Terraform section", + "additionalProperties": false, + "properties": { + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "backend_type": { + "$ref": "#/definitions/backend_type" + }, + "backend": { + "$ref": "#/definitions/backend" + }, + "remote_state_backend_type": { + "$ref": "#/definitions/remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/remote_state_backend" + }, + "overrides": { + "$ref": "#/definitions/overrides" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "terraform" + }, + "terraform_components": { + "type": "object", + "description": "Terraform components section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/terraform_component_manifest" + } + }, + "additionalProperties": false, + "title": "terraform_components" + }, + "terraform_component_manifest": { + "type": "object", + "description": "Terraform component manifest", + "additionalProperties": false, + "properties": { + "metadata": { + "$ref": "#/definitions/metadata" + }, + "component": { + "$ref": "#/definitions/component" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "backend_type": { + "$ref": "#/definitions/backend_type" + }, + "backend": { + "$ref": "#/definitions/backend" + }, + "remote_state_backend_type": { + "$ref": "#/definitions/remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/remote_state_backend" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "terraform_component_manifest" + }, + "helmfile": { + "type": "object", + "description": "Helmfile section", + "additionalProperties": false, + "properties": { + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "overrides": { + "$ref": "#/definitions/overrides" + } + }, + "required": [], + "title": "helmfile" + }, + "helmfile_components": { + "type": "object", + "description": "Helmfile components section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/helmfile_component_manifest" + } + }, + "additionalProperties": false, + "title": "helmfile_components" + }, + "helmfile_component_manifest": { + "type": "object", + "description": "Helmfile component manifest", + "additionalProperties": false, + "properties": { + "metadata": { + "$ref": "#/definitions/metadata" + }, + "component": { + "$ref": "#/definitions/component" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + } + }, + "required": [], + "title": "helmfile_component_manifest" + }, + "command": { + "type": "string", + "description": "Command to execute", + "title": "command" + }, + "component": { + "type": "string", + "description": "Component section", + "title": "component" + }, + "metadata": { + "type": "object", + "description": "Metadata section", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "abstract", + "real" + ] + }, + "component": { + "type": "string" + }, + "inherits": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "terraform_workspace": { + "type": "string" + }, + "terraform_workspace_pattern": { + "type": "string" + }, + "custom": { + "type": "object", + "description": "Custom configuration per component, not inherited by derived components", + "additionalProperties": true, + "title": "custom" + } + }, + "required": [], + "title": "metadata" + }, + "settings": { + "type": "object", + "description": "Settings section", + "additionalProperties": true, + "properties": { + "validation": { + "$ref": "#/definitions/validation" + }, + "depends_on": { + "$ref": "#/definitions/depends_on" + }, + "spacelift": { + "$ref": "#/definitions/spacelift" + }, + "atlantis": { + "$ref": "#/definitions/atlantis" + }, + "templates": { + "$ref": "#/definitions/templates" + } + }, + "required": [], + "title": "settings" + }, + "validation": { + "type": "object", + "description": "Validation section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/validation_manifest" + } + }, + "additionalProperties": false, + "title": "validation" + }, + "validation_manifest": { + "type": "object", + "description": "Validation manifest", + "properties": { + "schema_type": { + "type": "string", + "enum": [ + "jsonschema", + "opa" + ] + }, + "schema_path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "disabled": { + "type": "boolean" + }, + "timeout": { + "type": "integer", + "minimum": 0 + }, + "module_paths": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + }, + "description": "List of paths to validation modules" + } + }, + "additionalProperties": false, + "required": [ + "schema_type", + "schema_path" + ], + "title": "validation_manifest" + }, + "vars": { + "type": "object", + "description": "Vars section", + "additionalProperties": true, + "title": "vars" + }, + "env": { + "type": "object", + "description": "Env section", + "additionalProperties": true, + "required": [], + "title": "env" + }, + "backend_type": { + "type": "string", + "enum": [ + "local", + "s3", + "remote", + "vault", + "static", + "azurerm", + "gcs", + "cloud" + ], + "description": "Backend type", + "title": "backend_type" + }, + "backend": { + "$ref": "#/definitions/backend_manifest", + "title": "backend" + }, + "remote_state_backend_type": { + "type": "string", + "enum": [ + "local", + "s3", + "remote", + "vault", + "static", + "azurerm", + "gcs", + "cloud" + ], + "description": "Remote state backend type", + "title": "remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/backend_manifest", + "title": "remote_state_backend" + }, + "backend_manifest": { + "type": "object", + "description": "Backend manifest", + "additionalProperties": false, + "properties": { + "s3": { + "type": "object", + "additionalProperties": false, + "properties": { + "encrypt": { + "type": "boolean" + }, + "bucket": { + "type": "string" + }, + "key": { + "type": "string" + }, + "dynamodb_table": { + "type": "string" + }, + "acl": { + "type": "string" + }, + "region": { + "type": "string" + }, + "assume_role": { + "type": "object", + "additionalProperties": false, + "properties": { + "role_arn": { + "type": [ + "string", + "null" + ] + }, + "duration": { + "type": [ + "string", + "null" + ] + }, + "external_id": { + "type": [ + "string", + "null" + ] + }, + "policy": { + "type": [ + "string", + "null" + ] + }, + "policy_arns": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "session_name": { + "type": [ + "string", + "null" + ] + }, + "source_identity": { + "type": [ + "string", + "null" + ] + }, + "tags": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, + "transitive_tag_keys": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + } + } + }, + "role_arn": { + "type": [ + "string", + "null" + ] + }, + "profile": { + "type": [ + "string", + "null" + ] + }, + "workspace_key_prefix": { + "type": "string" + } + } + }, + "remote": { + "type": "object", + "additionalProperties": true + }, + "vault": { + "type": "object", + "additionalProperties": true + }, + "static": { + "type": "object", + "additionalProperties": true + }, + "azurerm": { + "type": "object", + "additionalProperties": true + }, + "gcs": { + "type": "object", + "additionalProperties": true + }, + "cloud": { + "type": "object", + "additionalProperties": true + } + }, + "required": [], + "title": "backend" + }, + "overrides": { + "type": "object", + "description": "Overrides section", + "additionalProperties": false, + "properties": { + "command": { + "$ref": "#/definitions/command" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "overrides" + }, + "depends_on": { + "type": "object", + "description": "Depends_on section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/depends_on_manifest" + } + }, + "additionalProperties": false, + "title": "depends_on" + }, + "depends_on_manifest": { + "type": "object", + "description": "Depends_on manifest", + "properties": { + "namespace": { + "type": "string" + }, + "tenant": { + "type": "string" + }, + "environment": { + "type": "string" + }, + "stage": { + "type": "string" + }, + "component": { + "type": "string" + }, + "file": { + "type": "string" + }, + "folder": { + "type": "string" + } + }, + "oneOf": [ + { + "required": [ + "component" + ] + }, + { + "required": [ + "file" + ] + }, + { + "required": [ + "folder" + ] + } + ], + "additionalProperties": false, + "title": "depends_on_manifest" + }, + "spacelift": { + "type": "object", + "description": "Spacelift section", + "additionalProperties": true, + "properties": { + "workspace_enabled": { + "type": "boolean" + }, + "stack_destructor_enabled": { + "type": "boolean" + }, + "protect_from_deletion": { + "type": "boolean" + }, + "autodeploy": { + "type": "boolean" + }, + "terraform_version": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + } + }, + "required": [], + "title": "spacelift" + }, + "atlantis": { + "type": "object", + "description": "Atlantis section", + "additionalProperties": false, + "properties": { + "config_template_name": { + "type": "string" + }, + "config_template": { + "type": "object", + "additionalProperties": true + }, + "project_template_name": { + "type": "string" + }, + "project_template": { + "type": "object", + "additionalProperties": true + }, + "workflow_templates": { + "type": "object", + "additionalProperties": true + } + }, + "required": [], + "title": "atlantis" + }, + "workflows": { + "type": "object", + "description": "Workflows section", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/workflow_manifest" + } + }, + "additionalProperties": false, + "title": "workflows" + }, + "workflow_manifest": { + "type": "object", + "description": "Atmos workflow manifest", + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "steps": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "command": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "command" + ] + } + } + }, + "required": [ + "steps" + ], + "title": "workflow_manifest" + }, + "providers": { + "type": "object", + "description": "Providers section", + "additionalProperties": true, + "title": "providers" + }, + "templates": { + "type": "object", + "description": "Templates section", + "additionalProperties": true, + "title": "templates" + } + } +} diff --git a/examples/demo-helmfile/stacks/catalog/demo.yaml b/examples/demo-helmfile/stacks/catalog/demo.yaml new file mode 100644 index 000000000..5e6b8c03a --- /dev/null +++ b/examples/demo-helmfile/stacks/catalog/demo.yaml @@ -0,0 +1,40 @@ +components: + helmfile: + demo: + metadata: + type: abstract + component: nginx + vars: + image: + tag: "latest" + service: + type: ClusterIP + port: 80 + replicaCount: 1 + ingress: + enabled: true + hostname: fbi.com + paths: + - / + extraHosts: + - name: '*.app.github.dev' + path: / + - name: 'localhost' + path: / + readinessProbe: + initialDelaySeconds: 1 + periodSeconds: 2 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + persistence: + enabled: false + extraVolumes: + - name: custom-html + configMap: + name: custom-html + extraVolumeMounts: + - name: custom-html + mountPath: /app/index.html + subPath: index.html + readOnly: true diff --git a/examples/demo-helmfile/stacks/deploy/dev/demo.yaml b/examples/demo-helmfile/stacks/deploy/dev/demo.yaml new file mode 100644 index 000000000..7e185ee39 --- /dev/null +++ b/examples/demo-helmfile/stacks/deploy/dev/demo.yaml @@ -0,0 +1,12 @@ +import: +- mixins/k3s +- catalog/demo + +vars: + stage: dev + +components: + helmfile: + demo: + metadata: + type: real diff --git a/examples/demo-helmfile/stacks/deploy/prod/demo.yaml b/examples/demo-helmfile/stacks/deploy/prod/demo.yaml new file mode 100644 index 000000000..3bff77241 --- /dev/null +++ b/examples/demo-helmfile/stacks/deploy/prod/demo.yaml @@ -0,0 +1,12 @@ +import: +- mixins/k3s +- catalog/demo + +vars: + stage: prod + +components: + helmfile: + demo: + metadata: + type: real diff --git a/examples/demo-helmfile/stacks/deploy/staging/demo.yaml b/examples/demo-helmfile/stacks/deploy/staging/demo.yaml new file mode 100644 index 000000000..ea75d03a8 --- /dev/null +++ b/examples/demo-helmfile/stacks/deploy/staging/demo.yaml @@ -0,0 +1,12 @@ +import: +- mixins/k3s +- catalog/demo + +vars: + stage: staging + +components: + helmfile: + demo: + metadata: + type: real diff --git a/examples/demo-helmfile/stacks/mixins/k3s.yaml b/examples/demo-helmfile/stacks/mixins/k3s.yaml new file mode 100644 index 000000000..d0499d7dc --- /dev/null +++ b/examples/demo-helmfile/stacks/mixins/k3s.yaml @@ -0,0 +1,4 @@ +env: + # Configure `kubectl` to use the `kubeconfig.yaml` file generated by the K3s server + KUBECONFIG: "./kubeconfig.yaml" + diff --git a/examples/demo-library/README.md b/examples/demo-library/README.md new file mode 100644 index 000000000..6bb569e01 --- /dev/null +++ b/examples/demo-library/README.md @@ -0,0 +1,30 @@ +# Demo Components + +Here are some examples of distributing reusable components as part of a library. + +Typically, a component library will be a separate repository containing only components with a monorepo design. + +## Examples + +These examples are somewhat contrived and selected mainly because they use remote APIs that do not require authentication. + +> ![TIP] +> These examples are more representative of proper child modules rather than "root modules". +> Remember, root modules are stateful pieces of your architecture, meaning they are Terraform root modules with a state backend. +> Typical root modules include networks, clusters, databases, caches, object stores, load balancers, and so on. +> For a real-world example of the components we use in Cloud Posse’s AWS Reference Architecture, please see [`cloudposse/terraform-aws-components](https://github.com/cloudposse/terraform-aws-components). + + +### GitHub + +The [`github/*`](github/) example components use the `http_provider` to anonymously query the GitHub API for information. + +### Weather + +The [`weather`](weather/) example component requests weather data from `wttr.in` based on the location provided. + +### IP Info + +The [`ipinfo`](ipinfo/) example component returns information about your current IP. + + diff --git a/examples/demo-library/github/stargazers/README.md b/examples/demo-library/github/stargazers/README.md new file mode 100644 index 000000000..ef3b13ab6 --- /dev/null +++ b/examples/demo-library/github/stargazers/README.md @@ -0,0 +1,13 @@ +# Example Terraform GitHub Stargazers Component + +This Terraform module retrieves the number of stargazers for a specified GitHub repository. + +## Usage + +### Inputs + +- `repository`: The GitHub repository in the format 'owner/repo'. + +### Outputs + +- `stargazers_count`: The number of stargazers for the specified GitHub repository. diff --git a/examples/demo-library/github/stargazers/main.tf b/examples/demo-library/github/stargazers/main.tf new file mode 100644 index 000000000..bbaef9513 --- /dev/null +++ b/examples/demo-library/github/stargazers/main.tf @@ -0,0 +1,3 @@ +data "github_repository" "repo" { + full_name = var.repository +} diff --git a/examples/demo-library/github/stargazers/outputs.tf b/examples/demo-library/github/stargazers/outputs.tf new file mode 100644 index 000000000..5f3cbbff2 --- /dev/null +++ b/examples/demo-library/github/stargazers/outputs.tf @@ -0,0 +1,4 @@ +output "stargazers_count" { + description = "The number of stargazers for the specified GitHub repository" + value = data.github_repository.repo.stargazers_count +} diff --git a/examples/demo-library/github/stargazers/providers.tf b/examples/demo-library/github/stargazers/providers.tf new file mode 100644 index 000000000..d08ff256a --- /dev/null +++ b/examples/demo-library/github/stargazers/providers.tf @@ -0,0 +1,3 @@ +provider "github" { + # No token is needed for accessing public repository data +} diff --git a/examples/demo-library/github/stargazers/variables.tf b/examples/demo-library/github/stargazers/variables.tf new file mode 100644 index 000000000..5fbe9ff26 --- /dev/null +++ b/examples/demo-library/github/stargazers/variables.tf @@ -0,0 +1,4 @@ +variable "repository" { + description = "The GitHub repository in the format 'owner/repo'" + type = string +} diff --git a/examples/demo-library/github/stargazers/versions.tf b/examples/demo-library/github/stargazers/versions.tf new file mode 100644 index 000000000..e2a3d732d --- /dev/null +++ b/examples/demo-library/github/stargazers/versions.tf @@ -0,0 +1,5 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers {} +} diff --git a/examples/demo-library/ipinfo/README.md b/examples/demo-library/ipinfo/README.md new file mode 100644 index 000000000..a1b28ebfd --- /dev/null +++ b/examples/demo-library/ipinfo/README.md @@ -0,0 +1,13 @@ +# Example Terraform IPinfo Component + +This Terraform module retrieves data from the IPinfo API for a specified IP address. If no IP address is specified, it retrieves data for the requester's IP address. + +## Usage + +### Inputs + +- `ip_address` (optional): The IP address to retrieve information for. If not specified, the requester's IP address will be used. The default value is an empty string. + +### Outputs + +- `metadata`: The data retrieved from IPinfo for the specified IP address, in JSON format. diff --git a/examples/demo-library/ipinfo/main.tf b/examples/demo-library/ipinfo/main.tf new file mode 100644 index 000000000..0e3e9d0b0 --- /dev/null +++ b/examples/demo-library/ipinfo/main.tf @@ -0,0 +1,7 @@ +data "http" "ipinfo" { + url = var.ip_address != "" ? "https://ipinfo.io/${var.ip_address}" : "https://ipinfo.io" + + request_headers = { + Accept = "application/json" + } +} diff --git a/examples/demo-library/ipinfo/outputs.tf b/examples/demo-library/ipinfo/outputs.tf new file mode 100644 index 000000000..12bb2bb8d --- /dev/null +++ b/examples/demo-library/ipinfo/outputs.tf @@ -0,0 +1,4 @@ +output "metadata" { + description = "The data retrieved from IPinfo for the specified IP address" + value = jsondecode(data.http.ipinfo.response_body) +} diff --git a/examples/demo-library/ipinfo/providers.tf b/examples/demo-library/ipinfo/providers.tf new file mode 100644 index 000000000..0b91fe2aa --- /dev/null +++ b/examples/demo-library/ipinfo/providers.tf @@ -0,0 +1 @@ +provider "http" {} diff --git a/examples/demo-library/ipinfo/variables.tf b/examples/demo-library/ipinfo/variables.tf new file mode 100644 index 000000000..85f32544d --- /dev/null +++ b/examples/demo-library/ipinfo/variables.tf @@ -0,0 +1,5 @@ +variable "ip_address" { + description = "The IP address to retrieve information for (optional)" + type = string + default = "" +} diff --git a/examples/demo-library/ipinfo/versions.tf b/examples/demo-library/ipinfo/versions.tf new file mode 100644 index 000000000..e2a3d732d --- /dev/null +++ b/examples/demo-library/ipinfo/versions.tf @@ -0,0 +1,5 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers {} +} diff --git a/examples/demo-library/weather/README.md b/examples/demo-library/weather/README.md new file mode 100644 index 000000000..1d7a7ee03 --- /dev/null +++ b/examples/demo-library/weather/README.md @@ -0,0 +1,50 @@ +# Example Terraform Weather Component + +This Terraform "root" module fetches weather information for a specified location with custom display options. +It queries data from the [`wttr.in`](https://wttr.in) weather service and stores the result in a local file (`cache.txt`). +It also provides several outputs like weather information, request URL, stage, location, language, and units of measurement. + +## Features + +- Fetch weather updates for a location using HTTP request. +- Write the obtained weather data in a local file. +- Customizable display options. +- View the request URL. +- Get informed about the stage, location, language, and units in the metadata. + +## Usage + +To include this module in your [Atmos Stacks](https://atmos.tools/core-concepts/stacks) configuration: + +```yaml +components: + terraform: + weather: + vars: + stage: dev + location: New York + options: 0T + format: v2 + lang: en + units: m +``` + +### Inputs +- `stage`: Stage where it will be deployed. +- `location`: Location for which the weather is reported. Default is "Los Angeles". +- `options`: Options to customize the output. Default is "0T". +- `format`: Specifies the output format. Default is "v2". +- `lang`: Language in which the weather will be displayed. Default is "en". +- `units`: Units in which the weather will be displayed. Default is "m". + +### Outputs +- `weather`: The fetched weather data. +- `url`: Requested URL. +- `stage`: Stage of deployment. +- `location`: Location of the reported weather. +- `lang`: Language used for weather data. +- `units`: Units of measurement for the weather data. + +Please note, this module requires Terraform version >=1.0.0, and you need to specify no other required providers. + +Happy Weather Tracking! diff --git a/examples/demo-library/weather/main.tf b/examples/demo-library/weather/main.tf new file mode 100644 index 000000000..9971bf5b0 --- /dev/null +++ b/examples/demo-library/weather/main.tf @@ -0,0 +1,22 @@ +locals { + url = format("https://wttr.in/%v?%v&format=%v&lang=%v&u=%v", + urlencode(var.location), + urlencode(var.options), + urlencode(var.format), + urlencode(var.lang), + urlencode(var.units), + ) +} + +data "http" "weather" { + url = local.url + request_headers = { + User-Agent = "curl" + } +} + +# Now write this to a file (as an example of a resource) +resource "local_file" "cache" { + filename = "cache.${var.stage}.txt" + content = data.http.weather.response_body +} diff --git a/examples/demo-library/weather/outputs.tf b/examples/demo-library/weather/outputs.tf new file mode 100644 index 000000000..f0e7fd442 --- /dev/null +++ b/examples/demo-library/weather/outputs.tf @@ -0,0 +1,27 @@ +output "weather" { + value = data.http.weather.response_body +} + +output "url" { + value = local.url +} + +output "stage" { + value = var.stage + description = "Stage where it was deployed" +} + +output "location" { + value = var.location + description = "Location of the weather report." +} + +output "lang" { + value = var.lang + description = "Language which the weather is displayed." +} + +output "units" { + value = var.units + description = "Units the weather is displayed." +} diff --git a/examples/demo-library/weather/providers.tf b/examples/demo-library/weather/providers.tf new file mode 100644 index 000000000..0b91fe2aa --- /dev/null +++ b/examples/demo-library/weather/providers.tf @@ -0,0 +1 @@ +provider "http" {} diff --git a/examples/demo-library/weather/variables.tf b/examples/demo-library/weather/variables.tf new file mode 100644 index 000000000..c8a32310a --- /dev/null +++ b/examples/demo-library/weather/variables.tf @@ -0,0 +1,34 @@ +variable "stage" { + description = "Stage where it will be deployed" + type = string +} + +variable "location" { + description = "Location for which the weather." + type = string + default = "Los Angeles" +} + +variable "options" { + description = "Options to customize the output." + type = string + default = "0T" +} + +variable "format" { + description = "Format of the output." + type = string + default = "v2" +} + +variable "lang" { + description = "Language in which the weather is displayed." + type = string + default = "en" +} + +variable "units" { + description = "Units in which the weather is displayed." + type = string + default = "m" +} diff --git a/examples/demo-library/weather/versions.tf b/examples/demo-library/weather/versions.tf new file mode 100644 index 000000000..e2a3d732d --- /dev/null +++ b/examples/demo-library/weather/versions.tf @@ -0,0 +1,5 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers {} +} diff --git a/examples/demo-localstack/.gitignore b/examples/demo-localstack/.gitignore new file mode 100644 index 000000000..bc2b4336e --- /dev/null +++ b/examples/demo-localstack/.gitignore @@ -0,0 +1,13 @@ +**/.terraform/** +**/.terraform.lock.hcl +**/.terraform.tfstate/** +**/.terraform.tfstate.backup/** +**/*.tfvars.json +**/*.planfile +**/terraform.tfstate +**/terraform.tfstate.backup +**/terraform.tfstate.d/** +**/cache.*.txt +**/*.tf.json +volume/** + diff --git a/examples/demo-localstack/README.md b/examples/demo-localstack/README.md new file mode 100644 index 000000000..b3cccd2df --- /dev/null +++ b/examples/demo-localstack/README.md @@ -0,0 +1,16 @@ + +## Notes + +When running Terraform with LocalStack, if you get the following warning from Terraform, you should not enable `skip_requesting_account_id`. Older versions of LocalStack required this, but not anymore. + +```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. +``` diff --git a/examples/demo-localstack/atmos.yaml b/examples/demo-localstack/atmos.yaml new file mode 100644 index 000000000..d63a92c36 --- /dev/null +++ b/examples/demo-localstack/atmos.yaml @@ -0,0 +1,97 @@ +base_path: "./" + +schemas: + atmos: + manifest: "schemas/atmos-manifest.json" + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +logs: + file: "/dev/stderr" + level: Info + +# Custom CLI commands + +# No arguments or flags are required +commands: +- name: "test" + description: "Run all tests" + steps: + - atmos validate stacks + # Test dev stack + - atmos terraform plan demo -s dev + - atmos terraform apply demo -s dev -auto-approve + - atmos terraform destroy demo -s dev -auto-approve + # Test staging stack + - atmos terraform plan demo -s staging + - atmos terraform apply demo -s staging -auto-approve + - atmos terraform destroy demo -s staging -auto-approve + # Test prod stack + - atmos terraform plan demo -s prod + - atmos terraform apply demo -s prod -auto-approve + - atmos terraform destroy demo -s prod -auto-approve + +# Use Nested Custom Commands to provide easier interface for Docker Compose +- name: "localstack" + commands: + - name: "up" + description: Start lockstack in the background + steps: + - | + container_running=$(docker ps -q -f "name=localstack") + if [ -n "$container_running" ]; then + echo "LocalStack is already running; run \`atmos localstack down\` to stop it" + else + docker compose up -d --wait + fi + + - name: "down" + description: Stop localstack + steps: + - docker compose down + + - name: "restart" + description: Restart localstack + steps: + - docker compose restart + + - name: "reset" + description: Reset localstack (delete all data) + steps: + - docker compose down + - rm -rf volume/ + - docker compose up -d + + - name: "status" + description: Show the status of LocalStack + steps: + - | + container_running=$(docker ps -q -f "name=localstack") + 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" + fi + +- name: "terraform" + commands: + - name: "reset" + description: Delete all local state files + steps: + - find . -type f -name "*.tfstate" -delete + - echo "Deleted all state files" + diff --git a/examples/demo-localstack/components/terraform/bucket/main.tf b/examples/demo-localstack/components/terraform/bucket/main.tf new file mode 100644 index 000000000..77d23d5a4 --- /dev/null +++ b/examples/demo-localstack/components/terraform/bucket/main.tf @@ -0,0 +1,3 @@ +resource "aws_s3_bucket" "bucket" { + bucket = "demo-${var.stage}" +} diff --git a/examples/demo-localstack/components/terraform/bucket/outputs.tf b/examples/demo-localstack/components/terraform/bucket/outputs.tf new file mode 100644 index 000000000..bc3f6860f --- /dev/null +++ b/examples/demo-localstack/components/terraform/bucket/outputs.tf @@ -0,0 +1,4 @@ +output "stage" { + description = "Stage of deployment" + value = var.stage +} diff --git a/examples/demo-localstack/components/terraform/bucket/providers.tf b/examples/demo-localstack/components/terraform/bucket/providers.tf new file mode 100644 index 000000000..8c9ebd175 --- /dev/null +++ b/examples/demo-localstack/components/terraform/bucket/providers.tf @@ -0,0 +1,2 @@ +provider "aws" { +} diff --git a/examples/demo-localstack/components/terraform/bucket/variables.tf b/examples/demo-localstack/components/terraform/bucket/variables.tf new file mode 100644 index 000000000..e5b6d81a1 --- /dev/null +++ b/examples/demo-localstack/components/terraform/bucket/variables.tf @@ -0,0 +1,3 @@ +variable "stage" { + description = "The stage of the environment (e.g. dev, staging, prod)" +} diff --git a/examples/demo-localstack/docker-compose.yml b/examples/demo-localstack/docker-compose.yml new file mode 100644 index 000000000..8829b87b6 --- /dev/null +++ b/examples/demo-localstack/docker-compose.yml @@ -0,0 +1,22 @@ +services: + localstack: + container_name: localstack + image: localstack/localstack:1.4.0 + ports: + - "0.0.0.0:4566:4566" # LocalStack Gateway + - "0.0.0.0:4510-4559:4510-4559" # external services port range + networks: + - localstack + environment: + - 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" + volumes: + - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" + - "/var/run/docker.sock:/var/run/docker.sock" + +networks: + localstack: + driver: bridge diff --git a/examples/demo-localstack/schemas/atmos-manifest.json b/examples/demo-localstack/schemas/atmos-manifest.json new file mode 100644 index 000000000..012ad9559 --- /dev/null +++ b/examples/demo-localstack/schemas/atmos-manifest.json @@ -0,0 +1,822 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json.schemastore.org/atmos-manifest.json", + "title": "JSON Schema for Atmos Stack Manifest files. Version 1.0. https://atmos.tools", + "type": "object", + "properties": { + "import": { + "$ref": "#/definitions/import" + }, + "terraform": { + "$ref": "#/definitions/terraform" + }, + "helmfile": { + "$ref": "#/definitions/helmfile" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "components": { + "$ref": "#/definitions/components" + }, + "overrides": { + "$ref": "#/definitions/overrides" + }, + "workflows": { + "$ref": "#/definitions/workflows" + } + }, + "additionalProperties": true, + "oneOf": [ + { + "required": [ + "workflows" + ] + }, + { + "anyOf": [ + { + "additionalProperties": true, + "not": { + "required": [ + "workflows" + ] + } + }, + { + "required": [ + "import" + ] + }, + { + "required": [ + "terraform" + ] + }, + { + "required": [ + "helmfile" + ] + }, + { + "required": [ + "vars" + ] + }, + { + "required": [ + "env" + ] + }, + { + "required": [ + "settings" + ] + }, + { + "required": [ + "components" + ] + }, + { + "required": [ + "overrides" + ] + } + ] + } + ], + "definitions": { + "import": { + "type": "array", + "description": "Import section", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "path": { + "type": "string" + }, + "skip_templates_processing": { + "type": "boolean" + }, + "ignore_missing_template_values": { + "type": "boolean" + }, + "skip_if_missing": { + "type": "boolean" + }, + "context": { + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "path" + ] + } + ] + } + }, + "components": { + "type": "object", + "description": "Components section", + "additionalProperties": false, + "properties": { + "terraform": { + "$ref": "#/definitions/terraform_components" + }, + "helmfile": { + "$ref": "#/definitions/helmfile_components" + } + }, + "required": [], + "title": "components" + }, + "terraform": { + "type": "object", + "description": "Terraform section", + "additionalProperties": false, + "properties": { + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "backend_type": { + "$ref": "#/definitions/backend_type" + }, + "backend": { + "$ref": "#/definitions/backend" + }, + "remote_state_backend_type": { + "$ref": "#/definitions/remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/remote_state_backend" + }, + "overrides": { + "$ref": "#/definitions/overrides" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "terraform" + }, + "terraform_components": { + "type": "object", + "description": "Terraform components section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/terraform_component_manifest" + } + }, + "additionalProperties": false, + "title": "terraform_components" + }, + "terraform_component_manifest": { + "type": "object", + "description": "Terraform component manifest", + "additionalProperties": false, + "properties": { + "metadata": { + "$ref": "#/definitions/metadata" + }, + "component": { + "$ref": "#/definitions/component" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "backend_type": { + "$ref": "#/definitions/backend_type" + }, + "backend": { + "$ref": "#/definitions/backend" + }, + "remote_state_backend_type": { + "$ref": "#/definitions/remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/remote_state_backend" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "terraform_component_manifest" + }, + "helmfile": { + "type": "object", + "description": "Helmfile section", + "additionalProperties": false, + "properties": { + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "overrides": { + "$ref": "#/definitions/overrides" + } + }, + "required": [], + "title": "helmfile" + }, + "helmfile_components": { + "type": "object", + "description": "Helmfile components section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/helmfile_component_manifest" + } + }, + "additionalProperties": false, + "title": "helmfile_components" + }, + "helmfile_component_manifest": { + "type": "object", + "description": "Helmfile component manifest", + "additionalProperties": false, + "properties": { + "metadata": { + "$ref": "#/definitions/metadata" + }, + "component": { + "$ref": "#/definitions/component" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + } + }, + "required": [], + "title": "helmfile_component_manifest" + }, + "command": { + "type": "string", + "description": "Command to execute", + "title": "command" + }, + "component": { + "type": "string", + "description": "Component section", + "title": "component" + }, + "metadata": { + "type": "object", + "description": "Metadata section", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "abstract", + "real" + ] + }, + "component": { + "type": "string" + }, + "inherits": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "terraform_workspace": { + "type": "string" + }, + "terraform_workspace_pattern": { + "type": "string" + }, + "custom": { + "type": "object", + "description": "Custom configuration per component, not inherited by derived components", + "additionalProperties": true, + "title": "custom" + } + }, + "required": [], + "title": "metadata" + }, + "settings": { + "type": "object", + "description": "Settings section", + "additionalProperties": true, + "properties": { + "validation": { + "$ref": "#/definitions/validation" + }, + "depends_on": { + "$ref": "#/definitions/depends_on" + }, + "spacelift": { + "$ref": "#/definitions/spacelift" + }, + "atlantis": { + "$ref": "#/definitions/atlantis" + }, + "templates": { + "$ref": "#/definitions/templates" + } + }, + "required": [], + "title": "settings" + }, + "validation": { + "type": "object", + "description": "Validation section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/validation_manifest" + } + }, + "additionalProperties": false, + "title": "validation" + }, + "validation_manifest": { + "type": "object", + "description": "Validation manifest", + "properties": { + "schema_type": { + "type": "string", + "enum": [ + "jsonschema", + "opa" + ] + }, + "schema_path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "disabled": { + "type": "boolean" + }, + "timeout": { + "type": "integer", + "minimum": 0 + }, + "module_paths": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + }, + "description": "List of paths to validation modules" + } + }, + "additionalProperties": false, + "required": [ + "schema_type", + "schema_path" + ], + "title": "validation_manifest" + }, + "vars": { + "type": "object", + "description": "Vars section", + "additionalProperties": true, + "title": "vars" + }, + "env": { + "type": "object", + "description": "Env section", + "additionalProperties": true, + "required": [], + "title": "env" + }, + "backend_type": { + "type": "string", + "enum": [ + "local", + "s3", + "remote", + "vault", + "static", + "azurerm", + "gcs", + "cloud" + ], + "description": "Backend type", + "title": "backend_type" + }, + "backend": { + "$ref": "#/definitions/backend_manifest", + "title": "backend" + }, + "remote_state_backend_type": { + "type": "string", + "enum": [ + "local", + "s3", + "remote", + "vault", + "static", + "azurerm", + "gcs", + "cloud" + ], + "description": "Remote state backend type", + "title": "remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/backend_manifest", + "title": "remote_state_backend" + }, + "backend_manifest": { + "type": "object", + "description": "Backend manifest", + "additionalProperties": false, + "properties": { + "s3": { + "type": "object", + "additionalProperties": false, + "properties": { + "encrypt": { + "type": "boolean" + }, + "bucket": { + "type": "string" + }, + "key": { + "type": "string" + }, + "dynamodb_table": { + "type": "string" + }, + "acl": { + "type": "string" + }, + "region": { + "type": "string" + }, + "assume_role": { + "type": "object", + "additionalProperties": false, + "properties": { + "role_arn": { + "type": [ + "string", + "null" + ] + }, + "duration": { + "type": [ + "string", + "null" + ] + }, + "external_id": { + "type": [ + "string", + "null" + ] + }, + "policy": { + "type": [ + "string", + "null" + ] + }, + "policy_arns": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "session_name": { + "type": [ + "string", + "null" + ] + }, + "source_identity": { + "type": [ + "string", + "null" + ] + }, + "tags": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, + "transitive_tag_keys": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + } + } + }, + "role_arn": { + "type": [ + "string", + "null" + ] + }, + "profile": { + "type": [ + "string", + "null" + ] + }, + "workspace_key_prefix": { + "type": "string" + } + } + }, + "remote": { + "type": "object", + "additionalProperties": true + }, + "vault": { + "type": "object", + "additionalProperties": true + }, + "static": { + "type": "object", + "additionalProperties": true + }, + "azurerm": { + "type": "object", + "additionalProperties": true + }, + "gcs": { + "type": "object", + "additionalProperties": true + }, + "cloud": { + "type": "object", + "additionalProperties": true + } + }, + "required": [], + "title": "backend" + }, + "overrides": { + "type": "object", + "description": "Overrides section", + "additionalProperties": false, + "properties": { + "command": { + "$ref": "#/definitions/command" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "overrides" + }, + "depends_on": { + "type": "object", + "description": "Depends_on section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/depends_on_manifest" + } + }, + "additionalProperties": false, + "title": "depends_on" + }, + "depends_on_manifest": { + "type": "object", + "description": "Depends_on manifest", + "properties": { + "namespace": { + "type": "string" + }, + "tenant": { + "type": "string" + }, + "environment": { + "type": "string" + }, + "stage": { + "type": "string" + }, + "component": { + "type": "string" + }, + "file": { + "type": "string" + }, + "folder": { + "type": "string" + } + }, + "oneOf": [ + { + "required": [ + "component" + ] + }, + { + "required": [ + "file" + ] + }, + { + "required": [ + "folder" + ] + } + ], + "additionalProperties": false, + "title": "depends_on_manifest" + }, + "spacelift": { + "type": "object", + "description": "Spacelift section", + "additionalProperties": true, + "properties": { + "workspace_enabled": { + "type": "boolean" + }, + "stack_destructor_enabled": { + "type": "boolean" + }, + "protect_from_deletion": { + "type": "boolean" + }, + "autodeploy": { + "type": "boolean" + }, + "terraform_version": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + } + }, + "required": [], + "title": "spacelift" + }, + "atlantis": { + "type": "object", + "description": "Atlantis section", + "additionalProperties": false, + "properties": { + "config_template_name": { + "type": "string" + }, + "config_template": { + "type": "object", + "additionalProperties": true + }, + "project_template_name": { + "type": "string" + }, + "project_template": { + "type": "object", + "additionalProperties": true + }, + "workflow_templates": { + "type": "object", + "additionalProperties": true + } + }, + "required": [], + "title": "atlantis" + }, + "workflows": { + "type": "object", + "description": "Workflows section", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/workflow_manifest" + } + }, + "additionalProperties": false, + "title": "workflows" + }, + "workflow_manifest": { + "type": "object", + "description": "Atmos workflow manifest", + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "steps": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "command": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "command" + ] + } + } + }, + "required": [ + "steps" + ], + "title": "workflow_manifest" + }, + "providers": { + "type": "object", + "description": "Providers section", + "additionalProperties": true, + "title": "providers" + }, + "templates": { + "type": "object", + "description": "Templates section", + "additionalProperties": true, + "title": "templates" + } + } +} diff --git a/examples/demo-localstack/stacks/catalog/demo.yaml b/examples/demo-localstack/stacks/catalog/demo.yaml new file mode 100644 index 000000000..b1517071b --- /dev/null +++ b/examples/demo-localstack/stacks/catalog/demo.yaml @@ -0,0 +1,7 @@ +components: + terraform: + demo: + metadata: + type: abstract + component: bucket + vars: {} diff --git a/examples/demo-localstack/stacks/deploy/dev/demo.yaml b/examples/demo-localstack/stacks/deploy/dev/demo.yaml new file mode 100644 index 000000000..4f370497e --- /dev/null +++ b/examples/demo-localstack/stacks/deploy/dev/demo.yaml @@ -0,0 +1,12 @@ +import: +- mixins/localstack +- catalog/demo + +vars: + stage: dev + +components: + terraform: + demo: + metadata: + type: real diff --git a/examples/demo-localstack/stacks/deploy/prod/demo.yaml b/examples/demo-localstack/stacks/deploy/prod/demo.yaml new file mode 100644 index 000000000..ff1c9203a --- /dev/null +++ b/examples/demo-localstack/stacks/deploy/prod/demo.yaml @@ -0,0 +1,12 @@ +import: +- mixins/localstack +- catalog/demo + +vars: + stage: prod + +components: + terraform: + demo: + metadata: + type: real diff --git a/examples/demo-localstack/stacks/deploy/staging/demo.yaml b/examples/demo-localstack/stacks/deploy/staging/demo.yaml new file mode 100644 index 000000000..306cf0b3e --- /dev/null +++ b/examples/demo-localstack/stacks/deploy/staging/demo.yaml @@ -0,0 +1,12 @@ +import: +- mixins/localstack +- catalog/demo + +vars: + stage: staging + +components: + terraform: + demo: + metadata: + type: real diff --git a/examples/demo-localstack/stacks/mixins/localstack.yaml b/examples/demo-localstack/stacks/mixins/localstack.yaml new file mode 100644 index 000000000..cfc4d2f43 --- /dev/null +++ b/examples/demo-localstack/stacks/mixins/localstack.yaml @@ -0,0 +1,41 @@ +env: + # We need to ensure no profile is set when using LocalStack, 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: false + skip_credentials_validation: true + skip_metadata_api_check: true + endpoints: + # An alias for the default LocalStack URL + sts: &localstack_url "https://localhost.localstack.cloud:4566" + + # S3 is an exception, and requires a TLS endpoint + s3: "https://localhost.localstack.cloud:4566" + + # Everything else can use HTTP on localhost + apigateway: *localstack_url + apigatewayv2: *localstack_url + cloudformation: *localstack_url + cloudwatch: *localstack_url + dynamodb: *localstack_url + ec2: *localstack_url + es: *localstack_url + elasticache: *localstack_url + iam: *localstack_url + lambda: *localstack_url + rds: *localstack_url + route53: *localstack_url + secretsmanager: *localstack_url + ses: *localstack_url + sns: *localstack_url + sqs: *localstack_url + ssm: *localstack_url + diff --git a/examples/demo-stacks/components/terraform/myapp/main.tf b/examples/demo-stacks/components/terraform/myapp/main.tf index d1e81c169..9971bf5b0 100644 --- a/examples/demo-stacks/components/terraform/myapp/main.tf +++ b/examples/demo-stacks/components/terraform/myapp/main.tf @@ -18,5 +18,5 @@ data "http" "weather" { # Now write this to a file (as an example of a resource) resource "local_file" "cache" { filename = "cache.${var.stage}.txt" - content = data.http.weather.body + content = data.http.weather.response_body } diff --git a/examples/demo-stacks/components/terraform/myapp/outputs.tf b/examples/demo-stacks/components/terraform/myapp/outputs.tf index e29b0d7bb..f0e7fd442 100644 --- a/examples/demo-stacks/components/terraform/myapp/outputs.tf +++ b/examples/demo-stacks/components/terraform/myapp/outputs.tf @@ -1,5 +1,5 @@ output "weather" { - value = data.http.weather.body + value = data.http.weather.response_body } output "url" { diff --git a/examples/demo-vendoring/atmos.yaml b/examples/demo-vendoring/atmos.yaml new file mode 100644 index 000000000..555d07515 --- /dev/null +++ b/examples/demo-vendoring/atmos.yaml @@ -0,0 +1,21 @@ +base_path: "./" + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "deploy/**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +logs: + file: "/dev/stderr" + level: Info diff --git a/examples/demo-vendoring/vendor.yaml b/examples/demo-vendoring/vendor.yaml new file mode 100644 index 000000000..be37486d9 --- /dev/null +++ b/examples/demo-vendoring/vendor.yaml @@ -0,0 +1,38 @@ +apiVersion: atmos/v1 +kind: AtmosVendorConfig +metadata: + name: demo-vendoring + description: Atmos vendoring manifest for Atmos demo component library +spec: + # Import other vendor manifests, if necessary + imports: [] + + sources: + - component: "github/stargazers" + source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" + version: "reorg" + targets: + - "components/terraform/{{ .Component }}/{{.Version}}" + included_paths: + - "**/*.tf" + - "**/*.tfvars" + - "**/*.md" + tags: + - demo + - github + + - component: "weather" + source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" + version: "reorg" + targets: + - "components/terraform/{{ .Component }}/{{.Version}}" + tags: + - demo + + - component: "ipinfo" + source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" + version: "reorg" + targets: + - "components/terraform/{{ .Component }}/{{.Version}}" + tags: + - demo diff --git a/examples/demo-workflows/atmos.yaml b/examples/demo-workflows/atmos.yaml new file mode 100644 index 000000000..1eb5c410f --- /dev/null +++ b/examples/demo-workflows/atmos.yaml @@ -0,0 +1,24 @@ +base_path: "./" + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "deploy/**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +workflows: + base_path: "stacks/workflows" + +logs: + file: "/dev/stderr" + level: Info diff --git a/examples/demo-workflows/components/myapp/main.tf b/examples/demo-workflows/components/myapp/main.tf new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-workflows/components/myapp/outputs.tf b/examples/demo-workflows/components/myapp/outputs.tf new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-workflows/components/myapp/variables.tf b/examples/demo-workflows/components/myapp/variables.tf new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-workflows/stacks/catalog/myapp.yaml b/examples/demo-workflows/stacks/catalog/myapp.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-workflows/stacks/deploy/dev.yaml b/examples/demo-workflows/stacks/deploy/dev.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-workflows/stacks/deploy/prod.yaml b/examples/demo-workflows/stacks/deploy/prod.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/demo-workflows/stacks/deploy/staging.yaml b/examples/demo-workflows/stacks/deploy/staging.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/examples/quick-start/.dockerignore b/examples/quick-start-advanced/.dockerignore similarity index 100% rename from examples/quick-start/.dockerignore rename to examples/quick-start-advanced/.dockerignore diff --git a/examples/quick-start/.gitignore b/examples/quick-start-advanced/.gitignore similarity index 100% rename from examples/quick-start/.gitignore rename to examples/quick-start-advanced/.gitignore diff --git a/examples/quick-start/Dockerfile b/examples/quick-start-advanced/Dockerfile similarity index 100% rename from examples/quick-start/Dockerfile rename to examples/quick-start-advanced/Dockerfile diff --git a/examples/quick-start/Makefile b/examples/quick-start-advanced/Makefile similarity index 100% rename from examples/quick-start/Makefile rename to examples/quick-start-advanced/Makefile diff --git a/examples/quick-start/README.md b/examples/quick-start-advanced/README.md similarity index 100% rename from examples/quick-start/README.md rename to examples/quick-start-advanced/README.md diff --git a/examples/quick-start/atmos.yaml b/examples/quick-start-advanced/atmos.yaml similarity index 98% rename from examples/quick-start/atmos.yaml rename to examples/quick-start-advanced/atmos.yaml index b5d527c0c..7cdb6e415 100644 --- a/examples/quick-start/atmos.yaml +++ b/examples/quick-start-advanced/atmos.yaml @@ -243,9 +243,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -256,7 +256,7 @@ schemas: manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/examples/quick-start/components/terraform/vpc-flow-logs-bucket/context.tf b/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/context.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc-flow-logs-bucket/context.tf rename to examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/context.tf diff --git a/examples/quick-start/components/terraform/vpc-flow-logs-bucket/main.tf b/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/main.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc-flow-logs-bucket/main.tf rename to examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/main.tf diff --git a/examples/quick-start/components/terraform/vpc-flow-logs-bucket/outputs.tf b/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/outputs.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc-flow-logs-bucket/outputs.tf rename to examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/outputs.tf diff --git a/examples/quick-start/components/terraform/vpc-flow-logs-bucket/providers.tf b/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/providers.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc-flow-logs-bucket/providers.tf rename to examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/providers.tf diff --git a/examples/quick-start/components/terraform/vpc-flow-logs-bucket/variables.tf b/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/variables.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc-flow-logs-bucket/variables.tf rename to examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/variables.tf diff --git a/examples/quick-start/components/terraform/vpc-flow-logs-bucket/versions.tf b/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/versions.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc-flow-logs-bucket/versions.tf rename to examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket/versions.tf diff --git a/examples/quick-start/components/terraform/vpc/context.tf b/examples/quick-start-advanced/components/terraform/vpc/context.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/context.tf rename to examples/quick-start-advanced/components/terraform/vpc/context.tf diff --git a/examples/quick-start/components/terraform/vpc/main.tf b/examples/quick-start-advanced/components/terraform/vpc/main.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/main.tf rename to examples/quick-start-advanced/components/terraform/vpc/main.tf diff --git a/examples/quick-start/components/terraform/vpc/outputs.tf b/examples/quick-start-advanced/components/terraform/vpc/outputs.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/outputs.tf rename to examples/quick-start-advanced/components/terraform/vpc/outputs.tf diff --git a/examples/quick-start/components/terraform/vpc/providers.tf b/examples/quick-start-advanced/components/terraform/vpc/providers.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/providers.tf rename to examples/quick-start-advanced/components/terraform/vpc/providers.tf diff --git a/examples/quick-start/components/terraform/vpc/remote-state.tf b/examples/quick-start-advanced/components/terraform/vpc/remote-state.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/remote-state.tf rename to examples/quick-start-advanced/components/terraform/vpc/remote-state.tf diff --git a/examples/quick-start/components/terraform/vpc/variables.tf b/examples/quick-start-advanced/components/terraform/vpc/variables.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/variables.tf rename to examples/quick-start-advanced/components/terraform/vpc/variables.tf diff --git a/examples/quick-start/components/terraform/vpc/versions.tf b/examples/quick-start-advanced/components/terraform/vpc/versions.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/versions.tf rename to examples/quick-start-advanced/components/terraform/vpc/versions.tf diff --git a/examples/quick-start/components/terraform/vpc/vpc-flow-logs.tf b/examples/quick-start-advanced/components/terraform/vpc/vpc-flow-logs.tf similarity index 100% rename from examples/quick-start/components/terraform/vpc/vpc-flow-logs.tf rename to examples/quick-start-advanced/components/terraform/vpc/vpc-flow-logs.tf diff --git a/examples/quick-start/rootfs/usr/local/etc/atmos/atmos.yaml b/examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml similarity index 98% rename from examples/quick-start/rootfs/usr/local/etc/atmos/atmos.yaml rename to examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml index 4a46b977a..5aff27c1d 100644 --- a/examples/quick-start/rootfs/usr/local/etc/atmos/atmos.yaml +++ b/examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml @@ -244,9 +244,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -257,7 +257,7 @@ schemas: manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/examples/quick-start/stacks/catalog/vpc-flow-logs-bucket/defaults.yaml b/examples/quick-start-advanced/stacks/catalog/vpc-flow-logs-bucket/defaults.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc-flow-logs-bucket/defaults.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc-flow-logs-bucket/defaults.yaml diff --git a/examples/quick-start/stacks/catalog/vpc-flow-logs-bucket/disabled.yaml b/examples/quick-start-advanced/stacks/catalog/vpc-flow-logs-bucket/disabled.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc-flow-logs-bucket/disabled.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc-flow-logs-bucket/disabled.yaml diff --git a/examples/quick-start/stacks/catalog/vpc/defaults.yaml b/examples/quick-start-advanced/stacks/catalog/vpc/defaults.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc/defaults.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc/defaults.yaml diff --git a/examples/quick-start/stacks/catalog/vpc/dev.yaml b/examples/quick-start-advanced/stacks/catalog/vpc/dev.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc/dev.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc/dev.yaml diff --git a/examples/quick-start/stacks/catalog/vpc/disabled.yaml b/examples/quick-start-advanced/stacks/catalog/vpc/disabled.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc/disabled.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc/disabled.yaml diff --git a/examples/quick-start/stacks/catalog/vpc/prod.yaml b/examples/quick-start-advanced/stacks/catalog/vpc/prod.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc/prod.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc/prod.yaml diff --git a/examples/quick-start/stacks/catalog/vpc/staging.yaml b/examples/quick-start-advanced/stacks/catalog/vpc/staging.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc/staging.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc/staging.yaml diff --git a/examples/quick-start/stacks/catalog/vpc/ue2.yaml b/examples/quick-start-advanced/stacks/catalog/vpc/ue2.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc/ue2.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc/ue2.yaml diff --git a/examples/quick-start/stacks/catalog/vpc/uw2.yaml b/examples/quick-start-advanced/stacks/catalog/vpc/uw2.yaml similarity index 100% rename from examples/quick-start/stacks/catalog/vpc/uw2.yaml rename to examples/quick-start-advanced/stacks/catalog/vpc/uw2.yaml diff --git a/examples/quick-start/stacks/mixins/region/global-region.yaml b/examples/quick-start-advanced/stacks/mixins/region/global-region.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/region/global-region.yaml rename to examples/quick-start-advanced/stacks/mixins/region/global-region.yaml diff --git a/examples/quick-start/stacks/mixins/region/us-east-2.yaml b/examples/quick-start-advanced/stacks/mixins/region/us-east-2.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/region/us-east-2.yaml rename to examples/quick-start-advanced/stacks/mixins/region/us-east-2.yaml diff --git a/examples/quick-start/stacks/mixins/region/us-west-2.yaml b/examples/quick-start-advanced/stacks/mixins/region/us-west-2.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/region/us-west-2.yaml rename to examples/quick-start-advanced/stacks/mixins/region/us-west-2.yaml diff --git a/examples/quick-start/stacks/mixins/stage/dev.yaml b/examples/quick-start-advanced/stacks/mixins/stage/dev.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/stage/dev.yaml rename to examples/quick-start-advanced/stacks/mixins/stage/dev.yaml diff --git a/examples/quick-start/stacks/mixins/stage/prod.yaml b/examples/quick-start-advanced/stacks/mixins/stage/prod.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/stage/prod.yaml rename to examples/quick-start-advanced/stacks/mixins/stage/prod.yaml diff --git a/examples/quick-start/stacks/mixins/stage/staging.yaml b/examples/quick-start-advanced/stacks/mixins/stage/staging.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/stage/staging.yaml rename to examples/quick-start-advanced/stacks/mixins/stage/staging.yaml diff --git a/examples/quick-start/stacks/mixins/tenant/core.yaml b/examples/quick-start-advanced/stacks/mixins/tenant/core.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/tenant/core.yaml rename to examples/quick-start-advanced/stacks/mixins/tenant/core.yaml diff --git a/examples/quick-start/stacks/mixins/tenant/plat.yaml b/examples/quick-start-advanced/stacks/mixins/tenant/plat.yaml similarity index 100% rename from examples/quick-start/stacks/mixins/tenant/plat.yaml rename to examples/quick-start-advanced/stacks/mixins/tenant/plat.yaml diff --git a/examples/quick-start/stacks/orgs/acme/_defaults.yaml b/examples/quick-start-advanced/stacks/orgs/acme/_defaults.yaml similarity index 91% rename from examples/quick-start/stacks/orgs/acme/_defaults.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/_defaults.yaml index e513fa021..7537abec9 100644 --- a/examples/quick-start/stacks/orgs/acme/_defaults.yaml +++ b/examples/quick-start-advanced/stacks/orgs/acme/_defaults.yaml @@ -2,7 +2,7 @@ vars: namespace: acme settings: - # https://atmos.tools/core-concepts/stacks/templating + # https://atmos.tools/core-concepts/stacks/templates templates: settings: # https://masterminds.github.io/sprig @@ -16,7 +16,7 @@ settings: terraform: vars: tags: - # https://atmos.tools/core-concepts/stacks/templating + # https://atmos.tools/core-concepts/stacks/templates atmos_component: "{{ .atmos_component }}" atmos_stack: "{{ .atmos_stack }}" atmos_manifest: "{{ .atmos_stack_file }}" @@ -29,7 +29,7 @@ terraform: atmos_component_description: "{{ strings.Title .atmos_component }} component {{ .vars.name | strings.Quote }} provisioned in the stack {{ .atmos_stack | strings.Quote }}" # Terraform backend configuration - # https://atmos.tools/core-concepts/components/terraform-backends + # https://atmos.tools/core-concepts/components/terraform/backends # https://developer.hashicorp.com/terraform/language/settings/backends/configuration # backend_type: cloud # s3, cloud # backend: diff --git a/examples/quick-start/stacks/orgs/acme/core/_defaults.yaml b/examples/quick-start-advanced/stacks/orgs/acme/core/_defaults.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/core/_defaults.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/core/_defaults.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/_defaults.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/_defaults.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/_defaults.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/_defaults.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/dev/_defaults.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/dev/_defaults.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/dev/_defaults.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/dev/_defaults.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/dev/global-region.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/dev/global-region.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/dev/global-region.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/dev/global-region.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/dev/us-east-2.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/dev/us-east-2.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/dev/us-east-2.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/dev/us-east-2.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/dev/us-west-2.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/dev/us-west-2.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/dev/us-west-2.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/dev/us-west-2.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/prod/_defaults.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/prod/_defaults.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/prod/_defaults.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/prod/_defaults.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/prod/global-region.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/prod/global-region.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/prod/global-region.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/prod/global-region.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/prod/us-east-2.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/prod/us-east-2.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/prod/us-east-2.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/prod/us-east-2.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/prod/us-west-2.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/prod/us-west-2.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/prod/us-west-2.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/prod/us-west-2.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/staging/_defaults.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/staging/_defaults.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/staging/_defaults.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/staging/_defaults.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/staging/global-region.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/staging/global-region.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/staging/global-region.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/staging/global-region.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/staging/us-east-2.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/staging/us-east-2.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/staging/us-east-2.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/staging/us-east-2.yaml diff --git a/examples/quick-start/stacks/orgs/acme/plat/staging/us-west-2.yaml b/examples/quick-start-advanced/stacks/orgs/acme/plat/staging/us-west-2.yaml similarity index 100% rename from examples/quick-start/stacks/orgs/acme/plat/staging/us-west-2.yaml rename to examples/quick-start-advanced/stacks/orgs/acme/plat/staging/us-west-2.yaml diff --git a/examples/quick-start-advanced/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json b/examples/quick-start-advanced/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json new file mode 100644 index 000000000..012ad9559 --- /dev/null +++ b/examples/quick-start-advanced/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json @@ -0,0 +1,822 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json.schemastore.org/atmos-manifest.json", + "title": "JSON Schema for Atmos Stack Manifest files. Version 1.0. https://atmos.tools", + "type": "object", + "properties": { + "import": { + "$ref": "#/definitions/import" + }, + "terraform": { + "$ref": "#/definitions/terraform" + }, + "helmfile": { + "$ref": "#/definitions/helmfile" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "components": { + "$ref": "#/definitions/components" + }, + "overrides": { + "$ref": "#/definitions/overrides" + }, + "workflows": { + "$ref": "#/definitions/workflows" + } + }, + "additionalProperties": true, + "oneOf": [ + { + "required": [ + "workflows" + ] + }, + { + "anyOf": [ + { + "additionalProperties": true, + "not": { + "required": [ + "workflows" + ] + } + }, + { + "required": [ + "import" + ] + }, + { + "required": [ + "terraform" + ] + }, + { + "required": [ + "helmfile" + ] + }, + { + "required": [ + "vars" + ] + }, + { + "required": [ + "env" + ] + }, + { + "required": [ + "settings" + ] + }, + { + "required": [ + "components" + ] + }, + { + "required": [ + "overrides" + ] + } + ] + } + ], + "definitions": { + "import": { + "type": "array", + "description": "Import section", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "path": { + "type": "string" + }, + "skip_templates_processing": { + "type": "boolean" + }, + "ignore_missing_template_values": { + "type": "boolean" + }, + "skip_if_missing": { + "type": "boolean" + }, + "context": { + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "path" + ] + } + ] + } + }, + "components": { + "type": "object", + "description": "Components section", + "additionalProperties": false, + "properties": { + "terraform": { + "$ref": "#/definitions/terraform_components" + }, + "helmfile": { + "$ref": "#/definitions/helmfile_components" + } + }, + "required": [], + "title": "components" + }, + "terraform": { + "type": "object", + "description": "Terraform section", + "additionalProperties": false, + "properties": { + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "backend_type": { + "$ref": "#/definitions/backend_type" + }, + "backend": { + "$ref": "#/definitions/backend" + }, + "remote_state_backend_type": { + "$ref": "#/definitions/remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/remote_state_backend" + }, + "overrides": { + "$ref": "#/definitions/overrides" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "terraform" + }, + "terraform_components": { + "type": "object", + "description": "Terraform components section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/terraform_component_manifest" + } + }, + "additionalProperties": false, + "title": "terraform_components" + }, + "terraform_component_manifest": { + "type": "object", + "description": "Terraform component manifest", + "additionalProperties": false, + "properties": { + "metadata": { + "$ref": "#/definitions/metadata" + }, + "component": { + "$ref": "#/definitions/component" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "backend_type": { + "$ref": "#/definitions/backend_type" + }, + "backend": { + "$ref": "#/definitions/backend" + }, + "remote_state_backend_type": { + "$ref": "#/definitions/remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/remote_state_backend" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "terraform_component_manifest" + }, + "helmfile": { + "type": "object", + "description": "Helmfile section", + "additionalProperties": false, + "properties": { + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + }, + "overrides": { + "$ref": "#/definitions/overrides" + } + }, + "required": [], + "title": "helmfile" + }, + "helmfile_components": { + "type": "object", + "description": "Helmfile components section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/helmfile_component_manifest" + } + }, + "additionalProperties": false, + "title": "helmfile_components" + }, + "helmfile_component_manifest": { + "type": "object", + "description": "Helmfile component manifest", + "additionalProperties": false, + "properties": { + "metadata": { + "$ref": "#/definitions/metadata" + }, + "component": { + "$ref": "#/definitions/component" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "command": { + "$ref": "#/definitions/command" + } + }, + "required": [], + "title": "helmfile_component_manifest" + }, + "command": { + "type": "string", + "description": "Command to execute", + "title": "command" + }, + "component": { + "type": "string", + "description": "Component section", + "title": "component" + }, + "metadata": { + "type": "object", + "description": "Metadata section", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "abstract", + "real" + ] + }, + "component": { + "type": "string" + }, + "inherits": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "terraform_workspace": { + "type": "string" + }, + "terraform_workspace_pattern": { + "type": "string" + }, + "custom": { + "type": "object", + "description": "Custom configuration per component, not inherited by derived components", + "additionalProperties": true, + "title": "custom" + } + }, + "required": [], + "title": "metadata" + }, + "settings": { + "type": "object", + "description": "Settings section", + "additionalProperties": true, + "properties": { + "validation": { + "$ref": "#/definitions/validation" + }, + "depends_on": { + "$ref": "#/definitions/depends_on" + }, + "spacelift": { + "$ref": "#/definitions/spacelift" + }, + "atlantis": { + "$ref": "#/definitions/atlantis" + }, + "templates": { + "$ref": "#/definitions/templates" + } + }, + "required": [], + "title": "settings" + }, + "validation": { + "type": "object", + "description": "Validation section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/validation_manifest" + } + }, + "additionalProperties": false, + "title": "validation" + }, + "validation_manifest": { + "type": "object", + "description": "Validation manifest", + "properties": { + "schema_type": { + "type": "string", + "enum": [ + "jsonschema", + "opa" + ] + }, + "schema_path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "disabled": { + "type": "boolean" + }, + "timeout": { + "type": "integer", + "minimum": 0 + }, + "module_paths": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + }, + "description": "List of paths to validation modules" + } + }, + "additionalProperties": false, + "required": [ + "schema_type", + "schema_path" + ], + "title": "validation_manifest" + }, + "vars": { + "type": "object", + "description": "Vars section", + "additionalProperties": true, + "title": "vars" + }, + "env": { + "type": "object", + "description": "Env section", + "additionalProperties": true, + "required": [], + "title": "env" + }, + "backend_type": { + "type": "string", + "enum": [ + "local", + "s3", + "remote", + "vault", + "static", + "azurerm", + "gcs", + "cloud" + ], + "description": "Backend type", + "title": "backend_type" + }, + "backend": { + "$ref": "#/definitions/backend_manifest", + "title": "backend" + }, + "remote_state_backend_type": { + "type": "string", + "enum": [ + "local", + "s3", + "remote", + "vault", + "static", + "azurerm", + "gcs", + "cloud" + ], + "description": "Remote state backend type", + "title": "remote_state_backend_type" + }, + "remote_state_backend": { + "$ref": "#/definitions/backend_manifest", + "title": "remote_state_backend" + }, + "backend_manifest": { + "type": "object", + "description": "Backend manifest", + "additionalProperties": false, + "properties": { + "s3": { + "type": "object", + "additionalProperties": false, + "properties": { + "encrypt": { + "type": "boolean" + }, + "bucket": { + "type": "string" + }, + "key": { + "type": "string" + }, + "dynamodb_table": { + "type": "string" + }, + "acl": { + "type": "string" + }, + "region": { + "type": "string" + }, + "assume_role": { + "type": "object", + "additionalProperties": false, + "properties": { + "role_arn": { + "type": [ + "string", + "null" + ] + }, + "duration": { + "type": [ + "string", + "null" + ] + }, + "external_id": { + "type": [ + "string", + "null" + ] + }, + "policy": { + "type": [ + "string", + "null" + ] + }, + "policy_arns": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "session_name": { + "type": [ + "string", + "null" + ] + }, + "source_identity": { + "type": [ + "string", + "null" + ] + }, + "tags": { + "type": [ + "object", + "null" + ], + "additionalProperties": true + }, + "transitive_tag_keys": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + } + } + }, + "role_arn": { + "type": [ + "string", + "null" + ] + }, + "profile": { + "type": [ + "string", + "null" + ] + }, + "workspace_key_prefix": { + "type": "string" + } + } + }, + "remote": { + "type": "object", + "additionalProperties": true + }, + "vault": { + "type": "object", + "additionalProperties": true + }, + "static": { + "type": "object", + "additionalProperties": true + }, + "azurerm": { + "type": "object", + "additionalProperties": true + }, + "gcs": { + "type": "object", + "additionalProperties": true + }, + "cloud": { + "type": "object", + "additionalProperties": true + } + }, + "required": [], + "title": "backend" + }, + "overrides": { + "type": "object", + "description": "Overrides section", + "additionalProperties": false, + "properties": { + "command": { + "$ref": "#/definitions/command" + }, + "vars": { + "$ref": "#/definitions/vars" + }, + "env": { + "$ref": "#/definitions/env" + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "providers": { + "$ref": "#/definitions/providers" + } + }, + "required": [], + "title": "overrides" + }, + "depends_on": { + "type": "object", + "description": "Depends_on section", + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/depends_on_manifest" + } + }, + "additionalProperties": false, + "title": "depends_on" + }, + "depends_on_manifest": { + "type": "object", + "description": "Depends_on manifest", + "properties": { + "namespace": { + "type": "string" + }, + "tenant": { + "type": "string" + }, + "environment": { + "type": "string" + }, + "stage": { + "type": "string" + }, + "component": { + "type": "string" + }, + "file": { + "type": "string" + }, + "folder": { + "type": "string" + } + }, + "oneOf": [ + { + "required": [ + "component" + ] + }, + { + "required": [ + "file" + ] + }, + { + "required": [ + "folder" + ] + } + ], + "additionalProperties": false, + "title": "depends_on_manifest" + }, + "spacelift": { + "type": "object", + "description": "Spacelift section", + "additionalProperties": true, + "properties": { + "workspace_enabled": { + "type": "boolean" + }, + "stack_destructor_enabled": { + "type": "boolean" + }, + "protect_from_deletion": { + "type": "boolean" + }, + "autodeploy": { + "type": "boolean" + }, + "terraform_version": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + } + }, + "required": [], + "title": "spacelift" + }, + "atlantis": { + "type": "object", + "description": "Atlantis section", + "additionalProperties": false, + "properties": { + "config_template_name": { + "type": "string" + }, + "config_template": { + "type": "object", + "additionalProperties": true + }, + "project_template_name": { + "type": "string" + }, + "project_template": { + "type": "object", + "additionalProperties": true + }, + "workflow_templates": { + "type": "object", + "additionalProperties": true + } + }, + "required": [], + "title": "atlantis" + }, + "workflows": { + "type": "object", + "description": "Workflows section", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^[\/a-zA-Z0-9-_{}. ]+$": { + "$ref": "#/definitions/workflow_manifest" + } + }, + "additionalProperties": false, + "title": "workflows" + }, + "workflow_manifest": { + "type": "object", + "description": "Atmos workflow manifest", + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "steps": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "command": { + "type": "string" + }, + "stack": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "command" + ] + } + } + }, + "required": [ + "steps" + ], + "title": "workflow_manifest" + }, + "providers": { + "type": "object", + "description": "Providers section", + "additionalProperties": true, + "title": "providers" + }, + "templates": { + "type": "object", + "description": "Templates section", + "additionalProperties": true, + "title": "templates" + } + } +} diff --git a/examples/quick-start/stacks/schemas/jsonschema/vpc/validate-vpc-component.json b/examples/quick-start-advanced/stacks/schemas/jsonschema/vpc/validate-vpc-component.json similarity index 100% rename from examples/quick-start/stacks/schemas/jsonschema/vpc/validate-vpc-component.json rename to examples/quick-start-advanced/stacks/schemas/jsonschema/vpc/validate-vpc-component.json diff --git a/examples/quick-start/stacks/schemas/opa/catalog/constants/constants.rego b/examples/quick-start-advanced/stacks/schemas/opa/catalog/constants/constants.rego similarity index 100% rename from examples/quick-start/stacks/schemas/opa/catalog/constants/constants.rego rename to examples/quick-start-advanced/stacks/schemas/opa/catalog/constants/constants.rego diff --git a/examples/quick-start/stacks/schemas/opa/vpc/validate-vpc-component.rego b/examples/quick-start-advanced/stacks/schemas/opa/vpc/validate-vpc-component.rego similarity index 100% rename from examples/quick-start/stacks/schemas/opa/vpc/validate-vpc-component.rego rename to examples/quick-start-advanced/stacks/schemas/opa/vpc/validate-vpc-component.rego diff --git a/examples/quick-start/stacks/workflows/networking.yaml b/examples/quick-start-advanced/stacks/workflows/networking.yaml similarity index 100% rename from examples/quick-start/stacks/workflows/networking.yaml rename to examples/quick-start-advanced/stacks/workflows/networking.yaml diff --git a/examples/quick-start/stacks/workflows/validation.yaml b/examples/quick-start-advanced/stacks/workflows/validation.yaml similarity index 100% rename from examples/quick-start/stacks/workflows/validation.yaml rename to examples/quick-start-advanced/stacks/workflows/validation.yaml diff --git a/examples/quick-start/vendor.yaml b/examples/quick-start-advanced/vendor.yaml similarity index 100% rename from examples/quick-start/vendor.yaml rename to examples/quick-start-advanced/vendor.yaml diff --git a/examples/quick-start-simple/.gitignore b/examples/quick-start-simple/.gitignore new file mode 100644 index 000000000..ebd3eac49 --- /dev/null +++ b/examples/quick-start-simple/.gitignore @@ -0,0 +1,10 @@ +**/.terraform/** +**/.terraform.lock.hcl +**/.terraform.tfstate/** +**/.terraform.tfstate.backup/** +**/*.tfvars.json +**/*.planfile +**/terraform.tfstate +**/terraform.tfstate.backup +**/terraform.tfstate.d/** +**/cache.*.txt diff --git a/examples/quick-start-simple/atmos.yaml b/examples/quick-start-simple/atmos.yaml new file mode 100644 index 000000000..555d07515 --- /dev/null +++ b/examples/quick-start-simple/atmos.yaml @@ -0,0 +1,21 @@ +base_path: "./" + +components: + terraform: + base_path: "components/terraform" + apply_auto_approve: false + deploy_run_init: true + init_run_reconfigure: true + auto_generate_backend_file: false + +stacks: + base_path: "stacks" + included_paths: + - "deploy/**/*" + excluded_paths: + - "**/_defaults.yaml" + name_pattern: "{stage}" + +logs: + file: "/dev/stderr" + level: Info diff --git a/examples/quick-start-simple/components/terraform/weather/README.md b/examples/quick-start-simple/components/terraform/weather/README.md new file mode 100644 index 000000000..1d7a7ee03 --- /dev/null +++ b/examples/quick-start-simple/components/terraform/weather/README.md @@ -0,0 +1,50 @@ +# Example Terraform Weather Component + +This Terraform "root" module fetches weather information for a specified location with custom display options. +It queries data from the [`wttr.in`](https://wttr.in) weather service and stores the result in a local file (`cache.txt`). +It also provides several outputs like weather information, request URL, stage, location, language, and units of measurement. + +## Features + +- Fetch weather updates for a location using HTTP request. +- Write the obtained weather data in a local file. +- Customizable display options. +- View the request URL. +- Get informed about the stage, location, language, and units in the metadata. + +## Usage + +To include this module in your [Atmos Stacks](https://atmos.tools/core-concepts/stacks) configuration: + +```yaml +components: + terraform: + weather: + vars: + stage: dev + location: New York + options: 0T + format: v2 + lang: en + units: m +``` + +### Inputs +- `stage`: Stage where it will be deployed. +- `location`: Location for which the weather is reported. Default is "Los Angeles". +- `options`: Options to customize the output. Default is "0T". +- `format`: Specifies the output format. Default is "v2". +- `lang`: Language in which the weather will be displayed. Default is "en". +- `units`: Units in which the weather will be displayed. Default is "m". + +### Outputs +- `weather`: The fetched weather data. +- `url`: Requested URL. +- `stage`: Stage of deployment. +- `location`: Location of the reported weather. +- `lang`: Language used for weather data. +- `units`: Units of measurement for the weather data. + +Please note, this module requires Terraform version >=1.0.0, and you need to specify no other required providers. + +Happy Weather Tracking! diff --git a/examples/quick-start-simple/components/terraform/weather/main.tf b/examples/quick-start-simple/components/terraform/weather/main.tf new file mode 100644 index 000000000..9971bf5b0 --- /dev/null +++ b/examples/quick-start-simple/components/terraform/weather/main.tf @@ -0,0 +1,22 @@ +locals { + url = format("https://wttr.in/%v?%v&format=%v&lang=%v&u=%v", + urlencode(var.location), + urlencode(var.options), + urlencode(var.format), + urlencode(var.lang), + urlencode(var.units), + ) +} + +data "http" "weather" { + url = local.url + request_headers = { + User-Agent = "curl" + } +} + +# Now write this to a file (as an example of a resource) +resource "local_file" "cache" { + filename = "cache.${var.stage}.txt" + content = data.http.weather.response_body +} diff --git a/examples/quick-start-simple/components/terraform/weather/outputs.tf b/examples/quick-start-simple/components/terraform/weather/outputs.tf new file mode 100644 index 000000000..f0e7fd442 --- /dev/null +++ b/examples/quick-start-simple/components/terraform/weather/outputs.tf @@ -0,0 +1,27 @@ +output "weather" { + value = data.http.weather.response_body +} + +output "url" { + value = local.url +} + +output "stage" { + value = var.stage + description = "Stage where it was deployed" +} + +output "location" { + value = var.location + description = "Location of the weather report." +} + +output "lang" { + value = var.lang + description = "Language which the weather is displayed." +} + +output "units" { + value = var.units + description = "Units the weather is displayed." +} diff --git a/examples/quick-start-simple/components/terraform/weather/variables.tf b/examples/quick-start-simple/components/terraform/weather/variables.tf new file mode 100644 index 000000000..c8a32310a --- /dev/null +++ b/examples/quick-start-simple/components/terraform/weather/variables.tf @@ -0,0 +1,34 @@ +variable "stage" { + description = "Stage where it will be deployed" + type = string +} + +variable "location" { + description = "Location for which the weather." + type = string + default = "Los Angeles" +} + +variable "options" { + description = "Options to customize the output." + type = string + default = "0T" +} + +variable "format" { + description = "Format of the output." + type = string + default = "v2" +} + +variable "lang" { + description = "Language in which the weather is displayed." + type = string + default = "en" +} + +variable "units" { + description = "Units in which the weather is displayed." + type = string + default = "m" +} diff --git a/examples/quick-start-simple/components/terraform/weather/versions.tf b/examples/quick-start-simple/components/terraform/weather/versions.tf new file mode 100644 index 000000000..e2a3d732d --- /dev/null +++ b/examples/quick-start-simple/components/terraform/weather/versions.tf @@ -0,0 +1,5 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers {} +} diff --git a/examples/quick-start-simple/stacks/catalog/station.yaml b/examples/quick-start-simple/stacks/catalog/station.yaml new file mode 100644 index 000000000..842460e80 --- /dev/null +++ b/examples/quick-start-simple/stacks/catalog/station.yaml @@ -0,0 +1,11 @@ +components: + terraform: + station: + metadata: + component: weather + vars: + location: Los Angeles + lang: en + format: '' + options: '0' + units: m diff --git a/examples/quick-start-simple/stacks/deploy/dev.yaml b/examples/quick-start-simple/stacks/deploy/dev.yaml new file mode 100644 index 000000000..388d721f2 --- /dev/null +++ b/examples/quick-start-simple/stacks/deploy/dev.yaml @@ -0,0 +1,12 @@ +vars: + stage: dev + +import: + - catalog/station + +components: + terraform: + myapp: + vars: + location: Stockholm + lang: se diff --git a/examples/quick-start-simple/stacks/deploy/prod.yaml b/examples/quick-start-simple/stacks/deploy/prod.yaml new file mode 100644 index 000000000..c5de58ba2 --- /dev/null +++ b/examples/quick-start-simple/stacks/deploy/prod.yaml @@ -0,0 +1,12 @@ +vars: + stage: prod + +import: + - catalog/station + +components: + terraform: + station: + vars: + location: Los Angeles + lang: en diff --git a/examples/quick-start-simple/stacks/deploy/staging.yaml b/examples/quick-start-simple/stacks/deploy/staging.yaml new file mode 100644 index 000000000..28b8659b4 --- /dev/null +++ b/examples/quick-start-simple/stacks/deploy/staging.yaml @@ -0,0 +1,12 @@ +vars: + stage: staging + +import: + - catalog/station + +components: + terraform: + station: + vars: + location: Los Angeles + lang: en diff --git a/examples/tests/atmos.yaml b/examples/tests/atmos.yaml index 4335d6a3b..3a9c4383d 100644 --- a/examples/tests/atmos.yaml +++ b/examples/tests/atmos.yaml @@ -337,9 +337,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -363,7 +363,7 @@ aliases: lc: list components # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/examples/tests/rootfs/usr/local/etc/atmos/atmos.yaml b/examples/tests/rootfs/usr/local/etc/atmos/atmos.yaml index 99429c306..e9d3c249e 100644 --- a/examples/tests/rootfs/usr/local/etc/atmos/atmos.yaml +++ b/examples/tests/rootfs/usr/local/etc/atmos/atmos.yaml @@ -585,9 +585,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -611,7 +611,7 @@ aliases: lc: list components # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/examples/tests/stacks/orgs/cp/_defaults.yaml b/examples/tests/stacks/orgs/cp/_defaults.yaml index 77513a396..3bc505c88 100644 --- a/examples/tests/stacks/orgs/cp/_defaults.yaml +++ b/examples/tests/stacks/orgs/cp/_defaults.yaml @@ -4,7 +4,7 @@ vars: terraform: vars: tags: - # https://atmos.tools/core-concepts/stacks/templating + # https://atmos.tools/core-concepts/stacks/templates # atmos_component: "{{\"{{`{{ .atmos_component }}`}}\"}}" atmos_component: "{{`{{ .atmos_component }}`}}" atmos_stack: "{{ .atmos_stack }}" @@ -89,7 +89,7 @@ components: helmfile: {} settings: - # https://atmos.tools/core-concepts/stacks/templating + # https://atmos.tools/core-concepts/stacks/templates templates: settings: # https://masterminds.github.io/sprig diff --git a/examples/welcome.md b/examples/welcome.md new file mode 100644 index 000000000..9fedabb4e --- /dev/null +++ b/examples/welcome.md @@ -0,0 +1,12 @@ +# Welcome to Atmos + +You can easily kick the tires with atmos. + +Here are some quick tips to get started: + +- **Demos**: Enter into any of the demo directories for a simple demo of some function of atmos +- **Develop**: Start coding in the `src/` directory. +- **Community**: Join usin [`#atmos` on Slack](https://atmos.tools/community/slack), if you get stuck. +- **Docs**: Documentation can be found at [atmos.tools](https://atmos.tools) + +Enjoy exploring with Atmos! diff --git a/internal/exec/describe_stacks.go b/internal/exec/describe_stacks.go index 1e00a3602..212443e64 100644 --- a/internal/exec/describe_stacks.go +++ b/internal/exec/describe_stacks.go @@ -297,7 +297,7 @@ func ExecuteDescribeStacks( if !cliConfig.Templates.Settings.Enabled { if strings.Contains(componentSectionStr, "{{") || strings.Contains(componentSectionStr, "}}") { errorMessage := "the stack manifests contain Go templates, but templating is disabled in atmos.yaml in 'templates.settings.enabled'\n" + - "to enable templating, refer to https://atmos.tools/core-concepts/stacks/templating" + "to enable templating, refer to https://atmos.tools/core-concepts/stacks/templates" err = errors.Join(err, errors.New(errorMessage)) } } @@ -474,7 +474,7 @@ func ExecuteDescribeStacks( if !cliConfig.Templates.Settings.Enabled { if strings.Contains(componentSectionStr, "{{") || strings.Contains(componentSectionStr, "}}") { errorMessage := "the stack manifests contain Go templates, but templating is disabled in atmos.yaml in 'templates.settings.enabled'\n" + - "to enable templating, refer to https://atmos.tools/core-concepts/stacks/templating" + "to enable templating, refer to https://atmos.tools/core-concepts/stacks/templates" err = errors.Join(err, errors.New(errorMessage)) } } diff --git a/internal/exec/utils.go b/internal/exec/utils.go index 8df6bca2f..1f53f1020 100644 --- a/internal/exec/utils.go +++ b/internal/exec/utils.go @@ -498,7 +498,7 @@ func ProcessStacks( if !cliConfig.Templates.Settings.Enabled { if strings.Contains(componentSectionStr, "{{") || strings.Contains(componentSectionStr, "}}") { errorMessage := "the stack manifests contain Go templates, but templating is disabled in atmos.yaml in 'templates.settings.enabled'\n" + - "to enable templating, refer to https://atmos.tools/core-concepts/stacks/templating" + "to enable templating, refer to https://atmos.tools/core-concepts/stacks/templates" err = errors.Join(err, errors.New(errorMessage)) } } diff --git a/internal/exec/validate_stacks.go b/internal/exec/validate_stacks.go index ab231d6b6..8088bd3ff 100644 --- a/internal/exec/validate_stacks.go +++ b/internal/exec/validate_stacks.go @@ -325,7 +325,7 @@ func checkComponentStackMap(componentStackMap map[string]map[string][]string) ([ "Consider the following solutions to fix the issue:\n"+ "- Ensure that the same instance of the Atmos '%[1]s' component in the stack '%[2]s' is only defined once (in one YAML stack manifest file)\n"+ "- When defining multiple instances of the same component in the stack, ensure each has a unique name\n"+ - "- Use multiple-inheritance to combine multiple configurations together (refer to https://atmos.tools/core-concepts/components/inheritance)\n\n", + "- Use multiple-inheritance to combine multiple configurations together (refer to https://atmos.tools/core-concepts/stacks/inheritance)\n\n", componentName, stackName, strings.Join(stackManifests, ", "), diff --git a/pkg/atlantis/atmos.yaml b/pkg/atlantis/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/atlantis/atmos.yaml +++ b/pkg/atlantis/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/aws/atmos.yaml b/pkg/aws/atmos.yaml index 74678242d..36a63ce2b 100644 --- a/pkg/aws/atmos.yaml +++ b/pkg/aws/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/component/atmos.yaml b/pkg/component/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/component/atmos.yaml +++ b/pkg/component/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/config/config.go b/pkg/config/config.go index 685d955af..93f89eb21 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -22,7 +22,7 @@ import ( var ( NotFound = errors.New("\n'atmos.yaml' CLI config was not found in any of the searched paths: system dir, home dir, current dir, ENV vars." + "\nYou can download a sample config and adapt it to your requirements from " + - "https://raw.githubusercontent.com/cloudposse/atmos/main/examples/quick-start/atmos.yaml") + "https://raw.githubusercontent.com/cloudposse/atmos/main/examples/quick-start-advanced/atmos.yaml") defaultCliConfig = schema.CliConfiguration{ BasePath: ".", diff --git a/pkg/describe/atmos.yaml b/pkg/describe/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/describe/atmos.yaml +++ b/pkg/describe/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/generate/atmos.yaml b/pkg/generate/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/generate/atmos.yaml +++ b/pkg/generate/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/spacelift/atmos.yaml b/pkg/spacelift/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/spacelift/atmos.yaml +++ b/pkg/spacelift/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/validate/atmos.yaml b/pkg/validate/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/validate/atmos.yaml +++ b/pkg/validate/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/vender/atmos.yaml b/pkg/vender/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/vender/atmos.yaml +++ b/pkg/vender/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/pkg/workflow/atmos.yaml b/pkg/workflow/atmos.yaml index 06c09412f..8a4e10435 100644 --- a/pkg/workflow/atmos.yaml +++ b/pkg/workflow/atmos.yaml @@ -320,9 +320,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes # https://www.schemastore.org/json @@ -333,7 +333,7 @@ schemas: manifest: "../quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" # `Go` templates in Atmos manifests -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: diff --git a/website/docs/best-practices/best-practices.mdx b/website/docs/best-practices/best-practices.mdx new file mode 100644 index 000000000..eec605e53 --- /dev/null +++ b/website/docs/best-practices/best-practices.mdx @@ -0,0 +1,17 @@ +--- +title: Best Practices +sidebar_position: 1 +sidebar_label: Best Practices +sidebar_class_name: hidden +description: Learn the opinionated "Best Practices" for using Atmos +id: best-practices +--- +import DocCardList from '@theme/DocCardList' + +> Physics is the law, everything else is a recommendation. +> Anyone can break laws created by people, but I have yet to see anyone break the laws of physics. +>

— **Elon Musk**

+ +Learn how to best leverage Stacks and Components together with Atmos. + + diff --git a/website/docs/best-practices/components.mdx b/website/docs/best-practices/components.mdx new file mode 100644 index 000000000..975edded6 --- /dev/null +++ b/website/docs/best-practices/components.mdx @@ -0,0 +1,170 @@ +--- +title: Component Best Practices +sidebar_position: 1 +sidebar_label: Components +description: Learn the opinionated "Best Practices" for using Components with Atmos +id: components +--- +import Intro from '@site/src/components/Intro' + + +Here are some essential best practices to follow when designing architectures using infrastructure as code (IaC), focusing on optimizing +component design, reusability, and lifecycle management. These guidelines are designed to help developers and operators build efficient, +scalable, and reliable systems, ensuring a smooth and effective infrastructure management process. + + +Also, be sure to review the [Terraform Best Practices](/best-practices/terraform) for additional guidance on using Terraform with Atmos. + +> Physics is the law, everything else is a recommendation. +> Anyone can break laws created by people, but I have yet to see anyone break the laws of physics. +>

— **Elon Musk**

+ +## Keep Your Components Small to Reduce the Blast Radius of Changes + +Focus on creating single purpose components that small, reusable components that adhere to the UNIX philosophy by doing one thing well. +This strategy leads to simpler updates, more straightforward troubleshooting, quicker plan/apply cycles, and a +clearer separation of responsibilities. Best of all, your state remains small and complexity remains manageable. + +Anti-patterns to avoid include: +- Combining VPCs with databases in the same component +- Defining every dependency needed by an application in a single component (provided there's no shared lifecycle) + +## Split Components By Lifecycle + +To keep your component small, consider breaking them apart by their Software Development Lifecycle (SDLC). +Things that always change together, go together. Things that seldom change together, should be managed separately. +Keep the coupling loose, and use remote state for cohesion. + +For instance, a VPC, which is rarely destroyed, should be managed separately from more dynamic resources like clusters +or databases that may frequently scale or undergo updates. + +## Make Them Opinionated, But Not Too Opinionated + +Ensure components are generalized to prevent the proliferation of similar components, thereby promoting easier testing, +reuse, and maintenance. + +:::important Don't Treat Components like Child Modules +Don't force users to use generic components if that will radically complicate the configuration. +The goal is to make 80% of your infrastructure highly reusable with generic single purpose components. +The remaining 20% might need to be specialized for your use case, and that's okay. +::: + +## Avoid Single Resource Components + +If you find yourself writing a component that is so small, it manages only a single resource e.g. (an IAM Policy), +consider if it should be part of a larger component. + +:::tip Stack Configurations are Not a Replacement for Terraform +The biggest risk for newcomers to Atmos is to over architect components into extremely DRY single-purpose components. +Stack configurations in YAML should not just be a proxy for terraform resources. + +Use terraform for its strengths, compliment it with YAML when it makes sense for very straight forward configuration. +::: + + +## Use Parameterization, But Avoid Over-Parameterization + +Good parameterization ensures components are reusable, but components become difficult to test and document with too many parameters. + +Often time, child modules might accept more parameters than the root module. You can always add more parameters to the root module +as needed, but it's hard to remove them once they are there. + +## Avoid Creating Factories Inside of Components + +[Factories are common software design patterns](https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)) that allow you +to create multiple instances of a component. + +To minimize the blast radius of changes and maintain fast plan/apply cycles, do not embed factories within components that +provision lists of resources. + +Examples of anti-patterns include: +- Reading a configuration file inside of Terraform to create multiple Buckets +- Using a `for_each` loop to create multiple DNS records from a variable input + (you may hit rate limits when you zones get large enough; it's happened to us) + +Instead, leverage [Stack configurations to serve as factories](/core-concepts/stacks) for provisioning multiple component instances. +This approach keeps the state isolated and scales efficiently with the increasing number of component instances. + +Please note, it's perfectly fine to use `for_each` loops sometimes to provision groups of resources, just use them with moderation +and be aware of the potential downsides, such as creating massive states with a wide blast radius. For example, maybe you can safely manage a collection of resources this way. + +:::note Do as we say, not as we do +It is with humility that we state this best practice. Even many of our own Cloud Posse components, do not follow this because +they were written before we realized the overwhelming benefits of this approach. +::: + +## Use Components Inside of Factories + +Google discusses the "factories" approach in the post [Resource Factories: A descriptive approach to Terraform](https://medium.com/google-cloud/resource-factories-a-descriptive-approach-to-terraform-581b3ebb59c). This concept is familiar to every major programming framework, and you can apply it to Terraform too. + +However, unlike Google's approach of creating the factory inside the component ([which we don't recommend](#avoid-creating-factories-inside-of-components)), we suggest using the stack configuration as the factory and the component as the product. + +By following this method, you create a single component for a specific purpose, such as a VPC, database, or Kubernetes cluster. Then, you can instantiate multiple instances of that component in your stack configuration. + +In the factory pattern, the component acts like the "factory class," and when defined in the stack configuration, it is used to create and configure multiple component instances. + +A component provides specific functionality but is not responsible for its own instantiation or configuration; this responsibility is delegated to the factory. + +This approach decouples your architecture from the configuration, resulting in smaller state files and independent lifecycle management for each instance. Most importantly, it maximizes the reusability of your components. + + +## Use Component Libraries & Vendoring + +Utilize a centralized [component library](/core-concepts/components/library) to distribute and share components across the +organization efficiently. This approach enhances discoverability by centralizing where components are stored, preventing +sprawl, and ensuring components are easily accessible to everyone. Employ vendoring to retrieve remote dependencies, like +components, ensuring the practice of immutable infrastructure. + +## Organize Related Components with Folders + +Organize multiple related components in a common folder. Use nested folders as necessary, to logically group components. +For example, by grouping components by cloud provider and layer (e.g. `components/terraform/aws/network/`) + +## Document Component Interfaces and Usage + +Utilize tools such as [terraform-docs](https://terraform-docs.io) to thoroughly document the input variables and outputs +of your component. Include snippets of stack configuration to simplify understanding for developers on integrating the component +into their stack configurations. Providing examples that cover common use-cases of the component is particularly effective. + +## Version Components for Breaking Changes + +Use versioned folders within the component to delineate major versions (e.g. `/components/terraform//v1/`) + +## Use a Monorepo for Your Components + +For streamlined development and simplified dependency management, smaller companies should consolidate stacks and components +in a single monorepo, facilitating easier updates and unified versioning. Larger companies and enterprises with multiple monorepos +can benefit from a central repository for upstream components, and then use vendoring to easily pull in these shared components to +team-specific monorepos. + +## Maintain Loose Coupling Between Components + +Avoid directly invoking one component from within another to ensure components remain loosely coupled. Specifically for Terraform +components (root modules), this practice is unsupported due to the inability to define a backend in a child module, potentially +leading to unexpected outcomes. It's crucial to steer clear of this approach to maintain system integrity. + +## Reserve Code Generation as an Escape Hatch for Emergencies + +We generally advise against using code generation for application logic (components), because it's challenging to ensure good test +coverage (e.g. with `terratest`) and no one likes to code review machine-generated boilerplate in Pull Requests. + +If you find yourself in a situation that seems to require code generation, take a step back and consider if that's the right approach. +- Do not code generate providers to [overcome "limitations" in Terraform](https://github.com/hashicorp/terraform/issues/19932#issuecomment-1817043906), + for example, to iterate over providers. This is a red flag. Instead, architect your components to work with a single provider +- If you are programmatically combining several child modules, consider if they should instead be separated by lifecycle. + +When you follow these rules, root modules become highly reusable, and you reduce the amount of state managed by a single component, +and therefore, the blast radius of changes. + +## Separate Your State by Region + +For Disaster Recovery purposes, always strive to keep the state of your components separate by region. +You don't want a regional outage to affect your ability to manage infrastructure in other regions. + +## Limit Providers to One or Two Per Component + +Avoid using multiple providers in a single component, as it reduces the reusability of the component and increases +the complexity and blast radius of what it manages. + +Consider instead "hub" and "spoke" models, where each spoke is its own component with its own lifecycle. +In this model, the "spoke" will usually have two providers, one for the current context and one for the "hub." diff --git a/website/docs/best-practices/stacks.mdx b/website/docs/best-practices/stacks.mdx new file mode 100644 index 000000000..3805408a4 --- /dev/null +++ b/website/docs/best-practices/stacks.mdx @@ -0,0 +1,96 @@ +--- +title: Stacks Best Practices +sidebar_position: 1 +sidebar_label: Stacks +description: Learn the opinionated "Best Practices" for using Stacks with Atmos +id: stacks +--- +import Intro from '@site/src/components/Intro' + + +Here are some essential best practices to follow when designing the Stack configurations that describe your architectures. These guidelines are intended to help developers and operators think about how they model the configuration of their infrastructure in Atmos, for maximum clarity and long-term maintainability. + + +> Physics is the law, everything else is a recommendation. +> Anyone can break laws created by people, but I have yet to see anyone break the laws of physics. +>

— **Elon Musk**

+ +## Define Factories in Stack Configurations + +Avoid creating factories inside of components, which make them overly complicate and succumb to their massive state. +Instead, use stack configurations to serve as factories for provisioning multiple component instances. +This approach keeps the state isolated and scales efficiently with the increasing number of component instances. + +## Treat Stack Templates like an Escape Hatch + +Apply them carefully and only when necessary. Using templates instead of inheritance can make stack configurations complex +and hard to manage. Be careful using stack templates together with the [factory pattern](#define-factories-in-stack-configurations). + +The simplest templates are the best templates. Using variable interpolation is perfectly fine, but avoid using complex logic, +conditionals, and loops in templates. If you find yourself needing to do this, consider if you are solving the problem in the right way. + +## Avoid Too Many Levels of Imports + +It's very difficult for others to follow relationships when there are too many nested levels and overrides. + +:::warning Complexity rashes + +**If you have more than (3) levels of imports, you're probably developing a complexity rash.** + +Overly DRY configurations can lead to complexity rashes that are difficult to debug and maintain, +and impossible for newcomers to understand. + +::: + +## Balance DRY Principles with Configuration Clarity + +Avoid overly DRY configuration as it leads to complexity rashes. Sometimes repeating configuration is beneficial +for maintenance and clarity. + +In recent years, the DevOps industry has often embraced the DRY (Don’t Repeat Yourself) principle to an extreme. +(And Atmos delivers!) While DRY aims to reduce redundancy and improve maintainability by eliminating duplicate code, +overzealous application of this principle leads to complications and rigidity. + +DRY is not a panacea. In fact, sometimes a bit of repetition is **beneficial**, particularly when anticipating future +divergence in configurations or functionality. A balance between DRY and WET (Write Everything Twice) can offer more +flexibility, and make it easier to see the entire context in one place without needing to trace through multiple abstractions +or indirections + +Here’s why: + +1. **Cognitive Load:** The more you strive for DRYness, the more indirection and abstraction layers you introduce. + This makes it harder for developers because they need to navigate through multiple layers of imports and abstractions + to grasp the complete picture. +2. **Plan for Future Divergence:** When initially similar configurations are likely diverge over time, + keeping them separate will make future changes easier. +3. **Premature Optimization:** Over-optimizing for DRYess may be a form of premature optimization. It’s important to recognize + when to prioritize flexibility and clarity over minimal repetition. + +## Reserve Code Generation for Stack Configuration + +While we generally advise against using code generation for application logic (components), it's beneficial for +creating configurations where appropriate, such as developer environments and SaaS tenants. +These configurations ought to be committed. + +Also, consider if you can [use templates](/core-concepts/stacks/templates) instead. + +## Use Mixin Pattern for Snippets of Stack Configuration + +Employ the [mixin pattern](/core-concepts/stacks/inheritance/mixins) for clarity when there there is brief configuration snippets that are reusable. Steer clear +of minimal stack configurations simply for the sake of DRYness as it frequently leads to too many levels of imports. + +## Use YAML Anchors to DRY Configuration + +YAML anchors are pretty sweet and you don’t get those with tfvars. + +:::important YAML Anchors Gotchas +When you define [YAML anchors](https://yaml.org/spec/1.2.2/#3222-anchors-and-aliases), they can only be used within the scope of the +same file. This is not an Atmos limitation, but how YAML works. For example, do not work together with [imports](/core-concepts/stacks/imports), +where you define an anchor in one stack configuration and try to use it in another. +::: + + +## Enforce Standards using OPA Policies + +Apply OPA or JSON Schema validation within stacks to establish policies governing component usage. These policies can be tailored +as needed, allowing the same component to be validated differently depending on its context of use. diff --git a/website/docs/best-practices/terraform.mdx b/website/docs/best-practices/terraform.mdx new file mode 100644 index 000000000..e8c6c92e4 --- /dev/null +++ b/website/docs/best-practices/terraform.mdx @@ -0,0 +1,54 @@ +--- +title: Terraform Best Practices with Atmos +sidebar_position: 1 +sidebar_label: Terraform +description: Learn the opinionated "Best Practices" for using Terraform with Atmos +id: terraform +--- +import Intro from '@site/src/components/Intro' + + +These are some of the best practices we recommend when using Terraform with Atmos. They are opinionated and based on our experience working with Terraform and Atmos. When followed, they lead to more reusable and maintainable infrastructure as code. + + +> Physics is the law, everything else is a recommendation. +> Anyone can break laws created by people, but I have yet to see anyone break the laws of physics. +>

— **Elon Musk**

+ +Also, since [Terraform "root modules" are components](/core-concepts/components/terraform), be sure to review the [Component Best Practices](/best-practices/components) for additional guidance on using components with Atmos. + +:::tip +[Cloud Posse](https://github.com/cloudposse) publishes their general [Terraform Best Practices](https://docs.cloudposse.com/reference/best-practices/terraform-best-practices/), which are more general and not specific to Atmos. +::: + +## Never Include Components Inside of Other Components + +We do not recommend consuming one terraform component inside of another as that would defeat the purpose; each component is intended to be a loosely coupled unit of IaC with its own lifecycle. + +Furthermore, since components define a state backend and providers, it's not advisable to call one root module from another root module. As only the stack backend of the first root module will be used, leading to unpredictable results. + + +## Use Terraform Overrides to Extend ("Monkey Patch") Vendored Components + +When you need to extend a component, we recommend using [Terraform Overrides](https://www.terraform.io/docs/language/modules/develop/override.html) with [Vendoring](https://www.terraform.io/docs/language/modules/develop/override.html#vendoring) to extend the component. +It's essentially a Terraform-native way of [Monkey Patching](https://en.wikipedia.org/wiki/Monkey_patch). This way, you can maintain the original component as a dependency and only override the parts you need to change. + +:::warning Pitfall! +Use this technique cautiously because your overrides may break if the upstream interfaces change. There’s no contract that an upstream component will remain the same. +::: + +To gain a deeper understanding of how this works, you have to understand how [Terarform overrides work](https://developer.hashicorp.com/terraform/language/files/override), and then it will make sense how [vendoring with Atmos](/core-concepts/vendor) can be used to extend components. + +
+Comparison to Other Languages or Frameworks + +#### Swizzling + +In [Objective-C](https://spin.atomicobject.com/method-swizzling-objective-c/) and [Swift-UI](https://medium.com/@pallavidipke07/method-swizzling-in-swift-5c9d9ab008e4), swizzling is the method of changing the implementation of an existing selector. + +In Docusaurus, [swizzling a component](https://docusaurus.io/docs/swizzling) means providing an alternative implementation that takes precedence over the component provided by the theme. + +#### Monkey Patching + +You can think of it also like [Monkey Patching](https://en.wikipedia.org/wiki/Monkey_patch) in [Ruby](http://blog.headius.com/2012/11/refining-ruby.html) or [React components](https://medium.com/@singhalaryan06/monkey-patching-mocking-hooks-and-methods-in-react-f6afef73e423), enabling you to override the default implementation. Gatsby has a similar concept called theme [shadowing](https://www.gatsbyjs.com/docs/how-to/plugins-and-themes/shadowing/). +
diff --git a/website/docs/cli/cheatsheet.mdx b/website/docs/cheatsheets/commands.mdx similarity index 99% rename from website/docs/cli/cheatsheet.mdx rename to website/docs/cheatsheets/commands.mdx index 211cb233b..0128c5567 100644 --- a/website/docs/cli/cheatsheet.mdx +++ b/website/docs/cheatsheets/commands.mdx @@ -1,7 +1,7 @@ --- title: CLI Commands Cheat Sheet sidebar_position: 2 -sidebar_label: Cheat Sheet +sidebar_label: All Commands description: CLI Commands Cheat Sheet --- import Link from '@docusaurus/Link' diff --git a/website/docs/introduction/cheatsheet.mdx b/website/docs/cheatsheets/common.mdx similarity index 98% rename from website/docs/introduction/cheatsheet.mdx rename to website/docs/cheatsheets/common.mdx index baf94bc46..f7a2a7b73 100644 --- a/website/docs/introduction/cheatsheet.mdx +++ b/website/docs/cheatsheets/common.mdx @@ -1,9 +1,9 @@ --- -id: cheatsheet +id: common slug: /cheatsheet title: Atmos Cheatsheet -sidebar_label: Cheatsheet -sidebar_position: 2 +sidebar_label: Overview +sidebar_position: 1 --- import Link from '@docusaurus/Link' import Card from '@site/src/components/Card' diff --git a/website/docs/core-concepts/components/component-cheatsheet.mdx b/website/docs/cheatsheets/components.mdx similarity index 71% rename from website/docs/core-concepts/components/component-cheatsheet.mdx rename to website/docs/cheatsheets/components.mdx index 2baa84f66..bf4d96cdc 100644 --- a/website/docs/core-concepts/components/component-cheatsheet.mdx +++ b/website/docs/cheatsheets/components.mdx @@ -1,7 +1,8 @@ --- -id: cheatsheet -title: Component Cheatsheet -sidebar_label: Cheatsheet +id: components +title: Components Cheatsheet +descriptions: Cheatsheet for managing components in Atmos +sidebar_label: Using Components sidebar_position: 2 --- import Link from '@docusaurus/Link' @@ -26,43 +27,6 @@ import CardGroup from '@site/src/components/CardGroup' └── staging.yaml ``` - - ```yaml - import: - - catalog/something - vars: - key: value - components: - terraform: - $component: - vars: - foo: "bar" - ``` - - - - ```yaml - terraform: - overrides: - env: {} - settings: {} - vars: {} - command: "opentofu" - ``` - - - ```yaml - terraform: - components: - $component: - settings: - spacelift: - # The `autodeploy` setting was overridden with the value - # from `terraform.overrides.settings.spacelift.autodeploy` - autodeploy: true - workspace_enabled: true - ``` - @@ -104,4 +68,3 @@ import CardGroup from '@site/src/components/CardGroup' ``` - diff --git a/website/docs/cheatsheets/stacks.mdx b/website/docs/cheatsheets/stacks.mdx new file mode 100644 index 000000000..37a6876ff --- /dev/null +++ b/website/docs/cheatsheets/stacks.mdx @@ -0,0 +1,84 @@ +--- +id: stacks +title: Stacks Cheatsheet +descriptions: Cheatsheet for configuring components in stacks with Atmos +sidebar_label: Stack Configurations +sidebar_position: 3 +--- +import Link from '@docusaurus/Link' +import Card from '@site/src/components/Card' +import CardGroup from '@site/src/components/CardGroup' + + + + ``` + ├── atmos.yaml + ├── components + │   └── myapp + │   ├── main.tf + │   ├── outputs.tf + │   └── variables.tf + └── stacks + ├── catalog + │   └── myapp.yaml + └── deploy + ├── dev.yaml + ├── prod.yaml + └── staging.yaml + ``` + + + ```yaml + import: + - catalog/something + vars: + key: value + components: + terraform: + $component: + vars: + foo: "bar" + ``` + + + + ```yaml + terraform: + overrides: + env: {} + settings: {} + vars: {} + command: "opentofu" + ``` + + + ```yaml + terraform: + components: + $component: + settings: + spacelift: + # The `autodeploy` setting was overridden with the value + # from `terraform.overrides.settings.spacelift.autodeploy` + autodeploy: true + workspace_enabled: true + ``` + + + + + + ```shell + atmos list components + ``` + + + ```shell + atmos validate component $component -s $stack + atmos validate component $component -s $stack --schema-type jsonschema --schema-path $component.json + atmos validate component $component -s $stack --schema-type opa --schema-path $component.rego + atmos validate component $component -s $stack --schema-type opa --schema-path $component.rego --module-paths catalog + atmos validate component $component -s $stack --timeout 15 + ``` + + diff --git a/website/docs/core-concepts/vendoring/cheatsheet.mdx b/website/docs/cheatsheets/vendoring.mdx similarity index 96% rename from website/docs/core-concepts/vendoring/cheatsheet.mdx rename to website/docs/cheatsheets/vendoring.mdx index f5ff7cb7b..cecd1554f 100644 --- a/website/docs/core-concepts/vendoring/cheatsheet.mdx +++ b/website/docs/cheatsheets/vendoring.mdx @@ -1,8 +1,8 @@ --- -id: cheatsheet +id: vendoring title: Vendoring Cheatsheet -sidebar_label: Cheatsheet -sidebar_position: 2 +sidebar_label: Vendoring Components +sidebar_position: 4 --- import Card from '@site/src/components/Card' diff --git a/website/docs/cli/cli.mdx b/website/docs/cli/cli.mdx index a5765f972..e96219d38 100644 --- a/website/docs/cli/cli.mdx +++ b/website/docs/cli/cli.mdx @@ -10,7 +10,7 @@ import Screengrab from '@site/src/components/Screengrab' import Terminal from '@site/src/components/Terminal' :::note Purpose -Use this command to start an interactive UI to select an Atmos command, component and stack. Press `Enter` to execute the command for the selected +Use this command to start an interactive UI to run Atmos commands against any component or stack. Press `Enter` to execute the command for the selected stack and component ::: diff --git a/website/docs/cli/commands/atlantis/atlantis-generate-repo-config.mdx b/website/docs/cli/commands/atlantis/atlantis-generate-repo-config.mdx index c1dc5b785..f4a98069c 100644 --- a/website/docs/cli/commands/atlantis/atlantis-generate-repo-config.mdx +++ b/website/docs/cli/commands/atlantis/atlantis-generate-repo-config.mdx @@ -5,26 +5,19 @@ sidebar_class_name: command id: generate-repo-config description: Use this command to generate a repository configuration for Atlantis. --- - import Screengrab from '@site/src/components/Screengrab' +import Intro from '@site/src/components/Intro' -:::info Purpose -Use this command to generate a repository configuration for Atlantis. -::: - -
+ +Use this command to generate a repository configuration (`atlantis.yaml`) for Atlantis. + -
-
- ```shell atmos atlantis generate repo-config [options] ``` -
- :::tip Run `atmos atlantis generate repo-config --help` to see all the available options ::: @@ -87,8 +80,6 @@ atmos atlantis generate repo-config --affected-only=true --clone-target-ref=true | `--verbose` | Print more detailed output when cloning and checking out the target
Git repository and processing the result | no | | `--clone-target-ref` | Clone the target reference with which to compare the current branch.
`atmos atlantis generate repo-config --affected-only=true --clone-target-ref=true`

The flag is only used when `--affected-only=true`

If set to `false` (default), the target reference will be checked out instead
This requires that the target reference is already cloned by Git,
and the information about it exists in the `.git` directory | no | -
- :::info Refer to [Atlantis Integration](/integrations/atlantis) for more details on the Atlantis integration in Atmos diff --git a/website/docs/cli/commands/atlantis/usage.mdx b/website/docs/cli/commands/atlantis/usage.mdx index 2950f7d1d..9d71ed59e 100644 --- a/website/docs/cli/commands/atlantis/usage.mdx +++ b/website/docs/cli/commands/atlantis/usage.mdx @@ -7,10 +7,11 @@ description: Atmos Atlantis Commands import DocCardList from '@theme/DocCardList'; import Screengrab from '@site/src/components/Screengrab' +import Intro from '@site/src/components/Intro' -:::note Purpose -Use the subcommands to execute Atlantis commands. -::: + +Use these subcommands to execute commands that generate Atlantis configurations. + ## Usage diff --git a/website/docs/cli/commands/aws/aws-eks-update-kubeconfig.mdx b/website/docs/cli/commands/aws/aws-eks-update-kubeconfig.mdx index cafdd0c6d..df7b1e0d6 100644 --- a/website/docs/cli/commands/aws/aws-eks-update-kubeconfig.mdx +++ b/website/docs/cli/commands/aws/aws-eks-update-kubeconfig.mdx @@ -6,17 +6,14 @@ id: eks-update-kubeconfig description: Use this command to download `kubeconfig` from an EKS cluster and saves it to a file. --- import Screengrab from '@site/src/components/Screengrab' +import Intro from '@site/src/components/Intro' -:::info Purpose + Use this command to download `kubeconfig` from an EKS cluster and save it to a file. -::: - -
+
-
- ```shell atmos aws eks update-kubeconfig [options] ``` @@ -56,8 +53,6 @@ For example: atmos aws eks update-kubeconfig -s --kubeconfig= --region=us-east-1 ``` -
- :::info Refer to [Update kubeconfig](https://docs.aws.amazon.com/cli/latest/reference/eks/update-kubeconfig.html) for more information ::: diff --git a/website/docs/cli/commands/commands.mdx b/website/docs/cli/commands/commands.mdx index ba73797b8..7bd0ccf99 100644 --- a/website/docs/cli/commands/commands.mdx +++ b/website/docs/cli/commands/commands.mdx @@ -2,6 +2,7 @@ title: Atmos CLI Commands sidebar_position: 3 sidebar_label: Commands +sidebar_class_name: hidden description: Atmos CLI Commands id: commands label: Commands @@ -9,14 +10,12 @@ collapsible: true collapsed: false --- import Screengrab from '@site/src/components/Screengrab' -import DocCardList from "@theme/DocCardList"; +import DocCardList from '@theme/DocCardList' :::note Purpose Use these commands to perform operations. ::: -
- # Commands diff --git a/website/docs/cli/commands/completion.mdx b/website/docs/cli/commands/completion.mdx index c84eab314..9909eaf72 100644 --- a/website/docs/cli/commands/completion.mdx +++ b/website/docs/cli/commands/completion.mdx @@ -10,8 +10,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to generate completion scripts for `Bash`, `Zsh`, `Fish` and `PowerShell`. ::: -
- ## Usage @@ -26,14 +24,10 @@ This command generates completion scripts for `Bash`, `Zsh`, `Fish` and `powersh When the generated completion script is loaded into the shell, pressing the tab key twice displays the available commands and the help. -
- :::tip Run `atmos completion --help` to see all the available options ::: -
- ### Examples ```shell @@ -62,8 +56,6 @@ source <(atmos completion bash) |:--------------|:--------------------------------------------------------------------|:---------| | `shell_name ` | Shell name. Valid values are `bash`, `zsh`, `fish` and `powershell` | yes | -
- :::info Refer to [Command-line completion](https://en.wikipedia.org/wiki/Command-line_completion) for more details ::: diff --git a/website/docs/cli/commands/describe/describe-affected.mdx b/website/docs/cli/commands/describe/describe-affected.mdx index 0c40468c9..aa411de88 100644 --- a/website/docs/cli/commands/describe/describe-affected.mdx +++ b/website/docs/cli/commands/describe/describe-affected.mdx @@ -13,8 +13,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to show a list of the affected Atmos components and stacks given two Git commits. ::: -
- ## Description @@ -74,23 +72,17 @@ The command performs the following: Since Atmos first checks the component folders for changes, if it finds any affected files, it will mark all related components and stacks as affected. Atmos will then skip evaluating the stacks for differences since it already knows that they are affected. - -
:::tip Use our GitHub Action Our [affected stacks](/integrations/github-actions/affected-stacks) GitHub Action provides a ready-to-go way to run `describe affected` and produce a GitHub matrix. ::: -
- ## Usage ```shell atmos describe affected [options] ``` -
- :::tip Run `atmos describe affected --help` to see all the available options ::: @@ -361,7 +353,6 @@ where: } ] ``` -
- `stack.settings.spacelift.admin_stack_selector` - the Atmos component for the Spacelift admin stack. This will be included only if all the following is true: @@ -476,8 +467,6 @@ where: ] ``` -
- :::note Abstract Atmos components (where `metadata.type` is set to `abstract`) are not included in the output since they serve @@ -563,8 +552,6 @@ as blueprints for other Atmos components and are not meant to be provisioned. ``` -
- ## Affected Components with Dependencies The output of the `atmos describe affected` command can include dependencies for the affected components. @@ -606,21 +593,15 @@ For example, suppose that we have the following configuration for the Atmos comp ``` -
- :::tip For more details on how to configure component dependencies, refer to [`atmos describe dependents`](/cli/commands/describe/dependents) ::: -
- In the above configuration, `component-3` depends on `component-2`, whereas `component-2` depends on `component-1`. If all the components are affected (modified) in the current working branch, the `atmos describe affected --include-dependents=true` command will produce the following result: -
- ```json [ @@ -667,8 +648,6 @@ the `atmos describe affected --include-dependents=true` command will produce the ``` -
- The `component-1` component does not depend on any other component, and therefore it has the `included_in_dependents` attribute set to `false`. The `component-2` and `component-3` components depend on other components and are included in the `dependents` property of the other components, and hence the `included_in_dependents` attribute is set to `true`. diff --git a/website/docs/cli/commands/describe/describe-component.mdx b/website/docs/cli/commands/describe/describe-component.mdx index 01cb3fa68..4287a7635 100644 --- a/website/docs/cli/commands/describe/describe-component.mdx +++ b/website/docs/cli/commands/describe/describe-component.mdx @@ -13,8 +13,6 @@ Use this command to describe the complete configuration for an [Atmos component] an [Atmos stack](/core-concepts/stacks). ::: -
- ## Usage @@ -25,8 +23,6 @@ Execute the `atmos describe component` command like this: atmos describe component -s ``` -
- :::tip Run `atmos describe component --help` to see all the available options ::: @@ -102,7 +98,7 @@ The output contains the following sections: - `env` - a map of ENV variables defined for the Atmos component -- `inheritance` - component's [inheritance chain](/core-concepts/components/inheritance) +- `inheritance` - component's [inheritance chain](/core-concepts/stacks/inheritance) - `metadata` - component's metadata config @@ -129,7 +125,7 @@ The output contains the following sections: - `deps` - a list of component stack dependencies where the _final_ values of all component configurations are defined (after the deep-merging and processing all the inheritance chains and all the base components) -- `overrides` - a map of overrides for the component. Refer to [Component Overrides](/core-concepts/components/overrides) for more details +- `overrides` - a map of overrides for the component. Refer to [Component Overrides](/core-concepts/stacks/overrides) for more details - `providers` - a map of provider configurations for the component @@ -137,23 +133,23 @@ The output contains the following sections: The difference between the `imports`, `deps_all` and `deps` outputs is as follows: -- `imports` shows all imports in the stack for all components. This can be useful in GitHub actions and - in [OPA validation policies](/core-concepts/components/validation) to check whether an import is allowed in the stack or not +- `imports` shows all imports in the stack for all components. This can be useful in GitHub actions and + in [OPA validation policies](/core-concepts/validate/opa) to check whether an import is allowed in the stack or not - `deps_all` shows all component stack dependencies (imports and root-level stacks) where any configuration for the component is present. - This also can be useful in GitHub Actions and [OPA validation policies](/core-concepts/components/validation) to check whether a user or a team + This also can be useful in GitHub Actions and [OPA validation policies](/core-concepts/validate/opa) to check whether a user or a team is allowed to import a particular config file for the component in the stack - `deps` shows all the component stack dependencies where the __FINAL__ values from all the component sections are defined (after the deep-merging and processing all the inheritance chains and all the base components). This is useful in CI/CD systems (e.g. Spacelift) - to detect only the affected files that the component depends on. `deps` is usually a much smaller list than `deps_all` and can + to detect only the affected files that the component depends on. `deps` is usually a much smaller list than `deps_all` and can differ from it in the following ways: - - An Atmos component can inherit configurations from many base components, see [Component Inheritance](/core-concepts/components/inheritance), and + - An Atmos component can inherit configurations from many base components, see [Component Inheritance](/core-concepts/stacks/inheritance), and import those base component configurations - - The component can override all the default variables from the base components, and the final values are not dependent on the base component - configs anymore. For example, `derived-component-3` import the base component `base-component-4`, inherits from it, and overrides all + - The component can override all the default variables from the base components, and the final values are not dependent on the base component + configs anymore. For example, `derived-component-3` import the base component `base-component-4`, inherits from it, and overrides all the variables: ```yaml @@ -173,8 +169,8 @@ The difference between the `imports`, `deps_all` and `deps` outputs is as follow # Override all the variables from the base component ``` - - Atmos detects that and does not include the base component `base-component-4` config file into the `deps` output since the `derived-component-3` - does not directly depend on `base-component-4` (all values are coming from the `derived-component-3`). This will help, for example, + - Atmos detects that and does not include the base component `base-component-4` config file into the `deps` output since the `derived-component-3` + does not directly depend on `base-component-4` (all values are coming from the `derived-component-3`). This will help, for example, prevent unrelated Spacelift stack triggering - In the above case, the `deps_all` output will include both `derived-component-3` and `base-component-4`, but the `deps` output will not include @@ -494,8 +490,6 @@ Each variable descriptor has the following schema: - `dependency_type` - how the variable was defined (`inline` or `import`). `inline` means the variable was defined in one of the sections in the stack manifest. `import` means the stack manifest where the variable is defined was imported into the parent Atmos stack -
- For example: @@ -603,8 +597,6 @@ sources: ``` -
- :::info The `stack_dependencies` inheritance chain shows the variable sources in the reverse order the sources were processed. @@ -612,8 +604,6 @@ The first item in the list was processed the last and its `variable_value` overr ::: -
- For example, the component's `enabled` variable has the following inheritance chain: ```yaml @@ -637,8 +627,6 @@ sources: variable_value: true ``` -
- Which we can interpret as follows (reading from the last to the first item in the `stack_dependencies` list): - In the `orgs/cp/tenant1/dev/us-east-2` stack manifest (the last item in the list), the value for `enabled` was set to `true` in the global `vars` @@ -670,8 +658,6 @@ Each variable descriptor has the following schema: - `dependency_type` - how the variable was defined (`inline` or `import`). `inline` means the variable was defined in one of the sections in the stack manifest. `import` means the stack manifest where the variable is defined was imported into the parent Atmos stack -
- For example: @@ -733,8 +719,6 @@ sources: ``` -
- :::info The `stack_dependencies` inheritance chain shows the ENV variable sources in the reverse order the sources were processed. @@ -742,8 +726,6 @@ The first item in the list was processed the last and its `variable_value` overr ::: -
- For example, the component's `TEST_ENV_VAR1` ENV variable has the following inheritance chain: ```yaml @@ -771,8 +753,6 @@ sources: variable_value: val1 ``` -
- Which we can interpret as follows (reading from the last to the first item in the `stack_dependencies` list): - In the `catalog/terraform/test-component` stack manifest (the last item in the list), the value for the `TEST_ENV_VAR1` ENV variable was set @@ -806,8 +786,6 @@ Each setting descriptor has the following schema: - `dependency_type` - how the setting was defined (`inline` or `import`). `inline` means the setting was defined in one of the sections in the stack manifest. `import` means the stack config file where the setting is defined was imported into the parent Atmos stack -
- For example: @@ -848,8 +826,6 @@ sources: ``` -
- :::info The `stack_dependencies` inheritance chain shows the sources of the setting in the reverse order the sources were processed. diff --git a/website/docs/cli/commands/describe/describe-config.mdx b/website/docs/cli/commands/describe/describe-config.mdx index 86a7f1c99..a75e7b204 100644 --- a/website/docs/cli/commands/describe/describe-config.mdx +++ b/website/docs/cli/commands/describe/describe-config.mdx @@ -12,11 +12,9 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to show the final (deep-merged) [CLI configuration](/cli/configuration) of all `atmos.yaml` file(s). ::: -
- -## Usage +## Usage Execute the `describe config` command like this: diff --git a/website/docs/cli/commands/describe/describe-dependents.mdx b/website/docs/cli/commands/describe/describe-dependents.mdx index c8a504e98..15ce456ee 100644 --- a/website/docs/cli/commands/describe/describe-dependents.mdx +++ b/website/docs/cli/commands/describe/describe-dependents.mdx @@ -12,13 +12,11 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to show a list of Atmos components in Atmos stacks that depend on the provided Atmos component. ::: -
- ## Description -In Atmos, you can define component dependencies by using the `settings.depends_on` section. The section used to define +In Atmos, you can define component dependencies by using the `settings.depends_on` section. The section used to define all the Atmos components (in the same or different stacks) that the current component depends on. The `settings.depends_on` section is a map of objects. The map keys are just the descriptions of dependencies and can be strings or numbers. @@ -34,8 +32,6 @@ Each object in the `settings.depends_on` section has the following schema: - `environment` (optional) - the `environment` where the `component` is provisioned - `stage` (optional) - the `stage` where the `component` is provisioned -
- One of `component`, `file` or `folder` is required. Dependencies on external files (not in the component's folder) are defined using the `file` attribute. For example: @@ -83,8 +79,6 @@ For example, you can specify: - `stage` if the `component` is from a different account - `tenant`, `environment` and `stage` if the component is from a different Atmos stack (e.g. `tenant1-ue2-dev`) -
- In the following example, we define that the `top-level-component1` component depends on the following: - The `test/test-component-override` component in the same Atmos stack @@ -143,8 +137,6 @@ components: enabled: true ``` -
- Having the `top-level-component` and `top-level-component2` components configured as shown above, we can now execute the following Atmos command to show all the components that depend on the `test/test-component` component in the `tenant1-ue2-dev` stack: @@ -204,8 +196,6 @@ the `tenant1-ue2-test-1` stack: ``` -
- After the `test/test-component` has been provisioned, you can use the outputs to perform the following actions: - Provision the dependent components by executing the Atmos commands `atmos terraform apply top-level-component1 -s tenant1-ue2-test-1` and @@ -224,8 +214,6 @@ After the `test/test-component` has been provisioned, you can use the outputs to atmos describe dependents [options] ``` -
- :::tip Run `atmos describe dependents --help` to see all the available options ::: @@ -303,8 +291,6 @@ where: - `atlantis_project` - the dependent Atlantis project name. It will be included only if the Atlantis integration is configured in the `settings.atlantis` section in the stack manifest. Refer to [Atlantis Integration](/integrations/atlantis) for more details -
- :::note Abstract Atmos components (`metadata.type` is set to `abstract`) are not included in the output since they serve as blueprints for other diff --git a/website/docs/cli/commands/describe/describe-stacks.mdx b/website/docs/cli/commands/describe/describe-stacks.mdx index d03d4b41f..6980def95 100644 --- a/website/docs/cli/commands/describe/describe-stacks.mdx +++ b/website/docs/cli/commands/describe/describe-stacks.mdx @@ -12,8 +12,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to show the fully deep-merged configuration for all stacks and the components in the stacks. ::: -
- ## Usage diff --git a/website/docs/cli/commands/describe/describe-workflows.mdx b/website/docs/cli/commands/describe/describe-workflows.mdx index a97ae8517..4e0c82d82 100644 --- a/website/docs/cli/commands/describe/describe-workflows.mdx +++ b/website/docs/cli/commands/describe/describe-workflows.mdx @@ -12,8 +12,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to show all configured Atmos workflows. ::: -
- ## Usage @@ -24,8 +22,6 @@ Execute the `describe workflows` command like this: atmos describe workflows [options] ``` -
- :::tip Run `atmos describe workflows --help` to see all the available options ::: @@ -49,8 +45,6 @@ atmos describe workflows -f json | `--format` | Specify the output format: `yaml` or `json` (`yaml` is default) | `-f` | no | | `--output` | Specify the output type: `list`, `map` or `all` (`list` is default) | `-o` | no | -
- When the `--output list` flag is passed (default), the output of the command is a list of objects. Each object has the following schema: @@ -85,8 +79,6 @@ atmos describe workflows -o list workflow: plan-all-vpc-flow-logs ``` -
- When the `--output map` flag is passed, the output of the command is a map of workflow manifests to the lists of workflows defined in each manifest. For example: @@ -111,8 +103,6 @@ networking.yaml: - plan-all-vpc-flow-logs ``` -
- When the `--output all` flag is passed, the output of the command is a map of workflow manifests to the maps of all workflow definitions. For example: @@ -185,8 +175,6 @@ validation.yaml: - command: validate component vpc-flow-logs-bucket -s plat-uw2-prod ``` -
- :::tip Use the [atmos workflow](/cli/commands/workflow) CLI command to execute an Atmos workflow ::: diff --git a/website/docs/cli/commands/docs.mdx b/website/docs/cli/commands/docs.mdx index f89af3f42..60158038c 100644 --- a/website/docs/cli/commands/docs.mdx +++ b/website/docs/cli/commands/docs.mdx @@ -10,8 +10,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to open the [Atmos docs](https://atmos.tools/) ::: -
- ## Usage diff --git a/website/docs/cli/commands/helmfile/helmfile-generate-varfile.mdx b/website/docs/cli/commands/helmfile/helmfile-generate-varfile.mdx index accb99ee0..6cbc3b547 100644 --- a/website/docs/cli/commands/helmfile/helmfile-generate-varfile.mdx +++ b/website/docs/cli/commands/helmfile/helmfile-generate-varfile.mdx @@ -12,8 +12,6 @@ import Terminal from '@site/src/components/Terminal' Use this command to generate a varfile for a `helmfile` component in a stack. ::: -
- ## Usage diff --git a/website/docs/cli/commands/helmfile/usage.mdx b/website/docs/cli/commands/helmfile/usage.mdx index 9165f8be0..c36df0991 100644 --- a/website/docs/cli/commands/helmfile/usage.mdx +++ b/website/docs/cli/commands/helmfile/usage.mdx @@ -11,8 +11,6 @@ import DocCardList from '@theme/DocCardList'; Use these subcommands to run `helmfile` commands. ::: -
- # Usage @@ -26,16 +24,12 @@ atmos helmfile -s [options] atmos helmfile --stack [options] ``` -
- :::info Atmos supports all `helmfile` commands and options described in [Helmfile CLI reference](https://github.com/helmfile/helmfile#cli-reference). In addition, the `component` argument and `stack` flag are required to generate variables for the component in the stack. ::: -
- **Additions and differences from native `helmfile`:** - `atmos helmfile generate varfile` command generates a varfile for the component in the stack @@ -49,8 +43,6 @@ In addition, the `component` argument and `stack` flag are required to generate - double-dash `--` can be used to signify the end of the options for Atmos and the start of the additional native arguments and flags for the `helmfile` commands. -
- :::tip Run `atmos helmfile --help` to see all the available options ::: @@ -85,8 +77,6 @@ atmos helmfile destroy echo-server --stack=tenant1-ue2-dev --redirect-stderr /de | `--dry-run` | Dry run | | no | | `--redirect-stderr` | File descriptor to redirect `stderr` to.
Errors can be redirected to any file or any standard file descriptor
(including `/dev/null`) | | no | -
- :::note All native `helmfile` flags, command options, and arguments are supported diff --git a/website/docs/cli/commands/help.mdx b/website/docs/cli/commands/help.mdx index 012ac2177..fcbc1c2e3 100644 --- a/website/docs/cli/commands/help.mdx +++ b/website/docs/cli/commands/help.mdx @@ -7,8 +7,6 @@ order: 10 import Screengrab from '@site/src/components/Screengrab' import Terminal from '@site/src/components/Terminal' -
- ## Usage diff --git a/website/docs/cli/commands/terraform/_category_.json b/website/docs/cli/commands/terraform/_category_.json index c352fcf53..6a2bc28ed 100644 --- a/website/docs/cli/commands/terraform/_category_.json +++ b/website/docs/cli/commands/terraform/_category_.json @@ -3,7 +3,7 @@ "position": 6, "className": "command", "collapsible": true, - "collapsed": false, + "collapsed": true, "link": { "type": "doc", "id": "usage" diff --git a/website/docs/cli/commands/terraform/terraform-clean.mdx b/website/docs/cli/commands/terraform/terraform-clean.mdx index 062225b17..5b7937bea 100644 --- a/website/docs/cli/commands/terraform/terraform-clean.mdx +++ b/website/docs/cli/commands/terraform/terraform-clean.mdx @@ -13,8 +13,6 @@ and `planfile` for a component in a stack. ::: -
- ## Usage diff --git a/website/docs/cli/commands/terraform/terraform-deploy.mdx b/website/docs/cli/commands/terraform/terraform-deploy.mdx index 4f8293e42..8eb8181b6 100644 --- a/website/docs/cli/commands/terraform/terraform-deploy.mdx +++ b/website/docs/cli/commands/terraform/terraform-deploy.mdx @@ -11,8 +11,6 @@ import Terminal from '@site/src/components/Terminal' Use this command to execute `terraform apply -auto-approve` on an Atmos component in an Atmos stack. ::: -
- ## Usage @@ -39,8 +37,6 @@ atmos terraform deploy -s See [all flags](#flags). -
- :::tip Run `atmos terraform deploy --help` to see all the available options ::: @@ -96,8 +92,6 @@ atmos terraform deploy test/test-component-override-3 -s tenant1-ue2-dev | `--from-plan` | If the flag is specified, use the `planfile` previously generated by Atmos instead of
generating a new `planfile`. The planfile name is in the format supported by Atmos
and is saved to the component's folder | | no | | `--planfile` | The path to a planfile. The `--planfile` flag should be used instead of the planfile
argument in the native `terraform apply ` command | | no | -
- :::note The `atmos terraform deploy` command supports all native `terraform apply` options described diff --git a/website/docs/cli/commands/terraform/terraform-generate-backend.mdx b/website/docs/cli/commands/terraform/terraform-generate-backend.mdx index 565a2608d..a2f9e9b2e 100644 --- a/website/docs/cli/commands/terraform/terraform-generate-backend.mdx +++ b/website/docs/cli/commands/terraform/terraform-generate-backend.mdx @@ -12,8 +12,6 @@ import Terminal from '@site/src/components/Terminal' Use this command to generate a Terraform backend config file for an Atmos terraform component in a stack. ::: -
- ## Usage @@ -52,8 +50,6 @@ atmos terraform generate backend test/test-component-override-2 -s tenant2-ue2-p | `--stack` | Atmos stack | `-s` | yes | | `--dry-run` | Dry run | | no | -
- :::info Refer to [Terraform backend configuration](https://developer.hashicorp.com/terraform/language/settings/backends/configuration) for more details on `terraform` backends and supported formats diff --git a/website/docs/cli/commands/terraform/terraform-generate-backends.mdx b/website/docs/cli/commands/terraform/terraform-generate-backends.mdx index 122da09b5..72f57506b 100644 --- a/website/docs/cli/commands/terraform/terraform-generate-backends.mdx +++ b/website/docs/cli/commands/terraform/terraform-generate-backends.mdx @@ -13,8 +13,6 @@ Use this command to generate the Terraform backend config files for all Atmos te all [stacks](/core-concepts/stacks). ::: -
- ## Usage @@ -59,8 +57,6 @@ atmos terraform generate backends --format backend-config --file-template - :::info Refer to [Terraform backend configuration](https://developer.hashicorp.com/terraform/language/settings/backends/configuration) for more details diff --git a/website/docs/cli/commands/terraform/terraform-generate-varfile.mdx b/website/docs/cli/commands/terraform/terraform-generate-varfile.mdx index 95e0b62e8..270a921f3 100644 --- a/website/docs/cli/commands/terraform/terraform-generate-varfile.mdx +++ b/website/docs/cli/commands/terraform/terraform-generate-varfile.mdx @@ -10,8 +10,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to generate a varfile (`.tfvar` ) for an Atmos terraform [component](/core-concepts/components) in a [stack](/core-concepts/stacks). ::: -
- ## Usage diff --git a/website/docs/cli/commands/terraform/terraform-generate-varfiles.mdx b/website/docs/cli/commands/terraform/terraform-generate-varfiles.mdx index 37a8c5b4d..f9f716c97 100644 --- a/website/docs/cli/commands/terraform/terraform-generate-varfiles.mdx +++ b/website/docs/cli/commands/terraform/terraform-generate-varfiles.mdx @@ -13,8 +13,6 @@ Use this command to generate the Terraform varfiles (`.tfvar`) for all Atmos ter all [stacks](/core-concepts/stacks). ::: -
- ## Usage diff --git a/website/docs/cli/commands/terraform/terraform-shell.mdx b/website/docs/cli/commands/terraform/terraform-shell.mdx index 506d27942..7fe8d7609 100644 --- a/website/docs/cli/commands/terraform/terraform-shell.mdx +++ b/website/docs/cli/commands/terraform/terraform-shell.mdx @@ -12,8 +12,6 @@ This command starts a new `SHELL` configured with the environment for an Atmos c inside the shell without using any atmos-specific arguments and flags. ::: -
- ## Usage @@ -41,8 +39,6 @@ The command does the following: - Inside the shell, the user can execute all `terraform` commands using the native syntax -
- :::tip Run `atmos terraform shell --help` to see all the available options ::: diff --git a/website/docs/cli/commands/terraform/terraform-workspace.mdx b/website/docs/cli/commands/terraform/terraform-workspace.mdx index a13b809b9..09d32fe7c 100644 --- a/website/docs/cli/commands/terraform/terraform-workspace.mdx +++ b/website/docs/cli/commands/terraform/terraform-workspace.mdx @@ -12,8 +12,6 @@ Use this command to calculate the `terraform` workspace for an Atmos component ( run `terraform init -reconfigure` and then select the workspace by executing the `terraform workspace select` command. ::: -
- ## Usage @@ -29,8 +27,6 @@ runs `terraform init -reconfigure`, then selects the workspace by executing the If the workspace does not exist, the command creates it by executing the `terraform workspace new` command. -
- :::tip Run `atmos terraform workspace --help` to see all the available options ::: diff --git a/website/docs/cli/commands/terraform/usage.mdx b/website/docs/cli/commands/terraform/usage.mdx index 58338d18a..096909fee 100644 --- a/website/docs/cli/commands/terraform/usage.mdx +++ b/website/docs/cli/commands/terraform/usage.mdx @@ -4,14 +4,12 @@ sidebar_label: terraform sidebar_class_name: command --- import Screengrab from '@site/src/components/Screengrab' -import DocCardList from "@theme/DocCardList"; +import DocCardList from '@theme/DocCardList' :::note Purpose Use these subcommands to interact with `terraform`. ::: -
- # Usage @@ -25,10 +23,13 @@ atmos terraform --stack [options]
-:::info Atmos supports all `terraform` commands and options described in [Terraform CLI reference](https://www.terraform.io/cli/commands). In addition, the `component` argument and `stack` flag are required to generate variables and backend config for the component in the stack. + +:::note Disambiguation +The term “Terraform” is used in this documentation to refer to generic concepts such as providers, modules, stacks, the +HCL-based domain-specific language and its interpreter. Atmos works with [OpenTofu](/core-concepts/projects/configuration/opentofu). :::
diff --git a/website/docs/cli/commands/validate/usage.mdx b/website/docs/cli/commands/validate/usage.mdx index b5de1725f..e6e2e9f17 100644 --- a/website/docs/cli/commands/validate/usage.mdx +++ b/website/docs/cli/commands/validate/usage.mdx @@ -11,8 +11,6 @@ import DocCardList from '@theme/DocCardList'; Use these subcommands to validate Atmos configurations. ::: -
- ## Subcommands diff --git a/website/docs/cli/commands/validate/validate-component.mdx b/website/docs/cli/commands/validate/validate-component.mdx index 5a098a357..3f6c61e33 100644 --- a/website/docs/cli/commands/validate/validate-component.mdx +++ b/website/docs/cli/commands/validate/validate-component.mdx @@ -11,8 +11,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to validate an Atmos component in a stack using JSON Schema and OPA policies. ::: -
- ## Usage @@ -25,8 +23,6 @@ atmos validate component -s [options] This command validates an Atmos component in a stack using JSON Schema and OPA policies. -
- :::tip Run `atmos validate component --help` to see all the available options ::: diff --git a/website/docs/cli/commands/validate/validate-stacks.mdx b/website/docs/cli/commands/validate/validate-stacks.mdx index fed318211..8a7cb2376 100644 --- a/website/docs/cli/commands/validate/validate-stacks.mdx +++ b/website/docs/cli/commands/validate/validate-stacks.mdx @@ -12,8 +12,6 @@ import Terminal from '@site/src/components/Terminal' Use this command to validate Atmos stack manifest configurations. ::: -
- ## Usage @@ -24,8 +22,6 @@ Execute the `validate stacks` command like this: atmos validate stacks ``` -
- This command validates Atmos stack manifests and checks the following: - All YAML manifest files for YAML errors and inconsistencies @@ -67,12 +63,10 @@ This command validates Atmos stack manifests and checks the following: ensure each has a unique name - Use multiple-inheritance to combine multiple configurations together - (refer to https://atmos.tools/core-concepts/components/inheritance) + (refer to https://atmos.tools/core-concepts/stacks/inheritance) ``` -
- :::tip Run `atmos validate stacks --help` to see all the available options ::: @@ -98,7 +92,7 @@ on the command line by executing the command `atmos validate stacks`. For this to work, configure the following: - Add the [Atmos Manifest JSON Schema](pathname:///schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) to your repository, for example - in [`stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) + in [`stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) - Configure the following section in the `atmos.yaml` [CLI config file](/cli/configuration) @@ -124,14 +118,12 @@ For this to work, configure the following: atmos validate stacks --schemas-atmos-manifest stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json ``` -
- In case of any validation errors (invalid YAML syntax, Atmos manifest JSON Schema errors, invalid imports, etc.), you'll get an output from the command similar to the following: ```console -no matches found for the import 'globals/tenant1-globals-does-not-exist' in the +no matches found for the import 'globals/tenant1-globals-does-not-exist' in the file 'catalog/invalid-yaml-and-schema/invalid-import-1.yaml' invalid import in the file 'catalog/invalid-yaml-and-schema/invalid-import-2.yaml' @@ -152,7 +144,7 @@ yaml: line 2: block sequence entries are not allowed in this context invalid stack manifest 'catalog/invalid-yaml-and-schema/invalid-yaml-7.yaml' yaml: line 4: could not find expected ':' -Atmos manifest JSON Schema validation error in the +Atmos manifest JSON Schema validation error in the file 'catalog/invalid-yaml-and-schema/invalid-import-5.yaml': { "valid": false, @@ -178,7 +170,7 @@ file 'catalog/invalid-yaml-and-schema/invalid-import-5.yaml': ] } -Atmos manifest JSON Schema validation error in the +Atmos manifest JSON Schema validation error in the file 'catalog/invalid-yaml-and-schema/invalid-schema-8.yaml': { "valid": false, diff --git a/website/docs/cli/commands/vendor/usage.mdx b/website/docs/cli/commands/vendor/usage.mdx index 7e9eb85dd..411b7dd34 100644 --- a/website/docs/cli/commands/vendor/usage.mdx +++ b/website/docs/cli/commands/vendor/usage.mdx @@ -11,8 +11,6 @@ import DocCardList from '@theme/DocCardList'; Use these subcommands to vendor Atmos components and stacks. ::: -
- ## Subcommands diff --git a/website/docs/cli/commands/vendor/vendor-pull.mdx b/website/docs/cli/commands/vendor/vendor-pull.mdx index cf3cd0fda..944b1579b 100644 --- a/website/docs/cli/commands/vendor/vendor-pull.mdx +++ b/website/docs/cli/commands/vendor/vendor-pull.mdx @@ -8,17 +8,12 @@ description: Use this command to pull sources and mixins from remote repositorie import Screengrab from '@site/src/components/Screengrab' :::note Purpose -This command implements [Atmos Vendoring](/core-concepts/vendoring/). Use this command to download sources from local and remote +This command implements [Atmos Vendoring](/core-concepts/vendor/). Use this command to download sources from local and remote repositories for Terraform and Helmfile components and stacks. ::: -
- -
-
- With Atmos vendoring, you can copy components and other artifacts from the following sources: - Copy all files from an [OCI Registry](https://opencontainers.org) into a local folder @@ -76,7 +71,7 @@ configurations. specified tags by executing a command `atmos vendor pull --tags ,` :::tip -Refer to [`Atmos Vendoring`](/core-concepts/vendoring) for more details +Refer to [`Atmos Vendoring`](/core-concepts/vendor) for more details ::: ## Vendoring using `component.yaml` manifest @@ -92,7 +87,7 @@ Refer to [`Atmos Vendoring`](/core-concepts/vendoring) for more details file names/paths (double-star/globstar `**` is supported as well). :::tip -Refer to [`Atmos Component Vendoring`](/core-concepts/components/vendoring) for more details +Refer to [`Atmos Component Vendoring`](/core-concepts/vendor/component-manifest) for more details ::: ## Vendoring from OCI Registries @@ -112,8 +107,6 @@ The following config can be used to download the `vpc` component from an AWS pub version: "latest" ``` -
- :::tip Run `atmos vendor pull --help` to see all the available options ::: @@ -129,8 +122,6 @@ atmos vendor pull --tags dev,test atmos vendor pull --tags networking --dry-run ``` -
- :::note When executing the `atmos vendor pull` command, Atmos performs the following steps to decide which vendoring manifest to use: diff --git a/website/docs/cli/commands/version.mdx b/website/docs/cli/commands/version.mdx index 8eaa5f20a..a8aabaf56 100644 --- a/website/docs/cli/commands/version.mdx +++ b/website/docs/cli/commands/version.mdx @@ -10,8 +10,6 @@ import Screengrab from '@site/src/components/Screengrab' Use this command to get the Atmos CLI version ::: -
- ## Usage @@ -24,19 +22,13 @@ atmos version This will show the CLI version. -
- :::tip To find the latest version of Atmos, go to the [releases](https://github.com/cloudposse/atmos/releases) page on GitHub. -For help with installing the latest version of Atmos, check out our [installation](/quick-start/install-atmos) page. +For help with installing the latest version of Atmos, check out our [installation](/install) page. ::: -
- When executing the `atmos version` command, Atmos automatically checks for the latest release from the [Atmos releases](https://github.com/cloudposse/atmos/releases) page on GitHub and compares the current version with the latest release. If the installed Atmos version is out of date, the following information is presented to the user: - -
diff --git a/website/docs/cli/commands/workflow.mdx b/website/docs/cli/commands/workflow.mdx index e1bc61c1b..262966ee3 100644 --- a/website/docs/cli/commands/workflow.mdx +++ b/website/docs/cli/commands/workflow.mdx @@ -11,12 +11,8 @@ import Terminal from '@site/src/components/Terminal' Use this command to perform sequential execution of `atmos` and `shell` commands defined as workflow steps. ::: -
- -
- An Atmos workflow is a series of steps that are run in order to achieve some outcome. Every workflow has a name and is easily executed from the command line by calling `atmos workflow`. Use workflows to orchestrate any number of commands. Workflows can call @@ -72,8 +68,6 @@ atmos workflow Use the `Tab` key to flip the 3rd column view between the selected workflow steps and full workflow definition. For example: - -
![`atmos workflow` CLI command 3](/img/cli/workflow/atmos-workflow-command-3.png) @@ -87,15 +81,10 @@ atmos workflow apply-all-components -f networking --dry-run atmos workflow test-1 -f workflow1 --from-step step2 ``` -
- :::tip Run `atmos workflow --help` to see all the available options ::: -
-
- ## Arguments | Argument | Description | Required | diff --git a/website/docs/cli/configuration/commands.mdx b/website/docs/cli/configuration/commands.mdx new file mode 100644 index 000000000..98a643701 --- /dev/null +++ b/website/docs/cli/configuration/commands.mdx @@ -0,0 +1,211 @@ +--- +title: Customize Commands +sidebar_position: 1 +id: commands +description: Use the `atmos.yaml` to configure any custom commands you want to add to the Atmos CLI. +--- +import Screengrab from '@site/src/components/Screengrab' +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' + + +You can extend the Atmos CLI and add as many custom commands as you want. This is a great way to increase improve the DX by exposing a consistent CLI interface to developers. + + +For example, one great way to use custom commands is to tie all the miscellaneous scripts into one consistent CLI interface. +Then we can kiss those ugly, inconsistent arguments to bash scripts goodbye! Just wire up the commands in atmos to call the script. +Then, developers can just run `atmos help` and discover all available commands. + +Here are some examples to play around with to get started. + + +```yaml +# Custom CLI commands +commands: + - name: tf + description: Execute 'terraform' commands + + # subcommands + commands: + - name: plan + description: This command plans terraform components + arguments: + - name: component + description: Name of the component + flags: + - name: stack + shorthand: s + description: Name of the stack + required: true + env: + - key: ENV_VAR_1 + value: ENV_VAR_1_value + - key: ENV_VAR_2 + # 'valueCommand' is an external command to execute to get the value for the ENV var + # Either 'value' or 'valueCommand' can be specified for the ENV var, but not both + valueCommand: echo ENV_VAR_2_value + # steps support Go templates + steps: + - atmos terraform plan {{ .Arguments.component }} -s {{ .Flags.stack }} + + - name: terraform + description: Execute 'terraform' commands + + # subcommands + commands: + - name: provision + description: This command provisions terraform components + arguments: + - name: component + description: Name of the component + + flags: + - name: stack + shorthand: s + description: Name of the stack + required: true + + # ENV var values support Go templates + env: + - key: ATMOS_COMPONENT + value: "{{ .Arguments.component }}" + - key: ATMOS_STACK + value: "{{ .Flags.stack }}" + steps: + - atmos terraform plan $ATMOS_COMPONENT -s $ATMOS_STACK + - atmos terraform apply $ATMOS_COMPONENT -s $ATMOS_STACK + + - name: show + description: Execute 'show' commands + + # subcommands + commands: + - name: component + description: Execute 'show component' command + arguments: + - name: component + description: Name of the component + flags: + - name: stack + shorthand: s + description: Name of the stack + required: true + + # ENV var values support Go templates and have access to {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables + env: + - key: ATMOS_COMPONENT + value: "{{ .Arguments.component }}" + - key: ATMOS_STACK + value: "{{ .Flags.stack }}" + - key: ATMOS_TENANT + value: "{{ .ComponentConfig.vars.tenant }}" + - key: ATMOS_STAGE + value: "{{ .ComponentConfig.vars.stage }}" + - key: ATMOS_ENVIRONMENT + value: "{{ .ComponentConfig.vars.environment }}" + - key: ATMOS_IS_PROD + value: "{{ .ComponentConfig.settings.config.is_prod }}" + + # If a custom command defines 'component_config' section with 'component' and 'stack', 'atmos' generates the config for the component in the stack + # and makes it available in {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables, + # exposing all the component sections (which are also shown by 'atmos describe component' command) + component_config: + component: "{{ .Arguments.component }}" + stack: "{{ .Flags.stack }}" + # Steps support using Go templates and can access all configuration settings (e.g. {{ .ComponentConfig.xxx.yyy.zzz }}) + # Steps also have access to the ENV vars defined in the 'env' section of the 'command' + steps: + - 'echo Atmos component from argument: "{{ .Arguments.component }}"' + - 'echo ATMOS_COMPONENT: "$ATMOS_COMPONENT"' + - 'echo Atmos stack: "{{ .Flags.stack }}"' + - 'echo Terraform component: "{{ .ComponentConfig.component }}"' + - 'echo Backend S3 bucket: "{{ .ComponentConfig.backend.bucket }}"' + - 'echo Terraform workspace: "{{ .ComponentConfig.workspace }}"' + - 'echo Namespace: "{{ .ComponentConfig.vars.namespace }}"' + - 'echo Tenant: "{{ .ComponentConfig.vars.tenant }}"' + - 'echo Environment: "{{ .ComponentConfig.vars.environment }}"' + - 'echo Stage: "{{ .ComponentConfig.vars.stage }}"' + - 'echo settings.spacelift.workspace_enabled: "{{ .ComponentConfig.settings.spacelift.workspace_enabled }}"' + - 'echo Dependencies: "{{ .ComponentConfig.deps }}"' + - 'echo settings.config.is_prod: "{{ .ComponentConfig.settings.config.is_prod }}"' + - 'echo ATMOS_IS_PROD: "$ATMOS_IS_PROD"' + + - name: list + description: Execute 'atmos list' commands + # subcommands + commands: + - name: stacks + description: | + List all Atmos stacks. + steps: + - > + atmos describe stacks --sections none | grep -e "^\S" | sed s/://g + - name: components + description: | + List all Atmos components in all stacks or in a single stack. + + Example usage: + atmos list components + atmos list components -s tenant1-ue1-dev + atmos list components --stack tenant2-uw2-prod + flags: + - name: stack + shorthand: s + description: Name of the stack + required: false + steps: + - > + {{ if .Flags.stack }} + atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]" + {{ else }} + atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]" + {{ end }} + + - name: set-eks-cluster + description: | + Download 'kubeconfig' and set EKS cluster. + + Example usage: + atmos set-eks-cluster eks/cluster -s tenant1-ue1-dev -r admin + atmos set-eks-cluster eks/cluster -s tenant2-uw2-prod --role reader + verbose: false # Set to `true` to see verbose outputs + arguments: + - name: component + description: Name of the component + flags: + - name: stack + shorthand: s + description: Name of the stack + required: true + - name: role + shorthand: r + description: IAM role to use + required: true + # If a custom command defines 'component_config' section with 'component' and 'stack', + # Atmos generates the config for the component in the stack + # and makes it available in {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables, + # exposing all the component sections (which are also shown by 'atmos describe component' command) + component_config: + component: "{{ .Arguments.component }}" + stack: "{{ .Flags.stack }}" + env: + - key: KUBECONFIG + value: /dev/shm/kubecfg.{{ .Flags.stack }}-{{ .Flags.role }} + steps: + - > + aws + --profile {{ .ComponentConfig.vars.namespace }}-{{ .ComponentConfig.vars.tenant }}-gbl-{{ .ComponentConfig.vars.stage }}-{{ .Flags.role }} + --region {{ .ComponentConfig.vars.region }} + eks update-kubeconfig + --name={{ .ComponentConfig.vars.namespace }}-{{ .Flags.stack }}-eks-cluster + --kubeconfig="${KUBECONFIG}" + > /dev/null + - chmod 600 ${KUBECONFIG} + - echo ${KUBECONFIG} +``` + + +:::tip + For more information, refer to [Atmos Custom Commands](/core-concepts/custom-commands) +::: diff --git a/website/docs/cli/configuration/components.mdx b/website/docs/cli/configuration/components.mdx new file mode 100644 index 000000000..6ab7e77ac --- /dev/null +++ b/website/docs/cli/configuration/components.mdx @@ -0,0 +1,159 @@ +--- +title: Customize Component Behavior +sidebar_position: 1 +sidebar_label: Customize Component Behavior +id: components +description: >- + Use the `atmos.yaml` configuration file to specify default behaviors for components, + such as what command to use when running Terraform commands, the base path for Terraform, and more. +--- +import Screengrab from '@site/src/components/Screengrab' +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' + + +In Atmos, every component is associated with a command. The command is what drives or provisions that component. +For example, [Terraform "root modules"](/core-concepts/components/terraform) can be used as components in Atmos. +To instruct Atmos how to interact with that component, we must specify the command to run and and where the code +for the component is located. Then, depending on the type of component, certain behaviors can be configured. + + +The `components` section of the `atmos.yaml` is how we do it. It defines how Atmos locates and executes your components. +Think of it as the bootstrapping configuration. This is where we can define the the `command` to run, +the `base_path` location of the components, and so forth. + + +:::important +Do not confuse this configuration with [configuring components in stacks](/core-concepts/stacks/define-components). +This configuration below is defined in the `atmos.yaml` and meant for specifying default behaviors for components, +such as what command to use when running Terraform commands, the base path for Terraform, and more. +::: + +## Terraform Component Behavior + +For additional details on configuring Terraform components, refer to the [Terraform](/core-concepts/projects/configuration/terraform) +and [OpenTofu](/core-concepts/projects/configuration/opentofu) documentation. + + +:::note Disambiguation +The term “Terraform” is used in this documentation to refer to generic concepts such as providers, modules, stacks, the +HCL-based domain-specific language and its interpreter. Atmos works with [OpenTofu](/core-concepts/projects/configuration/opentofu). +::: + + + +```yaml +components: + terraform: + # Optional `command` specifies the executable to be called by `atmos` when running Terraform commands + # If not defined, `terraform` is used + # Examples: + # command: terraform + # command: /usr/local/bin/terraform + # command: /usr/local/bin/terraform-1.8 + # command: tofu + # command: /usr/local/bin/tofu-1.7.1 + # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_COMMAND' ENV var, or '--terraform-command' command-line argument + command: terraform + + # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_BASE_PATH' ENV var, or '--terraform-dir' command-line argument + # Supports both absolute and relative paths + base_path: "components/terraform" + + # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE' ENV var + apply_auto_approve: false + + # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT' ENV var, or '--deploy-run-init' command-line argument + deploy_run_init: true + + # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE' ENV var, or '--init-run-reconfigure' command-line argument + init_run_reconfigure: true + + # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE' ENV var, or '--auto-generate-backend-file' command-line argument + auto_generate_backend_file: true +``` + + + +## Helmfile Component Behavior + + +```yaml +components: + helmfile: + # Optional `command` specifies the executable to be called by `atmos` when running Helmfile commands + # If not defined, `helmfile` is used + # Examples: + # command: helmfile + # command: /usr/local/bin/helmfile + # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_COMMAND' ENV var, or '--helmfile-command' command-line argument + command: helmfile + + # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_BASE_PATH' ENV var, or '--helmfile-dir' command-line argument + # Supports both absolute and relative paths + base_path: "components/helmfile" + + # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_USE_EKS' ENV var + # If not specified, defaults to 'true' + use_eks: true + + # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH' ENV var + kubeconfig_path: "/dev/shm" + + # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN' ENV var + helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" + + # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN' ENV var + cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" +``` + + + +
+
`command`
+
+ Specifies the executable to be called by `atmos` when running Helmfile commands. + If not defined, `helmfile` is used. Can also be set using `ATMOS_COMPONENTS_HELMFILE_COMMAND` ENV var, + or `--helmfile-command` command-line argument. + + Example values: `helmfile`, `/usr/local/bin/helmfile`. +
+ +
`base_path`
+
+ Example value: "components/helmfile". Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, + or `--helmfile-dir` command-line argument. + Supports both absolute and relative paths. +
+ +
`use_eks`
+
+ If not specified, defaults to `true`. + Can also be set using `ATMOS_COMPONENTS_HELMFILE_USE_EKS` ENV var. +
+ +
`kubeconfig_path`
+
+ Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var. + Example value: `/dev/shm`. +
+ +
`helm_aws_profile_pattern`
+
+ Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var. + Example value: + ``` + {namespace}-{tenant}-{gbl}-{stage}-helm + ``` +
+ +
`cluster_name_pattern`
+
+ Can also be set using ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var. + Example value: + ``` + {namespace}-{tenant}-{environment}-{stage}-eks-cluster` + ``` +
+
diff --git a/website/docs/cli/configuration.mdx b/website/docs/cli/configuration/configuration.mdx similarity index 59% rename from website/docs/cli/configuration.mdx rename to website/docs/cli/configuration/configuration.mdx index fb5f37866..368a981ba 100644 --- a/website/docs/cli/configuration.mdx +++ b/website/docs/cli/configuration/configuration.mdx @@ -1,6 +1,7 @@ --- title: CLI Configuration sidebar_position: 1 +sidebar_label: CLI Configuration id: configuration description: Use the `atmos.yaml` configuration file to control the behavior of the `atmos` CLI. --- @@ -8,18 +9,22 @@ description: Use the `atmos.yaml` configuration file to control the behavior of import Screengrab from '@site/src/components/Screengrab' import Terminal from '@site/src/components/Terminal' import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' # CLI Configuration -:::note Purpose + Use the `atmos.yaml` configuration file to control the behavior of the [`atmos` CLI](/cli) -::: - -
+
Everything in the [`atmos` CLI](/cli) is configurable. The defaults are established in the `atmos.yaml` configuration file. The CLI configuration should not be confused with [Stack configurations](/core-concepts/stacks/), which have a different schema. +Think of this file as where you [bootstrap the settings or configuration of your project](/core-concepts/projects). If you'll be using +[terraform](/core-concepts/components/terraform), then [this is where](/cli/configuration/components#terraform-component-behavior) +you'd specify the command to run (e.g. [`opentofu`](/core-concepts/projects/configuration/opentofu)), +the base path location of the components, and so forth. + ## Configuration File (`atmos.yaml`) The CLI config is loaded from the following locations (from lowest to highest priority): @@ -31,14 +36,12 @@ The CLI config is loaded from the following locations (from lowest to highest pr Each configuration file discovered is deep-merged with the preceeding configurations. -
- :::tip Pro-Tip Atmos supports [POSIX-style greedy Globs](https://en.wikipedia.org/wiki/Glob_(programming)) for all file names/paths (double-star/globstar `**` is supported as well) ::: -
+## Default CLI Configuration If `atmos.yaml` is not found in any of the searched locations, Atmos will use the following default CLI configuration: @@ -89,7 +92,7 @@ schemas: base_path: stacks/schemas/jsonschema opa: base_path: stacks/schemas/opa -# https://atmos.tools/core-concepts/stacks/templating +# https://atmos.tools/core-concepts/stacks/templates # https://pkg.go.dev/text/template templates: settings: @@ -103,19 +106,13 @@ templates: ``` -
- -If Atmos does not find an `atmos.yaml` file and the default CLI config is used, and if you set the ENV variable `ATMOS_LOGS_LEVEL` to `Debug` +If Atmos does not find an `atmos.yaml` file and the default CLI config is used, and if you set the ENV variable `ATMOS_LOGS_LEVEL` to `Debug` (e.g. `export ATMOS_LOGS_LEVEL=Debug`) before executing Atmos commands, you'll see the following message: -
- ![`atmos` CLI command mode 1](/img/cli/atmos.yaml/atmos-default-cli-config-message.png) -
- What follows are all the sections of the `atmos.yaml` configuration file. ## Base Path @@ -155,220 +152,26 @@ The `settings` section configures Atmos global settings. ``` -- `settings.list_merge_strategy` specifies how lists are merged in Atmos stack manifests. - The following strategies are supported: +
+
`settings.list_merge_strategy`
+
+ Specifies how lists are merged in Atmos stack manifests. - - `replace` - Most recent list imported wins (the default behavior). + The following strategies are supported: +
+
`replace`
+
Most recent list imported wins (the default behavior).
- - `append` - The sequence of lists is appended in the same order as imports. +
`append`
+
The sequence of lists is appended in the same order as imports.
- - `merge` - The items in the destination list are deep-merged with the items in the source list. - The items in the source list take precedence. - The items are processed starting from the first up to the length of the source list (the remaining items are not processed). - If the source and destination lists have the same length, all items in the destination lists are - deep-merged with all items in the source list. +
`merge`
+
The items in the destination list are deep-merged with the items in the source list. The items in the source list take precedence. The items are processed starting from the first up to the length of the source list (the remaining items are not processed). If the source and destination lists have the same length, all items in the destination lists are deep-merged with all items in the source list.
+
+
+
-## Components -Specify the default behaviors for components. - - -```yaml -components: - terraform: - # Optional `command` specifies the executable to be called by `atmos` when running Terraform commands - # If not defined, `terraform` is used - # Examples: - # command: terraform - # command: /usr/local/bin/terraform - # command: /usr/local/bin/terraform-1.8 - # command: tofu - # command: /usr/local/bin/tofu-1.7.1 - # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_COMMAND' ENV var, or '--terraform-command' command-line argument - command: terraform - - # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_BASE_PATH' ENV var, or '--terraform-dir' command-line argument - # Supports both absolute and relative paths - base_path: "components/terraform" - - # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE' ENV var - apply_auto_approve: false - - # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT' ENV var, or '--deploy-run-init' command-line argument - deploy_run_init: true - - # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE' ENV var, or '--init-run-reconfigure' command-line argument - init_run_reconfigure: true - - # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE' ENV var, or '--auto-generate-backend-file' command-line argument - auto_generate_backend_file: true - - helmfile: - # Optional `command` specifies the executable to be called by `atmos` when running Helmfile commands - # If not defined, `helmfile` is used - # Examples: - # command: helmfile - # command: /usr/local/bin/helmfile - # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_COMMAND' ENV var, or '--helmfile-command' command-line argument - command: helmfile - - # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_BASE_PATH' ENV var, or '--helmfile-dir' command-line argument - # Supports both absolute and relative paths - base_path: "components/helmfile" - - # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_USE_EKS' ENV var - # If not specified, defaults to 'true' - use_eks: true - - # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH' ENV var - kubeconfig_path: "/dev/shm" - - # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN' ENV var - helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" - - # Can also be set using 'ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN' ENV var - cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" -``` - - -## Stacks - -Define the stack name pattern or template and specify where to find stacks. - - -```yaml -stacks: - # Can also be set using 'ATMOS_STACKS_BASE_PATH' ENV var, or '--config-dir' and '--stacks-dir' command-line arguments - # Supports both absolute and relative paths - base_path: "stacks" - - # Can also be set using 'ATMOS_STACKS_INCLUDED_PATHS' ENV var (comma-separated values string) - included_paths: - # Tell Atmos to search for the top-level stack manifests in the `orgs` folder and its sub-folders - - "orgs/**/*" - - # Can also be set using 'ATMOS_STACKS_EXCLUDED_PATHS' ENV var (comma-separated values string) - excluded_paths: - # Tell Atmos that all `_defaults.yaml` files are not top-level stack manifests - - "**/_defaults.yaml" - - # To define Atmos stack naming convention, use either `name_pattern` or `name_template`. - # `name_template` has higher priority (if `name_template` is specified, `name_pattern` will be ignored). - # `name_pattern` uses the predefined context tokens {namespace}, {tenant}, {environment}, {stage}. - # `name_pattern` can also be set using 'ATMOS_STACKS_NAME_PATTERN' ENV var - name_pattern: "{tenant}-{environment}-{stage}" - # `name_template` is a Golang template. - # For the template tokens, and you can use any Atmos sections and attributes that the Atmos command - # `atmos describe component -s ` generates (refer to https://atmos.tools/cli/commands/describe/component). - # `name_template` can also be set using 'ATMOS_STACKS_NAME_TEMPLATE' ENV var - # name_template: "{{.vars.tenant}}-{{.vars.environment}}-{{.vars.stage}}" -``` - - -- `stacks.base_path` specifies the path to the folder where **all** Atmos stack config files (stack manifests) are defined. - If the global `base_path` is not provided or is an empty string, `stacks.base_path` is an independent setting that supports both absolute and - relative paths. If the global `base_path` is defined, `stacks.base_path` is relative to the global `base_path` - -- `stacks.included_paths` tells Atmos where to search for the top-level stack manifests - - :::note - Atmos top-level stack manifests are configuration files that define **all** settings and components for the corresponding environment (organization, - OU/tenant, account, region), and they are used in `atmos` CLI commands like `atmos terraform plan -s ` and - `atmos terraform apply -s ` - ::: - -
- -- `stacks.excluded_paths` tells Atmos which paths from `stacks.included_paths` to exclude. For example, we will exclude the config files that don't - contain the top-level stack manifests, but just define the default values that get imported into top-level stack manifests - - :::note - The `_defaults.yaml` files is the recommended way to define the stack manifests with the - default configurations for organizations, OUs/tenants, accounts and regions. The `_defaults.yaml` files themselves are not top-level Atmos stacks, - they just contain the default values for the organizations, OUs/tenants, accounts and regions (to make the entire configuration reusable and DRY) - ::: - -
- -- `stacks.name_pattern` configures the name pattern for the top-level Atmos stacks using the context variables `namespace`, `tenant`, `environment` - and `stage` as the tokens. Depending on the structure of your organization, OUs, accounts and regions, set `stacks.name_pattern` to the - following: - - - `name_pattern: {stage}` - if you use just one region and a few accounts (stages) in just one organization and one OU. In this case, the - top-level Atmos stacks will use just the `stage` (account) in their names, and to provision the Atmos components in the top-level stacks, you will - be executing Atmos commands like `atmos terraform apply --stack dev`, `atmos terraform apply --stack staging` - and `atmos terraform apply --stack prod` - - - `name_pattern: {environment}-{stage}` - if you have multiple regions and accounts (stages) in just one organization and one OU. In this case, the - top-level Atmos stacks will use the `environment` (region) and `stage` (account) in their names, and to provision the Atmos components in the - top-level stacks, you will be executing Atmos commands - like `atmos terraform apply --stack ue2-dev`, `atmos terraform apply --stack uw2-staging` - and `atmos terraform apply --stack ue1-prod`. Note that the `name_pattern` can also be defined - as `{stage}-{environment}`, in which case the Atmos commands will look like `atmos terraform apply --stack dev-ue2` - - - `name_pattern: {tenant}-{environment}-{stage}` - if you have multiple regions, OUs (tenants) and accounts (stages) in just one organization. In - this case, the top-level Atmos stacks will use the `tenant`, `environment` (region) and `stage` (account) in their names, and to provision the - Atmos components in the top-level stacks, you will be executing Atmos commands - like `atmos terraform apply --stack plat-ue2-dev`, `atmos terraform apply --stack core-uw2-staging` - and `atmos terraform apply --stack plat-ue1-prod`, where `plat` and `core` are the OUs/tenants in your organization - - - `name_pattern: {namespace}-{tenant}-{environment}-{stage}` - if you have a multi-org, multi-tenant, multi-account and multi-region architecture. - In this case, the top-level Atmos stacks will use the `namespace`, `tenant`, `environment` (region) and `stage` (account) in their names, and to - provision the Atmos components in the top-level stacks, you will be executing Atmos commands - like `atmos terraform apply --stack org1-plat-ue2-dev`, `atmos terraform apply --stack org2-core-uw2-staging` - and `atmos terraform apply --stack org2-plat-ue1-prod`, where `org1` and `org2` are the organization names (defined as `namespace` in - the corresponding `_defaults.yaml` config files for the organizations) - -- `stacks.name_template` serves the same purpose as `stacks.name_pattern` (defines the naming convention for the top-level Atmos stacks), but - provides much more functionality. Instead of using the predefined context variables as tokens, it uses [Go templates](https://pkg.go.dev/text/template). - [Sprig Functions](https://masterminds.github.io/sprig/) are supported as well - - - For the `Go` template tokens, and you can use any Atmos sections (e.g. `vars`, `providers`, `settings`) - that the Atmos command [`atmos describe component -s `](/cli/commands/describe/component) generates - for a component in a stack. - - - `name_template: "{{.vars.tenant}}-{{.vars.environment}}-{{.vars.stage}}"` defines the same name pattern for the top-level - Atmos stacks as `name_pattern: "{tenant}-{environment}-{stage}"` does - - - Since `stacks.name_template` allows using any variables form the `vars` section (and other sections), you can define - your own naming convention for your organization or for different clouds (AWS, Azure, GCP). For example, in the - corresponding `_defaults.yaml` stack manifests, you can use the following variables: - - - `org` instead of `namespace` - - `division` instead of `tenant` - - `region` instead of `environment` - - `account` instead of `stage` - - Then define the following `stacks.name_template` in `atmos.yaml`: - - ```yaml title="atmos.yaml" - stacks: - name_template: "{{.vars.division}}-{{.vars.account}}-{{.vars.region}}" - ``` - - You will be able to execute all Atmos commands using the newly defined naming convention: - - ```shell - atmos terraform plan -s - atmos terraform apply -s - atmos describe component -s - ``` - - :::note - Use either `stacks.name_pattern` or `stacks.name_template` to define the naming convention for the top-level Atmos stacks. - - `stacks.name_template` has higher priority. - - If `stacks.name_template` is specified, `stacks.name_pattern` will be ignored. - ::: - -
- -:::tip -Refer to [Atmos Design Patterns](/design-patterns) for the examples on how to configure the `stacks` section in `atmos.yaml` for different use-cases -::: - -
## Workflows @@ -381,209 +184,6 @@ workflows: ``` -## Custom CLI Commands - -You can extend the Atmos CLI and add as many custom commands as you want. This is a great way to increase DX by exposing a consistent CLI interface to -developers. - -For example, one great way to use custom commands is to tie all the miscellaneous scripts into one consistent CLI interface. -Then we can kiss those ugly, inconsistent arguments to bash scripts goodbye! Just wire up the commands in atmos to call the script. -Then developers can just run `atmos help` and discover all available commands. - -Here are some examples to play around with to get started. - - -```yaml -# Custom CLI commands -commands: - - name: tf - description: Execute 'terraform' commands - - # subcommands - commands: - - name: plan - description: This command plans terraform components - arguments: - - name: component - description: Name of the component - flags: - - name: stack - shorthand: s - description: Name of the stack - required: true - env: - - key: ENV_VAR_1 - value: ENV_VAR_1_value - - key: ENV_VAR_2 - # 'valueCommand' is an external command to execute to get the value for the ENV var - # Either 'value' or 'valueCommand' can be specified for the ENV var, but not both - valueCommand: echo ENV_VAR_2_value - # steps support Go templates - steps: - - atmos terraform plan {{ .Arguments.component }} -s {{ .Flags.stack }} - - - name: terraform - description: Execute 'terraform' commands - - # subcommands - commands: - - name: provision - description: This command provisions terraform components - arguments: - - name: component - description: Name of the component - - flags: - - name: stack - shorthand: s - description: Name of the stack - required: true - - # ENV var values support Go templates - env: - - key: ATMOS_COMPONENT - value: "{{ .Arguments.component }}" - - key: ATMOS_STACK - value: "{{ .Flags.stack }}" - steps: - - atmos terraform plan $ATMOS_COMPONENT -s $ATMOS_STACK - - atmos terraform apply $ATMOS_COMPONENT -s $ATMOS_STACK - - - name: show - description: Execute 'show' commands - - # subcommands - commands: - - name: component - description: Execute 'show component' command - arguments: - - name: component - description: Name of the component - flags: - - name: stack - shorthand: s - description: Name of the stack - required: true - - # ENV var values support Go templates and have access to {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables - env: - - key: ATMOS_COMPONENT - value: "{{ .Arguments.component }}" - - key: ATMOS_STACK - value: "{{ .Flags.stack }}" - - key: ATMOS_TENANT - value: "{{ .ComponentConfig.vars.tenant }}" - - key: ATMOS_STAGE - value: "{{ .ComponentConfig.vars.stage }}" - - key: ATMOS_ENVIRONMENT - value: "{{ .ComponentConfig.vars.environment }}" - - key: ATMOS_IS_PROD - value: "{{ .ComponentConfig.settings.config.is_prod }}" - - # If a custom command defines 'component_config' section with 'component' and 'stack', 'atmos' generates the config for the component in the stack - # and makes it available in {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables, - # exposing all the component sections (which are also shown by 'atmos describe component' command) - component_config: - component: "{{ .Arguments.component }}" - stack: "{{ .Flags.stack }}" - # Steps support using Go templates and can access all configuration settings (e.g. {{ .ComponentConfig.xxx.yyy.zzz }}) - # Steps also have access to the ENV vars defined in the 'env' section of the 'command' - steps: - - 'echo Atmos component from argument: "{{ .Arguments.component }}"' - - 'echo ATMOS_COMPONENT: "$ATMOS_COMPONENT"' - - 'echo Atmos stack: "{{ .Flags.stack }}"' - - 'echo Terraform component: "{{ .ComponentConfig.component }}"' - - 'echo Backend S3 bucket: "{{ .ComponentConfig.backend.bucket }}"' - - 'echo Terraform workspace: "{{ .ComponentConfig.workspace }}"' - - 'echo Namespace: "{{ .ComponentConfig.vars.namespace }}"' - - 'echo Tenant: "{{ .ComponentConfig.vars.tenant }}"' - - 'echo Environment: "{{ .ComponentConfig.vars.environment }}"' - - 'echo Stage: "{{ .ComponentConfig.vars.stage }}"' - - 'echo settings.spacelift.workspace_enabled: "{{ .ComponentConfig.settings.spacelift.workspace_enabled }}"' - - 'echo Dependencies: "{{ .ComponentConfig.deps }}"' - - 'echo settings.config.is_prod: "{{ .ComponentConfig.settings.config.is_prod }}"' - - 'echo ATMOS_IS_PROD: "$ATMOS_IS_PROD"' - - - name: list - description: Execute 'atmos list' commands - # subcommands - commands: - - name: stacks - description: | - List all Atmos stacks. - steps: - - > - atmos describe stacks --sections none | grep -e "^\S" | sed s/://g - - name: components - description: | - List all Atmos components in all stacks or in a single stack. - - Example usage: - atmos list components - atmos list components -s tenant1-ue1-dev - atmos list components --stack tenant2-uw2-prod - flags: - - name: stack - shorthand: s - description: Name of the stack - required: false - steps: - - > - {{ if .Flags.stack }} - atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]" - {{ else }} - atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]" - {{ end }} - - - name: set-eks-cluster - description: | - Download 'kubeconfig' and set EKS cluster. - - Example usage: - atmos set-eks-cluster eks/cluster -s tenant1-ue1-dev -r admin - atmos set-eks-cluster eks/cluster -s tenant2-uw2-prod --role reader - verbose: false # Set to `true` to see verbose outputs - arguments: - - name: component - description: Name of the component - flags: - - name: stack - shorthand: s - description: Name of the stack - required: true - - name: role - shorthand: r - description: IAM role to use - required: true - # If a custom command defines 'component_config' section with 'component' and 'stack', - # Atmos generates the config for the component in the stack - # and makes it available in {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables, - # exposing all the component sections (which are also shown by 'atmos describe component' command) - component_config: - component: "{{ .Arguments.component }}" - stack: "{{ .Flags.stack }}" - env: - - key: KUBECONFIG - value: /dev/shm/kubecfg.{{ .Flags.stack }}-{{ .Flags.role }} - steps: - - > - aws - --profile {{ .ComponentConfig.vars.namespace }}-{{ .ComponentConfig.vars.tenant }}-gbl-{{ .ComponentConfig.vars.stage }}-{{ .Flags.role }} - --region {{ .ComponentConfig.vars.region }} - eks update-kubeconfig - --name={{ .ComponentConfig.vars.namespace }}-{{ .Flags.stack }}-eks-cluster - --kubeconfig="${KUBECONFIG}" - > /dev/null - - chmod 600 ${KUBECONFIG} - - echo ${KUBECONFIG} -``` - - -
- -:::tip - For more information, refer to [Atmos Custom Commands](/core-concepts/custom-commands) -::: ## Integrations @@ -655,14 +255,13 @@ integrations: ``` -
- :::tip -For more information, refer to [Atmos Integrations](/integrations) +For more information, refer to Atmos Integrations. +- [GitHub Actions](/integrations/github-actions) +- [Atlantis](/integrations/atlantis) +- [Spacelift](/integrations/spacelift) ::: -
- ## Schemas Configure the paths where to find OPA and JSON Schema files to validate Atmos stack manifests and components. @@ -682,9 +281,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes atmos: @@ -694,16 +293,12 @@ schemas: ``` -
- :::tip For more information, refer to: -- [Atmos Manifests Validation](/reference/schemas) -- [Atmos Component Validation](/core-concepts/components/validation) +- [Atmos Manifests Validation](/cli/schemas) +- [Atmos Component Validation](/core-concepts/validate) ::: -
- ## Logs Logs are configured in the `logs` section: @@ -746,8 +341,6 @@ logs: ``` -
- ```console Checking out Git ref 'refs/remotes/origin/HEAD' ... @@ -758,8 +351,8 @@ BASE: f7aa382aa8b3d48be8f06cfdb27aad344b89aff4 HEAD Changed files: -examples/quick-start/Dockerfile -examples/quick-start/atmos.yaml +examples/quick-start-advanced/Dockerfile +examples/quick-start-advanced/atmos.yaml Affected components and stacks: @@ -767,7 +360,7 @@ Affected components and stacks: { "component": "vpc", "component_type": "terraform", - "component_path": "examples/quick-start/components/terraform/vpc", + "component_path": "examples/quick-start-advanced/components/terraform/vpc", "stack": "plat-uw2-prod", "stack_slug": "plat-uw2-prod-vpc", "affected": "stack.vars" @@ -775,7 +368,7 @@ Affected components and stacks: { "component": "vpc", "component_type": "terraform", - "component_path": "examples/quick-start/components/terraform/vpc", + "component_path": "examples/quick-start-advanced/components/terraform/vpc", "stack": "plat-ue2-prod", "stack_slug": "plat-ue2-prod-vpc", "affected": "stack.vars" @@ -784,8 +377,6 @@ Affected components and stacks: ```` -
- With `logs.level: Trace`, and `logs.file: "/dev/stdout"`, all the messages and the command's JSON output will be printed to the console to the `/dev/stdout` standard output. @@ -805,8 +396,6 @@ logs: ``` -
- Now when the `atmos describe affected` command is executed, the additional messages are printed to `/dev/stderr`, but the command's JSON output is printed to `/dev/stdout`, allowing `jq` to parse it without errors. @@ -826,7 +415,7 @@ BASE: f7aa382aa8b3d48be8f06cfdb27aad344b89aff4 HEAD { "component": "vpc", "component_type": "terraform", - "component_path": "examples/quick-start/components/terraform/vpc", + "component_path": "examples/quick-start-advanced/components/terraform/vpc", "stack": "plat-uw2-prod", "stack_slug": "plat-uw2-prod-vpc", "affected": "stack.vars" @@ -834,7 +423,7 @@ BASE: f7aa382aa8b3d48be8f06cfdb27aad344b89aff4 HEAD { "component": "vpc", "component_type": "terraform", - "component_path": "examples/quick-start/components/terraform/vpc", + "component_path": "examples/quick-start-advanced/components/terraform/vpc", "stack": "plat-ue2-prod", "stack_slug": "plat-ue2-prod-vpc", "affected": "stack.vars" @@ -843,8 +432,6 @@ BASE: f7aa382aa8b3d48be8f06cfdb27aad344b89aff4 HEAD ````
-
- ## Aliases CLI command aliases are configured in the `aliases` section. @@ -871,8 +458,6 @@ aliases: ``` -
- Execute an alias as you would any Atmos native or custom command: @@ -888,8 +473,6 @@ plat-uw2-staging ``` -
- The aliases configured in the `aliases` section automatically appear in Atmos help, and are shown as `alias for ''`. @@ -899,8 +482,6 @@ For example: ![`atmos --help`](/img/cli/help/atmos-help-command-3.png) -
- An alias automatically supports all command line arguments and flags that the aliased command accepts. For example: @@ -917,11 +498,9 @@ and [Gomplate Datasources](https://docs.gomplate.ca/datasources/) are supported as well. :::tip -For more details, refer to [Atmos Stack Manifest Templating](/core-concepts/stacks/templating) +For more details, refer to [Atmos Stack Manifest Templating](/core-concepts/stacks/templates) ::: -
- ```yaml # https://pkg.go.dev/text/template @@ -957,8 +536,6 @@ templates: ``` -
- - `templates.settings.enabled` - a boolean flag to enable/disable the processing of `Go` templates in Atmos stack manifests. If set to `false`, Atmos will not process `Go` templates in stack manifests @@ -1002,8 +579,6 @@ templates: - "application/json" ``` -
- :::warning Some functions are present in both [Sprig](https://masterminds.github.io/sprig/) and [Gomplate](https://docs.gomplate.ca/functions/). @@ -1020,8 +595,6 @@ functions. ::: -
- ## Environment Variables @@ -1052,7 +625,7 @@ setting `ATMOS_STACKS_BASE_PATH` to a path in `/localhost` to your local develop | ATMOS_WORKFLOWS_BASE_PATH | workflows.base_path | Base path to Atmos workflows | | ATMOS_SCHEMAS_JSONSCHEMA_BASE_PATH | schemas.jsonschema.base_path | Base path to JSON schemas for component validation | | ATMOS_SCHEMAS_OPA_BASE_PATH | schemas.opa.base_path | Base path to OPA policies for component validation | -| ATMOS_SCHEMAS_ATMOS_MANIFEST | schemas.atmos.manifest | Path to JSON Schema to validate Atmos stack manifests. For more details, refer to [Atmos Manifest JSON Schema](/reference/schemas) | +| ATMOS_SCHEMAS_ATMOS_MANIFEST | schemas.atmos.manifest | Path to JSON Schema to validate Atmos stack manifests. For more details, refer to [Atmos Manifest JSON Schema](/cli/schemas) | | ATMOS_LOGS_FILE | logs.file | The file to write Atmos logs to. Logs can be written to any file or any standard file descriptor, including `/dev/stdout`, `/dev/stderr` and `/dev/null`). If omitted, `/dev/stdout` will be used | | ATMOS_LOGS_LEVEL | logs.level | Logs level. Supported log levels are `Trace`, `Debug`, `Info`, `Warning`, `Off`. If the log level is set to `Off`, Atmos will not log any messages (note that this does not prevent other tools like Terraform from logging) | | ATMOS_SETTINGS_LIST_MERGE_STRATEGY | settings.list_merge_strategy | Specifies how lists are merged in Atmos stack manifests. The following strategies are supported: `replace`, `append`, `merge` | diff --git a/website/docs/cli/configuration/stacks.mdx b/website/docs/cli/configuration/stacks.mdx new file mode 100644 index 000000000..94b59d795 --- /dev/null +++ b/website/docs/cli/configuration/stacks.mdx @@ -0,0 +1,147 @@ +--- +title: Customize Stack Behavior +sidebar_position: 3 +id: stacks +description: Use the `atmos.yaml` to configure where Atmos will discover stack configurations. +--- +import Screengrab from '@site/src/components/Screengrab' +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' + + +The `stacks` section of the `atmos.yaml` defines how Atmos locates and manages your stack configurations. Think of it as the bootstrapping configuration. Here you can define the stack name pattern or template used to build the "slugs" and specify where to find stack files. + + +:::important +Do not confuse this configuration with [stack configuration](/core-concepts/stacks). +This configuration below is defined in the `atmos.yaml` and instructs atmos where to find +your stack configurations. +::: + + +```yaml +stacks: + # Can also be set using 'ATMOS_STACKS_BASE_PATH' ENV var, or '--config-dir' and '--stacks-dir' command-line arguments + # Supports both absolute and relative paths + base_path: "stacks" + + # Can also be set using 'ATMOS_STACKS_INCLUDED_PATHS' ENV var (comma-separated values string) + included_paths: + # Tell Atmos to search for the top-level stack manifests in the `orgs` folder and its sub-folders + - "orgs/**/*" + + # Can also be set using 'ATMOS_STACKS_EXCLUDED_PATHS' ENV var (comma-separated values string) + excluded_paths: + # Tell Atmos that all `_defaults.yaml` files are not top-level stack manifests + - "**/_defaults.yaml" + + # To define Atmos stack naming convention, use either `name_pattern` or `name_template`. + # `name_template` has higher priority (if `name_template` is specified, `name_pattern` will be ignored). + # `name_pattern` uses the predefined context tokens {namespace}, {tenant}, {environment}, {stage}. + # `name_pattern` can also be set using 'ATMOS_STACKS_NAME_PATTERN' ENV var + name_pattern: "{tenant}-{environment}-{stage}" + # `name_template` is a Golang template. + # For the template tokens, and you can use any Atmos sections and attributes that the Atmos command + # `atmos describe component -s ` generates (refer to https://atmos.tools/cli/commands/describe/component). + # `name_template` can also be set using 'ATMOS_STACKS_NAME_TEMPLATE' ENV var + # name_template: "{{.vars.tenant}}-{{.vars.environment}}-{{.vars.stage}}" +``` + + +- `stacks.base_path` specifies the path to the folder where **all** Atmos stack config files (stack manifests) are defined. + If the global `base_path` is not provided or is an empty string, `stacks.base_path` is an independent setting that supports both absolute and + relative paths. If the global `base_path` is defined, `stacks.base_path` is relative to the global `base_path` + +- `stacks.included_paths` tells Atmos where to search for the top-level stack manifests + + :::note + Atmos top-level stack manifests are configuration files that define **all** settings and components for the corresponding environment (organization, + OU/tenant, account, region), and they are used in `atmos` CLI commands like `atmos terraform plan -s ` and + `atmos terraform apply -s ` + ::: + +- `stacks.excluded_paths` tells Atmos which paths from `stacks.included_paths` to exclude. For example, we will exclude the config files that don't + contain the top-level stack manifests, but just define the default values that get imported into top-level stack manifests + + :::note + The `_defaults.yaml` files is the recommended way to define the stack manifests with the + default configurations for organizations, OUs/tenants, accounts and regions. The `_defaults.yaml` files themselves are not top-level Atmos stacks, + they just contain the default values for the organizations, OUs/tenants, accounts and regions (to make the entire configuration reusable and DRY) + ::: + +- `stacks.name_pattern` configures the name pattern for the top-level Atmos stacks using the context variables `namespace`, `tenant`, `environment` + and `stage` as the tokens. Depending on the structure of your organization, OUs, accounts and regions, set `stacks.name_pattern` to the + following: + + - `name_pattern: {stage}` - if you use just one region and a few accounts (stages) in just one organization and one OU. In this case, the + top-level Atmos stacks will use just the `stage` (account) in their names, and to provision the Atmos components in the top-level stacks, you will + be executing Atmos commands like `atmos terraform apply --stack dev`, `atmos terraform apply --stack staging` + and `atmos terraform apply --stack prod` + + - `name_pattern: {environment}-{stage}` - if you have multiple regions and accounts (stages) in just one organization and one OU. In this case, the + top-level Atmos stacks will use the `environment` (region) and `stage` (account) in their names, and to provision the Atmos components in the + top-level stacks, you will be executing Atmos commands + like `atmos terraform apply --stack ue2-dev`, `atmos terraform apply --stack uw2-staging` + and `atmos terraform apply --stack ue1-prod`. Note that the `name_pattern` can also be defined + as `{stage}-{environment}`, in which case the Atmos commands will look like `atmos terraform apply --stack dev-ue2` + + - `name_pattern: {tenant}-{environment}-{stage}` - if you have multiple regions, OUs (tenants) and accounts (stages) in just one organization. In + this case, the top-level Atmos stacks will use the `tenant`, `environment` (region) and `stage` (account) in their names, and to provision the + Atmos components in the top-level stacks, you will be executing Atmos commands + like `atmos terraform apply --stack plat-ue2-dev`, `atmos terraform apply --stack core-uw2-staging` + and `atmos terraform apply --stack plat-ue1-prod`, where `plat` and `core` are the OUs/tenants in your organization + + - `name_pattern: {namespace}-{tenant}-{environment}-{stage}` - if you have a multi-org, multi-tenant, multi-account and multi-region architecture. + In this case, the top-level Atmos stacks will use the `namespace`, `tenant`, `environment` (region) and `stage` (account) in their names, and to + provision the Atmos components in the top-level stacks, you will be executing Atmos commands + like `atmos terraform apply --stack org1-plat-ue2-dev`, `atmos terraform apply --stack org2-core-uw2-staging` + and `atmos terraform apply --stack org2-plat-ue1-prod`, where `org1` and `org2` are the organization names (defined as `namespace` in + the corresponding `_defaults.yaml` config files for the organizations) + +- `stacks.name_template` serves the same purpose as `stacks.name_pattern` (defines the naming convention for the top-level Atmos stacks), but + provides much more functionality. Instead of using the predefined context variables as tokens, it uses [Go templates](https://pkg.go.dev/text/template). + [Sprig Functions](https://masterminds.github.io/sprig/) are supported as well + + - For the `Go` template tokens, and you can use any Atmos sections (e.g. `vars`, `providers`, `settings`) + that the Atmos command [`atmos describe component -s `](/cli/commands/describe/component) generates + for a component in a stack. + + - `name_template: "{{.vars.tenant}}-{{.vars.environment}}-{{.vars.stage}}"` defines the same name pattern for the top-level + Atmos stacks as `name_pattern: "{tenant}-{environment}-{stage}"` does + + - Since `stacks.name_template` allows using any variables form the `vars` section (and other sections), you can define + your own naming convention for your organization or for different clouds (AWS, Azure, GCP). For example, in the + corresponding `_defaults.yaml` stack manifests, you can use the following variables: + + - `org` instead of `namespace` + - `division` instead of `tenant` + - `region` instead of `environment` + - `account` instead of `stage` + + Then define the following `stacks.name_template` in `atmos.yaml`: + + ```yaml title="atmos.yaml" + stacks: + name_template: "{{.vars.division}}-{{.vars.account}}-{{.vars.region}}" + ``` + + You will be able to execute all Atmos commands using the newly defined naming convention: + + ```shell + atmos terraform plan -s + atmos terraform apply -s + atmos describe component -s + ``` + + :::note + Use either `stacks.name_pattern` or `stacks.name_template` to define the naming convention for the top-level Atmos stacks. + + `stacks.name_template` has higher priority. + + If `stacks.name_template` is specified, `stacks.name_pattern` will be ignored. + ::: + +:::tip +Refer to [Atmos Design Patterns](/design-patterns) for the examples on how to configure the `stacks` section in `atmos.yaml` for different use-cases +::: diff --git a/website/docs/reference/schemas.mdx b/website/docs/cli/schemas.mdx similarity index 94% rename from website/docs/reference/schemas.mdx rename to website/docs/cli/schemas.mdx index 2820fd6bf..4ccd15921 100644 --- a/website/docs/reference/schemas.mdx +++ b/website/docs/cli/schemas.mdx @@ -1,15 +1,15 @@ --- -title: Atmos Schemas +title: Atmos Manifest JSON Schema description: Atmos Schemas sidebar_label: Schemas sidebar_position: 5 --- import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' -## Atmos Manifest JSON Schema - -[Atmos Manifest JSON Schema](pathname:///schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) can be used to validate Atmos stack manifests and provide -auto-completion. + +[Atmos Manifest JSON Schema](pathname:///schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) can be used to validate Atmos stack manifests and provide auto-completion. + ### Validate and Auto-Complete Atmos Manifests in IDEs @@ -18,8 +18,6 @@ or [Visual Studio Code](https://code.visualstudio.com/), the schema can offer au all sections in them, are correct. -
- :::tip A list of editors that support validation using [JSON Schema](https://json-schema.org/) can be @@ -27,8 +25,6 @@ found [here](https://json-schema.org/implementations#editors). ::: -
- ### Validate Atmos Manifests on the Command Line Atmos can use the [Atmos Manifest JSON Schema](pathname:///schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) to validate Atmos stack manifests on the @@ -37,7 +33,7 @@ command line by executing the command [`atmos validate stacks`](/cli/commands/va For this to work, configure the following: - Add the [Atmos Manifest JSON Schema](pathname:///schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) to your repository, for example - in [`stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) + in [`stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) - Configure the following section in the `atmos.yaml` [CLI config file](/cli/configuration) @@ -53,7 +49,7 @@ For this to work, configure the following: - Execute the command [`atmos validate stacks`](/cli/commands/validate/stacks) -- Instead of configuring the `schemas.atmos.manifest` section in `atmos.yaml`, you can provide the path to the Atmos Manifest JSON Schema file by +- Instead of configuring the `schemas.atmos.manifest` section in `atmos.yaml`, you can provide the path to the Atmos Manifest JSON Schema file by using the ENV variable `ATMOS_SCHEMAS_ATMOS_MANIFEST` or the `--schemas-atmos-manifest` command line argument: ```shell @@ -61,14 +57,12 @@ For this to work, configure the following: atmos validate stacks --schemas-atmos-manifest stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json ``` -
- In case of any validation errors (invalid YAML syntax, Atmos manifest JSON Schema errors, invalid imports, etc.), you'll get an output from the command similar to the following: ```text -Atmos manifest JSON Schema validation error in the +Atmos manifest JSON Schema validation error in the file 'catalog/invalid-yaml-and-schema/invalid-import-5.yaml': { "valid": false, @@ -94,7 +88,7 @@ file 'catalog/invalid-yaml-and-schema/invalid-import-5.yaml': ] } -Atmos manifest JSON Schema validation error in the +Atmos manifest JSON Schema validation error in the file 'catalog/invalid-yaml-and-schema/invalid-schema-8.yaml': { "valid": false, @@ -120,7 +114,7 @@ file 'catalog/invalid-yaml-and-schema/invalid-schema-8.yaml': ] } -no matches found for the import 'globals/tenant1-globals-does-not-exist' in the +no matches found for the import 'globals/tenant1-globals-does-not-exist' in the file 'catalog/invalid-yaml-and-schema/invalid-import-1.yaml' invalid import in the file 'catalog/invalid-yaml-and-schema/invalid-import-2.yaml' @@ -143,8 +137,6 @@ yaml: line 4: could not find expected ':' ``` -
- ## References - https://json-schema.org diff --git a/website/docs/reference/versioning.md b/website/docs/cli/versioning.mdx similarity index 96% rename from website/docs/reference/versioning.md rename to website/docs/cli/versioning.mdx index 0b76766b4..a1f2b428e 100644 --- a/website/docs/reference/versioning.md +++ b/website/docs/cli/versioning.mdx @@ -3,8 +3,11 @@ title: Atmos Versioning sidebar_label: Versioning sidebar_position: 4 --- +import Intro from '@site/src/components/Intro' + Atmos follows the Semantic Versioning (SemVer) convention: major.minor.patch. + Incompatible changes increment the major version, adding backwards-compatible functionality increments the minor version, and backwards-compatible bug fixes increment the patch version. diff --git a/website/docs/community/community.mdx b/website/docs/community/community.mdx new file mode 100644 index 000000000..3c20ee5cc --- /dev/null +++ b/website/docs/community/community.mdx @@ -0,0 +1,30 @@ +--- +title: Community +sidebar_position: 1 +sidebar_label: Community +sidebar_class_name: hidden +description: Community +id: community +--- +import DocCardList from '@theme/DocCardList' +import Intro from '@site/src/components/Intro' + +# Community Resources + + +Need help? Join the community! + +Atmos has a great community of active users who are all more than willing to help each other out. So, join us! + + +Found a bug or issue? Please report it in [our issue tracker](https://github.com/cloudposse/atmos/issues) + +:::tip Join us on Office Hours + +We hold ["office hours" every Wednesday at 11:30am PST](/community/office-hours). + +::: + +Are you more into email? Sign up for [Cloud Posse's Weekly Newsletter](https://newsletter.cloudposse.com) to get the latest news about things happening in our community and other news about building Open Source infrastructure—straight into your inbox. + + diff --git a/website/docs/community/office-hours.mdx b/website/docs/community/office-hours.mdx new file mode 100644 index 000000000..d7edb21dc --- /dev/null +++ b/website/docs/community/office-hours.mdx @@ -0,0 +1,19 @@ +--- +title: Office Hours +sidebar_position: 3 +sidebar_label: Office Hours +description: Office Hours with Cloud Posse +id: office-hours +--- +import HubspotForm from 'react-hubspot-form' + +# Office Hours Registration + + console.log('Submit!')} + onReady={(form) => console.log('Form ready!')} + loading={
Loading...
} +/> diff --git a/website/docs/community/slack.mdx b/website/docs/community/slack.mdx new file mode 100644 index 000000000..281de6d5f --- /dev/null +++ b/website/docs/community/slack.mdx @@ -0,0 +1,26 @@ +--- +title: "#atmos" +sidebar_position: 3 +sidebar_label: Slack +description: Cloud Posse's SweetOps Slack Community +id: slack +--- + +## Join our Slack Community! + +Atmos has a great community of active users who are all more than willing to help each other out. So, join us! + + + + diff --git a/website/docs/contributing/coc.md b/website/docs/contribute/coc.mdx similarity index 63% rename from website/docs/contributing/coc.md rename to website/docs/contribute/coc.mdx index eec210a1a..027c7665a 100644 --- a/website/docs/contributing/coc.md +++ b/website/docs/contribute/coc.mdx @@ -1,12 +1,15 @@ --- -sidebar_position: 1 +sidebar_position: 2 title: Code of Conduct sidebar_label: Code of Conduct --- +import Intro from '@site/src/components/Intro' + As contributors and maintainers of the Atmos project by [Cloud Posse](https://cloudposse.com), we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities. + -Communication through any of Cloud Posse's channels (GitHub, [Slack](https://slack.cloudposse.com), [Forum](https://ask.cloudposse.com/), [mailing lists](https://cloudposse.com/newsletter), [Twitter](https://twitter.com/cloudposse), etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. +Communication through any of Cloud Posse's channels ([GitHub](https://github.com/cloudposse), [Slack](https://slack.cloudposse.com), [mailing lists](https://cloudposse.com/newsletter), [Twitter](https://twitter.com/cloudposse), etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Atmos project to do the same. diff --git a/website/docs/contributing/contributing.mdx b/website/docs/contribute/contributing.mdx similarity index 59% rename from website/docs/contributing/contributing.mdx rename to website/docs/contribute/contributing.mdx index b068c585e..3aa390177 100644 --- a/website/docs/contributing/contributing.mdx +++ b/website/docs/contribute/contributing.mdx @@ -1,7 +1,8 @@ --- title: Contributing -sidebar_position: 10 +sidebar_position: 4 sidebar_label: Contributing +sidebar_class_name: hidden description: Contributing id: contributing --- @@ -9,6 +10,6 @@ id: contributing # Contributing -import DocCardList from "@theme/DocCardList"; +import DocCardList from '@theme/DocCardList' diff --git a/website/docs/contributing/how-to-contribute.md b/website/docs/contribute/how-to-contribute.md similarity index 94% rename from website/docs/contributing/how-to-contribute.md rename to website/docs/contribute/how-to-contribute.md index 239e7f9fd..7c0de3205 100644 --- a/website/docs/contributing/how-to-contribute.md +++ b/website/docs/contribute/how-to-contribute.md @@ -1,14 +1,14 @@ --- title: How to Contribute -sidebar_position: 2 -sidebar_label: Contributing +sidebar_position: 3 +sidebar_label: How to Contribute --- Thanks for the interest in contributing to the Atmos project! ## Contributing Etiquette -Please see the [Contributor Code of Conduct](coc.md) for information on the rules of conduct. +Please see the [Contributor Code of Conduct](/contribute/coc) for information on the rules of conduct. ## Creating an Issue diff --git a/website/docs/core-concepts/components/component-library.md b/website/docs/core-concepts/components/component-library.mdx similarity index 94% rename from website/docs/core-concepts/components/component-library.md rename to website/docs/core-concepts/components/component-library.mdx index dc18ba44d..0502b71ad 100644 --- a/website/docs/core-concepts/components/component-library.md +++ b/website/docs/core-concepts/components/component-library.mdx @@ -5,9 +5,11 @@ sidebar_label: Library description: "A component library is a collection of reusable building blocks." id: library --- +import Intro from '@site/src/components/Intro' -A component library is a collection of reusable "components" that are reused any number of times from within [Stacks](/core-concepts/stacks). -It's helpful to think of these as the essential "building blocks" of infrastructure, like VPCs, clusters or databases. + +A component library is a collection of reusable "components" that are reused any number of times from within [Stacks](/core-concepts/stacks). It's helpful to think of these "building blocks" as the essentials of infrastructure, like VPCs, clusters or databases. They should all be kept in a library. + :::tip Get a head start by utilizing Cloud Posse's free [Terraform components for AWS](https://github.com/cloudposse/terraform-aws-components), available on GitHub. @@ -56,7 +58,7 @@ If using `terraform` with multiple clouds, use the [multi-cloud filesytem layout ``` :::tip -Organizing the components on the filesystem is configurable in the [Atmos CLI configuration](/cli/configuration#configuration-file-atmosyaml). +Organizing the components on the filesystem is configurable in the [Atmos CLI configuration](/cli/configuration/#configuration-file-atmosyaml). ::: diff --git a/website/docs/core-concepts/components/component-oriented-programming.md b/website/docs/core-concepts/components/component-oriented-programming.md deleted file mode 100644 index daca01edd..000000000 --- a/website/docs/core-concepts/components/component-oriented-programming.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Component-Oriented Programming -sidebar_position: 6 -sidebar_label: Component-Oriented Programming -id: component-oriented-programming ---- - -[Component-Oriented Programming](https://en.wikipedia.org/wiki/Component-based_software_engineering) is a reuse-based approach to defining, -implementing and composing loosely-coupled independent components into systems. - -Atmos supports the following concepts and principles of **Component-Oriented Programming (COP)**: - -- [Single Inheritance](/core-concepts/components/inheritance#single-inheritance) - when an Atmos component inherits the configuration properties from - another Atmos component - -- [Multiple Inheritance](/core-concepts/components/inheritance#multiple-inheritance) - when an Atmos component inherits from more than one Atmos - component - -- Dynamic Polymorphism - ability to use and override base component(s) properties - -- Encapsulation - enclose a set of related configuration properties into reusable loosely-coupled modules. Encapsulation is implemented - by [Atmos Components](/core-concepts/components) which are opinionated building blocks of Infrastructure-as-Code (IAC) that solve one specific - problem or use-case - -- Abstraction, which is accomplished by these Atmos features: - - Principle of Abstraction: in a given stack, "hide" all but the relevant information about a component configuration in order to reduce complexity - and increase efficiency - - Abstract Components: if a component is marked as `abstract`, it can be used only as a base for other components and can't be provisioned - using `atmos` or CI/CD systems like [Spacelift](https://spacelift.io) or [Atlantis](https://www.runatlantis.io) (see - our [integrations](/integrations) for details) - -
- -:::info - -These concepts and principles are implemented and used in Atmos by combining two features: [`import`](/core-concepts/stacks/imports) -and `metadata` component's configuration section. - -::: - -## References - -- [Abstract Component Atmos Design Pattern](/design-patterns/abstract-component) -- [Component Inheritance Atmos Design Pattern](/design-patterns/component-inheritance) diff --git a/website/docs/core-concepts/components/component-validation.mdx b/website/docs/core-concepts/components/component-validation.mdx deleted file mode 100644 index b24e0952e..000000000 --- a/website/docs/core-concepts/components/component-validation.mdx +++ /dev/null @@ -1,454 +0,0 @@ ---- -title: Component Validation -sidebar_position: 2 -sidebar_label: Validation -description: Use JSON Schema and OPA policies to validate Components. -id: validation ---- -import Terminal from '@site/src/components/Terminal' - -Validation is essential for ensuring clean and correct configurations, especially in environments where multiple teams contribute -to the development and deployment processes. Atmos enhances this validation process in two significant ways with [JSON Schema](https://json-schema.org/) and [OPA](https://www.openpolicyagent.org/) policies. - -Atmos component validation allows: - -* Validate component config (`vars`, `settings`, `backend`, `env`, `overrides` and other sections) using JSON Schema - -* Check if the component config (including relations between different component variables) is correct to allow or deny component provisioning using - OPA/Rego policies - -:::tip - -Refer to [atmos validate component](/cli/commands/validate/component) CLI command for more information - -::: - -## JSON Schema - -Atmos has native support for [JSON Schema](https://json-schema.org/), which can validate the schema of configurations. JSON Schema is an industry -standard and provides a vocabulary to annotate and validate JSON documents for correctness. - -This is powerful stuff: because you can define many schemas, it's possible to validate components differently for different environments or teams. - -## Open Policy Agent (OPA) - -The [Open Policy Agent](https://www.openpolicyagent.org/docs/latest/) (OPA, pronounced “oh-pa”) is another open-source industry standard that provides -a general-purpose policy engine to unify policy enforcement across your stacks. The OPA language (Rego) is a high-level declarative language for -specifying policy as code. Atmos has native support for the OPA decision-making engine to enforce policies across all the components in your stacks -(e.g. for microservice configurations). - -## Usage - -Atmos `validate component` command supports `--schema-path`, `--schema-type` and `--module-paths` command line arguments. -If the arguments are not provided, Atmos will try to find and use the `settings.validation` section defined in the component's YAML config. - -```bash -# Validate 'vpc' component using JSON Schema in the 'plat-ue2-prod' stack -atmos validate component vpc -s plat-ue2-prod --schema-path vpc/validate-vpc-component.json --schema-type jsonschema - -# Validate 'vpc' component using OPA policy in the 'plat-ue2-prod' stack -atmos validate component vpc -s plat-ue2-prod --schema-path vpc/validate-vpc-component.rego --schema-type opa - -# Validate 'vpc' component using OPA policy in the 'plat-ue2-dev' stack with additional module paths 'catalog/constants' -atmos validate component vpc -s plat-ue2-dev --schema-path vpc/validate-vpc-component.rego --schema-type opa --module-paths catalog/constants - -# Validate 'vpc' component using OPA policy in the 'plat-ue2-dev' stack with additional module paths 'catalog' -atmos validate component vpc -s plat-ue2-dev --schema-path vpc/validate-vpc-component.rego --schema-type opa --module-paths catalog - -# Validate 'vpc' component in the 'plat-ue2-prod' stack -atmos validate component vpc -s plat-ue2-prod - -# Validate 'vpc' component in the 'plat-ue2-dev' stack -atmos validate component vpc -s plat-ue2-dev - -# Validate 'vpc' component in the 'plat-ue2-dev' stack with a timeout of 15 seconds -atmos validate component vpc -s plat-ue2-dev --timeout 15 -``` - -### Configure Component Validation - -In [`atmos.yaml`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/rootfs/usr/local/etc/atmos/atmos.yaml), add the `schemas` -section: - -```yaml title="atmos.yaml" -# Validation schemas (for validating atmos stacks and components) -schemas: - # https://json-schema.org - jsonschema: - # Can also be set using `ATMOS_SCHEMAS_JSONSCHEMA_BASE_PATH` ENV var, or `--schemas-jsonschema-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks/schemas/jsonschema" - # https://www.openpolicyagent.org - opa: - # Can also be set using `ATMOS_SCHEMAS_OPA_BASE_PATH` ENV var, or `--schemas-opa-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks/schemas/opa" -``` - -In the component [manifest](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/catalog/vpc/defaults.yaml), add -the `settings.validation` section: - -```yaml title="examples/quick-start/stacks/catalog/vpc/defaults.yaml" -components: - terraform: - vpc: - metadata: - # Point to the Terraform component - component: vpc - settings: - # Validation - # Supports JSON Schema and OPA policies - # All validation steps must succeed to allow the component to be provisioned - validation: - validate-vpc-component-with-jsonschema: - schema_type: jsonschema - # 'schema_path' can be an absolute path or a path relative to 'schemas.jsonschema.base_path' defined in `atmos.yaml` - schema_path: "vpc/validate-vpc-component.json" - description: Validate 'vpc' component variables using JSON Schema - check-vpc-component-config-with-opa-policy: - schema_type: opa - # 'schema_path' can be an absolute path or a path relative to 'schemas.opa.base_path' defined in `atmos.yaml` - schema_path: "vpc/validate-vpc-component.rego" - # An array of filesystem paths (folders or individual files) to the additional modules for schema validation - # Each path can be an absolute path or a path relative to `schemas.opa.base_path` defined in `atmos.yaml` - # In this example, we have the additional Rego modules in `stacks/schemas/opa/catalog/constants` - module_paths: - - "catalog/constants" - description: Check 'vpc' component configuration using OPA policy - # Set `disabled` to `true` to skip the validation step - # `disabled` is set to `false` by default, the step is allowed if `disabled` is not declared - disabled: false - # Validation timeout in seconds - timeout: 10 -``` - -Add the following JSON Schema in the -file [`stacks/schemas/jsonschema/vpc/validate-vpc-component.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/schemas/jsonschema/vpc/validate-vpc-component.json): - -```json title="examples/quick-start/stacks/schemas/jsonschema/vpc/validate-vpc-component.json" -{ - "$id": "vpc-component", - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "vpc component validation", - "description": "JSON Schema for the 'vpc' Atmos component.", - "type": "object", - "properties": { - "vars": { - "type": "object", - "properties": { - "region": { - "type": "string" - }, - "cidr_block": { - "type": "string", - "pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$" - }, - "map_public_ip_on_launch": { - "type": "boolean" - } - }, - "additionalProperties": true, - "required": [ - "region", - "cidr_block", - "map_public_ip_on_launch" - ] - } - } -} -``` - -Add the following Rego package in the file [`stacks/schemas/opa/catalog/constants/constants.rego`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/schemas/opa/catalog/constants/constants.rego): - -```rego title="examples/quick-start/stacks/schemas/opa/catalog/constants/constants.rego" -package atmos.constants - -vpc_dev_max_availability_zones_error_message := "In 'dev', only 2 Availability Zones are allowed" - -vpc_prod_map_public_ip_on_launch_error_message := "Mapping public IPs on launch is not allowed in 'prod'. Set 'map_public_ip_on_launch' variable to 'false'" - -vpc_name_regex := "^[a-zA-Z0-9]{2,20}$" - -vpc_name_regex_error_message := "VPC name must be a valid string from 2 to 20 alphanumeric chars" -``` - -Add the following OPA policy in the file [`stacks/schemas/opa/vpc/validate-vpc-component.rego`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/schemas/opa/vpc/validate-vpc-component.rego): - -```rego title="examples/quick-start/stacks/schemas/opa/vpc/validate-vpc-component.rego" -# Atmos looks for the 'errors' (array of strings) output from all OPA policies -# If the 'errors' output contains one or more error messages, Atmos considers the policy failed - -# 'package atmos' is required in all `atmos` OPA policies -package atmos - -import future.keywords.in - -# Import the constants from the file `stacks/schemas/opa/catalog/constants/constants.rego` -import data.atmos.constants.vpc_dev_max_availability_zones_error_message -import data.atmos.constants.vpc_prod_map_public_ip_on_launch_error_message -import data.atmos.constants.vpc_name_regex -import data.atmos.constants.vpc_name_regex_error_message - -# In production, don't allow mapping public IPs on launch -errors[vpc_prod_map_public_ip_on_launch_error_message] { - input.vars.stage == "prod" - input.vars.map_public_ip_on_launch == true -} - -# In 'dev', only 2 Availability Zones are allowed -errors[vpc_dev_max_availability_zones_error_message] { - input.vars.stage == "dev" - count(input.vars.availability_zones) != 2 -} - -# Check VPC name -errors[vpc_name_regex_error_message] { - not re_match(vpc_name_regex, input.vars.name) -} -``` - -
- -:::note - -Atmos supports OPA policies for components validation in a single Rego file and in multiple Rego files. - -As shown in the example above, you can define some Rego constants, modules and helper functions in a separate -file `stacks/schemas/opa/catalog/constants/constants.rego`, and then import them into the main policy -file `stacks/schemas/opa/vpc/validate-vpc-component.rego`. - -You also need to specify the `module_paths` attribute in the component's `settings.validation` section. -The `module_paths` attribute is an array of filesystem paths (folders or individual files) to the additional modules for schema validation. -Each path can be an absolute path or a path relative to `schemas.opa.base_path` defined in `atmos.yaml`. -If a folder is specified in `module_paths`, Atmos will recursively process the folder and all its sub-folders and load all Rego files into the OPA -engine. - -This allows you to separate the common OPA modules, constants and helper functions into a catalog of reusable Rego modules, -and to structure your OPA policies to make them DRY. - -::: - -
- -Run the following commands to validate the component in the stacks: - - -```console -Mapping public IPs on launch is not allowed in 'prod'. Set 'map_public_ip_on_launch' variable to 'false' - -exit status 1 -``` - - - -```console -In 'dev', only 2 Availability Zones are allowed -VPC name must be a valid string from 2 to 20 alphanumeric chars - -exit status 1 -``` - - - -```console -Validate 'vpc' component variables using JSON Schema -{ - "valid": false, - "errors": [ - { - "keywordLocation": "", - "absoluteKeywordLocation": "file:///examples/quick-start/stacks/schemas/jsonschema/vpc-component#", - "instanceLocation": "", - "error": "doesn't validate with file:///examples/quick-start/stacks/schemas/jsonschema/vpc-component#" - }, - { - "keywordLocation": "/properties/vars/properties/cidr_block/pattern", - "absoluteKeywordLocation": "file:///examples/quick-start/stacks/schemas/jsonschema/vpc-component#/properties/vars/properties/cidr_block/pattern", - "instanceLocation": "/vars/cidr_block", - "error": "does not match pattern '^([0-9]{1,3}\\\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$'" - } - ] -} - -exit status 1 -``` - - -Try to run the following commands to provision the component in the stacks: - -```bash -atmos terraform apply vpc -s plat-ue2-prod -atmos terraform apply vpc -s plat-ue2-dev -``` - -Since the OPA validation policies don't pass, Atmos does not allow provisioning the component in the stacks: - - -![atmos-validate-vpc-in-plat-ue2-prod](/img/atmos-validate-infra-vpc-in-tenant1-ue2-dev.png) - - - -![atmos-validate-vpc-in-plat-ue2-dev](/img/atmos-validate-infra-vpc-in-tenant1-ue2-dev.png) - - -## OPA Policy Examples - -```rego -# 'atmos' looks for the 'errors' (array of strings) output from all OPA policies -# If the 'errors' output contains one or more error messages, 'atmos' considers the policy failed - -# 'package atmos' is required in all 'atmos' OPA policies -package atmos - -import future.keywords.in - -# Import the constants -import data.atmos.constants.vpc_dev_max_availability_zones_error_message -import data.atmos.constants.vpc_prod_map_public_ip_on_launch_error_message -import data.atmos.constants.vpc_name_regex -import data.atmos.constants.vpc_name_regex_error_message - -# Function `object_has_key` checks if an object has the specified key with a string value -# https://www.openpolicyagent.org/docs/latest/policy-reference/#types -object_has_key(o, k) { - some item - item = o[k] - type_name(item) == "string" -} - -# In production, don't allow mapping public IPs on launch -errors[vpc_prod_map_public_ip_on_launch_error_message] { - input.vars.stage == "prod" - input.vars.map_public_ip_on_launch == true -} - -# In 'dev', only 2 Availability Zones are allowed -errors[vpc_dev_max_availability_zones_error_message] { - input.vars.stage == "dev" - count(input.vars.availability_zones) != 2 -} - -# Check VPC name -errors[vpc_name_regex_error_message] { - not re_match(vpc_name_regex, input.vars.name) -} - -# Check the app hostname usign Regex -errors[message] { - not re_match("^([a-z0-9]+([\\-a-z0-9]*[a-z0-9]+)?\\.){1,}([a-z0-9]+([\\-a-z0-9]*[a-z0-9]+)?){1,63}(\\.[a-z0-9]{2,7})+$", input.vars.app_config.hostname) - message = "'app_config.hostname' must contain at least a subdomain and a top level domain. Example: subDomain1.topLevelDomain.com" -} - -# Check the email address usign Regex -errors[message] { - not re_match("^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$", input.vars.app_config.contact.email) - message = "'app_config.contact.email' must be a valid email address" -} - -# Check the phone number usign Regex -errors[message] { - not re_match("^[\\+]?[(]?[0-9]{3}[)]?[-\\s\\.]?[0-9]{3}[-\\s\\.]?[0-9]{4,6}", input.vars.app_config.contact.phone) - message = "'app_config.contact.phone' must be a valid phone number" -} - -# Check if the component has a `Team` tag -errors[message] { - not object_has_key(input.vars.tags, "Team") - message = "All components must have 'Team' tag defined to specify which team is responsible for managing and provisioning them" -} - -# Check if the Team has permissions to provision components in an OU (tenant) -errors[message] { - input.vars.tags.Team == "devs" - input.vars.tenant == "corp" - message = "'devs' team cannot provision components into 'corp' OU" -} - -# Check the message of the day from the manager -# If `settings.notes.allowed` is set to `false`, output the message from the manager -errors[message] { - input.settings.notes.allowed == false - message = concat("", [input.settings.notes.manager, " says: ", input.settings.notes.message]) -} - -# Check `notes2` config in the free-form Atmos section `settings` -errors[message] { - input.settings.notes2.message == "" - message = "'notes2.message' should not be empty" -} - -# Check that the `app_config.hostname` variable is defined only once for the stack accross all stack manifests -# Refer to https://atmos.tools/cli/commands/describe/component#sources-of-component-variables for details on how -# 'atmos' detects sources for all variables -# https://www.openpolicyagent.org/docs/latest/policy-language/#universal-quantification-for-all -errors[message] { - hostnames := {app_config | some app_config in input.sources.vars.app_config; app_config.hostname} - count(hostnames) > 0 - message = "'app_config.hostname' variable must be defined only once for the stack accross all stack manifests" -} - -# This policy checks that the 'bar' variable is not defined in any of the '_defaults.yaml' Atmos stack manifests -# Refer to https://atmos.tools/cli/commands/describe/component#sources-of-component-variables for details on how -# 'atmos' detects sources for all variables -# https://www.openpolicyagent.org/docs/latest/policy-language/#universal-quantification-for-all -errors[message] { - # Get all 'stack_dependencies' of the 'bar' variable - stack_dependencies := input.sources.vars.bar.stack_dependencies - # Get all stack dependencies of the 'bar' variable where 'stack_file' ends with '_defaults' - defaults_stack_dependencies := {stack_dependency | some stack_dependency in stack_dependencies; endswith(stack_dependency.stack_file, "_defaults")} - # Check the count of the stack dependencies of the 'bar' variable where 'stack_file' ends with '_defaults' - count(defaults_stack_dependencies) > 0 - # Generate the error message - message = "The 'bar' variable must not be defined in any of '_defaults.yaml' stack manifests" -} - -# This policy checks that if the 'foo' variable is defined in the 'stack1.yaml' stack manifest, it cannot be overriden in 'stack2.yaml' -# Refer to https://atmos.tools/cli/commands/describe/component#sources-of-component-variables for details -# on how 'atmos' detects sources for all variables -# https://www.openpolicyagent.org/docs/latest/policy-language/#universal-quantification-for-all -errors[message] { - # Get all 'stack_dependencies' of the 'foo' variable - stack_dependencies := input.sources.vars.foo.stack_dependencies - # Check if the 'foo' variable is defined in the 'stack1.yaml' stack manifest - stack1_dependency := endswith(stack_dependencies[0].stack_file, "stack1") - stack1_dependency == true - # Get all stack dependencies of the 'foo' variable where 'stack_file' ends with 'stack2' (this means that the variable - # is redefined in one of the files 'stack2') - stack2_dependencies := {stack_dependency | some stack_dependency in stack_dependencies; endswith(stack_dependency.stack_file, "stack2")} - # Check the count of the stack dependencies of the 'foo' variable where 'stack_file' ends with 'stack2' - count(stack2_dependencies) > 0 - # Generate the error message - message = "If the 'foo' variable is defined in 'stack1.yaml', it cannot be overriden in 'stack2.yaml'" -} - -# This policy shows an example on how to check the imported files in the stacks -# All stack files (root stacks and imported) that the current component depends on are in the `deps` section -# For example: -# deps: -# - catalog/xxx -# - catalog/yyy -# - orgs/zzz/_defaults -errors[message] { - input.vars.tags.Team == "devs" - input.vars.tenant == "corp" - input.deps[_] == "catalog/xxx" - message = "'devs' team cannot import the 'catalog/xxx' file when provisioning components into 'corp' OU" -} - -errors["'service_1_name' variable length must be greater than 10 chars"] { - count(input.vars.service_1_name) <= 10 -} -``` - -
- -:::note - -- If a regex pattern in the 're_match' function contains a backslash to escape special chars (e.g. '\.' or '\-'), - it must be escaped with another backslash when represented as a regular Go string ('\\.', '\\-'). - -- The reason is that backslash is also used to escape special characters in Go strings like newline (\n). - -- If you want to match the backslash character itself, you'll need four slashes. - -::: diff --git a/website/docs/core-concepts/components/components.mdx b/website/docs/core-concepts/components/components.mdx index 86848b2fd..4e609ea04 100644 --- a/website/docs/core-concepts/components/components.mdx +++ b/website/docs/core-concepts/components/components.mdx @@ -1,24 +1,28 @@ --- title: Atmos Components -sidebar_position: 1 -sidebar_label: Components +sidebar_position: 2 +sidebar_label: Build Components description: Components are opinionated building blocks of infrastructure as code that solve one specific problem or use-case. --- +import Intro from '@site/src/components/Intro' -Components are opinionated, self-contained building blocks of Infrastructure-as-Code (IAC) that solve one specific problem or use-case. -Those Components are then configured inside of one or more [Stacks](/core-concepts/stacks). + +When you design cloud architectures with Atmos, you start by breaking them apart into pieces called components. Then, you [implement Terraform "root modules"](/core-concepts/components/terraform) for each of those components, and [compose them with Stack configurations](/core-concepts/stacks). + -Atmos was designed to be tool-agnostic, but also supports several native integrations with tools like [`terraform`](/cli/commands/terraform/usage) and [`helmfile`](/cli/commands/helmfile/usage). -A common use-case for Atmos is implementing components for [Terraform "root modules"](https://developer.hashicorp.com/terraform/language/modules#the-root-module). +The most common use-case for Atmos is using implementing components using [Terraform "root modules"](https://developer.hashicorp.com/terraform/language/modules#the-root-module). But since Atmos was designed to be tool-agnostic, [custom commands](/core-concepts/custom-commands) can be used to implement components for any type of tooling. + +Components can be as small as you'd like (but we don't recommend too small), or as large as a [Terralith](/terms/terralith) (but we don't recommend that either). See our [best practices for components](/best-practices/components) to get a sense of what we recommend. :::tip -Components are things like [Terraform "root" modules](https://developer.hashicorp.com/terraform/language/modules#the-root-module), Helm Charts, Dockerfiles, or any fundamental building block of infrastructure. + +Typical components of an architecture are things like VPCs, clusters, databases, buckets, load balancers, and applications. Implement components using [Terraform "root" modules](https://developer.hashicorp.com/terraform/language/modules#the-root-module). + ::: ## Use-cases -Components offer a multitude of applications across various business scenarios. Cloud Posse publishes its AWS components for free, so you can see -some [technical use-cases for Terraform components](https://docs.cloudposse.com/components/category/aws/). +Components offer a multitude of applications across various business scenarios. Cloud Posse publishes its AWS components for free, so you can see some [technical use-cases for Terraform components](https://docs.cloudposse.com/components/category/aws/). - **Accelerate Development Cycles:** By reusing components, development teams can significantly shorten the time from concept to deployment, facilitating faster product iterations and quicker responses to market changes. @@ -26,181 +30,18 @@ some [technical use-cases for Terraform components](https://docs.cloudposse.com/ - **Enhance Collaboration Across Teams:** Components foster a shared understanding and approach to infrastructure, promoting collaboration between development, operations, and security teams, leading to more cohesive and secure product development. -## Best Practices - -Here are some essential best practices to follow when designing architectures using infrastructure as code (IaC), focusing on optimizing -component design, reusability, and lifecycle management. These guidelines are designed to help developers and operators build efficient, -scalable, and reliable systems, ensuring a smooth and effective infrastructure management process. - -- **Keep Your Components Small to Reduce the Blast Radius of Changes.**
Focus on creating small, reusable components that adhere to the UNIX philosophy - by doing one thing well. This strategy leads to simpler updates, more straightforward troubleshooting, quicker plan/apply cycles, and a - clearer separation of responsibilities. -- **Split Components By Lifecycle.**
For instance, a VPC, which is rarely destroyed, should be managed separately from more dynamic - resources like clusters or databases that may frequently scale or undergo updates. -- **Make Them Opinionated, But Not Too Opinionated.**
Ensure components are generalized to prevent the proliferation of similar components, - thereby promoting easier testing, reuse, and maintenance. -- **Use Parameterization, But Avoid Over-Parameterization.**
Good parameterization ensures components are reusable, but components become difficult to - test and document with too many parameters. -- **Avoid Creating Factories Inside of Components.**
Minimize the blast radius of changes and maintain fast plan/apply cycles by not embedding factories within components that provision lists of resources. Instead, leverage [Stack configurations to serve as factories](https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)) for provisioning multiple component instances. This approach keeps the state isolated and scales efficiently with the increasing number of component instances. -- **Use Component Libraries & Vendoring** Utilize a centralized [component library](/core-concepts/components/library) to distribute and - share components across the organization efficiently. This approach enhances discoverability by centralizing where components are stored, preventing sprawl and ensuring components are easily accessible to everyone. Employ vendoring to retrieve remote dependencies, like components, ensuring the practice of immutable infrastructure. -- **Enforce Standards using OPA Policies**
Apply component validation within stacks to establish policies governing component usage. These policies can be tailored as needed, allowing the same component to be validated differently depending on its context of use. -- **Organize Related Components with Folders.**
Organize multiple related components in a common folder. Use nested folders as necessary, to logically group components. For example, by grouping components by cloud provider and layer (e.g. `components/terraform/aws/network/`) -- **Document Component Interfaces and Usage.**
Utilize tools such as [terraform-docs](https://terraform-docs.io) to thoroughly document the input variables and outputs of your component. Include snippets of stack configuration to simplify understanding for developers on integrating the component into their stack configurations. Providing examples that cover common use-cases of the component is particularly effective. -- **Version Components for Breaking Changes.**
Use versioned folders within the component to delineate major versions (e.g. `/components/terraform//v1/`) -- **Use a Monorepo for Your Components.**
For streamlined development and simplified dependency management, smaller companies should consolidate stacks and components in a single monorepo, facilitating easier updates and unified versioning. Larger companies and enterprises with multiple monorepos can benefit from a central repository for upstream components, and then use vendoring to easily pull in these shared components to team-specific monorepos. -- **Maintain Loose Coupling Between Components.**
Avoid directly invoking one component from within another to ensure components remain loosely coupled. Specifically for Terraform components (root modules), this practice is unsupported due to the inability to define a backend in a child module, potentially leading to unexpected outcomes. It's crucial to steer clear of this approach to maintain system integrity. -- **Reserve Code Generation for Emergencies.**
We generally advise against using code generation for application logic (components), because it's challenging to ensure good test coverage (e.g. with `terratest`) and no one likes to code review machine-generated boilerplate in Pull Requests. - -## Component Schema - -To configure a Component in a [Stack](/core-concepts/stacks), A Component consists of the infrastructure as code business logic (e.g. a Terraform "root" module) as well as the configuration of that -component. The configuration of a component is stored in a Stack configuration. - -
- -:::info Disambiguation - -- **Terraform Component** is a [Terraform Root Module](https://developer.hashicorp.com/terraform/language/modules#the-root-module) - that consists of the resources defined in the `.tf` files in a working directory - (e.g. [components/terraform/infra/vpc](https://github.com/cloudposse/atmos/tree/master/examples/tests/components/terraform/infra/vpc)) - -- **Atmos Component** provides configuration (variables and other settings) for a type of component (e.g. a Terraform component) and is defined in one or more YAML stack config - files (which are called [Atmos stacks](/core-concepts/stacks)) - -::: - -
- -The schema of an Atmos Component in an Atmos Stack is as follows: - -```yaml -components: - terraform: - # the slug of the component - example: - - # configuration specific to atmos - metadata: - # Components can be of type "real" (default) or "abstract" - type: real - # This is the directory path of the component. - # In this example, we're referencing a component in the `components/terraform/stable/example` folder. - component: stable/example - - # We can leverage multiple inheritance to sequentially deep merge multiple configurations - inherits: - - example-defaults - - # Settings are where we store configuration related to integrations. - # It's a freeform map; anything can be placed here. - settings: - spacelift: { } - - # Define the terraform variables, which will get deep-merged and exported to a `.tfvars` file by atmos. - vars: - enabled: true - name: superduper - nodes: 10 -``` - -### Component Attributes - -#### vars - -The `vars` section is a free-form map. Use [component validation](/core-concepts/components/validation) to enforce policies. - -#### vars.namespace - -This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. - -The namespace of all stacks. Typically, there will be one namespace for the organization. - -Example: - -```yaml -vars: - namespace: acme -``` - -#### vars.tenant - -This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. - -In a multi-tenant configuration, the tenant represents a single `tenant`. By convention, we typically -recommend that every tenant have its own Organizational Unit (OU). - -Example: - -```yaml -vars: - tenant: platform -``` - -#### vars.stage - -This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. - -The `stage` is where workloads run. See our [glossary](/terms) for disambiguation. - -Example: - -```yaml -vars: - # Production stage - stage: prod -``` - -#### vars.environment - -This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. - -The `environment` is used for location where things run. See our [glossary](/terms) for disambiguation. - -Example: - -```yaml - -vars: - # us-east-1 - environment: ue1 -``` - -#### metadata - -The `metadata` section extends functionality of the component. - -#### settings - -The `settings` block is a free-form map used to pass configuration information to [integrations](/integrations). - -### Types of Components - -The type of component is expressed in the `metadata.type` parameter of a given component configuration. - -There are two types of components: - -- `real` - is a ["concrete"](https://en.wikipedia.org/wiki/Concrete_class) component instance that can be provisioned -- `abstract` - a component configuration, which cannot be instantiated directly. The concept is borrowed - from ["abstract base classes"](https://en.wikipedia.org/wiki/Abstract_type) of Object-Oriented Programming - ## Flavors of Components Atmos natively supports two kinds of components, but using [custom commands](/core-concepts/custom-commands), the [CLI](/cli) can be extended to support anything (e.g. `docker`, `packer`, `ansible`, etc.) -1. **Terraform:** These are stand-alone "root modules" that implement some piece of your infrastructure. For example, typical components might be an +1. [Terraform](/core-concepts/components/terraform): These are stand-alone "root modules" that implement some piece of your infrastructure. For example, typical components might be an EKS cluster, RDS cluster, EFS filesystem, S3 bucket, DynamoDB table, etc. You can find the [full library of SweetOps Terraform components on GitHub](https://github.com/cloudposse/terraform-aws-components). By convention, we store components in the `components/terraform/` directory within the infrastructure repository. -2. **Helmfiles**: These are stand-alone applications deployed using [`helmfile`](https://github.com/helmfile) to Kubernetes. For example, typical +2. [Helmfiles](/core-concepts/components/helmfile): These are stand-alone applications deployed using [`helmfile`](https://github.com/helmfile) to Kubernetes. For example, typical helmfiles might deploy the DataDog agent, `cert-manager` controller, `nginx-ingress` controller, etc. By convention, we store these types of components in the `components/helmfile/` directory within the infrastructure repository. ## Terraform Components One important distinction about components that is worth noting about Terraform components is they should be opinionated Terraform "root" modules that typically call other child modules. Components are the building blocks of your infrastructure. This is where you define all the business logic for provisioning some common piece of infrastructure like ECR repos (with the [ecr](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/ecr) component) or EKS clusters (with the [eks/cluster](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/eks/cluster) component). Our convention is to stick Terraform components in the `components/terraform/` directory. - -If your components rely on submodules, our convention is to use a `modules/` subfolder of the component to store them. - -We do not recommend consuming one terraform component inside of another as that would defeat the purpose; each component is intended to be -a loosely coupled unit of IaC with its own lifecycle. Furthermore, since components define a state backend and providers, it's not advisable to call one root module from another root module. diff --git a/website/docs/core-concepts/components/describe-component.mdx b/website/docs/core-concepts/components/describe-component.mdx deleted file mode 100644 index ab64f9873..000000000 --- a/website/docs/core-concepts/components/describe-component.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Describe Component -sidebar_position: 4 -sidebar_label: Describing -description: Describe a component in a stack to view the fully deep-merged configuration -id: describing ---- - -Describing components is helpful to understand what the final, fully computed and deep-merged configuration of -an [Atmos component](/core-concepts/components) will look like across any number of [Atmos stacks](/core-concepts/stacks). - -The more [DRY a configuration is due to imports](/core-concepts/stacks/imports), the -more [derived the configuration is due to inheritance](/core-concepts/components/inheritance), the harder it may be to understand what the final -component configuration will be. - -For example, if we wanted to understand what the final configuration looks like for a "vpc" component running in the "production" stack in the -us-east-2 AWS region, we could do that by calling the [`atmos describe component`](/cli/commands/describe/component) command and view the YAML output: - -```shell -atmos describe component vpc -s ue2-prod -``` - -
- -For more powerful filtering options, consider [describing stacks](/core-concepts/stacks/describing) instead. - -The other helpful use-case for describing components and stacks is when developing polices for [validation](/core-concepts/components/validation) of -[Atmos components](/core-concepts/components) and [Atmos stacks](/core-concepts/stacks). OPA policies can enforce what is or is not permitted. -Everything in the output can be validated using policies that you develop. diff --git a/website/docs/integrations/helmfile.md b/website/docs/core-concepts/components/helmfile.mdx similarity index 81% rename from website/docs/integrations/helmfile.md rename to website/docs/core-concepts/components/helmfile.mdx index 52316ad50..f62714164 100644 --- a/website/docs/integrations/helmfile.md +++ b/website/docs/core-concepts/components/helmfile.mdx @@ -1,12 +1,13 @@ --- -title: Helmfile Integration +title: Using Helmfiles sidebar_position: 4 -sidebar_label: Helmfile +sidebar_label: Helmfiles --- +import Intro from '@site/src/components/Intro' -Atmos natively supports opinionated workflows for [Helmfile](https://github.com/helmfile/helmfile). - -Helmfile provides a declarative specification for deploying helm charts. + +Atmos natively supports opinionated workflows for [Helmfile](https://github.com/helmfile/helmfile). Helmfile provides a declarative specification for deploying helm charts. + For a complete list of supported commands, please see the Atmos [helmfile](/cli/commands/helmfile/usage) documentation. diff --git a/website/docs/core-concepts/components/terraform-backends.mdx b/website/docs/core-concepts/components/terraform/backends.mdx similarity index 89% rename from website/docs/core-concepts/components/terraform-backends.mdx rename to website/docs/core-concepts/components/terraform/backends.mdx index bf6e09d57..3674446ae 100644 --- a/website/docs/core-concepts/components/terraform-backends.mdx +++ b/website/docs/core-concepts/components/terraform/backends.mdx @@ -1,14 +1,16 @@ --- title: Terraform Backends -sidebar_position: 11 +sidebar_position: 2 sidebar_label: Terraform Backends description: Configure Terraform Backends. -id: terraform-backends +id: backends --- - import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' + Backends define where Terraform stores its [state](https://developer.hashicorp.com/terraform/language/state) data files. + Atmos supports all the backends supported by Terraform: @@ -30,32 +32,14 @@ Atmos supports all the backends supported by Terraform: By default, Terraform will use a backend called [local](https://developer.hashicorp.com/terraform/language/settings/backends/local), which stores Terraform state on the local filesystem, locks that state using system APIs, and performs operations locally. -Terraform's local backend is designed for development and testing purposes and is generally not recommended for production use. There are several -reasons why using the local backend in a production environment may not be suitable: - -- **State Management**: The local backend stores the Terraform state file on the local file system. In a production environment, it's crucial to have -a robust and scalable solution for managing the Terraform state. Storing state locally can lead to issues with collaboration, concurrency, and -consistency. - -- **Concurrency and Locking**: When multiple users or automation processes are working with Terraform concurrently, it's essential to ensure that only -one process can modify the infrastructure at a time. The local backend lacks built-in support for locking mechanisms that prevent multiple Terraform -instances from modifying the state simultaneously. This can lead to race conditions and conflicting changes. - -- **Collaboration**: In a production environment with multiple team members, it's important to have a centralized and shared state. The local backend -does not provide a way to easily share the state across different team members or systems. A remote backend, such as Amazon S3, Azure Storage, or -HashiCorp Consul, is more suitable for collaboration. +Terraform's local backend is designed for development and testing purposes and is generally not recommended for production use. There are several reasons why using the local backend in a production environment may not be suitable: -- **Durability and Backup**: The local backend does not provide durability or backup features. If the machine where Terraform is run experiences -issues, there's a risk of losing the state file, leading to potential data loss. Remote backends offer better durability and often provide features -for versioning and backup. +- **Not Suitable for Collaboration**: Local backend doesn't support easy state sharing. +- **No Concurrency and Locking**: Local backend lacks locking, leading to race conditions when multiple users modify the state. +- **Lacks Durability and Backup**: Local backend has no durability or backup. Machine failures can lead to data loss. +- **Unsuitable for CI/CD**: Local backend isn't ideal for CI/CD pipelines. -- **Remote Execution and Automation**: In production, it's common to use Terraform in automated workflows, such as continuous integration/continuous -deployment (CI/CD) pipelines. Remote backends are better suited for these scenarios, allowing for seamless integration with automation tools and -supporting the deployment of infrastructure as code in a reliable and controlled manner. - -To address these concerns, it's recommended to use one of the supported remote backends, such as Amazon S3, Azure Storage, Google Cloud Storage, -HashiCorp Consul, or Terraform Cloud, for production environments. Remote backends provide better scalability, collaboration support, and durability, -making them more suitable for managing infrastructure at scale in production environments. +To address these concerns, it's recommended to use one of the supported remote backends, such as Amazon S3, Azure Storage, Google Cloud Storage, HashiCorp Consul, or Terraform Cloud, for production environments. Remote backends provide better scalability, collaboration support, and durability, making them more suitable for managing infrastructure at scale in production environments. ## AWS S3 Backend @@ -81,8 +65,6 @@ terraform { ``` -
- In the example, `terraform_locks` is a DynamoDB table used for state locking. DynamoDB is recommended for locking when using the S3 backend to ensure safe concurrent access. @@ -108,13 +90,11 @@ terraform { ``` -
- - Configure Terraform S3 backend with Atmos to automatically generate a backend file for each Atmos component. This is the recommended way of configuring Terraform state backend since it offers many advantages and will save you from manually creating a backend configuration file for each component -Configuring Terraform S3 backend with Atmos consists of the three steps: +Configuring Terraform S3 backend with Atmos consists of three steps: - Set `auto_generate_backend_file` to `true` in the `atmos.yaml` CLI config file in the `components.terraform` section: @@ -127,8 +107,6 @@ components: ``` -
- - Configure the S3 backend in one of the `_defaults.yaml` manifests. You can configure it for the entire Organization, or per OU/tenant, or per region, or per account. @@ -136,8 +114,6 @@ region, or per account. The `_defaults.yaml` manifests contain the default settings for Organizations, Organizational Units and accounts. ::: -
- To configure the S3 backend for the entire Organization, add the following config in `stacks/orgs/acme/_defaults.yaml`: @@ -156,8 +132,6 @@ terraform: ``` -
- - (This step is optional) For each component, you can add `workspace_key_prefix` similar to the following: @@ -179,15 +153,11 @@ components: ``` -
- Note that this is optional. If you don’t add `backend.s3.workspace_key_prefix` to the component manifest, the Atmos component name will be used automatically (which is this example is `vpc`). `/` (slash) in the Atmos component name will be replaced with `-` (dash). We usually don’t specify `workspace_key_prefix` for each component and let Atmos use the component name as `workspace_key_prefix`. -
- Once all the above is configured, when you run the commands `atmos terraform plan vpc -s ` or `atmos terraform apply vpc -s `, before executing the Terraform commands, Atmos will [deep-merge](#terraform-backend-inheritance) the backend configurations from the `_defaults.yaml` manifest and from the component itself, and will generate a backend @@ -214,8 +184,6 @@ config JSON file `backend.tf.json` in the component's folder, similar to the fol ``` -
- You can also generate the backend configuration file for a component in a stack by executing the command [atmos terraform generate backend](/cli/commands/terraform/generate-backend). Or generate the backend configuration files for all components by executing the command [atmos terraform generate backends](/cli/commands/terraform/generate-backends). @@ -242,8 +210,6 @@ terraform: ``` -
- For each component, you can optionally add the `key` parameter similar to the following: @@ -258,8 +224,6 @@ components: ``` -
- If the `key` is not specified for a component, Atmos will use the component name (`my-component` in the example above) to auto-generate the `key` parameter in the format `.terraform.tfstate` replacing `` with the Atmos component name. In ``, all occurrences of `/` (slash) will be replaced with `-` (dash). @@ -286,8 +250,6 @@ similar to the following example: ``` -
- ## Google Cloud Storage Backend [`gcs`](https://developer.hashicorp.com/terraform/language/settings/backends/gcs) backend stores the state as an object @@ -308,8 +270,6 @@ terraform: ``` -
- For each component, you can optionally add the `prefix` parameter similar to the following: @@ -324,8 +284,6 @@ components: ``` -
- If the `prefix` is not specified for a component, Atmos will use the component name (`my-component` in the example above) to auto-generate the `prefix`. In the component name, all occurrences of `/` (slash) will be replaced with `-` (dash). @@ -349,8 +307,6 @@ similar to the following example: ``` -
- ## Terraform Cloud Backend [Terraform Cloud](https://developer.hashicorp.com/terraform/cli/cloud/settings) backend uses a `cloud` block to specify @@ -372,8 +328,6 @@ terraform: ``` -
- For each component, you can optionally specify the `workspaces.name` parameter similar to the following: @@ -389,8 +343,6 @@ components: ``` -
- If `auto_generate_backend_file` is set to `true` in the `atmos.yaml` CLI config file in the `components.terraform` section, Atmos will [deep-merge](#terraform-backend-inheritance) the backend configurations from the `_defaults.yaml` manifests and from the component itself, and will generate a backend config JSON file `backend.tf.json` in the component's folder, @@ -412,8 +364,6 @@ similar to the following example: ``` -
- Instead of specifying the `workspaces.name` parameter for each component in the component manifests, you can use the `{terraform_workspace}` token in the `cloud` backend config in the `_defaults.yaml` manifest. The token `{terraform_workspace}` will be automatically replaced by Atmos with the Terraform workspace for each component. @@ -434,10 +384,8 @@ terraform: ``` -
- :::tip -Refer to [Terraform Workspaces in Atmos](/core-concepts/components/terraform-workspaces) for more information on how +Refer to [Terraform Workspaces in Atmos](/core-concepts/components/terraform/workspaces) for more information on how Atmos calculates Terraform workspaces for components, and how workspaces can be overridden for each component. ::: @@ -448,7 +396,7 @@ Each account needs to have a separate S3 bucket, DynamoDB table, and IAM role wi (for example, the `development` Team should be able to access the Terraform backend only in the `dev` account, but not in `staging` and `prod`). Atmos supports this use-case by using deep-merging of stack manifests, [Imports](/core-concepts/stacks/imports) -and [Inheritance](/core-concepts/components/inheritance), which makes the backend configuration reusable and DRY. +and [Inheritance](/core-concepts/stacks/inheritance), which makes the backend configuration reusable and DRY. We'll split the backend config between the Organization and the accounts. @@ -467,8 +415,6 @@ terraform: ``` -
- Add the following config to the `dev` stack manifest in `stacks/orgs/acme/plat/dev/_defaults.yaml`: @@ -483,8 +429,6 @@ terraform: ``` -
- Add the following config to the `staging` stack manifest in `stacks/orgs/acme/plat/staging/_defaults.yaml`: @@ -499,8 +443,6 @@ terraform: ``` -
- Add the following config to the `prod` stack manifest in `stacks/orgs/acme/plat/prod/_defaults.yaml`: @@ -515,8 +457,6 @@ terraform: ``` -
- When you provision the `vpc` component into the `dev` account (by executing the command `atmos terraform apply vpc -s plat-ue2-dev`), Atmos will deep-merge the backend configuration from the Organization-level manifest with the configuration from the `dev` manifest, and will automatically add `workspace_key_prefix` for the component, generating the following final deep-merged backend config for the `vpc` component in the `dev` account: @@ -542,8 +482,6 @@ add `workspace_key_prefix` for the component, generating the following final dee ``` -
- In the same way, you can create different Terraform backends per Organizational Unit, per region, per account (or a group of accounts, e.g. `prod` and `non-prod`), or even per component or a set of components (e.g. root-level components like `account` and IAM roles can have a separate backend), and then configure parts of the backend config in the corresponding Atmos stack manifests. Atmos will deep-merge all the parts from the @@ -564,8 +502,6 @@ For more information on configuring and provision multiple instances of a Terraf refer to [Multiple Component Instances Atmos Design Patterns](/design-patterns/multiple-component-instances) ::: -
- For example, the following config shows how to define two Atmos components, `vpc/1` and `vpc/2`, which both point to the same Terraform component `vpc`: @@ -615,8 +551,6 @@ components: ``` -
- If we manually create a `backend.tf` file for the `vpc` Terraform component in the `components/terraform/vpc` folder using `workspace_key_prefix: "vpc"`, then both `vpc/1` and `vpc/2` Atmos components will use the same `workspace_key_prefix`, and they will not function correctly. @@ -649,8 +583,6 @@ For example, when the command `atmos terraform apply vpc/1 -s plat-ue2-dev` is e ``` -
- Similarly, when the command `atmos terraform apply vpc/2 -s plat-ue2-dev` is executed, the following `backend.tf.json` file is generated in the `components/terraform/vpc` folder: @@ -675,8 +607,6 @@ Similarly, when the command `atmos terraform apply vpc/2 -s plat-ue2-dev` is exe ``` -
- The generated files will have different `workspace_key_prefix` attribute auto-generated by Atmos. For this reason, configuring Atmos to auto-generate the backend configuration for the components in the stacks is recommended diff --git a/website/docs/core-concepts/components/remote-state-backend.mdx b/website/docs/core-concepts/components/terraform/brownfield.mdx similarity index 53% rename from website/docs/core-concepts/components/remote-state-backend.mdx rename to website/docs/core-concepts/components/terraform/brownfield.mdx index ba4c13d52..be8f8a7ed 100644 --- a/website/docs/core-concepts/components/remote-state-backend.mdx +++ b/website/docs/core-concepts/components/terraform/brownfield.mdx @@ -1,144 +1,66 @@ --- -title: Remote State Backend -sidebar_position: 16 -sidebar_label: Remote State Backend -id: remote-state-backend +title: Brownfield Considerations +sidebar_position: 7 +sidebar_label: Brownfield Considerations +id: brownfield --- +import Intro from '@site/src/components/Intro' -Atmos supports configuring [Terraform Backends](/core-concepts/components/terraform-backends) to define where -Terraform stores its [state](https://developer.hashicorp.com/terraform/language/state), -and [Remote State](/core-concepts/components/remote-state) to get the outputs -of a [Terraform component](/core-concepts/components), provisioned in the same or a -different [Atmos stack](/core-concepts/stacks), and use -the outputs as inputs to another Atmos component - -Atmos also supports Remote State Backends (in the `remote_state_backend` section), which can be used to configure the -following: - -- Override [Terraform Backend](/core-concepts/components/terraform-backends) configuration to access the - remote state of a component (e.g. override the IAM role to assume, which in this case can be a read-only role) - -- Configure a remote state of type `static` which can be used to provide configurations for - [Brownfield development](https://en.wikipedia.org/wiki/Brownfield_(software_development)) - -## Override Terraform Backend Configuration to Access Remote State - -Atmos supports the `remote_state_backend` section which can be used to provide configuration to access the remote state -of components. - -To access the remote state of components, you can override -any [Terraform Backend](/core-concepts/components/terraform-backends) -configuration in the `backend` section using the `remote_state_backend` section. The `remote_state_backend` section -is a first-class section, and it can be defined globally at any scope (organization, tenant, account, region), or per -component, and then deep-merged using [Atmos Component Inheritance](/core-concepts/components/inheritance). - -For example, let's suppose we have the following S3 backend configuration for the entire organization -(refer to [AWS S3 Backend](/core-concepts/components/terraform-backends#aws-s3-backend) for more details): - -```yaml title="stacks/orgs/acme/_defaults.yaml" -terraform: - backend_type: s3 - backend: - s3: - acl: "bucket-owner-full-control" - encrypt: true - bucket: "your-s3-bucket-name" - dynamodb_table: "your-dynamodb-table-name" - key: "terraform.tfstate" - region: "your-aws-region" - role_arn: "arn:aws:iam::xxxxxxxx:role/terraform-backend-read-write" -``` - -
- -Let's say we also have a read-only IAM role, and we want to use it to access the remote state instead of the read-write -role, because accessing remote state is a read-only operation, and we don't want to give the role more permissions than -it requires - this is the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege). - -We can add the `remote_state_backend` and `remote_state_backend_type` to override the required attributes from the -`backend` section: - -```yaml title="stacks/orgs/acme/_defaults.yaml" -terraform: - backend_type: s3 # s3, remote, vault, azurerm, gcs, cloud - backend: - s3: - acl: "bucket-owner-full-control" - encrypt: true - bucket: "your-s3-bucket-name" - dynamodb_table: "your-dynamodb-table-name" - key: "terraform.tfstate" - region: "your-aws-region" - role_arn: "arn:aws:iam::xxxxxxxx:role/terraform-backend-read-write" - - remote_state_backend_type: s3 # s3, remote, vault, azurerm, gcs, cloud, static - remote_state_backend: - s3: - role_arn: "arn:aws:iam::xxxxxxxx:role/terraform-backend-read-only" - # Override the other attributes from the `backend.s3` section as needed -``` + +There are some considerations you should be aware of when adopting Atmos in a brownfield environment. Atmos works best when you adopt the [Atmos mindset](/quick-start/mindset). + -
+The term "brownfield" comes from urban planning and refers to the redevelopment of land that was previously used and may need cleaning or modification. As it relates to infrastructure, [Brownfield development](https://en.wikipedia.org/wiki/Brownfield_(software_development)) describes the development and deployment of new software systems in the presence of existing (legacy) software applications/systems. Anytime this happens, new software architectures must take into account and coexist with the existing software. -In the example above, we've overridden the `role_arn` attribute for the `s3` backend to use the read-only role when -accessing the remote state of all components. All other attributes will be taken from the `backend` section (Atmos -deep-merges the `remote_state_backend` section with the `backend` section). +Atmos is not just a tool; it is a framework that provides a set of opinionated conventions, methodologies, design patterns, and best practices to ensure teams succeed with Terraform from the start. It can be hard to shoehorn existing systems that are not designed according to the [Atmos mindset](/quick-start/mindset). -When working with Terraform backends and writing/updating the state, the `terraform-backend-read-write` role will be -used. But when reading the remote state of components, the `terraform-backend-read-only` role will be used. +- **Decomposition**: Not only do you have challenges around how to decompose your architecture, but also the difficulty of making changes to live systems. +- **Technical Debt:** You may have significant technical debt that needs to be addressed +- **Knowledge Gaps**: There may be gaps in knowledge within the team regarding Atmos conventions and methodologies. -## Brownfield Considerations +By understanding these challenges, teams can better prepare for a smooth transition to using Atmos effectively. -The term "brownfield" comes from urban planning and refers to the redevelopment of land that was previously used and may need cleaning or modification. As it relates to infrastructure, [Brownfield development](https://en.wikipedia.org/wiki/Brownfield_(software_development)) describes development and deployment of new software -systems in the presence of existing (legacy) software applications/systems. Anytime this happens, new software architectures must take into account and coexist with the existing software. +## Brownfield Development in Atmos -In the context of Atmos, brownfield development involves adopting some new techniques, practices, and integrating them into -established systems. This can be challenging due to several factors: +Atmos is easier for new organizations or "greenfield" environments because you need to architect Terraform according to +our [best practices](/best-practices/components) to get all the benefits of Atmos. For example, when using our [Terraform components](https://github.com/cloudposse/terraform-aws-components), we frequently use [Terraform Remote State](/core-concepts/components/terraform/remote-state) to retrieve the outputs from other components. -- **Legacy Systems**: These are older systems that are still in use and may be harder to change. They might not even be managed with Terraform, or if they are, they might not provide outputs that are easily accessible in a conventional manner. +This works well when you use our components but less so when you operate in a "brownfield" environment, for example, +with an existing VPC, S3 bucket, or IAM role. -- **Complex Integrations**: Existing systems might leverage entirely different toolchains, such as CloudFormation, CDK, or Pulumi. Managing integrations and dependencies across toolchains is complicated. +When you approach brownfield development with Atmos, begin by designing what your architecture could look like if you break it down into various pieces. Then devise a plan to decompose those pieces into components you implement as Terraform "root modules". +The process of configuring Atmos components and stacks for the existing, already provisioned resources, will depend on how easy or hard this decomposition will be. Working on and updating existing infrastructure rather than creating a new one from scratch, known as "greenfield" development, will always be more difficult. -- **Technical Debt**: Over time, systems naturally accumulate technical debt, which includes outdated code, inconsistent conventions or lack of naming conventions, and suboptimal decisions that were previously made for expediency. Addressing this technical debt is crucial when adopting Atmos, as it introduces practices that ensure your system remains maintainable and scalable. +The process needs to respect the existing systems' constraints while progressively introducing improvements and modern practices. This will ultimately lead to more robust, flexible, and efficient systems. +## Remote State in Brownfield Development -## Brownfield Development in Atmos +So what happens when infrastructure wasn't provisioned by Atmos or predates your infrastructure? Then there's no way to retrieve that state in Terraform. -Atmos is easier for new organizations or "greenfield" environments because you need to architect Terraform according to -our best practices to get all the benefits of Atmos. For example, when using -our [Terraform components](https://github.com/cloudposse/terraform-aws-components), we frequently use -[Terraform Remote State](/core-concepts/components/remote-state) to retrieve the outputs from other components. -This works well when you use our components but less so when you operate in a "brownfield" environment, for example, -with an existing VPC, S3 bucket, or IAM role. - -But what happens if those things weren't provisioned by Atmos or predates your infrastructure? For this reason, we -support something we refer to as the `static` remote state backend. Using the static remote state backend, you can +For this reason, we support something we refer to as the `static` remote state backend. Using the static remote state backend, you can populate a virtual state backend with the outputs as though it had been provisioned with Terraform. You can use this technique anytime you want to use the remote state functionality in Atmos, but when the remote state was provisioned elsewhere. -In Atmos, brownfield development describes the process of configuring Atmos components and stacks for the -existing (already provisioned) resources, and working on and updating existing infrastructure rather than creating a new -one from scratch (which is known as "greenfield" development). The process respects the existing systems' constraints -while progressively introducing improvements and modern practices. This can ultimately lead to more robust, flexible, -and efficient systems. +### Hacking Remote State with `static` Backends -Atmos supports brownfield configuration by using the remote state of type `static`. -## `static` Remote State for Brownfield Development +Atmos supports brownfield configuration by using the remote state of type `static`. Suppose that we need to provision -the [`vpc`](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/terraform/vpc) +the [`vpc`](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/terraform/vpc) Terraform component and, instead of provisioning an S3 bucket for VPC Flow Logs, we want to use an existing bucket. The `vpc` Terraform component needs the outputs from the `vpc-flow-logs-bucket` Terraform component to configure [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html). Let's redesign the example with the `vpc` and `vpc-flow-logs-bucket` components described in -[Terraform Component Remote State](/core-concepts/components/remote-state) and configure the `static` remote state for +[Terraform Component Remote State](/core-concepts/components/terraform/remote-state) and configure the `static` remote state for the `vpc-flow-logs-bucket` component to use an existing S3 bucket. +## Examples + ### Configure the `vpc-flow-logs-bucket` Component In the `stacks/catalog/vpc-flow-logs-bucket.yaml` file, add the following configuration for @@ -150,7 +72,7 @@ components: vpc-flow-logs-bucket/defaults: metadata: type: abstract - # Use `static` remote state to configure the attributes for an existing + # Use `static` remote state to configure the attributes for an existing # S3 bucket for VPC Flow Logs remote_state_backend_type: static remote_state_backend: @@ -160,8 +82,6 @@ components: vpc_flow_logs_bucket_arn: "arn:aws:s3::/my-vpc-flow-logs-bucket" ``` -
- In the `stacks/ue2-dev.yaml` stack config file, add the following config for the `vpc-flow-logs-bucket-1` Atmos component in the `ue2-dev` Atmos stack: @@ -179,13 +99,11 @@ components: # Point to the Terraform component in `components/terraform` folder component: infra/vpc-flow-logs-bucket inherits: - # Inherit all settings and variables from the + # Inherit all settings and variables from the # `vpc-flow-logs-bucket/defaults` base Atmos component - vpc-flow-logs-bucket/defaults ``` -
- ### Configure and Provision the `vpc` Component In the `components/terraform/infra/vpc/remote-state.tf` file, configure the @@ -199,7 +117,7 @@ module "vpc_flow_logs_bucket" { source = "cloudposse/stack-config/yaml//modules/remote-state" version = "1.5.0" - # Specify the Atmos component name (defined in YAML stack config files) + # Specify the Atmos component name (defined in YAML stack config files) # for which to get the remote state outputs component = var.vpc_flow_logs_bucket_component_name @@ -257,8 +175,6 @@ components: vpc_flow_logs_traffic_type: "ALL" ``` -
- In the `stacks/ue2-dev.yaml` stack config file, add the following config for the `vpc/1` Atmos component in the `ue2-dev` stack: @@ -292,8 +208,6 @@ components: vpc_flow_logs_bucket_component_name: vpc-flow-logs-bucket-1 ``` -
- Having the stacks configured as shown above, we can now provision the `vpc/1` Atmos component in the `ue2-dev` stack by executing the following Atmos commands: diff --git a/website/docs/core-concepts/components/terraform-providers.mdx b/website/docs/core-concepts/components/terraform/providers.mdx similarity index 94% rename from website/docs/core-concepts/components/terraform-providers.mdx rename to website/docs/core-concepts/components/terraform/providers.mdx index 92156333e..3fe227036 100644 --- a/website/docs/core-concepts/components/terraform-providers.mdx +++ b/website/docs/core-concepts/components/terraform/providers.mdx @@ -1,15 +1,18 @@ --- title: Terraform Providers -sidebar_position: 12 +sidebar_position: 6 sidebar_label: Terraform Providers description: Configure and override Terraform Providers. -id: terraform-providers +id: providers --- import File from '@site/src/components/File' import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' + Terraform utilizes plugins known as [providers](https://developer.hashicorp.com/terraform/language/providers) for communication with cloud providers, SaaS providers, and various APIs. + In order for Terraform to install these providers, the corresponding Terraform configurations need to explicitly state what providers are required. Furthermore, certain providers require additional configuration, such as @@ -40,8 +43,6 @@ the `components/terraform/vpc/providers.tf` file: ``` -
- In this example, the `aws` provider block includes the region and IAM role required for Terraform to communicate with the AWS services. @@ -66,8 +67,6 @@ For example, the `providers` section at the global scope can look like this: ``` -
- Similarly, it can be defined (or overridden) at the OU/tenant, account and region scopes in the corresponding `_defaults.yaml` stack manifests. @@ -86,8 +85,6 @@ section. For example, the following config can be used to override the `assume_r ``` -
- You can include the `providers` sections in any Atmos stack manifest at any level of inheritance. Atmos will process, deep-merge and override all the `providers` configurations for a component in the following order: @@ -95,15 +92,11 @@ deep-merge and override all the `providers` configurations for a component in th - Base component scope (`component.terraform..providers` section) - Current component scope (`component.terraform..providers` section) -
- :::tip -Refer to [Atmos Component Inheritance](/core-concepts/components/inheritance) for more information on all types of component inheritance +Refer to [Atmos Component Inheritance](/core-concepts/stacks/inheritance) for more information on all types of component inheritance supported by Atmos ::: -
- When you define the `providers` sections, Atmos processes the inheritance chain for a component and generates a file `providers_override.tf.json` in the component's folder with the final values for all the defined providers. @@ -130,8 +123,6 @@ For example: ``` -
- The generated `providers_override.tf.json` file would look like this: @@ -148,8 +139,6 @@ The generated `providers_override.tf.json` file would look like this: ``` -
- Terraform then uses the values in the generated `providers_override.tf.json` to [override](https://developer.hashicorp.com/terraform/language/files/override) the parameters for all the providers in the file. @@ -180,24 +169,20 @@ For example: ``` -
- :::warning The above example uses a list of configuration blocks for the `aws` provider. Since it's a list, by default it doesn't work with deep-merging of stacks in the -[inheritance](/core-concepts/components/inheritance) chain since list are not deep-merged, they are replaced. +[inheritance](/core-concepts/stacks/inheritance) chain since list are not deep-merged, they are replaced. If you want to use the above configuration in the inheritance chain and allow appending or merging of lists, consider configuring the `settings.list_merge_strategy` in the `atmos.yaml` CLI config file. -For more details, refer to [Atmos CLI Settings](/cli/configuration#settings). +For more details, refer to [Atmos CLI Settings](/cli/configuration/#settings). ::: -
- ## References - [Terraform Providers](https://developer.hashicorp.com/terraform/language/providers) diff --git a/website/docs/core-concepts/components/remote-state.mdx b/website/docs/core-concepts/components/terraform/remote-state.mdx similarity index 72% rename from website/docs/core-concepts/components/remote-state.mdx rename to website/docs/core-concepts/components/terraform/remote-state.mdx index c2ded31a3..35cd3f28e 100644 --- a/website/docs/core-concepts/components/remote-state.mdx +++ b/website/docs/core-concepts/components/terraform/remote-state.mdx @@ -1,16 +1,29 @@ --- -title: Terraform Component Remote State -sidebar_position: 14 -sidebar_label: Remote State +title: Using Remote State +sidebar_position: 4 +sidebar_label: Using Remote State id: remote-state --- +import Intro from '@site/src/components/Intro' +import KeyPoints from '@site/src/components/KeyPoints' +import Note from '@site/src/components/Note' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import File from '@site/src/components/File' -The Terraform Component Remote State is used when we need to get the outputs of a [Terraform component](/core-concepts/components), -provisioned in the same or a different [Atmos stack](/core-concepts/stacks), and use the outputs as inputs to another Atmos component. + +Terraform natively supports the concept of remote state and there's a very easy way to access the outputs of one Terraform component in another component. We simplify this using the `remote-state` module, which is stack-aware and can be used to access the remote state of a component in the same or a different Atmos stack. + -:::info +As your architecture grows, it helps to be more intentional about how you deconstruct and organize your components to keep your Terraform state small (see our [best practices](/best-practices/components)). By creating smaller components, your state becomes naturally more manageable. However, this introduces a new problem: there are now dependencies between your components, and the state becomes distributed. We need to find a new way for state to flow between your components and for and [a way to share configuration](/core-concepts/stacks/imports). Plus, we want to [avoid manual duplication of configurations](/core-concepts/stacks/inheritance) as much as possible because that leads to bugs, like copy-paste mistakes. + + +- How to use the `remote-state` module to access the remote state of a component in the same or a different Atmos stack +- How to configure Atmos to work the `remote-state` module to access the remote state of a component +- Alternatives that might be easier for your use case + -In Atmos, Terraform Remote State is implemented by using these modules: +In Atmos, this is solved by using these modules: - [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) - The Cloud Posse Terraform Provider for various utilities, including stack configuration management @@ -18,30 +31,21 @@ In Atmos, Terraform Remote State is implemented by using these modules: - [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) - Terraform module that loads and processes stack configurations from YAML sources and returns remote state outputs for Terraform components -::: - -
- -[terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) is implemented in [Go](https://go.dev/) and uses Atmos `Go` -modules to work with [Atmos CLI config](/cli/configuration) and [Atmos stacks](/core-concepts/stacks). The provider processes stack -configurations to get the final config for an Atmos component in an Atmos stack. The final component config is then used by -the [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) Terraform module to return the remote -state for the component in the stack. +The [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) is implemented in [Go](https://go.dev/) and uses Atmos `Go` modules to work with [Atmos CLI config](/cli/configuration) and [Atmos stacks](/core-concepts/stacks). The provider processes stack configurations to get the final config for an Atmos component in an Atmos stack. The final component config is then used by the [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) Terraform module to return the remote state for the component in the stack. -
+ +Terraform remote state is incompatible with the `local` backend type. This is because the local backend is not recommended for production. Review the alternatives [here](/core-concepts/share-data), or consider switching to one of the other backend types. + -:::info Disambiguation - -- **Terraform Component** is a [Terraform Root Module](https://developer.hashicorp.com/terraform/language/modules#the-root-module) and stored typically in `components/terraform/$name` - that consists of the resources defined in the `.tf` files in a working directory - (e.g. [components/terraform/infra/vpc](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/terraform/vpc)) - -- **Atmos Component** provides configuration (variables and other settings) for a component and is defined in one or more Atmos stack manifests - (a.k.a. stack conffig files) +:::tip New & Improved Way to Share Data +Atmos now supports a new way to share data between components using a template function in your Stack configurations: +``` +{{ atmos.Component("").outputs. }} +``` +This function allows reading any Atmos section or any attribute (not just outputs) from a section of an Atmos component in a stack. For more details, refer to the [`atmos.Component` function](/core-concepts/stacks/templates/functions/atmos.Component). ::: -
## Example @@ -49,8 +53,8 @@ Here is an example. Suppose that we need to provision two Terraform components: -- [vpc-flow-logs-bucket](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/terraform/vpc-flow-logs-bucket) -- [vpc](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/terraform/vpc) +- [vpc-flow-logs-bucket](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket) +- [vpc](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/terraform/vpc) The `vpc` Terraform component needs the outputs from the `vpc-flow-logs-bucket` Terraform component to configure [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html) and store them in the S3 bucket. @@ -58,14 +62,12 @@ configure [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow- We will provision the two Terraform components in the `ue2-dev` Atmos stack (in the `dev` AWS account by setting `stage = "dev"` and in the `us-east-2` region by setting `environment = "ue2"`). -
- ### Configure and Provision the `vpc-flow-logs-bucket` Component -In the `stacks/catalog/vpc-flow-logs-bucket.yaml` file, add the following default configuration for the `vpc-flow-logs-bucket/defaults` Atmos -component: +In the `stacks/catalog/vpc-flow-logs-bucket.yaml` file, add the following default configuration for the `vpc-flow-logs-bucket/defaults` Atmos component: -```yaml title="stacks/catalog/vpc-flow-logs-bucket.yaml" + +```yaml components: terraform: vpc-flow-logs-bucket/defaults: @@ -82,13 +84,13 @@ components: lifecycle_rule_enabled: false traffic_type: "ALL" ``` - -
+
In the `stacks/ue2-dev.yaml` stack config file, add the following config for the `vpc-flow-logs-bucket-1` Atmos component in the `ue2-dev` Atmos stack: -```yaml title="stacks/ue2-dev.yaml" + +```yaml # Import the base Atmos component configuration from the `catalog`. # `import` supports POSIX-style Globs for file names/paths (double-star `**` is supported). # File extensions are optional (if not specified, `.yaml` is used by default). @@ -102,7 +104,7 @@ components: # Point to the Terraform component in `components/terraform` folder component: infra/vpc-flow-logs-bucket inherits: - # Inherit all settings and variables from the + # Inherit all settings and variables from the # `vpc-flow-logs-bucket/defaults` base Atmos component - vpc-flow-logs-bucket/defaults vars: @@ -112,8 +114,7 @@ components: # Override the default variables from the base component traffic_type: "REJECT" ``` - -
+
Having the stacks configured as shown above, we can now provision the `vpc-flow-logs-bucket-1` Atmos component into the `ue2-dev` stack by executing the following Atmos commands: @@ -123,8 +124,6 @@ atmos terraform plan vpc-flow-logs-bucket-1 -s ue2-dev atmos terraform apply vpc-flow-logs-bucket-1 -s ue2-dev ``` -
- ### Configure and Provision the `vpc` Component Having the `vpc-flow-logs-bucket` Terraform component provisioned into the `ue2-dev` stack, we can now configure the `vpc` Terraform component @@ -134,18 +133,19 @@ In the `components/terraform/infra/vpc/remote-state.tf` file, configure the [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) Terraform module to obtain the remote state for the `vpc-flow-logs-bucket-1` Atmos component: -```hcl title="components/terraform/infra/vpc/remote-state.tf" + +```hcl module "vpc_flow_logs_bucket" { count = local.vpc_flow_logs_enabled ? 1 : 0 source = "cloudposse/stack-config/yaml//modules/remote-state" version = "1.5.0" - # Specify the Atmos component name (defined in YAML stack config files) + # Specify the Atmos component name (defined in YAML stack config files) # for which to get the remote state outputs component = var.vpc_flow_logs_bucket_component_name - # Override the context variables to point to a different Atmos stack if the + # Override the context variables to point to a different Atmos stack if the # `vpc-flow-logs-bucket-1` Atmos component is provisioned in another AWS account, OU or region stage = try(coalesce(var.vpc_flow_logs_bucket_stage_name, module.this.stage), null) tenant = try(coalesce(var.vpc_flow_logs_bucket_tenant_name, module.this.tenant), null) @@ -156,11 +156,13 @@ module "vpc_flow_logs_bucket" { context = module.this.context } ``` + In the `components/terraform/infra/vpc/vpc-flow-logs.tf` file, configure the `aws_flow_log` resource for the `vpc` Terraform component to use the remote state output `vpc_flow_logs_bucket_arn` from the `vpc-flow-logs-bucket-1` Atmos component: -```hcl title="components/terraform/infra/vpc/vpc-flow-logs.tf" + +```hcl locals { enabled = module.this.enabled vpc_flow_logs_enabled = local.enabled && var.vpc_flow_logs_enabled @@ -179,10 +181,12 @@ resource "aws_flow_log" "default" { tags = module.this.tags } ``` + In the `stacks/catalog/vpc.yaml` file, add the following default config for the `vpc/defaults` Atmos component: -```yaml title="stacks/catalog/vpc.yaml" + +```yaml components: terraform: vpc/defaults: @@ -203,12 +207,12 @@ components: vpc_flow_logs_log_destination_type: s3 vpc_flow_logs_traffic_type: "ALL" ``` - -
+
In the `stacks/ue2-dev.yaml` stack config file, add the following config for the `vpc/1` Atmos component in the `ue2-dev` stack: -```yaml title="stacks/ue2-dev.yaml" + +```yaml # Import the base component configuration from the `catalog`. # `import` supports POSIX-style Globs for file names/paths (double-star `**` is supported). # File extensions are optional (if not specified, `.yaml` is used by default). @@ -237,23 +241,22 @@ components: # for the `infra/vpc-flow-logs-bucket` Terraform component vpc_flow_logs_bucket_component_name: vpc-flow-logs-bucket-1 - # Override the context variables to point to a different Atmos stack if the + # Override the context variables to point to a different Atmos stack if the # `vpc-flow-logs-bucket-1` Atmos component is provisioned in another AWS account, OU or region. - # If the bucket is provisioned in a different AWS account, + # If the bucket is provisioned in a different AWS account, # set `vpc_flow_logs_bucket_stage_name` # vpc_flow_logs_bucket_stage_name: prod - # If the bucket is provisioned in a different AWS OU, + # If the bucket is provisioned in a different AWS OU, # set `vpc_flow_logs_bucket_tenant_name` # vpc_flow_logs_bucket_tenant_name: core - # If the bucket is provisioned in a different AWS region, + # If the bucket is provisioned in a different AWS region, # set `vpc_flow_logs_bucket_environment_name` # vpc_flow_logs_bucket_environment_name: uw2 ``` - -
+
Having the stacks configured as shown above, we can now provision the `vpc/1` Atmos component into the `ue2-dev` stack by executing the following Atmos commands: @@ -263,16 +266,13 @@ atmos terraform plan vpc/1 -s ue2-dev atmos terraform apply vpc/1 -s ue2-dev ``` -## Caveats +## Atmos Configuration -Both the `atmos` [CLI](/cli) and [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider use the same `Go` code, -which try to locate the [CLI config](/cli/configuration) `atmos.yaml` file before parsing and processing [Atmos stacks](/core-concepts/stacks). +Both the `atmos` [CLI](/cli) and [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider use the same `Go` code, which try to locate the [CLI config](/cli/configuration) `atmos.yaml` file before parsing and processing [Atmos stacks](/core-concepts/stacks). This means that `atmos.yaml` file must be at a location in the file system where all the processes can find it. -While placing `atmos.yaml` at the root of the repository will work for Atmos, it will not work for -the [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider because the provider gets executed from the -component's directory (e.g. `components/terraform/infra/vpc`), and we don't want to replicate `atmos.yaml` into every component's folder. +While placing `atmos.yaml` at the root of the repository will work for Atmos, it will not work for the [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider because the provider gets executed from the component's directory (e.g. `components/terraform/infra/vpc`), and we don't want to replicate `atmos.yaml` into every component's folder. :::info @@ -285,16 +285,16 @@ component's directory (e.g. `components/terraform/infra/vpc`), and we don't want ::: -:::note + +
+ Initial Atmos configuration can be controlled by these ENV vars: -Initial Atmos configuration can be controlled by these ENV vars: + - `ATMOS_CLI_CONFIG_PATH` - where to find `atmos.yaml`. Absolute path to a folder where the `atmos.yaml` CLI config file is located + - `ATMOS_BASE_PATH` - absolute path to the folder containing the `components` and `stacks` folders +
+
-- `ATMOS_CLI_CONFIG_PATH` - where to find `atmos.yaml`. Absolute path to a folder where the `atmos.yaml` CLI config file is located -- `ATMOS_BASE_PATH` - absolute path to the folder containing the `components` and `stacks` folders - -::: - -
+### Recommended Options For this to work for both the `atmos` CLI and the Terraform provider, we recommend doing one of the following: @@ -309,8 +309,8 @@ For this to work for both the `atmos` CLI and the Terraform provider, we recomme set `ATMOS_CLI_CONFIG_PATH=/atmos/config`. Then set the ENV var `ATMOS_BASE_PATH` pointing to the absolute path of the root of the repo - When working in a Docker container, place `atmos.yaml` in the `rootfs` directory - at [/rootfs/usr/local/etc/atmos/atmos.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/rootfs/usr/local/etc/atmos/atmos.yaml) - and then copy it into the container's file system in the [Dockerfile](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/Dockerfile) + at [/rootfs/usr/local/etc/atmos/atmos.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml) + and then copy it into the container's file system in the [Dockerfile](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/Dockerfile) by executing the `COPY rootfs/ /` Docker command. Then in the Dockerfile, set the ENV var `ATMOS_BASE_PATH` pointing to the absolute path of the root of the repo. Note that the [Atmos example](https://github.com/cloudposse/atmos/blob/master/examples/quick-start) uses [Geodesic](https://github.com/cloudposse/geodesic) as the base Docker image. [Geodesic](https://github.com/cloudposse/geodesic) sets the ENV @@ -338,10 +338,10 @@ For this to work for both the `atmos` CLI and the Terraform provider, we recomme and the [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) module will get the remote state outputs for the Atmos component provisioned in that region -## Read remote state by using `atmos.Component` `Go` template function - + Atmos supports an alternative way to read the outputs (remote state) of components directly in Atmos stack manifests by using the `atmos.Component` `Go` template function and the `outputs` section instead of using the `remote-state` module and configuring Terraform/OpenTofu components to use the module. -For more details, refer to [`atmos.Component` function](/core-concepts/template-functions/atmos.Component). +Learn How + diff --git a/website/docs/core-concepts/components/terraform/state-backend.mdx b/website/docs/core-concepts/components/terraform/state-backend.mdx new file mode 100644 index 000000000..383f63893 --- /dev/null +++ b/website/docs/core-concepts/components/terraform/state-backend.mdx @@ -0,0 +1,85 @@ +--- +title: State Backend Configuration +sidebar_position: 3 +sidebar_label: Backend Configuration +id: state-backend +--- +import Intro from '@site/src/components/Intro' + + +Atmos supports configuring [Terraform Backends](/core-concepts/components/terraform/backends) to define where Terraform stores its [state](https://developer.hashicorp.com/terraform/language/state), and [Remote State](/core-concepts/components/terraform/remote-state) to get the outputs of a [Terraform component](/core-concepts/components), provisioned in the same or a different [Atmos stack](/core-concepts/stacks), and use the outputs as inputs to another Atmos component. + + +Bear in mind that Atmos is simply managing the configuration of the Backend; +provisioning the backend resources themselves, is the responsibility of a Terraform component. + +Atmos also supports Remote State Backends (in the `remote_state_backend` section), which can be used to configure the +following: + +- Override [Terraform Backend](/core-concepts/components/terraform/backends) configuration to access the + remote state of a component (e.g. override the IAM role to assume, which in this case can be a read-only role) + +- Configure a remote state of type `static` which can be used to provide configurations for + [Brownfield development](https://en.wikipedia.org/wiki/Brownfield_(software_development)) + +## Override Terraform Backend Configuration to Access Remote State + +Atmos supports the `remote_state_backend` section which can be used to provide configuration to access the remote state +of components. + +To access the remote state of components, you can override +any [Terraform Backend](/core-concepts/components/terraform/backends) +configuration in the `backend` section using the `remote_state_backend` section. The `remote_state_backend` section +is a first-class section, and it can be defined globally at any scope (organization, tenant, account, region), or per +component, and then deep-merged using [Atmos Component Inheritance](/core-concepts/stacks/inheritance). + +For example, let's suppose we have the following S3 backend configuration for the entire organization +(refer to [AWS S3 Backend](/core-concepts/components/terraform/backends#aws-s3-backend) for more details): + +```yaml title="stacks/orgs/acme/_defaults.yaml" +terraform: + backend_type: s3 + backend: + s3: + acl: "bucket-owner-full-control" + encrypt: true + bucket: "your-s3-bucket-name" + dynamodb_table: "your-dynamodb-table-name" + key: "terraform.tfstate" + region: "your-aws-region" + role_arn: "arn:aws:iam::xxxxxxxx:role/terraform-backend-read-write" +``` + +Let's say we also have a read-only IAM role, and we want to use it to access the remote state instead of the read-write +role, because accessing remote state is a read-only operation, and we don't want to give the role more permissions than +it requires - this is the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege). + +We can add the `remote_state_backend` and `remote_state_backend_type` to override the required attributes from the +`backend` section: + +```yaml title="stacks/orgs/acme/_defaults.yaml" +terraform: + backend_type: s3 # s3, remote, vault, azurerm, gcs, cloud + backend: + s3: + acl: "bucket-owner-full-control" + encrypt: true + bucket: "your-s3-bucket-name" + dynamodb_table: "your-dynamodb-table-name" + key: "terraform.tfstate" + region: "your-aws-region" + role_arn: "arn:aws:iam::xxxxxxxx:role/terraform-backend-read-write" + + remote_state_backend_type: s3 # s3, remote, vault, azurerm, gcs, cloud, static + remote_state_backend: + s3: + role_arn: "arn:aws:iam::xxxxxxxx:role/terraform-backend-read-only" + # Override the other attributes from the `backend.s3` section as needed +``` + +In the example above, we've overridden the `role_arn` attribute for the `s3` backend to use the read-only role when +accessing the remote state of all components. All other attributes will be taken from the `backend` section (Atmos +deep-merges the `remote_state_backend` section with the `backend` section). + +When working with Terraform backends and writing/updating the state, the `terraform-backend-read-write` role will be +used. But when reading the remote state of components, the `terraform-backend-read-only` role will be used. diff --git a/website/docs/core-concepts/components/terraform/terraform.mdx b/website/docs/core-concepts/components/terraform/terraform.mdx new file mode 100644 index 000000000..95bbe03a3 --- /dev/null +++ b/website/docs/core-concepts/components/terraform/terraform.mdx @@ -0,0 +1,183 @@ +--- +title: Terraform Root Modules +sidebar_position: 3 +sidebar_label: Terraform Root Modules +description: Learn why Atmos can change how you think about the Terraform modules that you use to build your infrastructure. +id: terraform +--- +import DocCardList from '@theme/DocCardList' +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' + + +Use Atmos to provision your Terraform root modules and manage their configurations consistently and repeatably +by leveraging imports and inheritance for DRY configurations and reduced blast radius of changes. + + + +- Why does Terraform need additional tooling +- How does Atmos change how you write Terraform code +- How to use Terraform with Atmos + + +Atmos can change how you think about the Terraform modules that you use to build your infrastructure. + +When you design cloud architectures with Atmos, you will first break it apart into pieces called components. +Then, you will implement Terraform "root modules" for each of your components. +To make them highly reusable, they should serve a "single purpose" so that they are the smallest possible +unit of infrastructure managed in the software development lifecycle (SDLC). +Finally, you will connect your components together using stacks, so that everything comes together. + +In the [Quick Start](/quick-start/simple) tutorial, we’ll guide you through the thought process of building Terraform "root modules" that are suitable for use as components. + + +## What is Terraform? + +Terraform is a command-line utility or interpreter (like Perl or Ruby), that processes infrastructure configurations +written in ["HashiCorp's Configuration Language" ("HCL")](https://en.wikipedia.org/wiki/HCL) to orchestrate infrastructure provisioning. +Its chief role is to delineate and structure infrastructure definitions. Terraform by itself is not a framework. + +:::note Disambiguation +The term “Terraform” is used in this documentation to refer to generic concepts such as providers, modules, stacks, the +HCL-based domain-specific language and its interpreter. Atmos works with [OpenTofu](/core-concepts/projects/configuration/opentofu). +::: + +
+Fun Fact! + +HCL is backward compatible with JSON, although it's not a strict superset of JSON. +HCL is more human-friendly and readable, while JSON is often used for machine-generated configurations. +This means you can write Terraform configurations in HCL or JSON, and Terraform will understand them. +This feature is particularly useful for programmatically generating configurations or integration with systems that already use JSON. +
+ +## How has Terraform HCL Evolved? + +Terraform's HCL started strictly as a configuration language, not a markup or programming language, although it has evolved +considerably over the years. + +As Terraform progressed and HCL evolved, notably from version _0.12_ onwards, HCL began incorporating features typical +of programming languages (albeit without a debugger!). This shift enriched infrastructure definitions, positioning HCL +more as a [domain-specific programming language (DSL)](https://en.wikipedia.org/wiki/Domain-specific_language) for +defining infrastructure than strictly a configuration language (aka data interchange formats like JSON). As a result, +the complexity of configuring Terraform projects has risen, while Terraform's inherent capabilities to be configured +haven't evolved at the same pace. + +- **Rich Expressions:** Introduced a richer expression syntax, removing the need for interpolations. + +- **For Loops and Conditionals:** Added for expressions and conditional expressions. + +- **Type System:** Introduced a more explicit type system for input and output values. + +## Why is additional tooling needed when using Terraform? + +**Every foundational tool begins simply.** + +As users grow more advanced and their ambitions expand, the need for advanced tooling emerges. These shifts demonstrate that core +technologies naturally progress, spawning more advanced constructs to tackle increased intricacies and enhance efficiency -- all +while retaining their core essence. Just as CSS, NodeJS, Docker, Helm, and many other tools have evolved to +include higher-order utilities, Terraform, too, benefits from additional orchestration tools, given the complexities and challenges +users face at different stages of adoption. + +Examples of tools like these are numerous, like: + +- **CSS has Sass:** Sass provides more expressive styling capabilities, variables, and functions, making stylesheets more maintainable and organized, especially for large projects. +- **NodeJS has React:** React brings component-based architecture to JavaScript, enhancing the creation of interactive UIs, improving code reusability, and better supporting the development of large-scale applications. +- **Docker has Docker Compose:** Docker Compose simplifies the management and orchestration of multi-container Docker applications, making it easier to define, run, and scale services collectively. +- **Helm charts have Helmfiles:** While Helm charts define the blueprints of Kubernetes services, Helmfiles enable better orchestration, management, and deployment of multiple charts, similar to coordinating various instruments in a symphony. +- **Kubernetes manifests have Kustomize:** Kustomize allows customization of Kubernetes manifests without changing their original form, facilitating dynamic configurations tailored to specific deployment scenarios. + +**These days, no one would dream of building a modern web app without a framework. Why should Terraform be any different?** + +When considering Terraform in the context of large-scale organizations or enterprises, it's clear that Terraform and its inherent language don't address all challenges. This is why teams progress through [10 stages of maturity](/introduction/why-atmos). With hundreds or even of components spread across hundreds of accounts, cloud providers and managed by a vast number of DevOps engineers and developers, the complexity becomes overwhelming and difficult to manage. + +A lot of the same challenges faced by NodeJS, Docker, Helm and Kubernetes also exist in Terraform as well. + +**Challenges in Terraform are centered around Root Modules:** +- **Large-Scale Architectures**: Providing better support for large-scale service-oriented architectures +- **Composition**: Making it straightforward to compose architectures of multiple "root modules" +- **Code Reusability and Maintainability**: Simplifying the definition and reuse of "root modules" +- **Ordered Dependencies**: Handling orchestration, management, and deployment of multiple loosely coupled "root modules" +- **Sharing State**: Sharing state between "root modules" +- **CI/CD Automation**: Enhancing CI/CD automation, especially in monorepos, when there are no rollback capabilities + +These are not language problems. These are framework problems. Without a coherent framework, Terraform is hard to use at scale. +Ultimately, the goal is to make Terraform more scalable, maintainable, and developer-friendly, especially in complex and large-scale environments. + +## Refresher on Terraform Concepts + +
+
Child Modules
+
Child modules are reusable pieces of Terraform code that accept parameters (variables) for customization and emit outputs. + Outputs can be passed between child modules and used to connect them together. + They are stateless and can be invoked multiple times. Child modules can also call other child modules, making + them a primary method for reducing repetition in Terraform HCL code; it's how you DRY up your HCL code.
+ +
Root Modules
+
Root modules in Terraform are the topmost modules that can call child modules or directly use Terraform code. + The key distinction between root and child modules is that root modules maintain Terraform state, + typically stored in a remote state backend like S3. Root modules cannot call other root modules, + but they can access the outputs of any other root module using Remote State.
+ +
State Backends
+
State Backends are where the desired state of your infrastructure code is stored. + It's always defined exactly once per "root module". This where the computed state of your HCL code is stored, + and it is what `terraform apply` will execute. The most common state backend is object storage + like S3, but there are many other types of state backends available.
+ +
Remote State
+
Remote state refers to the concept of retrieving the outputs from other root modules. + Terraform natively supports passing information between "root modules" without any additional tooling, + a capability we rely on in Atmos.
+
+ + +:::info Disambiguation + +- **Terraform Component** is a [Terraform Root Module](https://developer.hashicorp.com/terraform/language/modules#the-root-module) and stored typically in `components/terraform/$name` that consists of the resources defined in the `.tf` files in a working directory + (e.g. [components/terraform/infra/vpc](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/terraform/vpc)) + +- **Stack** provides configuration (variables and other settings) for a Terraform Component and is defined in one or more Atmos stack manifests + (a.k.a. stack conffig files) + +::: + + +## Example: Provision Terraform Component + +To provision a Terraform component using the `atmos` CLI, run the following commands in the container shell: + +```console +atmos terraform plan eks --stack=ue2-dev +atmos terraform apply eks --stack=ue2-dev +``` + +where: + +- `eks` is the Terraform component to provision (from the `components/terraform` folder) +- `--stack=ue2-dev` is the stack to provision the component into + +Short versions of all command-line arguments can be used: + +```console +atmos terraform plan eks -s ue2-dev +atmos terraform apply eks -s ue2-dev +``` + +The `atmos terraform deploy` command executes `terraform apply -auto-approve` to provision components in stacks without +user interaction: + +```console +atmos terraform deploy eks -s ue2-dev +``` + +## Using Submodules (Child Modules) + +If your components rely on local submodules, our convention is to use a `modules/` subfolder of the component to store them. + + +## Terraform Usage with Atmos + +Learn how to best leverage Terraform together with Atmos. + + diff --git a/website/docs/core-concepts/components/terraform-workspaces.mdx b/website/docs/core-concepts/components/terraform/workspaces.mdx similarity index 97% rename from website/docs/core-concepts/components/terraform-workspaces.mdx rename to website/docs/core-concepts/components/terraform/workspaces.mdx index 278efff11..f32110ae1 100644 --- a/website/docs/core-concepts/components/terraform-workspaces.mdx +++ b/website/docs/core-concepts/components/terraform/workspaces.mdx @@ -1,16 +1,19 @@ --- title: Terraform Workspaces -sidebar_position: 10 +sidebar_position: 4 sidebar_label: Terraform Workspaces description: Terraform Workspaces. -id: terraform-workspaces +id: workspaces --- import File from '@site/src/components/File' import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' + In Terraform, a [workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) is a feature that allows you to manage multiple "state" environments within a Terraform configuration. Each workspace maintains its own state, allowing you to deploy and manage infrastructure configurations independently. + Workspaces are useful in several scenarios: @@ -59,8 +62,6 @@ components: ``` -
- When you provision the `vpc` component in the stack `ue2-dev` by executing the following command: @@ -69,8 +70,6 @@ When you provision the `vpc` component in the stack `ue2-dev` by executing the f ``` -
- Atmos computes the workspace name to be `ue2-dev`. Any Atmos Terraform command other than `init`, using this stack, will cause Atmos to select this workspace, creating it if needed. (This leaves the workspace selected as a side effect for subsequent Terraform commands run outside of Atmos. Atmos version 1.55 took away this side effect, but it was @@ -121,8 +120,6 @@ components: ``` -
- When you provision the components by executing the commands: @@ -132,8 +129,6 @@ When you provision the components by executing the commands: ``` -
- Atmos computes the workspace names as `ue2-dev-vpc-1` and `ue2-dev-vpc-2` respectively, and selects the appropriate workspace for each component (again, creating it if needed). This is done because the same Terraform component `vpc` is used as the workspace prefix @@ -168,8 +163,6 @@ components: ``` -
- When you provision the components by executing the commands: @@ -179,8 +172,6 @@ When you provision the components by executing the commands: ``` -
- Atmos sets the Terraform workspace `vpc-1-workspace-override` for the `vpc/1` component, and `ue2-dev-vpc-2-workspace-override` for the `vpc/2` component. @@ -195,15 +186,11 @@ The following context tokens are supported by the `metadata.terraform_workspace_ - `{component}` - `{base-component}` -
- :::tip For more information on Atmos base and derived components, and to understand the `{base-component}` token, -refer to [Atmos Component Inheritance](/core-concepts/components/inheritance) +refer to [Atmos Component Inheritance](/core-concepts/stacks/inheritance) ::: -
- ## References - [Terraform Workspaces](https://developer.hashicorp.com/terraform/language/state/workspaces) diff --git a/website/docs/core-concepts/core-concepts.mdx b/website/docs/core-concepts/core-concepts.mdx index cf8d07912..eb5ee30cb 100644 --- a/website/docs/core-concepts/core-concepts.mdx +++ b/website/docs/core-concepts/core-concepts.mdx @@ -1,17 +1,16 @@ --- -title: Core Concepts +title: Core Concepts of the Atmos Framework sidebar_position: 3 sidebar_label: Core Concepts +sidebar_class_name: hidden description: Atmos Core Concepts id: core-concepts --- -import DocCardList from "@theme/DocCardList"; - -# Core Concepts +import DocCardList from '@theme/DocCardList' Atmos simplifies the process of managing and deploying your infrastructure across cloud platforms. -Dive into these core concepts of Atmos to discover how it facilitates these processes. +Dive into these core concepts of Atmos to discover how they facilitate these processes. -You're about discover a new way to think about things... +You're about to discover a new way to think about things... diff --git a/website/docs/core-concepts/custom-commands/custom-commands.mdx b/website/docs/core-concepts/custom-commands/custom-commands.mdx index f6e337d27..684a97c74 100644 --- a/website/docs/core-concepts/custom-commands/custom-commands.mdx +++ b/website/docs/core-concepts/custom-commands/custom-commands.mdx @@ -1,16 +1,16 @@ --- title: Atmos Custom Commands -sidebar_label: Custom Commands -sidebar_position: 5 +sidebar_label: Implement Custom Commands +sidebar_position: 8 id: custom-commands --- import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' -Atmos can be easily extended to support any number of custom CLI commands. - -Custom commands are exposed through the `atmos` CLI when you run `atmos help`. It's a great way to centralize -the way operational tools are run in order to improve DX. + +Atmos can be easily extended to support any number of custom CLI commands. Custom commands are exposed through the `atmos` CLI when you run `atmos help`. It's a great way to centralize the way operational tools are run in order to improve DX. + For example, one great way to use custom commands is to tie all the miscellaneous scripts into one consistent CLI interface. Then we can kiss those ugly, inconsistent arguments to bash scripts goodbye! Just wire up the commands in atmos to call the script. Then developers can just run `atmos help` diff --git a/website/docs/core-concepts/deploy/deploy.mdx b/website/docs/core-concepts/deploy/deploy.mdx new file mode 100644 index 000000000..6a431373a --- /dev/null +++ b/website/docs/core-concepts/deploy/deploy.mdx @@ -0,0 +1,46 @@ +--- +title: Deploy Components +sidebar_position: 6 +sidebar_label: Deploy Components +description: Deploy components with a single command or in a CI/CD pipeline. +id: deploy +--- +import Intro from '@site/src/components/Intro'; + + + Once you're done developing your components and configuring them with stacks, you can deploy them with a single command or in a CI/CD pipeline. + + + +In Atmos, when we talk about "Deployment," it refers to taking the [fully rendered and deep-merged configuration](/core-concepts/describe) of a [stack](/core-concepts/stacks) and provisioning an instance of one of the components. We call this a "component instance," and it's simply a component that has been deployed in a specific stack. + +### Deployment in Atmos + +Deployment in Atmos can be approached in several ways. + +1. **Command Line Deployment**: You can always deploy on the command line using Atmos, which is particularly useful for local development or in environments that are less mature and do not yet have CI/CD capabilities. For more complicated deployments, you can leverage [workflows](/core-concepts/workflows) to orchestrate multiple deployments in a specific order or run other commands, including [custom commands](/core-concepts/custom-commands). + +2. **CI/CD Integrations**: Atmos supports several common methods for CI/CD, with [GitHub Actions](/integrations/github-actions) being the recommended method. We maintain and invest the most time and effort into GitHub Actions. However, we also support integrations with [Spacelift](/integrations/spacelift) and [Atlantis](/integrations/atlantis). + +### Configuring Dependencies Between Components + +When deploying components, it's important to consider the dependencies between components. For example, a database component might depend on a network component. When this happens, it's important to ensure that the network component is deployed before the database component. + +Make sure to [configure dependencies](/core-concepts/stacks/dependencies) between components using the `settings.depends_on` section. + +### Managing Dependency Order Between Components + +Sometimes, components have dependencies on other components. For example, a database component might depend on a network component. When this happens, it's important to ensure that the network component is deployed before the database component. + +In Atmos, support of ordered dependencies is reliant on the integration and not all integrations support ordered dependencies. + +All configurations in Atmos are defined in YAML. If you can write a Terraform module, you can essentially Terraform anything based on the stack configuration. It's important to be aware of dependencies between your components. Depending on the integration mechanism or deployment approach you choose, handling these dependencies can be either built-in or more manual. + +- [GitHub Actions](/integrations/github-actions): Currently, our GitHub Actions do not support dependency order application. +- [Spacelift](/integrations/spacelift): Our Spacelift integrations support dependency order application. +- [Atlantis](/integrations/atlantis): By customizing the template generated for Atlantis, similar dependency handling can probably be achieved, although we do not have any documentation on this. + + +### Automate Cold Starts + +Atmos supports [workflows](/core-concepts/workflows), which provide a convenient way to automate deployments, especially for cold starts. A cold start is when you go from zero to a full deployment, typically occurring on day zero in the life cycle of your resources. diff --git a/website/docs/core-concepts/describe/components.mdx b/website/docs/core-concepts/describe/components.mdx new file mode 100644 index 000000000..1ab9634c6 --- /dev/null +++ b/website/docs/core-concepts/describe/components.mdx @@ -0,0 +1,32 @@ +--- +title: Describe Components +sidebar_position: 4 +sidebar_label: Components +description: Describe a component in a stack to view the fully deep-merged configuration +id: component +--- +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' + + +Describing components helps understand the final, fully deep-merged configuration for an [Atmos component](/core-concepts/components) in each [stack](/core-concepts/stacks). + + +The more [DRY a configuration is due to imports](/core-concepts/stacks/imports), the more [derived the configuration is due to inheritance](/core-concepts/stacks/inheritance), the harder it may be to understand what the final component configuration will be. + +For example, if we wanted to understand what the final configuration looks like for a "vpc" component running in the "production" stack in the `us-east-2` AWS region, we could do that by calling the [`atmos describe component`](/cli/commands/describe/component) command and view the YAML output: + +```shell +atmos describe component vpc -s ue2-prod +``` + +For more powerful filtering options, consider [describing stacks](/core-concepts/describe/stacks) instead. + +The other helpful use-case for describing components and stacks is when developing policies for [validation](/core-concepts/validate) of +[Atmos components](/core-concepts/components) and [Atmos stacks](/core-concepts/stacks). OPA policies can enforce what is or is not permitted. Everything in the output can be validated using policies that you develop. + + + For a deep dive into describing components, refer to the CLI command reference. + Command Reference + diff --git a/website/docs/core-concepts/describe/describe.mdx b/website/docs/core-concepts/describe/describe.mdx new file mode 100644 index 000000000..e800d0413 --- /dev/null +++ b/website/docs/core-concepts/describe/describe.mdx @@ -0,0 +1,19 @@ +--- +title: Describe Configuration +sidebar_position: 5 +sidebar_label: Describe Configuration +description: Describing your configuration so you understand what's happening. +id: describing +--- +import DocCardList from '@theme/DocCardList' +import Intro from '@site/src/components/Intro' + + +Atmos is a framework for defining cloud architectures in YAML. To understand what the fully-deep merged configuration will look like, you can describe it. + + +In Stacks, you define configurations for all Components, setting up small units of infrastructure like VPCs, Clusters, and Databases. Atmos lets you combine these components into reusable, nestable Stacks using Imports. You can break down everything from simple websites to full-blown multi-account/multi-subscription cloud architectures into components. + +In this chapter, you’ll learn to describe all aspects of the fully-deep merged configurations so you can understand what Atmos stacks look like. + + diff --git a/website/docs/core-concepts/stacks/describe-stacks.mdx b/website/docs/core-concepts/describe/stacks.mdx similarity index 89% rename from website/docs/core-concepts/stacks/describe-stacks.mdx rename to website/docs/core-concepts/describe/stacks.mdx index 228baf6a5..609b056b5 100644 --- a/website/docs/core-concepts/stacks/describe-stacks.mdx +++ b/website/docs/core-concepts/describe/stacks.mdx @@ -1,14 +1,18 @@ --- title: Describe Stacks sidebar_position: 4 -sidebar_label: Describing -id: describing +sidebar_label: Stacks +id: stacks description: Describe stacks to view the fully deep-merged configuration --- import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' -Describing stacks is helpful to understand what the final, fully computed and deep-merged configuration of a stack will look like. Use this to slice -and dice the Stack configuration to show different information about stacks and component. + +Describing stacks is helpful to understand what the final, fully computed and deep-merged configuration of a stack will look like. Use this to slice and dice the Stack configuration to show different information about stacks and component. + For example, if we wanted to understand what the final configuration looks like for the "production" stack, we could do that by calling the [`atmos describe stacks`](/cli/commands/describe/stacks) command to view the YAML output. @@ -16,6 +20,12 @@ the [`atmos describe stacks`](/cli/commands/describe/stacks) command to view the The output can be written to a file by passing the `--file` command-line flag to `atmos` or even formatted as YAML or JSON by using `--format` command-line flag. +:::tip PRO TIP + +If the filtering options built-in to Atmos are not sufficient, redirect the output to [`jq`](https://stedolan.github.io/jq/) for very powerful filtering options. + +::: + Since the output of a Stack might be overwhelming, and we're only interested in some particular section of the configuration, the output can be filtered using flags to narrow the output by `stack`, `component-types`, `components`, and `sections`. The component sections can be further filtered by `atmos_component`, `atmos_stack`, `atmos_stack_file`, `backend`, `backend_type`, `command`, `component`, `env`, `inheritance`, `metadata`, @@ -178,11 +188,7 @@ plat-ue2-dev: ``` -
- -:::tip PRO TIP - -If the filtering options built-in to Atmos are not sufficient, redirect the output to [`jq`](https://stedolan.github.io/jq/) for very powerful -filtering options. - -::: + + For a deep dive on describing stacks, refer to the CLI command reference. + Command Reference + diff --git a/website/docs/core-concepts/projects/configuration/configuration.mdx b/website/docs/core-concepts/projects/configuration/configuration.mdx new file mode 100644 index 000000000..e957e17c2 --- /dev/null +++ b/website/docs/core-concepts/projects/configuration/configuration.mdx @@ -0,0 +1,258 @@ +--- +title: Configure Atmos CLI +sidebar_position: 2 +sidebar_label: Configure Atmos +description: CLI configuration for Atmos to find your Terraform components and Atmos stacks +id: configuration +--- +import EmbedFile from '@site/src/components/EmbedFile' +import KeyPoints from '@site/src/components/KeyPoints' +import Screengrab from '@site/src/components/Screengrab' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' + + +The `atmos.yaml` configuration file is used to control the behavior of the `atmos` CLI for your project. This is how Atmos knows where to find your stack configurations and components. Almost everything in Atmos is configurable via this file. + + +Because this file is crucial to the configuration of the project, it should live along side of it, with your Terraform components and Atmos stacks. It's also where you can [configure integrations](/integrations), like with our [GitHub Actions](/integrations/github-actions). + + +- What are the different configuration files in Atmos +- How to configure `atmos.yaml` for your project's filesystem layout +- How Atmos finds the `atmos.yaml` file +- How Atmos identifies stack configurations using context variables and naming patterns + + +To configure Atmos to work with your project, we'll create a file called `atmos.yaml` to tell Atmos where to find the +Terraform components and Atmos stacks. Almost everything in Atmos is configurable via this file. + +## Types of Configuration Files + +In Atmos, there are some different types of configuration files to be aware of. The most important one is the `atmos.yaml` file, which is used to configure the behavior of the `atmos` CLI. This file is used to control how Atmos finds your Terraform components and Atmos stacks. + +
+
`atmos.yaml`
+
CLI configuration for Atmos to find your Terraform components and Atmos stacks. See [vendoring](/cli/configuration).
+ +
`vendor.yaml`
+
+ Vendoring manifest for any third-party dependencies. See [vendoring](/core-concepts/vendor/vendor-manifest). + __NOTE__: The vendor manifest can import other vendor manifests, allowing you to compose them together. +
+ +
`stacks/**/*.yaml`
+
+ Vendoring manifest for any third-party dependencies. See [vendoring](/core-concepts/vendor/vendor-manifest). + __NOTE__: the actual path to the stacks directory is configurable in the `atmos.yaml` file, via the `stacks.base_path` setting. +
+ +
`workflows/**/*.yaml`
+
+ Workflow definitions. See [workflows](/core-concepts/workflows). + __NOTE__: the actual path to the workflows directory is configurable in the `atmos.yaml` file, via the `workflows.base_path` setting. +
+ +
`**/components/**/component.yaml`
+
+ Component manifest for vendoring individual components. See [component manifest](/core-concepts/vendor/component-manifest). + __NOTE__: the actual path to the components directory is configurable in the `atmos.yaml` file, via the `components..base_path` setting. +
+ +
`schemas/*.schema.json`
+
+ JSON Schema for validating Atmos manifests. See [validation](/core-concepts/validate/json-schema). + __NOTE__, the actual path to the schemas directory is configurable in the `atmos.yaml` file, via the `schemas.atmos.manifest` setting. +
+ +
`schemas/*.rego`
+
+ OPA Policy for validating Atmos manifests. See [validation](/core-concepts/validate/opa). +
+
+ +## Atmos CLI Configuration Schema + +Below is the minimum recommended configuration for Atmos to work with Terraform and to configure [Atmos components](/core-concepts/components) and [Atmos stacks](/core-concepts/stacks). Copy this YAML config below into your `atmos.yaml` file. + + + +__NOTE:__ For a detailed description of all the sections, refer to [CLI Configuration](/cli/configuration). + +### Stack Names (Slugs) + +Atmos uses “slugs” to refer to stacks, so you don't need to pass multiple arguments to idenitfy a stack or a component in a stack. + +It's a deliberate design decision of Atmos to rely strictly on configuration, rather than on file names and directory locations, which can change (and would thereby change your state). + +For example, with the command `atmos terraform apply myapp -s dev`, Atmos interprets the slug `dev` using the pattern `{stage}` to locate the correct stack configuration in the stacks directory. + +The format of this slug, is determined by one of the following settings. + +
+
`stacks.name_template` (newer format, more powerful)
+
+ The name template allows you to define a custom Go template to format the stack name. This is useful when you want to use a different naming convention for your stacks. +
+
`stacks.name_pattern` (old format, still supported)
+
+ The name pattern relies strictly on variables (`var.namespace`, `var.tenant`, `var.environment`, `var.stage`) + to identify the stack. It does not support any other variables. + + You'll still see this in many of the examples, but we recommend using the newer `name_template` format. +
+
+ +### Logging + +Atmos provides some simple settings to control how it emits events to standard error. By convention, Atmos uses standard error to communicate all events related to its own processing. We reserve standard output (stdout) for the intended output of the commands that Atmos executes. By following this convention, you can safely pipe the output from Atmos into other commands as part of a pipeline. + +
+
`logs.level`
+
+ Set to `Info` to see the most helpful logs. You can also set it to `Trace` to see all the logs, which is helpful for debugging. + Supported options are: +
+
`Info` _default_
+
Emit standard messages that describe what Atmos is doing
+ +
`Warn`
+
Show all messages with a severity of "warning" or less
+ +
`Error`
+
Show all messages with a severity of "error" or less
+ +
`Debug`
+
Emit helpful debugging information, including all other severities. This is very verbose.
+ +
`Trace`
+
Turn off all filters, and just display every single message.
+
+
+ +
`logs.file`
+
+ Set to `/dev/stderr` to send all of Atmos output to the standard error stream. This is useful when running Atmos in a CI/CD pipeline. +
+
+ +### Command Aliases + +If you get tired of typing long commands in Atmos, you can alias them using the `aliases` section. This is especially useful for commands that you run frequently, like Terraform. Aliases you define appear in the `atmos help`, so you can see them at a glance. + +```yaml +# CLI command aliases +aliases: + # Aliases for Atmos native commands + tf: terraform + tp: terraform plan + up: terraform apply + down: terraform destroy + ds: describe stacks + dc: describe component + # Aliases for Atmos custom commands + ls: list stacks + lc: list components +``` + + + Aliases can make Atmos easier to use by allowing you to define shortcuts for frequently used commands. + Learn Aliases + + +### Path Configuration + +Well-known paths are how Atmos knows how to find all your stack configurations, comoponents and workflows. Here are the essnetial paths that you need to configure: + +
+
`base_path`
+
The base path for components, stacks, and workflows configurations. We set it to an empty string because we've decided to use the ENV var `ATMOS_BASE_PATH` to point to the absolute path of the root of the repo
+ +
`components.terraform.base_path`
+
The base path to the Terraform components (Terraform root modules). As described in [Configure Repository](/quick-start/advanced/configure-repository), we've decided to put the Terraform components into the `components/terraform` directory, and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENV var) with `components.terraform.base_path` to calculate the final path to the Terraform components
+ +
`stacks.base_path`
+
The base path to the Atmos stacks. As described in [Configure Repository](/quick-start/advanced/configure-repository), we've decided to put the stack configurations into the `stacks` directory, and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENV var) with `stacks.base_path` to calculate the final path to the stacks
+ +
`stacks.included_paths`
+
List of file paths to the top-level stacks in the `stacks` directory to include in search when Atmos searches for the stack where the component is defined when executing `atmos` commands
+ +
`stacks.excluded_paths`
+
List of file paths to the top-level stacks in the `stacks` directory to exclude from search when Atmos searches for the stack where the component is defined when executing `atmos` commands
+ +
`workflows.base_path`
+
The base path to Atmos [Workflows](/core-concepts/workflows) files
+
+ +:::tip Environment variables +Everything in the `atmos.yaml` file can be overridden by environment variables. This is useful for CI/CD pipelines where you might want to control the behavior of Atmos without changing the `atmos.yaml` file. +::: + +## Custom Commands + +
+
`commands`
+
configuration for [Atmos Custom Commands](/core-concepts/custom-commands)
+
+ +See our many [practical examples](https://github.com/cloudposse/atmos/tree/main/examples) of using Custom Commands in atmos. + + + Custom Commands are a versatile and powerful feature of Atmos. They allow you to extend Atmos’s functionality to meet your specific needs without modifying its core. + Learn Custom Commands + + +## Workflows + +Workflows allow you to automate routine operations, such as orchestrating the startup behavior of a series of services. Very little about workflows is configured in the `atmos.yaml`. Only the base path to the workflows is defined here. The workflows themselves are defined in the `workflows.base_path` folder. + + + Workflows allow you to orchestrate your components or any command. Unlike Custom Commands, Workflows focus on orchestration and are reentrant, allowing you to start at any step in the workflow. + Learn Workflows + + +## Schema Validation + +
+
`schemas`
+
+ [JSON Schema](https://json-schema.org/) and [OPA Policy](https://www.openpolicyagent.org/) configurations for: + - [Atmos Manifests Validation](/cli/schemas) + - [Atmos Stack Validation](/core-concepts/validate) +
+
+ +## Atmos Search Paths + +Atmos searches for the `atmos.yaml` file in several locations, stopping at the first successful match. The search order (from highest to lowest priority) is: + +- Environment variable `ATMOS_CLI_CONFIG_PATH` +- Current working directory +- Home dir (`~/.atmos/atmos.yaml`) +- System dir (`/usr/local/etc/atmos/atmos.yaml` on Linux, `%LOCALAPPDATA%/atmos/atmos.yaml` on Windows) + +Initial Atmos configuration can be controlled by these environment variables: + +
+
`ATMOS_CLI_CONFIG_PATH`
+
Directory that contains the `atmos.yaml` (just the folder without the file name). It's not possible to change the filename at this time.
+ +
`ATMOS_BASE_PATH`
+
Base path to the `components/` and `stacks/` folders.
+
+ +## Special Considerations for Terraform Components + +If you are relying on Atmos discovering the `atmos.yaml` based on your current working directory (e.g. at the root of repository), it will work for the `atmos` CLI; however, it will **not work** for [Component Remote State](/core-concepts/components/terraform/remote-state) because it uses the [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider. + +This is because Terraform executes provider from the component's folder (e.g. `components/terraform/vpc`), so it will no longer find the file in the root of the repository, since the working directory has changed. + +Both the `atmos` CLI and [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider use the same `Go` code, which try to locate the [CLI config](/cli/configuration) `atmos.yaml` file before parsing and processing [Atmos stacks](/core-concepts/stacks). + +This means that `atmos.yaml` file must be at a location in the file system where all processes can find it, such as by explicitly specifying the path in the `ATMOS_CLI_CONFIG_PATH` environment variable. + + + For a deep-dive on configuring the Atmos CLI and all of the sections of the `atmos.yaml`, refer to CLI Configuration. + Advanced CLI Configuration + diff --git a/website/docs/integrations/opentofu.mdx b/website/docs/core-concepts/projects/configuration/opentofu.mdx similarity index 75% rename from website/docs/integrations/opentofu.mdx rename to website/docs/core-concepts/projects/configuration/opentofu.mdx index 19be2b09d..33bf8b822 100644 --- a/website/docs/integrations/opentofu.mdx +++ b/website/docs/core-concepts/projects/configuration/opentofu.mdx @@ -1,18 +1,25 @@ --- -title: OpenTofu Integration -sidebar_position: 3 -sidebar_label: OpenTofu +title: Configure OpenTofu +sidebar_position: 2 +sidebar_label: Configure OpenTofu +id: opentofu --- - import useBaseUrl from '@docusaurus/useBaseUrl'; +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' + +Atmos natively supports [OpenTofu](https://opentofu.org), similar to the way it supports [Terraform](/core-concepts/projects/configuration/terraform). It's compatible with every version of `opentofu` and designed to work with multiple different versions of it concurrently, and can even work alongside with [HashiCorp Terraform](/core-concepts/projects/configuration/terraform). OpenTofu + -Atmos natively supports [OpenTofu](https://opentofu.org), -similar to the way it supports [Terraform](/integrations/terraform). It's compatible with every version of `opentofu` and designed to -work with multiple different versions of it concurrently, and can even work alongside with [HashiCorp Terraform](/integrations/terraform). + +- How to configure Atmos to use OpenTofu for Terraform components +- How to alias `terraform` to `tofu` in Atmos +- How to configure OpenTofu for only specific components + -Please see the complete configuration options for [Terraform](/integrations/terraform), as they are the same for OpenTofu. We'll focus +Please see the complete configuration options for [Terraform](/core-concepts/projects/configuration/terraform), as they are the same for OpenTofu. We'll focus only on what's different in this document, in order to utilize OpenTofu. Keep in mind that Atmos does not handle the downloading or installation of OpenTofu; it assumes that any required binaries for the commands are already installed on your system. @@ -35,10 +42,13 @@ components: base_path: "components/tofu" ``` -:::important +:::important Disambiguation Atmos consistently utilizes the `terraform` keyword across all configurations, rather than `tofu` or `opentofu`. +The term “Terraform” is used in this documentation to refer to generic concepts such as providers, modules, stacks, the +HCL-based domain-specific language and its interpreter. ::: + Additionally, if you prefer to run `atmos tofu` instead of `atmos terraform`, you can configure an alias. Just add the following configuration somewhere in the `atmos.yaml` CLI config file: diff --git a/website/docs/integrations/terraform.md b/website/docs/core-concepts/projects/configuration/terraform.mdx similarity index 66% rename from website/docs/integrations/terraform.md rename to website/docs/core-concepts/projects/configuration/terraform.mdx index 4b93c92af..4a01b45fc 100644 --- a/website/docs/integrations/terraform.md +++ b/website/docs/core-concepts/projects/configuration/terraform.mdx @@ -1,13 +1,19 @@ --- -title: Terraform Integration -sidebar_position: 2 -sidebar_label: Terraform +title: Configure Terraform +sidebar_position: 1 +sidebar_label: Configure Terraform +id: terraform --- +import Intro from '@site/src/components/Intro' -Atmos natively supports opinionated workflows for Terraform and [OpenTofu](/integrations/opentofu). + +Atmos natively supports opinionated workflows for Terraform and [OpenTofu](/core-concepts/projects/configuration/opentofu). It's compatible with every version of terraform and designed to work with multiple different versions of Terraform -concurrently. Keep in mind that Atmos does not handle the downloading or installation of Terraform; it assumes that any -required commands are already installed on your system. +concurrently. + + +Keep in mind that Atmos does not handle the downloading or installation of Terraform; it assumes that any +required commands are already installed on your system. To automate this, consider creating a [Custom Command](/core-concepts/custom-commands) to install Terraform. Atmos provides many settings that are specific to Terraform and OpenTofu. @@ -34,6 +40,21 @@ components: auto_generate_backend_file: false ``` +
+
components.terraform.apply_auto_approve
+
if set to `true`, Atmos automatically adds the `-auto-approve` option to instruct Terraform to apply the plan without + asking for confirmation when executing `terraform apply` command
+ +
`components.terraform.deploy_run_init`
+
if set to `true`, Atmos runs `terraform init` before executing [`atmos terraform deploy`](/cli/commands/terraform/deploy) command
+ +
`components.terraform.init_run_reconfigure`
+
if set to `true`, Atmos automatically adds the `-reconfigure` option to update the backend configuration when executing `terraform init` command
+ +
`components.terraform.auto_generate_backend_file`
+
if set to `true`, Atmos automatically generates the Terraform backend file from the component configuration when executing `terraform plan` and `terraform apply` commands
+
+ ## Configuration The settings for terraform can be defined in multiple places and support inheritance. This ensures that projects can @@ -87,31 +108,3 @@ module "vars" { context = module.this.context } ``` - -## Example: Provision Terraform Component - -To provision a Terraform component using the `atmos` CLI, run the following commands in the container shell: - -```console -atmos terraform plan eks --stack=ue2-dev -atmos terraform apply eks --stack=ue2-dev -``` - -where: - -- `eks` is the Terraform component to provision (from the `components/terraform` folder) -- `--stack=ue2-dev` is the stack to provision the component into - -Short versions of all command-line arguments can be used: - -```console -atmos terraform plan eks -s ue2-dev -atmos terraform apply eks -s ue2-dev -``` - -The `atmos terraform deploy` command executes `terraform apply -auto-approve` to provision components in stacks without -user interaction: - -```console -atmos terraform deploy eks -s ue2-dev -``` diff --git a/website/docs/core-concepts/projects/layout.mdx b/website/docs/core-concepts/projects/layout.mdx new file mode 100644 index 000000000..15435dc6f --- /dev/null +++ b/website/docs/core-concepts/projects/layout.mdx @@ -0,0 +1,69 @@ +--- +title: Folder Structure +sidebar_position: 1 +sidebar_label: Folder Structure +description: Recommended way to organaize your Atmos stacks and components +id: layout +--- +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' + + +At the root of your project, you’ll typically find an `atmos.yaml` configuration file. This file defines how Atmos should discover your stack files for configuration and your Terraform root modules as components. + + + +- How to organize your project on the file system +- How to separate configuration from components +- Different ways to organize your project + + +You can find some demos of how we organize projects in the Atmos GitHub repository under the [`examples/`](https://github.com/cloudposse/atmos/tree/main/examples) folder. + +To effectively organize an Atmos project, we want to ensure you have specific locations for Atmos to find your stack configurations and components. At a minimum, we recommend the following folder structure in your project: + +## Components Folder + +This folder will contain all your components. Organize the components by toolchain. For example, if you have components for Terraform, place them in a Terraform subfolder (e.g. `components/terraform/vpc`). + +## Stack Configurations Folder + +Next, you’ll have your stacks configurations, which are organized into multiple subfolders depending on their purpose: + +### Schema Validations + +### Catalogs +This should be a separate top-level folder containing your stack configurations. Stack configurations are divided into several parts: +- **Schemas Folder**: This folder contains the schemas used to validate the stack configurations. +- **Catalog Folder**: This includes all reusable imports, which can be organized into subfolders based on logical groupings. +- **Stacks Folder**: This contains the deployable stacks. Each stack is defined in a separate YAML file. + +We follow a few conventions in our reference architecture: + +### Deployable Stacks + +- **Orgs Folder**: Represents the AWS organizations to which you deploy. You might use a folder called deploy if you have a few simple stacks. +- **Multi-Cloud Projects**: If your project involves multiple clouds, consider additional organizational strategies. + + +## Recommended Filesystem Layout +
+
`components/`
+
folder containing all your components, usually organized by your toolchain
+ +
`components/terraform`
+
folder for all Terraform "root modules"
+ +
`stacks/orgs/`
+
folder for deployable stacks
+ +
`stacks/catalog/`
+
folder for the service catalog
+ +
`stacks/workflows/`
+
folder for workflows that operate on top of stacks.
+
+ +We provide detailed guidance on organizing your folder structure, whether it’s for a simple project or enterprise-scale architecture. + +Remember, you can’t optimize for everything at once, so choose the model that best fits the stage you plan to reach when you complete the project. diff --git a/website/docs/core-concepts/projects/projects.mdx b/website/docs/core-concepts/projects/projects.mdx new file mode 100644 index 000000000..cef8d297d --- /dev/null +++ b/website/docs/core-concepts/projects/projects.mdx @@ -0,0 +1,29 @@ +--- +title: Setup Projects for Atmos +sidebar_position: 1 +sidebar_label: Setup Project +id: projects +--- +import DocCardList from '@theme/DocCardList' +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' + + +Atmos is a framework, so we suggest some conventions for organizing your infrastructure using folders to separate configuration from components. This separation is key to making your components highly reusable. + + +By keeping configuration and components distinct, you can easily manage and update each part without affecting the other. + + +- Where to put your terraform components +- Where to keep your configuration +- How to configure Atmos to work with Terraform + + +If you're more of a hands-on learner, we also go into some of these details in our [Simple Quick Start](/quick-start/simple). + +## Configuration + +Learn how to best configure a project to work with Atmos. We recommend some conventions for how to organize your project into folders, then configure the Atmos CLI to use those folders. + + diff --git a/website/docs/core-concepts/share-data/share-data.mdx b/website/docs/core-concepts/share-data/share-data.mdx new file mode 100644 index 000000000..2a02c8c72 --- /dev/null +++ b/website/docs/core-concepts/share-data/share-data.mdx @@ -0,0 +1,177 @@ +--- +title: Share Data Between Components +sidebar_position: 4 +sidebar_label: Share Data Between Components +description: Share data between loosely-coupled components in Atmos +id: share-data +--- +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import KeyPoints from '@site/src/components/KeyPoints' +import CollapsibleText from '@site/src/components/CollapsibleText' +import File from '@site/src/components/File' +import Note from '@site/src/components/Note' + + +Breaking apart your infrastructure into loosely coupled components is a great way to manage complexity and reuse code. However, sometimes, you need to share data between components. In Atmos, you can easily share settings, configurations, and outputs between components and even tap into external data sources. + + +There are two ways to approach this: using native Terraform support for remote state to read outputs from other components or using template functions in stack configurations. In this chapter, you’ll learn how to share state between components within the same stack or even across different stacks. + + +- Why you might need to share data between components +- How to share data between components using Terraform remote state +- How to use template functions to share data between components in stack configurations + + + + +## Using Template Functions + +### Function: `atmos.Component` + +The `atmos.Component` template function can read all configurations of any Atmos component, including its outputs. + +For example, we can read the `vpc_id` output of the `vpc` component in the current `.stack`, simply by doing: + +```yaml +components: + terraform: + cluster: + vars: + vpc_id: '{{ (atmos.Component "vpc" .stack).outputs.vpc_id }}' +``` + +The `atmos.Component` function returns the entire configuration of the component in the stack. The configuration is a map of all the sections of the component, including its outputs. You can access properties using dot (`.`) notation, and chain any number of attributes with dot (`.`) notation. + +To access the configuration of a component in a different stack, you can specify the stack name as the second argument. For example, here we're reading the `vpc_id` output of the `vpc` component in the `staging` stack: + +```yaml +components: + terraform: + cluster: + vars: + vpc_id: '{{ (atmos.Component "vpc" "staging").outputs.vpc_id }}' +``` + + +For more advanced examples, check out the `atmos.Component` function documentation. +Learn More + + + +### Data Sources + +Data sources are incredibly powerful. They let you glue together components leveraging external data sources without modifying a line of Terraform code. This is great when you want to leave your Terraform codebase untouched, especially if you don't control the source. + +Data sources allow you to fetch and use data from external sources in your stack configurations. You can use data sources to fetch data from APIs, various key/value storage systems, or even local files. + +They can be fetched from any of the following schemes supported by Gomplate: + + +- **AWS Systems Manager Parameter Store** (`aws+smp://`) +- **AWS Secrets Manager** (`aws+sm://`) +- **Amazon S3** (`s3://`) +- **HashiCorp Consul** (`consul://`, `consul+http://`, `consul+https://`) +- **Environment Variables** (`env://`) +- **Files** (`file://`) +- **Git Repositories** (`git://`, `git+file://`, `git+http://`, `git+https://`, `git+ssh://`) +- **Google Cloud Storage** (`gs://`) +- **HTTP/HTTPS Endpoints** (`http://`, `https://`) +- **Merging Data Sources** (`merge://`) +- **Standard Input** (`stdin://`) +- **HashiCorp Vault** (`vault://`, `vault+http://`, `vault+https://`) + + +:::tip On-the-Fly Root Modules + +When you combine data sources with [vendoring](/core-concepts/vendor), [terraform backends](/core-concepts/components/terraform/backends) and [provider](/core-concepts/components/terraform/providers) generation, you can leverage any Terraform module as a "root module" and provision it as a component with Atmos. +::: + +Configure your data sources in `atmos.yaml`, then leverage them inside stack configurations. + +Here we set up a data source called `ip`, which will fetch the public IP address by hitting the +`https://api.ipify.org?format=json` endpoint. + + +```yaml +settings: + templates: + settings: + gomplate: + timeout: 5 + datasources: + network_egress: + url: "https://api.ipify.org?format=json" + headers: + accept: + - "application/json" +``` + + +Then, you can use the `network_egress` data source in your stack configurations to fetch the public `ip`. This is useful for setting a tag indicating the IP address that provisioned the resources. + +This assumes the Terraform component accepts a `tags` variable and appropriately handles tags. + +```yaml +terraform: + vars: + tags: + provisioned_by_ip: '{{ (datasource "ip").ip }}' +``` + + + + Use data sources to fetch data from external sources and use it in your Terraform configurations. + Learn More + + +## Using Remote State + +Atmos provides a [`remote-state`](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) Terraform module that makes it easier to look up the remote state of other components in the stack. This module can be used to share data between components provisioned in the same stack or across different stacks, using native HCL. + +Our convention is to place all remote-state dependencies in the `remote-state.tf` file. This file is responsible for fetching the remote state outputs of other components in the stack. + + +```hcl +module "vpc" { + source = "cloudposse/stack-config/yaml//modules/remote-state" + version = "1.5.0" + + # Specify the Atmos component name (defined in YAML stack config files) for which to get the remote state outputs + component = "vpc" + + # `context` input is a way to provide the information about the stack (using the context + # variables `namespace`, `tenant`, `environment`, `stage` defined in the stack config) + context = module.this.context +} +``` + + +Then we can use the `module.vpc` as easily as if it were provisioned within the `myapp` component. + +This gives us the best of both worlds: the ease of use of Terraform remote state and the reduced blast radius of using smaller components. + + +```hcl +resource "aws_network_acl" "default" { + + vpc_id = module.vpc.vpc_id + + ingress { + protocol = "tcp" + rule_no = 100 + action = "allow" + cidr_block = "0.0.0.0/0" + from_port = 80 + to_port = 80 + } +} +``` + + + + Use the Terraform-native `remote-state` module to share data between components. + Learn How + diff --git a/website/docs/core-concepts/stacks/catalogs.md b/website/docs/core-concepts/stacks/catalogs.mdx similarity index 90% rename from website/docs/core-concepts/stacks/catalogs.md rename to website/docs/core-concepts/stacks/catalogs.mdx index 97b8811df..7783c0daa 100644 --- a/website/docs/core-concepts/stacks/catalogs.md +++ b/website/docs/core-concepts/stacks/catalogs.mdx @@ -1,15 +1,17 @@ --- title: Stack Catalogs sidebar_position: 3 -sidebar_label: Catalogs +sidebar_label: Build Configuration Catalogs id: catalogs -description: Catalogs are how to organize all Stack configurations for easy imports. +description: Organize Stack configurations into catalogs for easy imports. --- +import Intro from '@site/src/components/Intro' -# Catalogs + +As you start splitting your stacks apart into smaller configurations, it often makes to organize those into a catalog of reusable configurations. That way you can take advantage of imports, to reuse configuration in multiple places. Catalogs are how to logically organize all the child [Stack](/core-concepts/stacks) configurations on the filesystem for use by [imports](/core-concepts/stacks/imports). + -Catalogs are how to logically organize all the child [Stack](/core-concepts/stacks) configurations on the filesystem for use by -[imports](/core-concepts/stacks/imports). There's no "right or wrong" way to do it, and Atmos does not enforce any one convention. +There's no "right or wrong" way to do it, and Atmos does not enforce any one convention. What we've come to realize is there's no "one way" to organize Stack configurations. The best way to organize them will come down to how an organization wants to model its infrastructure. @@ -64,7 +66,7 @@ Here's an example of how Stack imports might be organized on disk. ### Mixins -We go into more detail on using [Mixins](/core-concepts/stacks/mixins) to manage snippets of reusable configuration. These Mixins are frequently used alongside the other conventions such as Teams and Organizations. +We go into more detail on using [Mixins](/core-concepts/stacks/inheritance/mixins) to manage snippets of reusable configuration. These Mixins are frequently used alongside the other conventions such as Teams and Organizations. ### Teams diff --git a/website/docs/core-concepts/stacks/define-components.mdx b/website/docs/core-concepts/stacks/define-components.mdx new file mode 100644 index 000000000..38bbe62a4 --- /dev/null +++ b/website/docs/core-concepts/stacks/define-components.mdx @@ -0,0 +1,148 @@ +--- +title: Configuring Components in Stacks +sidebar_position: 2 +sidebar_label: Configure Components +id: define-components +--- +import Intro from '@site/src/components/Intro' + + +Stacks are used to compose multiple components together and provide their configuration. The schema is the same for all stacks, but the configuration can be different. Use a combination of [imports](/core-concepts/stacks/imports), [inheritance](/core-concepts/stacks/inheritance), and [catalogs](/core-concepts/stacks/catalogs) for a template-free way to reuse configuration and [override](/core-concepts/stacks/overrides) values when needed. + + +## Component Schema + +A Component consists of the infrastructure as code business logic (e.g. a Terraform "root" module) as well as the configuration of that +component. The configuration of a component is stored in a Stack configuration. + +To configure a Component in a [Stack](/core-concepts/stacks), you define the component in the `components` section of the Stack configuration. + +:::info Disambiguation + +- **Terraform Component** is a simply a [Terraform Root Module](https://developer.hashicorp.com/terraform/language/modules#the-root-module) + that consists of the resources defined in the `.tf` files in a working directory + (e.g. [components/terraform/infra/vpc](https://github.com/cloudposse/atmos/tree/master/examples/tests/components/terraform/infra/vpc)) + +- **Component Configuration** provides configuration (variables and other settings) for a type of component (e.g. a Terraform component) + and is defined in one or more YAML stack config files (which are called [Atmos stacks](/core-concepts/stacks)) +::: + +The schema of an Atmos Component in an Atmos Stack is as follows: + +```yaml +components: + terraform: + # the slug of the component + example: + + # configuration specific to atmos + metadata: + # Components can be of type "real" (default) or "abstract" + type: real + # This is the directory path of the component. + # In this example, we're referencing a component in the `components/terraform/stable/example` folder. + component: stable/example + + # We can leverage multiple inheritance to sequentially deep merge multiple configurations + inherits: + - example-defaults + + # Settings are where we store configuration related to integrations. + # It's a freeform map; anything can be placed here. + settings: + spacelift: { } + + # Define the terraform variables, which will get deep-merged and exported to a `.tfvars` file by atmos. + vars: + enabled: true + name: superduper + nodes: 10 +``` + +### Component Attributes + +
+ +
`vars` (optional)
+
The `vars` section is a free-form map. Use [component validation](/core-concepts/validate) to enforce policies.
+ +
`vars.namespace` (optional)
+
+ This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. + + The namespace of all stacks. Typically, there will be one namespace for the organization. + + Example: + + ```yaml + vars: + namespace: acme + ``` +
+ +
`vars.tenant` (optional)
+
+ This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. + + In a multi-tenant configuration, the tenant represents a single `tenant`. By convention, we typically + recommend that every tenant have its own Organizational Unit (OU). + + Example: + + ```yaml + vars: + tenant: platform + ``` +
+ +
`vars.stage` (optional)
+
+ This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. + + The `stage` is where workloads run. See our [glossary](/terms) for disambiguation. + + Example: + + ```yaml + vars: + # Production stage + stage: prod + ``` +
+ +
`vars.environment` (optional)
+
+ This is an *optional* [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) convention. + + The `environment` is used for location where things run. See our [glossary](/terms) for disambiguation. + + Example: + + ```yaml + + vars: + # us-east-1 + environment: ue1 + ``` +
+ +
`metadata` (optional)
+
The `metadata` section extends functionality of the component.
+ +
`settings`
+
The `settings` block is a free-form map used to pass configuration information to [integrations](/integrations).
+ +
+ +### Types of Components + +The type of component is expressed in the `metadata.type` parameter of a given component configuration. + +There are two types of components: +
+
`real`
+
is a ["concrete"](https://en.wikipedia.org/wiki/Concrete_class) component instance that can be provisioned
+ +
`abstract`
+
a component configuration, which cannot be instantiated directly. The concept is borrowed from ["abstract base classes"](https://en.wikipedia.org/wiki/Abstract_type) of Object-Oriented Programming
+
diff --git a/website/docs/core-concepts/stacks/dependencies.mdx b/website/docs/core-concepts/stacks/dependencies.mdx new file mode 100644 index 000000000..ff0ec8ef7 --- /dev/null +++ b/website/docs/core-concepts/stacks/dependencies.mdx @@ -0,0 +1,86 @@ +--- +title: Configure Dependencies Between Components +sidebar_position: 3 +sidebar_label: Define Dependencies +id: dependencies +--- +import Intro from '@site/src/components/Intro' + + +Atmos supports configuring the relationships between components in the same or different stacks. You can define dependencies between components to ensure that components are deployed in the correct order. + + +Before deploying components, it's important to consider the dependencies between components. For example, a database component might depend on a network component. When this happens, it's important to ensure that the network component is deployed before the database component. + +:::important Support for Dependencies +Support for dependencies is reliant on the [integration](/integrations) used and not all integrations support dependencies. + +For example, GitHub Actions do not support dependency order applies, while [Spacelift does](https://docs.spacelift.io/concepts/stack/stack-dependencies). +::: + +You can define component dependencies by using the `settings.depends_on` section. The section used to define all the Atmos components (in +the same or different stacks) that the current component depends on. + +The `settings.depends_on` section is a map of objects. The map keys are just the descriptions of dependencies and can be strings or numbers. Provide meaningful descriptions or numbering so that people can understand what the dependencies are about. + +
+Why is `settings.depends_on` a map instead of a list? + +We originally implemented `settings.depends_on` as a list. However, since it’s not clear how lists should be deep-merged, so we decided to convert it to a map instead. In this map, the keys are lexicographically ordered, and based on that order, the dependencies are managed. +
+ + +Each object in the `settings.depends_on` section has the following schema: + +- `component` (required) - an Atmos component that the current component depends on +- `namespace` (optional) - the `namespace` where the Atmos component is provisioned +- `tenant` (optional) - the `tenant` where the Atmos component is provisioned +- `environment` (optional) - the `environment` where the Atmos component is provisioned +- `stage` (optional) - the `stage` where the Atmos component is provisioned + +The `component` attribute is required. The rest are the context variables and are used to define Atmos stacks other than the current stack. +For example, you can specify: + +- `namespace` if the `component` is from a different Organization +- `tenant` if the `component` is from a different Organizational Unit +- `environment` if the `component` is from a different region +- `stage` if the `component` is from a different account +- `tenant`, `environment` and `stage` if the component is from a different Atmos stack (e.g. `tenant1-ue2-dev`) + +In the following example, we specify that the `top-level-component1` component depends on the following: + +- The `test/test-component-override` component in the same Atmos stack +- The `test/test-component` component in Atmos stacks in the `dev` stage +- The `my-component` component from the `tenant1-ue2-staging` Atmos stack + +```yaml +components: + terraform: + top-level-component1: + settings: + depends_on: + 1: + # If the `context` (namespace, tenant, environment, stage) is not provided, + # the `component` is from the same Atmos stack as this component + component: "test/test-component-override" + 2: + # This component (in any stage) depends on `test/test-component` + # from the `dev` stage (in any `environment` and any `tenant`) + component: "test/test-component" + stage: "dev" + 3: + # This component depends on `my-component` + # from the `tenant1-ue2-staging` Atmos stack + component: "my-component" + tenant: "tenant1" + environment: "ue2" + stage: "staging" + vars: + enabled: true +``` + +:::tip + +Refer to [`atmos describe dependents` CLI command](/cli/commands/describe/dependents) for more information. + +::: diff --git a/website/docs/core-concepts/stacks/imports.mdx b/website/docs/core-concepts/stacks/imports.mdx index 130a7473e..3e9134520 100644 --- a/website/docs/core-concepts/stacks/imports.mdx +++ b/website/docs/core-concepts/stacks/imports.mdx @@ -1,24 +1,31 @@ --- -title: Stack Imports -sidebar_position: 5 -sidebar_label: Imports +title: Import Stack Configurations +sidebar_position: 3 +sidebar_label: Import Configurations id: imports --- import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' -Imports are how we reduce duplication of configurations by creating reusable baselines. The imports should be thought of almost like blueprints. Once -a reusable catalog of Stacks exists, robust architectures can be easily created simply by importing those blueprints. + +As your stacks grow taller with more and more component configurations, it often makes sense to start splitting them apart into different files. That's why you might want to take advantage of imports. This helps you keep your stack files smaller so they are easier to understand, while reuseing their configuration in multiple places. + -Imports may be used in Stack configurations together with [inheritance](/core-concepts/components/inheritance) -and [mixins](/core-concepts/stacks/mixins) to produce an exceptionally DRY configuration in a way that is logically organized and easier to maintain -for your team. +Each import overlays on top of others, and gets deep merged. Then we support [inheritance](/core-concepts/stacks/inheritance) and overrides to manage configuration variations, all without relying on templating. When none of these other methods work for your use-case, we provide an "Escape Hatch" with [templating](/core-concepts/stacks/templates). + +## Use cases +- **DRY Configuration:** Imports are how we reduce duplication of configurations. +- **Configuration Blueprints:** Define reusable baselines or "defaults". Think of them almost as blueprints, that you can reuse anytime you want some particular combination of components in a stack. +- **Service Catalogs:** Provide a "Service Catalog" for your team with reusable configurations that anyone can use to easily compose architectures with golden-path configurations. -:::info -The mechanics of mixins and inheritance apply only to the [Stack](/core-concepts/stacks) configurations. Atmos knows nothing about the underlying -components (e.g. terraform), and does not magically implement inheritance for HCL. However, by designing highly reusable components that do one thing -well, we're able to achieve many of the same benefits. +:::warning Pitfalls! +Imports can make your configurations harder to understand if overused. Review our [best practices](/best-practices/stacks) for practical guidance. ::: +Imports may be used in Stack configurations together with [inheritance](/core-concepts/stacks/inheritance) +and [mixins](/core-concepts/stacks/inheritance/mixins) to produce an exceptionally DRY configuration in a way that is logically organized and easier to maintain +for your team. + ## Configuration To import any stack configuration from the `catalog/`, simply define an `import` section at the top of any [Stack](/core-concepts/stacks) @@ -48,7 +55,7 @@ import: We recommend placing all baseline "imports" in the `stacks/catalog` folder, however, they can exist anywhere. -Use [mixins](/core-concepts/stacks/mixins) for reusable snippets of configurations that alter the behavior of Stacks in some way. +Use [mixins](/core-concepts/stacks/inheritance/mixins) for reusable snippets of configurations that alter the behavior of Stacks in some way. ## Imports Schema @@ -89,12 +96,12 @@ where: - `context` - (map) An optional freeform map of context variables that are applied as template variables to the imported file (if the imported file is a [Go template](https://pkg.go.dev/text/template)) -- `skip_templates_processing` - (boolean) Skip template processing for the imported file. Can be used if the imported file uses `Go` templates +- `skip_templates_processing` - (boolean) Skip template processing for the imported file. Can be used if the imported file uses `Go` templates to configure external systems, e.g. Datadog -- `ignore_missing_template_values` - (boolean) Ignore the missing template values in the imported file. Can be used if the imported file uses `Go` - templates to configure external systems, e.g. Datadog. In this case, Atmos will process all template values that are provided in the `context`, - and will skip the missing values in the templates for the external systems without throwing an error. The `ignore_missing_template_values` setting +- `ignore_missing_template_values` - (boolean) Ignore the missing template values in the imported file. Can be used if the imported file uses `Go` + templates to configure external systems, e.g. Datadog. In this case, Atmos will process all template values that are provided in the `context`, + and will skip the missing values in the templates for the external systems without throwing an error. The `ignore_missing_template_values` setting is different from `skip_templates_processing` in that `skip_templates_processing` skips the template processing completely in the imported file, while `ignore_missing_template_values` processes the templates using the values provided in the `context` and skips all the missing values @@ -141,8 +148,6 @@ components: flavor: "{{ .flavor }}" ``` -
- :::note Since `Go` processes templates as text files, we can parameterize the Atmos component name `eks-{{ .flavor }}/cluster` and any values in any @@ -150,8 +155,6 @@ sections (`vars`, `settings`, `env`, `backend`, etc.), and even the `import` sec ::: -
- Then we can import the template into a top-level stack multiple times providing different context variables to each import: ```yaml title="stacks/orgs/cp/tenant1/test1/us-west-2.yaml" @@ -159,7 +162,7 @@ import: - path: "mixins/region/us-west-2" - path: "orgs/cp/tenant1/test1/_defaults" - # This import with the provided context will dynamically generate + # This import with the provided context will dynamically generate # a new Atmos component `eks-blue/cluster` in the current stack - path: "catalog/terraform/eks_cluster_tmpl" context: @@ -168,7 +171,7 @@ import: service_1_name: "blue-service-1" service_2_name: "blue-service-2" - # This import with the provided context will dynamically generate + # This import with the provided context will dynamically generate # a new Atmos component `eks-green/cluster` in the current stack - path: "catalog/terraform/eks_cluster_tmpl" context: @@ -220,8 +223,6 @@ vars: tenant: tenant1 ``` -
- ## Hierarchical Imports with Context Atmos supports hierarchical imports with context. @@ -259,8 +260,6 @@ components: flavor: "{{ .flavor }}" ``` -
- Then we can import the template into a top-level stack multiple times providing different context variables to each import and to the imports for the entire inheritance chain (which `catalog/terraform/eks_cluster_tmpl_hierarchical` imports itself): @@ -300,8 +299,6 @@ import: stage: "test1" ``` -
- In the case of hierarchical imports, Atmos performs the following steps: - Processes all the imports in the `import` section in the current configuration in the order they are specified providing the `context` to all @@ -342,8 +339,6 @@ vars: tenant: tenant1 ``` -
- :::warning Handle with Care Leveraging Go templating for Atmos stack generation grants significant power but demands equal responsibility. It can easily defy the principle of creating stack configurations that are straightforward and intuitive to read. @@ -391,8 +386,8 @@ components: {{- end }} ``` -The `iam_managed_policy_arns` and `iam_source_policy_documents` variables will be included in the component configuration only if the -provided `context` object has the `iam_managed_policy_arns` and `iam_source_policy_documents` fields. +The `iam_managed_policy_arns` and `iam_source_policy_documents` variables will be included in the component configuration only if the +provided `context` object has the `iam_managed_policy_arns` and `iam_source_policy_documents` fields. ## Summary @@ -402,5 +397,5 @@ for [EKS blue-green deployment](https://aws.amazon.com/blogs/containers/kubernet ## Related -- [Configure CLI](/quick-start/configure-cli) -- [Create Atmos Stacks](/quick-start/create-atmos-stacks) +- [Configure CLI](/quick-start/advanced/configure-cli) +- [Create Atmos Stacks](/quick-start/advanced/create-atmos-stacks) diff --git a/website/docs/core-concepts/components/component-inheritance.mdx b/website/docs/core-concepts/stacks/inheritance/inheritance.mdx similarity index 83% rename from website/docs/core-concepts/components/component-inheritance.mdx rename to website/docs/core-concepts/stacks/inheritance/inheritance.mdx index f697dad53..1068d6155 100644 --- a/website/docs/core-concepts/components/component-inheritance.mdx +++ b/website/docs/core-concepts/stacks/inheritance/inheritance.mdx @@ -1,55 +1,64 @@ --- -title: Component Inheritance -sidebar_position: 7 -sidebar_label: Inheritance +title: Inherit Configurations in Atmos Stacks +sidebar_position: 4 +sidebar_label: Inherit Configurations id: inheritance --- import File from '@site/src/components/File' import Terminal from '@site/src/components/Terminal' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -Component Inheritance is one of the principles of [Component-Oriented Programming (COP)](/core-concepts/components/component-oriented-programming) -supported by Atmos. + +Inheritance provides a template-free way to customize Stack configurations. When combined with [imports](/core-concepts/stacks/imports), it provides the ability to combine multiple configurations through ordered deep-merging of configurations. Inheritance is how you manage configuration variations, without resorting to [templating](/core-concepts/stacks/templates). + -Component Inheritance is the ability to combine multiple configurations through ordered deep-merging of configurations. The concept is borrowed from -[Object-Oriented Programming](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) to logically organize complex configurations in -a way that makes conceptual sense. The side effect of this are extremely DRY and reusable configurations. +Atmos supports the following concepts and principles of **Component-Oriented Programming (COP)**: -:::info +- [Single Inheritance](/core-concepts/stacks/inheritance#single-inheritance) - when an Atmos component inherits the configuration properties from + another Atmos component -In Object-Oriented Programming (OOP), Inheritance is the mechanism of basing an object or class upon another object (prototype-based inheritance) or -class (class-based inheritance), retaining similar implementation. +- [Multiple Inheritance](/core-concepts/stacks/inheritance#multiple-inheritance) - when an Atmos component inherits the configuration from more than one Atmos + component -Similarly, in Atmos, **Component Inheritance** is the mechanism of deriving a component from one or more base components, inheriting all the -properties of the base component(s) and overriding only some fields specific to the derived component. The derived component acquires all the -properties of the "parent" component(s), allowing creating very DRY configurations that are built upon existing components. +These concepts and principles are implemented and used in Atmos by combining two features: [`import`](/core-concepts/stacks/imports) +and [`metadata`](/core-concepts/stacks/define-components#metadata) component's configuration section. +:::info +The mechanics of mixins and inheritance apply only to the [Stack](/core-concepts/stacks) configurations. Atmos knows nothing about the underlying +components (e.g. terraform), and does not magically implement inheritance for HCL. However, by designing highly reusable components that do one thing +well, we're able to achieve many of the same benefits. ::: -
- Component Inheritance is implemented and used in Atmos by combining two features: [`import`](/core-concepts/stacks/imports) and `metadata` component's configuration section. -
+### Definitions -:::info Definitions +
+
Base Component
+
is an Atmos component from which other Atmos components inherit all the configuration properties
+
Derived Component
+
is an Atmos component that derives the configuration properties from other Atmos components
+
-- **Base Component** is an Atmos component from which other Atmos components inherit all the configuration properties -- **Derived Component** is an Atmos component that derives the configuration properties from other Atmos components +# Understanding Inheritance -::: +The concept of inheritance in Atmos is implemented through deep merging. Deep merging involves taking two maps or objects and combining them in a specific order, where the values in the latter map override those in the former. This approach allows us to achieve a template-free way of defining configurations in a logical, predictable, and consistent manner. ## Single Inheritance +Easy + Single Inheritance is used when an Atmos component inherits from another base Atmos component. In the diagram below, `ComponentA` is the base component. `ComponentB` and `ComponentC` are derived components, they inherit all the configurations (`vars`, `settings`, `env` and other sections) from `ComponentA`, and can override the default values from `ComponentA`. -
```mermaid classDiagram + direction TB ComponentA --> ComponentB ComponentA --> ComponentC ComponentA : vars @@ -76,8 +85,6 @@ classDiagram } ``` -
- ### Single Inheritance Example Let's say we want to provision two VPCs with different settings into the same AWS account. @@ -106,8 +113,6 @@ components: ``` -
- In the configuration above, the following **Component-Oriented Programming** concepts are implemented: - **Abstract Components**: `atmos` component `vpc-defaults` is marked as abstract in `metadata.type`. This makes the component non-deployable, and it @@ -116,12 +121,41 @@ In the configuration above, the following **Component-Oriented Programming** con override and use the base component properties in the derived components to provision the same Terraform configuration many times but with different settings -
+
+Deep Dive + +Component Inheritance is one of the principles of [Component-Oriented Programming (COP)](https://en.wikipedia.org/wiki/Component-based_software_engineering) +supported by Atmos. + +The concept is borrowed from [Object-Oriented Programming](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) +to logically organize complex configurations in a way that makes conceptual sense. The side effect of this are extremely DRY and reusable +configurations. + +[Component-Oriented Configuration](https://en.wikipedia.org/wiki/Component-based_software_engineering) is a reuse-based approach to defining, +implementing and composing loosely-coupled independent components into systems. + +
+
Dynamic Polymorphism
+
Ability to use and override base component(s) properties
+ +
Encapsulation
+
Enclose a set of related configuration properties into reusable loosely-coupled modules. Encapsulation is implemented by Atmos Components which are opinionated building blocks of Infrastructure-as-Code (IAC) that solve one specific problem or use-case
+ +
Abstraction
+
+
    +
  • Principle of Abstraction: In a given stack, "hide" all but the relevant information about a component configuration in order to reduce complexity and increase efficiency
  • +
  • Abstract Components: If a component is marked as abstract, it can be used only as a base for other components and can't be provisioned using atmos
  • +
+
+
+
+ In the `stacks/ue2-dev.yaml` stack config file, add the following config for the derived VPC components in the `ue2-dev` stack: -```yaml +```yaml # Import the base component configuration from the `catalog`. # `import` supports POSIX-style Globs for file names/paths (double-star `**` is supported). # File extensions are optional (if not specified, `.yaml` is used by default). @@ -160,8 +194,6 @@ components: ``` -
- In the configuration above, the following **Component-Oriented Programming** concepts are implemented: - **Component Inheritance**: In the `ue2-dev` stack (`stacks/ue2-dev.yaml` stack config file), the Atmos components `vpc/1` and `vpc/2` inherit from @@ -171,8 +203,6 @@ In the configuration above, the following **Component-Oriented Programming** con - **Dynamic Polymorphism**: The derived `vpc/1` and `vpc/2` components override and use the base component properties to be able to provision the same Terraform configuration many times but with different settings -
- Having the components in the stack configured as shown above, we can now provision the `vpc/1` and `vpc/2` components into the `ue2-dev` stack by executing the following `atmos` commands: @@ -181,22 +211,21 @@ atmos terraform apply vpc/1 -s ue2-dev atmos terraform apply vpc/2 -s ue2-dev ``` -
- As we can see, using the principles of **Component-Oriented Programming (COP)**, we are able to define two (or more) components with different settings, and provision them into the same (or different) environment (account/region) using the same Terraform code (which is environment-agnostic). And the configurations are extremely DRY and reusable. ## Multiple Inheritance +Advanced + Multiple Inheritance is used when an Atmos component inherits from more than one Atmos component. + In the diagram below, `ComponentA` and `ComponentB` are the base components. `ComponentC` is a derived components, it inherits all the configurations (`vars`, `settings`, `env` and other sections) from `ComponentA` and `ComponentB`, and can override the default values from `ComponentA` and `ComponentB`. -
- ```mermaid classDiagram ComponentA --> ComponentC @@ -223,28 +252,21 @@ classDiagram } ``` -
-
- Multiple Inheritance allows a component to inherit from many base components or mixins, each base component having its own inheritance chain, effectively making it an inheritance matrix. It uses a method similar to Method Resolution Order (MRO) using the [C3 linearization](https://en.wikipedia.org/wiki/C3_linearization) algorithm, which is how Python supports multiple inheritance. -
- :::info In **Object-Oriented Programming (OOP)**, a mixin is a class that contains methods for use by other classes without having to be the parent class of those other classes. -In **Component-Oriented Programming (COP)** implemented in Atmos, a [mixin](/core-concepts/stacks/mixins) is an abstract base component that is never +In **Component-Oriented Programming (COP)** implemented in Atmos, a [mixin](/core-concepts/stacks/inheritance/mixins) is an abstract base component that is never meant to be provisioned and does not have any physical implementation - it just contains default settings/variables/properties for use by other Atmos components. ::: -
- Multiple Inheritance, similarly to Single Inheritance, is defined by the `metadata.inherits` section in the component configuration. `metadata.inherits` is a list of component or mixins names from which the current component inherits. In the case of multiple base components, it is processed in the order by which it was declared. @@ -262,21 +284,15 @@ Atmos will recursively deep-merge all the base components of `componentA` (each then all the base components of `componentB` (each component overriding its base), then the two results are deep-merged together with `componentB` inheritance chain overriding the values from `componentA` inheritance chain. -
- :::caution All the base components/mixins referenced by `metadata.inherits` must be already defined in the Stack configuration, either by using an `import` statement or by explicitly defining them in the Stack configuration. The `metadata.inhertis` statement does not imply that we are importing anything. ::: -
- ### Multiple Inheritance Example Here is a concrete example: -
- ```yaml # Import all the base components and mixins we want to inherit from. @@ -295,8 +311,8 @@ components: # `abstract` makes the component protected from being deployed. type: real # Terraform component. Must exist in `components/terraform` folder. - # If not specified, it's assumed that this component `test/test-component-override-3` - # is also a Terraform component in + # If not specified, it's assumed that this component `test/test-component-override-3` + # is also a Terraform component in # `components/terraform/test/test-component-override-3` folder. component: "test/test-component" # Multiple inheritance. @@ -309,8 +325,6 @@ components: ``` -
- In the configuration above, all the base components and mixins are processed and deep-merged in the order they are specified in the `inherits` list: - `test/test-component-override-2` overrides `test/test-component-override` and its base components (all the way up its inheritance chain) @@ -335,16 +349,16 @@ Atmos component: test/test-component-override-3 Terraform component: test/test-component Terraform command: apply Stack: tenant1-ue2-dev -Inheritance: test/test-component-override-3 -> mixin/test-2 -> mixin/test-1 -> +Inheritance: test/test-component-override-3 -> mixin/test-2 -> mixin/test-1 -> test/test-component-override-2 -> test/test-component-override -> test/test-component ``` -
- The `Inheritance` output shows the multiple inheritance steps that Atmos performed and deep-merged into the final configuration, including the variables which are sent to the Terraform component `test/test-component` that is being provisioned. -## Multilevel Inheritance +### Multilevel Inheritance + +Advanced Multilevel Inheritance is used when an Atmos component inherits from a base Atmos component, which in turn inherits from another base Atmos component. @@ -357,10 +371,9 @@ sections) from both `ComponentB` and `ComponentA`. Note that `ComponentB` overrides the values from `ComponentA`. `ComponentC` overrides the values from both `ComponentB` and `ComponentA`. -
- ```mermaid classDiagram + direction LR ComponentA --> ComponentB ComponentB --> ComponentC ComponentA : vars @@ -387,17 +400,15 @@ classDiagram } ``` -
+### Hierarchical Inheritance -## Hierarchical Inheritance +Advanced Hierarchical Inheritance is a combination of Multiple Inheritance and Multilevel Inheritance. In Hierarchical Inheritance, every component can act as a base component for one or more child (derived) components, and each derived component can inherit from one of more base components. -
- ```mermaid classDiagram ComponentA --> ComponentB @@ -482,8 +493,6 @@ classDiagram } ``` -
- In the diagram above: - `ComponentA` is the base component of the whole hierarchy @@ -495,8 +504,6 @@ In the diagram above: - `ComponentE` is an example of using both Multiple Inheritance and Multilevel Inheritance. It inherits from `ComponentB` and `ComponentH` directly, and from `ComponentA` via Multilevel Inheritance -
- For `ComponentE`, the inherited components are processed and deep-merged in the order they are specified in the `inherits` list: - `ComponentB` overrides the configuration from `ComponentA` @@ -505,8 +512,6 @@ For `ComponentE`, the inherited components are processed and deep-merged in the - And finally, `ComponentE` overrides `ComponentH`, `ComponentB` and `ComponentA` -
- For `ComponentG`: - `ComponentI` is processed first (since it's the first item in the `inherits` list) @@ -517,7 +522,7 @@ For `ComponentG`: - And finally, `ComponentG` is processed, and it overrides `ComponentC`, `ComponentA` and `ComponentI` -### Hierarchical Inheritance Example +#### Hierarchical Inheritance Example Let's consider the following configuration for Atmos components `base-component-1`, `base-component-2`, `derived-component-1` and `derived-component-2`: @@ -556,12 +561,8 @@ components: ``` -
- This configuration can be represented by the following diagram: -
- ```mermaid classDiagram `base-component-1` --> `derived-component-1` @@ -602,8 +603,6 @@ classDiagram } ``` -
- In the configuration above, `derived-component-1` inherits from `base-component-1`. `derived-component-2` inherits from `base-component-2` and `derived-component-1` via Multiple Inheritance, and from `base-component-1` via Multilevel @@ -644,8 +643,6 @@ Inheritance: derived-component-2 -> derived-component-1 -> base-component-1 -> b Note that the `hierarchical_inheritance_test` variable was inherited from `base-component-1` because it overrode the configuration from `base-component-2`. -
- If we change the order of the components in the `inherits` list for `derived-component-2`: diff --git a/website/docs/core-concepts/stacks/mixins.mdx b/website/docs/core-concepts/stacks/inheritance/mixins.mdx similarity index 77% rename from website/docs/core-concepts/stacks/mixins.mdx rename to website/docs/core-concepts/stacks/inheritance/mixins.mdx index 72a41259d..72e2a0792 100644 --- a/website/docs/core-concepts/stacks/mixins.mdx +++ b/website/docs/core-concepts/stacks/inheritance/mixins.mdx @@ -5,14 +5,18 @@ sidebar_label: Mixins id: mixins --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' -Mixins are reusable snippets of configurations (like regions, tags, etc) included in stack configurations to avoid repetition and enhance modularity. -They allow for defining common settings, variables, or configurations once and applying them efficiently across various stacks. +Advanced -Mixins are really just a [Design Pattern](/design-patterns/component-catalog-with-mixins) that uses [`imports`](/core-concepts/stacks/imports) to -alter the Stack in some deliberate way. + +Mixins are reusable snippets of configurations (like regions, tags, etc) included in stack configurations to avoid repetition and enhance modularity. They allow for defining common settings, variables, or configurations once and applying them efficiently across various stacks. + -:::important +:::important Mixins are treated the same as all other imports in Atmos, with no special handling or technical distinction. ::: @@ -36,7 +40,7 @@ For example, let's define a mixin with the defaults for operating in the `us-eas vars: region: us-east-1 # the canonical cloud region availability_zones: # the designated availability zones to use in this region - - us-east-1a + - us-east-1a - us-east-1b ``` @@ -77,11 +81,9 @@ terraform: # ... ``` -
- :::tip Use Mixins for Naming Conventions This simple example highlights a simple fix for one of the most common issues in enterprise organizations: naming inconsistency. -Using a mixin is a great way for organizations ensure naming conventions are followed consistently. +Using a mixin is a great way for organizations ensure naming conventions are followed consistently. For example, there are many ways developers will define `production`. @@ -96,7 +98,7 @@ For example, there are many ways developers will define `production`. To avoid this situation, use the mixin `mixins/stage/prod` and always use the appropriate naming convention. -## References - - - [Component Catalog Atmos Design Pattern](/design-patterns/component-catalog) - - [Component Catalog with Mixins Atmos Design Pattern](/design-patterns/component-catalog-with-mixins) + +Mixins are really just a [Design Pattern](/design-patterns/component-catalog-with-mixins) for [`imports`](/core-concepts/stacks/imports) that uses [inheritance](/core-concepts/stacks/inheritance) to alter the Stack configuration in some deliberate way. +Learn Design Pattern + diff --git a/website/docs/core-concepts/components/component-overrides.mdx b/website/docs/core-concepts/stacks/overrides.mdx similarity index 84% rename from website/docs/core-concepts/components/component-overrides.mdx rename to website/docs/core-concepts/stacks/overrides.mdx index 3f8da0082..4f58445e9 100644 --- a/website/docs/core-concepts/components/component-overrides.mdx +++ b/website/docs/core-concepts/stacks/overrides.mdx @@ -1,14 +1,16 @@ --- -title: Component Overrides -sidebar_position: 9 -sidebar_label: Overrides +title: Override Configurations +sidebar_position: 5 +sidebar_label: Override Configurations description: Use the 'Component Overrides' pattern to modify components' configuration and behavior in the current scope. id: overrides --- import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' -Atmos supports the [Component Overrides](/design-patterns/component-overrides) Design Pattern to modify components' configuration and behavior using -the `overrides` section in Atmos stack manifests. + +Atmos supports the ability to override the behavior of [imports](/core-concepts/stacks/imports) when the order of deep-merging interferes with what you want to express. Use the `overrides` section in Atmos stack manifests. + You can override the following sections in the component(s) configuration: @@ -20,6 +22,8 @@ You can override the following sections in the component(s) configuration: The `overrides` section can be used in the global scope or in the Terraform and Helmfile scopes. +The [Component Overrides](/design-patterns/component-overrides) Design Pattern goes into further details on how to use this effectively. + ## Overrides Schema The `overrides` section schema at the global scope is as follows: @@ -58,15 +62,10 @@ helmfile: command: "" ``` -You can include the `overrides`, `terraform.overrides` and `helmfile.overrides` sections in any Atmos stack manifest at any level of inheritance. -The scope of the `override` configuration is limited to all the Atmos components defined within the manifest and all its imports up until that point. -In other words, the `overrides` configuration defined within a stack manifest does not affect any other components defined in different stack -manifests for the same top-level stack. - -
+You can include the `overrides`, `terraform.overrides` and `helmfile.overrides` sections in any Atmos stack manifest at any level of inheritance. The scope of the `override` configuration is limited to all the Atmos components defined within the manifest and all its imports up until that point. In other words, the `overrides` configuration defined within a stack manifest does not affect any other components defined in different stack manifests for the same top-level stack. :::tip -Refer to [Atmos Component Inheritance](/core-concepts/components/inheritance) for more information on all types of component inheritance +Refer to [Atmos Component Inheritance](/core-concepts/stacks/inheritance) for more information on all types of component inheritance supported by Atmos ::: @@ -114,16 +113,11 @@ import: - teams/testing ``` -Suppose that we want to change some variables in the `vars` and `env` sections and some config in the `settings` section for all the components -that the `testing` Team manges, but we don't want to affect any components that the `devops` Team manages. +Suppose that we want to change some variables in the `vars` and `env` sections and some config in the `settings` section for all the components that the `testing` Team manges, but we don't want to affect any components that the `devops` Team manages. -If we added a global or Terraform level `vars`, `env` or `settings` sections to the top-level manifest `stacks/orgs/cp/tenant1/dev/us-west-2.yaml` -or to the Team manifest `stacks/teams/testing.yaml`, then all the components in the `tenant1/dev/us-west-2` top-level stack would be modified, -including those managed by the `devops` Team. +If we added a global or Terraform level `vars`, `env` or `settings` sections to the top-level manifest `stacks/orgs/cp/tenant1/dev/us-west-2.yaml` or to the Team manifest `stacks/teams/testing.yaml`, then all the components in the `tenant1/dev/us-west-2` top-level stack would be modified, including those managed by the `devops` Team. -To solve this, we could individually modify the `vars`, `env` and `settings` sections in all the components managed by the `testing` Team, -but the entire configuration would not be DRY and reusable. That's where the __overrides__ pattern comes into play. To make the configuration DRY and -configured only in one place, use the `overrides` section. +To solve this, we could individually modify the `vars`, `env` and `settings` sections in all the components managed by the `testing` Team, but the entire configuration would not be DRY and reusable. That's where the __overrides__ pattern comes into play. To make the configuration DRY and configured only in one place, use the `overrides` section. For example, we want to override some values in the `env`, `vars` and `setings` sections for all the components managed by the `testing` Team: @@ -187,8 +181,6 @@ In the manifest above, we configure the following: the `testing` Team will get the new ENV variable value (but not the Terraform components). The Helmfile `overrides` are deep-merged with the global `overrides` and takes higher priority (it will override the same keys from the global `overrides`). -
- To confirm that the components managed by the `testing` Team get the new values from the `overrides` sections, execute the following commands: @@ -222,7 +214,7 @@ env: settings: spacelift: - # The `autodeploy` setting was overridden with the value + # The `autodeploy` setting was overridden with the value # from `terraform.overrides.settings.spacelift.autodeploy` autodeploy: true workspace_enabled: true @@ -238,8 +230,6 @@ vars: ``` -
- To confirm that the components managed by the `devops` Team are not affected by the `overrides` for the `testing` Team, execute the following command: @@ -248,7 +238,7 @@ command: # The `command` is not overridden command: terraform -# The component does not get the `overrides` section since it's not defined +# The component does not get the `overrides` section since it's not defined # for the components managed by the `devops` Team overrides: {} @@ -266,8 +256,6 @@ settings: The `top-level-component1` component managed by the `devops` Team does not get affected by the `overrides` sections for the `testing` Team, and the sections `vars`, `env`, `settings` and `command` are not updated with the values from the `overrides` configuration. -
- :::tip -Refer to [`atmos describe component`](/cli/commands/describe/component) CLI command for more details +Refer to [`atmosxw describe component`](/cli/commands/describe/component) CLI command for more details ::: diff --git a/website/docs/core-concepts/stacks/stacks.mdx b/website/docs/core-concepts/stacks/stacks.mdx index 7e332397e..445096a88 100644 --- a/website/docs/core-concepts/stacks/stacks.mdx +++ b/website/docs/core-concepts/stacks/stacks.mdx @@ -1,59 +1,106 @@ --- title: Atmos Stacks -sidebar_position: 2 -sidebar_label: Stacks -description: Stacks are a way to express the complete infrastructure needed for an environment +sidebar_position: 3 +sidebar_label: Configure Stacks +description: Use Stacks to configure Components for an environment id: stacks --- import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' -Stacks are a way to express the complete infrastructure needed for an environment. Think of a Stack like an architectural "Blueprint" composed -of one or more [Components](/core-concepts/components) and defined using a [standardized YAML configuration](#schema). + +When you design cloud architectures with Atmos, you break them apart into pieces called components that you implement with Terraform "root modules". Stacks are how you connect your components with configuration, so that everything comes together. + -This abstraction layer helps to automate the orchestration and deployment of loosely coupled [components](/core-concepts/components), such as Terraform "root" modules. They enable scalable infrastructure-as-code configurations, allowing environments to inherit from one or more common bases (child stacks) -by importing configuration that gets deep-merged, thus minimizing config duplication and manual effort. Each stack uses a simple schema that provides a declarative description of your various environments. This approach empowers you to separate your infrastructure’s environment configuration settings from the code it manages (e.g., Terraform components). +The power of components comes from their ability to be reused: you can compose stacks with one or more components, even reusing any component multiple times within a stack. But as your stacks grow with more and more components, it often makes sense to start splitting them into different files and that's why you might want to make use of imports. This lets you keep your Stack files easier to scan and reuse their configuration in multiple places. -By facilitating the infrastructure configurations this way, developers achieve DRY (Don't Repeat Yourself) architectures with minimal configuration. Stacks make infrastructure more streamlined and consistent, significantly enhancing productivity. Best of all, Stacks can deploy -vanilla Terraform "root" modules *without* any code generation, custom vendor extensions, or changes to the HCL code. +Stacks define the complete configuration of an environment. Think of Stacks like an architectural "Blueprints" composed of one or more [Components](/core-concepts/components) configurations and defined using a [standardized YAML configuration](#schema). -Atmos utilizes a custom YAML configuration format for stacks. YAML is ideal because it's portable across multiple toolchains and languages; every developer understands it. The Atmos [CLI](/cli), the [terraform-utils-provider](https://github.com/cloudposse/terraform-provider-utils) provider, and Spacelift via the [terraform-spacelift-cloud-infrastructure-automation](https://github.com/cloudposse/terraform-spacelift-cloud-infrastructure-automation) module all support stacks. Utilizing the Terraform provider enables native access to the entire infrastructure configuration directly from Terraform. +Then by running the `atmos` command, automate the orchestrate the deployment of loosely coupled [components](/core-concepts/components), such as Terraform "root" modules. By doing this, it enables scalable infrastructure-as-code configurations, allowing environments to inherit from one or more common bases (child stacks) by importing configuration that gets deep-merged, thus minimizing config duplication and manual effort. Each stack uses a simple schema that provides a declarative description of your various environments. This approach empowers you to separate your infrastructure’s environment configuration settings from the code it manages (e.g., [Terraform components](/core-concepts/components/terraform)). -## Use-cases +By facilitating the infrastructure configurations this way, developers achieve DRY (Don't Repeat Yourself) architectures with minimal +configuration. Stacks make infrastructure more streamlined and consistent, significantly enhancing productivity. Best of all, Stacks +can deploy vanilla Terraform "root" modules *without* any code generation, custom vendor extensions, or changes to the HCL code. -- **Rapid Environment Provisioning:** Leverage stacks to swiftly set up and replicate development, testing, and production environments, ensuring consistency and reducing manual setup errors. This accelerates the development cycle and enables businesses to respond quickly to market demands or development needs. -- **Multi-Tenant Infrastructure Management:** Utilize stacks to manage and isolate resources for different clients or projects within a single cloud infrastructure. This approach supports SaaS companies in providing secure, isolated environments for each tenant, optimizing resource utilization and simplifying the management of complex, multi-tenant architectures. -- **Compliance and Governance:** Implement stacks to enforce compliance and governance policies across all environments systematically. By defining standard configurations that meet regulatory requirements, businesses can ensure that every deployment is compliant, reducing the risk of violations and enhancing security posture. +Atmos utilizes a custom YAML configuration format for stacks. YAML is ideal because it's portable across multiple toolchains and languages; every developer understands it. The Atmos [CLI](/cli), the [terraform-utils-provider](https://github.com/cloudposse/terraform-provider-utils) provider, and Spacelift via the [terraform-spacelift-cloud-infrastructure-automation](https://github.com/cloudposse/terraform-spacelift-cloud-infrastructure-automation) module all support stacks. Utilizing the Terraform provider enables native access to the entire infrastructure configuration directly from Terraform. -## Best Practices + + Define your first component configuration using stacks. + -:::tip -Remember to adhere to the laws physics. All other laws are meant broken. -::: +## Use-cases -- **Treat Stack Templates like an Escape Hatch** Apply it carefully and only when necessary. Using templates instead of inheritance can make stack configurations complex and hard to manage. Be careful using stack templates together with the component factory pattern. -- **Avoid Too Many Levels of Imports** It's very difficult for others to follow relationships when there are too many nested levels and overrides. -- **Balance DRY Principles with Configuration Clarity** Avoid overly DRY configuration as it leads to complexity rashes. Sometimes repeating configuration is beneficial for maintenance and clarity. -- **Reserve Code Generation for Stack Configuration** While we generally advise against using code generation for application logic (components), it's beneficial for creating configurations where appropriate, such as developer environments and SaaS tenants. These configurations ought to be committed. -- **Use Mixin Pattern for Snippets of Stack Configuration** Employ the mixin pattern for clarity when there there is brief configuration snippets that are reusable. Steer clear of minimal stack configurations simply for the sake of DRYness as it frequently leads to too many levels of imports. +- **Rapid Environment Provisioning:** Leverage stacks to swiftly set up and replicate development, testing, + and production environments, ensuring consistency and reducing manual setup errors. This accelerates the development + cycle and enables businesses to respond quickly to market demands or development needs. +- **Multi-Tenant Infrastructure Management:** Utilize stacks to manage and isolate resources for different clients or projects + within a single cloud infrastructure. This approach supports SaaS companies in providing secure, isolated environments for each + tenant, optimizing resource utilization and simplifying the management of complex, multi-tenant architectures. +- **Compliance and Governance:** Implement stacks to enforce compliance and governance policies across all environments systematically. + By defining standard configurations that meet regulatory requirements, businesses can ensure that every deployment is compliant, + reducing the risk of violations and enhancing security posture. ## Conventions The differentiation between the following two types of stacks is crucial for understanding how to organize stacks and the basis for the various [design patterns](/design-patterns/). -### Parent Stacks +### Stack Names (aka "slugs") + +Every stack is uniquely identified by a name. The name is used to reference the stack in the Atmos CLI, or with stack dependencies. + +These are computed from either the `name_pattern` (old way) or the more configurable +`name_template` (new way). These are configured in the `atmos.yaml` configuration file. + +For example, using the slug, we can reference a stack like this when applying the `vpc` stack in the `us2-dev` environment: + +```bash +atmos terraform apply vpc -s us2-dev +``` + +### Components vs Component instances + +Components are different from Stacks. + +When a component is added to a stack, we call that a "Component Instance" + + + +### Parent Stacks vs Child Stacks + +
+
Parent Stacks
+
These are the top-level stacks that are responsible for importing Child stacks. Components inside of Parent stacks are deployable, unlike in Child stacks.
+ +
Child Stacks
+
These are any stacks whose components cannot be deployed independently without being imported by a Parent Stack. Catalogs are typically where we keep our Child stacks.
+
+ +### Logical Stacks vs. Physical Stack Manifests + +
+
Logical Stacks
+
+ Represent the entire environment defined by context variables and global settings in atmos.yaml. + Logical stacks are the in-memory representation of the deep-merged configuration. +
+ +
Physical Stacks
+
Are the raw YAML files where the specific configurations of components are defined.
+
-*Parent Stacks* are the top-level stacks that are responsible for importing Child stacks. Components inside of Parent stacks are deployable, unlike in Child stacks. +Atmos processes each physical stack file, first evaluating any templates and then processing it as YAML. After loading the YAML, +it proceeds to deep-merge the configuration with the current in-memory logical representation of the Stack, then apply any overrides. +This is done iteratively for each physical stack file in the order they are defined in the `import` section of the Stack file. -### Child Stacks +Note, the logical repersentation is never influenced by file paths or directories. It's only influenced by the configuration itself. -*Child Stacks* are any stacks whose components cannot be deployed independently without being imported by a Parent Stack. -[Catalogs](/core-concepts/stacks/catalogs) are typically where we keep our Child stacks. ## Schema -A Stack file contains a manifest defined in YAML that follows a simple, extensible schema. In fact, every Stack file follows exactly the same schema, and every setting in the configuration is optional. Enforcing a consistent schema ensures we can easily [import and deep-merge](/core-concepts/stacks/imports) configurations and use [inheritance](/core-concepts/components/inheritance) to achieve DRY configuration. +A Stack file contains a manifest defined in YAML that follows a simple, extensible schema. In fact, every Stack file follows exactly the same schema, and every setting in the configuration is optional. Enforcing a consistent schema ensures we can easily [import and deep-merge](/core-concepts/stacks/imports) configurations and use [inheritance](/core-concepts/stacks/inheritance) to achieve DRY configuration. ```yaml @@ -62,13 +109,13 @@ import: # each import is a "Stack" file. The `.yaml` extension is optional, and we do not recommend using it. - ue2-globals -# Top-level variables that are inherited by every single component. +# Top-level variables that are inherited by every single component. # Use these wisely. Too many global vars will pollute the variable namespace. vars: # Variables can be anything you want. They can be scalars, lists, and maps. Whatever is supported by YAML. stage: dev -# There can then be global variables for each type of component. +# There can then be global variables for each type of component. # Here we set global variables for any "terraform" component. terraform: vars: { } @@ -127,19 +174,15 @@ components: ## Stack Files -Stack files can be very numerous in large cloud environments (think many dozens to hundreds of stack files). To enable the proper organization of -stack files, SweetOps has established some conventions that are good to follow. However, these are just conventions, and there are no limits enforced -by the tool. +Stack files can be very numerous in large cloud environments (think many dozens to hundreds of stack files). To enable the proper organization of stack files, SweetOps has established some conventions that are good to follow. However, these are just conventions, and there are no limits enforced by the tool. -By convention, we recommend to store all Stacks in a `stacks/` folder at the root of your infrastructure repository. This way it's clear where they -live and helps keep the configuration separate from your code (e.g. HCL). +By convention, we recommend storing all Stacks in a `stacks/` folder at the root of your infrastructure repository. This way it's clear where they live and helps keep the configuration separate from your code (e.g. HCL). -The filename of individual environment stacks can follow any convention, and the best one will depend on how you model environments at your -organization. +The filename of individual environment stacks can follow any convention, and the best one will depend on how you model environments at your organization. ### Basic Layout -A basic form of organization is to follow the pattern of naming where each `$environment-$stage.yaml` is a file. This works well until you have so +A basic form of organization is to follow the naming pattern where each `$environment-$stage.yaml` is a file. This works well until you have so many environments and stages. For example, `$environment` might be `ue2` (for `us-east-2`) and `$stage` might be `prod` which would result in `stacks/ue2-prod.yaml` diff --git a/website/docs/core-concepts/stacks/templates/datasources.mdx b/website/docs/core-concepts/stacks/templates/datasources.mdx new file mode 100644 index 000000000..0e7e320c9 --- /dev/null +++ b/website/docs/core-concepts/stacks/templates/datasources.mdx @@ -0,0 +1,432 @@ +--- +title: Templatie Data Sources +sidebar_position: 7 +sidebar_label: Data Sources +id: datasources +--- +import File from '@site/src/components/File' +import Terminal from '@site/src/components/Terminal' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' + +Advanced + + +Data sources in Atmos refer to external locations from which Atmos can fetch configuration data. Atmos supports all data sources supported by [Gomplate](https://docs.gomplate.ca/datasources). For example, you can use data sources to fetch JSON metadata from API endpoints or read from various backends like S3 Buckets, AWS SSM Parameter Store, HashiCorp Vault, and many others. + + +## Datasources + +Currently, Atmos supports all the [Gomplate Datasources](https://docs.gomplate.ca/datasources). +More data sources will be added in the future (and this doc will be updated). All datasource configurations are defined in the `templates.settings.gomplate.datasources` section in `atmos.yaml` [CLI config file](/cli/configuration) or in the `settings.templates.settings` section of any [Atmos stack manifests](/core-concepts/stacks). + +The `templates.settings.gomplate.datasources` section is a map of objects. + +The keys of the map are the data source names (aliases) that you will use to refer to them. For example, if you define a data source called `foobar` which has a property called `tag`, you could refer to it like this in a stack manifest: `{{ (datasource "foobar").tag }}` + +The values in the map are data source definitions following this schema: + +
+
`url`
+
+ All data sources are defined as a [URL](https://docs.gomplate.ca/datasources/#url-format). + + As a refresher, a Gomplate Data Source URL is made up of the following components: + + ```plaintext + scheme://user@host.com:8080/path?query=string#fragment + ``` +
+ +
`headers`
+
+ A map of [HTTP request headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) for + the [`http` data source](https://docs.gomplate.ca/datasources/#sending-http-headers). + The keys of the map are the header names. The values of the map are lists of values for the header. + + The following configuration will result in the + [`accept: application/json`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) HTTP header + being sent with the HTTP request to the data source: + + ```yaml + headers: + accept: + - "application/json" + ``` +
+
+ +## Types of Data Sources + +The following are the types of data sources are supported by Atmos via [Gomplate](https://docs.gomplate.ca/datasources/#url-format). + +
+
`aws+smp://`
+
+ AWS Systems Manager Parameter Store is a key/value store that supports encryption and versioning. +
+ +
`aws+sm://`
+
+ AWS Secrets Manager lets you store and retrieve secrets. +
+ +
`s3://`
+
Amazon S3 provides object storage, which is convenient for stashing shared configurations.
+ +
`consul://`, `consul+http://`, `consul+https://`
+
Use HashiCorp Consul provides as a backend key/value store
+ +
`env://`
+
Environment variables can be used as data sources, although [template functions](/core-concepts/stacks/templates/functions) might make more sense.
+ +
`file://`
+
Files can be read in any of the supported formats (JSON, YAML). Directories are also supported, just end the URL path with a `/`.
+ +
`git://`, `git+file://`, `git+http://`, `git+https://`, `git+ssh://`
+
+ Files can be read from a local or remote git repository, at specific branches or tags. Directory semantics are also supported. +
+ +
`gs://`
+
+ Google Cloud Storage is the object storage service that is similar to AWS S3. +
+ +
`http://`, `https://`
+
+ Retrieve data from HTTP/HTTPS endpoints. Custom HTTP headers can also be passed. +
+ +
`merge://`
+
+ Merge two or more data sources together to produce the final value - useful for resolving defaults. Uses coll.Merge for merging. +
+ +
`stdin://`
+
+ Read configuration data from standard input. +
+ +
`vault://`, `vault+http://`, `vault+https://`
+
+ HashiCorp Vault is a popular open-source secret management platform. +
+
+ +## Environment Variables + +Some data sources might need environment variables that are different from the environment variables in Stack configuration. Environment variables may be passed to data soruces when processing and executing templates by defining `env` map. +It's supported in both the `templates.settings` section in `atmos.yaml` [CLI config file](/cli/configuration) and in the +`settings.templates.settings` section in [Atmos stack manifests](/core-concepts/stacks). + +For example: + + +```yaml +settings: + templates: + settings: + # Environment variables passed to datasources when evaluating templates + # https://docs.gomplate.ca/datasources/#using-awssmp-datasources + # https://docs.gomplate.ca/functions/aws/#configuring-aws + # https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html + env: + AWS_PROFILE: "" + AWS_TIMEOUT: 2000 +``` + + +This is useful when executing the `datasources` that need to authenticate to cloud APIs. + +For more details, refer to: + +- [Configuring AWS](https://docs.gomplate.ca/functions/aws/#configuring-aws) +- [Configuring GCP](https://docs.gomplate.ca/functions/gcp/#configuring-gcp) + +## Configuring Data Sources + +For example, let's define the following Gomplate `datasources` in the global `settings` section (this will apply to all +components in all stacks in the infrastructure): + + +```yaml +settings: + templates: + settings: + gomplate: + # Timeout in seconds to execute the datasources + timeout: 5 + # https://docs.gomplate.ca/datasources + datasources: + # 'http' datasource + # https://docs.gomplate.ca/datasources/#using-file-datasources + ip: + url: "https://api.ipify.org?format=json" + # https://docs.gomplate.ca/datasources/#sending-http-headers + # https://docs.gomplate.ca/usage/#--datasource-header-h + headers: + accept: + - "application/json" + # 'file' datasources + # https://docs.gomplate.ca/datasources/#using-file-datasources + config-1: + url: "./config1.json" + config-2: + url: "file:///config2.json" + # `aws+smp` AWS Systems Manager Parameter Store datasource + # https://docs.gomplate.ca/datasources/#using-awssmp-datasources + secret-1: + url: "aws+smp:///path/to/secret" + # `aws+sm` AWS Secrets Manager datasource + # https://docs.gomplate.ca/datasources/#using-awssm-datasource + secret-2: + url: "aws+sm:///path/to/secret" + # `s3` datasource + # https://docs.gomplate.ca/datasources/#using-s3-datasources + s3-config: + url: "s3://mybucket/config/config.json" +``` + + +After the above `datasources` are defined, you can use them in Atmos stack manifests like this: + +```yaml +terraform: + vars: + tags: + tag1: '{{ (datasource "config-1").tag }}' + service_name2: '{{ (datasource "config-2").service.name }}' + service_name3: '{{ (datasource "s3-config").config.service_name }}' + +components: + terraform: + vpc-1: + settings: + provisioned_by_ip: '{{ (datasource "ip").ip }}' + secret-1: '{{ (datasource "secret-1").secret1.value }}' + vars: + enabled: '{{ (datasource "config-2").config.enabled }}' +``` + + + +```yaml +# https://pkg.go.dev/text/template +templates: + settings: + # Enable `Go` templates in Atmos stack manifests + enabled: true + # https://docs.gomplate.ca + # https://docs.gomplate.ca/functions + gomplate: + # Enable Gomplate functions and datasources in `Go` templates in Atmos stack manifests + enabled: true + # Timeout in seconds to execute the datasources + timeout: 5 + # https://docs.gomplate.ca/datasources + datasources: + # 'http' datasource + # https://docs.gomplate.ca/datasources/#using-file-datasources + ip: + url: "https://api.ipify.org?format=json" + # https://docs.gomplate.ca/datasources/#sending-http-headers + # https://docs.gomplate.ca/usage/#--datasource-header-h + headers: + accept: + - "application/json" + # 'file' datasources + # https://docs.gomplate.ca/datasources/#using-file-datasources + config-1: + url: "./config1.json" + config-2: + url: "file:///config2.json" + # `aws+smp` AWS Systems Manager Parameter Store datasource + # https://docs.gomplate.ca/datasources/#using-awssmp-datasources + secret-1: + url: "aws+smp:///path/to/secret" + # `aws+sm` AWS Secrets Manager datasource + # https://docs.gomplate.ca/datasources/#using-awssm-datasource + secret-2: + url: "aws+sm:///path/to/secret" + # `s3` datasource + # https://docs.gomplate.ca/datasources/#using-s3-datasources + s3-config: + url: "s3://mybucket/config/config.json" +``` + + + +
`templates.settings.gomplate.datasources`
+
+A map of [Gomplate Datasource](https://docs.gomplate.ca/datasources) definitions. + +The keys of the map are the datasource names (aliases), which are used in `Go` templates in Atmos stack manifests. + For example: + + ```yaml + terraform: + vars: + tags: + provisioned_by_ip: '{{ (datasource "ip").ip }}' + config1_tag: '{{ (datasource "config-1").tag }}' + config2_service_name: '{{ (datasource "config-2").service.name }}' + ``` + + + The values of the map are the datasource definitions with the following schema: +
+
`url`
+
the [Datasource URL](https://docs.gomplate.ca/datasources/#url-format)
+ +
`headers`
+
+ a map of [HTTP request headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) for the [`http` datasource](https://docs.gomplate.ca/datasources/#sending-http-headers). The keys of the map are the header names. The values of the map are lists of values for the header. + + The following configuration will result in the + [`accept: application/json`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) HTTP header + being sent with the HTTP request to the datasource: + + ```yaml + headers: + accept: + - "application/json" + ``` +
+
+
+ + +## Using templates in the URLs of `datasources` + +Advanced + +Let's suppose that your company uses a centralized software catalog to consolidate all tags for tagging all the cloud +resources. The tags can include tags per account, per team, per service, billing tags, etc. + +:::note +An example of such a centralized software catalog could be https://backstage.io +::: + +
+ +Let's also suppose that you have a service to read the tags from the centralized catalog and write them into an S3 +bucket in one of your accounts. The bucket serves as a cache to not hit the external system's API with too many requests +and not to trigger rate limiting. + +And finally, let's say that in the bucket, you have folders per account (`dev`, `prod`, `staging`). Each folder has a JSON +file with all the tags defined for all the cloud resources in the accounts. + +We can then use the [Gomplate S3 datasource](https://docs.gomplate.ca/datasources/#using-s3-datasources) to read the JSON +file with the tags for each account and assign the tags to all cloud resources. + +In `atmos.yaml`, we figure two evaluations steps of template processing: + + +```yaml +templates: + settings: + enabled: true + # Number of evaluations to process `Go` templates + evaluations: 2 + gomplate: + enabled: true +``` + + +In an Atmos stack manifest, we define the environment variables in the `env` section (AWS profile with permissions to +access the S3 bucket), and the `s3-tags` Gomplate datasource. + +In the `terraform.vars.tags` section, we define all the tags that are returned from the call to the S3 datasource. + +```yaml +import: + # Import the default configuration for all VPCs in the infrastructure + - catalog/vpc/defaults + +# Global settings +settings: + templates: + settings: + # Environment variables passed to datasources when evaluating templates + # https://docs.gomplate.ca/functions/aws/#configuring-aws + # https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html + env: + # AWS profile with permissions to access the S3 bucket + AWS_PROFILE: "" + gomplate: + # Timeout in seconds to execute the datasources + timeout: 5 + # https://docs.gomplate.ca/datasources + datasources: + # `s3` datasource + # https://docs.gomplate.ca/datasources/#using-s3-datasources + s3-tags: + # The `url` uses a `Go` template with the delimiters `${ }`, + # which is processed as first step in the template processing pipeline + url: "s3://mybucket/{{ .vars.stage }}/tags.json" + +# Global Terraform config +terraform: + # Global variables that are used by all Atmos components + vars: + tags: + atmos_component: "{{ .atmos_component }}" + atmos_stack: "{{ .atmos_stack }}" + terraform_component: "{{ .component }}" + terraform_workspace: "{{ .workspace }}" + devops_team: '{{`{{ (datasource "s3-tags").tags.devops_team }}`}}' + billing_team: '{{`{{ (datasource "s3-tags").tags.billing_team }}`}}' + service: '{{`{{ (datasource "s3-tags").tags.service }}`}}' + +# Atmos component configurations +components: + terraform: + vpc/1: + metadata: + component: vpc # Point to the Terraform component in `components/terraform/vpc` folder + inherits: + # Inherit from the `vpc/defaults` base Atmos component, which defines the default + # configuration for all VPCs in the infrastructure. + # The `vpc/defaults` base component is defined in the `catalog/vpc/defaults` + # manifest (which is imported above). + # This inheritance makes the `vpc/1` Atmos component config DRY. + - "vpc/defaults" + vars: + name: "vpc-1" +``` + +When executing an Atmos command like `atmos terraform apply vpc/1 -s plat-ue2-dev`, the above template will be processed +in two evaluation steps: + +- Evaluation 1: + + - `datasources.s3-tags.url` is set to `s3://mybucket/dev/tags.json` + + - the tags that use the `datasource` templates are set to the following: + + ```yaml + devops_team: '{{ (datasource "s3-tags").tags.devops_team }}' + billing_team: '{{ (datasource "s3-tags").tags.billing_team }}' + service: '{{ (datasource "s3-tags").tags.service }}' + ``` + +- Evaluation 2: + - all `s3-tags` datasources get executed, the JSON file `s3://mybucket/dev/tags.json` with the tags + for the `dev` account is downloaded from the S3 bucket, and the tags are parsed and assigned in the + `terraform.vars.tags` section + +After executing the two evaluation steps, the resulting tags for the Atmos component `vpc/1` in the stack `plat-ue2-dev` +would look like this: + +```yaml +atmos_component: vpc/1 +atmos_stack: plat-ue2-dev +terraform_component: vpc +terraform_workspace: plat-ue2-dev-vpc-1 +devops_team: dev_networking +billing_team: billing_net +service: net +``` + +The tags will be added to all the AWS resources provisioned by the `vpc` Terraform component in the `plat-ue2-dev` stack. diff --git a/website/docs/core-concepts/stacks/templates/functions/atmos.Component.mdx b/website/docs/core-concepts/stacks/templates/functions/atmos.Component.mdx new file mode 100644 index 000000000..2c8ae9d71 --- /dev/null +++ b/website/docs/core-concepts/stacks/templates/functions/atmos.Component.mdx @@ -0,0 +1,168 @@ +--- +title: atmos.Component +sidebar_position: 1 +sidebar_label: atmos.Component +description: Read the remote state or configuration of any Atmos component +--- +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' + + +The `atmos.Component` template function allows reading any Atmos section or any attribute from a section for an +Atmos component in a stack, and use it in `Go` templates in Atmos component configurations. + + +## Usage + +```yaml + {{ (atmos.Component "" "").
. }} +``` + +## Arguments + +
+
`component`
+
Atmos component name
+ +
`stack`
+
Atmos stack name
+ +
`section`
+
Atmos section name. Any section returned by the CLI command + atmos describe component can be used. + A special `outputs` section is also supported to get the outputs (remote state) of Terraform/OpenTofu components.
+ +
`outputs`
+
Using the `outputs` section in the `atmos.Component` command is an convenient way to read the outputs (remote state) + of a component in a stack directly in Atmos stack manifests. It is an alternative to using the `remote-state` + module and configuring Terraform/OpenTofu components to use the `remote-state` module as described in + Component Remote State
+ +
`attribute`
+
+ Attribute name (field) from the `section`. `attribute` is optional, you can use the `section` itself + if it's a simple type (e.g. `string`). Any number of attributes can be chained using the dot (`.`) notation. + For example, if the first two attributes are maps, you can chain them and get a field from the last map: + ```yaml + {{ (atmos.Component "" "").
... }} + ``` +
+
+ + +## Specifying Atmos `stack` + +There are multiple ways you can specify the Atmos stack parameter in the `atmos.Component` function. + +The `stack` argument is the second argument of the `atmos.Component` function, and it can be specified in a few different ways: + +### Hardcoded Stack Name + +Hardcoded stack name. Use it if you want to get an output from a component from a different (well-known and static) stack. For example, you have a `tgw` component in a stack `plat-ue2-dev` that requires the `vpc_id` output from the `vpc` component from the stack `plat-ue2-prod`: + +```yaml title="plat-ue2-dev" + components: + terraform: + tgw: + vars: + vpc_id: '{{ (atmos.Component "vpc" "plat-ue2-prod").outputs.vpc_id }}' +``` + +### Reference the Current Stack Name + +Use the `.stack` (or `.atmos_stack`) template identifier to specify the same stack as the current component (for which the `atmos.Component` function is executed): + +```yaml + {{ (atmos.Component "" .stack).
. }} + {{ (atmos.Component "" .atmos_stack).
. }} +``` + +For example, you have a `tgw` component that requires the `vpc_id` output from the `vpc` component in the same stack: + +```yaml + components: + terraform: + tgw: + vars: + vpc_id: '{{ (atmos.Component "vpc" .stack).outputs.vpc_id }}' +``` + +### Use a Format Function + +Use the `printf` template function to construct stack names using static strings and dynamic identifiers. This is convenient when you want to override some identifiers in the stack name: + +```yaml + {{ (atmos.Component "" (printf "%s-%s-%s" .vars.tenant .vars.environment .vars.stage)).
. }} + + {{ (atmos.Component "" (printf "plat-%s-prod" .vars.environment)).
. }} + + {{ (atmos.Component "" (printf "%s-%s-%s" .settings.context.tenant .settings.context.region .settings.context.account)).
. }} +``` + +For example, you have a `tgw` component deployed in the stack `plat-ue2-dev`. The `tgw` component requires the +`vpc_id` output from the `vpc` component from the same environment (`ue2`) and same stage (`dev`), but from a different +tenant `net` (instead of `plat`): + +```yaml title="plat-ue2-dev" + components: + terraform: + tgw: + vars: + vpc_id: '{{ (atmos.Component "vpc" (printf "net-%s-%s" .vars.environment .vars.stage)).outputs.vpc_id }}' +``` + +:::tip Important + By using the `printf "%s-%s-%s"` function, you are constructing stack names using the stack context variables/identifiers. + + For more information on Atmos stack names and how to define them, refer to `stacks.name_pattern` and `stacks.name_template` + sections in [`atmos.yaml` CLI config file](/cli/configuration/#stacks) +::: + +## Examples + +The following configurations show different ways of using the `atmos.Component` template function to read values from +different Atmos sections directly in Atmos stack manifests, including the outputs of other +(already provisioned) components. + + +```yaml +# Global `settings` section +# It will be added and deep-merged to the `settings` section of all components +settings: + test: true + +components: + terraform: + test: + metadata: + # Point to the Terraform/OpenTofu component + component: "test" + vars: + name: "test" + + test1: + metadata: + # Point to the Terraform/OpenTofu component + component: "test1" + vars: + name: "test1" + + test2: + metadata: + # Point to the Terraform/OpenTofu component + component: "test2" + vars: + name: "test2" + # Use the `atmos.Component` function to get the outputs of the Atmos component `test1` + # The `test1` component must be already provisioned and its outputs stored in the Terraform/OpenTofu state + # Atmos will execute `terraform output` on the `test1` component in the same stack to read its outputs + test1_id: '{{ (atmos.Component "test1" .stack).outputs.test1_id }}' + tags: + # Get the `settings.test` field from the `test` component in the same stack + test: '{{ (atmos.Component "test" .stack).settings.test }}' + # Get the `metadata.component` field from the `test` component in the same stack + test_terraform_component: '{{ (atmos.Component "test" .stack).metadata.component }}' + # Get the `vars.name` field from the `test1` component in the same stack + test1_name: '{{ (atmos.Component "test1" .stack).vars.name }}' +``` + diff --git a/website/docs/core-concepts/stacks/templates/functions/functions.mdx b/website/docs/core-concepts/stacks/templates/functions/functions.mdx new file mode 100644 index 000000000..ec3561b79 --- /dev/null +++ b/website/docs/core-concepts/stacks/templates/functions/functions.mdx @@ -0,0 +1,33 @@ +--- +title: Atmos Template Functions +sidebar_position: 6 +sidebar_label: Functions +description: Atmos functions for the Go’s template language. +id: functions +--- +import DocCardList from '@theme/DocCardList' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' + + +Atmos provides template functions for the `Go` template language, that can be used in Atmos stack manifests. These functions are used to manipulate data and perform operations on the data. + + +## Supported Functions + +Atmos supports an exhaustive list of functions can be used in [`Go` templates in Atmos stack manifests](/core-concepts/stacks/templates). + +You can use the following functions and datasources: + + - [Go `text/template` functions](https://pkg.go.dev/text/template#hdr-Functions) + - [Sprig Functions](https://masterminds.github.io/sprig/) + - [Gomplate Functions](https://docs.gomplate.ca/functions/) + - [Gomplate Datasources](https://docs.gomplate.ca/datasources/) + - [Atmos Template Functions](/core-concepts/stacks/templates/functions) + +## Native Functions + +Atmos also has some functions that are native to Atmos. + + diff --git a/website/docs/core-concepts/stacks/templating.mdx b/website/docs/core-concepts/stacks/templates/templates.mdx similarity index 58% rename from website/docs/core-concepts/stacks/templating.mdx rename to website/docs/core-concepts/stacks/templates/templates.mdx index e30b77b55..d4103c32a 100644 --- a/website/docs/core-concepts/stacks/templating.mdx +++ b/website/docs/core-concepts/stacks/templates/templates.mdx @@ -1,79 +1,87 @@ --- title: Stack Manifest Templating sidebar_position: 7 -sidebar_label: Templating -id: templating +sidebar_label: Template Configurations +id: templates --- import File from '@site/src/components/File' import Terminal from '@site/src/components/Terminal' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' -Atmos supports [Go templates](https://pkg.go.dev/text/template) in stack manifests. +Advanced -In `Go` templates, you can use the following functions and datasources: + +Use templates as an _escape hatch_, when standard [inheritance](/core-concepts/stacks/inheritance) as insufficient. Atmos supports [Go templates](https://pkg.go.dev/text/template) in stack manifests and functions to customize Stack configurations _prior_ to interpretting them as YAML. + - - [Go `text/template` functions](https://pkg.go.dev/text/template#hdr-Functions) - - [Sprig Functions](https://masterminds.github.io/sprig/) - - [Gomplate Functions](https://docs.gomplate.ca/functions/) - - [Gomplate Datasources](https://docs.gomplate.ca/datasources/) - - [Atmos Template Functions](/core-concepts/template-functions) +### Enable Templating -## Important Note +Templating in Atmos stack manifests is configured in the `atmos.yaml` [CLI config file](/cli/configuration) in the +`templates.settings` section. -Atmos supports many different ways of configuring and using `Go` templates: +
+
`templates.settings`
+
In the `templates.settings` section in `atmos.yaml` [CLI config file](/cli/configuration)
-- In [Atmos Custom Commands](/core-concepts/custom-commands) -- In [Atmos Vendoring](/core-concepts/vendoring) -- In [Atmos Component Vendoring](/core-concepts/components/vendoring) -- In [Imports](/core-concepts/stacks/imports) -- In [Stack Manifests](/core-concepts/stacks) +
`settings.templates.settings`
+
+ In the `settings.templates.settings` section in [Atmos stack manifests](/core-concepts/stacks). The `settings.templates.settings` section can be defined globally per organization, tenant, account, or per component. Atmos deep-merges the configurations from all scopes into the final result using [inheritance](/core-concepts/stacks/inheritance). +
-These templates are processed in different phases and use different context: +
`templates.settings.enabled`
+
A boolean flag to enable/disable the processing of `Go` templates in Atmos stack manifests. If set to `false`, Atmos will not process `Go` templates in stack manifests.
+
-- `Go` templates in [Atmos Custom Commands](/core-concepts/custom-commands) are processed when the custom commands are - executed. The execution context can be specified by using the `component_config` section. If a custom command defines - a `component_config` section with `component` and `stack`, Atmos generates the config for the component in the stack - and makes it available in the `{{ .ComponentConfig.xxx.yyy.zzz }}` template variables, - exposing all the component sections that are returned by the `atmos describe component -s ` CLI - command -- `Go` templates in [Atmos Vendoring](/core-concepts/vendoring) and [Atmos Component Vendoring](/core-concepts/components/vendoring) - are processed when the CLI command [`atmos vendor pull`](/cli/commands/vendor/pull) is executed. The templates in - the vendoring manifests support the `{{.Version}}` variable, and the execution context is provided in the `version` attribute +### Configure Templating -- [`Go` Templates in Imports](/core-concepts/stacks/imports#go-templates-in-imports) are used in imported stack - manifests to make them DRY and reusable. The context (variables) for the `Go` templates is provided via the static - `context` section. Atmos processes `Go` templates in imports as the **very first** phase of the stack processing pipeline. - When executing the [CLI commands](/cli/commands), Atmos parses and executes the templates using the provided static - `context`, processes all imports, and finds stacks and components +
-- `Go` templates in Atmos stack manifests, on the other hand, are processed as the **very last** phase of the stack processing - pipeline (after all imports are processed, all stack configurations are deep-merged, and the component in the stack is found). - For the context (template variables), it uses all the component's attributes returned from the - [`atmos describe component`](/cli/commands/describe/component) CLI command +
`templates.settings.env`
+
A map of environment variables to use when executing the templates.
-These mechanisms, although all using `Go` templates, serve different purposes, use different contexts, and are executed -in different phases of the stack processing pipeline. +
`templates.settings.evaluations`
+
Number of evaluations/passes to process `Go` templates. If not defined, `evaluations` is automatically set to `1`. For more details, refer to [Template Evaluations and Template Processing Pipelines](#template-evaluations-and-template-processing-pipelines).
-For more details, refer to: +
`templates.settings.delimiters`
+
A list of left and right delimiters to use to process the templates. If not defined, the default `Go` template delimiters `["{{", "}}"]` will be used.
-- [`Go` Templates in Imports](/core-concepts/stacks/imports#go-templates-in-imports) -- [Excluding templates in imports from processing by Atmos](#excluding-templates-in-stack-manifest-from-processing-by-atmos) +
`templates.settings.sprig.enabled`
+
A boolean flag to enable/disable the [Sprig Functions](https://masterminds.github.io/sprig/) in Atmos stack manifests.
+
`templates.settings.gomplate.enabled`
+
A boolean flag to enable/disable the [Gomplate Functions](https://docs.gomplate.ca/functions/) and [Gomplate Datasources](https://docs.gomplate.ca/datasources) in Atmos stack manifests.
-## Stack Manifest Templating Configuration +
`templates.settings.gomplate.timeout`
+
Timeout in seconds to execute [Gomplate Datasources](https://docs.gomplate.ca/datasources).
-Templating in Atmos stack manifests can be configured in the following places: +
-- In the `templates.settings` section in `atmos.yaml` [CLI config file](/cli/configuration) +:::warning -- In the `settings.templates.settings` section in [Atmos stack manifests](/core-concepts/stacks). - The `settings.templates.settings` section can be defined globally per organization, tenant, account, or per component. - Atmos deep-merges the configurations from all scopes into the final result using [inheritance](/core-concepts/components/inheritance). +Some functions are present in both [Sprig](https://masterminds.github.io/sprig/) and [Gomplate](https://docs.gomplate.ca/functions/). -### Configuring Templating in `atmos.yaml` CLI Config File +For example, the `env` function has the same name in [Sprig](https://masterminds.github.io/sprig/os.html) and +[Gomplate](https://docs.gomplate.ca/functions/env/), but has different syntax and accept different number of arguments. -Templating in Atmos stack manifests is configured in the `atmos.yaml` [CLI config file](/cli/configuration) in the -`templates.settings` section: +If you use the `env` function from one templating engine and enable both [Sprig](https://masterminds.github.io/sprig/) +and [Gomplate](https://docs.gomplate.ca/functions/), it will be invalid in the other templating engine, and an error will be thrown. + +To be able to use the `env` function from both templating engines, you can do one of the following: + +- Use the `env` function from one templating engine, and disable the other templating engine by using the + `templates.settings.sprig.enabled` and `templates.settings,gomplate.enabled` settings + +- Enable both engines and use the Gomplate's `env` function via its + [`getenv`](https://docs.gomplate.ca/functions/env/#examples) alias + +::: + +#### Example Configuration ```yaml @@ -106,121 +114,33 @@ templates: enabled: true # Timeout in seconds to execute the datasources timeout: 5 - # https://docs.gomplate.ca/datasources - datasources: - # 'http' datasource - # https://docs.gomplate.ca/datasources/#using-file-datasources - ip: - url: "https://api.ipify.org?format=json" - # https://docs.gomplate.ca/datasources/#sending-http-headers - # https://docs.gomplate.ca/usage/#--datasource-header-h - headers: - accept: - - "application/json" - # 'file' datasources - # https://docs.gomplate.ca/datasources/#using-file-datasources - config-1: - url: "./config1.json" - config-2: - url: "file:///config2.json" - # `aws+smp` AWS Systems Manager Parameter Store datasource - # https://docs.gomplate.ca/datasources/#using-awssmp-datasources - secret-1: - url: "aws+smp:///path/to/secret" - # `aws+sm` AWS Secrets Manager datasource - # https://docs.gomplate.ca/datasources/#using-awssm-datasource - secret-2: - url: "aws+sm:///path/to/secret" - # `s3` datasource - # https://docs.gomplate.ca/datasources/#using-s3-datasources - s3-config: - url: "s3://mybucket/config/config.json" + datasources: {} ``` -- `templates.settings.enabled` - a boolean flag to enable/disable the processing of `Go` templates in Atmos stack manifests. - If set to `false`, Atmos will not process `Go` templates in stack manifests - -- `templates.settings.env` - a map of environment variables to use when executing the templates - -- `templates.settings.evaluations` - number of evaluations/passes to process `Go` templates. If not defined, `evaluations` - is automatically set to `1`. For more details, refer to - [Template Evaluations and Template Processing Pipelines](#template-evaluations-and-template-processing-pipelines) - -- `templates.settings.delimiters` - a list of left and right delimiters to use to process the templates. - If not defined, the default `Go` template delimiters `["{{", "}}"]` will be used - -- `templates.settings.sprig.enabled` - a boolean flag to enable/disable the [Sprig Functions](https://masterminds.github.io/sprig/) - in Atmos stack manifests - -- `templates.settings.gomplate.enabled` - a boolean flag to enable/disable the [Gomplate Functions](https://docs.gomplate.ca/functions/) - and [Gomplate Datasources](https://docs.gomplate.ca/datasources) in Atmos stack manifests - -- `templates.settings.gomplate.timeout` - timeout in seconds to execute [Gomplate Datasources](https://docs.gomplate.ca/datasources) - -- `templates.settings.gomplate.datasources` - a map of [Gomplate Datasource](https://docs.gomplate.ca/datasources) definitions: - - - The keys of the map are the datasource names (aliases), which are used in `Go` templates in Atmos stack manifests. - For example: - - ```yaml - terraform: - vars: - tags: - provisioned_by_ip: '{{ (datasource "ip").ip }}' - config1_tag: '{{ (datasource "config-1").tag }}' - config2_service_name: '{{ (datasource "config-2").service.name }}' - ``` - - - - The values of the map are the datasource definitions with the following schema: - - - `url` - the [Datasource URL](https://docs.gomplate.ca/datasources/#url-format) - - - `headers` - a map of [HTTP request headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) for - the [`http` datasource](https://docs.gomplate.ca/datasources/#sending-http-headers). - The keys of the map are the header names. The values of the map are lists of values for the header. - - The following configuration will result in the - [`accept: application/json`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) HTTP header - being sent with the HTTP request to the datasource: - - ```yaml - headers: - accept: - - "application/json" - ``` - -
- -:::warning - -Some functions are present in both [Sprig](https://masterminds.github.io/sprig/) and [Gomplate](https://docs.gomplate.ca/functions/). - -For example, the `env` function has the same name in [Sprig](https://masterminds.github.io/sprig/os.html) and -[Gomplate](https://docs.gomplate.ca/functions/env/), but has different syntax and accept different number of arguments. - -If you use the `env` function from one templating engine and enable both [Sprig](https://masterminds.github.io/sprig/) -and [Gomplate](https://docs.gomplate.ca/functions/), it will be invalid in the other templating engine, and an error will be thrown. +## Functions and Data Sources -To be able to use the `env` function from both templating engines, you can do one of the following: +Go templates by themselves are pretty basic, supporting concepts like ranges and variable interpolations. But what really makes templating powerful is the library of functions provided by Atmos to the template engine. -- Use the `env` function from one templating engine, and disable the other templating engine by using the - `templates.settings.sprig.enabled` and `templates.settings,gomplate.enabled` settings - -- Enable both engines and use the Gomplate's `env` function via its - [`getenv`](https://docs.gomplate.ca/functions/env/#examples) alias +In `Go` templates, you can use the following functions and datasources: -::: + - [Go `text/template` functions](https://pkg.go.dev/text/template#hdr-Functions) + - [Sprig Functions](https://masterminds.github.io/sprig/) + - [Gomplate Functions](https://docs.gomplate.ca/functions/) (note, this is "Gomplate" and not "Go template") + - [Gomplate Datasources](https://docs.gomplate.ca/datasources/) + - [Atmos Template Functions](/core-concepts/stacks/templates/functions) -
+ + Functions are a crucial part of templating in Atmos stack manifests. They allow you to manipulate data and perform operations on the data to customize the stack configurations. + Learn About Functions + ### Configuring Templating in Atmos Stack Manifests Templating in Atmos can also be configured in the `settings.templates.settings` section in stack manifests. The `settings.templates.settings` section can be defined globally per organization, tenant, account, or per component. -Atmos deep-merges the configurations from all scopes into the final result using [inheritance](/core-concepts/components/inheritance). +Atmos deep-merges the configurations from all scopes into the final result using [inheritance](/core-concepts/stacks/inheritance). The schema is the same as `templates.settings` in the `atmos.yaml` [CLI config file](/cli/configuration), except the following settings are not supported in the `settings.templates.settings` section: @@ -233,13 +153,13 @@ except the following settings are not supported in the `settings.templates.setti These settings are not supported for the following reasons: -- You can't disable templating in the stack manifests which are being processed by Atmos as `Go` templates +- You can't disable templating in the stack manifests which are being processed by Atmos as `Go` templates -- If you define the `delimiters` in the `settings.templates.settings` section in stack manifests, - the `Go` templating engine will think that the delimiters specify the beginning and the end of template strings, will +- If you define the `delimiters` in the `settings.templates.settings` section in stack manifests, + the `Go` templating engine will think that the delimiters specify the beginning and the end of template strings, will try to evaluate it, which will result in an error -As an example, let's define templating configuration for the entire organization in the `stacks/orgs/acme/_defaults.yaml` +As an example, let's define templating configuration for the entire organization in the `stacks/orgs/acme/_defaults.yaml` stack manifest: @@ -269,14 +189,14 @@ settings: Atmos deep-merges the configurations from the `settings.templates.settings` section in [Atmos stack manifests](/core-concepts/stacks) -with the `templates.settings` section in `atmos.yaml` [CLI config file](/cli/configuration) using [inheritance](/core-concepts/components/inheritance). +with the `templates.settings` section in `atmos.yaml` [CLI config file](/cli/configuration) using [inheritance](/core-concepts/stacks/inheritance). -The `settings.templates.settings` section in [Atmos stack manifests](/core-concepts/stacks) takes precedence over +The `settings.templates.settings` section in [Atmos stack manifests](/core-concepts/stacks) takes precedence over the `templates.settings` section in `atmos.yaml` [CLI config file](/cli/configuration), allowing you to define the global `datasources` in `atmos.yaml` and then add or override `datasources` in Atmos stack manifests for the entire organization, tenant, account, or per component. -For example, taking into account the configurations described above in `atmos.yaml` [CLI config file](/cli/configuration) +For example, taking into account the configurations described above in `atmos.yaml` [CLI config file](/cli/configuration) and in the `stacks/orgs/acme/_defaults.yaml` stack manifest, the final `datasources` map will look like this: @@ -306,7 +226,7 @@ gomplate: ``` -Note that the `config-1` datasource from `atmos.yaml` was overridden with the `config-1` datasource from the +Note that the `config-1` datasource from `atmos.yaml` was overridden with the `config-1` datasource from the `stacks/orgs/acme/_defaults.yaml` stack manifest. The `timeout` attribute was overridden as well. You can now use the `datasources` in `Go` templates in all Atmos sections that support `Go` templates. @@ -325,15 +245,11 @@ You can use `Go` templates in the following Atmos sections to refer to values in - `component` - `metadata.component` -
- :::tip -In the template tokens, you can refer to any value in any section that the Atmos command +In the template tokens, you can refer to any value in any section that the Atmos command [`atmos describe component -s `](/cli/commands/describe/component) generates ::: -
- For example, let's say we have the following component configuration using `Go` templates: @@ -386,11 +302,11 @@ component: ``` -When executing Atmos commands like `atmos describe component` and `atmos terraform plan/apply`, Atmos processes all the template tokens +When executing Atmos commands like `atmos describe component` and `atmos terraform plan/apply`, Atmos processes all the template tokens in the manifest and generates the final configuration for the component in the stack: -```yaml +```yaml settings: setting1: 1 setting2: 2 @@ -431,130 +347,76 @@ vars: ``` -## Environment Variables - -Some data sources might need environment variables that are different from the environment variables in Stack configuration. Environment variables may be passed to data soruces when processing and executing templates by defining `env` map. -It's supported in both the `templates.settings` section in `atmos.yaml` [CLI config file](/cli/configuration) and in the -`settings.templates.settings` section in [Atmos stack manifests](/core-concepts/stacks). +## Template Evaluations -For example: - - -```yaml -settings: - templates: - settings: - # Environment variables passed to datasources when evaluating templates - # https://docs.gomplate.ca/datasources/#using-awssmp-datasources - # https://docs.gomplate.ca/functions/aws/#configuring-aws - # https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html - env: - AWS_PROFILE: "" - AWS_TIMEOUT: 2000 -``` - - -This is useful when executing the `datasources` that need to authenticate to cloud APIs. +Atmos supports many different ways of configuring and using `Go` templates: -For more details, refer to: +- In [Atmos Custom Commands](/core-concepts/custom-commands) +- In [Atmos Vendoring](/core-concepts/vendor) +- In [Atmos Component Vendoring](/core-concepts/vendor/vendor-manifest) +- In [Imports](/core-concepts/stacks/imports) +- In [Stack Manifests](/core-concepts/stacks) -- [Configuring AWS](https://docs.gomplate.ca/functions/aws/#configuring-aws) -- [Configuring GCP](https://docs.gomplate.ca/functions/gcp/#configuring-gcp) +### Phases -## Datasources +These templates are processed in different phases and use different context: -Currently, Atmos supports all the [Gomplate Datasources](https://docs.gomplate.ca/datasources). -More datasources will be added in the future (and this doc will be updated). +- `Go` templates in [Atmos Custom Commands](/core-concepts/custom-commands) are processed when the custom commands are + executed. The execution context can be specified by using the `component_config` section. If a custom command defines + a `component_config` section with `component` and `stack`, Atmos generates the config for the component in the stack + and makes it available in the `{{ .ComponentConfig.xxx.yyy.zzz }}` template variables, + exposing all the component sections that are returned by the `atmos describe component -s ` CLI + command -The [Gomplate Datasources](https://docs.gomplate.ca/datasources) can be configured in the -`templates.settings.gomplate.datasources` section in `atmos.yaml` -[CLI config file](/cli/configuration) and in the `settings.templates.settings` section in -[Atmos stack manifests](/core-concepts/stacks). +- `Go` templates in [Atmos Vendoring](/core-concepts/vendor) and [Atmos Component Vendoring](/core-concepts/vendor/vendor-manifest) + are processed when the CLI command [`atmos vendor pull`](/cli/commands/vendor/pull) is executed. The templates in + the vendoring manifests support the `{{.Version}}` variable, and the execution context is provided in the `version` attribute -The `templates.settings.gomplate.datasources` section is a map of objects. +- [`Go` Templates in Imports](/core-concepts/stacks/imports#go-templates-in-imports) are used in imported stack + manifests to make them DRY and reusable. The context (variables) for the `Go` templates is provided via the static + `context` section. Atmos processes `Go` templates in imports as the **very first** phase of the stack processing pipeline. + When executing the [CLI commands](/cli/commands), Atmos parses and executes the templates using the provided static + `context`, processes all imports, and finds stacks and components -The keys of the map are the datasource names (aliases). +- `Go` templates in Atmos stack manifests, on the other hand, are processed as the **very last** phase of the stack processing + pipeline (after all imports are processed, all stack configurations are deep-merged, and the component in the stack is found). + For the context (template variables), it uses all the component's attributes returned from the + [`atmos describe component`](/cli/commands/describe/component) CLI command -The values of the map are the datasource definitions with the following schema: +These mechanisms, although all using `Go` templates, serve different purposes, use different contexts, and are executed +in different phases of the stack processing pipeline. - - `url` - the [Datasource URL](https://docs.gomplate.ca/datasources/#url-format) +For more details, refer to: - - `headers` - a map of [HTTP request headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) for - the [`http` datasource](https://docs.gomplate.ca/datasources/#sending-http-headers). - The keys of the map are the header names. The values of the map are lists of values for the header. +- [`Go` Templates in Imports](/core-concepts/stacks/imports#go-templates-in-imports) +- [Excluding templates in imports from processing by Atmos](#excluding-templates-in-stack-manifest-from-processing-by-atmos) - The following configuration will result in the - [`accept: application/json`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) HTTP header - being sent with the HTTP request to the datasource: +### Processing Pipelines - ```yaml - headers: - accept: - - "application/json" - ``` +Atmos supports configuring the number of evaluations/passes for template processing in `atmos.yaml` [CLI config file](/cli/configuration). +It effectively allows you to define template processing pipelines. -For example, let's define the following Gomplate datasources in the global `settings` section (this will apply to all -components in all stacks in the infrastructure): +For example: ```yaml -settings: - templates: - settings: - gomplate: - # Timeout in seconds to execute the datasources - timeout: 5 - # https://docs.gomplate.ca/datasources - datasources: - # 'http' datasource - # https://docs.gomplate.ca/datasources/#using-file-datasources - ip: - url: "https://api.ipify.org?format=json" - # https://docs.gomplate.ca/datasources/#sending-http-headers - # https://docs.gomplate.ca/usage/#--datasource-header-h - headers: - accept: - - "application/json" - # 'file' datasources - # https://docs.gomplate.ca/datasources/#using-file-datasources - config-1: - url: "./config1.json" - config-2: - url: "file:///config2.json" - # `aws+smp` AWS Systems Manager Parameter Store datasource - # https://docs.gomplate.ca/datasources/#using-awssmp-datasources - secret-1: - url: "aws+smp:///path/to/secret" - # `aws+sm` AWS Secrets Manager datasource - # https://docs.gomplate.ca/datasources/#using-awssm-datasource - secret-2: - url: "aws+sm:///path/to/secret" - # `s3` datasource - # https://docs.gomplate.ca/datasources/#using-s3-datasources - s3-config: - url: "s3://mybucket/config/config.json" +templates: + settings: + # Enable `Go` templates in Atmos stack manifests + enabled: true + # Number of evaluations/passes to process `Go` templates + # If not defined, `evaluations` is automatically set to `1` + evaluations: 2 ``` -After the above `datasources` are defined, you can use them in Atmos stack manifests like this: +- `templates.settings.evaluations` - number of evaluations to process `Go` templates. If not defined, `evaluations` + is automatically set to `1` -```yaml -terraform: - vars: - tags: - tag1: '{{ (datasource "config-1").tag }}' - service_name2: '{{ (datasource "config-2").service.name }}' - service_name3: '{{ (datasource "s3-config").config.service_name }}' +Template evaluations are useful in the following scenarios: -components: - terraform: - vpc-1: - settings: - provisioned_by_ip: '{{ (datasource "ip").ip }}' - secret-1: '{{ (datasource "secret-1").secret1.value }}' - vars: - enabled: '{{ (datasource "config-2").config.enabled }}' -``` +- Combining templates from different sections in Atmos stack manifests +- Using templates in the URLs of `datasources` ## Use-cases @@ -650,8 +512,6 @@ chart_values: } ``` -
- The `printf` template function is also supported and can be used instead of **double curly braces + backtick + double curly braces**. The following examples produce the same result: @@ -685,14 +545,12 @@ chart_values: ## Excluding Templates in Imports from Processing by Atmos If you are using [`Go` Templates in Imports](/core-concepts/stacks/imports#go-templates-in-imports) and `Go` templates -in stack manifests in the same Atmos manifest, take into account that in this case Atmos will do `Go` +in stack manifests in the same Atmos manifest, take into account that in this case Atmos will do `Go` template processing two times (two passes): - When importing the manifest and processing the template tokens using the variables from the provided `context` object - After finding the component in the stack as the final step in the processing pipeline -
- For example, we can define the following configuration in the `stacks/catalog/eks/eks_cluster.tmpl` template file: ```yaml title="stacks/catalog/eks/eks_cluster.tmpl" @@ -710,8 +568,6 @@ components: terraform_workspace: "{{ .workspace }}" ``` -
- Then we import the template into a top-level stack providing the context variables for the import in the `context` object: ```yaml title="stacks/orgs/acme/plat/prod/us-east-2.yaml" @@ -741,9 +597,7 @@ components: terraform_workspace: ``` -
- -The second pass of template processing will not replace the tokens in `tags` because they are already processed in the +The second pass of template processing will not replace the tokens in `tags` because they are already processed in the first pass (importing) and the values `` are generated. To deal with this, use **double curly braces + backtick + double curly braces** instead of just **double curly braces** @@ -764,8 +618,6 @@ components: terraform_workspace: "{{`{{ .workspace }}`}}" ``` -
- Atmos will first process the import and replace the template tokens using the variables from the `context`. Then in the second pass the tokens in `tags` will be replaced with the correct values. @@ -786,32 +638,6 @@ components: terraform_workspace: plat-ue2-prod ``` -## Template Evaluations and Template Processing Pipelines - -Atmos supports configuring the number of evaluations/passes for template processing in `atmos.yaml` [CLI config file](/cli/configuration). -It effectively allows you to define template processing pipelines. - -For example: - - -```yaml -templates: - settings: - # Enable `Go` templates in Atmos stack manifests - enabled: true - # Number of evaluations/passes to process `Go` templates - # If not defined, `evaluations` is automatically set to `1` - evaluations: 2 -``` - - -- `templates.settings.evaluations` - number of evaluations to process `Go` templates. If not defined, `evaluations` - is automatically set to `1` - -Template evaluations are useful in the following scenarios: - -- Combining templates from different sections in Atmos stack manifests -- Using templates in the URLs of `datasources` ### Combining templates from different sections in Atmos stack manifests @@ -843,7 +669,7 @@ components: tag2: "{{\"{{`{{ .atmos_component }}`}}\"}}" ``` -When executing an Atmos command like `atmos terraform plan vpc -s `, the above template will be processed +When executing an Atmos command like `atmos terraform plan vpc -s `, the above template will be processed in three phases: - Evaluation 1 @@ -867,147 +693,13 @@ in three phases: - `vpc.vars.tags.tag1` is `vpc-vpc` - `vpc.vars.tags.tag2` is set to `vpc` -
- :::warning The above example shows the supported functionality in Atmos templating. You can use it for some use-cases, but it does not mean that you **should** use it just for the sake of using, since it's not easy to read and understand what data we have after each evaluation step. -The following use-case describes a practical approach to using evaluation steps in Atmos templates to work +The following use-case describes a practical approach to using evaluation steps in Atmos templates to work with `datasources`. ::: - -### Using templates in the URLs of `datasources` - -Let's suppose that your company uses a centralized software catalog to consolidate all tags for tagging all the cloud -resources. The tags can include tags per account, per team, per service, billing tags, etc. - -:::note -An example of such a centralized software catalog could be https://backstage.io -::: - -
- -Let's also suppose that you have a service to read the tags from the centralized catalog and write them into an S3 -bucket in one of your accounts. The bucket serves as a cache to not hit the external system's API with too many requests -and not to trigger rate limiting. - -And finally, let's say that in the bucket, you have folders per account (`dev`, `prod`, `staging`). Each folder has a JSON -file with all the tags defined for all the cloud resources in the accounts. - -We can then use the [Gomplate S3 datasource](https://docs.gomplate.ca/datasources/#using-s3-datasources) to read the JSON -file with the tags for each account and assign the tags to all cloud resources. - -In `atmos.yaml`, we figure two evaluations steps of template processing: - - -```yaml -templates: - settings: - enabled: true - # Number of evaluations to process `Go` templates - evaluations: 2 - gomplate: - enabled: true -``` - - -In an Atmos stack manifest, we define the environment variables in the `env` section (AWS profile with permissions to -access the S3 bucket), and the `s3-tags` Gomplate datasource. - -In the `terraform.vars.tags` section, we define all the tags that are returned from the call to the S3 datasource. - -```yaml -import: - # Import the default configuration for all VPCs in the infrastructure - - catalog/vpc/defaults - -# Global settings -settings: - templates: - settings: - # Environment variables passed to datasources when evaluating templates - # https://docs.gomplate.ca/functions/aws/#configuring-aws - # https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html - env: - # AWS profile with permissions to access the S3 bucket - AWS_PROFILE: "" - gomplate: - # Timeout in seconds to execute the datasources - timeout: 5 - # https://docs.gomplate.ca/datasources - datasources: - # `s3` datasource - # https://docs.gomplate.ca/datasources/#using-s3-datasources - s3-tags: - # The `url` uses a `Go` template with the delimiters `${ }`, - # which is processed as first step in the template processing pipeline - url: "s3://mybucket/{{ .vars.stage }}/tags.json" - -# Global Terraform config -terraform: - # Global variables that are used by all Atmos components - vars: - tags: - atmos_component: "{{ .atmos_component }}" - atmos_stack: "{{ .atmos_stack }}" - terraform_component: "{{ .component }}" - terraform_workspace: "{{ .workspace }}" - devops_team: '{{`{{ (datasource "s3-tags").tags.devops_team }}`}}' - billing_team: '{{`{{ (datasource "s3-tags").tags.billing_team }}`}}' - service: '{{`{{ (datasource "s3-tags").tags.service }}`}}' - -# Atmos component configurations -components: - terraform: - vpc/1: - metadata: - component: vpc # Point to the Terraform component in `components/terraform/vpc` folder - inherits: - # Inherit from the `vpc/defaults` base Atmos component, which defines the default - # configuration for all VPCs in the infrastructure. - # The `vpc/defaults` base component is defined in the `catalog/vpc/defaults` - # manifest (which is imported above). - # This inheritance makes the `vpc/1` Atmos component config DRY. - - "vpc/defaults" - vars: - name: "vpc-1" -``` - -When executing an Atmos command like `atmos terraform apply vpc/1 -s plat-ue2-dev`, the above template will be processed -in two evaluation steps: - -- Evaluation 1: - - - `datasources.s3-tags.url` is set to `s3://mybucket/dev/tags.json` - - - the tags that use the `datasource` templates are set to the following: - - ```yaml - devops_team: '{{ (datasource "s3-tags").tags.devops_team }}' - billing_team: '{{ (datasource "s3-tags").tags.billing_team }}' - service: '{{ (datasource "s3-tags").tags.service }}' - ``` - -- Evaluation 2: - - all `s3-tags` datasources get executed, the JSON file `s3://mybucket/dev/tags.json` with the tags - for the `dev` account is downloaded from the S3 bucket, and the tags are parsed and assigned in the - `terraform.vars.tags` section - -After executing the two evaluation steps, the resulting tags for the Atmos component `vpc/1` in the stack `plat-ue2-dev` -would look like this: - -```yaml -atmos_component: vpc/1 -atmos_stack: plat-ue2-dev -terraform_component: vpc -terraform_workspace: plat-ue2-dev-vpc-1 -devops_team: dev_networking -billing_team: billing_net -service: net -``` - -The tags will be added to all the AWS resources provisioned by the `vpc` Terraform component in the `plat-ue2-dev` stack. diff --git a/website/docs/core-concepts/stacks/validation.mdx b/website/docs/core-concepts/stacks/validation.mdx deleted file mode 100644 index 72e663b10..000000000 --- a/website/docs/core-concepts/stacks/validation.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Stack Validation -sidebar_position: 2 -sidebar_label: Validation -description: Validate all Stack configurations and YAML syntax. -id: validation ---- - -import Terminal from '@site/src/components/Terminal' - -To validate all Stack configurations and YAML syntax, execute the `validate stacks` command: - -```shell -atmos validate stacks -``` - -
- -The command checks and validates the following: - -- All YAML manifest files for YAML errors and inconsistencies - -- All imports: if they are configured correctly, have valid data types, and point to existing manifest files - -- Schema: if all sections in all YAML manifest files are correctly configured and have valid data types - -- Misconfiguration and duplication of components in stacks. If the same Atmos component in the same Atmos stack is - defined in more than one stack manifest file, and the component configurations are different, an error message will - be displayed similar to the following: - - - ```console - The Atmos component 'vpc' in the stack 'plat-ue2-dev' is defined in more than one - top-level stack manifest file: orgs/acme/plat/dev/us-east-2-extras, orgs/acme/plat/dev/us-east-2. - - The component configurations in the stack manifests are different. - - To check and compare the component configurations in the stack manifests, run the following commands: - - atmos describe component vpc -s orgs/acme/plat/dev/us-east-2-extras - - atmos describe component vpc -s orgs/acme/plat/dev/us-east-2 - - You can use the '--file' flag to write the results of the above commands to files - (refer to https://atmos.tools/cli/commands/describe/component). - - You can then use the Linux 'diff' command to compare the files line by line and show the differences - (refer to https://man7.org/linux/man-pages/man1/diff.1.html) - - When searching for the component 'vpc' in the stack 'plat-ue2-dev', Atmos can't decide which - stack manifest file to use to get configuration for the component. This is a stack misconfiguration. - - Consider the following solutions to fix the issue: - - - Ensure that the same instance of the Atmos 'vpc' component in the stack 'plat-ue2-dev' - is only defined once (in one YAML stack manifest file) - - - When defining multiple instances of the same component in the stack, - ensure each has a unique name - - - Use multiple-inheritance to combine multiple configurations together - (refer to https://atmos.tools/core-concepts/components/inheritance) - ``` - - -
- -:::tip -For more details, refer to [`atmos validate stacks`](/cli/commands/validate/stacks) CLI command -::: diff --git a/website/docs/core-concepts/template-functions/atmos.Component.mdx b/website/docs/core-concepts/template-functions/atmos.Component.mdx deleted file mode 100644 index 73cc881c8..000000000 --- a/website/docs/core-concepts/template-functions/atmos.Component.mdx +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: atmos.Component -sidebar_position: 1 -sidebar_label: atmos.Component ---- - -import File from '@site/src/components/File' - -The `atmos.Component` template function allows reading any Atmos section or any attribute from a section for an -Atmos component in a stack, and use it in `Go` templates in Atmos component configurations. - -## Usage - -```yaml - {{ (atmos.Component "" "").
. }} -``` - -## Arguments - -- `component` - Atmos component name - -- `stack` - Atmos stack name - -- `section` - Atmos section name. Any section returned by the CLI command - [`atmos describe component`](/cli/commands/describe/component#output) can be used. - A special `outputs` section is also supported to get the outputs (remote state) of Terraform/OpenTofu components. - - :::note - Using the `outputs` section in the `atmos.Component` command is an alternative way to read the outputs (remote state) - of a component in a stack directly in Atmos stack manifests instead of using the `remote-state` - module and configuring Terraform/OpenTofu components to use the `remote-state` module as described in - [Component Remote State](/core-concepts/components/remote-state) - ::: - -
- -- `attribute` - attribute name (field) from the `section`. `attribute` is optional, you can use the `section` itself - if it's a simple type (e.g. `string`). Any number of attributes can be chained using the dot (`.`) notation. - For example, if the first two attributes are maps, you can chain them and get a field from the last map: - - ```yaml - {{ (atmos.Component "" "").
... }} - ``` - -## Specifying Atmos `stack` - -`stack` is the second argument of the `atmos.Component` function, and it can be specified in a few different ways: - - - Hardcoded stack name. Use it if you want to get an output from a component from a different (well-known and static) - stack. For example, you have a `tgw` component in a stack `plat-ue2-dev` that requires the `vpc_id` output from - the `vpc` component from the stack `plat-ue2-prod`: - - ```yaml title="plat-ue2-dev" - components: - terraform: - tgw: - vars: - vpc_id: '{{ (atmos.Component "vpc" "plat-ue2-prod").outputs.vpc_id }}' - ``` - - - Use the `.stack` (or `.atmos_stack`) template identifier to specify the same stack as the current component - (for which the `atmos.Component` function is executed): - - ```yaml - {{ (atmos.Component "" .stack).
. }} - {{ (atmos.Component "" .atmos_stack).
. }} - ``` - - For example, you have a `tgw` component that requires the `vpc_id` output from the `vpc` component in the same stack: - - ```yaml - components: - terraform: - tgw: - vars: - vpc_id: '{{ (atmos.Component "vpc" .stack).outputs.vpc_id }}' - ``` - - - Use the `printf` template function to construct stack names using static strings and dynamic identifiers: - - ```yaml - {{ (atmos.Component "" (printf "%s-%s-%s" .vars.tenant .vars.environment .vars.stage)).
. }} - - {{ (atmos.Component "" (printf "plat-%s-prod" .vars.environment)).
. }} - - {{ (atmos.Component "" (printf "%s-%s-%s" .settings.context.tenant .settings.context.region .settings.context.account)).
. }} - ``` - - For example, you have a `tgw` component deployed in the stack `plat-ue2-dev`. The `tgw` component requires the - `vpc_id` output from the `vpc` component from the same environment (`ue2`) and same stage (`dev`), but from a different - tenant `net` (instead of `plat`): - - ```yaml title="plat-ue2-dev" - components: - terraform: - tgw: - vars: - vpc_id: '{{ (atmos.Component "vpc" (printf "net-%s-%s" .vars.environment .vars.stage)).outputs.vpc_id }}' - ``` - -
- - :::tip Important - By using the `printf "%s-%s-%s"` function, you are constructing stack names using the stack context variables/identifiers. - - For more information on Atmos stack names and how to define them, refer to `stacks.name_pattern` and `stacks.name_template` - sections in [`atmos.yaml` CLI config file](/cli/configuration/#stacks) - ::: - -## Examples - -The following configurations show different ways of using the `atmos.Component` template function to read values from -different Atmos sections directly in Atmos stack manifests, including the outputs of other -(already provisioned) components. - - -```yaml -# Global `settings` section -# It will be added and deep-merged to the `settings` section of all components -settings: - test: true - -components: - terraform: - test: - metadata: - # Point to the Terraform/OpenTofu component - component: "test" - vars: - name: "test" - - test1: - metadata: - # Point to the Terraform/OpenTofu component - component: "test1" - vars: - name: "test1" - - test2: - metadata: - # Point to the Terraform/OpenTofu component - component: "test2" - vars: - name: "test2" - # Use the `atmos.Component` function to get the outputs of the Atmos component `test1` - # The `test1` component must be already provisioned and its outputs stored in the Terraform/OpenTofu state - # Atmos will execute `terraform output` on the `test1` component in the same stack to read its outputs - test1_id: '{{ (atmos.Component "test1" .stack).outputs.test1_id }}' - tags: - # Get the `settings.test` field from the `test` component in the same stack - test: '{{ (atmos.Component "test" .stack).settings.test }}' - # Get the `metadata.component` field from the `test` component in the same stack - test_terraform_component: '{{ (atmos.Component "test" .stack).metadata.component }}' - # Get the `vars.name` field from the `test1` component in the same stack - test1_name: '{{ (atmos.Component "test1" .stack).vars.name }}' -``` - diff --git a/website/docs/core-concepts/template-functions/template-functions.mdx b/website/docs/core-concepts/template-functions/template-functions.mdx deleted file mode 100644 index af68bf2f3..000000000 --- a/website/docs/core-concepts/template-functions/template-functions.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Atmos Template Functions -sidebar_position: 6 -sidebar_label: Template Functions -description: Atmos functions for the Go’s template language. -id: template-functions ---- - -Atmos provides template functions for the `Go` template language. - -These functions can be used in [`Go` templates in Atmos stack manifests](/core-concepts/stacks/templating). - -
- -import DocCardList from "@theme/DocCardList"; - - diff --git a/website/docs/core-concepts/validate/json-schema.mdx b/website/docs/core-concepts/validate/json-schema.mdx new file mode 100644 index 000000000..d06a92416 --- /dev/null +++ b/website/docs/core-concepts/validate/json-schema.mdx @@ -0,0 +1,51 @@ +--- +title: JSON Schema Validation +sidebar_position: 1 +sidebar_label: JSON Schema +description: Use JSON Schema policies to validate Stacks and Component configurations. +id: json-schema +--- +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import EmbedFile from '@site/src/components/EmbedFile' +import Intro from '@site/src/components/Intro' + + +Atmos supports [JSON Schema](https://json-schema.org/) validation, which can validate the schema of configurations such as stacks, workflows, and vendoring manifests. JSON Schema is an industry standard and provides a vocabulary to annotate and validate JSON documents for correctness. + + +## Example + + +```shell +# Validate 'vpc' component using JSON Schema in the 'plat-ue2-prod' stack +atmos validate component vpc -s plat-ue2-prod --schema-path vpc/validate-vpc-component.json --schema-type jsonschema +``` + + +### Configure Component Validation + +In [`atmos.yaml`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml), add the `schemas` +section: + + +```yaml +# Validation schemas (for validating atmos stacks and components) +schemas: + # https://json-schema.org + jsonschema: + # Can also be set using `ATMOS_SCHEMAS_JSONSCHEMA_BASE_PATH` ENV var, or `--schemas-jsonschema-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks/schemas/jsonschema" +``` + + +In the component [manifest](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/catalog/vpc/defaults.yaml), add +the `settings.validation` section: + + + +Add the following JSON Schema in the +file [`stacks/schemas/jsonschema/vpc/validate-vpc-component.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/schemas/jsonschema/vpc/validate-vpc-component.json): + + diff --git a/website/docs/core-concepts/validate/opa.mdx b/website/docs/core-concepts/validate/opa.mdx new file mode 100644 index 000000000..67a6e06bf --- /dev/null +++ b/website/docs/core-concepts/validate/opa.mdx @@ -0,0 +1,169 @@ +--- +title: Open Policy Agent (OPA) Validation +sidebar_position: 2 +sidebar_label: Open Policy Agent (OPA) +description: Use OPA policies to validate Stacks and Component configurations. +id: opa +--- +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import EmbedFile from '@site/src/components/EmbedFile' +import Intro from '@site/src/components/Intro' + + +The [Open Policy Agent](https://www.openpolicyagent.org/docs/latest/) (OPA) is the open-source industry standard for policy-as-code validation. It provides a general-purpose policy engine to unify policy enforcement across your stacks. + + +The OPA (pronounced “oh-pa”) language (Rego) is a high-level declarative language for specifying policy as code. Atmos has native support for the OPA decision-making engine to enforce policies across all the components in your stacks (e.g. for microservice configurations). + +This is powerful stuff: because you can define many policies, it's possible to apply different policies depending on where a component is defined in the stacks. For example, it could validate differently based on environments or teams. + +## Use Cases + +Use Open Policy Agent (OPA) policies to validate Atmos stacks and component configurations. + +* Validate component config (`vars`, `settings`, `backend`, `env`, `overrides` and other sections) using JSON Schema + +* Check if the component config (including relations between different component variables) is correct to allow or deny component provisioning using + OPA/Rego policies + +## Usage + +Atmos `validate component` command supports `--schema-path`, `--schema-type` and `--module-paths` command line arguments. +If the arguments are not provided, Atmos will try to find and use the `settings.validation` section defined in the component's YAML config. + +:::tip + +Refer to [atmos validate component](/cli/commands/validate/component) CLI command for more information + +::: + + +```shell + +# Validate 'vpc' component using OPA policy in the 'plat-ue2-prod' stack +atmos validate component vpc -s plat-ue2-prod --schema-path vpc/validate-vpc-component.rego --schema-type opa + +# Validate 'vpc' component using OPA policy in the 'plat-ue2-dev' stack with additional module paths 'catalog/constants' +atmos validate component vpc -s plat-ue2-dev --schema-path vpc/validate-vpc-component.rego --schema-type opa --module-paths catalog/constants + +# Validate 'vpc' component using OPA policy in the 'plat-ue2-dev' stack with additional module paths 'catalog' +atmos validate component vpc -s plat-ue2-dev --schema-path vpc/validate-vpc-component.rego --schema-type opa --module-paths catalog + +# Validate 'vpc' component in the 'plat-ue2-prod' stack +atmos validate component vpc -s plat-ue2-prod + +# Validate 'vpc' component in the 'plat-ue2-dev' stack +atmos validate component vpc -s plat-ue2-dev + +# Validate 'vpc' component in the 'plat-ue2-dev' stack with a timeout of 15 seconds +atmos validate component vpc -s plat-ue2-dev --timeout 15 +``` + + +### Configure Component Validation + +In [`atmos.yaml`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml), add the `schemas` +section: + + +```yaml +# Validation schemas for OPA for validating atmos stacks and components +schemas: + # https://www.openpolicyagent.org + opa: + # Can also be set using `ATMOS_SCHEMAS_OPA_BASE_PATH` ENV var, or `--schemas-opa-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks/schemas/opa" +``` + + +In the component [manifest](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/catalog/vpc/defaults.yaml), add +the `settings.validation` section: + + + +Add the following Rego package in the file [`stacks/schemas/opa/catalog/constants/constants.rego`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/schemas/opa/catalog/constants/constants.rego): + + + +Add the following OPA policy in the file [`stacks/schemas/opa/vpc/validate-vpc-component.rego`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/schemas/opa/vpc/validate-vpc-component.rego): + + + +### Use One Policy File or Many + +Atmos supports OPA policies for components validation in a single Rego file and in multiple Rego files. + +As shown in the example above, you can define some Rego constants, modules and helper functions in a separate +file `stacks/schemas/opa/catalog/constants/constants.rego`, and then import them into the main policy +file `stacks/schemas/opa/vpc/validate-vpc-component.rego`. + +You also need to specify the `module_paths` attribute in the component's `settings.validation` section. +The `module_paths` attribute is an array of filesystem paths (folders or individual files) to the additional modules for schema validation. +Each path can be an absolute path or a path relative to `schemas.opa.base_path` defined in `atmos.yaml`. +If a folder is specified in `module_paths`, Atmos will recursively process the folder and all its sub-folders and load all Rego files into the OPA +engine. + +This allows you to separate the common OPA modules, constants and helper functions into a catalog of reusable Rego modules, +and to structure your OPA policies to make them DRY. + +## Examples + +### Validate VPC Component in Stacks + +Run the following commands to validate the component in the stacks: + + +```console +Mapping public IPs on launch is not allowed in 'prod'. Set 'map_public_ip_on_launch' variable to 'false' + +exit status 1 +``` + + + +```console +In 'dev', only 2 Availability Zones are allowed +VPC name must be a valid string from 2 to 20 alphanumeric chars + +exit status 1 +``` + + + +### Validate Before Provisioning + +Try to run the following commands to provision the component in the stacks: + + +```bash +atmos terraform apply vpc -s plat-ue2-prod +atmos terraform apply vpc -s plat-ue2-dev +``` + + +Since the OPA validation policies don't pass, Atmos does not allow provisioning the component in the stacks: + + +![atmos-validate-vpc-in-plat-ue2-prod](/img/atmos-validate-infra-vpc-in-tenant1-ue2-dev.png) + + + +![atmos-validate-vpc-in-plat-ue2-dev](/img/atmos-validate-infra-vpc-in-tenant1-ue2-dev.png) + + +### Advanced Policy Examples + + + +:::note + +- If a regex pattern in the 're_match' function contains a backslash to escape special chars (e.g. '\.' or '\-'), + it must be escaped with another backslash when represented as a regular Go string ('\\.', '\\-'). + +- The reason is that backslash is also used to escape special characters in Go strings like newline (\n). + +- If you want to match the backslash character itself, you'll need four slashes. + +::: diff --git a/website/docs/core-concepts/validate/validate.mdx b/website/docs/core-concepts/validate/validate.mdx new file mode 100644 index 000000000..3aac5c71b --- /dev/null +++ b/website/docs/core-concepts/validate/validate.mdx @@ -0,0 +1,96 @@ +--- +title: Validating Stack Configurations +sidebar_position: 5 +sidebar_label: Validate Configurations +description: Use JSON Schema and OPA policies to validate Components. +id: validating +--- +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' + + +Validation is essential for ensuring clean and correct configurations, especially in environments where multiple teams contribute +to the development and deployment processes. Atmos enhances this validation process in two significant ways with [JSON Schema](https://json-schema.org/) and [OPA](https://www.openpolicyagent.org/) policies. + + +## Types of Validation + +Atmos supports two types of native validation. + +### JSON Schema + +Atmos supports [JSON Schema](https://json-schema.org/) validation, which can validate the schema of configurations such as stacks, workflows, and vendoring manifests. +JSON Schema is an industry standard and provides a vocabulary to annotate and validate JSON documents for correctness. + +### Open Policy Agent (OPA) + +The [Open Policy Agent](https://www.openpolicyagent.org/docs/latest/) (OPA, pronounced “oh-pa”) is another open-source industry standard that provides +a general-purpose policy engine to unify policy enforcement across your stacks. The OPA language (Rego) is a high-level declarative language for specifying policy as code. Atmos has native support for the OPA decision-making engine to enforce policies across all the components in your stacks (e.g. for microservice configurations). + +This is powerful stuff: because you can define many policies, it's possible to validate components differently for different environments or teams. + +## Validate Your Configurations + +:::tip + +Refer to [atmos validate component](/cli/commands/validate/component) CLI command for more information + +::: + +### Check Your Stacks + +To validate all Stack configurations and YAML syntax, execute the `validate stacks` command: + +```shell +atmos validate stacks +``` + +The command checks and validates the following: + +- All YAML manifest files for YAML errors and inconsistencies + +- All imports: if they are configured correctly, have valid data types, and point to existing manifest files + +- Schema: if all sections in all YAML manifest files are correctly configured and have valid data types + +- Misconfiguration and duplication of components in stacks. If the same Atmos component in the same Atmos stack is + defined in more than one stack manifest file, and the component configurations are different, an error message will + be displayed similar to the following: + + + ```console + The Atmos component 'vpc' in the stack 'plat-ue2-dev' is defined in more than one + top-level stack manifest file: orgs/acme/plat/dev/us-east-2-extras, orgs/acme/plat/dev/us-east-2. + + The component configurations in the stack manifest are different. + + To check and compare the component configurations in the stack manifests, run the following commands: + - atmos describe component vpc -s orgs/acme/plat/dev/us-east-2-extras + - atmos describe component vpc -s orgs/acme/plat/dev/us-east-2 + + You can use the '--file' flag to write the results of the above commands to files + (refer to https://atmos.tools/cli/commands/describe/component). + + You can then use the Linux 'diff' command to compare the files line by line and show the differences + (refer to https://man7.org/linux/man-pages/man1/diff.1.html) + + When searching for the component 'vpc' in the stack 'plat-ue2-dev', Atmos can't decide which + stack manifest file to use to get the configuration for the component. This is a stack misconfiguration. + + Consider the following solutions to fix the issue: + + - Ensure that the same instance of the Atmos 'vpc' component in the stack 'plat-ue2-dev' + is only defined once (in one YAML stack manifest file) + + - When defining multiple instances of the same component in the stack, + ensure each has a unique name + + - Use multiple-inheritance to combine multiple configurations together + (refer to https://atmos.tools/core-concepts/stacks/inheritance) + ``` + + +:::tip +For more details, refer to [`atmos validate stacks`](/cli/commands/validate/stacks) CLI command +::: diff --git a/website/docs/core-concepts/components/component-vendoring.md b/website/docs/core-concepts/vendor/components-manifest.mdx similarity index 72% rename from website/docs/core-concepts/components/component-vendoring.md rename to website/docs/core-concepts/vendor/components-manifest.mdx index ab62b6579..4b3ac618e 100644 --- a/website/docs/core-concepts/components/component-vendoring.md +++ b/website/docs/core-concepts/vendor/components-manifest.mdx @@ -1,45 +1,18 @@ --- -title: Component Vendoring -sidebar_position: 3 -sidebar_label: Vendoring -description: Use Component Vendoring to make copies of 3rd-party components in your own repo. -id: vendoring +title: Component Manifest +sidebar_position: 2 +sidebar_label: Component Manifest +description: Use Component manifests to make copies of 3rd-party components in your own repo. +id: component-manifest --- +import File from '@site/src/components/File' +import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' -Atmos natively supports the concept of "vendoring", which is making a copy of 3rd-party components or other dependencies in your own repo. -Our implementation is primarily inspired by the excellent tool by VMware Tanzu, called [`vendir`](https://github.com/vmware-tanzu/carvel-vendir). -While Atmos does not call `vendir`, it functions and supports a subset of the configuration that is very similar. - -## Use-cases - -Atmos vendoring streamlines component sharing and version control across an enterprise, enhancing efficiency and collaboration while offering the flexibility to customize and manage multiple versions of dependencies, ensuring best practices in DevOps environments. - -- **Sharing Components Across an Enterprise**: Utilize Atmos vendoring to access a centralized component library, promoting code reuse and - efficiency across teams (or business units) while enabling customization and independent version control post-vendoring. This approach enhances collaboration without sacrificing the flexibility for teams to tailor components to their specific needs or update them at their preferred pace. -- **Managing Multiple Versions of Dependencies:** Use Atmos vendoring to manage multiple versions of remote dependencies, - effectively implementing version pinning through locally controlled artifacts. By configuring a stacks component directory (e.g., `vpc/v1` or `vpc/v2`), vendoring provides maximum flexibility while still aligning with best practices in DevOps environments. -- **Reinforce Immutable Infrastructure**: Employ Atmos vendoring to store immutable infrastructure artifacts, guaranteeing that once a committed, - it remains unaltered throughout its lifecycle, ensuring stability and reliability in deployments. - -## Usage - -Atmos supports two different ways of vendoring components: - -- Using `vendor.yaml` vendoring manifest file containing a list of all dependencies. See [Vendoring](/core-concepts/vendoring/). -- Using `component.yaml` manifest file inside of a component directory. See below. - -The `vendor.yaml` vendoring manifest describes the vendoring config for all components, stacks and other artifacts for the entire infrastructure. -The file is placed into the directory from which the `atmos vendor pull` command is executed. It's the recommended way to describe vendoring -configurations. - -:::tip -Refer to [`Atmos Vendoring`](/core-concepts/vendoring) for more details -::: - -
- -The `component.yaml` vendoring manifest is used to vendor components from remote repositories. -A `component.yaml` file placed into a component's directory is used to describe the vendoring config for one component only. + +Atmos natively supports the concept of "vendoring" individual components by defining a `component.yaml` inside of the component +directory, which is making a copy of 3rd-party components or other dependencies in your own repo. + ## Examples @@ -47,7 +20,7 @@ A `component.yaml` file placed into a component's directory is used to describe After defining the `component.yaml` vendoring manifest, the remote component can be downloaded by running the following command: -```bash +```shell atmos vendor pull -c components/terraform/vpc ``` @@ -104,8 +77,6 @@ spec: filename: introspection.mixin.tf ``` -
- :::warning The `glob` library that Atmos uses to download remote artifacts does not treat the double-star `**` as including sub-folders. @@ -124,12 +95,10 @@ spec: - "**/modules/**" ``` -
- ### Vendoring Modules as Components Any terraform module can also be used as a component, provided that Atmos backend -generation ([`auto_generate_backend_file` is `true`](/cli/configuration/#components)) is enabled. Use this strategy when you want to use the module +generation ([`auto_generate_backend_file` is `true`](/cli/configuration/components)) is enabled. Use this strategy when you want to use the module directly, without needing to wrap it in a component to add additional functionality. This is essentially treating a terraform child module as a root module. diff --git a/website/docs/core-concepts/vendoring/vendoring.mdx b/website/docs/core-concepts/vendor/vendor-manifest.mdx similarity index 58% rename from website/docs/core-concepts/vendoring/vendoring.mdx rename to website/docs/core-concepts/vendor/vendor-manifest.mdx index 5bbc50107..00b916f1e 100644 --- a/website/docs/core-concepts/vendoring/vendoring.mdx +++ b/website/docs/core-concepts/vendor/vendor-manifest.mdx @@ -1,74 +1,46 @@ --- -title: Vendoring +title: Vendor Manifest description: Use Atmos vendoring to make copies of 3rd-party components, stacks, and other artifacts in your own repo. -sidebar_position: 4 -sidebar_label: Vendoring -id: vendoring +sidebar_position: 1 +sidebar_label: Vendor Manifest +id: vendor-manifest --- +import File from '@site/src/components/File' +import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' -Atmos natively supports "vendoring," a practice that involves replicating 3rd-party components, stacks, and artifacts within your own repository. -This feature is particularly beneficial for managing dependencies in software like Terraform, which do not support pulling root modules remotely -by configuration. Vendoring standardizes dependency management, encourages enterprise component reuse, and ensures compliance standards adherence. Furthermore, it allows teams to customize and independently manage their vendored components according to their specific requirements. + +The vendoring configuration is defined in the `vendor.yaml` manifest (vendor config file). The vendoring manifest is used to make copies of 3rd-party components, stacks, and other artifacts in your own repository. + -## Use-cases - -Use vendoring to maintain a local copy of external dependencies critical for managing your infrastructure. Organize the dependencies in the manner that best suits your project's structure. Even create multiple vendor manifests, for example, tailored to specific layers, products, or teams. Then easily -update those dependencies by bumping the versions in the vendor manifest. - -- **Managing Third-Party Dependencies**: Use vendoring in Atmos to efficiently manage and version-control third-party Terraform components, modules or other infrastructure dependencies. This approach is crucial for teams relying on external libraries, root modules, and configurations from sources such as Git repositories. Vendoring these dependencies into your project repository ensures that every team member and CI/CD pipeline works with the same dependency versions, enhancing consistency and reliability across development, testing, and production environments. -- **Sharing Components Across an Enterprise**: Utilize Atmos vendoring to access a centralized component library, promoting code reuse and efficiency across teams while enabling customization and independent version control post-vendoring. This approach enhances collaboration without sacrificing the flexibility for teams to tailor components to their specific needs or update them at their preferred pace. -- **Maintaining Immutable Artifacts for Compliance**: Employ vendoring through Atmos to maintain local, immutable copies of remote dependencies, essential for meeting compliance and regulatory requirements. Keeping a local version-controlled artifact of dependencies ensures that your infrastructure complies with policies that mandate a record of all external components used within the system. This practice supports auditability and traceability, key aspects of maintaining a secure and compliant infrastructure. -- **Overcoming Tooling Limitations with Remote Dependencies**: Utilize Atmos vendoring as a practical solution when your tooling lacks native support for managing remote dependencies. By copying these dependencies into your project repository, you can work around these limitations, ensuring that your infrastructure can still leverage essential external modules and configurations. This approach allows for greater flexibility in infrastructure management, adapting to tooling constraints while still benefiting from the broad ecosystem of available infrastructure modules and configurations. -- **Optimize Boilerplate Code Reusability with Vendoring** Developers can utilize Atmos vendoring together with components to consolidate code by sourcing mixins (e.g. `providers.tf`, `context.tf`, etc) and boilerplate from centralized locations, streamlining development with DRY principles and immutable infrastructure. - -:::tip Pro Tip! Use GitOps -Vendoring plays nicely with GitOps practices, especially when leveraging [GitHub Actions](/integrations/github-actions/). -Use a workflow that automatically updates the vendor manifest and opens a pull request (PR) with all the changes. -This allows you to inspect and precisely assess the impact of any upgrades before merging by reviewing the job summary of the PR. -::: - -## Features - -With Atmos vendoring, you can copy components and other artifacts from the following sources: - -- Copy all files from an [OCI Registry](https://opencontainers.org) into a local folder -- Copy all files from Git, Mercurial, Amazon S3, Google GCP into a local folder -- Copy all files from an HTTP/HTTPS endpoint into a local folder -- Copy a single file from an HTTP/HTTPS endpoint to a local file -- Copy a local file into a local folder (keeping the same file name) -- Copy a local file to a local file with a different file name -- Copy a local folder (all files) into a local folder - -The vendoring configuration is defined in the `vendor.yaml` manifest (vendor config file). +It functions a little bit like the `packages.json` file in Node.js or the `go.mod` file in Go, but for infrastructure code. ## How it works -Atmos searches for the vendoring manifest in the following locations, and uses the first one found: +Atmos searches for the vendoring manifest in the following locations and uses the first one found: - In the directory from which the [`atmos vendor pull`](/cli/commands/vendor/pull) command is executed, usually in the root of the infrastructure repo -- In the directory pointed to by the [`base_path`](/cli/configuration#base-path) setting in the [`atmos.yaml`](/cli/configuration) CLI config file +- In the directory pointed to by the [`base_path`](/cli/configuration/#base-path) setting in the [`atmos.yaml`](/cli/configuration) CLI config file After defining the `vendor.yaml` manifest, all the remote artifacts can be downloaded by running the following command: -```bash +```shell atmos vendor pull ``` To vendor a particular component or other artifact, execute the following command: -```bash +```shell atmos vendor pull -c ``` To vendor components and artifacts tagged with specific tags, execute the following command: -```bash +```shell atmos vendor pull --tags , ``` -
- :::tip Refer to [`atmos vendor pull`](/cli/commands/vendor/pull) CLI command for more details ::: @@ -77,15 +49,8 @@ Refer to [`atmos vendor pull`](/cli/commands/vendor/pull) CLI command for more d To vendor remote artifacts, create a `vendor.yaml` file similar to the example below: -```yaml title="vendor.yaml" -# atmos vendor pull -# atmos vendor pull --component vpc-mixin-1 -# atmos vendor pull -c vpc-mixin-2 -# atmos vendor pull -c vpc-mixin-3 -# atmos vendor pull -c vpc-mixin-4 -# atmos vendor pull --tags test -# atmos vendor pull --tags networking,storage - + +```yaml apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: @@ -181,80 +146,107 @@ spec: tags: - test ``` + -
+With this configuration, it would be possible to run the following commands: + +```shell +# atmos vendor pull +# atmos vendor pull --component vpc-mixin-1 +# atmos vendor pull -c vpc-mixin-2 +# atmos vendor pull -c vpc-mixin-3 +# atmos vendor pull -c vpc-mixin-4 +# atmos vendor pull --tags test +# atmos vendor pull --tags networking,storage +``` + -- The `vendor.yaml` vendoring manifest supports Kubernetes-style YAML config to describe vendoring configuration for components, stacks, +The `vendor.yaml` vendoring manifest supports Kubernetes-style YAML config to describe vendoring configuration for components, stacks, and other artifacts. The file is placed into the directory from which the `atmos vendor pull` command is executed (usually the root of the repo). -- The `source` attribute supports all protocols (local files, Git, Mercurial, HTTP, HTTPS, Amazon S3, Google GCP), and all the URL and - archive formats as described in [go-getter](https://github.com/hashicorp/go-getter), and also the `oci://` scheme to download artifacts from - [OCI registries](https://opencontainers.org). - - **IMPORTANT:** Include the `{{ .Version }}` parameter in your `source` URI to ensure the correct version of the artifact is downloaded. - For example: - - ```yaml - source: "github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref={{.Version}}" +
+ +
`source`
+
+ The `source` attribute supports all protocols (local files, Git, Mercurial, HTTP, HTTPS, Amazon S3, Google GCP), and all the URL and + archive formats as described in [go-getter](https://github.com/hashicorp/go-getter), and also the `oci://` scheme to download artifacts from [OCI registries](https://opencontainers.org). + + **IMPORTANT:** Include the `{{ .Version }}` parameter in your `source` URI to ensure the correct version of the artifact is downloaded. + For example: + + ```yaml + source: "github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref={{.Version}}" + ``` +
+ +
`targets`
+
+ The `targets` in each source supports absolute paths and relative paths (relative to the `vendor.yaml` file). Note: if the `targets` paths + are set as relative, and if the `vendor.yaml` file is detected by Atmos using the `base_path` setting in `atmos.yaml`, the `targets` paths + will be considered relative to the `base_path`. Multiple targets can be specified. +
+ +
`included_paths` and `excluded_paths`
+
+ `included_paths` and `excluded_paths` support [POSIX-style greedy Globs](https://en.wikipedia.org/wiki/Glob_(programming)) for filenames/paths (double-star/globstar `**` is supported as well). +
+ +
`component`
+
+ The `component` attribute in each source is optional. It's used in the `atmos vendor pull -- component ` command if the component is passed in. In this case, Atmos will vendor only the specified component instead of vendoring all the artifacts configured in the `vendor.yaml` manifest. +
+ +
`source` and `targets` templates
+
+ The `source` and `targets` attributes support [Go templates](https://pkg.go.dev/text/template) and [Sprig Functions](http://masterminds.github.io/sprig/). This can be used to templatise the `source` and `targets` paths with the artifact versions specified in the `version` attribute. + + Here's an advanced example showcasing how templates and Sprig functions can be used together with `targets`: + + ```yaml + targets: + # Vendor a component into a major-minor versioned folder like 1.2 + - "components/terraform/infra/vpc-flow-logs-bucket/{{ (first 2 (splitList \".\" .Version)) | join \".\" }}" + ``` +
+ +
`tags`
+
+ The `tags` in each source specifies a list of tags to apply to the component. This allows you to only vendor the components that have the specified tags by executing a command `atmos vendor pull --tags ,` +
+ +
`imports`
+
+ The `imports` section defines the additional vendoring manifests that are merged into the main manifest. Hierarchical imports are supported at many levels (one vendoring manifest can import another, which in turn can import other manifests, etc.). Atmos processes all imports and all sources in the imported manifests in the order they are defined. + + :::note + The imported file extensions are optional. Imports that do not include file extensions will default to the `.yaml` extension. + ::: + + + ```yaml title="vendor.yaml" + spec: + sources: + - component: "vpc-flow-logs-bucket" + source: "github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref={{.Version}}" + version: "1.323.0" + targets: + - "components/terraform/vpc-flow-logs-bucket" + included_paths: + - "**/**" + # If the component's folder has the `modules` sub-folder, it needs to be explicitly defined + - "**/modules/**" ``` + -- The `targets` in each source supports absolute paths and relative paths (relative to the `vendor.yaml` file). Note: if the `targets` paths - are set as relative, and if the `vendor.yaml` file is detected by Atmos using the `base_path` setting in `atmos.yaml`, the `targets` paths - will be considered relative to the `base_path`. Multiple targets can be specified. - -- `included_paths` and `excluded_paths` support [POSIX-style greedy Globs](https://en.wikipedia.org/wiki/Glob_(programming)) for filenames/paths - (double-star/globstar `**` is supported as well). - -- The `component` attribute in each source is optional. It's used in the `atmos vendor pull -- component ` command if the component is - passed in. In this case, Atmos will vendor only the specified component instead of vendoring all the artifacts configured in the `vendor.yaml` - manifest. - -- The `source` and `targets` attributes support [Go templates](https://pkg.go.dev/text/template) - and [Sprig Functions](http://masterminds.github.io/sprig/). This can be used to templatise the `source` and `targets` paths with the artifact - versions specified in the `version` attribute. - - Here's an advanced example showcasing how templates and Sprig functions can be used together with `targets`: - - ```yaml - targets: - # Vendor a component into a major-minor versioned folder like 1.2 - - "components/terraform/infra/vpc-flow-logs-bucket/{{ (first 2 (splitList \".\" .Version)) | join \".\" }}" - ``` + :::warning -- The `tags` in each source specifies a list of tags to apply to the component. This allows you to only vendor the components that have the - specified tags by executing a command `atmos vendor pull --tags ,` + The `glob` library that Atmos uses to download remote artifacts does not treat the double-star `**` as including sub-folders. + If the component's folder has sub-folders, and you need to vendor them, they have to be explicitly defined as in the following example. -- The `imports` section defines the additional vendoring manifests that are merged into the main manifest. Hierarchical imports are supported - at many levels (one vendoring manifest can import another, which in turn can import other manifests, etc.). Atmos processes all imports and all - sources in the imported manifests in the order they are defined. + ::: +
+
- **NOTE:** The imported file extensions are optional. If an import is defined without an extension, the `.yaml` extension is assumed and used - by default. - -
- -:::warning - -The `glob` library that Atmos uses to download remote artifacts does not treat the double-star `**` as including sub-folders. -If the component's folder has sub-folders, and you need to vendor them, they have to be explicitly defined as in the following example. - -::: - -```yaml title="vendor.yaml" -spec: - sources: - - component: "vpc-flow-logs-bucket" - source: "github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref={{.Version}}" - version: "1.323.0" - targets: - - "components/terraform/vpc-flow-logs-bucket" - included_paths: - - "**/**" - # If the component's folder has the `modules` sub-folder, it needs to be explicitly defined - - "**/modules/**" -``` - -
## Hierarchical Imports in Vendoring Manifests @@ -274,7 +266,8 @@ imports: Hierarchical imports are supported at many levels. For example, consider the following vendoring configurations: -```yaml title="vendor.yaml" + +```yaml apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: @@ -297,8 +290,11 @@ spec: targets: - "components/terraform/infra/vpc-flow-logs-bucket/{{.Version}}" ``` + -```yaml title="vendor/vendor2.yaml" + + +```yaml apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: @@ -315,8 +311,10 @@ spec: targets: - "components/terraform/infra/my-vpc1" ``` + -```yaml title="vendor/vendor4.yaml" + +```yaml apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: @@ -333,6 +331,7 @@ spec: targets: - "components/terraform/infra/my-vpc4" ``` + When you execute the `atmos vendor pull` command, Atmos processes the import chain and the sources in the imported manifests in the order they are defined: @@ -344,9 +343,8 @@ are defined: - Etc. - Then all the sources from all the imported manifests are processed and the artifacts are downloaded into the paths defined by the `targets` -
- -```bash + +```shell > atmos vendor pull Processing vendor config file 'vendor.yaml' @@ -358,6 +356,7 @@ Pulling sources for the component 'my-vpc2' from 'github.com/cloudposse/terrafor Pulling sources for the component 'vpc' from 'public.ecr.aws/cloudposse/components/terraform/stable/aws/vpc:latest' into 'components/terraform/infra/vpc3' Pulling sources for the component 'vpc-flow-logs-bucket' from 'github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref=1.323.0' into 'components/terraform/infra/vpc-flow-logs-bucket/1.323.0' ``` + ## Vendoring from OCI Registries @@ -377,6 +376,7 @@ source: "oci://public.ecr.aws/cloudposse/components/terraform/stable/aws/vpc:lat The schema of a `vendor.yaml` manifest is as follows: + ```yaml # This is an example of how to download a Terraform component from an OCI registry (https://opencontainers.org), e.g. AWS Public ECR @@ -398,9 +398,12 @@ spec: - "**/*.md" excluded_paths: [] ``` + To vendor the `vpc` component, execute the following command: + ```bash atmos vendor pull -c vpc ``` + diff --git a/website/docs/core-concepts/vendor/vendor.mdx b/website/docs/core-concepts/vendor/vendor.mdx new file mode 100644 index 000000000..20d51d8d1 --- /dev/null +++ b/website/docs/core-concepts/vendor/vendor.mdx @@ -0,0 +1,77 @@ +--- +title: Vendoring +description: Use Atmos vendoring to make copies of 3rd-party components, stacks, and other artifacts in your own repo. +sidebar_position: 7 +sidebar_label: Vendor Dependencies +id: vendor +--- +import File from '@site/src/components/File' +import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' + + +Atmos natively supports "vendoring," a practice that involves replicating 3rd-party components, stacks, and artifacts within your own repository. This feature is particularly beneficial for managing dependencies in software like Terraform, which do not support pulling root modules remotely by configuration. + + +Vendoring standardizes dependency management, encourages enterprise component reuse, and ensures compliance standards adherence. Furthermore, it allows teams to customize and independently manage their vendored components according to their specific requirements. + +## Use-cases + +Use vendoring to maintain a local copy of external dependencies critical for managing your infrastructure. Organize the dependencies in the manner that best suits your project's structure. Even create multiple vendor manifests, for example, tailored to specific layers, products, or teams. Then easily +update those dependencies by bumping the versions in the vendor manifest. + +- **Managing Third-Party Dependencies**: Use vendoring in Atmos to efficiently manage and version-control third-party Terraform components, modules or other infrastructure dependencies. This approach is crucial for teams relying on external libraries, root modules, and configurations from sources such as Git repositories. Vendoring these dependencies into your project repository ensures that every team member and CI/CD pipeline works with the same dependency versions, enhancing consistency and reliability across development, testing, and production environments. +- **Sharing Components Across an Enterprise**: Utilize Atmos vendoring to access a centralized component library, promoting code reuse and efficiency across teams while enabling customization and independent version control post-vendoring. This approach enhances collaboration without sacrificing the flexibility for teams to tailor components to their specific needs or update them at their preferred pace. +- **Maintaining Immutable Artifacts for Compliance**: Employ vendoring through Atmos to maintain local, immutable copies of remote dependencies, essential for meeting compliance and regulatory requirements. Keeping a local version-controlled artifact of dependencies ensures that your infrastructure complies with policies that mandate a record of all external components used within the system. This practice supports auditability and traceability, key aspects of maintaining a secure and compliant infrastructure. +- **Overcoming Tooling Limitations with Remote Dependencies**: Utilize Atmos vendoring as a practical solution when your tooling lacks native support for managing remote dependencies. By copying these dependencies into your project repository, you can work around these limitations, ensuring that your infrastructure can still leverage essential external modules and configurations. This approach allows for greater flexibility in infrastructure management, adapting to tooling constraints while still benefiting from the broad ecosystem of available infrastructure modules and configurations. +- **Optimize Boilerplate Code Reusability with Vendoring** Developers can utilize Atmos vendoring together with components to consolidate code by sourcing mixins (e.g. `providers.tf`, `context.tf`, etc) and boilerplate from centralized locations, streamlining development with DRY principles and immutable infrastructure. + +:::tip Pro Tip! Use GitOps +Vendoring plays nicely with GitOps practices, especially when leveraging [GitHub Actions](/integrations/github-actions/). +Use a workflow that automatically updates the vendor manifest and opens a pull request (PR) with all the changes. +This allows you to inspect and precisely assess the impact of any upgrades before merging by reviewing the job summary of the PR. +::: + +## Features + +With Atmos vendoring, you can copy components and other artifacts from the following sources: + +- Copy all files from an [OCI Registry](https://opencontainers.org) into a local folder +- Copy all files from Git, Mercurial, Amazon S3, Google GCP into a local folder +- Copy all files from an HTTP/HTTPS endpoint into a local folder +- Copy a single file from an HTTP/HTTPS endpoint to a local file +- Copy a local file into a local folder (keeping the same file name) +- Copy a local file to a local file with a different file name +- Copy a local folder (all files) into a local folder + +Our implementation is primarily inspired by the excellent tool by VMware Tanzu, called [`vendir`](https://github.com/vmware-tanzu/carvel-vendir). +While Atmos does not call `vendir`, it functions and supports a subset of the configuration that is very similar. + +## Use-cases + +Atmos vendoring streamlines component sharing and version control across an enterprise, enhancing efficiency and collaboration while offering the flexibility to customize and manage multiple versions of dependencies, ensuring best practices in DevOps environments. + +- **Sharing Components Across an Enterprise**: Utilize Atmos vendoring to access a centralized component library, promoting code reuse and + efficiency across teams (or business units) while enabling customization and independent version control post-vendoring. This approach enhances collaboration without sacrificing the flexibility for teams to tailor components to their specific needs or update them at their preferred pace. +- **Managing Multiple Versions of Dependencies:** Use Atmos vendoring to manage multiple versions of remote dependencies, + effectively implementing version pinning through locally controlled artifacts. By configuring a stacks component directory (e.g., `vpc/v1` or `vpc/v2`), vendoring provides maximum flexibility while still aligning with best practices in DevOps environments. +- **Reinforce Immutable Infrastructure**: Employ Atmos vendoring to store immutable infrastructure artifacts, guaranteeing that once a committed, + it remains unaltered throughout its lifecycle, ensuring stability and reliability in deployments. + +## Types of Vendoring + +Atmos supports two different ways of vendoring components: + +- [**Vendor Manifest**](/core-concepts/vendor/vendor-manifest) Using `vendor.yaml` vendoring manifest file containing a list of all dependencies. +- [**Component Manifest**](/core-concepts/vendor/vendor-manifest) Using `component.yaml` manifest file inside of a component directory. See below. + +The `vendor.yaml` vendoring manifest describes the vendoring config for all components, stacks and other artifacts for the entire infrastructure. +The file is placed into the directory from which the `atmos vendor pull` command is executed. It's the recommended way to describe vendoring +configurations. + +:::tip +Refer to [`Atmos Vendoring`](/core-concepts/vendor) for more details +::: + +The `component.yaml` vendoring manifest is used to vendor components from remote repositories. +A `component.yaml` file placed into a component's directory is used to describe the vendoring config for one component only. diff --git a/website/docs/core-concepts/workflows/workflows.mdx b/website/docs/core-concepts/workflows/workflows.mdx index 6123dbbf8..72a8b4910 100644 --- a/website/docs/core-concepts/workflows/workflows.mdx +++ b/website/docs/core-concepts/workflows/workflows.mdx @@ -1,20 +1,18 @@ --- title: Workflows -sidebar_position: 3 -sidebar_label: Workflows +sidebar_position: 7 +sidebar_label: Automate Workflows --- import File from '@site/src/components/File' import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' + Workflows are a way of combining multiple commands into one executable unit of work. + -
- -:::note -You can use [Atmos Custom Commands](/core-concepts/custom-commands) in Atmos Workflows, and Atmos Workflows -in [Atmos Custom Commands](/core-concepts/custom-commands) -::: +You can use [Atmos Custom Commands](/core-concepts/custom-commands) in Atmos Workflows, and Atmos Workflows in [Atmos Custom Commands](/core-concepts/custom-commands) ## Simple Example @@ -31,16 +29,12 @@ workflows: - command: terraform apply eks/alb-controller -auto-approve ``` -
- :::note The workflow name can be anything you want, and the workflows can also be parameterized. ::: -
- If you define this workflow in the file `workflow1.yaml`, it can we executed like this to provision the `vpc`, `eks/cluster` and `eks/alb-controller` [Atmos Components](/core-concepts/components) into the `tenant1-ue2-dev` [Atmos Stack](/core-concepts/stacks): @@ -49,8 +43,6 @@ the `tenant1-ue2-dev` [Atmos Stack](/core-concepts/stacks): atmos workflow eks-up -f workflow1 --stack tenant1-ue2-dev ``` -
- :::tip Refer to [`atmos workflow`](/cli/commands/workflow) for the complete description of the CLI command @@ -72,9 +64,9 @@ In `atmos.yaml` CLI config file, add the following sections related to Atmos wor # Base path for components, stacks and workflows configurations. # Can also be set using 'ATMOS_BASE_PATH' ENV var, or '--base-path' command-line argument. # Supports both absolute and relative paths. -# If not provided or is an empty string, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' +# If not provided or is an empty string, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' # and 'workflows.base_path' are independent settings (supporting both absolute and relative paths). -# If 'base_path' is provided, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' +# If 'base_path' is provided, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' # and 'workflows.base_path' are considered paths relative to 'base_path'. base_path: "" @@ -86,15 +78,19 @@ workflows: where: -- `base_path` - the base path for components, stacks and workflows configurations +
+
`base_path`
+
The base path for components, stacks and workflows configurations
-- `workflows.base_path` - the base path to Atmos workflow files +
`workflows.base_path`
+
The base path to Atmos workflow files
+
-### Create Workflow Files and Define Workflows +### Create Workflow Files In `atmos.yaml`, we set `workflows.base_path` to `stacks/workflows`. The folder is relative to the root of the repository. -Refer to [networking.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/stacks/workflows/networking.yaml) for an example. +Refer to [networking.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/stacks/workflows/networking.yaml) for an example. We put the workflow files into the folder. The workflow file names can be anything you want, but we recommend naming them according to the functions they perform, e.g. create separate workflow files per environment, account, team, or service. @@ -108,6 +104,8 @@ account. You can segregate the workflow files even further, e.g. per account and service. For example, in the workflow file `stacks/workflows/workflows-dev-eks.yaml` you can define all EKS-related workflows for the `dev` account. +### Use Workflow Schema + Workflow files must confirm to the following schema: ```yaml @@ -143,32 +141,30 @@ Each workflow definition must confirm to the following schema: type: shell # required for the steps of type `shell` ``` -where: - -- `description` - the workflow description +### Schema Definitions -- `stack` - workflow-level Atmos stack (optional). If specified, all workflow steps of type `atmos` will be executed for this Atmos stack. It can be - overridden in each step or on the command line by using the `--stack` flag (`-s` for shorthand) +
+
`description`
+
The workflow description
-- `steps` - a list of workflow steps which are executed sequentially in the order they are specified +
`stack`
+
Workflow-level Atmos stack (optional). If specified, all workflow steps of type `atmos` will be executed for this Atmos stack. It can be overridden in each step or on the command line by using the `--stack` flag (`-s` for shorthand)
-Each step is configured using the following attributes: +
`steps`
+
A list of workflow steps which are executed sequentially in the order they are specified
-- `command` - the command to execute. Can be either an Atmos [CLI command](/cli/commands) (without the `atmos` binary name in front of it, - for example `command: terraform apply vpc`), or a shell script. The type of the command is specified by the `type` attribute +
`command`
+
The command to execute. Can be either an Atmos [CLI command](/cli/commands) (without the `atmos` binary name in front of it, for example `command: terraform apply vpc`), or a shell script. The type of the command is specified by the `type` attribute
-- `name` - step name (optional). It's used to find the first step from which to start executing the workflow when the command-line flag `--from-step` - is specified. If the `name` is omitted, a friendly name will be generated for you consisting of a prefix of `step` and followed by the index of the - step (the index starts with 1, so the first generated step name would be `step1`). +
`name`
+
Step name (optional). It's used to find the first step from which to start executing the workflow when the command-line flag `--from-step` is specified. If the `name` is omitted, a friendly name will be generated for you consisting of a prefix of `step` and followed by the index of the step (the index starts with 1, so the first generated step name would be `step1`).
-- `type` - the type of the command. Can be either `atmos` or `shell`. Type `atmos` is implicit, you don't have to specify it if the `command` - is an Atmos [CLI command](/cli/commands). Type `shell` is required if the command is a shell script. When executing a step of type `atmos`, - Atmos prepends the `atmos` binary name to the provided command before executing it +
`type`
+
The type of the command. Can be either `atmos` or `shell`. Type `atmos` is implicit, you don't have to specify it if the `command` is an Atmos [CLI command](/cli/commands). Type `shell` is required if the command is a shell script. When executing a step of type `atmos`, Atmos prepends the `atmos` binary name to the provided command before executing it
-- `stack` - step-level Atmos stack (optional). If specified, the `command` will be executed for this Atmos stack. It overrides the - workflow-level `stack` attribute, and can itself be overridden on the command line by using the `--stack` flag (`-s` for shorthand) - -
+
`stack`
+
Step-level Atmos stack (optional). If specified, the `command` will be executed for this Atmos stack. It overrides the workflow-level `stack` attribute, and can itself be overridden on the command line by using the `--stack` flag (`-s` for shorthand)
+
:::note @@ -269,7 +265,7 @@ workflows: terraform-plan-all-test-components: description: | Run 'terraform plan' on 'test/test-component' and all its derived components. - The stack must be provided on the command line: + The stack must be provided on the command line: `atmos workflow terraform-plan-all-test-components -f workflow1 -s ` steps: # Inline scripts are also supported @@ -293,8 +289,6 @@ To run this workflow for the `tenant1-ue2-dev` stack, execute the following comm atmos workflow terraform-plan-all-test-components -f workflow1 -s tenant1-ue2-dev ``` -
- The following workflow executes `terraform plan` on `test/test-component-override-2` component in all stacks. In this case, the stack is specified inline for each workflow command. @@ -319,8 +313,6 @@ To run this workflow, execute the following command: atmos workflow terraform-plan-test-component-override-2-all-stacks -f workflow1 ``` -
- The following workflow is similar to the above, but the stack for each command is specified in the step-level `stack` attribute. ```yaml title=stacks/workflows/workflow1.yaml @@ -348,17 +340,17 @@ To run this workflow, execute the following command: atmos workflow terraform-plan-test-component-override-3-all-stacks -f workflow1 ``` -## Atmos Stacks in Workflows +## Working with Atmos Stacks in Workflows -Atmos stack for the workflow commands of type `atmos` can be specified in four different ways: +The Atmos stack used by the workflow commands of type `atmos` can be specified in four different ways: -- Inline in the command itself +### Inline in the command itself ```yaml steps: - command: terraform plan test/test-component-override-2 -s tenant1-ue2-dev ``` -- In the workflow-level `stack` attribute +### In the workflow-level `stack` attribute ```yaml workflows: my-workflow: @@ -367,19 +359,19 @@ Atmos stack for the workflow commands of type `atmos` can be specified in four d - command: terraform plan test/test-component ``` -- In the step-level `stack` attribute +### In the step-level `stack` attribute ```yaml steps: - command: terraform plan test/test-component stack: tenant1-ue2-dev ``` -- On the command line +### On the command line ```console atmos workflow my-workflow -f workflow1 -s tenant1-ue2-dev ``` -
+### Stack Presedence The stack defined inline in the command itself has the lowest priority, it can and will be overridden by any other stack definition. The step-level stack will override the workflow-level stack. The command line `--stack` option will override all other stacks defined in the workflow diff --git a/website/docs/design-patterns/abstract-component.mdx b/website/docs/design-patterns/abstract-component.mdx index 9366c25e9..3c3ffda81 100644 --- a/website/docs/design-patterns/abstract-component.mdx +++ b/website/docs/design-patterns/abstract-component.mdx @@ -1,22 +1,29 @@ --- -title: Abstract Component Atmos Design Pattern +title: Abstract Component sidebar_position: 9 sidebar_label: Abstract Component description: Abstract Component Atmos Design Pattern --- import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import PillBox from '@site/src/components/PillBox' -# Abstract Component +Atmos Design Pattern -The **Abstract Component** Design Pattern describes the mechanism of deriving Atmos components from one or more **abstract** base components ( -blueprints), allowing reusing the base components' configurations and prohibiting the abstract base component from being provisioned. + +The **Abstract Component** Design Pattern describes the mechanism of deriving Atmos components from one or more **abstract** base components (blueprints), allowing reusing the base components' configurations and prohibiting the abstract base component from being provisioned. + Atmos supports two types of components: -- `real` - is a ["concrete"](https://en.wikipedia.org/wiki/Concrete_class) component instance that can be provisioned +
+
`real`
+
is a ["concrete"](https://en.wikipedia.org/wiki/Concrete_class) component instance that can be provisioned
-- `abstract` - a component configuration, which cannot be instantiated directly. The concept is borrowed - from ["abstract base classes"](https://en.wikipedia.org/wiki/Abstract_type) of Object-Oriented Programming +
`abstract`
+
a component configuration, which cannot be instantiated directly. The concept is borrowed + from ["abstract base classes"](https://en.wikipedia.org/wiki/Abstract_type) of Object-Oriented Programming
+
The type of component is expressed in the `metadata.type` parameter of a given component configuration. @@ -193,8 +200,6 @@ components: ipv4_primary_cidr_block: 10.9.0.0/18 ``` -
- To provision the `vpc` component into the `plat-ue2-prod` top-level stack, execute the following command: ```shell @@ -211,7 +216,7 @@ atmos terraform apply vpc/defaults -s plat-ue2-prod the following error will be thrown: ```console -abstract component 'vpc/defaults' cannot be provisioned since it's explicitly prohibited from +abstract component 'vpc/defaults' cannot be provisioned since it's explicitly prohibited from being deployed by 'metadata.type: abstract' attribute ``` @@ -227,5 +232,5 @@ being deployed by 'metadata.type: abstract' attribute ## References -- [Component-Oriented Programming](/core-concepts/components/component-oriented-programming) -- [Component Inheritance](/core-concepts/components/inheritance) +- [Component-Oriented Programming](/core-concepts/stacks/inheritance) +- [Component Inheritance](/core-concepts/stacks/inheritance) diff --git a/website/docs/design-patterns/component-catalog-template.mdx b/website/docs/design-patterns/component-catalog-template.mdx index f7ce90500..9ee07856a 100644 --- a/website/docs/design-patterns/component-catalog-template.mdx +++ b/website/docs/design-patterns/component-catalog-template.mdx @@ -1,16 +1,18 @@ --- -title: Component Catalog Template Atmos Design Pattern +title: Component Catalog Template sidebar_position: 7 sidebar_label: Component Catalog Template description: Component Catalog Template Atmos Design Pattern --- import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import PillBox from '@site/src/components/PillBox' -# Component Catalog Template +Atmos Design Pattern -The **Component Catalog Template** Design Pattern is used when you have an unbounded number of a component's instances provisioned in one environment -(the same organization, OU/tenant, account and region). New instances with different settings can be configured and provisioned anytime. The old -instances must be kept unchanged and never destroyed. + +The **Component Catalog Template** Design Pattern is used when you have an unbounded number of a component's instances provisioned in one environment (the same organization, OU/tenant, account and region). New instances with different settings can be configured and provisioned anytime. The old instances must be kept unchanged and never destroyed. + This is achieved by using [`Go` Templates in Imports](/core-concepts/stacks/imports#go-templates-in-imports) and [Hierarchical Imports with Context](/core-concepts/stacks/imports#hierarchical-imports-with-context). diff --git a/website/docs/design-patterns/component-catalog-with-mixins.mdx b/website/docs/design-patterns/component-catalog-with-mixins.mdx index 72e726eca..87674a6e0 100644 --- a/website/docs/design-patterns/component-catalog-with-mixins.mdx +++ b/website/docs/design-patterns/component-catalog-with-mixins.mdx @@ -1,16 +1,18 @@ --- -title: Component Catalog with Mixins Atmos Design Pattern +title: Component Catalog with Mixins sidebar_position: 6 sidebar_label: Component Catalog with Mixins description: Component Catalog with Mixins Atmos Design Pattern --- import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import PillBox from '@site/src/components/PillBox' -# Component Catalog with Mixins +Atmos Design Pattern -The **Component Catalog with Mixins** Design Pattern is a variation of the [Component Catalog](/design-patterns/component-catalog) pattern, with the -difference being that we first create parts of a component's configuration related to different environments (e.g. in `mixins` folder), then -assemble environment-specific manifests from the parts, and then import the environment-specific manifests themselves into the top-level stacks. + +The **Component Catalog with Mixins** Design Pattern is a variation of the [Component Catalog](/design-patterns/component-catalog) pattern, with the difference being that we first create parts of a component's configuration related to different environments (e.g. in `mixins` folder), then assemble environment-specific manifests from the parts, and then import the environment-specific manifests themselves into the top-level stacks. + It's similar to how [Helm](https://helm.sh/) and [helmfile](https://helmfile.readthedocs.io/en/latest/#environment) handle environments. @@ -61,7 +63,6 @@ The **Component Catalog with Mixins** Design Pattern prescribes the following: | `stacks/catalog/vpc/mixins/org1.yaml` | Component manifest with settings for `org1` organization | | `stacks/catalog/vpc/mixins/org2.yaml` | Component manifest with settings for `org2` organization | -
:::note Having the environment-specific manifests in the component's catalog makes the most sense for multi-Org, multi-OU and/or @@ -69,7 +70,6 @@ The **Component Catalog with Mixins** Design Pattern prescribes the following: into multiple Org/OU top-level stack manifests. ::: -
- In the component's catalog folder, add manifests for specific environments by assembling the corresponding mixins together (using imports). For example: @@ -89,7 +89,6 @@ The **Component Catalog with Mixins** Design Pattern prescribes the following: | `stacks/catalog/vpc/org2-plat-uw2-prod.yaml` | Manifest for the `org2` organization, `plat` tenant, `uw2` region, `prod` account | | `stacks/catalog/vpc/org2-plat-uw2-staging.yaml` | Manifest for the `org2` organization, `plat` tenant, `uw2` region, `staging` account | -
- Import the environment manifests into the top-level stacks. For example: @@ -438,4 +437,4 @@ using the following patterns: ## References - [Catalogs](/core-concepts/stacks/catalogs) -- [Mixins](/core-concepts/stacks/mixins) +- [Mixins](/core-concepts/stacks/inheritance/mixins) diff --git a/website/docs/design-patterns/component-catalog.mdx b/website/docs/design-patterns/component-catalog.mdx index 783e217ab..00ffeabc4 100644 --- a/website/docs/design-patterns/component-catalog.mdx +++ b/website/docs/design-patterns/component-catalog.mdx @@ -1,13 +1,17 @@ --- -title: Component Catalog Atmos Design Pattern +title: Component Catalog sidebar_position: 5 sidebar_label: Component Catalog description: Component Catalog Atmos Design Pattern --- import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import PillBox from '@site/src/components/PillBox' -# Component Catalog - +Atmos Design Pattern + +The **Component Catalog** is a powerful pattern for organizing and managing the configuration of components across multiple stacks, enabling easy reuse of default configurations. Use this pattern to maintain a DRY (Don't Repeat Yourself) configuration approach, ensuring consistent and efficient deployments across various environments and regions. + ## Use-cases @@ -373,4 +377,4 @@ patterns: ## References - [Catalogs](/core-concepts/stacks/catalogs) -- [Mixins](/core-concepts/stacks/mixins) +- [Mixins](/core-concepts/stacks/inheritance/mixins) diff --git a/website/docs/design-patterns/component-inheritance.mdx b/website/docs/design-patterns/component-inheritance.mdx index b1eb29636..a47613227 100644 --- a/website/docs/design-patterns/component-inheritance.mdx +++ b/website/docs/design-patterns/component-inheritance.mdx @@ -1,22 +1,24 @@ --- -title: Component Inheritance Atmos Design Pattern +title: Component Inheritance sidebar_position: 8 sidebar_label: Component Inheritance description: Component Inheritance Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Component Inheritance - -The **Component Inheritance** Design Pattern describes the mechanism of deriving Atmos components from one or more base components, allowing reusing -the base components' configurations. +Atmos Design Pattern + +The **Component Inheritance** Design Pattern describes the mechanism of deriving Atmos components from one or more base components, allowing reusing the base components' configurations. + In Atmos, **Component Inheritance** is the mechanism of deriving a component from one or more base components, inheriting all the properties of the base component(s) and overriding only some fields specific to the derived component. The derived component acquires all the properties of the base component(s), allowing creating very DRY configurations that are built upon existing components. :::note -Atmos supports many different types on component inheritance. Refer to [Component Inheritance](/core-concepts/components/inheritance) for +Atmos supports many different types on component inheritance. Refer to [Component Inheritance](/core-concepts/stacks/inheritance) for more details. ::: @@ -35,7 +37,7 @@ The **Component Inheritance** pattern provides the following benefits: - Enables very DRY, consistent, and reusable configurations built upon existing components - Any Atmos component can serve as a building block for other Atmos components - + ## Example @@ -172,8 +174,6 @@ components: ipv4_primary_cidr_block: 10.9.0.0/18 ``` -
- ## Related Patterns - [Abstract Component](/design-patterns/abstract-component) @@ -186,5 +186,5 @@ components: ## References -- [Component-Oriented Programming](/core-concepts/components/component-oriented-programming) -- [Component Inheritance](/core-concepts/components/inheritance) +- [Component-Oriented Programming](/core-concepts/stacks/inheritance) +- [Component Inheritance](/core-concepts/stacks/inheritance) diff --git a/website/docs/design-patterns/component-overrides.mdx b/website/docs/design-patterns/component-overrides.mdx index b6798a3c8..c403e1129 100644 --- a/website/docs/design-patterns/component-overrides.mdx +++ b/website/docs/design-patterns/component-overrides.mdx @@ -1,22 +1,21 @@ --- -title: Component Overrides Atmos Design Pattern +title: Component Overrides sidebar_position: 14 sidebar_label: Component Overrides description: Component Overrides Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Component Overrides +Atmos Design Pattern -The **Component Overrides** Design Pattern describes the mechanism of modifying and overriding the configuration and behavior of groups of Atmos -components in the current scope. - -This is achieved by using the `overrides` section in Atmos stack manifests. - -
+ +The **Component Overrides** Design Pattern describes the mechanism of modifying and overriding the configuration and behavior of groups of Atmos components in the current scope. This is achieved by using the `overrides` section in Atmos stack manifests. + :::tip -Refer to [Component Overrides](/core-concepts/components/overrides) for more information on the `overrides` section +Refer to [Component Overrides](/core-concepts/stacks/overrides) for more information on the `overrides` section ::: ## Use-cases @@ -50,8 +49,6 @@ In this example, we'll use the structure described by the [Layered Stack Configu Design Pattern. ::: -
- In the following structure, we have many different Terraform components (Terraform root modules) in the `components/terraform` folder. In the `stacks/catalog` folder, we define the defaults for each component using the [Component Catalog](/design-patterns/component-catalog) Atmos @@ -73,8 +70,6 @@ components in the layer will get the `Layer` and `Team` tags). Finally, we import all the layer manifests into the top-level stacks. -
- ```console    │   # Centralized stacks configuration (stack manifests)    ├── stacks @@ -340,7 +335,7 @@ Import the required layers into the `stacks/orgs/acme/plat/dev/us-east-2.yaml` t ```yaml title="stacks/orgs/acme/plat/dev/us-east-2.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -359,7 +354,7 @@ Import the required layers into the `stacks/orgs/acme/plat/dev/us-west-2.yaml` t ```yaml title="stacks/orgs/acme/plat/dev/us-west-2.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-west-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-west-2` manifests # define the top-level Atmos stack `plat-uw2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-west-2 @@ -378,7 +373,7 @@ Import the required layers into the `stacks/orgs/acme/plat/prod/us-east-2.yaml` ```yaml title="stacks/orgs/acme/plat/prod/us-east-2.yaml" import: - # The `orgs/acme/plat/prod/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/prod/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-prod` - orgs/acme/plat/prod/_defaults - mixins/region/us-east-2 @@ -393,8 +388,6 @@ import: - layers/eks ``` -
- Similarly, import the required layers into the other top-level stacks for the other organizations, OUs/tenants, accounts and regions. Make sure to import only the layers that define the component that need to be provisioned in the stacks. @@ -412,4 +405,4 @@ corresponding layers. ## References - [Catalogs](/core-concepts/stacks/catalogs) -- [Mixins](/core-concepts/stacks/mixins) +- [Mixins](/core-concepts/stacks/inheritance/mixins) diff --git a/website/docs/design-patterns/design-patterns.mdx b/website/docs/design-patterns/design-patterns.mdx index ce9d2f284..2700a0874 100644 --- a/website/docs/design-patterns/design-patterns.mdx +++ b/website/docs/design-patterns/design-patterns.mdx @@ -1,68 +1,57 @@ --- title: Atmos Design Patterns sidebar_position: 5 -sidebar_label: Design Patterns -description: Atmos Design Patterns. Elements of Reusable Infrastructure Configuration +sidebar_label: Use Design Patterns +sidebar_class_name: hidden +description: Techniques of Reusable Infrastructure Configuration id: design-patterns --- -import DocCardList from "@theme/DocCardList"; +import DocCardList from '@theme/DocCardList' +import Intro from '@site/src/components/Intro' +import KeyPoints from '@site/src/components/KeyPoints' -# Atmos Design Patterns + +Atmos Design Patterns are a collection of conventions, best practices, concepts, principles and insights derived from our experience building enterprise scale architectures. These are vital for effectively structuring and organizing infrastructures, components, and stacks. They empower implementors and cloud architects alike, by providing access to the collective wisdom of seasoned professionals. + -Elements of Reusable Infrastructure Configuration +These patterns serve as a guide for creating solutions that are not only reusable but also robust, flexible, and maintainable. Importantly, they foster convergence amongst engineers on a standard set of recognized patterns, effectively putting a name to the practices and strategies that have proven successful. This standardization aids in streamlining communication and understanding among professionals, enhancing collaboration and efficiency in the field. + + +- How utilizing established patterns can simplify complex system architecture. +- The iterative and challenging process of achieving reusable, adaptable designs. +- Ways expert architects leverage past solutions to enhance efficiency and drive innovation. + ## Motivation The importance of patterns in architecting complex systems has been long recognized across various fields. -A well-architected infrastructure is rich with patterns. Giving careful attention to these patterns during the development of a system can result in -an architecture that is not only smaller and simpler but also more comprehensible compared to ignoring these patterns. - -Designing for organizational complexity is challenging, and making all the components and configurations reusable is even harder. -It involves identifying relevant components and configurations, transforming them into reusable artifacts at the appropriate granularity, -establishing inheritance hierarchies, and defining crucial relationships among them. The design must be specific to the current problem while also -being sufficiently general to accommodate future challenges and requirements. Additionally, minimizing or avoiding redesign is essential. Seasoned -architects emphasize that creating a design that is both reusable and flexible is a daunting task, if not impossible, on the first attempt. - -Nevertheless, experienced architects consistently produce effective designs. -What do they know that the others don't? -They possess insights that less-experienced architects may lack. One key aspect of their expertise is the avoidance of solving every problem from -scratch. Instead, they leverage solutions that have proven successful in the past, applying them repeatedly. This accumulated experience is a crucial -factor that distinguishes them as experts. Recurrent patterns are evident in well-designed systems, offering solutions to specific design challenges -and enhancing the flexibility, elegance, and reusability of infrastructure configurations. These patterns enable architects to build upon successful -designs by drawing on prior experience. An architect who is familiar with such patterns can immediately apply them to design problems without the need -to rediscover them. - -:::info Summary +A well-architected infrastructure is rich with patterns. Giving careful attention to these patterns during the development of a system can result in an architecture that is not only smaller and simpler but also more comprehensible compared to ignoring these patterns. -- Utilizing established patterns simplifies complex system architecture. -- Achieving reusable, adaptable design is challenging and iterative. -- Expert architects leverage past solutions to enhance efficiency and innovation. +Designing for organizational complexity is challenging, and making all the components and configurations reusable is even harder. It involves identifying relevant components and configurations, transforming them into reusable artifacts at the appropriate granularity, establishing inheritance hierarchies, and defining crucial relationships among them. The design must be specific to the current problem while also being sufficiently general to accommodate future challenges and requirements. Additionally, minimizing or avoiding redesign is essential. Seasoned architects emphasize that creating a design that is both reusable and flexible is a daunting task, if not impossible, on the first attempt. -::: +Nevertheless, experienced architects consistently produce effective designs. What do they know that the others don't? They possess insights that less-experienced architects may lack. One key aspect of their expertise is the avoidance of solving every problem from scratch. Instead, they leverage solutions that have proven successful in the past, applying them repeatedly. This accumulated experience is a crucial factor that distinguishes them as experts. Recurrent patterns are evident in well-designed systems, offering solutions to specific design challenges and enhancing the flexibility, elegance, and reusability of infrastructure configurations. These patterns enable architects to build upon successful designs by drawing on prior experience. An architect who is familiar with such patterns can immediately apply them to design problems without the need to rediscover them. ## What is a Design Pattern? The well-known architect and design theorist [Christopher Alexander](https://en.wikipedia.org/wiki/Christopher_Alexander) said: > Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution -> to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.

— **Christopher Alexander**

+> to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.

— **Christopher Alexander**

Even though Christopher Alexander was describing the patterns in construction and buildings, what he said is true about DevOps design patterns. +:::tip Check Out Best Practices +Also, checkout our [best practices](/best-practices) for more insights on how to design and manage your infrastructure. +::: + ## What are Atmos Design Patterns? Atmos Design Patterns capture key concepts, principles, and insights vital for effectively structuring and organizing infrastructures, -components, and stacks. Inspired by [Cloud Posse's](https://cloudposse.com) extensive real-world experience in assisting -Funded Startups and Enterprises, these patterns are meticulously developed to tackle organizational complexity. They focus on facilitating -the creation of multi-account, enterprise-grade environments, specifically designed for the nuanced needs of complex organizations. +components, and stacks. Inspired by [Cloud Posse's](https://cloudposse.com) extensive real-world experience in assisting Funded Startups and Enterprises, these patterns are meticulously developed to tackle organizational complexity. They focus on facilitating the creation of multi-account, enterprise-grade environments, specifically designed for the nuanced needs of complex organizations. -Atmos Design Patterns empower infrastructure designers and cloud architects by providing access to the collective wisdom of seasoned professionals. -These patterns serve as a guide for creating solutions that are not only reusable but also robust, flexible, and maintainable. Importantly, -they foster convergence on a standard set of recognized patterns, effectively putting a name to the practices and strategies that have proven -successful. This standardization aids in streamlining communication and understanding among professionals, enhancing collaboration and efficiency -in the field. +Atmos Design Patterns empower infrastructure designers and cloud architects by providing access to the collective wisdom of seasoned professionals. These patterns serve as a guide for creating solutions that are not only reusable but also robust, flexible, and maintainable. Importantly, they foster convergence on a standard set of recognized patterns, effectively putting a name to the practices and strategies that have proven successful. This standardization aids in streamlining communication and understanding among professionals, enhancing collaboration and efficiency in the field. :::info Summary @@ -81,17 +70,10 @@ forms. Once you understand the Design Patterns and have experience with them, you won't ever think about infrastructure design in the same way. You'll have knowledge and insights that can make your own designs more flexible, modular, reusable, and understandable. -
- :::note -We view this collection of Design Patterns as neither exhaustive nor fixed. Instead, it serves as a documentation of our present ideas, insights and -knowledge. Your input, whether in the form of comments, critiques, references, or suggestions for Design Patterns we may have overlooked, is highly -encouraged and appreciated. +We view this collection of Design Patterns as neither exhaustive nor fixed. Instead, it serves as a documentation of our present ideas, insights and knowledge. Your input, whether in the form of comments, critiques, references, or suggestions for Design Patterns we may have overlooked, is highly encouraged and appreciated. ::: -
-
- diff --git a/website/docs/design-patterns/inline-component-configuration.mdx b/website/docs/design-patterns/inline-component-configuration.mdx index 6e58d661e..0979e6db3 100644 --- a/website/docs/design-patterns/inline-component-configuration.mdx +++ b/website/docs/design-patterns/inline-component-configuration.mdx @@ -1,15 +1,20 @@ --- -title: Inline Component Configuration Atmos Design Pattern +title: Inline Component Configuration sidebar_position: 2 sidebar_label: Inline Component Configuration description: Inline Component Configuration Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Inline Component Configuration +Atmos Design Pattern -The **Inline Component Configuration** pattern is used when the [components](/core-concepts/components) in a [stack](/core-concepts/stacks) -are configured inline in the stack manifest without [importing](/core-concepts/stacks/imports) and reusing default/base configurations. If you're starting with Atmos, this will be the easiest to understand until you need the more advanced features. + +The **Inline Component Configuration** pattern is used when the [components](/core-concepts/components) in a [stack](/core-concepts/stacks) are configured inline in the stack manifest without [importing](/core-concepts/stacks/imports) and reusing default/base configurations. + + +If you're starting with Atmos, inline configurations will be the easiest to understand until you need the more advanced features. ## Use-cases diff --git a/website/docs/design-patterns/inline-component-customization.mdx b/website/docs/design-patterns/inline-component-customization.mdx index d125359d5..999e9d13f 100644 --- a/website/docs/design-patterns/inline-component-customization.mdx +++ b/website/docs/design-patterns/inline-component-customization.mdx @@ -1,17 +1,18 @@ --- -title: Inline Component Customization Atmos Design Pattern +title: Inline Component Customization sidebar_position: 3 sidebar_label: Inline Component Customization description: Inline Component Customization Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Inline Component Customization +Atmos Design Pattern -The **Inline Component Customization** pattern is used when the defaults for the [components](/core-concepts/components) in -a [stack](/core-concepts/stacks) -are configured in default manifests, the manifests are [imported](/core-concepts/stacks/imports) into the top-level stacks, and the components -are customized inline in each top-level stack overriding the configuration for each environment (OU, account, region). + +The **Inline Component Customization** pattern is used when the defaults for the [components](/core-concepts/components) in a [stack](/core-concepts/stacks) are configured in default manifests, the manifests are [imported](/core-concepts/stacks/imports) into the top-level stacks, and the components are customized inline in each top-level stack overriding the configuration for each environment (OU, account, region). + ## Use-cases diff --git a/website/docs/design-patterns/layered-stack-configuration.mdx b/website/docs/design-patterns/layered-stack-configuration.mdx index 4fb2fd959..c779c84d0 100644 --- a/website/docs/design-patterns/layered-stack-configuration.mdx +++ b/website/docs/design-patterns/layered-stack-configuration.mdx @@ -1,20 +1,21 @@ --- -title: Layered Stack Configuration Atmos Design Pattern +title: Layered Stack Configuration sidebar_position: 13 sidebar_label: Layered Stack Configuration description: Layered Stack Configuration Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Layered Stack Configuration +Atmos Design Pattern + The **Layered Stack Configuration** Design Pattern describes the mechanism of grouping Atmos components by category or function, adding the groups of components to layers, and importing the layers into top-level Atmos stacks. + -Each layer imports or configures a set of related Atmos components. Each Atmos component belongs to just one layer. -Each layer can be managed separately, possibly by different teams. - -
+Each layer imports or configures a set of related Atmos components. Each Atmos component belongs to just one layer. Each layer can be managed separately, possibly by different teams. :::note @@ -68,8 +69,6 @@ In the `stacks/layers` folder, we define layers (groups of components), and impo - `networking.yaml` - `eks.yaml` -
- ```console    │   # Centralized stacks configuration (stack manifests)    ├── stacks @@ -263,7 +262,7 @@ Import the required layers into the `stacks/orgs/acme/plat/dev/us-east-2.yaml` t ```yaml title="stacks/orgs/acme/plat/dev/us-east-2.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -282,7 +281,7 @@ Import the required layers into the `stacks/orgs/acme/plat/dev/us-west-2.yaml` t ```yaml title="stacks/orgs/acme/plat/dev/us-west-2.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-west-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-west-2` manifests # define the top-level Atmos stack `plat-uw2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-west-2 @@ -301,7 +300,7 @@ Import the required layers into the `stacks/orgs/acme/plat/prod/us-east-2.yaml` ```yaml title="stacks/orgs/acme/plat/prod/us-east-2.yaml" import: - # The `orgs/acme/plat/prod/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/prod/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-prod` - orgs/acme/plat/prod/_defaults - mixins/region/us-east-2 @@ -316,8 +315,6 @@ import: - layers/eks ``` -
- Similarly, import the required layers into the other top-level stacks for the other organizations, OUs/tenants, accounts and regions. Make sure to import only the layers that define the component that need to be provisioned in the stacks. @@ -330,4 +327,4 @@ Make sure to import only the layers that define the component that need to be pr ## References - [Catalogs](/core-concepts/stacks/catalogs) -- [Mixins](/core-concepts/stacks/mixins) +- [Mixins](/core-concepts/stacks/inheritance/mixins) diff --git a/website/docs/design-patterns/multiple-component-instances.mdx b/website/docs/design-patterns/multiple-component-instances.mdx index 48777421e..9d91f77ca 100644 --- a/website/docs/design-patterns/multiple-component-instances.mdx +++ b/website/docs/design-patterns/multiple-component-instances.mdx @@ -1,19 +1,20 @@ --- -title: Multiple Component Instances Atmos Design Pattern +title: Multiple Component Instances sidebar_position: 10 sidebar_label: Multiple Component Instances description: Multiple Component Instances Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Multiple Component Instances +Atmos Design Pattern -The **Multiple Component Instances** Design Pattern describes how to provision many instances of a Terraform component in the same environment by -configuring multiple Atmos component instances. + +The **Multiple Component Instances** Design Pattern describes how to provision multiple instances of a single Terraform component in the same environment by configuring multiple Atmos component instances. + -An Atmos component can have any name that can be different from the Terraform component name. More than one instance of the same Terraform component -(with the same or different settings) can be provisioned into the same environment by defining multiple Atmos components that provide configuration -for the Terraform component. +An Atmos component can have any name that can be different from the Terraform component name. More than one instance of the same Terraform component (with the same or different settings) can be provisioned into the same environment by defining multiple Atmos components that provide configuration for the Terraform component. For example, two different Atmos components `vpc/1` and `vpc/2` can provide configuration for the same Terraform component `vpc`. @@ -33,7 +34,7 @@ The **Multiple Component Instances** pattern provides the following benefits: - The defaults for the components are defined in just one place making the entire configuration [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) - + ## Example The following example shows the Atmos stack and component configurations to provision two Atmos components (`vpc/1` and `vpc/2`) that use the @@ -184,8 +185,6 @@ components: map_public_ip_on_launch: false ``` -
- To provision the components in the stack, execute the following commands: ```shell diff --git a/website/docs/design-patterns/organizational-structure-configuration.mdx b/website/docs/design-patterns/organizational-structure-configuration.mdx index 651439597..81137b65e 100644 --- a/website/docs/design-patterns/organizational-structure-configuration.mdx +++ b/website/docs/design-patterns/organizational-structure-configuration.mdx @@ -1,18 +1,21 @@ --- -title: Organizational Structure Configuration Atmos Design Pattern +title: Organizational Structure Configuration sidebar_position: 4 sidebar_label: Organizational Structure Configuration description: Organizational Structure Configuration Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Organizational Structure Configuration +Atmos Design Pattern + The **Organizational Structure Configuration** pattern describes core concepts and best practices to structure and organize components and stacks to design for organizational complexity and provision multi-account enterprise-grade environments. + -The pattern is used to model multi-region infrastructures for organizations with multiple organizational units/departments/tenants and multiple -accounts. +The pattern is frequently used to model multi-region infrastructures for organizations with multiple organizational units/departments/tenants and multiple accounts. ## Use-cases @@ -306,20 +309,14 @@ vars: # Other defaults for the `staging` stage/account ``` -
- ### Configure Organization Defaults -
- :::note The `_defaults.yaml` files in the organization, tenant, account and region folders is the recommended way to define the stack manifests with the default configurations for organizations, OUs/tenants, accounts and regions. The `_defaults.yaml` files themselves are not top-level Atmos stacks, they just contain the default values for the organizations, OUs/tenants, accounts and regions (to make the entire configuration reusable and DRY) ::: -
- In `stacks/orgs/org1/_defaults.yaml`, add the following config: ```yaml title="stacks/orgs/org1/_defaults.yaml" @@ -528,8 +525,6 @@ The **Organizational Structure Configuration** pattern has the following limitat - The configuration described by the pattern can be complex for very simple infrastructures (e.g. just one organization, one organizational unit, a few accounts and regions) -
- :::note Even if you are just starting with a very simple infrastructure (e.g. just one organization, one organizational unit, a few accounts, one or a few @@ -540,8 +535,6 @@ easy to extend the configuration without changing anything for the exiting envir ::: -
- ## Related Patterns - [Inline Component Configuration](/design-patterns/inline-component-configuration) @@ -557,4 +550,4 @@ easy to extend the configuration without changing anything for the exiting envir ## References - [Catalogs](/core-concepts/stacks/catalogs) -- [Mixins](/core-concepts/stacks/mixins) +- [Mixins](/core-concepts/stacks/inheritance/mixins) diff --git a/website/docs/design-patterns/partial-component-configuration.mdx b/website/docs/design-patterns/partial-component-configuration.mdx index 25fcff8b2..895af7df8 100644 --- a/website/docs/design-patterns/partial-component-configuration.mdx +++ b/website/docs/design-patterns/partial-component-configuration.mdx @@ -1,21 +1,23 @@ --- -title: Partial Component Configuration Atmos Design Pattern +title: Partial Component Configuration sidebar_position: 11 sidebar_label: Partial Component Configuration description: Partial Component Configuration Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Partial Component Configuration +Atmos Design Pattern -The **Partial Component Configuration** Design Pattern describes the mechanism of splitting an Atmos component's configuration across many Atmos -manifests to manage, modify and apply them separately and independently in one top-level stack without affecting the others. + +The **Partial Component Configuration** Design Pattern describes the mechanism of splitting an Atmos component's configuration across many Atmos manifests to manage, modify and apply them separately and independently in one top-level stack without affecting the others. + The mechanism is similar to [Partial Classes in C#](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods). -This is not the same as Atmos [Component Inheritance](/core-concepts/components/inheritance) where more than one Atmos components -take part in the inheritance chain. The **Partial Component Configuration** pattern deals with just one Atmos component with its configuration split -across a few configuration files. +This is not the same as Atmos [Component Inheritance](/core-concepts/stacks/inheritance) where more than one Atmos components +take part in the inheritance chain. The **Partial Component Configuration** pattern deals with just one Atmos component with its configuration split across a few configuration files. :::note @@ -200,7 +202,7 @@ import: # Import the mixin for the required Kubernetes version to define the k8s version and addon versions for the EKS cluster in this stack. # This is an example of partial component configuration in Atmos where the config for the component is split across many Atmos stack manifests (stack config files). # It's similar to Partial Classes in C# (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods). - # This is not the same as 'Atmos Component Inheritance' (https://atmos.tools/core-concepts/components/inheritance) + # This is not the same as 'Atmos Component Inheritance' (https://atmos.tools/core-concepts/stacks/inheritance) # where more than one Atmos component participates in the inheritance chain. - catalog/eks/clusters/mixins/k8s-1-27 ``` @@ -234,4 +236,4 @@ clusters in the other accounts and regions will stay at the current Kubernetes v ## References - [Catalogs](/core-concepts/stacks/catalogs) -- [Mixins](/core-concepts/stacks/mixins) +- [Mixins](/core-concepts/stacks/inheritance/mixins) diff --git a/website/docs/design-patterns/partial-stack-configuration.mdx b/website/docs/design-patterns/partial-stack-configuration.mdx index 6a2881bd6..da197fc4e 100644 --- a/website/docs/design-patterns/partial-stack-configuration.mdx +++ b/website/docs/design-patterns/partial-stack-configuration.mdx @@ -1,19 +1,20 @@ --- -title: Partial Stack Configuration Atmos Design Pattern +title: Partial Stack Configuration sidebar_position: 12 sidebar_label: Partial Stack Configuration description: Partial Stack Configuration Atmos Design Pattern --- import File from '@site/src/components/File' +import PillBox from '@site/src/components/PillBox' +import Intro from '@site/src/components/Intro' -# Partial Stack Configuration +Atmos Design Pattern -The **Partial Stack Configuration** Design Pattern describes the mechanism of splitting an Atmos top-level stack's configuration across many Atmos -stack manifests to manage and modify them separately and independently. + +The **Partial Stack Configuration** Design Pattern describes the mechanism of splitting an Atmos top-level stack's configuration across many Atmos stack manifests to manage and modify them separately and independently. + -Each partial top-level stack manifest imports or configures a set of related Atmos components. Each Atmos component belongs to just one of the partial -top-level stack manifests. The pattern helps to group all components by category or function and to make each partial stack manifest smaller and -easier to manage. +Each partial top-level stack manifest imports or configures a set of related Atmos components. Each Atmos component belongs to just one of the partial top-level stack manifests. The pattern helps to group all components by category or function and to make each partial stack manifest smaller and easier to manage. ## Use-cases @@ -55,8 +56,6 @@ In the `stacks/orgs/acme/plat/dev/us-east-2` folder, we split the top-level stac - `networking.yaml` - `eks.yaml` -
- ```console    │   # Centralized stacks configuration (stack manifests)    ├── stacks @@ -166,7 +165,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/load ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/load-balancers.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -179,7 +178,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/data ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/data.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -194,7 +193,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/dns. ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/dns.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -207,7 +206,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/logs ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/logs.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -221,7 +220,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/noti ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/notifications.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -235,7 +234,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/fire ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/firewalls.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -249,7 +248,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/netw ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/networking.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -262,7 +261,7 @@ Add the following configuration to the `stacks/orgs/acme/plat/dev/us-east-2/eks. ```yaml title="stacks/orgs/acme/plat/dev/us-east-2/eks.yaml" import: - # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests + # The `orgs/acme/plat/dev/_defaults` and `mixins/region/us-east-2` manifests # define the top-level Atmos stack `plat-ue2-dev` - orgs/acme/plat/dev/_defaults - mixins/region/us-east-2 @@ -299,4 +298,4 @@ the [Layered Stack Configuration](/design-patterns/layered-stack-configuration) ## References - [Catalogs](/core-concepts/stacks/catalogs) -- [Mixins](/core-concepts/stacks/mixins) +- [Mixins](/core-concepts/stacks/inheritance/mixins) diff --git a/website/docs/design-patterns/summary.md b/website/docs/design-patterns/summary.mdx similarity index 86% rename from website/docs/design-patterns/summary.md rename to website/docs/design-patterns/summary.mdx index c1eb41abb..3fbe63c80 100644 --- a/website/docs/design-patterns/summary.md +++ b/website/docs/design-patterns/summary.mdx @@ -4,13 +4,12 @@ sidebar_position: 100 sidebar_label: Summary description: Summary --- +import Intro from '@site/src/components/Intro' + Architecting and provisioning enterprise-grade infrastructure is challenging, and making all the components and -configurations [reusable](https://en.wikipedia.org/wiki/Reusability) and [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) is even more -difficult. - -These Atmos Design Patterns can help with structuring and organizing your design to provision multi-account enterprise-grade environments for complex -organizations. +configurations [reusable](https://en.wikipedia.org/wiki/Reusability) and [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) is even more difficult. These Atmos Design Patterns can help with structuring and organizing your design to provision multi-account enterprise-grade environments for complex organizations. + We've already identified and documented many Atmos Design Patterns. You may be wondering, "Where do I begin and what steps should I follow?" @@ -19,11 +18,11 @@ Here are some recommendations. ### Quick Start Repository Introduction -This [Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start) repository presents an example of an infrastructure managed +This [Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced) repository presents an example of an infrastructure managed by Atmos. You can clone it and configure to your own needs. The repository should be a good start to get yourself familiar with Atmos and the Design Patterns. The [Quick Start Guide](/quick-start) describes the steps required to configure and start using the repository. -The [Atmos Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start) repository, that is described in +The [Atmos Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced) repository, that is described in the [Quick Start](/quick-start) guide, uses the following Atmos Design Patterns: - [Organizational Structure Configuration](/design-patterns/organizational-structure-configuration) diff --git a/website/docs/reference/glossary/_category_.json b/website/docs/glossary/_category_.json similarity index 100% rename from website/docs/reference/glossary/_category_.json rename to website/docs/glossary/_category_.json diff --git a/website/docs/reference/glossary/abstract-component.md b/website/docs/glossary/abstract-component.md similarity index 100% rename from website/docs/reference/glossary/abstract-component.md rename to website/docs/glossary/abstract-component.md diff --git a/website/docs/reference/glossary/catalog.md b/website/docs/glossary/catalog.md similarity index 100% rename from website/docs/reference/glossary/catalog.md rename to website/docs/glossary/catalog.md diff --git a/website/docs/reference/glossary/component-instance.md b/website/docs/glossary/component-instance.md similarity index 100% rename from website/docs/reference/glossary/component-instance.md rename to website/docs/glossary/component-instance.md diff --git a/website/docs/reference/glossary/component.md b/website/docs/glossary/component.md similarity index 100% rename from website/docs/reference/glossary/component.md rename to website/docs/glossary/component.md diff --git a/website/docs/reference/glossary/concrete-component.md b/website/docs/glossary/concrete-component.md similarity index 100% rename from website/docs/reference/glossary/concrete-component.md rename to website/docs/glossary/concrete-component.md diff --git a/website/docs/reference/glossary/environment.md b/website/docs/glossary/environment.md similarity index 100% rename from website/docs/reference/glossary/environment.md rename to website/docs/glossary/environment.md diff --git a/website/docs/glossary/framework.mdx b/website/docs/glossary/framework.mdx new file mode 100644 index 000000000..6175e3d6d --- /dev/null +++ b/website/docs/glossary/framework.mdx @@ -0,0 +1,6 @@ +--- +id: framework +title: Programming Framework +hoverText: A framework provides ready-made solutions and guidelines for common tasks, saving time and effort. +--- +Think of a programming framework like a toolkit or a set of building blocks for creating software. Just like how a carpenter uses specific tools and materials to build a house, programmers use frameworks to build applications. A framework provides ready-made solutions and guidelines for common tasks, saving time and effort. It helps ensure that the software is built in a consistent and efficient way, without having to start from scratch every time. diff --git a/website/docs/reference/glossary/imports.md b/website/docs/glossary/imports.md similarity index 100% rename from website/docs/reference/glossary/imports.md rename to website/docs/glossary/imports.md diff --git a/website/docs/reference/glossary/index.mdx b/website/docs/glossary/index.mdx similarity index 94% rename from website/docs/reference/glossary/index.mdx rename to website/docs/glossary/index.mdx index d929a769e..daac8454c 100644 --- a/website/docs/reference/glossary/index.mdx +++ b/website/docs/glossary/index.mdx @@ -1,6 +1,7 @@ --- id: glossary title: Glossary +sidebar_class_name: hidden slug: /terms/ --- @@ -12,6 +13,4 @@ of [Object-Oriented Programming](https://en.wikipedia.org/wiki/Object-oriented_p to configuration, enabling you to model configuration in a way that makes sense for your organization. ::: -
- Click on a term for a more detailed description. diff --git a/website/docs/reference/glossary/inheritance.md b/website/docs/glossary/inheritance.md similarity index 100% rename from website/docs/reference/glossary/inheritance.md rename to website/docs/glossary/inheritance.md diff --git a/website/docs/reference/glossary/integration.md b/website/docs/glossary/integration.md similarity index 100% rename from website/docs/reference/glossary/integration.md rename to website/docs/glossary/integration.md diff --git a/website/docs/reference/glossary/kubernetes-namespace.mdx b/website/docs/glossary/kubernetes-namespace.mdx similarity index 100% rename from website/docs/reference/glossary/kubernetes-namespace.mdx rename to website/docs/glossary/kubernetes-namespace.mdx diff --git a/website/docs/reference/glossary/library.md b/website/docs/glossary/library.md similarity index 100% rename from website/docs/reference/glossary/library.md rename to website/docs/glossary/library.md diff --git a/website/docs/reference/glossary/mixins.md b/website/docs/glossary/mixins.md similarity index 100% rename from website/docs/reference/glossary/mixins.md rename to website/docs/glossary/mixins.md diff --git a/website/docs/reference/glossary/multiple-inheritance.md b/website/docs/glossary/multiple-inheritance.md similarity index 100% rename from website/docs/reference/glossary/multiple-inheritance.md rename to website/docs/glossary/multiple-inheritance.md diff --git a/website/docs/reference/glossary/namespace.md b/website/docs/glossary/namespace.md similarity index 100% rename from website/docs/reference/glossary/namespace.md rename to website/docs/glossary/namespace.md diff --git a/website/docs/reference/glossary/parent-stack.md b/website/docs/glossary/parent-stack.md similarity index 100% rename from website/docs/reference/glossary/parent-stack.md rename to website/docs/glossary/parent-stack.md diff --git a/website/docs/reference/glossary/real-component.md b/website/docs/glossary/real-component.md similarity index 100% rename from website/docs/reference/glossary/real-component.md rename to website/docs/glossary/real-component.md diff --git a/website/docs/reference/glossary/spacelift-stack.md b/website/docs/glossary/spacelift-stack.md similarity index 100% rename from website/docs/reference/glossary/spacelift-stack.md rename to website/docs/glossary/spacelift-stack.md diff --git a/website/docs/reference/glossary/stack-manifest.md b/website/docs/glossary/stack-manifest.md similarity index 100% rename from website/docs/reference/glossary/stack-manifest.md rename to website/docs/glossary/stack-manifest.md diff --git a/website/docs/reference/glossary/stack.mdx b/website/docs/glossary/stack.mdx similarity index 100% rename from website/docs/reference/glossary/stack.mdx rename to website/docs/glossary/stack.mdx diff --git a/website/docs/reference/glossary/stage.md b/website/docs/glossary/stage.md similarity index 100% rename from website/docs/reference/glossary/stage.md rename to website/docs/glossary/stage.md diff --git a/website/docs/reference/glossary/tenant.md b/website/docs/glossary/tenant.md similarity index 100% rename from website/docs/reference/glossary/tenant.md rename to website/docs/glossary/tenant.md diff --git a/website/docs/reference/glossary/terraform-child-module.md b/website/docs/glossary/terraform-child-module.md similarity index 100% rename from website/docs/reference/glossary/terraform-child-module.md rename to website/docs/glossary/terraform-child-module.md diff --git a/website/docs/glossary/terralith.mdx b/website/docs/glossary/terralith.mdx new file mode 100644 index 000000000..74e5b798f --- /dev/null +++ b/website/docs/glossary/terralith.mdx @@ -0,0 +1,36 @@ +--- +id: teralith +slug: /terms/terralith +title: Terralith +hoverText: "On overly large Terraform \"root module\" a large portion of the infrastructure." +--- + +A monolithic Terraform "root module" is also known as a Terralith. It's characterized by an expansive, all-encompassing Terraform configuration that attempts to manage every aspect of the infrastructure within a single module. + +```mermaid +--- +title: Anatomy of a Terralith +--- +graph TD + subgraph TerraformRootModule[Terraform Root Module] + subgraph Network[Network VPC] + subgraph Cluster[Kubernetes Cluster] + App1(Application 1) + App2(Application 2) + end + LB[(Load Balancer Module)] + DB[(Database Module)] + Cache[(Cache Module)] + ObjectStorage[(Object Storage Module)] + end + LB --> App1 + LB --> App2 + App1 --> DB + App1 --> Cache + App2 --> ObjectStorage + end +``` + +In Atmos, this is considered an anti-pattern; instead, this should be broken down into [components](/core-concepts/components) and configured with [stacks](/core-concepts/stacks). + +To learn more, see [Stage 2](/introduction/why-atmos/stage-2) of the typical Terraform maturity path. diff --git a/website/docs/reference/glossary/vendoring.md b/website/docs/glossary/vendoring.md similarity index 100% rename from website/docs/reference/glossary/vendoring.md rename to website/docs/glossary/vendoring.md diff --git a/website/docs/integrations/atlantis.mdx b/website/docs/integrations/atlantis.mdx index 9660e40c5..8c8be4b4e 100644 --- a/website/docs/integrations/atlantis.mdx +++ b/website/docs/integrations/atlantis.mdx @@ -3,10 +3,12 @@ title: Atlantis Integration sidebar_position: 10 sidebar_label: Atlantis --- - import Terminal from '@site/src/components/Terminal' +import Intro from '@site/src/components/Intro' + Atmos natively supports [Atlantis](https://runatlantis.io) for Terraform Pull Request Automation. + ## How it Works @@ -163,8 +165,6 @@ workflows: - run: terraform plan -input=false -refresh -out $PLANFILE -var-file varfiles/$PROJECT_NAME.tfvars ``` -
- __NOTE:__ If Atlantis Integration is configured only in the `integrations.atlantis` section in `atmos.yaml`, the command-line flags `--config-template` and `--project-template` are required to specify a config template and a project template from the collection of templates defined in the `integrations.atlantis.config_templates` and `integrations.atlantis.project_templates` sections in `atmos.yaml`. You can @@ -190,7 +190,7 @@ Configuring the Atlantis Integration in the `settings.atlantis` sections in the example: - ```yaml + ```yaml atmos_component: test/test-component-override atmos_stack: tenant1-ue2-dev component: test/test-component @@ -246,7 +246,7 @@ Configuring the Atlantis Integration in the `settings.atlantis` sections in the affected Atlantis projects in the `atlantis_project` field. For example: - ```json + ```json [ { "component": "infra/vpc", @@ -268,8 +268,6 @@ Configuring the Atlantis Integration in the `settings.atlantis` sections in the ``` -
- #### Configure `settings.atlantis.workflow_templates` section in stack configs If you are using the [Atlantis Repo Level workflows](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html), you can configure the workflows @@ -309,8 +307,6 @@ workflows: - run: terraform plan -out $PLANFILE -var-file varfiles/$PROJECT_NAME.tfvars ``` -
- :::note The `settings.atlantis.workflow_templates` section in stack configs has higher priority then the `integration.atlantis.workflow_templates` @@ -320,8 +316,6 @@ Atmos will use the workflows from the `integration.atlantis.workflow_templates` ::: -
- #### Define config template and project template in `settings.atlantis` section in stack configs The Atlantis config template and project template can be defined in the `settings.atlantis` section in two different ways: @@ -333,7 +327,7 @@ The Atlantis config template and project template can be defined in the `setting integrations: atlantis: path: "atlantis.yaml" - + # Config templates config_templates: config-1: @@ -346,7 +340,7 @@ The Atlantis config template and project template can be defined in the `setting - dev/ - staging/ - prod/ - + # Project templates project_templates: project-1: @@ -368,11 +362,11 @@ The Atlantis config template and project template can be defined in the `setting ```yaml title="stacks/orgs/cp/_defaults.yaml" settings: atlantis: - # Select a config template defined in `atmos.yaml` in + # Select a config template defined in `atmos.yaml` in # the `integrations.atlantis.config_templates` section config_template_name: "config-1" - - # Select a project template defined in `atmos.yaml` in + + # Select a project template defined in `atmos.yaml` in # the `integrations.atlantis.project_templates` section project_template_name: "project-1" ``` @@ -382,8 +376,6 @@ The Atlantis config template and project template can be defined in the `setting defined at any level in the stack configs and they participate in deep-merging and inheritance (meaning they can be overridden per tenant, environment, stage and component). -
- - Define `config_template` and `project_template` in the `settings.atlantis` section. These attributes tell Atmos to use the templates instead of searching for them in the `integration.atlantis` section in `atmos.yaml`. For example: @@ -391,7 +383,7 @@ The Atlantis config template and project template can be defined in the `setting settings: atlantis: - # For this `tenant1-ue2-dev` stack, override the org-wide config template + # For this `tenant1-ue2-dev` stack, override the org-wide config template # specified in `stacks/orgs/cp/_defaults.yaml` # in the `settings.atlantis.config_template_name` section config_template: @@ -403,7 +395,7 @@ The Atlantis config template and project template can be defined in the `setting allowed_regexp_prefixes: - dev/ - # For this `tenant1-ue2-dev` stack, override the org-wide project template + # For this `tenant1-ue2-dev` stack, override the org-wide project template # specified in `stacks/orgs/cp/_defaults.yaml` # in the `settings.atlantis.project_template_name` section project_template: @@ -423,8 +415,6 @@ The Atlantis config template and project template can be defined in the `setting - "approved" ``` -
- :::note summary - Atlantis integration can be configured in the `integrations.atlantis` section in `atmos.yaml`. If this is the only place where it's configured, then @@ -467,7 +457,7 @@ Atlantis workflows can be defined in two different ways: # allow_custom_workflows defines whether this repo can define its own # workflows. If false (default), the repo can only use server-side defined # workflows. - allow_custom_workflows: true + allow_custom_workflows: true # workflows lists server-side custom workflows workflows: @@ -479,7 +469,7 @@ Atlantis workflows can be defined in two different ways: apply: steps: - run: echo applying - - apply + - apply ``` - In the [Repo Level atlantis.yaml Config](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html) using the `workflows` section and @@ -505,16 +495,14 @@ Atlantis workflows can be defined in two different ways: - apply ``` -
- If you use the [Server Side Config](https://www.runatlantis.io/docs/server-side-repo-config.html) to define the Atlantis workflows, you don't need to -define workflows in the [CLI Config Atlantis Integration](/cli/configuration#integrations) section in `atmos.yaml` or in +define workflows in the [CLI Config Atlantis Integration](/cli/configuration/#integrations) section in `atmos.yaml` or in the `settings.atlantis.workflow_templates` section in the stack configurations. When you defined the workflows in the server config `workflows` section, you can reference a workflow to be used for each generated Atlantis project in the project templates. On the other hand, if you use [Repo Level workflows](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html), you need to provide at least one workflow template in the `integrations.atlantis.workflow_templates` section in -the [Atlantis Integration](/cli/configuration#integrations) in `atmos.yaml`, or in the `settings.atlantis.workflow_templates` section in the stack +the [Atlantis Integration](/cli/configuration/#integrations) in `atmos.yaml`, or in the `settings.atlantis.workflow_templates` section in the stack configurations. For example, after executing the following command: @@ -544,8 +532,6 @@ workflows: - run: terraform plan -input=false -refresh -out $PLANFILE -var-file varfiles/$PROJECT_NAME.tfvars.json ``` -
- ## Dynamic Repo Config Generation If you want to generate the `atlantis.yaml` file before Atlantis can parse it, you can use @@ -765,8 +751,6 @@ jobs: verbose: false ``` -
- ## Next Steps Generating the Atlantis `repo-config` is only part of what's needed to use Atmos with Atlantis. The rest will depend on your organization's diff --git a/website/docs/integrations/aws.mdx b/website/docs/integrations/aws.mdx deleted file mode 100644 index 1bead836b..000000000 --- a/website/docs/integrations/aws.mdx +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: Amazon Web Services (AWS) Integration -sidebar_position: 5 -sidebar_label: Amazon Web Services ---- - -:::tip Atmos is Cloud Agnostic -*Nothing* about `atmos` relies on AWS; the tool is built to be cloud agnostic and will work easily with AWS, Azure, GCP, etc. -::: - - -## Commands - -Atmos currently supports one native command to make working with EKS on AWS easier. - -See also: -* [`atmos aws eks update-kubeconfig`](/cli/commands/aws/eks-update-kubeconfig) which downloads the `kubeconfig` from an EKS cluster and saves it to a file. - - -## Components - -Cloud Posse publishes our entire library of [Components for AWS](https://github.com/cloudposse/terraform-aws-components) that we use in [DevOps Accelerator](https://cloudposse.com/services) tracks. These are all Open Source and licensed under the permissive APACHE 2 license. - -### AWS Accounts & Organizations - -| Component | Description | -| :---------------------------------------------------------------------------------------------------------------- | :---------- | -| [account](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/account) | | -| [account-map](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/account-map) | | -| [account-quotas](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/account-quotas) | | -| [account-settings](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/account-settings) | | -| [acm](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/acm) | | -| [aws-backup](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/aws-backup) | | -| [cloudtrail](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/cloudtrail) | | -| [cloudtrail-bucket](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/cloudtrail-bucket) | | -| [cloudwatch-logs](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/cloudwatch-logs) | | -| [kms](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/kms) | | -| [s3-bucket](https://github.com/cloudposse/terraform-aws-components/tree/master/modules/s3-bucket) | | - -### Analytics -| Component | Description | -| :----------------- | :---------- | -| athena | | -| dms | | -| kinesis-stream | | -| lakeformation | | -| mwaa | | -| snowflake-account | | -| snowflake-database | | - -### Databases -| Component | Description | -| :------------------------ | :---------- | -| aurora-mysql | | -| aurora-mysql-resources | | -| aurora-postgres | | -| aurora-postgres-resources | | -| elasticache-redis | | -| elasticsearch | | -| rds | | -| documentdb | | -| dynamodb | | - -### Identity & Access Management (IAM) -| Component | Description | -| :----------------------- | :---------- | -| aws-saml | | -| aws-sso | | -| aws-team-roles | | -| aws-teams | | -| cognito | | -| iam-role | | -| iam-service-linked-roles | | -| sso | | - -### Networking -| Component | Description | -| :-------------------------------- | :---------- | -| alb | | -| aws-waf-acl | | -| bastion | | -| dns-delegated | | -| dns-primary | | -| ec2-client-vpn | | -| global-accelerator | | -| global-accelerator-endpoint-group | | -| strongdm | | -| tgw | | -| vpc | | -| vpc-flow-logs-bucket | | -| vpc-peering | | -| waf | | -| zscaler | | -| ses | | -| sftp | | - - -### Datadog -| Component | Description | -| :----------------------- | :---------- | -| datadog-agent | | -| datadog-integration | | -| datadog-lambda-forwarder | | -| datadog-monitor | | - - -### Containers -| Component | Description | -| :-------- | :---------- | -| ecr | | - -### EKS -| Component | Description | -| :---------- | :---------- | -| eks | | -| eks-iam | | -| argocd-repo | | - -### ECS -| Component | Description | -| :---------- | :---------- | -| ecs | | -| ecs-service | | - - -### GitHub -| github-action-token-rotator | | -| github-oidc-provider | | -| github-runners | | - - -### OpsGenie - -| Component | Description | -| :------------ | :---------- | -| opsgenie-team | | - - -### Spacelift -| Component | Description | -| :-------------------- | :---------- | -| spacelift | | -| spacelift-worker-pool | | - -### Message Queues & Brokers -| Component | Description | -| :------------- | :---------- | -| sqs-queue | | -| ssm-parameters | | -| mq-broker | | -| sns-topic | | - -### Terraform -| Component | Description | -| :-------------- | :---------- | -| tfstate-backend | | - - diff --git a/website/docs/integrations/github-actions/affected-stacks.mdx b/website/docs/integrations/github-actions/affected-stacks.mdx index 98381ead0..5f497bcab 100644 --- a/website/docs/integrations/github-actions/affected-stacks.mdx +++ b/website/docs/integrations/github-actions/affected-stacks.mdx @@ -2,16 +2,21 @@ title: Affected Stacks sidebar_position: 30 sidebar_label: Affected Stacks +description: Identify the affected stacks and components in a pull request --- - import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' -**Streamline Your Change Management Process** + +The [Atmos Affected Stacks GitHub Action](https://github.com/cloudposse/github-action-atmos-affected-stacks) makes it easy identify the affected [atmos stacks](/core-concepts/stacks/) for a pull request. Use it to build a matrix so you can run other actions based on what was affected. + -The [Atmos Affected Stacks GitHub Action](https://github.com/cloudposse/github-action-atmos-affected-stacks) empowers you to easily identify the affected [atmos stacks](/core-concepts/stacks/) for a pull request so you can gain better insights into the impact of your pull requests. It works by installing Atmos and running [`atmos describe affected`](/cli/commands/describe/affected), and outputs a comprehensive list of affected stacks, both as raw output and as a matrix to be used in subsequent GitHub action jobs. +This GitHub Action installs Atmos, then runs [`atmos describe affected`](/cli/commands/describe/affected), and outputs a comprehensive list of affected stacks, both as raw output and as a matrix to be used in subsequent GitHub action jobs. Discover more details, including the full list of `inputs` and `outputs`, in the [GitHub Action repository](https://github.com/cloudposse/github-action-atmos-affected-stacks) on GitHub. +## How it works + The [`describe affected`](/cli/commands/describe/affected) command works by comparing two different Git commits to generate a list of affected Atmos components and stacks. It assumes that the current repo root is a Git checkout and accepts a parameter to specify the second commit. Overall Process: diff --git a/website/docs/integrations/github-actions/atmos-terraform-apply.mdx b/website/docs/integrations/github-actions/atmos-terraform-apply.mdx index a96ccd502..fbc0951b6 100644 --- a/website/docs/integrations/github-actions/atmos-terraform-apply.mdx +++ b/website/docs/integrations/github-actions/atmos-terraform-apply.mdx @@ -2,11 +2,14 @@ title: Atmos Terraform Apply sidebar_position: 50 sidebar_label: Terraform Apply +description: Run a `terraform apply` to provision changes --- - import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' -The Cloud Posse GitHub Action for "Atmos Terraform Apply" simplifies provisioning Terraform entirely within GitHub Action workflows. It makes it very easy to understand exactly what happened directly within the GitHub UI. + +Simplify provisioning Terraform entirely from within GitHub Action workflows. This action makes it very easy to apply that changes from a `terraform plan` from directly within the GitHub UI. Use this action in your workflows to apply changes to your infrastructure. + Given any component and stack in an Atmos supported infrastructure environment, [`github-action-atmos-terraform-apply`](https://github.com/cloudposse/github-action-atmos-terraform-apply) will retrieve an existing Terraform [planfile](https://developer.hashicorp.com/terraform/tutorials/automation/automate-terraform) from a given S3 bucket using metadata stored inside a DynamoDB table, run `atmos terraform apply` with that planfile, and format the Terraform Apply result as part of a [GitHub Workflow Job Summary](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/). @@ -22,7 +25,6 @@ This GitHub Action incorporates superior GitOps support for Terraform by utilizi * **Beautiful Job Summaries** don't clutter up pull requests with noisy GitHub comments * **100% Open Source with Permissive APACHE2 License** means there are no expensive subscriptions or long-term commitments. - ## Screenshots In the following screenshot, we see a successful "apply" Job Summary report. The report utilizes badges to clearly indicate success or failure. Unnecessary details are neatly hidden behind a collapsible `
` block, providing a streamlined view. Additionally, a direct link is provided to view the job run, eliminating the need for developers to search for information about any potential issues. diff --git a/website/docs/integrations/github-actions/atmos-terraform-drift-detection.mdx b/website/docs/integrations/github-actions/atmos-terraform-drift-detection.mdx index 9220e10be..b48a927d9 100644 --- a/website/docs/integrations/github-actions/atmos-terraform-drift-detection.mdx +++ b/website/docs/integrations/github-actions/atmos-terraform-drift-detection.mdx @@ -2,13 +2,18 @@ title: Atmos Terraform Drift Detection sidebar_position: 60 sidebar_label: Terraform Drift Detection +description: Identify drift and create GitHub Issues for remediation --- - import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' + + +The "Atmos Terraform Drift Detection" and "Atmos Terraform Drift Remediation" GitHub Actions provide a scalable pattern for detecting and remediating Terraform drift from within GitHub by utilizing a combination of scheduled GitHub Workflows and GitHub Issues. + -The Cloud Posse GitHub Action for "Atmos Terraform Drift Detection" and "Atmos Terraform Drift Remediation" define a scalable pattern for detecting and remediating Terraform drift from within GitHub using workflows and Issues. "Atmos Terraform Drift Detection" will determine drifted Terraform state by running [Atmos Terraform Plan](/integrations/github-actions/atmos-terraform-plan) and creating GitHub Issues for any drifted component and stack. Furthermore, "Atmos Terraform Drift Remediation" will run [Atmos Terraform Apply](/integrations/github-actions/atmos-terraform-apply) for any open Issue if called and close the given Issue. With these two actions, we can fully support drift detection for Terraform directly within the GitHub UI. +The "Atmos Terraform Drift Detection" will determine drifted Terraform state by running [Atmos Terraform Plan](/integrations/github-actions/atmos-terraform-plan) and creating GitHub Issues for any drifted component and stack. Furthermore, "Atmos Terraform Drift Remediation" will run [Atmos Terraform Apply](/integrations/github-actions/atmos-terraform-apply) for any open Issue if called and close the given Issue. With these two actions, we can fully support drift detection for Terraform directly within the GitHub UI. -This action is intended to be used together with [Atmos Terraform Plan](/integrations/github-actions/atmos-terraform-plan) and [Atmos Terraform Apply](/integrations/github-actions/atmos-terraform-apply). +These actions are intended to be used together with [Atmos Terraform Plan](/integrations/github-actions/atmos-terraform-plan) and [Atmos Terraform Apply](/integrations/github-actions/atmos-terraform-apply). ## Features diff --git a/website/docs/integrations/github-actions/atmos-terraform-drift-remediation.mdx b/website/docs/integrations/github-actions/atmos-terraform-drift-remediation.mdx new file mode 100644 index 000000000..9c17cd536 --- /dev/null +++ b/website/docs/integrations/github-actions/atmos-terraform-drift-remediation.mdx @@ -0,0 +1,129 @@ +--- +title: Atmos Terraform Drift Remediation +sidebar_position: 60 +sidebar_label: Terraform Drift Remediation +description: Remediate Terraform drift using IssueOps +--- +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' + + +The "Atmos Terraform Drift Remediation" GitHub Action provides a way for easily remediating Terraform drift and works with GitHub Issues using IssueOps. + + +This action is used for drift remediation together with it's [companion action for drift detection](/integrations/github-actions/atmos-terraform-drift-detection). + + +## Usage + +### Config + +The action expects the atmos configuration file `atmos.yaml` to be present in the repository. +The config should have the following structure: + +```yaml +integrations: + github: + gitops: + terraform-version: 1.5.2 + infracost-enabled: false + artifact-storage: + region: us-east-2 + bucket: cptest-core-ue2-auto-gitops + table: cptest-core-ue2-auto-gitops-plan-storage + role: arn:aws:iam::xxxxxxxxxxxx:role/cptest-core-ue2-auto-gitops-gha + role: + plan: arn:aws:iam::yyyyyyyyyyyy:role/cptest-core-gbl-identity-gitops + apply: arn:aws:iam::yyyyyyyyyyyy:role/cptest-core-gbl-identity-gitops + matrix: + sort-by: .stack_slug + group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") +``` + +> [!IMPORTANT] +> **Please note!** This GitHub Action only works with `atmos >= 1.63.0`. If you are using `atmos < 1.63.0` please use `v1` version of this action. + +### Workflow example + +In this example drift will be remediated when user sets label `apply` to an issue. + +```yaml +name: 👽 Atmos Terraform Drift Remediation +run-name: 👽 Atmos Terraform Drift Remediation + +on: + issues: + types: + - labeled + - closed + +permissions: + id-token: write + contents: read + +jobs: + remediate-drift: + runs-on: ubuntu-latest + name: Remediate Drift + if: | + github.event.action == 'labeled' && + contains(join(github.event.issue.labels.*.name, ','), 'apply') + steps: + - name: Remediate Drift + uses: cloudposse/github-action-atmos-terraform-drift-remediation@v1 + with: + issue-number: ${{ github.event.issue.number }} + action: remediate + atmos-config-path: ./rootfs/usr/local/etc/atmos/ + + discard-drift: + runs-on: ubuntu-latest + name: Discard Drift + if: | + github.event.action == 'closed' && + !contains(join(github.event.issue.labels.*.name, ','), 'remediated') + steps: + - name: Discard Drift + uses: cloudposse/github-action-atmos-terraform-drift-remediation@v1 + with: + issue-number: ${{ github.event.issue.number }} + action: discard + atmos-gitops-config-path: ./.github/config/atmos-gitops.yaml +``` + + +## Requirements + +This action has the requirements as [Github Actions](/integrations/github-actions/). Use the same S3 Bucket, DynamoDB table, IAM Roles and config described there. + +## Inputs + +
+
`action`, _required_, default: `remediate`
+
+ Drift remediation action. One of ['remediate', 'discard'] +
+ +
`atmos-config-path`, _required_
+
The path to the `atmos.yaml` file
+ +
`atmos-version`, _optional_, default: `>= 1.63.0`
+
The version of `atmos` to install
+ +
`debug`, _optional_, default: `false`
+
Enable action debug mode
+ +
`issue-number`, _required_
+
Issue Number
+ +
`token`, _optional_
+
+ Used to pull node distributions for Atmos from Cloud Posse's GitHub repository. Since there's a default, this is typically not supplied by the user. When running this action on github.com, the default value is sufficient. When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting. + Default: + ``` + ${{ github.server\_url == 'https://github.com' && github.token \|\| '' }} + ``` +
+
+ + diff --git a/website/docs/integrations/github-actions/atmos-terraform-plan.mdx b/website/docs/integrations/github-actions/atmos-terraform-plan.mdx index 3d443d303..88c1abe97 100644 --- a/website/docs/integrations/github-actions/atmos-terraform-plan.mdx +++ b/website/docs/integrations/github-actions/atmos-terraform-plan.mdx @@ -2,9 +2,13 @@ title: Atmos Terraform Plan sidebar_position: 40 sidebar_label: Terraform Plan +description: Run a `terraform plan` to understand the impact of changes --- +import Intro from '@site/src/components/Intro' -import File from '@site/src/components/File' + +Simplify provisioning Terraform entirely from within GitHub Action workflows. This action makes it very easy to understand exactly what will happen from from the changes in a Pull Request (or any commit) by running a `terraform plan` and surfacing the output as a neatly formatted Job Summary viewable directly within the GitHub UI. + The Cloud Posse GitHub Action for "Atmos Terraform Plan" simplifies provisioning Terraform from within GitHub using workflows. Understand precisely what to expect from running a `terraform plan` from directly within the GitHub UI for any Pull Request. @@ -37,7 +41,7 @@ Furthermore, when a resource is marked for deletion, the Plan Summary will inclu ![Example Destroy](/img/github-actions/destroy.png) -## Usage Example +## Usage In this example, the action is triggered when certain events occur, such as a manual workflow dispatch or the opening, synchronization, or reopening of a pull request, specifically on the main branch. It specifies specific permissions related to assuming roles in AWS. Within the "plan" job, the "component" and "stack" are hardcoded (`foobar` and `plat-ue2-sandbox`). In practice, these are usually derived from another action. @@ -47,36 +51,131 @@ We recommend combining this action with the [`affected-stacks`](/integrations/gi ::: - + +```yaml + # .github/workflows/atmos-terraform-plan.yaml + name: "atmos-terraform-plan" + on: + pull_request: + types: + - opened + - synchronize + - reopened + branches: + - main + # These permissions are required for GitHub to assume roles in AWS + permissions: + id-token: write + contents: read + jobs: + plan: + runs-on: ubuntu-latest + steps: + - name: Plan Atmos Component + uses: cloudposse/github-action-atmos-terraform-plan@v1 + with: + component: "foobar" + stack: "plat-ue2-sandbox" + atmos-gitops-config-path: ./.github/config/atmos-gitops.yaml +``` + +with the following configuration as an example: + ```yaml -name: "atmos-terraform-plan" -on: - pull_request: - types: - - opened - - synchronize - - reopened - branches: - - main -# These permissions are required for GitHub to assume roles in AWS -permissions: - id-token: write - contents: read -jobs: - plan: - runs-on: ubuntu-latest - steps: - - name: Plan Atmos Component - uses: cloudposse/github-action-atmos-terraform-plan@v2 - with: - component: "foobar" - stack: "plat-ue2-sandbox" - sha: ${{ github.sha }} - atmos-config-path: ./rootfs/usr/local/etc/atmos/ - atmos-version: 1.63.0 + # .github/config/atmos-gitops.yaml + atmos-config-path: ./rootfs/usr/local/etc/atmos/ + atmos-version: 1.65.0 + aws-region: us-east-2 + enable-infracost: false + group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") + sort-by: .stack_slug + terraform-apply-role: arn:aws:iam::yyyyyyyyyyyy:role/cptest-core-gbl-identity-gitops + terraform-plan-role: arn:aws:iam::yyyyyyyyyyyy:role/cptest-core-gbl-identity-gitops + terraform-state-bucket: cptest-core-ue2-auto-gitops + terraform-state-role: arn:aws:iam::xxxxxxxxxxxx:role/cptest-core-ue2-auto-gitops-gha + terraform-state-table: cptest-core-ue2-auto-gitops + terraform-version: 1.65.0 ``` - ## Requirements -This action has the requirements as [Github Actions](/integrations/github-actions/). Use the same S3 Bucket, DynamoDB table, IAM Roles and config described there. +This GitHub Action depends on a few resources: +* **S3 bucket** for storing planfiles +* **DynamoDB table** for retrieving metadata about planfiles +* **2x IAM roles** for "planning" and accessing the "state" bucket + +### S3 Bucket + +This action can use any S3 Bucket to keep track of your planfiles. Just ensure the bucket is properly locked down since planfiles may contain secrets. + +For example, [vendor in](/core-concepts/vendor/component-manifest) the [`s3-component`](https://docs.cloudposse.com/components/library/aws/s3-bucket/), then using an [Atmos stack configuration](/core-concepts/stacks/), define a bucket using the [`s3-bucket` component](https://github.com/cloudposse/terraform-aws-components/tree/main/modules/s3-bucket) with this catalog configuration: + +```yaml +import: + - catalog/s3-bucket/defaults + +components: + terraform: + # S3 Bucket for storing Terraform Plans + gitops/s3-bucket: + metadata: + component: s3-bucket + inherits: + - s3-bucket/defaults + vars: + name: gitops-plan-storage + allow_encrypted_uploads_only: false +``` + + +Assign this S3 Bucket ARN to the `terraform-plan-bucket` input. + +### DynamoDB Table + +Similarly, a simple DynamoDB table can be provisioned using our [`dynamodb` component](https://docs.cloudposse.com/components/library/aws/dynamodb/). Set the **Hash Key** and create a **Global Secondary Index** as follows: + +```yaml +import: + - catalog/dynamodb/defaults + +components: + terraform: + # DynamoDB table used to store metadata for Terraform Plans + gitops/dynamodb: + metadata: + component: dynamodb + inherits: + - dynamodb/defaults + vars: + name: gitops-plan-storage + # This key (case-sensitive) is required for the cloudposse/github-action-terraform-plan-storage action + hash_key: id + range_key: "" + # Only these 2 attributes are required for creating the GSI, + # but there will be several other attributes on the table itself + dynamodb_attributes: + - name: 'createdAt' + type: 'S' + - name: 'pr' + type: 'N' + # This GSI is used to Query the latest plan file for a given PR. + global_secondary_index_map: + - name: pr-createdAt-index + hash_key: pr + range_key: createdAt + projection_type: ALL + non_key_attributes: [] + read_capacity: null + write_capacity: null + # Auto delete old entries + ttl_enabled: true + ttl_attribute: ttl +``` + +Pass the ARN of this table as the input to the `terraform-plan-table` of the [`cloudposse/github-action-atmos-terraform-plan`](https://github.com/cloudposse/github-action-atmos-terraform-plan) GitHub Action. + +### IAM Access Roles + +First create an access role for storing and retrieving planfiles from the S3 Bucket and DynamoDB table. We deploy this role using the [`gitops` component](https://docs.cloudposse.com/components/library/aws/gitops/). Assign this role ARN to the `terraform-state-role` input. + +Next, create a role for GitHub workflows to use to plan and apply Terraform. We typically create an "AWS Team" with our [`aws-teams` component](https://docs.cloudposse.com/components/library/aws/aws-teams/), and then allow this team to assume `terraform` in the delegated accounts with our [`aws-team-roles` component](https://docs.cloudposse.com/components/library/aws/aws-team-roles/). Assign this role ARN to the `terraform-plan-role` input diff --git a/website/docs/integrations/github-actions/component-updater.mdx b/website/docs/integrations/github-actions/component-updater.mdx index 2a18bd3ac..5edd2b0ed 100644 --- a/website/docs/integrations/github-actions/component-updater.mdx +++ b/website/docs/integrations/github-actions/component-updater.mdx @@ -2,15 +2,19 @@ title: Component Updater sidebar_position: 20 sidebar_label: Component Updater +description: Easily update your vendored components with Pull Requests --- - import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import Admonition from '@theme/Admonition'; -**Efficient Automation for Component Updates** + +Keep your infrastructure repositories current with the latest versions of [vendored components](/core-concepts/vendor) using the [Atmos Component Updater GitHub Action](https://github.com/cloudposse/github-action-atmos-component-updater). This powerful action simplifies and accelerates the management of component updates across repositories by using pull requests, ensuring that updates are processed quickly, accurately, and without hassle. + Use Cloud Posse's GitHub Action for updating [Atmos components](/core-concepts/components/) (e.g. [like the ones provided by Cloud Posse](https://github.com/cloudposse/terraform-aws-components/)) to streamline your infrastructure management. -Keep your infrastructure repositories current with the latest versions of components using the [Cloud Posse GitHub Actions for Updating Atmos Components](https://github.com/cloudposse/github-action-atmos-component-updater). This powerful action simplifies and accelerates the management of component updates using pull requests, ensuring that updates are processed quickly, accurately, and without hassle. + With its customizable features, you can design an automated workflow tailored to your needs, making infrastructure repository maintenance more efficient and less error-prone. @@ -112,12 +116,9 @@ You may notice that we pass a generated token from a GitHub App to `github-acces 1. Create a new GitHub App 2. Name this new app whatever you prefer. For example, `Atmos Component Updater []`. - -:::tip GitHub Requires Unique App Names - -GitHub requires all GitHub Apps to have unique names. The name you select for this GitHub App can be whatever you'd prefer. For example, an `acme` organization might name their GitHub App `Atmos Component Updater [ACME]`. - -::: + + GitHub requires all GitHub Apps to have globally unique names. The name you select for this GitHub App can be whatever you'd prefer, so long as it's not already in use. For example, an `acme` organization might name their GitHub App `Atmos Component Updater [ACME]`. + 3. List a Homepage URL of your choosing. This is required by GitHub, but you can use any URL. For example use our documentation page: `https://atmos.tools/integrations/github-actions/component-updater/` 4. (Optional) Add an icon for your new app (See below) diff --git a/website/docs/integrations/github-actions/github-actions.mdx b/website/docs/integrations/github-actions/github-actions.mdx index 80b23c533..1fc6b333a 100644 --- a/website/docs/integrations/github-actions/github-actions.mdx +++ b/website/docs/integrations/github-actions/github-actions.mdx @@ -1,36 +1,30 @@ --- title: GitHub Actions sidebar_position: 1 -sidebar_label: GitHub Actions -description: GitHub Actions. +sidebar_label: GitHub Actions 🚀 +description: Use GitHub Actions with Atmos id: gitHub-actions --- +import File from '@site/src/components/File' +import DocCardList from '@theme/DocCardList' +import Intro from '@site/src/components/Intro' +import PrimaryCTA from '@site/src/components/PrimaryCTA' -import File from '@site/src/components/File'; -import DocCardList from "@theme/DocCardList"; + +GitHub Actions are a powerful way to automate your workflows with Atmos. Use these actions to plan, apply, and manage your Terraform infrastructure with Atmos. + -# GitHub Actions +This collection of GitHub Actions is designed to work specifically with Atmos in an opinionated manner, enabling you to implement a modern change management system entirely within the native GitHub UI. These Actions use the standard [`atmos.yaml` configuration](/cli/configuration/#integrations) and [some backing services](#requirements) designed to properly manage Terraform plan files, including their invalidation. -:::tip Important! +These GitHub Actions stribe to be cloud-agnostic; however, most of our instructions focus on AWS, where we predominantly use them. None of these actions require hardcoded credentials, and all work using GitHub OIDC and GitHub Apps managed by your organization. These Actions do not require any subscriptions and are based entirely on open source. -**Please note!** GitHub Actions versions usage depends of the Atmos versions. Please follow this table - - -::: - -| Github action | Atmos `< 1.63.0` | Atmos `>= 1.63.0` | -|------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| -| [`github-action-atmos-affected-stacks`](https://github.com/cloudposse/github-action-atmos-affected-stacks) | [`v2`](https://github.com/cloudposse/github-action-atmos-affected-stacks/tree/v2) | [`v1`](https://github.com/cloudposse/github-action-atmos-affected-stacks/tree/v1) | -| [`github-action-atmos-terraform-plan`](https://github.com/cloudposse/github-action-atmos-terraform-plan) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-plan/tree/v1) | [`v2`](https://github.com/cloudposse/github-action-atmos-terraform-plan/tree/v2) | -| [`github-action-atmos-terraform-apply`](https://github.com/cloudposse/github-action-atmos-terraform-apply) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-apply/tree/v1) | [`v2`](https://github.com/cloudposse/github-action-atmos-terraform-apply/tree/v2) | -| [`github-action-atmos-terraform-drift-remediation`](https://github.com/cloudposse/github-action-atmos-terraform-drift-remediation) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-drift-remediation/tree/v1) | [`v2`](https://github.com/cloudposse/github-action-atmos-terraform-drift-remediation/tree/v2) | -| [`github-action-atmos-terraform-drift-detection`](https://github.com/cloudposse/github-action-atmos-terraform-drift-detection) | [`v0`](https://github.com/cloudposse/github-action-atmos-terraform-drift-detection/tree/v0) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-drift-detection/tree/v1) | +## GitHub Actions for Atmos ## Requirements -This GitHub Action depends on a few resources: +GitHub Actions that utilize "plan file" storage depends on a few resources: * **S3 bucket** for storing planfiles * **DynamoDB table** for retrieving metadata about planfiles * **2x IAM roles** for "planning" and accessing the "state" bucket @@ -40,7 +34,7 @@ This GitHub Action depends on a few resources: This action can use any S3 Bucket to keep track of your planfiles. Just ensure the bucket is properly locked down since planfiles may contain secrets. -For example, [vendor in](/core-concepts/components/vendoring) the [`s3-component`](https://docs.cloudposse.com/components/library/aws/s3-bucket/), then using an [Atmos stack configuration](/core-concepts/stacks/), define a bucket using the [`s3-bucket` component](https://github.com/cloudposse/terraform-aws-components/tree/main/modules/s3-bucket) with this catalog configuration: +For example, [vendor in](/core-concepts/vendor) the [`s3-component`](https://docs.cloudposse.com/components/library/aws/s3-bucket/), then using an [Atmos stack configuration](/core-concepts/stacks/), define a bucket using the [`s3-bucket` component](https://github.com/cloudposse/terraform-aws-components/tree/main/modules/s3-bucket) with this catalog configuration: ```yaml @@ -144,3 +138,21 @@ integrations: For actions that use atmos `< 1.63.0` the settings passed as github action inputs. Please follow documentation for each action to see the required inputs. + +## Compatibility Matrix + +:::important Important! + +Our GitHub Actions depend on specific versions of Atmos. + +Please refer to the table below. + +::: + +| Github action | Atmos `< 1.63.0` | Atmos `>= 1.63.0` | +|------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| +| [`github-action-atmos-affected-stacks`](https://github.com/cloudposse/github-action-atmos-affected-stacks) | [`v2`](https://github.com/cloudposse/github-action-atmos-affected-stacks/tree/v2) | [`v1`](https://github.com/cloudposse/github-action-atmos-affected-stacks/tree/v1) | +| [`github-action-atmos-terraform-plan`](https://github.com/cloudposse/github-action-atmos-terraform-plan) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-plan/tree/v1) | [`v2`](https://github.com/cloudposse/github-action-atmos-terraform-plan/tree/v2) | +| [`github-action-atmos-terraform-apply`](https://github.com/cloudposse/github-action-atmos-terraform-apply) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-apply/tree/v1) | [`v2`](https://github.com/cloudposse/github-action-atmos-terraform-apply/tree/v2) | +| [`github-action-atmos-terraform-drift-remediation`](https://github.com/cloudposse/github-action-atmos-terraform-drift-remediation) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-drift-remediation/tree/v1) | [`v2`](https://github.com/cloudposse/github-action-atmos-terraform-drift-remediation/tree/v2) | +| [`github-action-atmos-terraform-drift-detection`](https://github.com/cloudposse/github-action-atmos-terraform-drift-detection) | [`v0`](https://github.com/cloudposse/github-action-atmos-terraform-drift-detection/tree/v0) | [`v1`](https://github.com/cloudposse/github-action-atmos-terraform-drift-detection/tree/v1) | diff --git a/website/docs/integrations/github-actions/setup-atmos.mdx b/website/docs/integrations/github-actions/setup-atmos.mdx index c225615b7..6a0934d48 100644 --- a/website/docs/integrations/github-actions/setup-atmos.mdx +++ b/website/docs/integrations/github-actions/setup-atmos.mdx @@ -2,13 +2,16 @@ title: Setup Atmos sidebar_position: 10 sidebar_label: Setup Atmos +description: Install Atmos in your GitHub Action workflows --- - import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' -The Cloud Posse GitHub Action to "Setup Atmos" simplifies your GitHub Action Workflows. + +The Cloud Posse GitHub Action to “Setup Atmos” makes it easy to run atmos in your GitHub Action workflows by installing Atmos. + -Easily integrate Atmos into your GitHub Action workflows using [`github-action-setup-atmos`](https://github.com/cloudposse/github-action-setup-atmos). To simplify your workflows, we offer a [GitHub Action](https://github.com/cloudposse/github-action-setup-atmos) that streamlines the process of [installing Atmos](/quick-start/install-atmos). +Easily integrate Atmos into your GitHub Action workflows using [`github-action-setup-atmos`](https://github.com/cloudposse/github-action-setup-atmos). To simplify your workflows, we offer a [GitHub Action](https://github.com/cloudposse/github-action-setup-atmos) that streamlines the process of [installing Atmos](/install). We provide a [GitHub Action](https://github.com/cloudposse/github-action-setup-atmos) to make that easier for CI/CD applications. diff --git a/website/docs/integrations/integrations.mdx b/website/docs/integrations/integrations.mdx index a56884425..40c074d71 100644 --- a/website/docs/integrations/integrations.mdx +++ b/website/docs/integrations/integrations.mdx @@ -1,18 +1,11 @@ --- -title: Integrations -sidebar_position: 6 -sidebar_label: Integrations -description: Atmos supports many native Atmos integrations. They extend the core functionality of Atmos. +title: Infrastructure CI/CD (GitOps) +sidebar_position: 8 +sidebar_label: CI/CD Integrations +sidebar_class_name: hidden +description: Natively supported CI/CD integrations in Atmos id: integrations --- - -# Integrations - -Atmos supports many native Atmos integrations. They extend the core functionality of Atmos. - -
- - -import DocCardList from "@theme/DocCardList"; +import DocCardList from '@theme/DocCardList' diff --git a/website/docs/integrations/spacelift.md b/website/docs/integrations/spacelift.mdx similarity index 91% rename from website/docs/integrations/spacelift.md rename to website/docs/integrations/spacelift.mdx index 329a45a09..77d2035cb 100644 --- a/website/docs/integrations/spacelift.md +++ b/website/docs/integrations/spacelift.mdx @@ -3,10 +3,11 @@ title: Spacelift Integration sidebar_position: 6 sidebar_label: Spacelift --- +import Intro from '@site/src/components/Intro' -Atmos natively supports [Spacelift](https://spacelift.io). This is accomplished using -the [`cloudposse/terraform-spacelift-cloud-infrastructure-automation`](https://github.com/cloudposse/terraform-spacelift-cloud-infrastructure-automation) -terraform module that reads the YAML Stack configurations and produces the Spacelift resources. + +Atmos natively supports [Spacelift](https://spacelift.io). This is accomplished using this [terraform module](https://github.com/cloudposse/terraform-spacelift-cloud-infrastructure-automation) that reads the YAML Stack configurations and provisions the Spacelift resources. + Cloud Posse provides two terraform components for Spacelift support: @@ -58,8 +59,6 @@ components: - trigger-administrative-policy ``` -
- ## OpenTofu Support @@ -70,11 +69,11 @@ To make OpenTofu the default, add the following to your top-level stack manifest ```yaml settings: spacelift: - # Use OpenTofu + # Use OpenTofu terraform_workflow_tool: OPEN_TOFU ``` -Similarly, to override this behavior, or to only configure it on specific components, add the following to the component +Similarly, to override this behavior, or to only configure it on specific components, add the following to the component configuration: ```yaml @@ -87,7 +86,7 @@ components: terraform_workflow_tool: OPEN_TOFU ``` -For more details on [Atmos support for OpenTofu](/integrations/opentofu) see our integration page. +For more details on [Atmos support for OpenTofu](/core-concepts/projects/configuration/opentofu) see our integration page. ## Spacelift Stack Dependencies @@ -107,8 +106,6 @@ Each object in the `settings.depends_on` section has the following schema: - `environment` (optional) - the `environment` where the Atmos component is provisioned - `stage` (optional) - the `stage` where the Atmos component is provisioned -
- The `component` attribute is required. The rest are the context variables and are used to define Atmos stacks other than the current stack. For example, you can specify: @@ -118,8 +115,6 @@ For example, you can specify: - `stage` if the `component` is from a different account - `tenant`, `environment` and `stage` if the component is from a different Atmos stack (e.g. `tenant1-ue2-dev`) -
- In the following example, we specify that the `top-level-component1` component depends on the following: - The `test/test-component-override` component in the same Atmos stack @@ -152,8 +147,6 @@ components: enabled: true ``` -
- :::tip Refer to [`atmos describe dependents` CLI command](/cli/commands/describe/dependents) for more information. diff --git a/website/docs/introduction/faq.mdx b/website/docs/introduction/faq.mdx index e37158415..14a0b7d4d 100644 --- a/website/docs/introduction/faq.mdx +++ b/website/docs/introduction/faq.mdx @@ -2,13 +2,10 @@ slug: /faq title: Atmos FAQ sidebar_label: FAQ -sidebar_position: 3 +sidebar_position: 4 --- - - import ReactPlayer from 'react-player' - ### Why is the tool called Atmos? *Once upon a time*, in the vast expanse of cloud computing, there was a need for a tool that could orchestrate and manage the complex layers of @@ -17,9 +14,7 @@ much like a protective layer enveloping the Earth. Thus, the idea of "atmos" was of the 1986 "Aliens" movie, where [atmospheric terraformers](https://avp.fandom.com/wiki/Atmosphere_Processing_Plant) transform alien worlds into hospitable realms. - -
-But there's more to the story. As the [Cloud Posse](https://cloudposse.com) delved deeper into crafting this tool, they discovered a wonderful +But there's more to the story. As the [Cloud Posse](https://cloudposse.com) delved deeper into crafting this tool, they discovered a wonderful coincidence. "Atmos" could stand for **"Automated Terraform Management & Orchestration Software"** perfectly encapsulating its purpose and capabilities. This serendipitous acronym was a delightful surprise, further cementing the name's destiny. @@ -66,7 +61,7 @@ and offers an easy exit strategy by [generating and committing these files](/cli #### Atmos provides prescriptive guidance on operating Terraform at scale -Furthermore, Atmos delivers prescriptive guidance on [design patterns](/design-patterns/) and [component architecture](/core-concepts/components/component-oriented-programming) for Terraform root modules, establishing itself as an opinionated framework designed to enhance Terraform's capabilities. It offers [advanced features](/core-concepts/components/inheritance) tailored for both straightforward and intricate deployment scenarios. Essentially acting as a comprehensive framework, Atmos is exceptionally well-suited for complex, regulated enterprise environments. Its robust support for [Stack manifests](/core-concepts/stacks) underscores its versatility as a tool, enabling precise and effortless infrastructure management and orchestration across various scales and complexities. +Furthermore, Atmos delivers prescriptive guidance on [design patterns](/design-patterns/) and [component architecture](/core-concepts/stacks/inheritance) for Terraform root modules, establishing itself as an opinionated framework designed to enhance Terraform's capabilities. It offers [advanced features](/core-concepts/stacks/inheritance) tailored for both straightforward and intricate deployment scenarios. Essentially acting as a comprehensive framework, Atmos is exceptionally well-suited for complex, regulated enterprise environments. Its robust support for [Stack manifests](/core-concepts/stacks) underscores its versatility as a tool, enabling precise and effortless infrastructure management and orchestration across various scales and complexities. ### Can Atmos be used together with Terragrunt? @@ -78,7 +73,7 @@ The key motivation for integrating Terragrunt within Atmos would be to offer a s There are a few ways to accomplish it, depending on your needs or preferences. 1. Set the default the `command` to call in the Atmos CLI Configuration for Terraform components. -2. Override the `command` in the `settings` section for each component definition in the stack configuration (this respects inheritances, so the [`mixin`](/core-concepts/stacks/mixins) pattern can be used.) +2. Override the `command` in the `settings` section for each component definition in the stack configuration (this respects inheritances, so the [`mixin`](/core-concepts/stacks/inheritance/mixins) pattern can be used.) ### What are some of the alternatives to Atmos? diff --git a/website/docs/introduction/features.md b/website/docs/introduction/features.mdx similarity index 82% rename from website/docs/introduction/features.md rename to website/docs/introduction/features.mdx index 5b3da6643..68f982f61 100644 --- a/website/docs/introduction/features.md +++ b/website/docs/introduction/features.mdx @@ -2,13 +2,15 @@ slug: /features title: Atmos Features sidebar_label: Features -sidebar_position: 1 +sidebar_position: 2 --- +import Intro from '@site/src/components/Intro' -Atmos streamlines Terraform orchestration, environment, and configuration management, offering developers and DevOps a set of -powerful tools to tackle deployment challenges. Designed to be cloud agnostic, it enables you to operate consistently across -various cloud platforms. These features boost efficiency, clarity, and control across various environments, making it an -indispensable asset for managing complex infrastructures with confidence. + +Atmos streamlines Terraform orchestration, environment, and configuration management, offering developers and DevOps a framework and a set of powerful tools to tackle deployment challenges. + + +Designed to be cloud agnostic, it enables you to operate consistently across various cloud platforms. These features boost efficiency, clarity, and control across various environments, making it an indispensable asset for managing complex infrastructures with confidence. ### Core Features - **Terminal UI** Polished interface for easier interaction with Terraform, workflows, and commands. diff --git a/website/docs/introduction/index.mdx b/website/docs/introduction/index.mdx index c26a38d6f..089bf17f4 100644 --- a/website/docs/introduction/index.mdx +++ b/website/docs/introduction/index.mdx @@ -5,33 +5,37 @@ label: Introduction sidebar_label: Introduction sidebar_position: 1 keywords: [atmos, terraform, helmfile, introduction] -title: Automated Terraform Management & Orchestration Software (ATMOS) +title: Getting Started with Atmos description: >- - Atmos is the Ultimate Terraform Environment Configuration and Orchestration Tool for DevOps to manage complex configurations with ease. + Atmos is a Component Oriented Framework and Orchestration Tool for DevOps that makes it easy to automate Terraform Environments and manage complex configurations with ease. It's compatible with Terraform and many other tools. --- - import ReactPlayer from 'react-player' import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + +

Atmos is a cloud architecture framework for native Terraform.

+ + +Use Atmos to break your architecture into reusable [Components](/core-concepts/components) that you implement using [Terraform "root modules"](/core-concepts/components/terraform). Then, tie everything together using [Stack](/core-concepts/stacks) configurations defined in YAML. + +If you're familiar with mainstream programming frameworks, then you'll feel right at home with Atmos. It's a cloud-agnostic framework for managing your cloud infrastructure using native Terraform. You'll benefit from a [well-organized project layout](/core-concepts/projects), [best practices](/best-practices/), [design patterns](/design-patterns/), and a [supportive community](/community) ready to help. -Use Atmos to easily compose complex architectures based on Terraform with very [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) configuration. -Concepts like [Stacks](/core-concepts/stacks) and [Components](/core-concepts/components) -help you overcome most of [Terraform's limitations](/reference/terraform-limitations/) -by using [established conventions](/core-concepts) and proven [design patterns](/design-patterns/). +If you're [new to Terraform or struggling to manage your infrastructure at scale](/introduction/why-atmos), then [Atmos is you](/introduction/why-atmos/nirvana). It's been [proven to work for countless venture-backed startups and enterprises](https://cloudposse.com), and we're confident it will work for you too. #### Are you tired of doing Terraform the old way? Try the new way. - Get Started + Try Quick Start - Live Demo + Learn Atmos @@ -42,20 +46,18 @@ an interactive UI in the terminal. Use the arrow keys to select stacks and compo ![Atmos Screenshot](../../../docs/demo.gif) -
- In Atmos, you can easily search and navigate your configuration from the built-in UI. ![`atmos` CLI command example 2](/img/cli/atmos/atmos-cli-command-1.png) ## Introduction -With Atmos, you gain simplified control over your cloud resources, enabling you to manage unlimited environments, services, -and configurations using simple, clear YAML configuration files. Best of all, it works without writing a single line of HCL or code generation. +With Atmos, you gain simplified control over your cloud resources, enabling you to manage unlimited environments, services, +and configurations using simple, clear YAML configuration files. Best of all, it works without writing a single line of HCL or code generation. This approach not only ensures that your infrastructure's deployment and scaling are as straightforward as executing a single command, but also cleanly separates your configuration from your Terraform code keeping it portable, thereby streamlining the entire process. -Designed to operate seamlessly across diverse environments—be it production, staging, development, or testing — Atmos integrates +Designed to operate seamlessly across diverse environments—be it production, staging, development, or testing — Atmos integrates perfectly into continuous integration (CI/CD) workflows with its [GitHub Actions](/integrations/github-actions/) or support for other [TACOS](/integrations/). It offers a comprehensive set of commands for managing the lifecycle of your cloud infrastructure, from creation to maintenance and beyond. @@ -70,18 +72,18 @@ operational mastery and innovation faster, transforming their infrastructure man At a high-level, Atmos is responsible for managing the configuration that gets passed to [Components](/terms/component) when they are instantiated. To make this less abstract, we're going to focus on Terraform and how configuration gets passed to it. -The secret to scaling architectures with Terraform, is to decompose it into smaller root modules. We want to keep these root modules -as generic and reusable as possible by parameterizing them. In doing so, we shift the complexity from the HCL code, to managing -the configuration itself. In terraform, there is the concept of variable files (aka "var files"), -which are JSON-esque configuration files and how external configuration is passed to `terraform plan` using -the [`-var-file` argument](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files). +The secret to scaling architectures with Terraform, is to decompose it into smaller root modules. We want to keep these root modules +as generic and reusable as possible by parameterizing them. In doing so, we shift the complexity from the HCL code to managing +the configuration itself. In terraform, there is the concept of variable files (aka "var files"), +which are JSON-esque configuration files and how external configuration is passed to `terraform plan` using +the [`-var-file` argument](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files). All we need to do is tap into this power, and pass our own configuration that comes from Atmos. -With Atmos, we organize our configuration into [Stacks](/core-concepts/stacks). Stacks are YAML manifests that compose all the +With Atmos, we organize our configuration into [Stacks](/core-concepts/stacks). Stacks are YAML manifests that compose all the [Components](/core-concepts/components) (e.g. Terraform root modules) we need to bring up our environment. For example, in its -simplest form, we may have `production`, `dev`, and `staging` stacks. We can then deploy any of these stacks to provision -everything using Terraform. All that Atmos does, is deep-merge the variables from the stack configurations and produce a single "var file" -that we pass to the `terraform plan`. There's very little magic, which is how to ensure future compatibility with Terraform and +simplest form, we may have `production`, `dev`, and `staging` stacks. We can then deploy any of these stacks to provision +everything using Terraform. All that Atmos does is deep-merge the variables from the stack configurations and produce a single "var file" +that we pass to the `terraform plan`. There's very little magic, which is how to ensure future compatibility with Terraform and interoperability with the entire Terraform ecosystem. :::info Summary @@ -134,7 +136,7 @@ downloaded hundreds of millions of times. :::tip Become a part of our Movement -We encourage you to become a part of our movement and make a significant impact on the industry as a whole. +We encourage you to become a part of our movement and make a significant impact on the industry as a whole. Join us on [Slack](https://slack.cloudposse.com/) or tune-in on our [Weekly "DevOps" Office Hours](https://cloudposse.com/office-hours/) ::: @@ -165,12 +167,10 @@ It might help to also understand what Atmos is not attempting to replace: Here's a live demo we did on [our weekly "Office Hours"](https://cloudposse.com/office-hours/). -
- ## How do we make money? -[Cloud Posse](https://cloudposse.com/) sells [reference architectures for AWS](https://cloudposse.com/services/) that are based on Atmos and Terraform. -Our typical customers are Funded Startups and Enterprises that want to leverage AWS together with platforms +[Cloud Posse](https://cloudposse.com/) sells [reference architectures for AWS](https://cloudposse.com/services/) that are based on Atmos and Terraform. +Our typical customers are Funded Startups and Enterprises that want to leverage AWS together with platforms like GitHub, GitHub Actions, Datadog, OpsGenie, Okta, etc. ## Next Steps diff --git a/website/docs/introduction/use-cases.md b/website/docs/introduction/use-cases.mdx similarity index 72% rename from website/docs/introduction/use-cases.md rename to website/docs/introduction/use-cases.mdx index 54a9f840c..49618307c 100644 --- a/website/docs/introduction/use-cases.md +++ b/website/docs/introduction/use-cases.mdx @@ -3,20 +3,21 @@ title: Atmos Use-Cases id: use-cases slug: /use-cases sidebar_label: Use-cases -sidebar_position: 2 +sidebar_position: 3 --- +import Intro from '@site/src/components/Intro' -Atmos has consistently demonstrated its effectiveness in addressing these key use-cases, showcasing its adaptability and -strength in the cloud infrastructure and DevOps domains: + +Atmos has proven time and again that it works great for these key use cases. It’s versatile like a Swiss Army knife and reliable like a well-oiled machine, making it a solid choice for cloud infrastructure and DevOps. + -- **Managing Large Multi-Account Cloud Environments.**
Suitable for organizations using multiple cloud accounts to separate different - projects or stages of development. +- **Managing Large Multi-Account Cloud Environments.**
Suitable for organizations using multiple cloud accounts to separate different projects or stages of development. - **Cross-Platform Cloud Architectures.**
Ideal for businesses that need to manage the configuration of services across AWS, GCP, Azure, etc., to build a cohesive system. - **Multi-Tenant Systems for SaaS.**
Perfect for SaaS companies looking to host multiple customers within a unified infrastructure. Simply define a baseline tenant configuration once, and then seamlessly onboard new tenants by reusing this baseline through pure configuration, bypassing the need for further code development. -- **Efficient Multi-Region Deployments.**
Atmos facilitates streamlined multi-region deployments by enabling businesses to define baseline configurations with [stacks](/core-concepts/stacks/) and extend them across regions with DRY principles through [imports](/core-concepts/stacks/imports) and [inheritance](/core-concepts/components/inheritance). -- **Compliant Infrastructure for Regulated Industries.**
Atmos empowers DevOps and SecOps teams to create vetted configurations that comply with SOC2, HIPAA, HITRUST, PCI, and other regulatory standards. These configurations can then be efficiently shared and reused across the organization via [service catalogs](/core-concepts/stacks/catalogs), [component libraries](/core-concepts/components/library), [vendoring](/core-concepts/vendoring), and [OPA policies](/core-concepts/components/validation), simplifying the process of achieving and maintaining rigorous compliance. +- **Efficient Multi-Region Deployments.**
Atmos facilitates streamlined multi-region deployments by enabling businesses to define baseline configurations with [stacks](/core-concepts/stacks/) and extend them across regions with DRY principles through [imports](/core-concepts/stacks/imports) and [inheritance](/core-concepts/stacks/inheritance). +- **Compliant Infrastructure for Regulated Industries.**
Atmos empowers DevOps and SecOps teams to create vetted configurations that comply with SOC2, HIPAA, HITRUST, PCI, and other regulatory standards. These configurations can then be efficiently shared and reused across the organization via [service catalogs](/core-concepts/stacks/catalogs), [component libraries](/core-concepts/components/library), [vendoring](/core-concepts/vendor), and [OPA policies](/core-concepts/validate/opa), simplifying the process of achieving and maintaining rigorous compliance. - **Empowering Teams with Self-Service Infrastructure.**
Allows teams to manage their infrastructure needs independently, using predefined templates and policies. - **Streamlining Deployment with Service Catalogs, Landing Zones, and Blueprints:** Provides businesses the ability to craft their own ready-to-use templates and guidelines for setting up cloud environments quickly and consistently, tailored to the unique needs of the organization. -Don't see your use-case listed? Ask us in the [`#atmos`](https://slack.cloudposse.com) Slack channel, or [join us for "Office Hours"](https://cloudposse.com/office-hours/) every week. +Don't see your use-case listed? Ask us in the [`#atmos`](/community/slack) Slack channel, or [join us for "Office Hours"](/community/office-hours) every week. diff --git a/website/docs/introduction/why-atmos/nirvana.mdx b/website/docs/introduction/why-atmos/nirvana.mdx new file mode 100644 index 000000000..0c48735f6 --- /dev/null +++ b/website/docs/introduction/why-atmos/nirvana.mdx @@ -0,0 +1,51 @@ +--- +title: Nirvana 💫 +description: Teams who adopt Atmos have total clarity of their infrastructure. +sidebar_label: Nirvana +sidebar_position: 12 +id: nirvana +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' + + +## The Atmos Difference + +Atmos lets you model the configuration of your cloud architecture in a way that makes logical sense. +You can then develop components using any toolchain you want, including Terraform, to implement +the components of your infrastructure. + + +Most teams don’t have a Terraform problem; they struggle with modeling their architecture in a reusable manner. Terraform provides everything needed to provision infrastructure, but an effective strategy to model cloud architecture is missing. Atmos fills this gap with a robust framework, offering design patterns, best practices, and advanced tooling to optimize your cloud architecture. + +**A well-designed framework does not limit you; it enables you. It doesn’t hold you back; it empowers you.** + +## The Benefits of Using Atmos + +Atmos provides a lightweight framework around Terraform, making it easier to manage and deploy your infrastructure +across cloud platforms. It leverages vanilla Terraform for all its strengths, ensuring you can harness the full power +of Terraform. Additionally, with Atmos, you no longer need to rely on code generation or templating HCL. + +You'll have a clear separation of concerns, consistent conventions, and organized project structures. + +Configuration is organized into stacks defined by YAML and separate from components (terraform root modules). +This ensures root modules remain highly reusable across teams and promotes testing. + +It was designed to be used with CI/CD, so you can integrate with [GitHub Actions](https://atmos.tools/integrations/github-actions), [Spacelift](https://atmos.tools/integrations/spacelift), or even [Atlantis](https://atmos.tools/integrations/atlantis). + +And it was [inspired by giants](/reference/alternatives). We took the best of what we learned from all these other tools stuck into Atmos. So if you like the concepts of imports, inheritance, layering, and composition, you'll love Atmos. + +Oh yes, and it's entirely free and truly Open Source (licensed APACHE2) like [everything else Cloud Posse builds](https://github.com/cloudposse)! 🔥 + + + Now that we're all on the same page, start your first Atmos project in 30 minutes! + + Try out our Simple Quick Start or delve deeper into the syntax and concepts used by Atmos. +
+ Try our Simple Tutorial + Learn Atmos Concepts +
+
diff --git a/website/docs/introduction/why-atmos/stage-0.mdx b/website/docs/introduction/why-atmos/stage-0.mdx new file mode 100644 index 000000000..92eb9f649 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-0.mdx @@ -0,0 +1,44 @@ +--- +title: "Stage 0: ClickOps" +description: All infrastructure is manually provisioned using web interfaces. +sidebar_label: "Stage 0: ClickOps" +sidebar_position: 1 +id: stage-0 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +ClickOps is the "art" of provisioning or setting up your infrastructure using the _click_ of the mouse, +aimed at the web console of your chosen cloud provider. + + +Think of ClickOps as the sketching phase of designing your cloud infrastructure — it’s a way to quickly +and visually design how your setup should look without investing the time to codify it as formal blueprints. +Initially, ClickOps is often the fastest way to get up and running, allowing you to understand your infrastructure +through hands-on experimentation. + +However, just as sketches aren’t used to construct buildings, you need blueprints for a successful, repeatable implementation. +These blueprints ensure that any team member can reproduce the setup accurately. Although, sometimes ClickOps is unavoidable +because the underlying APIs aren’t available, or a Terraform resource isn’t available by a provider; most of the time, +infrastructure can and should be codified. + +:::warning New Problems +1. No consistency or reproducibility +2. Repetitive error-prone work +3. No history of changes +::: + +The biggest problem with ClickOps is reproducibility. No self-respecting engineer enjoys repetitive work and visually comparing +two configurations or spot-checking two environments side-by-side in the web console. These issues disappear when you adopt infrastructure as code (IaC). IaC provides the blueprints for consistent, automated, and scalable infrastructure management, +eliminating the pitfalls of manual, repetitive ClickOps processes. + +## Realization + +So developers [begin their journey with Terraform](/introduction/why-atmos/stage-1), a tool that allows them to define their infrastructure as code, + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-1.mdx b/website/docs/introduction/why-atmos/stage-1.mdx new file mode 100644 index 000000000..a05df11e9 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-1.mdx @@ -0,0 +1,38 @@ +--- +title: "Stage 1: Introduction to Terraform" +description: Exploration into Terraform begins with a simple example. +sidebar_label: "Stage 1: Hello World!" +sidebar_position: 2 +id: stage-1 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +At this initial stage, developers begin their Terraform journey with the basics, focusing on getting a grasp of Terraform's +core concepts with a straightforward and simple implementation. + + +1. Developers roll up their sleeves to get a simple terraform example up and running. They create resources directly in the + configuration without the use of modules. This phase is characterized by hard-coded settings and a hands-on approach to learning + Terraform's syntax and capabilities. +2. Local state files are used since this is just an exploration. This approach simplifies the learning process by avoiding the complexities of remote state management. +3. Version control systems are not yet in use. Developers store their Terraform configurations directly on their local workstations + allowing them to focus on learning Terraform's mechanics without the added complexity of collaboration tools or best practices. + +:::warning New Problems +1. How do we handle secrets? +2. Where do we store the state file? +3. How do we maintain something with so many hardcoded settings? +::: + +## Realization + +With this quick win, developers realize Terraform's power, so they are eager to [Terraform everything in sight](/introduction/why-atmos/stage-2). + + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-10.mdx b/website/docs/introduction/why-atmos/stage-10.mdx new file mode 100644 index 000000000..d3f6caa2c --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-10.mdx @@ -0,0 +1,66 @@ +--- +title: "Stage 10: Terraform Bankruptcy 💥" +description: Teams start looking for alternatives out of frustration. +sidebar_label: "Stage 10: Terraform Bankruptcy" +sidebar_position: 11 +id: stage-10 +--- +import Link from '@docusaurus/Link' +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' +import Definition from '@site/src/components/Definition' + + +At this point, developers might be ready to throw in the towel on Terraform. +They question the hype and wonder if it's all worth it. + +They might even start looking for alternatives like [CDK](https://aws.amazon.com/cdk/), +[CDK TF](https://developer.hashicorp.com/terraform/cdktf), [Pulumi](https://www.pulumi.com/), +or platforms like [Crossplane](https://www.crossplane.io/). + + + +As the complexity and scale of Terraform projects reach a tipping point, developers face a stark realization. +This wasn't easy. Questions arise about the inherent difficulties of managing sprawling infrastructure code bases +using Terraform, leading to a moment of reckoning. Some might question if Terraform is still the right tool for them. + +:::danger + +- Scripts all over the place that call Terraform +- No clear separation of concerns +- Inconsistent conventions, or a total lack of conventionss +- Disorganized project structures +- Interdependencies that complicate deployment processes +- Unsafe CI/CD practices and hardcoded credentials +- Incomplete or out-of-date documentation +- **No one understands how it all works anymore ⚠️** + +::: + +## But the problem isn't Terraform. + +**The problem is how they are using Terraform.** + +Changing the tool, will not change the outcome. Even if they decide to switch to a different tool, +they will face the same challenges, just with a different set of limitations. + +Terraform is not a framework. It's a tool. One that can be used by a framework. Just as Docker is not Kubernetes. + +What developers _really_ need is a coherent strategy with some rigor for approaching cloud architecture that translates to +how they manage the configuration and design all the components that comprise their infrastructure. + +It's not a surprise that teams fail with Terraform. Most developers never get the opportunity to write their own framework from scratch; +Instead, they use one that is well-established and proven by countless enterprises and supported by a community. +So why should we expect DevOps teams to be equipped and prepared to design an extensible framework when they’ve never done it before? + +## Realization + +After a little bit of Googling, searching Reddit and asking around, they then [stumble upon Atmos](/introduction/why-atmos/nirvana). A framework that will make their lives easier. + + + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-2.mdx b/website/docs/introduction/why-atmos/stage-2.mdx new file mode 100644 index 000000000..79b8a8a29 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-2.mdx @@ -0,0 +1,45 @@ +--- +title: "Stage 2: The Monolithic Root Module" +description: Terraform code expands into a monolithic root module. +sidebar_label: "Stage 2: Write Terraliths" +sidebar_position: 3 +id: stage-2 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +As developers grow more comfortable with Terraform, they often transition to a more ambitious approach of automating everything. This results in creating a monolithic "root module," also known as a [Terralith](/terms/terralith). + + +This stage is characterized by an expansive, +all-encompassing Terraform configuration that attempts to manage every aspect of the infrastructure within a single module. + +1. Developers begin by composing a single root module that continuously expands. +2. Define all environments as code (dev, staging, production) within the single Terraform root module. +3. Extensive use of feature flags for everything (e.g. `prod_cluster_size`, `staging_cluster_size`, etc.) + +:::warning New Problems +1. Massive blast radius for every change +2. Brittle and prolonged plan/apply cycles +3. Large root modules become more complicated +4. Far from DRY with significant code duplication +5. Testing every parameter combination is impossible +6. No practical way to separate responsibilities +::: + +After a while, it becomes scary to apply the changes because, literally, anything can go wrong. Deployments are often interrupted by transient errors, +expiring credentials, and API rate limits that require frequent and manual retries. To get around these problems or as a workaround +for cycles, developers perform targeted applies (e.g. `terraform apply -target`), which is an anti-pattern. +Unfortunately, it will take developers a few more stages of toil [to realize the inefficiencies of this approach (stage 5)](/introduction/why-atmos/stage-5). + +## Realization + +When developers first started using Terraform, they didn’t appreciate the purpose behind modules. +Everything seemed easy enough; just using plain resources worked. However, as the codebase grew, the need for structure and organization became clear. Now, it all makes sense, and developers commit to writing [everything new as a module](/introduction/why-atmos/stage-3). + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-3.mdx b/website/docs/introduction/why-atmos/stage-3.mdx new file mode 100644 index 000000000..bb6b00042 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-3.mdx @@ -0,0 +1,38 @@ +--- +title: "Stage 4: Move Towards Modularization" +description: In-house modules are created to avoid code duplication. +sidebar_label: "Stage 3: Reinvent the Wheel" +sidebar_position: 4 +id: stage-3 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +As developers dive deeper into Terraform's capabilities, they begin to recognize the inefficiencies of their initial approaches. +The move towards modularization represents a significant leap in managing infrastructure as code more effectively. + + +1. Developers realize that a lot of code is getting copied and pasted, so they advance to writing modules to avoid duplication. +2. Modules act like functions in Terraform: reusable and parameterized. They can be called multiple times and accept parameters. +3. It works well for now, and developers succeed in bringing up all the environments. It certainly beats [ClickOps](/introduction/why-atmos/stage-0). + +:::warning New Problems +1. These modules are "reusable" but usually just within the project itself and not written to be reused across the organization. +2. Many assumptions are made on specific requirements of the problem at hand, and generalizing them is not of paramount concern. +3. Lots of similar modules appear in the organization, some more maintained than others. +4. No automated tests (E.g. `terratest`). +5. Everyone is probably an Administrator. +::: + +## Realization + +As developers researched how to accomplish various tasks with Terraform while writing their modules, they came across one +of [Cloud Posse's hundreds of terraform modules](https://github.com/cloudposse). Then it dawned on them that they could +[avoid reinventing the wheel by using these modules](/introduction/why-atmos/stage-4). + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-4.mdx b/website/docs/introduction/why-atmos/stage-4.mdx new file mode 100644 index 000000000..a059ea460 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-4.mdx @@ -0,0 +1,38 @@ +--- +title: "Stage 4: Adoption of Open Source Modules" +description: Open Source modules replace in-house modules. +sidebar_label: "Stage 4: Discover Open Source" +sidebar_position: 5 +id: stage-4 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +Developers begin their Terraform journey by often crafting their own modules. But as they research how to accomplish various things with Terraform, they usually stumble across one of [Cloud Posse's hundreds of terraform modules](https://github.com/cloudposse). Then it dawns on them that they could avoid reinventing the wheel by using these modules instead. + + +1. Developers, initially crafting bespoke modules, discover hundreds of freely available open-source Terraform modules. +2. With the recognition of high-quality, well-maintained open-source modules, developers start to replace their custom solutions (like VPCs and clusters) with those from the community, streamlining their infrastructure code. +3. The switch to open-source modules often leads to pull requests that dramatically reduce the complexity and lines of code, + sometimes cutting out hundreds or even thousands of lines, to the team's astonishment and delight. + +:::warning New Problems +1. Now, you need to stay up-to-date with the latest changes in the modules. +2. The scope of the monolithic "root module" is at a tipping point. +3. Code is a mishmash of different styles, naming conventions, and approaches. +::: + + +## Realization + +Developers recognize the pitfalls of having so much code one root module, especially after moving to using open source modules. + +They realize the time has come to do a refactor, [decomposing the monolithic root module into smaller, more manageable pieces](/introduction/why-atmos/stage-5). + + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-5.mdx b/website/docs/introduction/why-atmos/stage-5.mdx new file mode 100644 index 000000000..7cf97d875 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-5.mdx @@ -0,0 +1,40 @@ +--- +title: "Stage 5: Refactor Root Modules" +description: Root modules are refactored into smaller, more manageable units. +sidebar_label: "Stage 5: Refactor Root Modules" +sidebar_position: 6 +id: stage-5 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +Developers recognize the pitfalls of having all environments in one root module. After having refactored their code heavily into modules, Developers realized it was a bad idea to define dev, staging and prod, all in the same root module. Developers realize terraform gets very slow and brittle when a root module is too large. + + +1. Initiate the split of the monolithic root module into smaller, more manageable units while incorporating additional feature flags + and expanding configuration management through `.tfvars` files. +2. Move towards a structure where multiple root modules are used, each one precisely aligned with specific environments + to enhance maintainability and performance. +3. Recognize the efficiency gains and increased adaptability that came from segregating large root modules, leading to quicker + Terraform operations and easier adjustments per environment. + + +:::warning New Problems +1. Increased feature flags and configuration management using `.tfvars`. +2. Performance becomes a concern with overly large root modules. +3. Very poor reusability across the organization due to the "snowflake" nature of the root modules. +::: + +## Realization + +After refactoring to smaller "root modules", now there are some dependencies between them, including shared configurations +that were once easily passed between resources, but are now variable inputs. + +Developers hate repeating themselves, so attention shifts to [DRY Configuration](/introduction/why-atmos/stage-6). + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-6.mdx b/website/docs/introduction/why-atmos/stage-6.mdx new file mode 100644 index 000000000..10b8e8aa9 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-6.mdx @@ -0,0 +1,38 @@ +--- +title: "Stage 6: Optimize for DRY Configuration" +description: Configuration management moves to `.tfvar` files. +sidebar_label: "Stage 6: DRY Configuration" +sidebar_position: 7 +id: stage-6 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +As developers navigate the complexities of managing multiple environments, root modules, and accounts or organizations, +the focus shifts from merely defining infrastructure as code to the overarching challenge of maintaining these expansive +configurations efficiently. + + +1. With numerous environments, root modules, and accounts or organizations, the challenge shifts from defining infrastructure as code to maintaining the extensive configuration of parameters that get passed to Terraform. +2. In an effort to manage repetitive configurations, developers resort to using symlinks or other methods to link common files across projects, seeking to reduce redundancy. +3. Code Generation is adopted to overcome *perceived* limitations of Terraform (when, in fact it's often a flaw in the architecture of the project). + +:::warning New Problems +1. For every new application developed, the automatic response is to create bespoke root modules for specific needs, despite + reusing child modules, raising the question of why a new root module is necessary for each application in the first place. +2. As the number of root modules grows, the Terraform state gets divided by component. Managing these inter-component dependencies + falls outside Terraform's capabilities and needs to be solved in another way. +3. The adoption of code generation tools to address Terraform's *perceived* limitations (e.g., [inability to](https://github.com/hashicorp/terraform/issues/19932#issuecomment-1817043906) iterate over providers](https://github.com/hashicorp/terraform/issues/19932#issuecomment-1817043906)) that often can mask underlying architectural issues as well as make automated testing complicated. +::: + +## Realization + +Now with all these new configuration files and additional parameters to run Terraform, developers invest +more time in [scripting and automation](/introduction/why-atmos/stage-7) to manage these configurations. + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-7.mdx b/website/docs/introduction/why-atmos/stage-7.mdx new file mode 100644 index 000000000..f6cdf475a --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-7.mdx @@ -0,0 +1,63 @@ +--- +title: "Stage 7: Terraform Scripting" +description: Scripts automate terraform to make it easier. +sidebar_label: "Stage 7: Bash Scripts & Makefiles" +sidebar_position: 8 +id: stage-7 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +As Terraform projects grow in complexity and scale, developers seek ways to automate and streamline their workflows beyond what native Terraform commands offer. This leads to exploring scripting as a means to orchestrate Terraform operations. + + +1. The first path usually involves adopting a simple `bash` script or `Makefile` to orchestrate Terraform. This works well, up to a point (we know this because it is how we started using Terraform at Cloud Posse). +2. These scripts evolved to solve specific problems that made Terraform cumbersome as a tool. +3. Terraform scripts still run on local machines, reflecting the initial stages of development focus. + +:::warning New Problems +1. What happens in practice is every team/company using Terraform ends up building different homegrown scripts, + often then combining those with `Makefiles`, into a hodgepodge of configurations with different levels of validation. + The scripts grow in complexity and have to survive generations of developers that come and go. +2. New patterns emerge, for example, hacks that involve Jinja templates, string concatenation, symlinks, and worse... + `sed` & `awk` replacements!!! +3. Terraform is run mostly from local workstations/laptops, with no thought for how it will run in CI/CD. +::: + +## Realization + +With these scripts, they are ready to [introduce the rest of the team or company to Terraform](/introduction/why-atmos/stage-8). + +
+The Atmos Difference + +### No More Homegrown Scripts + +When you use Atmos, you eliminate the need for rampant scripting that is constantly breaking, never tested, poorly parameterized and seldom validated. Instead of relying on scripts that vary between companies and teams, Atmos provides a [purpose-built tool designed for Terraform]( /core-concepts/components/terraform). It introduces a framework that ensures all your Terraform code and configurations are consistently organized and validated, reducing sprawl and inconsistency across the enterprise. + +### Standardized Framework & Best Practices + +The issue with using scripts is the lack of a framework and standardization, leading to chaotic and inconsistent practices. +Unlike many DevOps teams that reinvent the wheel, Atmos provides a validated, thoroughly documented framework, ensuring all +your developers are on the same page. + +### Terraform Runs Natively with CI/CD + +Atmos comes with [native support for multiple CI/CD platforms](/integrations), including [GitHub Actions](/integrations/github-actions), +[Spacelift](/integrations/spacelift), and [Atlantis](/integrations/atlantis). + +This means you no longer need to run your workflows on your laptop, enabling anyone to contribute to infrastructure +just like they do with application development. + +### Stop Generating Terraform Code from Templates + +The main reason teams resort to using Jinja templates is due to perceived limitations with Terraform itself. +However, these limitations stem from the architecture, design, and use of Terraform. With Atmos, you no longer need to generate your Terraform code. Instead, you can use native Terraform code the way it was meant to be used, building more reusable and easier-to-test Terraform root modules. + + + Try Atmos! + +
diff --git a/website/docs/introduction/why-atmos/stage-8.mdx b/website/docs/introduction/why-atmos/stage-8.mdx new file mode 100644 index 000000000..2ffa87645 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-8.mdx @@ -0,0 +1,38 @@ +--- +title: "Stage 8: Team Challenges" +description: Team expands and begins to struggle with Terraform +sidebar_label: "Stage 8: Team Challenges" +sidebar_position: 9 +id: stage-8 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +As Terraform use grows within the team, it becomes clear that what facilitated the initial success, is insufficient for the next level of growth and teamwork. This stage is a turning point, emphasizing the need for evolved workflows, enhanced collaboration tools, and a +more structured approach to managing scalable infrastructure projects. + + +1. Change velocity increases dramatically. +2. Codebase increases in size by 10x (but with lots of duplication). +3. New SLA/Commitment to keep it all running all the time. + +:::warning New Problems +1. Configuration starts drifting more often as the team neglects to apply changes consistently, or "ClickOps" persists in parts of the organization. +2. Developers are stepping on each other's toes. What worked when there were only a few developers no longer scales. +3. Poor controls and lack of consistency of Terraform code. Tons of duplication. +::: + +## Realization + +But it turns out, it wasn't that easy for everyone to run these scripts. Lot's tooling needs to be installed. +Some developers are on Windows, some on Mac, and others on Linux. The scripts weren't that not portable, +so the team is struggling to keep up with the changes. And the documentation, isn't that great either. + +To solve these problems, developers realize it's time to bite the bullet and [implement a CI/CD process for their Terraform code](/introduction/why-atmos/stage-9). + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/stage-9.mdx b/website/docs/introduction/why-atmos/stage-9.mdx new file mode 100644 index 000000000..2169d5ed6 --- /dev/null +++ b/website/docs/introduction/why-atmos/stage-9.mdx @@ -0,0 +1,48 @@ +--- +title: "Stage 9: DIY CI/CD with Terraform" +description: Terraform is deployed with a CI/CD pipeline +sidebar_label: "Stage 9: CI/CD Challenges" +sidebar_position: 10 +id: stage-9 +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' + + +With the greater adoption of Terraform and DevOps principles, Developers are now using Terraform daily. They decide to use the same patterns for deploying applications with Terraform. + + +Only Terraform is exceptionally different from deploying containerized apps. There are no rollbacks. It's more akin to performing database migrations without transactions (YOLO!). It's a scary business. Controls are needed. + +1. Developers stick their scripts in a CI/CD pipeline with hardcoded credentials set in the environment variables. +2. Pipeline posts comments for each commit on every PR containing the raw output of the `terraform plan`, to validate what *should* happen during `terraform apply`. +3. On merge to main, `terraform apply` is run *without* a planfile. 🤞 + +:::warning New Problems +- _Still using Jenkins? 🧌🔥_ +- CI/CD system promoted to *God Mode*. 🤞 Static administrative cloud credentials are exposed as environment variables, ripe for exfiltration +- No visibility into the impact of the changes across multiple environments at the same time +
+And then there's... +- No recourse for when a `terraform apply` fails +- Inadequate security mechanisms create a critical risk of catastrophic business loss +- Lack of plan file storage means incorrect implementation of plan/apply workflows +- Missing project-level locks, so PRs can easily clobber each other, rolling back state. +- The entire organization is spammed by GitHub comments every time someone pushes a commit, and a plan is run on the PR +- Automated drift detection is still missing, so you have no idea if what is in `main` is actually deployed +
+::: + +## Realization + +So, it turns out that implementing CI/CD was not as straightforward as developers thought. +It was not as easy as deploying a container that could be easily rolled back. It's more like performing +database migrations without transactions. That's a scary business, and controls are needed. + +Developers have [hit a wall](/introduction/why-atmos/stage-10) and realize they [need a better way to manage their Terraform code](/introduction/why-atmos/nirvana). + + + Try Atmos! + diff --git a/website/docs/introduction/why-atmos/why-atmos.mdx b/website/docs/introduction/why-atmos/why-atmos.mdx new file mode 100644 index 000000000..46920ccd2 --- /dev/null +++ b/website/docs/introduction/why-atmos/why-atmos.mdx @@ -0,0 +1,37 @@ +--- +title: "Why Does Atmos Exist?" +description: Learn about the typical Terraform journey when not using Atmos. +sidebar_label: Why Atmos? +sidebar_position: 9 +id: why-atmos +--- +import DocCardList from '@theme/DocCardList' +import Intro from '@site/src/components/Intro' + +# Why Does Atmos Exist? + +Atmos fills the gap for Terraform users by offering a proven framework complete with conventions, methodologies, design patterns, and best practices, ensuring teams succeed with Terraform from the start. + + +Every team progresses through a similar path when adopting Terraform, maturing over time. + +Each advancement brings new challenges, adding complexities that are ultimately justified by the benefits. +Often, the true value of these evolutions only becomes clear after we encounter and address these intricate challenges first-hand. + +**Most companies today wouldn't dream of starting a new product without using a mainstream framework like React or NextJS.** + +Despite [Terraform’s HCL language being a decade old](https://en.wikipedia.org/wiki/Terraform_(software)), many companies still begin their Terraform journey with a blank slate, oblivious to the existing tooling and frameworks like Atmos. This is reminiscent of the early days of the web, with languages like NodeJS, PHP, and Ruby, before the rise of modern frameworks like Rails and React revolutionized application design. However, it doesn’t have to be this way. It's no wonder some teams endure over 10 stages of evolution before reaching Terraform maturity. + +From [Cloud Posse's experience working with countless venture-backed startups all the up to Fortune 100 companies](https://cloudposse.com), here's the typical journey we see them take when using Terraform without a framework to guide them. + +:::tip Shortcuts +[You can shortcut this entire process by using Atmos from the start.](/introduction/why-atmos/nirvana) 😎 +::: + +# What stage are you at? + +Let's explore the challenges and constraints we faced using Terraform without a framework. + + + + diff --git a/website/docs/quick-start/add-custom-commands.mdx b/website/docs/quick-start/advanced/add-custom-commands.mdx similarity index 100% rename from website/docs/quick-start/add-custom-commands.mdx rename to website/docs/quick-start/advanced/add-custom-commands.mdx diff --git a/website/docs/quick-start/advanced/advanced.mdx b/website/docs/quick-start/advanced/advanced.mdx new file mode 100644 index 000000000..180a13a2f --- /dev/null +++ b/website/docs/quick-start/advanced/advanced.mdx @@ -0,0 +1,56 @@ +--- +title: Advanced Tutorial +sidebar_position: 4 +sidebar_label: Advanced Tutorial +description: Take 30 minutes to learn the most important Atmos concepts. +id: advanced +--- +import PillBox from '@site/src/components/PillBox' + +Advanced + +# Advanced Tutorial + +Take 30 minutes to learn the most important Atmos concepts. We recommend starting with the [Simple Quick Start](/quick-start/simple) tutorial before diving into this advanced tutorial. This tutorial will take you through the process of configuring and provisioning infrastructure on AWS using Atmos. It requires administrative access to an AWS organization. + +:::tip + +This Quick Start guide describes the steps to configure and provision the infrastructure +from this [Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced) repository. + +You can clone it and configure to your own needs. The repository should be a good start to get yourself familiar with Atmos. + +::: + +In this advanced tutorial, we’ll delve into concepts like [inheritance](/core-concepts/stacks/inheritance) +and [state management](/core-concepts/components/terraform/state-backend). +Additionally, we’ll cover how to read the remote state from other components using native Terraform. +This example focuses on AWS, and while Atmos isn’t AWS-specific, this tutorial will be. + +## Requirements + +We’ll assume you have administrative access to an AWS organization, as this tutorial will also provision +AWS accounts and the IAM architecture. If you don’t have these prerequisites, our [Simple Quick Start](/quick-start/simple) tutorial +might be a more practical starting point. + +## Overview + +The 10 steps to configure and provision the infrastructure are as follows: + +1. [Install Atmos](/install) +2. [Configure Project Repository](/quick-start/advanced/configure-repository) +3. [Configure Atmos CLI](/quick-start/advanced/configure-cli) +4. [Vendor Component Dependencies](/quick-start/advanced/vendor-components) +5. [Create Atmos Stacks](/quick-start/advanced/create-atmos-stacks) +6. [Configure Validation](/quick-start/advanced/configure-validation) +7. [Automate Common Workflows](/quick-start/advanced/create-workflows) +8. [Add Custom Commands](/quick-start/advanced/add-custom-commands) +9. [Configure Terraform Backend](/quick-start/advanced/configure-terraform-backend) +10. [Deploy Everything](/quick-start/advanced/provision) + +We'll then conclude with some [final notes](/quick-start/advanced/final-notes) and [next steps](/quick-start/advanced/next-steps) + + +import DocCardList from '@theme/DocCardList' + + diff --git a/website/docs/quick-start/configure-cli.mdx b/website/docs/quick-start/advanced/configure-cli.mdx similarity index 56% rename from website/docs/quick-start/configure-cli.mdx rename to website/docs/quick-start/advanced/configure-cli.mdx index 3e2e0a13b..f8a0e99f5 100644 --- a/website/docs/quick-start/configure-cli.mdx +++ b/website/docs/quick-start/advanced/configure-cli.mdx @@ -1,7 +1,7 @@ --- -title: Configure CLI +title: Configure Atmos CLI sidebar_position: 4 -sidebar_label: Configure CLI +sidebar_label: Configure Atoms CLI --- import File from '@site/src/components/File' @@ -9,7 +9,7 @@ In the previous step, we've decided on the following: - Use a monorepo to configure and provision two Terraform components into three AWS accounts and two AWS regions - The filesystem layout for the infrastructure monorepo -- To be able to use [Component Remote State](/core-concepts/components/remote-state), we put the `atmos.yaml` CLI config file +- To be able to use [Component Remote State](/core-concepts/components/terraform/remote-state), we put the `atmos.yaml` CLI config file into `/usr/local/etc/atmos/atmos.yaml` folder and set the ENV var `ATMOS_BASE_PATH` to point to the absolute path of the root of the repo Next step is to configure `atmos.yaml`. @@ -21,8 +21,6 @@ For the purpose of this Quick Start, below is the minimum configuration required configure [Atmos components](/core-concepts/components) and [Atmos stacks](/core-concepts/stacks). Copy the YAML config below into your `atmos.yaml` file. -
- ```yaml # CLI config is loaded from the following locations (from lowest to highest priority): @@ -38,9 +36,9 @@ file. # Base path for components, stacks and workflows configurations. # Can also be set using 'ATMOS_BASE_PATH' ENV var, or '--base-path' command-line argument. # Supports both absolute and relative paths. -# If not provided or is an empty string, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' +# If not provided or is an empty string, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' # and 'workflows.base_path' are independent settings (supporting both absolute and relative paths). -# If 'base_path' is provided, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' +# If 'base_path' is provided, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' # and 'workflows.base_path' are considered paths relative to 'base_path'. base_path: "" @@ -104,9 +102,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes atmos: @@ -116,60 +114,51 @@ schemas: ``` -
- The `atmos.yaml` configuration file defines the following sections. __NOTE:__ below is the description of the sections relevant to this Quick Start guide. For the description of all the sections, refer to [CLI Configuration](/cli/configuration). -- `base_path` - the base path for components, stacks and workflows configurations. We set it to an empty string because we've decided to use the ENV - var `ATMOS_BASE_PATH` to point to the absolute path of the root of the repo +
+
`base_path`
+
The base path for components, stacks and workflows configurations. We set it to an empty string because we've decided to use the ENV var `ATMOS_BASE_PATH` to point to the absolute path of the root of the repo.
-- `components.terraform.base_path` - the base path to the Terraform components (Terraform root modules). As described in - [Configure Repository](/quick-start/configure-repository), we've decided to put the Terraform components into the `components/terraform` directory, - and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENN var) - with `components.terraform.base_path` to calculate the final path to the Terraform components +
`components.terraform.base_path`
+
The base path to the Terraform components (Terraform root modules). As described in [Configure Repository](/quick-start/advanced/configure-repository), we've decided to put the Terraform components into the `components/terraform` directory, and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENN var) with `components.terraform.base_path` to calculate the final path to the Terraform components.
-- `components.terraform.apply_auto_approve` - if set to `true`, Atmos automatically adds the `-auto-approve` option to instruct Terraform to apply the - plan without asking for confirmation when executing `terraform apply` command +
`components.terraform.apply_auto_approve`
+
If set to `true`, Atmos automatically adds the `-auto-approve` option to instruct Terraform to apply the plan without asking for confirmation when executing `terraform apply` command.
-- `components.terraform.deploy_run_init` - if set to `true`, Atmos runs `terraform init` before - executing [`atmos terraform deploy`](/cli/commands/terraform/deploy) command +
`components.terraform.deploy_run_init`
+
If set to `true`, Atmos runs `terraform init` before executing [`atmos terraform deploy`](/cli/commands/terraform/deploy) command.
-- `components.terraform.init_run_reconfigure` - if set to `true`, Atmos automatically adds the `-reconfigure` option to update the backend - configuration when executing `terraform init` command +
`components.terraform.init_run_reconfigure`
+
If set to `true`, Atmos automatically adds the `-reconfigure` option to update the backend configuration when executing `terraform init` command.
-- `components.terraform.auto_generate_backend_file` - if set to `true`, Atmos automatically generates the Terraform backend file from the component - configuration when executing `terraform plan` and `terraform apply` commands +
`components.terraform.auto_generate_backend_file`
+
If set to `true`, Atmos automatically generates the Terraform backend file from the component configuration when executing `terraform plan` and `terraform apply` commands.
-- `stacks.base_path` - the base path to the Atmos stacks. As described in - [Configure Repository](/quick-start/configure-repository), we've decided to put the stack configurations into the `stacks` directory, - and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENN var) - with `stacks.base_path` to calculate the final path to the stacks +
`stacks.base_path`
+
The base path to the Atmos stacks. As described in [Configure Repository](/quick-start/advanced/configure-repository), we've decided to put the stack configurations into the `stacks` directory, and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENN var) with `stacks.base_path` to calculate the final path to the stacks.
-- `stacks.included_paths` - list of file paths to the top-level stacks in the `stacks` directory to include in search when Atmos searches for the - stack where the component is defined when executing `atmos` commands +
`stacks.included_paths`
+
List of file paths to the top-level stacks in the `stacks` directory to include in search when Atmos searches for the stack where the component is defined when executing `atmos` commands.
-- `stacks.excluded_paths` - list of file paths to the top-level stacks in the `stacks` directory to exclude from search when Atmos searches for the - stack where the component is defined when executing `atmos` commands +
`stacks.excluded_paths`
+
List of file paths to the top-level stacks in the `stacks` directory to exclude from search when Atmos searches for the stack where the component is defined when executing `atmos` commands.
-- `stacks.name_pattern` - Atmos stack name pattern. When executing `atmos` commands, Atmos does not use the configuration file names and their - filesystem locations to search for the stack where the component is defined. Instead, Atmos uses the context - variables (`namespace`, `tenant`, `environment`, `stage`) to search for the stack. The stack config file names can be anything, and they can be in - any folder in any sub-folder in the `stacks` directory. For example, when executing the `atmos terraform apply vpc -s tenant1-ue2-dev` - command, the stack `tenant1-ue2-dev` is specified by the `-s` flag. By looking at `name_pattern: "{tenant}-{environment}-{stage}"` and processing - the tokens, Atmos knows that the first part of the stack name is `tenant`, the second part is `environment`, and the third part is `stage`. Then - Atmos searches for the stack configuration file (in the `stacks` directory) where `tenant: tenant1`, `environment: ue2` and `stage: dev` are - defined (inline or via imports) +
`stacks.name_pattern`
+
Atmos stack name pattern. When executing `atmos` commands, Atmos does not use the configuration file names and their filesystem locations to search for the stack where the component is defined. Instead, Atmos uses the context variables (`namespace`, `tenant`, `environment`, `stage`) to search for the stack. The stack config file names can be anything, and they can be in any folder in any sub-folder in the `stacks` directory. For example, when executing the `atmos terraform apply vpc -s tenant1-ue2-dev` command, the stack `tenant1-ue2-dev` is specified by the `-s` flag. By looking at `name_pattern: "{tenant}-{environment}-{stage}"` and processing the tokens, Atmos knows that the first part of the stack name is `tenant`, the second part is `environment`, and the third part is `stage`. Then Atmos searches for the stack configuration file (in the `stacks` directory) where `tenant: tenant1`, `environment: ue2` and `stage: dev` are defined (inline or via imports).
-- `workflows.base_path` - the base path to Atmos [Workflows](/core-concepts/workflows) files +
`workflows.base_path`
+
The base path to Atmos [Workflows](/core-concepts/workflows) files.
-- `logs.verbose` - set to `true` to increase log verbosity. When set to `true`, Atmos prints to the console all the steps it takes to find and - process the `atmos.yaml` CLI config file, and all the steps it takes to find the stack and find and process the component in the stack +
`logs.verbose`
+
Set to `true` to increase log verbosity. When set to `true`, Atmos prints to the console all the steps it takes to find and process the `atmos.yaml` CLI config file, and all the steps it takes to find the stack and find and process the component in the stack.
-- `commands` - configuration for [Atmos Custom Commands](/core-concepts/custom-commands) +
`commands`
+
Configuration for [Atmos Custom Commands](/core-concepts/custom-commands).
-- `schemas` - [JSON Schema](https://json-schema.org/) and [OPA Policy](https://www.openpolicyagent.org/) configurations for: - - [Atmos Manifests Validation](/reference/schemas) - - [Atmos Components Validation](/core-concepts/components/validation) +
`schemas`
+
See [JSON Schema](https://json-schema.org/) and [OPA Policy](https://www.openpolicyagent.org/) configurations for: [Atmos Schema Validation](/cli/schemas), [Atmos Custom Validation](/core-concepts/validate).
+
diff --git a/website/docs/quick-start/configure-repository.md b/website/docs/quick-start/advanced/configure-repository.md similarity index 92% rename from website/docs/quick-start/configure-repository.md rename to website/docs/quick-start/advanced/configure-repository.md index f8988dfb3..21275738a 100644 --- a/website/docs/quick-start/configure-repository.md +++ b/website/docs/quick-start/advanced/configure-repository.md @@ -1,7 +1,7 @@ --- -title: Configure Repository +title: Configure Project Repository sidebar_position: 3 -sidebar_label: Configure Repository +sidebar_label: Configure Project Repository --- Atmos supports both the [monorepo and polyrepo architectures](https://en.wikipedia.org/wiki/Monorepo) when managing the configurations for components @@ -21,8 +21,8 @@ infrastructure. For example, depending on various requirements (including securi In this Quick Start guide, we will be using a monorepo to provision the following resources into multiple AWS accounts (`dev`, `staging`, `prod`) and regions (`us-east-2` and `us-west-2`): -- [vpc-flow-logs-bucket](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/terraform/vpc-flow-logs-bucket) -- [vpc](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/terraform/vpc) +- [vpc-flow-logs-bucket](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/terraform/vpc-flow-logs-bucket) +- [vpc](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/terraform/vpc) ## Common Directories and Files @@ -42,7 +42,7 @@ Atmos separates code from configuration (separation of concerns). The code is in :::note While it's recommended to use the directory names as shown above, the `stacks` and `components` directory names and filesystem locations are -configurable in the `atmos.yaml` CLI config file. Refer to [Configure CLI](/quick-start/configure-cli) for more details. +configurable in the `atmos.yaml` CLI config file. Refer to [Configure CLI](/quick-start/advanced/configure-cli) for more details. :::
@@ -78,7 +78,7 @@ The following example provides the simplest filesystem layout that Atmos can wor ## `atmos.yaml` CLI Config File Location While placing `atmos.yaml` at the root of the repository will work for the `atmos` CLI, it will not work -for [Component Remote State](/core-concepts/components/remote-state) because it uses +for [Component Remote State](/core-concepts/components/terraform/remote-state) because it uses the [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider. Terraform executes the provider from the component's folder (e.g. `components/terraform/vpc`), and we don't want to replicate `atmos.yaml` into every component's folder. @@ -102,7 +102,7 @@ This means that `atmos.yaml` file must be at a location in the file system where Initial Atmos configuration can be controlled by these ENV vars: -- `ATMOS_CLI_CONFIG_PATH` - where to find `atmos.yaml`. Path to a folder where the `atmos.yaml` CLI config file is located (just the folder without +- `ATMOS_CLI_CONFIG_PATH` - where to find `atmos.yaml`. Path to a folder where the `atmos.yaml` CLI config file is located (just the folder without the file name) - `ATMOS_BASE_PATH` - base path to `components` and `stacks` folders @@ -124,8 +124,8 @@ For this to work for both the `atmos` CLI and the Terraform provider, we recomme set `ATMOS_CLI_CONFIG_PATH=/atmos/config`. Then set the ENV var `ATMOS_BASE_PATH` pointing to the absolute path of the root of the repo - When working in a Docker container, place `atmos.yaml` in the `rootfs` directory - at [/rootfs/usr/local/etc/atmos/atmos.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/rootfs/usr/local/etc/atmos/atmos.yaml) - and then copy it into the container's file system in the [Dockerfile](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/Dockerfile) + at [/rootfs/usr/local/etc/atmos/atmos.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml) + and then copy it into the container's file system in the [Dockerfile](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/Dockerfile) by executing the `COPY rootfs/ /` Docker command. Then in the Dockerfile, set the ENV var `ATMOS_BASE_PATH` pointing to the absolute path of the root of the repo. Note that the [Atmos Quick Start example](https://github.com/cloudposse/atmos/blob/master/examples/quick-start) uses [Geodesic](https://github.com/cloudposse/geodesic) as the base Docker image. [Geodesic](https://github.com/cloudposse/geodesic) sets the ENV @@ -154,6 +154,6 @@ layout: :::tip -For a Quick Start example, refer to [Atmos Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start) +For a Quick Start example, refer to [Atmos Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced) ::: diff --git a/website/docs/quick-start/configure-terraform-backend.mdx b/website/docs/quick-start/advanced/configure-terraform-backend.mdx similarity index 98% rename from website/docs/quick-start/configure-terraform-backend.mdx rename to website/docs/quick-start/advanced/configure-terraform-backend.mdx index 2c39d7910..14ea15af7 100644 --- a/website/docs/quick-start/configure-terraform-backend.mdx +++ b/website/docs/quick-start/advanced/configure-terraform-backend.mdx @@ -106,7 +106,7 @@ can be provisioned with Atmos. Here's an example of an Atmos manifest to configure the `tfstate-backend` Terraform component: -```yaml +```yaml components: terraform: tfstate-backend: @@ -152,7 +152,7 @@ Configuring Terraform S3 backend with Atmos consists of the three steps: - Set `auto_generate_backend_file` to `true` in the `atmos.yaml` CLI config file in the `components.terraform` section: - ```yaml + ```yaml components: terraform: # Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE' ENV var, or '--auto-generate-backend-file' command-line argument @@ -160,7 +160,7 @@ Configuring Terraform S3 backend with Atmos consists of the three steps: ``` - Refer to [Quick Start: Configure CLI](/quick-start/configure-cli) and [CLI Configurtion](/cli/configuration) for more details. + Refer to [Quick Start: Configure CLI](/quick-start/advanced/configure-cli) and [CLI Configurtion](/cli/configuration) for more details. - Configure the S3 backend in one of the `_defaults.yaml` manifests. You can configure it for the entire Organization, or per OU/tenant, or per region, or per account. @@ -169,7 +169,6 @@ Configuring Terraform S3 backend with Atmos consists of the three steps: The `_defaults.yaml` manifests contain the default settings for Organizations, Organizational Units and accounts. ::: -
To configure the S3 backend for the entire Organization, add the following config in `stacks/orgs/acme/_defaults.yaml`: @@ -189,8 +188,6 @@ Configuring Terraform S3 backend with Atmos consists of the three steps: ```
-
- - (This step is optional) For each component, you can add `workspace_key_prefix` similar to the following: ```yaml @@ -216,8 +213,6 @@ Configuring Terraform S3 backend with Atmos consists of the three steps: We usually don’t specify `workspace_key_prefix` for each component and let Atmos use the component name as `workspace_key_prefix`. -
- Once all the above is configured, when you run the commands `atmos terraform plan vpc -s ` or `atmos terraform apply vpc -s `, before executing the Terraform commands, Atmos will deep-merge the backend configurations from the `_defaults.yaml` manifest and from the component itself, and will generate a backend config JSON file `backend.tf.json` in the component's folder, @@ -244,8 +239,6 @@ similar to the following example: ```
-
- You can also generate the backend configuration file for a component in a stack by executing the command [atmos terraform generate backend](/cli/commands/terraform/generate-backend). Or generate the backend configuration files for all components by executing the command [atmos terraform generate backends](/cli/commands/terraform/generate-backends). @@ -261,7 +254,7 @@ needs to have a separate S3 bucket, DynamoDB table, and IAM role with different access the Terraform backend only in the `dev` account, but not in `staging` and `prod`). Atmos supports this use-case by using deep-merging of stack manifests, [Imports](/core-concepts/stacks/imports) -and [Inheritance](/core-concepts/components/inheritance), which makes the backend configuration reusable and DRY. +and [Inheritance](/core-concepts/stacks/inheritance), which makes the backend configuration reusable and DRY. We'll split the backend config between the Organization and the accounts. @@ -345,8 +338,6 @@ add `workspace_key_prefix` for the component, generating the following final dee ```
-
- In the same way, you can create different Terraform backends per Organizational Unit, per region, per account (or a group of accounts, e.g. `prod` and `non-prod`), or even per component or a set of components (e.g. root-level components like `account` and IAM roles can have a separate backend), and then configure parts of the backend config in the corresponding Atmos stack manifests. Atmos will deep-merge all the parts from the @@ -360,16 +351,14 @@ auto-generating the backend config file is helpful and saves you from creating t when you provision multiple instances of a Terraform component into the same environment (same account and region). You can provision more than one instance of the same Terraform component (with the same or different settings) into the same environment by defining -many Atmos components that provide configuration for the Terraform component. +many Atmos components that provide configuration for the Terraform component. :::tip For more information on configuring and provision multiple instances of a Terraform component, refer to [Multiple Component Instances Atmos Design Patterns](/design-patterns/multiple-component-instances) ::: -
- -For example, the following config shows how to define two Atmos components, `vpc/1` and `vpc/2`, which both point to +For example, the following config shows how to define two Atmos components, `vpc/1` and `vpc/2`, which both point to the same Terraform component `vpc`: diff --git a/website/docs/quick-start/configure-validation.mdx b/website/docs/quick-start/advanced/configure-validation.mdx similarity index 83% rename from website/docs/quick-start/configure-validation.mdx rename to website/docs/quick-start/advanced/configure-validation.mdx index a39f4e045..6e329d301 100644 --- a/website/docs/quick-start/configure-validation.mdx +++ b/website/docs/quick-start/advanced/configure-validation.mdx @@ -1,24 +1,22 @@ --- -title: Configure Validation +title: Validate Configurations sidebar_position: 7 -sidebar_label: Configure Validation +sidebar_label: Validation Configurations --- -Atmos supports [Atmos Manifests Validation](/reference/schemas) and [Atmos Components Validation](/core-concepts/components/validation) +Atmos supports [Stack Schema Validation](/cli/schemas) and [Custom Policy Validation](/core-concepts/validate) using [JSON Schema](https://json-schema.org/) and [OPA Policies](https://www.openpolicyagent.org/). :::tip This Quick Start guide describes the steps to configure and provision the infrastructure -from the [Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start) repository. +from the [Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced) repository. You can clone the repository and modify to your own needs. The repository will help you understand the validation configurations for Atmos manifests and components. ::: -
- Configuring validation for Atmos manifests and components consists of the three steps: - Configure validation schemas in `atmos.yaml` @@ -43,9 +41,9 @@ schemas: # Supports both absolute and relative paths base_path: "stacks/schemas/opa" # JSON Schema to validate Atmos manifests - # https://atmos.tools/reference/schemas/ + # https://atmos.tools/cli/schemas/ # https://atmos.tools/cli/commands/validate/stacks/ - # https://atmos.tools/quick-start/configure-validation/ + # https://atmos.tools/quick-start/advanced/configure-validation/ # https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json # https://json-schema.org/draft/2020-12/release-notes atmos: @@ -54,19 +52,15 @@ schemas: manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json" ``` -
- :::tip For more information, refer to: -- [Quick-Start: Configure CLI](/quick-start/configure-cli) +- [Quick-Start: Configure CLI](/quick-start/advanced/configure-cli) - [Atmos CLI Configuration](/cli/configuration) ::: -
- ## Configure Atmos Manifests Validation [Atmos Manifest JSON Schema](pathname:///schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) can be used to validate Atmos stack manifests and provide @@ -75,10 +69,10 @@ auto-completion in IDEs and editors. Complete the following steps to configure Atmos manifest validation: - Add the [Atmos Manifest JSON Schema](pathname:///schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) to your repository, for example - in [`stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) + in [`stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json`](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json) - Configure the `schemas.atmos.manifest` section in the `atmos.yaml` [CLI config file](/cli/configuration) as described - in [Atmos Manifests Validation using JSON Schema](/reference/schemas) + in [Atmos Manifests Validation using JSON Schema](/cli/schemas) ```yaml title="atmos.yaml" # Validation schemas (for validating atmos stacks and components) @@ -100,19 +94,15 @@ Complete the following steps to configure Atmos manifest validation: atmos validate stacks --schemas-atmos-manifest stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json ``` -
- :::tip For more information, refer to: -- [Atmos Manifests Validation using JSON Schema](/reference/schemas) +- [Atmos Manifests Validation using JSON Schema](/cli/schemas) - [atmos validate stacks](/cli/commands/validate/stacks) ::: -
- ## Configure Atmos Components Validation Atmos component validation allows: @@ -122,17 +112,13 @@ Atmos component validation allows: * Check if the component config (including relations between different component variables) is correct to allow or deny component provisioning using [OPA Policies](https://www.openpolicyagent.org/) -To configure Atmos components validation, complete the steps described in [Atmos Components Validation](/core-concepts/components/validation). - -
+To configure Atmos components validation, complete the steps described in [Custom Policy Validation](/core-concepts/validate). :::tip For more information, refer to: -- [Atmos Components Validation](/core-concepts/components/validation) -- [atmos validate component](/cli/commands/validate/component) +- [Custom Policy Validation](/core-concepts/validate) +- Command: [`atmos validate component`](/cli/commands/validate/component) ::: - -
diff --git a/website/docs/quick-start/create-atmos-stacks.mdx b/website/docs/quick-start/advanced/create-atmos-stacks.mdx similarity index 97% rename from website/docs/quick-start/create-atmos-stacks.mdx rename to website/docs/quick-start/advanced/create-atmos-stacks.mdx index 4fd80d5f8..b1a0bc300 100644 --- a/website/docs/quick-start/create-atmos-stacks.mdx +++ b/website/docs/quick-start/advanced/create-atmos-stacks.mdx @@ -21,7 +21,7 @@ Refer to [Stack Imports](/core-concepts/stacks/imports) for more details on Atmo In the `stacks/catalog/vpc-flow-logs-bucket/defaults.yaml` file, add the following manifest for the `vpc-flow-logs-bucket` Atmos component: -```yaml +```yaml components: terraform: vpc-flow-logs-bucket: @@ -166,20 +166,18 @@ components: ``` -
- These Atmos component manifests will be imported into the top-level Atmos stacks. The default variables (in the `vars` sections) -can be overridden in the derived Atmos components by using [Atmos Component Inheritance](/core-concepts/components/inheritance). +can be overridden in the derived Atmos components by using [Atmos Component Inheritance](/core-concepts/stacks/inheritance). ## Atmos Top-level Stacks -When executing the [CLI commands](/cli/cheatsheet), Atmos does not use the stack file names and their filesystem locations to search for the stack +When executing the [CLI commands](/cheatsheets/commands), Atmos does not use the stack file names and their filesystem locations to search for the stack where the component is defined. Instead, Atmos uses the context variables (`namespace`, `tenant`, `environment`, `stage`) to search for the stack. The stack config file names (stack manifest names) can be anything, and they can be in any folder in any sub-folder in the `stacks` directory. For example, when executing the `atmos terraform apply vpc -s plat-ue2-dev` command, the Atmos stack `plat-ue2-dev` is specified by the `-s` flag. By looking at `name_pattern: "{tenant}-{environment}-{stage}"` -(see [Configure CLI](/quick-start/configure-cli)) and processing the tokens, Atmos knows that the first part of the stack name is `tenant`, the second +(see [Configure CLI](/quick-start/advanced/configure-cli)) and processing the tokens, Atmos knows that the first part of the stack name is `tenant`, the second part is `environment`, and the third part is `stage`. Then Atmos searches for the top-level stack manifest (in the `stacks` directory) where `tenant: plat`, `environment: ue2` and `stage: dev` are defined (inline or via imports). @@ -224,8 +222,6 @@ would look like this: ```
-
- ### Hierarchical Layout We recommend using a hierarchical layout that follows the way AWS thinks about infrastructure. This works very well when you may have dozens or @@ -295,7 +291,7 @@ Create the following filesystem layout (which will be the final layout for this ### Configure Region and Stage Mixins -[Mixins](/core-concepts/stacks/mixins) are a special kind of "[import](/core-concepts/stacks/imports)". +[Mixins](/core-concepts/stacks/inheritance/mixins) are a special kind of "[import](/core-concepts/stacks/imports)". It's simply a convention we recommend to distribute reusable snippets of configuration that alter the behavior in some deliberate way. Mixins are not handled in any special way. They are technically identical to all other imports. @@ -342,7 +338,7 @@ vars: In `stacks/mixins/region/us-west-2.yaml`, add the following config: -```yaml +```yaml import: # Import the `uw2` manifest with `vpc` configuration for `us-west-2` region - catalog/vpc/uw2 @@ -360,7 +356,7 @@ vars: In `stacks/mixins/stage/dev.yaml`, add the following config: -```yaml +```yaml vars: stage: dev @@ -371,7 +367,7 @@ vars: In `stacks/mixins/stage/prod.yaml`, add the following config: -```yaml +```yaml vars: stage: prod @@ -390,8 +386,6 @@ vars: ``` -
- As we can see, in the tenant, region and stage mixins, besides some other common variables, we are defining the global context variables `tenant`, `environment` and `stage`, which Atmos uses when searching for a component in a stack. These mixins then get imported into the parent Atmos stacks without defining the context variables in each top-level stack, making the configuration DRY. @@ -414,7 +408,7 @@ The file defines the context variable `namespace` for the entire `acme` Organiza In `stacks/orgs/acme/core/_defaults.yaml`, add the following config for the `core` OU (tenant): -```yaml +```yaml import: - orgs/acme/_defaults - mixins/tenant/core @@ -424,7 +418,7 @@ import: In `stacks/orgs/acme/plat/_defaults.yaml`, add the following config for the `plat` OU (tenant): -```yaml +```yaml import: - orgs/acme/_defaults - mixins/tenant/plat @@ -468,8 +462,6 @@ import: ``` -
- ### Configure Top-level Stacks After we've configured the catalog for the components, the mixins for the tenants, regions and stages, and the defaults for the Organization, OU and diff --git a/website/docs/quick-start/create-workflows.mdx b/website/docs/quick-start/advanced/create-workflows.mdx similarity index 98% rename from website/docs/quick-start/create-workflows.mdx rename to website/docs/quick-start/advanced/create-workflows.mdx index 582ff86ff..7c91d9985 100644 --- a/website/docs/quick-start/create-workflows.mdx +++ b/website/docs/quick-start/advanced/create-workflows.mdx @@ -1,28 +1,22 @@ --- -title: Create Workflows +title: Automate Common Workflows sidebar_position: 8 -sidebar_label: Create Workflows +sidebar_label: Automate Common Workflows --- import Terminal from '@site/src/components/Terminal' Atmos workflows are a way of combining multiple commands into executable units of work. -
- :::tip Refer to [Atmos Workflows](/core-concepts/workflows) for more information about configuring workflows ::: -
- :::note You can use [Atmos Custom Commands](/core-concepts/custom-commands) in [Atmos Workflows](/core-concepts/workflows), and [Atmos Workflows](/core-concepts/workflows) in [Atmos Custom Commands](/core-concepts/custom-commands) ::: -
- To define workflows, add the following configurations: - In `atmos.yaml`, add the `workflows` section and configure the base path to the workflows: @@ -141,19 +135,13 @@ atmos workflow validate-all-vpc-flow-logs -f validation atmos workflow validate-all-vpc -f validation ``` -
- :::tip Refer to [atmos workflow](/cli/commands/workflow) for more information on the `atmos workflow` CLI command ::: -
- The `atmos workflow` CLI command supports the `--dry-run` flag. If passed, the command will just print information about the executed workflow steps without executing them. For example: -
- ```console diff --git a/website/docs/quick-start/final-notes.mdx b/website/docs/quick-start/advanced/final-notes.mdx similarity index 99% rename from website/docs/quick-start/final-notes.mdx rename to website/docs/quick-start/advanced/final-notes.mdx index 29bb11cea..de1dc98a5 100644 --- a/website/docs/quick-start/final-notes.mdx +++ b/website/docs/quick-start/advanced/final-notes.mdx @@ -56,7 +56,6 @@ Atmos provides unlimited flexibility in defining and configuring stacks and comp ipv4_primary_cidr_block: 10.10.0.0/18 ``` -
Then we can execute the following `atmos` commands to provision the two VPCs into the `dev` account in the `us-east-2` region: @@ -65,7 +64,5 @@ Atmos provides unlimited flexibility in defining and configuring stacks and comp atmos terraform apply vpc/2 --stack plat-ue2-dev ``` -
- All the above makes Atmos an ideal framework to organize infrastructure, to design for organizational complexity, and to provision multi-account environments for very complex organizations. diff --git a/website/docs/quick-start/next-steps.md b/website/docs/quick-start/advanced/next-steps.md similarity index 56% rename from website/docs/quick-start/next-steps.md rename to website/docs/quick-start/advanced/next-steps.md index ccc8cd2b2..941fdfc2d 100644 --- a/website/docs/quick-start/next-steps.md +++ b/website/docs/quick-start/advanced/next-steps.md @@ -4,21 +4,21 @@ sidebar_label: Next Steps sidebar_position: 13 --- -You have just learned the **basics of Atmos**. +You have just learned the **essentials of Atmos**. Atmos is a powerful enterprise-grade workflow automation tool with so **much more to offer**! ## What's next? -Here are some of the major differentiators of Atmos: +Here are some of the major differentiators of Atmos and topics worth exploring in greater depth: * [Atmos Design Patterns](/design-patterns) * [Third-party Integrations](/integrations) -* [Atmos Vendoring](/core-concepts/vendoring) -* [Component Vendoring](/core-concepts/components/vendoring) +* [Atmos Vendoring](/core-concepts/vendor) +* [Component Vendoring](/core-concepts/vendor/component-manifest) * [Imports](/core-concepts/stacks/imports) (mixins, catalogs) * [Workflow Automation](/core-concepts/workflows) * [Custom Commands](/core-concepts/custom-commands) -* [Component Inheritance & Multiple Inheritance](/core-concepts/components/inheritance) -* [JSON Schema & OPA Policy Enforcement](/core-concepts/components/validation) -* [Atmos Manifest JSON Schema](/reference/schemas) +* [Component Inheritance & Multiple Inheritance](/core-concepts/stacks/inheritance) +* [JSON Schema & OPA Policy Enforcement](/core-concepts/validate) +* [Atmos Manifest JSON Schema](/cli/schemas) diff --git a/website/docs/quick-start/provision.md b/website/docs/quick-start/advanced/provision.md similarity index 92% rename from website/docs/quick-start/provision.md rename to website/docs/quick-start/advanced/provision.md index 51be87ea4..4cd559b2b 100644 --- a/website/docs/quick-start/provision.md +++ b/website/docs/quick-start/advanced/provision.md @@ -48,7 +48,7 @@ atmos terraform apply vpc -s plat-uw2-prod
-Alternatively, you can execute the configured [Atmos workflow](/quick-start/create-workflows) to provision all the components in all the stacks: +Alternatively, you can execute the configured [Atmos workflow](/quick-start/advanced/create-workflows) to provision all the components in all the stacks: ```shell # Execute the workflow `apply-all-components` from the workflow manifest `networking` @@ -61,7 +61,7 @@ Looking at the commands above, you might have a question "How does Atmos find th Let's consider what Atmos does when executing the command `atmos terraform apply vpc -s plat-ue2-prod`: -- Atmos uses the [CLI config](/quick-start/configure-cli) `stacks.name_pattern: "{tenant}-{environment}-{stage}"` to figure out that the first part of +- Atmos uses the [CLI config](/quick-start/advanced/configure-cli) `stacks.name_pattern: "{tenant}-{environment}-{stage}"` to figure out that the first part of the stack name is `tenant`, the second part is `environment`, and the third part is `stage` - Atmos searches for the stack configuration file (in the `stacks` folder and all sub-folders) where `tenant: plat`, `environment: ue2` diff --git a/website/docs/quick-start/vendor-components.mdx b/website/docs/quick-start/advanced/vendor-components.mdx similarity index 92% rename from website/docs/quick-start/vendor-components.mdx rename to website/docs/quick-start/advanced/vendor-components.mdx index 780866736..69001cc7a 100644 --- a/website/docs/quick-start/vendor-components.mdx +++ b/website/docs/quick-start/advanced/vendor-components.mdx @@ -5,6 +5,9 @@ sidebar_label: Vendor Components --- import Terminal from '@site/src/components/Terminal' import File from '@site/src/components/File' +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' + In the previous steps, we've configured the repository and decided to provision the `vpc-flow-logs-bucket` and `vpc` Terraform components into three AWS accounts (`dev`, `staging`, `prod`) in the two AWS regions (`us-east-2` and `us-west-2`). @@ -23,32 +26,30 @@ One way to create the Terraform components is to copy them into the correspondin [vpc](https://github.com/cloudposse/terraform-aws-components/tree/main/modules/vpc) into the `components/terraform/vpc` folder -
- :::note The recommended way to vendor the components is to execute the `atmos vendor pull` CLI command. ::: -
- :::tip For more information about Atmos Vendoring and the `atmos vendor pull` CLI command, refer to: -- [Atmos Vendoring](/core-concepts/vendoring) +- [Atmos Vendoring](/core-concepts/vendor) - [atmos vendor pull](/cli/commands/vendor/pull) ::: -
- To vendor the components from the open-source component repository [terraform-aws-components](https://github.com/cloudposse/terraform-aws-components), perform the following steps: -- Create a `vendor.yaml` Atmos vendor config file in the root of the repo with the following content: + + +## Create a `vendor.yaml` config file + +Create a `vendor.yaml` Atmos vendor config file in the root of the repo with the following content: -```yaml +```yaml apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: @@ -100,8 +101,9 @@ spec: ``` -
+
+Advanced Configuration :::warning The `glob` library that Atmos uses to download remote artifacts does not treat the double-star `**` as including sub-folders. @@ -110,7 +112,7 @@ If the component's folder has sub-folders, and you need to vendor them, they hav ::: -```yaml +```yaml spec: sources: - component: "vpc-flow-logs-bucket" @@ -124,21 +126,24 @@ spec: - "**/modules/**" ``` +
+
-
-- Execute the command `atmos vendor pull` from the root of the repo + +## Vendor the dependencies +Execute the command `atmos vendor pull` from the root of the repo. ```shell Processing vendor config file 'vendor.yaml' -Pulling sources for the component 'vpc' -from 'github.com/cloudposse/terraform-aws-components.git//modules/vpc?ref=1.343.1' +Pulling sources for the component 'vpc' +from 'github.com/cloudposse/terraform-aws-components.git//modules/vpc?ref=1.343.1' into 'components/terraform/vpc' -Pulling sources for the component 'vpc-flow-logs-bucket' -from 'github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref=1.343.1' +Pulling sources for the component 'vpc-flow-logs-bucket' +from 'github.com/cloudposse/terraform-aws-components.git//modules/vpc-flow-logs-bucket?ref=1.343.1' into 'components/terraform/vpc-flow-logs-bucket/1.343.1' ``` @@ -146,8 +151,6 @@ into 'components/terraform/vpc-flow-logs-bucket/1.343.1' After the command is executed, the filesystem layout should look like this: -
- ```console    │   # Centralized stacks configuration    ├── stacks @@ -173,7 +176,8 @@ After the command is executed, the filesystem layout should look like this:                └── versions.tf ``` -
+
+ Each component follows the [Standard Module Structure](https://developer.hashicorp.com/terraform/language/modules/develop/structure) that Terraform recommends. There are a few additions: @@ -181,7 +185,7 @@ recommends. There are a few additions: - `context.tf` - this file contains all the common variables that Terraform modules and components consume (to make the component's `variables.tf` file DRY). This is a standard file that is copied into each component. The file also defines the context variables (`namespace`, `tenant`, `environment`, `stage`) which are used by Atmos to search for Atmos stacks when executing - the [CLI commands](/cli/cheatsheet) + the [CLI commands](/cheatsheets/commands) - `remote-state.tf` in the `vpc` component - this file configures the [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) Terraform module to obtain the remote state @@ -196,11 +200,11 @@ module "vpc_flow_logs_bucket" { source = "cloudposse/stack-config/yaml//modules/remote-state" version = "1.5.0" - # Specify the Atmos component name (defined in YAML stack config files) + # Specify the Atmos component name (defined in YAML stack config files) # for which to get the remote state outputs component = "vpc-flow-logs-bucket" - # Override the context variables to point to a different Atmos stack if the + # Override the context variables to point to a different Atmos stack if the # `vpc-flow-logs-bucket` Atmos component is provisioned in another AWS account, OU or region stage = try(coalesce(var.vpc_flow_logs_bucket_stage_name, module.this.stage), null) tenant = try(coalesce(var.vpc_flow_logs_bucket_tenant_name, module.this.tenant), null) @@ -215,7 +219,7 @@ module "vpc_flow_logs_bucket" { ## Remote State Notes -The [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) Terraform module uses the [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) +The [remote-state](https://github.com/cloudposse/terraform-yaml-stack-config/tree/main/modules/remote-state) Terraform module uses the [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider to read Atmos configuration and obtain the remote state for Atmos components. Both the `atmos` CLI and [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider use the same `Go` code, @@ -238,8 +242,6 @@ component's directory (e.g. `components/terraform/vpc`), and we don't want to re ::: -
- For this to work for both the `atmos` CLI and the Terraform `utils` provider, we recommend doing one of the following: - Put `atmos.yaml` at `/usr/local/etc/atmos/atmos.yaml` on local host and set the ENV var `ATMOS_BASE_PATH` to point to the absolute path of the root @@ -253,13 +255,11 @@ For this to work for both the `atmos` CLI and the Terraform `utils` provider, we set `ATMOS_CLI_CONFIG_PATH=/atmos/config`. Then set the ENV var `ATMOS_BASE_PATH` pointing to the absolute path of the root of the repo - When working in a Docker container, place `atmos.yaml` in the `rootfs` directory - at [/rootfs/usr/local/etc/atmos/atmos.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/rootfs/usr/local/etc/atmos/atmos.yaml) - and then copy it into the container's file system in the [Dockerfile](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/Dockerfile) + at [/rootfs/usr/local/etc/atmos/atmos.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/rootfs/usr/local/etc/atmos/atmos.yaml) + and then copy it into the container's file system in the [Dockerfile](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/Dockerfile) by executing the `COPY rootfs/ /` Docker command. Then in the Dockerfile, set the ENV var `ATMOS_BASE_PATH` pointing to the absolute path of the root of the repo. Note that the [Atmos example](https://github.com/cloudposse/atmos/blob/master/examples/quick-start) uses [Geodesic](https://github.com/cloudposse/geodesic) as the base Docker image. [Geodesic](https://github.com/cloudposse/geodesic) sets the ENV var `ATMOS_BASE_PATH` automatically to the absolute path of the root of the repo on local host -
- -For a complete description of how Atmos components use remote state, refer to [Component Remote State](/core-concepts/components/remote-state). +For a complete description of how Atmos components use remote state, refer to [Component Remote State](/core-concepts/components/terraform/remote-state). diff --git a/website/docs/quick-start/install-atmos.mdx b/website/docs/quick-start/install-atmos.mdx index f600d5f01..dfc4587fa 100644 --- a/website/docs/quick-start/install-atmos.mdx +++ b/website/docs/quick-start/install-atmos.mdx @@ -1,18 +1,26 @@ --- title: Install Atmos sidebar_label: Install Atmos -sidebar_position: 2 +sidebar_position: 3 +slug: /install +id: install-atmos --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import Link from '@docusaurus/Link'; +import Intro from '@site/src/components/Intro' +import LatestRelease from '@site/src/components/LatestRelease' +import File from '@site/src/components/File' -There are many ways to install Atmos. + +There are many ways to install Atmos. Choose the method that works best for you! + +To check what version of Atmos you have installed, just run `atmos version`. The latest version of Atmos is . -To check what version of Atmos you have installed, just run `atmos version`. +To find the latest available version of Atmos, visit the [Releases Page](https://github.com/cloudposse/atmos/releases). The latest version will always be available for download here. -To find the latest available version of Atmos, visit the [Releases Page](https://github.com/cloudposse/atmos/releases). The latest version will -always be available for download here. +## Using OS Package Managers Atmos has native packages for macOS and every major Linux distribution. We also supply binary releases for Windows. @@ -25,6 +33,16 @@ Atmos has native packages for macOS and every major Linux distribution. We also ```shell brew install atmos ``` + + #### Pro tip! Use a `Brewfile` + + Create a `Brewfile` in your [Atmos project](/core-concepts/projects), and add `brew "atmos"`. This way, you can ensure that everyone on your team is using the same version of Atmos. + + +
brew "atmos", ""
+
+ + Then just run `brew install` in the same directory as the `Brewfile`. @@ -101,7 +119,7 @@ Atmos has native packages for macOS and every major Linux distribution. We also go install github.com/cloudposse/atmos@latest ``` - __NOTE:__ Since the version is passed in via `-ldflags` during build, when running `go install` without using `-ldflags`, the CLI will return `0.0.1` + __NOTE:__ Since the version is passed in via `-ldflags` during the build, when running `go install` without using `-ldflags`, the CLI will return `0.0.1` when running `atmos version`. @@ -134,7 +152,7 @@ Atmos has native packages for macOS and every major Linux distribution. We also :::note -The latest version of Atmos might not be available with third party package managers. +The latest version of Atmos () might not be available with third-party package managers. ::: @@ -150,3 +168,12 @@ The latest version of Atmos might not be available with third party package mana - Rename the downloaded file to `atmos` (optional) - Add the execution bit to the binary (e.g. on Linux and Mac, run `chmod u+x atmos`) - Place the binary somewhere on your `PATH` (e.g. on Linux and Mac: `mv atmos /usr/local/bin/`) + + +## Next Steps + +Now, try one of our Quick Start guides to get started with Atmos + +

Simple Tutorial

+

Advanced Tutorial

+ diff --git a/website/docs/quick-start/introduction.md b/website/docs/quick-start/introduction.md deleted file mode 100644 index 9a68b1161..000000000 --- a/website/docs/quick-start/introduction.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Quick Start Introduction -sidebar_position: 1 -sidebar_label: Introduction ---- - -# Introduction - -Atmos is a CLI and a powerful enterprise-grade workflow automation tool for DevOps. - -It's also a framework that prescribes patterns and best practices to structure and organize components and stacks to design for organizational -complexity and provision multi-account environments for complex organizations. - -It allows you to very quickly configure and provision infrastructure into many environments (e.g. AWS accounts and regions), and make those -configurations extremely [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). - -One of the main principles of Atmos is the separation of configuration from code, so the code is generic and can be deployed anywhere (in any -Organization, Organizational Unit, region, account). This design principle is -called [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns). - -Atmos separates the components (logic) and stacks (configuration of the components for diff environments) so they can be independently managed and -evolved. In the case of using Terraform, the components -are [Terraform root modules](https://developer.hashicorp.com/terraform/language/modules#the-root-module). - -In many cases, with enterprise-grade infrastructures (multi-org, multi-tenant, multi-account, multi-region, multi-team), the configuration is much -more complicated than the code. That's what Atmos is trying to solve - to make the configuration manageable, reusable (by -using [Imports](/core-concepts/stacks/imports), [Inheritance](/core-concepts/components/inheritance), and other -Atmos features) and [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), and to make the code completely generic. - -In this Quick Start guide, we describe how to provision infrastructure managed by Terraform into different AWS environments. -The configurations for the environments are managed by Atmos. - -
- -:::tip - -This Quick Start guide describes the steps to configure and provision the infrastructure -from this [Quick Start](https://github.com/cloudposse/atmos/tree/master/examples/quick-start) repository. - -You can clone it and configure to your own needs. The repository should be a good start to get yourself familiar with Atmos. - -::: - -
- -The steps to configure and provision the infrastructure are as follows: - -- [Install Atmos](/quick-start/install-atmos) -- [Configure Repository](/quick-start/configure-repository) -- [Configure CLI](/quick-start/configure-cli) -- [Vendor Components](/quick-start/vendor-components) -- [Create Atmos Stacks](/quick-start/create-atmos-stacks) -- [Configure Validation](/quick-start/configure-validation) -- [Create Workflows](/quick-start/create-workflows) -- [Add Custom Commands](/quick-start/add-custom-commands) -- [Configure Terraform Backend](/quick-start/configure-terraform-backend) -- [Provision](/quick-start/provision) -- [Final Notes](/quick-start/final-notes) -- [Next Steps](/quick-start/next-steps) diff --git a/website/docs/quick-start/introduction.mdx b/website/docs/quick-start/introduction.mdx new file mode 100644 index 000000000..40097fabd --- /dev/null +++ b/website/docs/quick-start/introduction.mdx @@ -0,0 +1,34 @@ +--- +title: Quick Start Introduction +sidebar_position: 1 +sidebar_label: Introduction +sidebar_class_name: hidden +id: quick-start +slug: /quick-start +--- +import Link from '@docusaurus/Link' +import Intro from '@site/src/components/Intro' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' + + +Atmos is a CLI and a powerful enterprise-grade workflow automation tool for DevOps. It's also a framework that prescribes patterns and best practices to structure and organize components and stacks to design for organizational complexity and provision multi-account environments for complex organizations. + + +It allows you to very quickly configure and provision infrastructure into many environments (e.g. AWS accounts and regions), and make those configurations extremely [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). + +One of the main principles of Atmos is the separation of configuration from code, so the code is generic and can be deployed anywhere (in any Organization, Organizational Unit, region, account). This design principle is called [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns). + +Atmos separates the components (logic) and stacks (configuration of the components for different environments) so they can be independently managed and evolved. In the case of using Terraform, the components are [Terraform root modules](https://developer.hashicorp.com/terraform/language/modules#the-root-module). + +In many cases, with enterprise-grade infrastructures (multi-org, multi-tenant, multi-account, multi-region, multi-team), the configuration is much more complicated than the code. That's what Atmos is trying to solve - to make the configuration manageable, reusable (by using [Imports](/core-concepts/stacks/imports), [Inheritance](/core-concepts/stacks/inheritance), and other Atmos features) and [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), and to make the code completely generic. + +In this Quick Start guide, we describe how to provision infrastructure managed by Terraform into different AWS environments. Atmos manages the configurations for the environments. + + + Try our Simple Tutorial + + + + Try our Advanced Tutorial + diff --git a/website/docs/quick-start/mindset.mdx b/website/docs/quick-start/mindset.mdx new file mode 100644 index 000000000..b4b31778a --- /dev/null +++ b/website/docs/quick-start/mindset.mdx @@ -0,0 +1,252 @@ +--- +title: Thinking Like Atmos +sidebar_position: 2 +sidebar_label: Atmos Mindset +id: mindset +--- +import Link from '@docusaurus/Link' +import KeyPoints from '@site/src/components/KeyPoints' +import Screengrab from '@site/src/components/Screengrab'; +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' + + + Atmos can change how you think about the Terraform code you write to build your infrastructure. + + When you design cloud architectures with Atmos, you will first break them apart into pieces called components. Then, you will implement Terraform "root modules" for each of those components. Finally, compose your components in any way you like using stacks, without the need to write any code or messy templates for code generation. + + +In this tutorial, we’ll guide you through the thought process of building Terraform "root modules" that are suitable for use as components. To ensure your components are highly reusable, parameterize them with variables. +Design them to serve a single purpose, making them the smallest possible unit of infrastructure in a typical +software development lifecycle (SDLC). Group pieces that usually change together, and separate those that change independently. + + +You're about to discover a new way to think about terraform... + + + Try our Simple Tutorial + + + + Learn Atmos + + + +

Your Architecture is Made up of Components

+ +Start by thinking about your architecture in terms of its logical components. + +For example, let’s consider the architecture of a typical modern website. Its components might include a network, a cluster, some applications running on it, a database to store data, a cache, and maybe some object storage. + +```mermaid +--- +title: Infrastructure Components of a Typical Website +--- + +graph TD + + subgraph Network + style Network fill:none + subgraph Cluster + style Cluster fill:#ffffff15 + App1(Application 1) + App2(Application 2) + end + LB[[Load Balancer]] + DB[(Database)] + Cache[(Cache)] + ObjectStorage[(Object Storage)] + end + LB --> App1 + LB --> App2 + App1 --> DB + App1 --> Cache + App2 --> ObjectStorage +``` + +Each of these logical pieces is a component and typically changes independently. + +They are loosely related and this relationship forms a stack. A stack logically combines components without tightly coupling them, +ensuring each component’s state is separate. This approach minimizes the blast radius of changes, keeps the state separate, and +allows teams to own components. Plus, it encourages reuse since there is a finite number of ways to express infrastructure. + +Then, to implement this architecture with Atmos, you will usually follow these same five steps every time. + +
+Why don't we just put everything into a single "Root module"? + +The goal should be to build a loosely coupled [service-oriented architecture (SOA)](https://en.wikipedia.org/wiki/Service-oriented_architecture). Like with modern app design, we should avoid monolithic infrastructure code. Decoupling our infrastructure into [components](/core-concepts/components) ensures resilience and maintainability. + +When we place all the infrastructure into a single "root module," we end up with a [Terralith](/terms/terralith), which is roughly [Stage-2 of the Terraform maturity path](/introduction/why-atmos/stage-2). All your eggs are in one basket. + +- Massive blast radius for every change +- Brittle and prolonged plan/apply cycles +- All your state is in one place + +Large root modules are less reusable across teams due to varying requirements, resulting in many specialized root modules without significant benefits. As these root modules grow, they become increasingly time-consuming to plan and apply. This can even lead to hitting cloud provider rate limits, rendering your infrastructure code undeployable. +
+ +## The Five Steps of Atmos + + + ### Start Your Project + + Create a solid foundation with a well-structured folder layout, embracing best practices and conventions for a consistently organized project. By convention, we recommend keeping all configurations separate from your components, which helps ensure your components' reusability across teams. + +
+ See Example + +
+ + + Projects are organized into a well-structured folder layout, embracing best practices and conventions for a consistently organized project. + Learn About Projects + + +
+ + + ### Write Your Components (e.g. Terraform Root Modules) + + For each component in your architecture, write a Terraform root module. + + Use your existing Terraform root modules or create new ones. As your component library grows, you’ll need to write fewer new components, enabling faster development cycles by reusing infrastructure components across projects. + + Try to reuse 80% of your components across projects, and only write new ones when necessary. + + + ```mermaid + --- + title: Example of Typical Root Modules + --- + flowchart TB + subgraph Network ["Network"] + style Network fill:none + VPC[VPC Network Root Module] + LB[Load Balancer Root Module] + end + + subgraph Platform ["App Platform"] + style Platform fill:none + Cluster[Cluster Root Module] + App["Application Root Module(s)"] + end + + subgraph Services ["Backing Services"] + style Services fill:none + DB[Database Root Module] + Cache[Cache Root Module] + ObjectStorage[Object Storage Root Module] + end + + ``` + Each component stands alone as its own “root module.” Think of them as layers if it helps. + + What you should end up with are "root modules" for each of these pieces. Something like this... +
+ See Example + +
+ + + Components form the essential building blocks of your architecture. They are the smallest unit of infrastructure in a typical software development lifecycle (SDLC). + Learn Atmos Components + +
+ + + ### Pass Values Between Components + + Use Terraform's native ability to read the remote state or configuration of any other component, for a "loosely coupled" architecture. Atmos provides [methods that make this easy](/core-concepts/share-data). + + ```mermaid + classDiagram + class Network["VPC (root module)"] { + outputs: vpc_id + } + + class TerraformStateBackend["Terraform State Backend (e.g S3)"] { + vpc_id: 12345 + } + + class Cluster["Kubernetes Cluster (root module)"] { + needs: vpc_id + } + + Network --> TerraformStateBackend : Stores Output + Cluster --> TerraformStateBackend : Reads Remote State + Cluster ..> Network : Loosely Depends on + + ``` + + + Passing state between components is how you build a loosely coupled architecture. + Learn How + + + + + ### Configure Your Components with Stacks + + Configure your environments such as development, staging, and production—each tailored to different stages of the lifecycle, ensuring smooth transitions and robust deployment strategies. Use a combination imports and inheritance for a template-free way to keep your configurations DRY and enforce consistency across your stacks. + +
+ See Example + +
+ + Components are configured with Stacks, which are defined om YAML. Stacks are separate from Components (terraform root modules) to ensure root modules remain highly reusable across teams and promote testing. + Learn Configuration + +
+ + + ### Deploy Stacks with Atmos 🚀 + + Execute deployments with precision using Terraform's `plan` and `apply` commands, fully integrated with [native GitOps workflows](/integrations) through [GitHub Actions](/integrations/github-actions) for seamless deployment automation. Leverage [workflows](/core-concepts/workflows) to orchestrate more complicated deployments that involve multiple steps. + + ```mermaid + graph LR + Dev[Development] + Stage[Staging] + Prod[Production] + + Dev --> Stage + Stage --> Prod + ``` + +
+ See Example + +
+ + Deploy Components with Atmos, fully integrated with GitOps workflows through GitHub Actions for seamless deployment automation. + Deploying with Atmos + +
+ +## Where to Go From Here + +This brief introduction covered the essentials of designing cloud architectures that can be used with Atmos. + +Now you can start with your first Atmos project! Try out our [Simple](/quick-start/simple)/[Advanced](/quick-start/advanced) Quick Start, +or delve deeper into the [syntax and concepts](/core-concepts) used in this tutorial. + + + Try our Simple Tutorial + + + + Learn Atmos + diff --git a/website/docs/quick-start/quick-start.mdx b/website/docs/quick-start/quick-start.mdx deleted file mode 100644 index 27faefbd4..000000000 --- a/website/docs/quick-start/quick-start.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Quick Start -sidebar_position: 2 -sidebar_label: Quick Start -description: Take 30 minutes to learn the most important Atmos concepts. -id: quick-start ---- - -# Quick Start - -Take 30 minutes to learn the most important Atmos concepts. - -## Thinking in Atmos - -Atmos can change how you think about the designs and the infrastructure you build. -When you build infrastructure with Atmos, you will first break it apart into pieces called components. -Then, you will describe the different configurations for each of your components. -Finally, you will connect your components together so that the data flows through them. -In this Quick Start, we’ll guide you through the thought process of building an infrastructure with Atmos. - -
- -import DocCardList from "@theme/DocCardList"; - - diff --git a/website/docs/quick-start/simple/configure-cli.mdx b/website/docs/quick-start/simple/configure-cli.mdx new file mode 100644 index 000000000..dada28dd6 --- /dev/null +++ b/website/docs/quick-start/simple/configure-cli.mdx @@ -0,0 +1,183 @@ +--- +title: Configure Atmos CLI +sidebar_position: 2 +sidebar_label: 2. Configure Atmos CLI +--- +import EmbedFile from '@site/src/components/EmbedFile' +import KeyPoints from '@site/src/components/KeyPoints' +import Screengrab from '@site/src/components/Screengrab' +import LatestRelease from '@site/src/components/LatestRelease' +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' +import Note from '@site/src/components/Note' + + +The `atmos.yaml` configuration file controls the behavior of the `atmos` CLI and how Atmos will work with your project. + + +Therefore, this file should exist in the project repository alongside your Terraform components and Atmos stacks. It's also where you can [configure integrations](/integrations), like with our [GitHub Actions](/integrations/github-actions). + + +- How install `atmos` and make sure you're on a current version +- How to configure `atmos.yaml` for your project's filesystem layout +- How Atmos identifies stack configurations using context variables and naming patterns + + + + +## Install Atmos +Let's ensure you've [properly installed Atmos](/install) by running the following command. + +```bash +atmos --version +``` + +You should see something like this... + +the current release of Atmos is **** + + + +## Configure `atmos.yaml` for your project +To configure Atmos to work with your project, we'll create a file called `atmos.yaml` to tell Atmos where to find the +Terraform components and Atmos stacks. Almost everything in Atmos is configurable via this file. + +Below is the minimum recommended configuration for Atmos to work with Terraform and to configure [Atmos components](/core-concepts/components) +and [Atmos stacks](/core-concepts/stacks). Copy this YAML config below into your `atmos.yaml` file. + + + +For the description of all the sections, refer to [CLI Configuration](/cli/configuration). + + + +## Understand what it's doing + +And here's what all that means... + +### Basic Settings + +
+
`stacks.name_pattern`
+
+ Atmos uses “slugs” to refer to stacks, which are defined by the `name_pattern` setting.
+ Instead of relying on file names and locations, which can change, Atmos uses context variables (`namespace`, `tenant`, `environment`, `stage`) + to identify the stack. For example, with the command `atmos terraform apply myapp -s dev`, + Atmos interprets the slug `dev` using the pattern `{stage}` to locate the correct stack configuration + in the stacks directory. +
+ +
`logs.level`
+
+ Set to `Info` to see the most helpful logs. You can also set it to `Trace` to see all the logs, which is helpful for debugging. +
+ +
`logs.file`
+
+ Set to `/dev/stderr` to send all of Atmos output to the standard error stream. This is useful when running Atmos in a CI/CD pipeline. +
+
+ +### Path Configuration + +Well-known paths are how Atmos finds all your stack configurations, components, and workflows. Here are the essential paths that you need to configure: + +
+
`base_path`
+
The base path for components, stacks, and workflow configurations. We set it to an empty string because we've decided to use the ENV var `ATMOS_BASE_PATH` to point to the absolute path of the root of the repo
+ +
`components.terraform.base_path`
+
The base path to the Terraform components (Terraform root modules). As described in [Configure Repository](/quick-start/advanced/configure-repository), we've decided to put the Terraform components into the `components/terraform` directory, and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENV var) with `components.terraform.base_path` to calculate the final path to the Terraform components
+ +
`stacks.base_path`
+
The base path to the Atmos stacks. As described in [Configure Repository](/quick-start/advanced/configure-repository), we've decided to put the stack configurations into the `stacks` directory, and this setting tells Atmos where to find them. Atmos will join the base path (set in the `ATMOS_BASE_PATH` ENV var) with `stacks.base_path` to calculate the final path to the stacks
+ +
`stacks.included_paths`
+
List of file paths to the top-level stacks in the `stacks` directory to include in search when Atmos searches for the stack where the component is defined when executing `atmos` commands
+ +
`stacks.excluded_paths`
+
List of file paths to the top-level stacks in the `stacks` directory to exclude from search when Atmos searches for the stack where the component is defined when executing `atmos` commands
+ +
`workflows.base_path`
+
The base path to Atmos [Workflows](/core-concepts/workflows) files
+
+ + +
+Advanced Options +
+
components.terraform.apply_auto_approve
+
if set to `true`, Atmos automatically adds the `-auto-approve` option to instruct Terraform to apply the plan without + asking for confirmation when executing `terraform apply` command
+ +
`components.terraform.deploy_run_init`
+
if set to `true`, Atmos runs `terraform init` before executing [`atmos terraform deploy`](/cli/commands/terraform/deploy) command
+ +
`components.terraform.init_run_reconfigure`
+
if set to `true`, Atmos automatically adds the `-reconfigure` option to update the backend configuration when executing `terraform init` command
+ +
`components.terraform.auto_generate_backend_file`
+
if set to `true`, Atmos automatically generates the Terraform backend file from the component configuration when executing `terraform plan` and `terraform apply` commands
+ +
`commands`
+
configuration for [Atmos Custom Commands](/core-concepts/custom-commands)
+ +
`schemas`
+
+ [JSON Schema](https://json-schema.org/) and [OPA Policy](https://www.openpolicyagent.org/) configurations for: + - [Atmos Manifests Validation](/cli/schemas) + - [Atmos Stack Validation](/core-concepts/validate) +
+
+ +
+ + +### Config File Location + +While placing `atmos.yaml` at the root of the repository will work for the `atmos` CLI, it will not work +for [Component Remote State](/core-concepts/components/terraform/remote-state) because it uses +the [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider. Terraform executes the provider from the +component's folder (e.g. `components/terraform/vpc`), and we don't want to replicate `atmos.yaml` into every component's folder. + +Both the `atmos` CLI and [terraform-provider-utils](https://github.com/cloudposse/terraform-provider-utils) Terraform provider use the same `Go` code, +which try to locate the [CLI config](/cli/configuration) `atmos.yaml` file before parsing and processing [Atmos stacks](/core-concepts/stacks). + +This means that `atmos.yaml` file must be at a location in the file system where all processes can find it. + +
+How is the `atmos.yaml` file located? + +`atmos.yaml` is loaded from the following locations (from lowest to highest priority): + +- System dir (`/usr/local/etc/atmos/atmos.yaml` on Linux, `%LOCALAPPDATA%/atmos/atmos.yaml` on Windows) +- Home dir (`~/.atmos/atmos.yaml`) +- Current directory +- ENV var `ATMOS_CLI_CONFIG_PATH` + +:::note + +Initial Atmos configuration can be controlled by these ENV vars: + +
+
`ATMOS_CLI_CONFIG_PATH`
+
Directory that contains the `atmos.yaml` (just the folder without the file name). It's not possible to change the filename at this time.
+ +
`ATMOS_BASE_PATH`
+
Base path to the `components/` and `stacks/` folders.
+
+::: +
+
+ + + Now you're ready to learn how to write your first Atmos component using Terraform. +
+ Next Step + Deep Dive +
+
diff --git a/website/docs/quick-start/simple/configure-project.mdx b/website/docs/quick-start/simple/configure-project.mdx new file mode 100644 index 000000000..215318685 --- /dev/null +++ b/website/docs/quick-start/simple/configure-project.mdx @@ -0,0 +1,123 @@ +--- +title: Start Your Project +sidebar_position: 1 +sidebar_label: 1. Start Your Project +--- +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' + + +The folder structure for an Atmos project is designed to organize your infrastructure effectively on the file system. It separates configuration from code, ensuring your Terraform root modules are distinct and reusable. + + +While you can customize the structure using the `atmos.yaml` configuration, we will start with a simple layout to get you started. + + +- Why Atmos works best with monorepos +- How to structure your project repository on the filesystem +- Where to put your Terraform "root modules" and Stack configurations + + + +Atmos works best with [monorepo](https://en.wikipedia.org/wiki/Monorepo) infrastructure repositories when managing the configurations for components +and stacks. For example, multiple monorepos can also be used for different teams or products. Monorepos are recommended because they provide a single source of truth for all configurations and simplify infrastructure management. + + +
+What is a monorepo? + +A "monorepo" is a version-controlled repository that stores all the code, configurations and scripts for the entire infrastructure composed of individual components with independent lifecycles. Monorepos usually improve collaboration, CI/CD build speed, and overall productivity. A monorepo should not be confused with a [monolith](https://en.wikipedia.org/wiki/Monolithic_application), which is a single, often large, codebase for an application. + +Polyrepo architectures consist of several version-controlled repositories for code, configurations and scripts for different parts of the infrastructure. For example, depending on various requirements (including security, lifecycle management, access control, audit, etc.), separate repositories can be used to manage infrastructure per account (e.g. `dev`, `staging`, `prod`), per service, or per team. +
+ + +## Filesystem Layout + + +Here's what it will look like on the filesystem: + +```console +   │   # Atmos CLI configuration +   ├── atmos.yaml +   │   +   │   # Centralized stacks configuration +   ├── stacks/ +   │   ├── .yaml +   │   ├── .yaml +   │   └── .yaml +   │   +   │   # Centralized components configuration. Components are broken down by tool +   └── components/ +       └── terraform/ # Terraform root modules +           └── myapp/ +``` + +Ultimately, the paths are all configurable via the `atmos.yaml` CLI Configuration file, which we'll cover in the next chapter. + +## Common Directories and Files + +Atmos requires a few common directories and files, which need to be configured in the infrastructure repo: + +
+
`components/` directory (required)
+
contains centralized component configurations
+ +
`stacks/` directory (required)
+
contains centralized stack configurations
+ +
`atmos.yaml` (required)
+
Atmos CLI config file
+ +
+ +:::tip + +The source code for this Quick Start guide can be found in the [Atmos repo](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-simple) demo repository. (It's similar to the demo you see on the Atmos landing page) + +You can clone it and tweak it to your own needs. The example should be a good start for getting familiar with Atmos. + +::: + +Atmos separates code from configuration ([separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns)). All the code is stored in the `components` directories, and the configurations for different environments are stored in the `stacks` directory. This allows the code (Terraform root modules and Helmfile components) to be environment-agnostic, meaning the components don't know and don't care how and where they will be provisioned. They can be provisioned into many accounts and regions - the configurations for different environments are defined in the `stacks` directory. + +:::note +While it's recommended to use the directory names as shown above, the `stacks` and `components` directory names and filesystem locations are configurable in the `atmos.yaml` CLI config file. Refer to [Configure CLI](/quick-start/advanced/configure-cli) for more details. +::: + +The following example provides the simplest filesystem layout that Atmos can work with: + +```console +   │   # Centralized stacks configuration +   ├── stacks/ +   │   ├── .yaml +   │   ├── .yaml +   │   └── .yaml +   │   +   │   # Centralized components configuration. Components are broken down by tool +   ├── components/ +   │   └── terraform/ # Terraform root modules +   │      ├── / +   │      ├── / +   │      └── / +  │ +   │   # Atmos CLI configuration +   ├── atmos.yaml +   │ +   │   # Atmos vendoring configuration +   └── vendor.yaml +``` + + + Now you're ready to learn how to configure the Atmos CLI to work with your project. +
+ Next Step + Deep Dive +
+
+ + + diff --git a/website/docs/quick-start/simple/configure-stacks.mdx b/website/docs/quick-start/simple/configure-stacks.mdx new file mode 100644 index 000000000..b31b68312 --- /dev/null +++ b/website/docs/quick-start/simple/configure-stacks.mdx @@ -0,0 +1,166 @@ +--- +title: Use Your Component in a Stack +sidebar_position: 4 +sidebar_label: 4. Configure with Stacks +--- +import File from '@site/src/components/File' +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' +import EmbedFile from '@site/src/components/EmbedFile' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import Note from '@site/src/components/Note' + + +[Atmos Stacks](/core-concepts/stacks) are the configuration for your components. It's how you can combine multiple reusable, stateful +components into your "Stack" that you depend on. + + +If you think of your "components" as applications, then Stacks are simply which components you depend on and the settings that you want +to pass to them. If you make your components highly reusable, it usually means they will need to accept a lot of configuration. + +**This is what makes Atmos so powerful:** you can import and inherit configurations in a logical way to keep your configurations DRY and consistent. + + +- How to specify the configuration for your Terraform "root modules" using Atmos Stacks +- How to organize Atmos Stacks into a Service Catalog +- How to use imports and inheritance for DRY configurations +- How Atmos identifies components using context variables and naming patterns + + +Stack configurations are merely all the settings for your components. They can be organized in any way you like, but we recommend a hierarchical layout. We share some [different ways to organize your stacks in the Catalog](/core-concepts/stacks/catalogs), but for this example, we will use a simple layout. + +## Create Catalog for Reusable Configurations + +Atmos supports the concept of a [Service Catalog](/core-concepts/stacks/catalogs), which is where you can define all +of your default configurations. + +All the common default settings for each Atmos component should be in a separate file in the `stacks/catalog` directory. +The file then gets imported into the parent Atmos stacks. This makes the stack configurations DRY by reusing the component's config that is common for all environments. + +Refer to [Stack Imports](/core-concepts/stacks/imports) for more details on Atmos imports. + +These Atmos component manifests will be imported into the top-level Atmos stacks. The default variables (in the `vars` sections) +can be overridden in the derived Atmos components by using [Atmos Component Inheritance](/core-concepts/stacks/inheritance). + +## Atmos Top-level Stacks + +When executing the [CLI commands](/cheatsheets/commands), Atmos does not use the stack file names and their filesystem locations to search for the stack where the component is defined. Instead, Atmos uses the context variables (`namespace`, `tenant`, `environment`, `stage`) to search for the stack. The stack config file names (stack manifest names) can be anything, and they can be in any folder in any sub-folder in the `stacks` directory. + +For example, when executing the `atmos terraform apply station -s dev` command, the Atmos stack `dev` is specified by the `-s` flag. By looking at `name_pattern: "{stage}"` (see [Configure CLI](/quick-start/advanced/configure-cli)) and processing the tokens, Atmos knows that the `stage` is `dev`. This `name_pattern` also supports `{namespace}`, `{tenant}`, and `{environment}`. + +
+
`{namespace}`
+
Corresponds to `var.namespace` in the stack configuration.
+ +
`{tenant}`
+
Corresponds to `var.tenant` in the stack configuration.
+ +
`{environment}`
+
Corresponds to `var.environment` in the stack configuration.
+ +
`{stage}`
+
Corresponds to `var.stage` in the stack configuration.
+
+ +Atmos top-level stacks can be configured using a Basic Layout or a Hierarchical Layout. + +The Basic Layout can be used when you have a very simple configuration using just a few stages. A more Hierarchical Layout should be used when you have a very complex organization, for example, with many AWS Organizational Units (which Atmos refers to as tenants) and dozens of AWS accounts and regions. + +### Basic Layout + +A basic form of stack organization is to follow the pattern of naming where each `$environment-$stage.yaml` is a file. This works well until you have so many environments and stages. + +For example, `$stage` might be `prod`, which would result in `stacks/deploy/prod.yaml` + +In our example, the filesystem layout for the stacks uses a Basic Layout with `dev`, `staging` and `prod` and +would look like this: + + +```console +├── atmos.yaml +├── components/ +│ └── terraform/ +│ └── weather/ +│ ├── README.md +│ ├── main.tf +│ ├── outputs.tf +│ ├── variables.tf +│ └── versions.tf +│ +│ # Centralized stacks configuration +└── stacks/ + ├── catalog/ + │ └── station.yaml + └── deploy/ + ├── dev.yaml + ├── prod.yaml + └── staging.yaml +``` + + +## Create Stack Configurations for Deployment + +Since this is a simple Quick Start, we will just use a single Terraform component (`components/terraform/weather`); in a real-world scenario, you may have dozens of components that comprise your stack. Rest assured, the process is the same for all components. + +### Define the Baseline Configuration +We’ll start by defining the baseline configuration of our Terraform root module to gather weather data. The name of our component’s configuration doesn’t need to match the name of the component folder. This allows us to deploy multiple instances of our component using different names. + +```yaml +components: + terraform: + : +``` + +To specify which component to use, set the `metadata.component` property to the path of the component's directory, relative to the `components.base_path` as defined in the `atmos.yaml`. In our case, the `components.base_path` is `components/terraform`, so we can simply specify `weather` as the path. + + +```yaml +components: + terraform: + station: + metadata: + component: weather +``` +To support multiple versions of a component, simply place each component version in a subfolder, which is the typical convention for versioning in a monorepo. For example, `components/terraform/weather/v1`. The goal for maintainable infrastructure as code is to have as few versions as possible and to have all environments converge on the same version. + +So the complete baseline definition for our weather station configuration might look something like the following. + + + +It's important to quote strings that start with zeros (e.g., `0001`) in YAML to prevent them from being interpreted as integers. This is how YAML processes it, and not something special about Atmos. + +### Define the Environment-specific Configurations + +Next, we’ll define the environment-specific configurations for our Terraform root module. We’ll create a separate file for each environment and stage. In our case, we have three environments: `dev`, `staging`, and `prod`. + +When Atmos processes this stack config, it will first import and deep-merge all the variables from the imported files, then overlay the inline configuration. While the order of keys in a YAML map doesn’t affect behavior, lists are strictly ordered. Therefore, the order of `imports` is important. + +#### Define the `dev` Environment Configuration + +In the `dev` stack configuration, Atmos first processes the `imports` in the order defined. Then, it applies the globals `vars` defined in the top-level section. Only include `vars` in the globals that are true for every single component in the stack. If that's not the case, define them on a per-component basis. + +For example, by setting `var.stage` to `dev` at a global level, we assume that every component in this stack will have a stage variable. + +Finally, in the component-specific configuration for the `station`, we set the fine-tuned parameters for this environment. Everything else gets inherited from its baseline configuration. There are no strict rules about where to place configurations. Organize them in a way that makes logical sense for your infrastructure’s data model. + + + +#### Define the `staging` Environment Configuration + +The staging stack configuration is almost identical to the dev stack. The only changes are the location and language settings. Everything else stays the same as the baseline configuration, ensuring that the staging and dev environments are very similar. + + + +#### Define the `prod` Environment Configuration + +And finally, we have the production (`prod`) stack. Much like the `staging` and `dev` stacks, it’s very similar to the baseline configuration but with some parameter changes. In this setup, all three stacks are separate, share the same component, and vary the station's parameters as needed. + + + +Now, we're finally ready to deploy our components. We'll show you how to do this in the next step. + + + You can do so much more with stacks! We're just scratching the surface. If you want [learn about imports, inheritance, templating, etc](/core-concepts/stacks), check out the Core Concepts. + Learn More + diff --git a/website/docs/quick-start/simple/extra-credit/_category_.json b/website/docs/quick-start/simple/extra-credit/_category_.json new file mode 100644 index 000000000..8e86b84ab --- /dev/null +++ b/website/docs/quick-start/simple/extra-credit/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Extra Credit!", + "position": 7, + "collapsible": true, + "collapsed": true +} diff --git a/website/docs/quick-start/simple/extra-credit/add-another-component.mdx b/website/docs/quick-start/simple/extra-credit/add-another-component.mdx new file mode 100644 index 000000000..6d25e4a5f --- /dev/null +++ b/website/docs/quick-start/simple/extra-credit/add-another-component.mdx @@ -0,0 +1,68 @@ +--- +title: 'Deploy Another App' +sidebar_position: 1 +sidebar_label: 'Deploy Another App' +description: Provision multiple components in the same stack +--- +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import Note from '@site/src/components/Note' + + +We can provision more than one instance of the same Terraform component (with the same or different settings) +into the same environment by defining many Atmos components that provide configuration for the Terraform component. + + +For example, the following config shows how to define two Atmos components, `station/1` and `station/2`, which both point to the same Terraform component `components/terraform/weather`. + +The `station/1` and `station/2` naming convention doesn't have any inherent meaning. Atmos simply interprets them as two different strings. Feel free to use whatever format you prefer. + + +```yaml +import: + # Import the baseline for all station components + - catalog/station + +components: + terraform: + # Atmos component `station/1` + station/1: + metadata: + # Point to the Terraform component in `components/terraform/weather` + component: weather + # Inherit the defaults for all station components + inherits: + - station + # Define/override variables specific to this `station/1` component + vars: + name: station-1 + + # Atmos component `station/2` + station/2: + metadata: + # Point to the Terraform component in `components/terraform/weather` + component: weather + # Inherit the defaults for all station components + inherits: + - station + # Define/override variables specific to this `station/2` component + vars: + name: station-2 +``` + + +In this example, we've included more information than necessary to demonstrate the concept. For instance, we explicitly added `inherits` to show how you can use multiple inheritance to merge multiple baseline configurations. We also specified the component path in both instances, even though it's already defined in the baseline configuration. This redundancy is just to emphasize that both are pointing to the same component. + +Then we can execute the following `atmos` commands to provision the two stations into the `dev` environment: + +```shell +# Provision the first weather station +atmos terraform apply station/1 -s dev +# Provision the second weather station +atmos terraform apply station/2 --stack dev +``` +You can use the shorthand `-s` flag to specify the stack name, or the long form `--stack`. They both do the same thing + +Sweet! You’ve just finished your first Atmos QuickStart tutorial. Now you're at a crossroads with two options: you can continue to the bonus materials for some extra credit, or dive deeper into the core concepts and learn the Atmos Fundamentals. diff --git a/website/docs/quick-start/simple/extra-credit/add-custom-commands.mdx b/website/docs/quick-start/simple/extra-credit/add-custom-commands.mdx new file mode 100644 index 000000000..6c9eb43b4 --- /dev/null +++ b/website/docs/quick-start/simple/extra-credit/add-custom-commands.mdx @@ -0,0 +1,66 @@ +--- +title: Add Custom Commands +sidebar_position: 9 +sidebar_label: Add Custom Commands +description: Extend Atmos with your own custom CLI commands +--- +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import Note from '@site/src/components/Note' + + +Atmos can be easily extended to support any number of custom CLI commands. For example, imagine you wanted to add a command +like `atmos reload-database`, you can do that with custom commands. + + +Custom commands are defined in the `commands` section in `atmos.yaml` CLI configuration file. + + +Refer to [Atmos Custom Commands](/core-concepts/custom-commands) for more information about Atmos Custom Commands + + +In this Quick Start guide, we'll define two custom commands to list the Atmos stacks in the infrastructure and the components in the stacks. + + +```yaml +# Custom CLI commands +commands: +- name: ip + description: Return my current IP + steps: + - curl -s https://ifconfig.me + - echo + +# Use Nested Custom Commands +- name: "github" + commands: + - name: "status" + description: This command returns the number of stargazers for a GitHub repository + steps: + - curl -s https://www.githubstatus.com/api/v2/status.json | jq -r .status.description +``` + + +Run the following Atmos command to get the current GitHub status. + + +```console +All Systems Operational +``` + + +Run the following Atmos command to retrieve your current public IP address. + + +```console +13.37.13.37 +``` + + + + Custom commands can accept flags, arguments, and even advanced templating. + Learn More + diff --git a/website/docs/quick-start/simple/extra-credit/create-workflows.mdx b/website/docs/quick-start/simple/extra-credit/create-workflows.mdx new file mode 100644 index 000000000..992aa251e --- /dev/null +++ b/website/docs/quick-start/simple/extra-credit/create-workflows.mdx @@ -0,0 +1,113 @@ +--- +title: Automate Common Workflows +sidebar_position: 3 +sidebar_label: Create Workflows +description: Automate your repetitive tasks with workflows +--- +import Terminal from '@site/src/components/Terminal' +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' + + +[Atmos Workflows](/core-concepts/workflows) combine multiple commands into executable units of work, ideal for automating common +tasks and orchestrating “cold starts,” where you bring an environment up from scratch. + + +Workflows can call other workflows and be combined with [Custom Commands](/core-concepts/custom-commands). Usually, we use +workflows to provision some combinatino of [Terraform](/core-concepts/components/terraform) components. + +Defining workflows is entirely optional; use them if they are helpful for your project. + + +## Configure Your Project to Support Workflows + +To define workflows, update your `atmos.yaml` to tell it where to find your workflows. + +Add the following `workflows` section and configure the base path to the workflows: + +```yaml +workflows: + # Can also be set using 'ATMOS_WORKFLOWS_BASE_PATH' ENV var, or '--workflows-dir' command-line arguments + # Supports both absolute and relative paths + base_path: "stacks/workflows" +``` + + + + +## Create an Atmos Workflow + +Now, let's create a workflow in the `stacks/workflows` directory. + +```console +   │   # Centralized stacks configuration +   └── stacks/ +      └── workflows/ +          └── weather.yaml +``` + +Add the following Atmos workflows to the `stacks/workflows/weather.yaml` file: + +```yaml +name: Workflows for Weather Station +description: Atmos workflows for managing Weather Station + +workflows: + + plan-all: + description: | + Run 'terraform plan' on all 'station' components in all stacks + steps: + - command: terraform plan station -s dev + - command: terraform plan station -s staging + - command: terraform plan station -s prod + + apply-all-components: + description: | + Run 'terraform apply' on all 'station' components in all stacks + steps: + - command: terraform apply station -auto-apply -s dev + - command: terraform apply station -auto-apply -s staging + - command: terraform apply station -auto-apply -s prod +``` + + + + +## Run the Atmos Workflow + +Run the following Atmos commands to execute the workflows: + +```shell +# Execute the workflow `plan-all-vpc-flow-logs` from the workflow manifest `weather.yaml` +atmos workflow plan-all -f weather + +# Execute the workflow `apply-all-components` from the workflow manifest `weather.yaml` +atmos workflow apply-all -f weather +``` + +The `atmos workflow` CLI command supports the `--dry-run` flag. If passed, the command will just print information about +the executed workflow steps without executing them. For example: + + +```console +Executing the workflow 'plan-all' from 'stacks/workflows/weather.yaml' + +Executing workflow step: terraform plan station -s dev +Executing workflow step: terraform plan station -s staging +Executing workflow step: terraform plan station -s prod +``` + + + +:::tip +Refer to [atmos workflow](/cli/commands/workflow) for more information on the `atmos workflow` CLI command +::: + + + Workflows can do a lot more than we're showing here. Workflows support templates, and can call other workflows. + Learn More + diff --git a/website/docs/quick-start/simple/extra-credit/extra-credit.mdx b/website/docs/quick-start/simple/extra-credit/extra-credit.mdx new file mode 100644 index 000000000..48124ce80 --- /dev/null +++ b/website/docs/quick-start/simple/extra-credit/extra-credit.mdx @@ -0,0 +1,24 @@ +--- +title: 'Extra Credit!' +sidebar_position: 7 +sidebar_label: 'Extra Credit!' +--- +import KeyPoints from '@site/src/components/KeyPoints' +import DocCardList from '@theme/DocCardList' +import Intro from '@site/src/components/Intro' + + +Now we want to provide you with some bonus material because we didn’t want to overwhelm you when you were just getting started. +These are common ways we use Atmos daily in the infrastructures we manage. + + + +- How to deploy additional instances of your components. +- How to automate repetitive operations using workflows. +- How to extend the Atmos CLI by adding your own custom commands, making it easy for developers to rely on a single command. +- How to vendor all your external dependencies, which can include other components, stack configurations, and really just anything! + + +## What's Included + + diff --git a/website/docs/quick-start/simple/extra-credit/vendor-components.mdx b/website/docs/quick-start/simple/extra-credit/vendor-components.mdx new file mode 100644 index 000000000..0b39343ca --- /dev/null +++ b/website/docs/quick-start/simple/extra-credit/vendor-components.mdx @@ -0,0 +1,157 @@ +--- +title: Vendor Dependencies +sidebar_position: 2 +sidebar_label: Vendor Dependencies +description: Learn how to vendor components from remote sources +--- +import Terminal from '@site/src/components/Terminal' +import File from '@site/src/components/File' +import Intro from '@site/src/components/Intro' +import Note from '@site/src/components/Note' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' + + +In the previous steps, we wrote our own component from scratch. In practice, you'll often want to reuse components that are already available in the open-source community, or within your organization. To do that, you'll leverage vendoring. + + +Vendoring is driven by the `atmos vendor pull` command. It allows you to pull in components from remote sources, like Git repositories, and place them in your project's filesystem. This way, you can reuse components across multiple projects. The vendoring process is defined in the `vendor.yaml` file, which specifies the components to pull in, where to place them, and how to filter them. + + +For more information about Atmos Vendoring and the `atmos vendor pull` CLI command, refer to: +- [Atmos Vendoring](/core-concepts/vendor) +- [atmos vendor pull](/cli/commands/vendor/pull) + + +Let's kick the tires on this, by vendoring some more components from the [`demo-library`](https://github.com/cloudposse/atmos/tree/main/examples/demo-library). + + +## Create Vendor Manifest + +Create a `vendor.yaml` Atmos vendor config file in the root of the repo with the following content: + + +```yaml +apiVersion: atmos/v1 +kind: AtmosVendorConfig +metadata: + name: my-vendor-config + description: Example Atmos vendoring manifest +spec: + sources: + - component: "ipinfo" + source: "github.com/cloudposse/atmos.git//examples/demo-library/ipinfo?ref={{.Version}}" + version: "main" + targets: + - "components/terraform/{{.Component}}" + included_paths: + - "**/*.tf" + # If the component's folder has the `modules` sub-folder, it needs to be explicitly defined + - "**/modules/**" +``` + + +Let's unpack what's going on here. The `sources` section defines a list of components to pull in. Each component has the following attributes: +
+
`component`
+
The name of the component to pull in.
+ +
`source`
+
The source of the component. It can be a Git repository URL with an optional reference to a specific version. The `{{.Version}}` token is a placeholder for the version of the component. In this example, we're pulling in the `ipinfo` component from the `atmos` repository from the `examples/demo-library` folder.
+ +
`version`
+
The version (git ref) of the component to pull in. In this example, we're pulling in the `main` branch, but in practice you will usually pin to a tag or major release.
+ +
`targets`
+
The target directories where the component will be placed. In this example, we're placing the `ipinfo` component in the `components/terraform/ipinfo` directory, because we reference the `{{ .Component }}`
+ +
`included_paths`
+
+ A list of file paths to include in the vendored component. In this example, we're including all `.tf` files and any files in the `modules` sub-folder. + + The `glob` library that Atmos uses to download remote artifacts does not treat the double-star `**` as including sub-folders. + If the component's folder has sub-folders, and you need to vendor them, they have to be explicitly defined as in the following example. + +
+ +
`excluded_paths`
+
A list of file paths to exclude from the vendored component.
+ +
+ + +If you have a lot of dependencies, it can be helpful to break them down into smaller, more manageable pieces. You can do this by importing other vendoring configurations. Just define the `imports` section in the `vendor.yaml` file. + + +```yaml +apiVersion: atmos/v1 +kind: AtmosVendorConfig +metadata: + name: my-vendor-config + description: Example Atmos vendoring manifest +spec: + imports: vendor/**.yaml +``` + + +In this example, could add additional vendoring configurations in the `vendor/` directory, and they will be imported into the main vendoring configuration. + + +
+ + + ## Pull the Components + Execute the command `atmos vendor pull` from the root of the repo + + + ```shell + Processing vendor config file 'vendor.yaml' + + Pulling sources for the component 'ipinfo' + from 'github.com/cloudposse/atmos.git//examples/demo-library/ipinfo?ref=main' + into 'components/terraform/ipinfo' + ``` + + + After the command completes, the filesystem layout should look like this (in addition to any other files you already had): + + ```console +    │ +    ├── stacks/ +    │ +    └── components/ +        └── terraform/ # Terraform root modules +            └── ipinfo/ # Vendored component +               ├── main.tf +               ├── outputs.tf +               ├── providers.tf +               ├── variables.tf +               └── versions.tf + ``` + + + + + ## Configure Component in Stack + + Now that the component is vendored, you can use it in your stack configurations. For example, you can include the `ipinfo` component in your stack configuration like this: + + + ```yaml + terraform: + components: + ipinfo: + metadata: + component: ipinfo + vars: {} + ``` + + + + + + Vendoring is a critical concept to master, if you want to reuse components across multiple projects. + Learn More + diff --git a/website/docs/quick-start/simple/provision.mdx b/website/docs/quick-start/simple/provision.mdx new file mode 100644 index 000000000..fcb3151d6 --- /dev/null +++ b/website/docs/quick-start/simple/provision.mdx @@ -0,0 +1,68 @@ +--- +title: Deploy Everything +sidebar_position: 5 +sidebar_label: 5. Deploy Everything +--- +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' + + +After you've written your components and configured your stacks, now we're ready to deploy them! + + + +- How Atmos identifies components using context variables and naming patterns +- How to preview your configurations and changes before applying them +- How to deploy your components, one at a time + + +## Provision Atmos Components into all Stacks + +Provision the `vpc-flow-logs-bucket` Atmos component into the stacks: + +```shell +atmos terraform apply myapp -s dev + +atmos terraform apply myapp -s staging + +atmos terraform apply myapp -s prod +``` + +Alternatively, you can execute the configured [Atmos workflow](/quick-start/advanced/create-workflows) to provision all the components in all the stacks: + +```shell +# Execute the workflow `apply-all-components` from the workflow manifest `networking` +atmos workflow apply-all-components -f networking +``` + +## Stack Search Algorithm + +Looking at the commands above, you might have a question "How does Atmos find the component in the stack and all the variables?" + +Let's consider what Atmos does when executing the command `atmos terraform apply vpc -s plat-ue2-prod`: + +- Atmos uses the `stacks.name_pattern` defined in the [CLI config](/quick-start/advanced/configure-cli). In this example, we have defined a simple name based on `stacks.name_pattern: "{stage}"`. This means that the stack name is just the `stage` part of the stack name. + +- Atmos searches for the stack configuration file (in the `stacks` folder and all sub-folders) where `tenant: plat`, `environment: ue2` + and `stage: prod` are defined (inline or via imports). During the search, Atmos processes all parent (top-level) config files and compares the context variables specified in the command (`-s` flag) with the context variables defined in the stack configurations, finally finding the matching stack + +- Atmos finds the component `myapp` in the stack, processing all the inline configs and all the imports + +- Atmos deep-merges all the catalog imports for the `myapp` component and then deep-merges all the variables for the component defined in all sections (global `vars`, terraform `vars`, base components `vars`, component `vars`), producing the final variables for the `myapp` component in the `prod` stack + +- And lastly, Atmos writes the final deep-merged variables into a `.tfvar.json` file in the component directory and then + executes `terraform apply -var-file ...` command + + + Now that you’ve seen Atmos in action, you can explore the extra credit! + + Or take a moment to explore its core concepts. You have only just scratched the surface of Atmos. Atmos is a powerful enterprise-grade framework with so **much more to offer**! + +
+ Extra Credit + Deep Dive +
+
diff --git a/website/docs/quick-start/simple/simple.mdx b/website/docs/quick-start/simple/simple.mdx new file mode 100644 index 000000000..7ac107051 --- /dev/null +++ b/website/docs/quick-start/simple/simple.mdx @@ -0,0 +1,79 @@ +--- +title: Simple Atmos Tutorial +sidebar_position: 3 +sidebar_label: Simple Tutorial +description: Take 30 minutes to learn the most important Atmos concepts. +id: simple +--- +import PillBox from '@site/src/components/PillBox' +import DocCardList from '@theme/DocCardList' +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' + +Easy + + +In this simple example, we will show you, how you can Terraform the weather. We won’t focus on more advanced concepts like configuring state backends or integrating with specific cloud providers, +allowing us to concentrate on the core concepts of Atmos. + + +You're about to discover [a new way to think about terraform...](/quick-start/mindset) + + +1. How to set up a project repository to organize your Terraform code and configurations +2. How to configure the Atmos CLI to work with the project +3. Write a simple Terraform root module +4. How to create stacks and configure the root module as a component of a stack +5. Finally, how to deploy everything using Atmos + + + +**Spoiler alert** You can’t actually change the weather with Terraform, but you can certainly ask for it. + +We’ll [use this example](https://github.com/cloudposse/atmos/tree/master/examples/demo-stacks) to avoid relying on complicated cloud credentials, which can vary based on your organizational context and cloud provider. Instead, we want to focus on Terraform and how to utilize it effectively as a component within Atmos. Once you understand this, you’ll see how to tailor your Terraform "root modules" to work seamlessly with Atmos. + +__NOTE:__ This tutorial is for those who prefer hands-on learning and want to create something tangible quickly. +If you prefer to learn theory and concepts first, start with the [Core Concepts](/core-concepts). + +## Prerequisites + +Here's what you'll need to get started with this tutorial. + +- [Install Atmos](/install) +- [Install Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) + +:::tip Use GitHub Codespaces + +**You can try out `atmos` directly in your browser using GitHub Codespaces** + +We bundle all the examples and tools you need to get started with Atmos in a GitHub Codespace. Click the button below to start a new Codespace with the Atmos repository (it's FREE). + +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=cloudposse/atmos&skip_quickstart=true) +
Already start one? Find it [here](https://github.com/codespaces).
+ +::: + +Then, when you're ready for a deeper understanding of using Atmos with Terraform, handling state management and working with +AWS authentication, please refer to our [advanced quick start guide](/quick-start/advanced). + +## Extra Credit + +After you finish mastering the basics, maybe check out the "Extra Credit" exercises to learn how to... + +- [Deploy additional instances of your components](/quick-start/simple/extra-credit/add-another-component) +- [Automate common operations with workflows](/quick-start/simple/extra-credit/create-workflows) +- [Customize the Atmos CLI by adding your own commands](/quick-start/simple/extra-credit/add-custom-commands) +- [Vendor your dependencies for proper Immutable Infrastructure](/quick-start/simple/extra-credit/vendor-components) + +## What's Included + +Start your first project in 5 easy steps. After this, you can configure and provision infrastructure with Terraform using Atmos. + + + + + Start with the first step, which is configuring your project for Atmos. + Configure Project + diff --git a/website/docs/quick-start/simple/summary.mdx b/website/docs/quick-start/simple/summary.mdx new file mode 100644 index 000000000..7cc8d7166 --- /dev/null +++ b/website/docs/quick-start/simple/summary.mdx @@ -0,0 +1,35 @@ +--- +title: Where to go from here... +sidebar_position: 8 +sidebar_label: Next Steps +--- +import KeyPoints from '@site/src/components/KeyPoints' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' + + +Atmos provides unlimited flexibility in defining and configuring stacks and components in the stacks. + + + +- Terraform "root modules" are deployed as components that are organized in sub-folders within `components/terraform` by type, team, operations, or any other category. +- Stacks define the configuration of your "root modules", and can have arbitrary names and located anywhere in the `stacks/` directory; Atmos finds stacks using a "slug". +- Terraform components can be reused any number of times by giving them unique names in the stack configurations + and pointing them to the same Terraform root module. + + +All the above makes Atmos an ideal framework for organizing infrastructure, designing for organizational complexity, and provisioning multi-account environments for very complex organizations. + +As you continue to poke around, here are some suggestions for what to do next: + +1. [Review Atmos Design Patterns](/design-patterns) +2. [Use GitHub Actions](/integrations/github-actions) +3. [Try the Advanced Tutorial](/quick-start/advanced) + + + Now that you’ve seen Atmos in action, take a moment to explore its core concepts. + + You have only just scratched the surface of Atmos. Atmos is a powerful enterprise-grade framework with so **much more to offer**! + Learn Core Concepts + diff --git a/website/docs/quick-start/simple/write-components.mdx b/website/docs/quick-start/simple/write-components.mdx new file mode 100644 index 000000000..5200a1be9 --- /dev/null +++ b/website/docs/quick-start/simple/write-components.mdx @@ -0,0 +1,129 @@ +--- +title: Write Some Components +sidebar_position: 3 +sidebar_label: 3. Write Some Components +--- +import EmbedFile from '@site/src/components/EmbedFile' +import KeyPoints from '@site/src/components/KeyPoints' +import Screengrab from '@site/src/components/Screengrab' +import LatestRelease from '@site/src/components/LatestRelease' +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' +import Intro from '@site/src/components/Intro' +import ActionCard from '@site/src/components/ActionCard' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' +import Note from '@site/src/components/Note' + + +When you [design cloud architectures with Atmos](/quick-start/mindset), you will first break them apart into pieces called [components](/core-concepts/components). Then, you will implement [Terraform "root modules"](/core-concepts/components/terraform) for each of those components. + + +After we're done with this, we'll show you [how you connect your components using stacks](/quick-start/simple/configure-stacks), so that everything comes together. + + +- Where to place your components +- How to write a suitable Terraform root module to use as a component +- How to make your components reusable and other considerations + + + +## Decide what your component should do + +Once we consider our infrastructure in terms of components, we need to determine the specific functions each component must perform. + +We recommend following the [Single Responsibility Principle (SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle). That is, design components to serve a single purpose, making them the smallest possible unit of infrastructure in a typical software development lifecycle (SDLC). Group pieces usually change together as one component and separate those that change independently (or seldom). + +We discuss some of the [best practices for components](/best-practices/components) in our documentation. + +In this case, since our goal is to retrieve the current weather, let's create a component that will do just that. + + + + +## Create a Directory for Your Component + +The implementation for the component (e.g. HCL code) will be stored in a directory under the `components/` folder corresponding to the toolchain used (e.g. `terraform/`). For Terraform, place your component in the `components/terraform` directory. Inside this directory, create a folder to store your component’s Terraform code, which serves as the root module. Since our component is a simple Terraform root module, we will create a directory called `weather` to store the Terraform code for our weather component. + +```bash +mkdir -p components/terraform/weather +``` + + + + + +## Write a Terraform Root Module + +In the following descriptions, you’ll see that everything is just plain Terraform (HCL) with nothing specific to Atmos. That’s intentional: we want to demonstrate that Atmos works seamlessly with plain Terraform. Atmos introduces conventions around how you use Terraform with its framework, which will become more evident in the subsequent lessons. + +To write our Terraform root module, we’ll follow Terraform's standard conventions: +
+
`variables.tf`
+
Defines variables
+ +
`outputs.tf`
+
Defines outputs
+ +
`versions.tf`
+
Specifies required provider versions
+ +
`providers.tf`
+
Specifies providers
+ +
`main.tf`
+
Implements main functionality
+
+ +So, let’s start by defining our root module as usual. + +### Implement `variables.tf` + +To make the best use of Atmos, ensure your root modules are highly reusable by accepting parameters, allowing them to be deployed multiple times without conflicts. This also usually means provisioning resources with unique names. + + + +### Implement `main.tf` + +The `main.tf` file is where the main implementation of your component resides. This is where you define all the business logic for what you’re trying to achieve—the core functionality of your root module. If this file becomes too large or complex, you can break it into multiple files in a way that makes sense. However, sometimes that is also a red flag, indicating that the component is trying to do too much and should be broken down into smaller components. + +In this example, we define a local variable that creates a URL using the variable inputs we receive. We also set up a data source to perform an HTTP request to that endpoint and retrieve the current weather. Additionally, we write this output to a file to demonstrate a stateful resource. + + + +
+How do we recommend ensuring unique resource names? + +Cloud Posse's [`terraform-null-label`](https://github.com/cloudposse/terraform-null-label) module makes this easier by turning naming into a standardized, programmatically enforced convention. Setting the null label parameters ensures unique resource names and enforces consistency across your team and organization. + +In our example, we will keep it simple to focus on the basics, so we will not use this module. +
+ +For the purpose of this quickstart, we’ll assume you have minimal experience with Terraform. Some of this information might be obvious to more experienced users, but we’re including it here to ensure a smooth learning experience for everyone. + +### Implement `versions.tf` + +The `versions.tf` file is where provider pinning is typically defined. Provider pinning increases the stability of your components and ensures consistency between deployments in multiple environments. + + + +### Implement `outputs.tf` + +The `outputs.tf` file is where, by convention in Terraform, you place any outputs you want to expose from your root module. Outputs are essential for passing state between your root modules and can be used in conjunction with [remote state](/core-concepts/components/terraform/remote-state) or the [Atmos function to retrieve the state](/core-concepts/stacks/templates/functions) of any other component. +In object-oriented parlance, think of your outputs as the “public” attributes of the module that are intended to be accessed by other modules. This convention helps maintain clarity and organization within your Terraform configurations. + + +Technically outputs can be placed in any file, but the standard convention in Terraform is to place them usually in `outputs.tf`. +
+ + + + + Now that you have a Terraform "root module", you can use it as a component in your Atmos stacks, and deploy it any number of times, tweaking the configuration as needed. + + We will show you [how to do that in the next step](/quick-start/simple/configure-stacks). +
+ Next Step + Deep Dive +
+
diff --git a/website/docs/reference/alternatives.md b/website/docs/reference/alternatives.md deleted file mode 100644 index b4f9fef9b..000000000 --- a/website/docs/reference/alternatives.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: Atmos Alternatives -sidebar_label: Alternatives -sidebar_position: 3 ---- - -To better understand where Atmos fits in, it may be helpful to understand some of the alternative tooling it seeks to replace. There are lots of great -tools out there and we're going through a bit of a "DevOps Rennisance" when it comes to creativity on how to automate systems. - -## General Alternatives - -There are many tools in the general category of "task runners" or "workflow automation". Here are some of the alternatives to Atmos, many of which -inspired core functionality in Atmos. - -### Make (Makefile) by Free Software Foundation - -https://www.gnu.org/software/make/ - -Many companies (including Cloud Posse) started by leveraging `make` with `Makefile` and targets to call `terraform`. Using `make` is popular method of -orchestrating tools, but it has trouble scaling up to support large projects. We know this because [Cloud Posse](https://cloudposse.com/) used it for -3+ years. The problems we ran into is that `make` targets do not support "natural" parameterization, which leads to a proliferation of environment -variables that are difficult to validate or hacks like overloading make-targets and parsing them (e.g. `make apply/prod`). Makefiles are unintuitive -for newcomers because they are first evaluated as a template, and then executed as a script where each line of a target runs in a separate process -space. Spaces matter too, and it's made worse with inconsistent rules using tabs in some places and spaces in others. - -### Mage (Magefile) - -https://magefile.org/ - -Mage is a make/rake-like build tool using native Golang and plain-old `Go` functions. Mage then automatically provides a CLI to call them as -Makefile-like runnable targets. - -### Task (Taskfile) - -https://github.com/go-task/task - -Task is a task runner and build tool that aims to be simpler and easier to use than GNU Make. - -:::info -Atmos supports native [workflows](/core-concepts/workflows) that have very similar schema to "Taskfile", only they can be defined together -with [Stacks](/core-concepts/stacks) or as standalone workflow files. -::: - -### Variant - -https://github.com/mumoshu/variant -https://github.com/mumoshu/variant2 (second generation) - -Variant lets you wrap all your scripts and CLIs into a modern CLI and a single-executable that can run anywhere. - -:::info -The earliest versions of `atmos` were built on top of [`variant2`](https://github.com/mumoshu/variant2) until we decided to rewrite it from the ground -up in pure Go. Atmos supports native [workflows](/core-concepts/workflows) which provide similar benefits. -::: - -### AppBuilder by Choria - -https://github.com/choria-io/appbuilder - -AppBuilder is a tool built in Golang to create a friendly CLI command that wraps your operational tools. - -:::info -Atmos is heavily inspired by the excellent schema provided by AppBuilder and has implemented a similar interface as part of -our [Custom Commands](/core-concepts/custom-commands). -::: - -## Terraform Alternatives - -There are many tools explicitly designed around how to deploy with Terraform. - -The following is a list of tools that only support Terraform. - -:::tip Atmos Differentiators -Atmos not only supports Terraform, but can be used to manage any CLI. For example, by combining [Custom commands](/core-concepts/custom-commands) -and [workflows](/core-concepts/workflows), it's possible to support any CLI tool (even the ones listed below) or even reimplement core functionality of -atmos. That's how extensible it is. -::: - -### Terragrunt by Gruntwork - -https://github.com/gruntwork-io/terragrunt - -Terragrunt is a tool built in Golang that is a thin wrapper for Terraform that provides extra tools for working with multiple Terraform modules. - -### Terramate by Mineros - -https://github.com/mineiros-io/terramate - -Terramate is a tool built in Golang for managing multiple Terraform stacks with support for change detection and code generation. - -### Terraspace (Terrafile) by Bolt Ops - -https://github.com/boltops-tools/terraspace - -Terrapsace is a tool built in Ruby that provides an opinionated framework for working with Terraform. - -### Terraplate by Verifa - -https://github.com/verifa/terraplate - -Terraplate is a tool built in Golang that is a lightweight wrapper for terraform the focused on code generation. - -### Astro by Uber (abandoned) - -https://github.com/uber/astro - -Astro is a tool built in Golang that provides a YAML DSL for defining all your terraform projects and then running them. - -### Opta by Run X - -https://github.com/run-x/opta - -Opta is tool built in Python that makes Terraform easier by providing high-level constructs and not getting stuck with low-level cloud configurations. - -### pterradactyl by Nike - -https://github.com/Nike-Inc/pterradactyl - -Pterradactyl is a library developed to abstract Terraform configuration from the Terraform environment setup. - -### Leverage by Binbash - -The Leverage CLI written in Python and intended to orchestrate Leverage Reference Architecture for AWS - -https://github.com/binbashar/leverage - diff --git a/website/docs/reference/alternatives.mdx b/website/docs/reference/alternatives.mdx new file mode 100644 index 000000000..04a9f27be --- /dev/null +++ b/website/docs/reference/alternatives.mdx @@ -0,0 +1,161 @@ +--- +title: Atmos Alternatives & Inspirations +sidebar_label: Alternatives +sidebar_position: 3 +--- +import Intro from '@site/src/components/Intro' + + +To better understand where Atmos fits in, it may be helpful to understand some of the tooling that has inspired its design or serve as possible alternatives to its approach. + + +## Conceptual Inspiration + +Atmos is inspired by the follow frameworks or tooling. + +### React for JavaScript + +https://react.dev/ + +[React’s](https://react.dev/) component-based architecture serves as a key inspiration for Atmos. By breaking down UIs into reusable components, React simplifies the development of complex applications. Similarly, Atmos promotes modularity in infrastructure as code, allowing components to be reused across different environments and projects. For example, in Atmos, any Terraform "root module" may be used as a component. + +### Kustomize for Kubernetes + +https://kustomize.io/ + +[Kustomize](https://kustomize.io/) introduces a template-free way to customize Kubernetes configurations, focusing on overlays and inheritance to manage configuration variations. Atmos adopts a similar approach, enabling users to import, overlay, and override configurations efficiently, thereby simplifying the management of complex infrastructure setups, all without relying on templating. + +However, due to popular demand, Atmos now supports advanced templating and data sources in addition to the original template-free configurations. Templating complicates configurations and should be used solely as an escape hatch for when the first-class concepts of imports and inheritance are insufficient. + +### Helmfile for Helm Charts + +https://helmfile.com + +[Helmfile](https://helmfile.com) manages collections of Helm charts with declarative syntax, combining them into a "stack" for deployment to Kubernetes. It handles environmental configuration, deep merging it, and evaluating templates with a Go template engine before passing the values files to Helm. + +Atmos draws from Helmfile’s ability to orchestrate multiple Helm charts, applying the concept to Terraform root modules to manage interdependencies and deployment order. It supports environmental configuration through stack configurations that define all the environmental configurations for Terraform root modules. Atmos generates the necessary Terraform `.tfvar` files, much like Helmfile generates Helm values files, ensuring consistent and efficient deployment of Terraform infrastructure. + +### Helm Charts for Configuration + +https://helm.sh/ + +[Helm Charts](https://helm.sh/) provide a packaging format for deploying applications on Kubernetes, simplifying the processes of defining, installing, and upgrading even the most complex applications. Similarly, Atmos organizes Terraform configurations into reusable, versioned modules, facilitating consistent and repeatable infrastructure deployments. + +The concept is that if your root modules are sufficiently parameterized, they function much like Helm charts. You only need to supply the appropriate values to achieve the desired configuration. + +### Vendir by Tanzu + +https://github.com/carvel-dev/vendir + +Atmos Vendoring was heavily inspired by [Vendir from VMWare Tanzu](https://github.com/carvel-dev/vendir), which served as the basis for our initial implementation. However, after using it, we realized we only needed a simpler subset of Vendir’s full functionality. Therefore, we implemented our own version using [HashiCorp’s GoGetter (MPL-2.0) library](https://github.com/hashicorp/go-getter). Additionally, we’ve added support for OCI, allowing Vendoring to pull configurations from anywhere. This advanced feature enables consistent and declarative pulling of configurations not just for components, but also for stack configurations or any dependencies you have. + +## General Alternatives + +There are many tools in the general category of "task runners" or "workflow automation". +Here are some of the alternatives to Atmos, many of which inspired core functionality in Atmos. + +### Make (Makefile) by Free Software Foundation + +https://www.gnu.org/software/make/ + +Many companies (including Cloud Posse) started by leveraging `make` with `Makefile` and targets to call `terraform`. Using `make` is a popular method of orchestrating tools, but it has trouble scaling up to support large projects. We know this because [Cloud Posse](https://cloudposse.com/) used it for 3+ years. The problem we ran into is that `make` targets do not support "natural" parameterization, which leads to a proliferation of environment variables that are difficult to validate or hacks like overloading make-targets and parsing them (e.g. `make apply/prod`). Makefiles are unintuitive for newcomers because they are first evaluated as a template and then executed as a script where each line of a target runs in a separate process space. Spaces matter too, and it's made worse with inconsistent rules using tabs in some places and spaces in others. + +### Mage (Magefile) + +https://magefile.org/ + +Mage is a make/rake-like build tool using native Golang and plain-old `Go` functions. Mage then automatically provides a CLI to call them as +Makefile-like runnable targets. + +### Task (Taskfile) + +https://github.com/go-task/task + +Task is a task runner and build tool that aims to be simpler and easier to use than GNU Make. + +:::info +Atmos supports native [workflows](/core-concepts/workflows) that have very similar schema to "Taskfile", only they can be defined together +with [Stacks](/core-concepts/stacks) or as standalone workflow files. +::: + +### Variant + +https://github.com/mumoshu/variant +https://github.com/mumoshu/variant2 (second generation) + +Variant lets you wrap all your scripts and CLIs into a modern CLI and a single-executable that can run anywhere. + +:::info +The earliest versions of `atmos` were built on top of [`variant2`](https://github.com/mumoshu/variant2) until we decided to rewrite it from the ground +up in pure Go. Atmos supports native [workflows](/core-concepts/workflows) which provide similar benefits. +::: + +### AppBuilder by Choria + +https://github.com/choria-io/appbuilder + +AppBuilder is a tool built in Golang to create a friendly CLI command that wraps your operational tools. + +:::info +Atmos is heavily inspired by the excellent schema provided by AppBuilder and has implemented a similar interface as part of +our [Custom Commands](/core-concepts/custom-commands). +::: + +## Terraform-specific Tooling Alternatives + +There are many tools explicitly designed around how to deploy with Terraform. + +The following is a list of tools that only support Terraform. + +:::tip Atmos Differentiators +Atmos supports Terraform and can also be used to manage any command-line tool. For example, by combining [Custom commands](/core-concepts/custom-commands) and [workflows](/core-concepts/workflows), it's possible to support any CLI tool (even the ones listed below) or even reimplement the core functionality of Atmos. That's how extensible it is. +::: + +### Terragrunt by Gruntwork + +https://github.com/gruntwork-io/terragrunt + +Terragrunt is a tool built in Golang that is a thin wrapper for Terraform that provides extra tools for working with multiple Terraform modules. + +### Terramate by Mineros + +https://github.com/mineiros-io/terramate + +Terramate is a tool built in Golang for managing multiple Terraform stacks with support for change detection and code generation. + +### Terraspace (Terrafile) by Bolt Ops + +https://github.com/boltops-tools/terraspace + +Terrapsace is a tool built in Ruby that provides an opinionated framework for working with Terraform. + +### Terraplate by Verifa + +https://github.com/verifa/terraplate + +Terraplate is a tool built in Golang that is a lightweight wrapper for Terraform the focused on code generation. + +### Astro by Uber (abandoned) + +https://github.com/uber/astro + +Astro is a tool built in Golang that provides a YAML DSL for defining all your terraform projects and then running them. + +### Opta by Run X + +https://github.com/run-x/opta + +Opta is a tool built in Python that makes Terraform easier by providing high-level constructs and not getting stuck with low-level cloud configurations. + +### pterradactyl by Nike + +https://github.com/Nike-Inc/pterradactyl + +Pterradactyl is a library developed to abstract Terraform configuration from the Terraform environment setup. + +### Leverage by Binbash + +The Leverage CLI is written in Python and intended to orchestrate Leverage Reference Architecture for AWS + +https://github.com/binbashar/leverage + diff --git a/website/docs/reference/reference.mdx b/website/docs/reference/reference.mdx index 67d96c013..a69cb94f9 100644 --- a/website/docs/reference/reference.mdx +++ b/website/docs/reference/reference.mdx @@ -2,13 +2,10 @@ title: Reference sidebar_position: 8 sidebar_label: Reference +sidebar_class_name: hidden description: Reference id: reference --- - -# Reference - - -import DocCardList from "@theme/DocCardList"; +import DocCardList from '@theme/DocCardList' diff --git a/website/docs/reference/slides.mdx b/website/docs/reference/slides.mdx index e90263cb4..820d86986 100644 --- a/website/docs/reference/slides.mdx +++ b/website/docs/reference/slides.mdx @@ -5,6 +5,6 @@ sidebar_position: 2 sidebar_label: Slides --- -import Slides from "@site/src/components/slides/slides"; +import Slides from "@site/src/components/Slides"; diff --git a/website/docs/reference/terraform-limitations.md b/website/docs/reference/terraform-limitations.md deleted file mode 100644 index 12e4bd70d..000000000 --- a/website/docs/reference/terraform-limitations.md +++ /dev/null @@ -1,295 +0,0 @@ ---- -title: Overcoming Terraform Limitations with Atmos -description: Overcoming Terraform Limitations with Atmos -sidebar_label: Overcoming Terraform Limitations -sidebar_position: 6 ---- - -# Overcoming Terraform Limitations with Atmos - -To better understand the rationale behind Atmos's design, it may be helpful to hear about our experiences with Terraform—a tool integral to our development processes. Let's explore the challenges and constraints we faced using Terraform, which paved the way for creating Atmos. - -## What is Terraform? - -Terraform is a command-line utility that processes infrastructure configurations in ["HashiCorp's Configuration Language" ("HCL")](https://en.wikipedia.org/wiki/HCL) to orchestrate infrastructure provisioning. Its chief role is to delineate and structure infrastructure definitions. - -Terraform's HCL started strictly as a configuration language, not a markup or programming language, although has evolved considerably over the years. HCL is backward compatible with JSON, although it's not a strict superset of JSON. HCL is more human-friendly and readable, while JSON is often used for machine-generated configurations. This means you can write Terraform configurations in HCL or JSON, and Terraform will understand them. This feature is particularly useful for generating configurations programmatically or integration with systems that already use JSON. - -## How has Terraform HCL Evolved? - -As Terraform progressed and HCL evolved, notably from version _0.12_ onwards, HCL began incorporating fetatures typical of programming languages (albeit without a debugger!). This shift enriched infrastructure definitions, positioning HCL more as a [domain-specific programming language](https://en.wikipedia.org/wiki/Domain-specific_language) for defining infrastructure than strictly a configuration language (aka data interchange formats like JSON). As a result, the complexity of configuring Terraform projects has risen, while Terraform's inherent capabilities to be configured haven't evolved at the same pace. - -- **Rich Expressions:** Introduced a richer expression syntax, removing the need for interpolations. - -- **For Loops and Conditionals:** Added for expressions and conditional expressions. - -- **Type System:** Introduced a more explicit type system for input and output values. - -## Why is additional tooling needed when using Terraform? - -**Every foundational tool begins simply.** - -As users grow more advanced and their ambitions expand, the need for advanced tooling emerges. These shifts demonstrate that core technologies naturally progress, spawning more advanced constructs to tackle increased intricacies and enhance efficiency -- all while retaining their core essence. Just as CSS, JavaScript, Docker, Helm, and many other tools have evolved to include higher-order utilities, Terraform, too, benefits from additional orchestration tools, given the complexities and challenges users face at different stages of adoption. - -Examples of tools like these are numerous, like - -- **CSS has Sass:** Sass provides more expressive styling capabilities, variables, and functions, making stylesheets more maintainable and organized, especially for large projects. -- **JavaScript has TypeScript:** TypeScript brings static typing to JavaScript, improving code robustness, aiding in catching errors at compile-time, and better supporting large-scale applications. -- **Docker has Docker Compose:** Docker Compose simplifies the management and orchestration of multi-container Docker applications, making it easier to define, run, and scale services collectively. -- **Helm charts have Helmfiles.** While Helm charts define the blueprints of Kubernetes services, Helmfiles enable better orchestration, management, and deployment of multiple charts, similar to coordinating various instruments in a symphony. -- **Kubernetes manifests have Kustomize:** Kustomize allows customization of Kubernetes manifests without changing their original form, facilitating dynamic configurations tailored to specific deployment scenarios. - -When considering Terraform in the context of large-scale organizations or enterprises, it's clear that Terraform and its inherent language don't address all challenges. With thousands of components spread across hundreds of accounts, cloud providers and managed by a vast number of DevOps engineers and developers, the complexity becomes overwhelming and difficult to manage. - -A lot of the same challenges faced by CSS, Javascript, Docker, Helm and Kubernetes also exist in Terraform as well. - -- Making modules more maintainable and organized, especially for large projects -- Better support for large-scale service-oriented architectures -- Easier ways to define, run, and scale services collectively -- Better orchestration, management, and deployment of multiple services - -Here's a more exhaustive list: - -- **Lack of DRY Configurations**: Terraform does not inherently support hierarchical configurations. There's no support for [deep merging configurations](https://github.com/hashicorp/terraform/issues/24987), making manual `varfile` maintenance unscalable. This makes it more difficult to enforce organizational standards, security controls, tagging, and policies. -- **State Management**: Managing Terraform's state, especially at scale, lacks inherent strategies for handling complexities such as access controls, multi-region, and Disaster Recovery (DR). -- **Limited Modularization**: Structuring configurations modularly while promoting code reuse is cumbersome. -- **Manual Initialization**: Backend initialization, module downloads, and other setup tasks require manual steps before executing `terraform apply`. This ties into the need for some kind of workflow tool. -- **Dependency Management**: Community edition of Terraform doesn't provide any mechanisms for orchestrating dependencies among root modules. -- **Absence of Stack Management**: Organizing configurations into structured stacks isn't a built-in feature of the community edition. -- **Lack of Automatic Dependency Ordering**: Standalone Terraform doesn't inherently determine execution order based on inter-stack dependencies. -- **No Native Workflow Automation and Standardization**: Dynamic workflow executions, such as having a unified workflow both in CI/CD platforms like GitHub Actions (GHA) and locally, are not inherently supported. Workflow standardization and automation capabilities do not exist, making provisioning and management tasks more manual, or relying on custom scripts, Makefiles, or other tooling. -- **Basic Environment Management**: Managing configurations across multiple environments can become complex without higher-level tooling. - -For each of these challenges, a tailored solution is essential. Ultimately, the goal is to make Terraform more scalable, maintainable, and developer-friendly, especially in complex and large-scale environments. - -HashiCorp primarily offers foundational guidance on Terraform and pushes companies instead toward Terraform Enterprise. In fact, it's held back features from entering into the Terraform core that would make it more standalone. HashiCorp does not thoroughly address how to solve the above challenges using Terraform. While suitable for some, it may not meet the scalability demands of enterprise, especially as they embark on their Terraform adoption journey. - -## What is the natural progression of Terraform adoption? - -Every advancement in tool adoption is accompanied by new challenges, introducing complexities that are justified by the evolution's benefits. Indeed, the true value of these evolutions often only becomes clear once we're faced with the intricate challenges they address. Here's what a typical path of adoption looks like for organizations adopting Terraform. - -### **Stage 1:** Introduction to Terraform, *Hello World!* - -At this initial stage, developers begin their Terraform journey with the basics, focusing on getting a grasp of its core concepts through a straightforward implementation. - -1. Developers roll up their sleeves to get a simple terraform example up and running. They create resources directly in the - configuration without the use of modules. This phase is characterized by hard-coded settings and a hands-on approach to learning - Terraform's syntax and capabilities. -2. Local state files (since this is just an exploration). This approach simplifies the learning process by avoiding the complexities of remote state management. -3. Version control systems are not yet in use. Developers store their Terraform configurations directly on their local workstations - allowing them to focus on learning Terraform's mechanics without the added complexity of collaboration tools or best practices. - -:::warning New Problems -1. How do we handle secrets? -2. Where do we store the state file? -3. How do we maintain something with so many hardcoded settings? -::: - -### **Stage 2:** The Monolithic Root Module (aka Terralith) - -As developers grow more comfortable with Terraform, they often transition to a more ambitious approach of automating everything. -It results in creating a monolithic root module, also known as a Terralith. This stage is characterized by an expansive, -all-encompassing Terraform configuration that attempts to manage every aspect of the infrastructure within a single module. - -1. Developers begin by composing a single root module that continuously expands. -2. Define all environments as code (dev, staging, production) in a single Terraform root module. -3. Extensive use of feature flags for everything (e.g. `prod_cluster_size`, `staging_cluster_size`, etc.) - -:::warning New Problems -1. Massive blast radius for every change. It's literally scary to apply the changes, because anything can go wrong. -2. Brittle and prolonged plan/apply cycles, often disrupted by transient errors, expiring credentials and API rate limits, require frequent, manual retries. -3. Large root modules become more complicated, often necessitating the use of targeted applies (e.g. `terraform apply -target`) as a workaround for cycles. -4. Far from DRY. Significant code duplication. Tons parameters are used for toggling settings for each environment within the same root module. -5. No practical way to separate responsibilities by team within the root module. -6. Testing every parameter combination is impossible. -::: - -### **Stage 3:** Move Towards Modularization - -As developers dive deeper into Terraform's capabilities, they begin to recognize the inefficiencies of their initial approaches. The move towards modularization represents a significant leap in managing infrastructure as code more effectively. - -1. Developers realize that a lot of code is getting copied and pasted, so they advance to writing modules to avoid duplication. -2. Modules act like functions in Terraform: reusable and parameterized. They can be called multiple times and accept parameters. -3. It works well for now, and developers succeed in bringing up all the environments. It certainly beats ClickOps. - -:::warning New Problems -1. These modules are "reusable" but usually just within the project itself and not written to be reused across the organization. -2. Many assumptions are made on specific requirements of the problem at hand, and generalizing them is not of paramount concern. -3. Lots of similar modules appear in the organization, some more maintained than others. -4. Still, no automated tests (E.g. `terratest`). -5. Everyone is probably an Administrator. -::: - -### **Stage 4:** Adoption of Open Source Modules - -Developers begin their Terraform journey often by crafting their own modules, initially overlooking the extensive ecosystem of pre-existing modules, such as [Cloud Posse's terraform modules](https://github.com/cloudposse). - -1. Developers, initially crafting bespoke modules, discover hundreds of freely available open-source Terraform modules. -2. With the recognition of high-quality, well-maintained open-source modules, developers start to replace their custom solutions (like VPCs and clusters) with those from the community, streamlining their infrastructure code. -3. The switch to open-source modules often leads to pull requests that dramatically reduce the complexity and lines of code, - sometimes cutting out hundreds or even thousands of lines, to the team's astonishment and delight. - -:::warning New Problems -1. How will they keep their modules current and ensure they meet certain policies for the organization? -2. Which of the XYZ modules should they pick? For example, there are dozens of VPC modules. What if 2 different teams pick different ones? -3. The quality of open-source modules varies drastically. - - What if the modules are abandoned? - - What if they aren't updated to support the latest versions? - - What if they don't accept pull requests? - - What if two modules conflict with each other? -::: - -### **Stage 5:** Multiple Root Modules - -Developers recognize the pitfalls of having all environments in one root module. After having refactored their code heavily into modules, Developers realize it was a bad idea to define dev, staging and prod, all in the same root module. Developers realize terraform gets very slow and brittle when a root module is too large. - -1. Initiate the split of the monolithic root module into smaller, more manageable units while incorporating additional feature flags - and expanding configuration management through `.tfvars` files. -2. Move towards a structure where multiple root modules are used, each one precisely aligned with specific environments - to enhance maintainability and performance. -3. Recognize the efficiency gains and increased adaptability that came from segregating large root modules, leading to quicker - Terraform operations and easier adjustments per environment. - - -:::warning New Problems -1. Increased feature flags and configuration management using `.tfvars`. -2. Performance becomes a concern with overly large root modules. -3. Very poor reusability across the organization due to the "snowflake" nature of the root modules. -::: - -### **Stage 6:** Refactoring for DRY Configuration - -As developers navigate the complexities of managing multiple environments, root modules, and accounts or organizations, the focus shifts from merely defining -infrastructure as code to the overarching challenge of maintaining these expansive configurations efficiently. - -1. With numerous environments, root modules, and accounts or organizations, the challenge shifts from defining infrastructure as code to maintaining the extensive configuration of parameters that get passed to Terraform. -2. In an effort to manage repetitive configurations, developers resort to using symlinks or other methods to link common files across projects, seeking to reduce redundancy. -3. Code Generation is adopted to overcome *perceived* limitations of Terraform (when, in fact it's often a flaw in the architecture of the project). - -:::warning New Problems -1. For every new application developed, the automatic response is to create bespoke root modules for specific needs, despite - reusing child modules, raising the question of why a new root module is necessary for each application in the first place. -2. As the number of root modules grows, the Terraform state gets divided by component. Managing these inter-component dependencies - falls outside Terraform's capabilities and needs to be solved in another way. -3. The adoption of code generation tools to address Terraform's *perceived* limitations (e.g., [inability to](https://github.com/hashicorp/terraform/issues/19932#issuecomment-1817043906) iterate over providers](https://github.com/hashicorp/terraform/issues/19932#issuecomment-1817043906)) that often can mask underlying architectural issues as well as make automated testing complicated. -::: - -### **Stage 7:** Terraform Scripting - -As Terraform projects grow in complexity and scale, developers seek ways to automate and streamline their workflows beyond what native Terraform commands offer. This leads to exploring scripting as a means to orchestrate Terraform operations. - -1. The first path usually involves adopting a simple `bash` script or `Makefile` to orchestrate Terraform. This works well, up to a point (we know this because it is how we started using Terraform at Cloud Posse). -2. These scripts evolved to solve specific problems that made Terraform cumbersome as a tool. -3. Terraform scripts still run on local machines, reflecting the initial stages of development focus. - -:::warning New Problems -1. What happens in practice is every team/company using Terraform ends up building different homegrown scripts, often then combining those with `Makefiles`, into a hodgepodge of configurations with different levels of validation. The scripts grow in complexity and have to survive generations of developers. -2. New patterns emerge, for example, hacks that involve Jinja templates, string concatenation, symlinks, and worse... sed & awk replacements!!! -3. Terraform is run mostly from local workstations/laptops, with no thought for how it will run in CI/CD. -::: - -### **Stage 8:** Team Adoption - -As Terraform use grows within the team, it becomes clear that what facilitated the initial success, is insufficient for the next level of growth and teamwork. This stage is a turning point, emphasizing the need for evolved workflows, enhanced collaboration tools, and a -more structured approach to managing scalable infrastructure projects. - -1. Change velocity increases dramatically. -2. Codebase increases in size by 10x (but with lots of duplication). -3. New SLA/Commitment to keep it all running all the time. - -:::warning New Problems -1. Configuration starts drifting more often as the team neglects to apply changes consistently, or "ClickOps" persists in parts of the organization. -2. Developers are stepping on each other's toes. What worked when there were only a few developers no longer scales. -3. Poor controls and lack of consistency of Terraform code. Tons of duplication. -::: - -### **Stage 9:** DIY GitOps, *Hello Jenkins!* - -With the greater adoption of Terraform and DevOps principles, Developers are now using Terraform daily. They decide to use the same patterns for deploying applications with Terraform. Only Terraform is exceptionally different from deploying containerized apps. There are no rollbacks. It's more akin to performing database migrations without transactions (YOLO!). It's a scary business. Controls are needed. - -1. Developers stick their scripts in a CI/CD pipeline. -2. Pipeline posts comments for each commit on every PR containing the raw output of the `terraform plan`, to validate what *should* happen during `terraform apply`. -3. On merge to main, `terraform apply` is run *without* a planfile. 🤞 - -:::warning New Problems -- Still using Jenkins. 🧌🔥 -- CI/CD system promoted to *God Mode*. 🤞 Static administrative cloud credentials are exposed as environment variables, ripe for exfiltration -- No visibility into the impact of the changes across multiple environments at the same time -- Inadequate security mechanisms creating a critical risk of catastrophic business loss -- Lack of plan file storage means incorrect implementation of plan/apply workflows -- Missing project-level locks, so PRs can easily clobber each other, rolling back state. -- Entire organization is spammed by GitHub comments every time someone pushes a commit, and a plan is run on the PR -- No recourse for when a `terraform apply` fails -- Automated drift detection is needed to ensure environments converge with what's in version control -::: - -### **Stage 10:** Terraform Bankruptcy 💥 - -As the complexity and scale of Terraform projects reach a tipping point, developers face a stark realization. -Questions arise about the inherent difficulties of managing sprawling infrastructure code bases using Terraform, -leading to a moment of reckoning. Some might question if Terraform is even the right tool. - -:::danger - -- Scripts all over the place that call terraform -- Inconsistent conventions on what is a module, root module and when to combine them -- Root modules that need to be provisioned in a specific order to bring them up and down, often necessitating the use of `-target` -- No way to define dependencies between root modules -- Passing state between root modules is inconsistent -- Automating the terraform in CI/CD is oversimplified, lacking project-level locks and `planfile` retrieval -- Inconsistent conventions or a total lack of conventions -- Incomplete or out-of-date documentation -- **No one understands how it all works anymore ⚠️** - -::: - -This should be a solved problem. - -**If only there were a tool to compose everything together...** - -*(...and then they discover [Atmos](/)!)* 😉 - -### **Stage 11:** New Toolchain Selection - -Having learned Terraform the hard way, developers emerge with a well-defined set of requirements for a toolchain that can address the complexities they've encountered. Their experiences have crystallized what is necessary to operate infrastructure at scale based on real-world experience. - -1. **Consistent Invocation:** I want a tool that standardizes how Terraform is invoked across the organization. -2. **Made Composition Easier:** It would be fantastic if it were an equivalent to [Docker Compose](https://docs.docker.com/compose/compose-application-model/#illustrative-example) for piecing together root modules. -3. **Efficient Configuration:** I need a method similar to [Kustomize](https://kustomize.io/) for configurations. It should reduce redundancy and support features like imports, hierarchy, inheritance, and deep merging to help set organizational standards, security, and tags with ease. -4. **Reusable Building Blocks:** I want to establish a library filled with thoroughly tested modules and components for the entire organization. After it's set up, we should hardly require additional HCL development. -5. **State Backends:** I need something to configure the state backend since Terraform doesn't support interpolations. Root modules cannot effectively be re-used without backend generation. -6. **Policy Enforcement:** I expect a mechanism to enforce specific policies and rules across configurations to control everything -7. **Structured Modularity:** I desire Terraform configurations to have a modular design to promote code reuse across varied use cases. -8. **Seamless Initialization:** I want the backend setup, module fetching, and all preparatory measures to be in place seamlessly before even thinking of using `terraform apply`. -9. **Dependency Coordination:** I'm looking for a way to ensure Terraform modules, which are dependent on one another, are applied in - sequence and without hiccups. -10. **Stack Organization:** I need a system that categorizes and manages Terraform configurations using a stack-driven approach, making it easier to deal with multiple configurations. -11. **Standardized Workflows:** I would love a unified system, something in the league of `Make` or `Gotask`, for laying out workflows. This should automate repetitive tasks and be versatile enough to adapt, whether it's GitHub Actions or local setups. -12. **Environment Consistency:** It'd be great to have a tool that mirrors the consistency of `helmfile` for environment definitions, ensuring steadiness and reliability across varying environments. -13. **Turnkey CI/CD:** I want to effortlessly integrate with GitHub Actions and run operations without being charged a deployment tax. - -*Oh, one last ask. Can it also be free and open source?* - -## What's the Solution? *Hello Atmos!* 👽 - -😎 Good news! Atmos supports all of this out of the box and exactly what you **cannot** achieve with "standalone" (a.k.a. community edition) Terraform and [none of the alternatives](/reference/alternatives) can do it all. Plus, there's no need to abandon Terraform—it's actually a great tool, and Atmos enhances its strengths. - -Here's what you can expect after adopting Atmos: - -- **Consistent Invocation:** Atmos ensures Terraform invokes the same way every time; no more need to pass complicated arguments to `terraform`. This removes guesswork and confusion across teams with what parameters to pass and what order of operations things need to be invoked. -- **Seamless Initialization:** Backend? Modules? Prep steps? Atmos makes sure everything is ready before you run `terraform apply`. -- **Separation of Configuration from Code** Unlike most alternatives, Atmos cleanly separates the configuration into Stacks, separate from Components (terraform root modules). This ensure root modules remain highly reusable across teams and promotes testing. -- **Enables Efficient Configuration:** Borrowing from the Kustomize playbook, Atmos makes configurations streamlined. It employs imports, hierarchy, inheritance, and deep merging, thus establishing company-wide standards effortlessly. -- **Environment Consistency:** With a nod to helmfile, Atmos ensures environments remain consistent, providing a toolkit that ensures reliability, no matter where you deploy. -- **Ensures Structured Modularity:** With Atmos, write Terraform configurations modularly using stacks and catalogs. - This not only ensures the code is reusable but also that it's efficient. -- **Promotes Reusable Building Blocks:** Set up a robust library of proven and easily reusable components (terraform root modules). Once done, there's minimal need for extra HCL work. This reduces the number of custom root modules needed in an organization and facilitates integration testing. -- **Makes Composition Easier:** Think [Docker Compose](https://docs.docker.com/compose/intro/features-uses/), but for Terraform. Atmos seamlessly integrates root modules into a stack manifest. -- **Stack Organization:** Keeping Terraform configurations organized is a breeze with Atmos's stack-based approach for combining components to build your "Stack". It's the solution for those multi-config puzzles. -- **Simplifies State Backends:** Atmos can generate a backend configuration dynamically based on the context within its stack. -- **OPA Policy Controls:** Atmos integrates [OPA](https://www.openpolicyagent.org/), offering high-level policy enforcement based on configuration values rather than the intricate HCL code details. This enhancement doesn't negate using tools like `tfsec`, `tflint`, or `checkov`, since none function at this elevated capacity. -- **Dependency Coordination:** Atmos takes the lead, ensuring Terraform components that depend on each other play nicely. -- **Standardized Workflows:** Workflows capture the intricate details of how to invoke commands, so it's easy to codify routine operations, the same way developers use `Makefiles` (or, more recently, [`Gotask`](https://github.com/go-task/task)) -- **Turnkey CI/CD:** Integrate with [GitHub Actions](https://atmos.tools/integrations/github-actions), [Spacelift](https://atmos.tools/integrations/spacelift), or [Atlantis](https://atmos.tools/integrations/atlantis) seamlessly. With Atmos, you can avoid the steep costs associated with commercial solutions that charge based on the number of resources under management, self-hosted runners, or users. - -Oh yes, and it's entirely free and truly Open Source (licensed APACHE2) like [everything else Cloud Posse builds](https://github.com/cloudposse)! 🔥 diff --git a/website/docs/troubleshooting/debugging.md b/website/docs/troubleshoot/debugging.md similarity index 76% rename from website/docs/troubleshooting/debugging.md rename to website/docs/troubleshoot/debugging.md index 4c18d7f69..1d78f5394 100644 --- a/website/docs/troubleshooting/debugging.md +++ b/website/docs/troubleshoot/debugging.md @@ -2,6 +2,7 @@ title: Debugging sidebar_position: 2 sidebar_label: Debugging +sidebar_class_name: hidden --- :::note diff --git a/website/docs/troubleshooting/errors.mdx b/website/docs/troubleshoot/errors.mdx similarity index 98% rename from website/docs/troubleshooting/errors.mdx rename to website/docs/troubleshoot/errors.mdx index bfe553d8d..12c7219d7 100644 --- a/website/docs/troubleshooting/errors.mdx +++ b/website/docs/troubleshoot/errors.mdx @@ -1,7 +1,7 @@ --- -title: Errors +title: Common Errors sidebar_position: 1 -sidebar_label: Errors +sidebar_label: Common Errors --- ## Common Mistakes @@ -26,8 +26,6 @@ stacks: name_pattern: "{tenant}-{environment}-{stage}" ``` -
- ### Error: `The stack name pattern ... does not have a tenant defined` ```console @@ -42,8 +40,6 @@ stacks: name_pattern: "{tenant}-{environment}-{stage}" ``` -
- ### Error: `depends_on expected a map, got slice` ```console @@ -87,8 +83,6 @@ components: enabled: true ``` -
- :::tip For more information, refer to: diff --git a/website/docs/troubleshooting/troubleshooting.mdx b/website/docs/troubleshooting/troubleshooting.mdx deleted file mode 100644 index 64a7145d5..000000000 --- a/website/docs/troubleshooting/troubleshooting.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Troubleshooting -sidebar_position: 9 -sidebar_label: Troubleshooting -description: Troubleshooting -id: troubleshooting ---- - -# Troubleshooting - - -import DocCardList from "@theme/DocCardList"; - - diff --git a/website/docs/tutorials/atmos-component-migrations-in-yaml.mdx b/website/docs/tutorials/atmos-component-migrations-in-yaml.mdx index 43987510f..3cb56c254 100644 --- a/website/docs/tutorials/atmos-component-migrations-in-yaml.mdx +++ b/website/docs/tutorials/atmos-component-migrations-in-yaml.mdx @@ -39,7 +39,7 @@ description: "Learn how to migrate an Atmos component to a new name or to use th import: - gbl-ue2 - catalog/vpc - + components: terraform: vpc: @@ -72,7 +72,7 @@ description: "Learn how to migrate an Atmos component to a new name or to use th 1. Pull down the latest `vpc` component and repeat the previous step (optional) ```sh - ⨠ wget https://raw.githubusercontent.com/cloudposse/atmos/main/examples/quick-start/components/terraform/vpc/component.yaml -O components/terraform/vpc/component.yaml + ⨠ wget https://raw.githubusercontent.com/cloudposse/atmos/main/examples/quick-start-advanced/components/terraform/vpc/component.yaml -O components/terraform/vpc/component.yaml ⨠ sed -i 's,infra/vpc-flow-logs-bucket,vpc,g' components/terraform/vpc/component.yaml ⨠ atmos vendor pull -c vpc ``` diff --git a/website/docs/tutorials/atmos-example-infra.mdx b/website/docs/tutorials/atmos-example-infra.mdx index 19e115e42..074b9c9fd 100644 --- a/website/docs/tutorials/atmos-example-infra.mdx +++ b/website/docs/tutorials/atmos-example-infra.mdx @@ -5,11 +5,11 @@ sidebar_position: 3 description: "Learn about the Example Infrastructure that Atmos shows how to configure and provision" --- -The [example](https://github.com/cloudposse/atmos/tree/master/examples/quick-start) folder contains a complete solution that shows how to: +The [example](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced) folder contains a complete solution that shows how to: - Structure the Terraform components - Configure the CLI -- Add [stack configurations](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/stacks) for the Terraform and helmfile components (to +- Add [stack configurations](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/stacks) for the Terraform and helmfile components (to provision them to different environments and stages) ## Example Filesystem Layout @@ -55,10 +55,10 @@ This example provides a simple filesystem layout that looks like this: Atmos provides separation of configuration and code, allowing you to provision the same code into different regions, environments and stages. In our example, all the code (Terraform and helmfiles) is in -the [components](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components) folder. +the [components](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components) folder. The centralized stack configurations (variables for the Terraform and helmfile components) are in -the [stacks](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/stacks) folder. +the [stacks](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/stacks) folder. In the example, all stack configuration files are broken down by environments and stages and use the predefined format `$environment-$stage.yaml`. @@ -69,15 +69,15 @@ The global values get merged with the `$environment-$stage.yaml` configuration f In the example, we defined a few config files: -- [stacks/orgs/cp/tenant1/dev/us-east-2.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/stacks/orgs/cp/tenant1/dev/us-east-2.yaml) +- [stacks/orgs/cp/tenant1/dev/us-east-2.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/stacks/orgs/cp/tenant1/dev/us-east-2.yaml) - stack configuration (Terraform and helmfile variables) for the environment `ue2` and stage `dev` -- [stacks/orgs/cp/tenant1/staging/us-east-2.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/stacks/orgs/cp/tenant1/staging/us-east-2.yaml) +- [stacks/orgs/cp/tenant1/staging/us-east-2.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/stacks/orgs/cp/tenant1/staging/us-east-2.yaml) - stack configuration (Terraform and helmfile variables) for the environment `ue2` and stage `staging` -- [stacks/orgs/cp/tenant1/prod/us-east-2.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/stacks/orgs/cp/tenant1/prod/us-east-2.yaml) +- [stacks/orgs/cp/tenant1/prod/us-east-2.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/stacks/orgs/cp/tenant1/prod/us-east-2.yaml) - stack configuration (Terraform and helmfile variables) for the environment `ue2` and stage `prod` -- [stacks/orgs/cp/tenant1/dev/global-region.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/stacks/ue2-globals.yaml) - global +- [stacks/orgs/cp/tenant1/dev/global-region.yaml](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/stacks/ue2-globals.yaml) - global settings for the environment `ue2` (e.g. `region`, `environment`) -- [stacks/orgs/cp/_defaults.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start/stacks/orgs/cp/_defaults.yaml) - global settings +- [stacks/orgs/cp/_defaults.yaml](https://github.com/cloudposse/atmos/blob/master/examples/quick-start-advanced/stacks/orgs/cp/_defaults.yaml) - global settings for the entire solution __NOTE:__ The stack configuration structure and the file names described above are just an example of how to name and structure the config files. @@ -132,11 +132,11 @@ The `components` section consists of the following: - `terraform` - defines variables, the binary to execute, and the backend for each Terraform component. Terraform component names correspond to the Terraform components in - the [terraform](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/terraform) folder + the [terraform](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/terraform) folder - `helmfile` - defines variables and the binary to execute for each helmfile component. Helmfile component names correspond to the helmfile components in - the [helmfile](https://github.com/cloudposse/atmos/tree/master/examples/quick-start/components/helmfile) folder + the [helmfile](https://github.com/cloudposse/atmos/tree/master/examples/quick-start-advanced/components/helmfile) folder ## Run the Example diff --git a/website/docs/tutorials/tutorials.mdx b/website/docs/tutorials/tutorials.mdx index 8396504ec..e2ae4af81 100644 --- a/website/docs/tutorials/tutorials.mdx +++ b/website/docs/tutorials/tutorials.mdx @@ -11,6 +11,6 @@ id: tutorials Here are some lessons on how to implement Atmos in a project. -import DocCardList from "@theme/DocCardList"; +import DocCardList from '@theme/DocCardList' diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 7b3ced105..c0254ebf8 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -5,8 +5,11 @@ // https://docusaurus.io/docs/markdown-features/code-blocks#line-highlighting // https://github.com/FormidableLabs/prism-react-renderer/tree/master/packages/prism-react-renderer/src/themes +const path = require('path'); + const lightCodeTheme = require('prism-react-renderer').themes.vsDark; const darkCodeTheme = require('prism-react-renderer').themes.nightOwl; +const latestReleasePlugin = require('./plugins/fetch-latest-release'); const BASE_URL = ''; @@ -26,13 +29,15 @@ const config = { projectName: 'atmos', // Even if you don't use internalization, you can use this field to set useful - // metadata like html lang. For example, if your site is Chinese, you may want - // to replace "en" with "zh-Hans". + // metadata like html lang. i18n: { defaultLocale: 'en', locales: ['en'], }, + scripts: [ + ], + plugins: [ [ 'docusaurus-plugin-image-zoom', {}, @@ -40,11 +45,11 @@ const config = { [ '@docusaurus/plugin-client-redirects', { redirects: [ - /* + { - from: '/cli', - to: '/cli/configuration' - }*/ + from: '/reference/terraform-limitations', + to: '/introduction/why-atmos' + } ], }, ], @@ -64,6 +69,23 @@ const config = { containerId: 'GTM-KQ62MGX9', }, ], + [ + "posthog-docusaurus", + { + apiKey: "phc_G3idXOACKt4vIzgRu2FVP8ORO1D2VlkeEwX9mE2jDvT", + appUrl: "https://us.i.posthog.com", + enableInDevelopment: false, // optional + }, + ], + [ + 'docusaurus-plugin-sentry', + { + DSN: 'b022344b0e7cc96f803033fff3b377ee@o56155.ingest.us.sentry.io/4507472203087872', + }, + ], + [ + path.resolve(__dirname, 'plugins', 'fetch-latest-release'), {} + ] ], presets: [ @@ -89,17 +111,17 @@ const config = { theme: { customCss: require.resolve('./src/css/custom.css'), }, - + }), ], ], - themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ docs: { sidebar: { hideable: true, + autoCollapseCategories: true, }, }, navbar: { @@ -113,55 +135,44 @@ const config = { height: 36 }, items: [ + { + label: `Latest Release`, + href: `https://github.com/cloudposse/atmos/releases/latest`, + position: 'left', + className: 'latest-release-link' // Add a class to identify this link + }, { type: 'doc', docId: 'introduction/index', position: 'left', - label: 'Docs', + label: 'Learn', }, { to: '/cli', position: 'left', - label: 'CLI' + label: 'Reference' }, { - type: 'dropdown', label: 'Community', - position: 'right', - items: [ - { - label: 'GitHub Discussions', - href: 'https://ask.sweetops.com/', - }, - { - label: 'Community', - href: 'https://sweetops.com/', - }, - { - label: 'Slack', - href: 'https://slack.sweetops.com/', - }, - { - label: 'Slack Archives', - href: 'https://archive.sweetops.com/atmos/', - }, - { - label: 'Office Hours', - href: 'https://cloudposse.com/office-hours/', - }, - ], + position: 'left', + to: '/community' }, + // Algolia search configuration { - to: 'https://cloudposse.com/services/', - label: 'Get Help', + type: 'search', position: 'right', - className: 'button button--primary navbar-cta-button' }, { href: 'https://github.com/cloudposse/atmos', position: 'right', className: 'header-github-link', 'aria-label': 'GitHub repository', + }, + { + to: 'https://cloudposse.com/services/', + label: 'Get Help', + position: 'right', + className: 'button button--primary navbar-cta-button' } ], }, @@ -190,17 +201,29 @@ const config = { colorMode: { // "light" | "dark" defaultMode: 'dark', - + // Hides the switch in the navbar // Useful if you want to force a specific mode disableSwitch: false, - + // Should respect the user's color scheme preference // "light" | "dark" | "system" respectPrefersColorScheme: false, }, + + mermaid: { + theme: { + light: 'neutral', + dark: 'dark', + + }, + }, }), + customFields: { + latestRelease: 'v0.0.0', // initial placeholder + }, + markdown: { mermaid: true, }, diff --git a/website/examples b/website/examples new file mode 120000 index 000000000..a6573af9c --- /dev/null +++ b/website/examples @@ -0,0 +1 @@ +../examples \ No newline at end of file diff --git a/website/package-lock.json b/website/package-lock.json index 14938c6c9..c51d18d7c 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -14,6 +14,7 @@ "@docusaurus/plugin-google-tag-manager": "^3.4.0", "@docusaurus/preset-classic": "^3.4.0", "@docusaurus/theme-mermaid": "^3.4.0", + "@excalidraw/excalidraw": "^0.17.6", "@fortawesome/fontawesome-svg-core": "^6.5.2", "@fortawesome/free-brands-svg-icons": "^6.5.2", "@fortawesome/free-regular-svg-icons": "^6.5.2", @@ -24,13 +25,20 @@ "clsx": "^2.1.1", "custom-loaders": "file:plugins/custom-loaders", "docusaurus-plugin-image-zoom": "^2.0.0", + "docusaurus-plugin-sentry": "^2.0.0", "html-loader": "^5.0.0", "marked": "^13.0.0", + "node-fetch": "^3.3.2", + "posthog-docusaurus": "^2.0.0", + "posthog-js": "^1.140.1", "prism-react-renderer": "^2.3.1", + "raw-loader": "^4.0.2", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-hubspot-form": "^1.3.7", "react-image-gallery": "^1.3.0", "react-player": "^2.16.0", + "react-social-media-embed": "^2.5.13", "react-table": "^7.8.0", "remark-html": "^16.0.1", "remark-parse": "^11.0.0", @@ -223,116 +231,52 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", - "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.5", - "@babel/parser": "^7.23.5", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -356,62 +300,50 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", - "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dependencies": { - "@babel/types": "^7.23.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -419,14 +351,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -435,24 +359,19 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.5.tgz", - "integrity": "sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", + "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "semver": "^6.3.1" }, "engines": { @@ -471,11 +390,11 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", "semver": "^6.3.1" }, @@ -495,9 +414,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", - "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -510,68 +429,73 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", + "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -581,32 +505,32 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", - "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -616,13 +540,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -632,96 +556,99 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", - "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -792,9 +719,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", - "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -802,12 +729,27 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -817,13 +759,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -833,12 +775,12 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.3.tgz", - "integrity": "sha512-XaJak1qcityzrX0/IU5nKHb34VaibwP3saKqG6a/tppelgllOH13LUann4ZCIBcVOeE6H18K4Vx9QKkVww3z/w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -917,11 +859,11 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -931,11 +873,11 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -967,11 +909,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1075,11 +1017,11 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1104,11 +1046,11 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1118,13 +1060,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.4.tgz", - "integrity": "sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -1135,13 +1077,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1151,11 +1093,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1165,11 +1107,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1179,12 +1121,12 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1194,12 +1136,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -1210,18 +1152,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz", - "integrity": "sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz", + "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "globals": "^11.1.0" }, "engines": { @@ -1232,12 +1173,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1247,11 +1188,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz", + "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1261,12 +1202,12 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1276,11 +1217,11 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1290,11 +1231,11 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -1305,12 +1246,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1320,11 +1261,11 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -1335,11 +1276,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.3.tgz", - "integrity": "sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1349,13 +1291,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1365,11 +1307,11 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1380,11 +1322,11 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1394,11 +1336,11 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1409,11 +1351,11 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1423,12 +1365,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1438,13 +1380,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", + "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1454,14 +1396,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", - "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1471,12 +1413,12 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1486,12 +1428,12 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1501,11 +1443,11 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1515,11 +1457,11 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1530,11 +1472,11 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1545,15 +1487,14 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", "dependencies": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/plugin-transform-parameters": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1563,12 +1504,12 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1578,11 +1519,11 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1593,12 +1534,12 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz", + "integrity": "sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1609,11 +1550,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1623,12 +1564,12 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1638,13 +1579,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1655,11 +1596,11 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1669,11 +1610,11 @@ } }, "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.1.tgz", - "integrity": "sha512-QXp1U9x0R7tkiGB0FOk8o74jhnap0FlZ5gNkRIWdG3eP+SvMFg118e1zaWewDzgABb106QSKpVsD3Wgd8t6ifA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", + "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1683,11 +1624,11 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz", - "integrity": "sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1697,15 +1638,15 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", - "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/types": "^7.23.4" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1715,11 +1656,11 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.22.5" + "@babel/plugin-transform-react-jsx": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1729,12 +1670,12 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", - "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1744,11 +1685,11 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1759,11 +1700,11 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1773,15 +1714,15 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.4.tgz", - "integrity": "sha512-ITwqpb6V4btwUG0YJR82o2QvmWrLgDnx/p2A3CTPYGaRgULkDiC0DRA2C4jlRB9uXGUEfaSS/IGHfVW+ohzYDw==", - "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.6", - "babel-plugin-polyfill-corejs3": "^0.8.5", - "babel-plugin-polyfill-regenerator": "^0.5.3", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", + "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, "engines": { @@ -1800,11 +1741,11 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1814,12 +1755,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1829,11 +1770,11 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1843,11 +1784,11 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1857,11 +1798,11 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz", + "integrity": "sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1871,14 +1812,14 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.5.tgz", - "integrity": "sha512-2fMkXEJkrmwgu2Bsv1Saxgj30IXZdJ+84lQcKKI7sm719oXs0BBw2ZENKdJdR1PjWndgLCEBNXJOri0fk7RYQA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz", + "integrity": "sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1888,11 +1829,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1902,12 +1843,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1917,12 +1858,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1932,12 +1873,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1947,25 +1888,26 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.5.tgz", - "integrity": "sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A==", - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.3", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.7.tgz", + "integrity": "sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ==", + "dependencies": { + "@babel/compat-data": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -1977,58 +1919,58 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.4", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.5", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.3", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.3", - "@babel/plugin-transform-modules-umd": "^7.23.3", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.7", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.7", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.7", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.6", - "babel-plugin-polyfill-corejs3": "^0.8.5", - "babel-plugin-polyfill-regenerator": "^0.5.3", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, @@ -2061,16 +2003,16 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", - "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-transform-react-display-name": "^7.23.3", - "@babel/plugin-transform-react-jsx": "^7.22.15", - "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2080,15 +2022,15 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2103,9 +2045,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", - "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2114,9 +2056,9 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.5.tgz", - "integrity": "sha512-7+ziVclejQTLYhXl+Oi1f6gTGD1XDCeLa4R472TNGQxb08zbEJ0OdNoh5Piz+57Ltmui6xR88BXR4gS3/Toslw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.7.tgz", + "integrity": "sha512-eytSX6JLBY6PVAeQa2bFlDx/7Mmln/gaEpsit5a3WEvjGfiIytEsgAwuIXCPM0xvw0v0cJn3ilq0/TvXrW0kgA==", "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.14.0" @@ -2126,32 +2068,32 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", - "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.5", - "@babel/types": "^7.23.5", - "debug": "^4.1.0", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -2159,12 +2101,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", - "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2378,45 +2320,6 @@ "react-dom": "^18.0.0" } }, - "node_modules/@docusaurus/mdx-loader/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@docusaurus/mdx-loader/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@docusaurus/mdx-loader/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/@docusaurus/module-type-aliases": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz", @@ -2489,45 +2392,6 @@ "react-dom": "^18.0.0" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/@docusaurus/plugin-content-docs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz", @@ -2931,6 +2795,15 @@ "node": ">=18.0" } }, + "node_modules/@excalidraw/excalidraw": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@excalidraw/excalidraw/-/excalidraw-0.17.6.tgz", + "integrity": "sha512-fyCl+zG/Z5yhHDh5Fq2ZGmphcrALmuOdtITm8gN4d8w4ntnaopTXcTfnAAaU3VleDC6LhTkoLOTG6P5kgREiIg==", + "peerDependencies": { + "react": "^17.0.2 || ^18.2.0", + "react-dom": "^17.0.2 || ^18.2.0" + } + }, "node_modules/@fortawesome/fontawesome-common-types": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", @@ -3025,29 +2898,6 @@ "react-dom": "^18.0.0" } }, - "node_modules/@grnet/docusaurus-term-preview/node_modules/postel": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/postel/-/postel-0.1.5.tgz", - "integrity": "sha512-RpBl+D++vYGGRr8TYHJOyK5eJB+kg8iUgVx0zCiHNArfaG9EtUNcfu1ZWAeNHlMVL0jGDSFq22t8YXGK5FmGkQ==", - "peerDependencies": { - "react": "^16.13.1", - "react-dom": "^16.13.1", - "typescript": "~3.7.2" - } - }, - "node_modules/@grnet/docusaurus-term-preview/node_modules/typescript": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.7.tgz", - "integrity": "sha512-MmQdgo/XenfZPvVLtKZOq9jQQvzaUAUpcKW8Z43x9B2fOm4S5g//tPtMweZUIP+SoBqrVPEIm+dJeQ9dfO0QdA==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/@grnet/docusaurus-terminology": { "version": "2.0.0-rc.1", "resolved": "https://registry.npmjs.org/@grnet/docusaurus-terminology/-/docusaurus-terminology-2.0.0-rc.1.tgz", @@ -3254,6 +3104,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/@grnet/webpack-terms-loader/node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@grnet/webpack-terms-loader/node_modules/unist-util-position": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", @@ -3263,6 +3122,33 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/@grnet/webpack-terms-loader/node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@grnet/webpack-terms-loader/node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@grnet/webpack-terms-replace-loader": { "version": "2.0.0-rc.1", "resolved": "https://registry.npmjs.org/@grnet/webpack-terms-replace-loader/-/webpack-terms-replace-loader-2.0.0-rc.1.tgz", @@ -3314,59 +3200,47 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -3378,14 +3252,14 @@ } }, "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" }, "node_modules/@mdx-js/mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.0.tgz", - "integrity": "sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", @@ -3416,53 +3290,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/@mdx-js/mdx/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@mdx-js/mdx/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/mdx/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/mdx/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/@mdx-js/react": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", @@ -3530,6 +3357,11 @@ "node": ">=12.22.0" } }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, "node_modules/@pnpm/npm-conf": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", @@ -3544,14 +3376,14 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.23", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==" + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" }, "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -3756,6 +3588,45 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@svgr/core/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@svgr/core/node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@svgr/hast-util-to-babel-ast": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", @@ -3813,6 +3684,45 @@ "@svgr/core": "*" } }, + "node_modules/@svgr/plugin-svgo/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@svgr/plugin-svgo/node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@svgr/webpack": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", @@ -3923,18 +3833,18 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", - "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -3946,9 +3856,9 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/estree-jsx": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.3.tgz", - "integrity": "sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "dependencies": { "@types/estree": "*" } @@ -3965,9 +3875,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.41", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", - "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz", + "integrity": "sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -3981,9 +3891,9 @@ "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" }, "node_modules/@types/hast": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.3.tgz", - "integrity": "sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "dependencies": { "@types/unist": "*" } @@ -4038,22 +3948,22 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/mdast": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", - "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "dependencies": { "@types/unist": "*" } }, "node_modules/@types/mdx": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.10.tgz", - "integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==" + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" }, "node_modules/@types/mime": { "version": "1.3.5", @@ -4066,37 +3976,40 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/node-forge": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz", - "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, "node_modules/@types/prismjs": { - "version": "1.26.3", - "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", - "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==" + "version": "1.26.4", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", + "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==" }, "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/qs": { - "version": "6.9.10", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", - "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==" + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" }, "node_modules/@types/range-parser": { "version": "1.2.7", @@ -4104,12 +4017,11 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/react": { - "version": "18.0.25", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz", - "integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, @@ -4123,9 +4035,9 @@ } }, "node_modules/@types/react-router-config": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.10.tgz", - "integrity": "sha512-Wn6c/tXdEgi9adCMtDwx8Q2vGty6TsPTc/wCQQ9kAlye8UqFxj0vGFWWuhywNfkwqth+SOgJxQTLTZukrqDQmQ==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", "dependencies": { "@types/history": "^4.7.11", "@types/react": "*", @@ -4155,11 +4067,6 @@ "@types/node": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" - }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -4178,13 +4085,13 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", - "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dependencies": { "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@types/node": "*", + "@types/send": "*" } }, "node_modules/@types/sockjs": { @@ -4221,15 +4128,20 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, + "node_modules/@types/youtube-player": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/@types/youtube-player/-/youtube-player-5.5.11.tgz", + "integrity": "sha512-pM41CDBqJqBmTeJWnF7NOGz82IQoYOhqzMYXv5vKCXBqGiYSLldxMtpCk6KAEtADTy49S45AriYaCaZyeUX38Q==" + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -4246,9 +4158,9 @@ "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", @@ -4266,14 +4178,14 @@ "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { @@ -4298,26 +4210,26 @@ "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/leb128": "1.11.6", @@ -4325,22 +4237,22 @@ } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", @@ -4349,11 +4261,11 @@ } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -4399,9 +4311,9 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "bin": { "acorn": "bin/acorn" }, @@ -4409,10 +4321,10 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "peerDependencies": { "acorn": "^8" } @@ -4426,17 +4338,20 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } }, "node_modules/address": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.1.tgz", - "integrity": "sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", "engines": { "node": ">= 10.0.0" } @@ -4454,14 +4369,14 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -4484,32 +4399,15 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "peerDependencies": { - "ajv": "^6.9.1" + "ajv": "^8.8.2" } }, "node_modules/algoliasearch": { @@ -4605,9 +4503,9 @@ } }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -4627,9 +4525,9 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-union": { "version": "2.1.0", @@ -4716,12 +4614,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", - "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.3", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" }, "peerDependencies": { @@ -4737,28 +4635,73 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", - "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.3", - "core-js-compat": "^3.33.1" + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", - "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.3" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/babel-types/node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -4787,20 +4730,23 @@ } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -4808,7 +4754,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -4850,12 +4796,10 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } @@ -4896,20 +4840,20 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "funding": [ { "type": "opencollective", @@ -4925,10 +4869,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -4975,24 +4919,19 @@ "node": ">=14.16" } }, - "node_modules/cacheable-request/node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5038,9 +4977,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001607", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz", - "integrity": "sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==", + "version": "1.0.30001634", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001634.tgz", + "integrity": "sha512-fbBYXQ9q3+yp1q1gBk86tOFs4pyn/yxFm5ZNP18OXJDfA3txImOY9PhfxVggZ4vRHDqoU8NrKU81eN0OtzOgRA==", "funding": [ { "type": "opencollective", @@ -5161,15 +5100,9 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -5182,22 +5115,34 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "engines": { "node": ">=6.0" } }, "node_modules/ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } }, "node_modules/classnames": { "version": "2.5.1", @@ -5215,6 +5160,14 @@ "node": ">= 10.0" } }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -5235,9 +5188,9 @@ } }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dependencies": { "string-width": "^4.2.0" }, @@ -5279,17 +5232,6 @@ "node": ">=6" } }, - "node_modules/clone-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -5334,9 +5276,9 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/combine-promises": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz", - "integrity": "sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", "engines": { "node": ">=10" } @@ -5484,9 +5426,9 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -5542,13 +5484,13 @@ } }, "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dependencies": { "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", "merge2": "^1.4.1", "slash": "^4.0.0" }, @@ -5571,9 +5513,9 @@ } }, "node_modules/core-js": { - "version": "3.33.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.3.tgz", - "integrity": "sha512-lo0kOocUlLKmm6kv/FswQL8zbkH7mVsLJ/FULClOhv8WRVmKLVcs6XPNQAzstfeJTCHMyButEwG+z1kHxHoDZw==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", + "integrity": "sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -5581,11 +5523,11 @@ } }, "node_modules/core-js-compat": { - "version": "3.33.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.3.tgz", - "integrity": "sha512-cNzGqFsh3Ot+529GIXacjTJ7kegdt5fPXxCBVS1G0iaZpuo/tBz399ymceLJveQhFFZ8qThHiP3fzuoQjKN2ow==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dependencies": { - "browserslist": "^4.22.1" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -5593,9 +5535,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.33.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.33.3.tgz", - "integrity": "sha512-taJ00IDOP+XYQEA2dAe4ESkmHt1fL8wzYDo3mRWQey8uO9UojlBFMneA65kMyxfYP7106c6LzWaq7/haDT6BCQ==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.37.1.tgz", + "integrity": "sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -5616,28 +5558,18 @@ } }, "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=8" } }, "node_modules/cross-spawn": { @@ -5690,18 +5622,18 @@ } }, "node_modules/css-loader": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", - "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", "dependencies": { "icss-utils": "^5.1.0", - "postcss": "^8.4.21", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.3", - "postcss-modules-scope": "^3.0.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "engines": { "node": ">= 12.13.0" @@ -5711,7 +5643,16 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/css-minimizer-webpack-plugin": { @@ -5930,22 +5871,18 @@ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" }, "node_modules/csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/custom-loaders": { "resolved": "plugins/custom-loaders", "link": true }, "node_modules/cytoscape": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.27.0.tgz", - "integrity": "sha512-pPZJilfX9BxESwujODz5pydeGi+FBrXq1rcaB1mfhFXXFJ9GjE6CNndAk+8jPzoXGD+16LtSS4xlYEIUiW4Abg==", - "dependencies": { - "heap": "^0.2.6", - "lodash": "^4.17.21" - }, + "version": "3.29.2", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.29.2.tgz", + "integrity": "sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ==", "engines": { "node": ">=0.10" } @@ -5961,34 +5898,10 @@ "cytoscape": "^3.2.0" } }, - "node_modules/cytoscape-fcose": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", - "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", - "dependencies": { - "cose-base": "^2.2.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/cose-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", - "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", - "dependencies": { - "layout-base": "^2.0.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/layout-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", - "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" - }, "node_modules/d3": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", - "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", "dependencies": { "d3-array": "3", "d3-axis": "3", @@ -6193,9 +6106,9 @@ } }, "node_modules/d3-geo": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", - "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", "dependencies": { "d3-array": "2.5.0 - 3" }, @@ -6305,9 +6218,9 @@ } }, "node_modules/d3-scale-chromatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", - "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" @@ -6407,10 +6320,18 @@ "lodash-es": "^4.17.21" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" }, "node_modules/debounce": { "version": "1.2.1", @@ -6418,9 +6339,9 @@ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -6505,6 +6426,22 @@ "node": ">=10" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -6514,10 +6451,11 @@ } }, "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -6550,11 +6488,11 @@ } }, "node_modules/delaunator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", - "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", "dependencies": { - "robust-predicates": "^3.0.0" + "robust-predicates": "^3.0.2" } }, "node_modules/depd": { @@ -6588,9 +6526,9 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" }, "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", "dependencies": { "address": "^1.0.1", "debug": "4" @@ -6598,6 +6536,9 @@ "bin": { "detect": "bin/detect-port.js", "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" } }, "node_modules/detect-port-alt": { @@ -6642,9 +6583,9 @@ } }, "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "engines": { "node": ">=0.3.1" } @@ -6660,11 +6601,6 @@ "node": ">=8" } }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" - }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -6688,6 +6624,19 @@ "@docusaurus/theme-classic": ">=3.0.0" } }, + "node_modules/docusaurus-plugin-sentry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-sentry/-/docusaurus-plugin-sentry-2.0.0.tgz", + "integrity": "sha512-LiiQ90pbaJ4ztgmFegK3+p8ywX4m0XHNtKGIRY1UD6xVRFubIejFFGaDXWOVU5FuATcMmE0d+WPNRPHLyYlFFw==", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@docusaurus/core": ">=3", + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/dom-align": { "version": "1.12.4", "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", @@ -6740,9 +6689,9 @@ } }, "node_modules/dompurify": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", - "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.5.tgz", + "integrity": "sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==" }, "node_modules/domutils": { "version": "3.1.0", @@ -6804,14 +6753,14 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.730", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.730.tgz", - "integrity": "sha512-oJRPo82XEqtQAobHpJIR3zW5YO3sSRRkPz2an4yxi1UvqhsGm54vR/wzTFV74a3soDOJ8CKW7ajOOX5ESzddwg==" + "version": "1.4.803", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.803.tgz", + "integrity": "sha512-61H9mLzGOCLLVsnLiRzCbc63uldP0AniRYPV3hbGVtONA1pI7qSGILdbofR7A8TMbOypDocEAjH/e+9k1QIe3g==" }, "node_modules/elkjs": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", - "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", + "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -6849,9 +6798,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -6861,9 +6810,9 @@ } }, "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { "node": ">=0.12" }, @@ -6879,15 +6828,34 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz", + "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==" }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { "node": ">=6" } @@ -7020,25 +6988,14 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/estree-util-to-js/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, "node_modules/estree-util-value-to-estree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.0.1.tgz", - "integrity": "sha512-b2tdzTurEIbwRh+mKrEcaWfu1wgb8J1hVsgREg7FFiecWwK/PhO8X0kyc+0bIcKNtD4sqxIdNoRy6/p/TvECEA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.1.tgz", + "integrity": "sha512-5mvUrF2suuv5f5cGDnDphIy4/gW86z82kl5qG6mM9z04SEQI4FB5Apmaw/TGEf3l55nLtMs5s51dmhUzvAHQCA==", "dependencies": { "@types/estree": "^1.0.0", "is-plain-obj": "^4.0.0" }, - "engines": { - "node": ">=16.0.0" - }, "funding": { "url": "https://github.com/sponsors/remcohaszing" } @@ -7139,16 +7096,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -7179,11 +7136,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, "node_modules/express/node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -7243,9 +7195,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -7271,9 +7223,9 @@ } }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { "reusify": "^1.0.4" } @@ -7312,6 +7264,33 @@ "node": ">=0.4.0" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + }, "node_modules/file-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", @@ -7331,10 +7310,38 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/file-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -7357,9 +7364,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -7427,14 +7434,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -7444,9 +7443,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -7463,9 +7462,9 @@ } }, "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", - "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", "dependencies": { "@babel/code-frame": "^7.8.3", "@types/json-schema": "^7.0.5", @@ -7500,19 +7499,27 @@ } } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { @@ -7529,6 +7536,11 @@ "node": ">=10" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", @@ -7570,6 +7582,17 @@ "node": ">=0.4.x" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -7612,9 +7635,9 @@ } }, "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -7622,9 +7645,9 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -7635,9 +7658,12 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -7648,13 +7674,18 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7685,6 +7716,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7800,7 +7832,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/got": { + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { "version": "12.6.1", "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", @@ -7836,9 +7879,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/gray-matter": { "version": "4.0.3", @@ -7893,17 +7936,6 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -7913,11 +7945,22 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7945,6 +7988,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hast-util-from-parse5": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", @@ -7986,9 +8040,9 @@ } }, "node_modules/hast-util-raw": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.1.tgz", - "integrity": "sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.3.tgz", + "integrity": "sha512-ICWvVOF2fq4+7CMmtCPD5CM4QKjPbHpPotE6+8tDooV0ZuyJVUzHsrNX+O5NaRbieTf0F7FfeBOMAwi6Td0+yQ==", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", @@ -8009,45 +8063,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-raw/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/hast-util-sanitize": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-5.0.1.tgz", @@ -8090,9 +8105,9 @@ } }, "node_modules/hast-util-to-html": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.0.tgz", - "integrity": "sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.1.tgz", + "integrity": "sha512-hZOofyZANbyWo+9RP75xIDV/gq+OUKx+T46IlwERnKmfpwp81XBFbT9mi26ws+SJchA4RVUQwIBJpqEOBhMzEQ==", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", @@ -8139,16 +8154,16 @@ } }, "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.2.tgz", - "integrity": "sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==" + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" }, "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.5.tgz", - "integrity": "sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", "dependencies": { - "inline-style-parser": "0.2.2" + "inline-style-parser": "0.2.3" } }, "node_modules/hast-util-to-parse5": { @@ -8205,11 +8220,6 @@ "he": "bin/he" } }, - "node_modules/heap": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", - "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" - }, "node_modules/history": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", @@ -8275,9 +8285,9 @@ } }, "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", "funding": [ { "type": "github", @@ -8362,9 +8372,9 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", - "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", "dependencies": { "@types/html-minifier-terser": "^6.0.0", "html-minifier-terser": "^6.0.2", @@ -8380,7 +8390,16 @@ "url": "https://opencollective.com/html-webpack-plugin" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/html-webpack-plugin/node_modules/commander": { @@ -8549,17 +8568,17 @@ } }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { "node": ">= 4" } }, "node_modules/image-size": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz", - "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", "dependencies": { "queue": "6.0.2" }, @@ -8567,13 +8586,13 @@ "image-size": "bin/image-size.js" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.x" } }, "node_modules/immer": { - "version": "9.0.16", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz", - "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==", + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -8630,6 +8649,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -8675,9 +8695,9 @@ } }, "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", "engines": { "node": ">= 10" } @@ -8754,11 +8774,11 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8901,9 +8921,12 @@ } }, "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, "engines": { "node": ">=0.10.0" } @@ -9030,21 +9053,21 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "bin": { "jiti": "bin/jiti.js" } }, "node_modules/joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "version": "17.13.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.1.tgz", + "integrity": "sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg==", "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } @@ -9087,9 +9110,9 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json5": { "version": "2.2.3", @@ -9113,6 +9136,29 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/katex": { + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -9179,9 +9225,9 @@ } }, "node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "engines": { "node": ">=14" }, @@ -9299,14 +9345,11 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "yallist": "^3.0.2" } }, "node_modules/markdown-extensions": { @@ -9353,77 +9396,60 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", - "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/mdast-util-definitions/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" }, - "node_modules/mdast-util-directive/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, + "node_modules/mdast-util-definitions/node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-directive/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "node_modules/mdast-util-definitions/node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", "dependencies": { - "@types/unist": "^3.0.0" + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-directive/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "node_modules/mdast-util-definitions/node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-directive/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "node_modules/mdast-util-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", + "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", "dependencies": { + "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", @@ -9456,35 +9482,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdast-util-find-and-replace/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-from-markdown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", - "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", @@ -9547,76 +9548,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdast-util-frontmatter/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-frontmatter/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-frontmatter/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-frontmatter/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", - "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { "type": "opencollective", @@ -9640,9 +9583,9 @@ } }, "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -9689,64 +9632,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-gfm-strikethrough": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", @@ -9761,64 +9646,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-strikethrough/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-gfm-table": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", @@ -9835,64 +9662,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-table/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-gfm-task-list-item": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", @@ -9900,650 +9669,138 @@ "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", - "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", - "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.0.0.tgz", - "integrity": "sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-remove-position": "^5.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.0.0.tgz", - "integrity": "sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.0.2.tgz", - "integrity": "sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz", - "integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==", - "dependencies": { - "@types/unist": "^2.0.0", - "longest-streak": "^2.0.0", - "mdast-util-to-string": "^2.0.0", - "parse-entities": "^2.0.0", - "repeat-string": "^1.0.0", - "zwitch": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, - "node_modules/mdast-util-to-markdown/node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown/node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown/node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown/node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown/node_modules/longest-streak": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", - "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown/node_modules/mdast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", - "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown/node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown/node_modules/zwitch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", - "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/mdast-util-to-string": { @@ -10582,11 +9839,11 @@ "integrity": "sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==" }, "node_modules/memfs": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.10.tgz", - "integrity": "sha512-0bCUP+L79P4am30yP1msPzApwuMQG23TjwlwdHeEV5MxioDR1a0AgB0T9FfggU52eJuDCq8WVwb5ekznFyWiTQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", "dependencies": { - "fs-monkey": "^1.0.3" + "fs-monkey": "^1.0.4" }, "engines": { "node": ">= 4.0.0" @@ -10616,22 +9873,22 @@ } }, "node_modules/mermaid": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.6.1.tgz", - "integrity": "sha512-Hky0/RpOw/1il9X8AvzOEChfJtVvmXm+y7JML5C//ePYMy0/9jCEmW1E1g86x9oDfW9+iVEdTV/i+M6KWRNs4A==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.1.tgz", + "integrity": "sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA==", "dependencies": { "@braintree/sanitize-url": "^6.0.1", "@types/d3-scale": "^4.0.3", "@types/d3-scale-chromatic": "^3.0.0", - "cytoscape": "^3.23.0", + "cytoscape": "^3.28.1", "cytoscape-cose-bilkent": "^4.1.0", - "cytoscape-fcose": "^2.1.0", "d3": "^7.4.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.10", "dayjs": "^1.11.7", "dompurify": "^3.0.5", - "elkjs": "^0.8.2", + "elkjs": "^0.9.0", + "katex": "^0.16.9", "khroma": "^2.0.0", "lodash-es": "^4.17.21", "mdast-util-from-markdown": "^1.3.0", @@ -11113,9 +10370,9 @@ } }, "node_modules/micromark-core-commonmark": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", - "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", "funding": [ { "type": "GitHub Sponsors", @@ -11165,9 +10422,9 @@ } }, "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11236,9 +10493,9 @@ } }, "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11285,9 +10542,9 @@ } }, "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11353,9 +10610,9 @@ } }, "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11425,9 +10682,9 @@ } }, "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11526,9 +10783,9 @@ } }, "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11607,9 +10864,9 @@ } }, "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11685,9 +10942,9 @@ } }, "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11759,9 +11016,9 @@ } }, "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11844,9 +11101,9 @@ } }, "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11898,9 +11155,9 @@ } }, "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11953,9 +11210,9 @@ } }, "node_modules/micromark-factory-label/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12012,9 +11269,9 @@ } }, "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12120,9 +11377,9 @@ } }, "node_modules/micromark-factory-title/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12194,9 +11451,9 @@ } }, "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12315,9 +11572,9 @@ } }, "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12422,9 +11679,9 @@ } }, "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12597,9 +11854,9 @@ } }, "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12631,9 +11888,9 @@ ] }, "node_modules/micromark-util-subtokenize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", - "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", "funding": [ { "type": "GitHub Sponsors", @@ -12716,9 +11973,9 @@ } }, "node_modules/micromark/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12750,11 +12007,11 @@ ] }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -12811,11 +12068,12 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.7.6", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", - "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", + "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", "dependencies": { - "schema-utils": "^4.0.0" + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" }, "engines": { "node": ">= 12.13.0" @@ -12861,9 +12119,9 @@ } }, "node_modules/mrmime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", - "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", "engines": { "node": ">=10" } @@ -12924,6 +12182,24 @@ "tslib": "^2.0.3" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -12938,6 +12214,23 @@ "node": ">=18" } }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -12972,6 +12265,17 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -13024,12 +12328,12 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -13087,9 +12391,9 @@ } }, "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -13104,49 +12408,21 @@ }, "node_modules/opener": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dependencies": { - "p-limit": "^4.0.0" - }, + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12.20" } }, - "node_modules/p-locate/node_modules/p-limit": { + "node_modules/p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", @@ -13160,12 +12436,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dependencies": { + "p-limit": "^4.0.0" + }, "engines": { - "node": ">=12.20" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -13357,11 +12636,11 @@ } }, "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/path-is-absolute": { @@ -13436,9 +12715,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -13499,6 +12778,20 @@ "node": ">=6" } }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pkg-up/node_modules/p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -13651,13 +12944,13 @@ } }, "node_modules/postcss-loader": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", - "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", "dependencies": { - "cosmiconfig": "^8.2.0", - "jiti": "^1.18.2", - "semver": "^7.3.8" + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" }, "engines": { "node": ">= 14.15.0" @@ -13671,6 +12964,45 @@ "webpack": "^5.0.0" } }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss-loader/node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/postcss-merge-idents": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", @@ -13779,9 +13111,9 @@ } }, "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "engines": { "node": "^10 || ^12 || >= 14" }, @@ -13790,9 +13122,9 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -13806,9 +13138,9 @@ } }, "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -14016,9 +13348,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", + "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -14086,6 +13418,42 @@ "postcss": "^8.4.31" } }, + "node_modules/postel": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/postel/-/postel-0.1.5.tgz", + "integrity": "sha512-RpBl+D++vYGGRr8TYHJOyK5eJB+kg8iUgVx0zCiHNArfaG9EtUNcfu1ZWAeNHlMVL0jGDSFq22t8YXGK5FmGkQ==", + "peerDependencies": { + "react": "^16.13.1", + "react-dom": "^16.13.1", + "typescript": "~3.7.2" + } + }, + "node_modules/posthog-docusaurus": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/posthog-docusaurus/-/posthog-docusaurus-2.0.0.tgz", + "integrity": "sha512-nDSTIhmH/Fexv347Gx6wBCE97Z+fZTj0p/gqVYAaolMwSdVuzwyFWcFA+aW9uzA5Y5hjzRwwKJJOrIv8smkYkA==", + "engines": { + "node": ">=10.15.1" + } + }, + "node_modules/posthog-js": { + "version": "1.140.1", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.140.1.tgz", + "integrity": "sha512-UeKuAtQSvbzmTCzNVaauku8F194EYwAP33WrRrWZlDlMNbMy7GKcZOgKbr7jZqnha7FlVlHrWk+Rpyr1zCFhPQ==", + "dependencies": { + "fflate": "^0.4.8", + "preact": "^10.19.3" + } + }, + "node_modules/preact": { + "version": "10.22.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.22.0.tgz", + "integrity": "sha512-RRurnSjJPj4rp5K6XoP45Ui33ncb7e4H7WiOHVpjbkvqvA3U+N8Z6Qbo0AE6leGYBV66n8EhEaFixvIu3SkxFw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -14151,9 +13519,9 @@ } }, "node_modules/property-information": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.4.0.tgz", - "integrity": "sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -14272,9 +13640,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -14304,6 +13672,70 @@ "node": ">=0.10.0" } }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/raw-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/raw-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/raw-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -14335,13 +13767,13 @@ } }, "node_modules/rc-motion": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.0.tgz", - "integrity": "sha512-XIU2+xLkdIr1/h6ohPZXyPBMvOmuyFZQ/T0xnawz+Rh+gh4FINcnZmMT5UTIj6hgI0VLDjTaPeRd+smJeSPqiQ==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.1.tgz", + "integrity": "sha512-QD4bUqByjVQs7PhUT1d4bNxvtTcK9ETwtg7psbDfo6TmYalH/1hhjj4r2hbhW7g5OOEqYHhfwfj4noIvuOVRtQ==", "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", - "rc-util": "^5.21.0" + "rc-util": "^5.39.3" }, "peerDependencies": { "react": ">=16.9.0", @@ -14381,9 +13813,9 @@ } }, "node_modules/rc-util": { - "version": "5.39.1", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.39.1.tgz", - "integrity": "sha512-OW/ERynNDgNr4y0oiFmtes3rbEamXw7GHGbkbNd9iRr7kgT03T6fT0b9WpJ3mbxKhyOcAHnGcIoh5u/cjrC2OQ==", + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.42.1.tgz", + "integrity": "sha512-9raEonoOiRka2hXedkMjILdz24Z4UHfAoyWSi/na1B4w4fiBujV+atJEdQrZST+Bs7NuQB0FFBsRAdD8ykInfg==", "dependencies": { "@babel/runtime": "^7.18.3", "react-is": "^18.2.0" @@ -14394,9 +13826,9 @@ } }, "node_modules/rc-util/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", @@ -14467,9 +13899,9 @@ } }, "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", "engines": { "node": ">= 12.13.0" } @@ -14510,48 +13942,142 @@ "p-limit": "^3.0.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-html-props": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/react-html-props/-/react-html-props-2.0.9.tgz", + "integrity": "sha512-Q9wIP8hs4HFUb3CDh5tF1nKgZ4S9odU07tR/lZ+/9ePv+psxRy+mUn7ujjrCGwtrLA52AI41fXWr425yK1iyTA==", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0" + } + }, + "node_modules/react-hubspot-form": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/react-hubspot-form/-/react-hubspot-form-1.3.7.tgz", + "integrity": "sha512-gDeqIt23QlDfF7ci+jKAOKd2C4Ek4Nih+wzx+cttkvD1SdxsuL/mb+BylRiy7RjMS+4KAtQ3Jl7Iot1agJIUjQ==", + "dependencies": { + "styled-jsx": "^2.2.4" + } + }, + "node_modules/react-hubspot-form/node_modules/convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha512-LNHI/Ll1UqBTGhrR6vMhtVZmX4kjYdCJUjIM6Ydp7/oJ5w1C0MKrzELuUAmMlU0eKwBGx6PaO0TRZ/KDXAFTBg==" + }, + "node_modules/react-hubspot-form/node_modules/react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-hubspot-form/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "node_modules/react-hubspot-form/node_modules/styled-jsx": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-2.2.7.tgz", + "integrity": "sha512-L67wypf8ULpAFxbVefl7ccE/rutz9w/Q1eJLg8Szm4KyN+bmmmaHYfSyfogfDn2l/CmzOlf8/bHbVSI6EeWYkQ==", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "convert-source-map": "1.5.1", + "source-map": "0.6.1", + "string-hash": "1.1.3", + "stylis": "3.5.1", + "stylis-rule-sheet": "0.0.10" }, "peerDependencies": { - "react": "^18.3.1" + "react": "15.x.x || 16.x.x" } }, - "node_modules/react-error-overlay": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", - "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" - }, - "node_modules/react-fast-compare": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", - "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + "node_modules/react-hubspot-form/node_modules/stylis": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.1.tgz", + "integrity": "sha512-yM4PyeHuwhIOUHNJxi1/Mbq8kVLv4AkyE7IYLP/LK0lIFcr3tRa2H1iZlBYKIxOlf+/jruBTe8DdKSyQX9w4OA==" }, - "node_modules/react-helmet-async": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", - "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "invariant": "^2.2.4", - "prop-types": "^15.7.2", - "react-fast-compare": "^3.2.0", - "shallowequal": "^1.1.0" - }, + "node_modules/react-hubspot-form/node_modules/stylis-rule-sheet": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", "peerDependencies": { - "react": "^16.6.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + "stylis": "^3.5.0" } }, "node_modules/react-image-gallery": { @@ -14668,6 +14194,32 @@ "react": ">=15" } }, + "node_modules/react-social-media-embed": { + "version": "2.5.13", + "resolved": "https://registry.npmjs.org/react-social-media-embed/-/react-social-media-embed-2.5.13.tgz", + "integrity": "sha512-9udbyUZpG8lXhDzDHH6ceDZfhW7QGg2WoVjJD6F8PTOXJoULZTkvLV7vYpqeWthqP33iwagLEHo7goJVDuL7ug==", + "dependencies": { + "@types/youtube-player": "^5.5.5", + "classnames": "^2.5.1", + "react-html-props": "^2.0.3", + "react-sub-unsub": "^2.2.1", + "react-twitter-embed": "^4.0.4", + "react-youtube": "^10.1.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0" + } + }, + "node_modules/react-sub-unsub": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/react-sub-unsub/-/react-sub-unsub-2.2.7.tgz", + "integrity": "sha512-b2o0mIW8G4Yb3aaKxFB9iiCCHxCDGmogy+493oQpEJHjBy/hl6uf+6RhAinqKWRwi1fvO6mGIMVGsf2XYLL38g==", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0" + } + }, "node_modules/react-table": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz", @@ -14680,6 +14232,37 @@ "react": "^16.8.3 || ^17.0.0-0 || ^18.0.0" } }, + "node_modules/react-twitter-embed": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-twitter-embed/-/react-twitter-embed-4.0.4.tgz", + "integrity": "sha512-2JIL7qF+U62zRzpsh6SZDXNI3hRNVYf5vOZ1WRcMvwKouw+xC00PuFaD0aEp2wlyGaZ+f4x2VvX+uDadFQ3HVA==", + "dependencies": { + "scriptjs": "^2.5.9" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-youtube": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-10.1.0.tgz", + "integrity": "sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg==", + "dependencies": { + "fast-deep-equal": "3.1.3", + "prop-types": "15.8.1", + "youtube-player": "5.5.2" + }, + "engines": { + "node": ">= 14.x" + }, + "peerDependencies": { + "react": ">=0.14.1" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -14748,9 +14331,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regenerator-transform": { "version": "0.15.2", @@ -14918,6 +14501,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-gfm/node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-html": { "version": "16.0.1", "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-16.0.1.tgz", @@ -14935,9 +14532,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.0.tgz", - "integrity": "sha512-O7yfjuC6ra3NHPbRVxfflafAj3LTwx3b73aBvkEFU5z4PsD6FD4vrqJAkE5iNGLz71GdjXfgRqm3SQ0h0VuE7g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" @@ -14963,9 +14560,9 @@ } }, "node_modules/remark-rehype": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.0.0.tgz", - "integrity": "sha512-vx8x2MDMcxuE4lBmQ46zYUDfcFMmvg80WYX+UNLeG6ixjdCCLcw1lrgAukwBTuOFsS78eoAedHGn9sNM0w7TPw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", @@ -14979,75 +14576,148 @@ } }, "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz", + "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" + "mdast-util-to-markdown": "^0.6.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-stringify/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "node_modules/remark-stringify/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "node_modules/remark-stringify/node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/remark-stringify/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "node_modules/remark-stringify/node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/longest-streak": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", + "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/mdast-util-to-markdown": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz", + "integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==", "dependencies": { - "@types/unist": "^3.0.0" + "@types/unist": "^2.0.0", + "longest-streak": "^2.0.0", + "mdast-util-to-string": "^2.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.0.0", + "zwitch": "^1.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-stringify/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, + "node_modules/remark-stringify/node_modules/mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-stringify/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "node_modules/remark-stringify/node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-stringify/node_modules/zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, "node_modules/remark/node_modules/@types/mdast": { @@ -15220,18 +14890,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remark/node_modules/remark-stringify": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz", - "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==", - "dependencies": { - "mdast-util-to-markdown": "^0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/remark/node_modules/trough": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", @@ -15426,11 +15084,11 @@ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -15505,6 +15163,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dependencies": { "glob": "^7.1.3" }, @@ -15535,9 +15194,9 @@ } }, "node_modules/rtl-detect": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz", - "integrity": "sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", + "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==" }, "node_modules/rtlcss": { "version": "4.1.1", @@ -15619,9 +15278,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" }, "node_modules/scheduler": { "version": "0.23.2", @@ -15644,41 +15303,15 @@ "engines": { "node": ">= 12.13.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "node_modules/scriptjs": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz", + "integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg==" }, "node_modules/search-insights": { "version": "2.14.0", @@ -15716,12 +15349,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -15793,9 +15423,9 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dependencies": { "randombytes": "^2.1.0" } @@ -15904,6 +15534,22 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -15969,13 +15615,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -15987,18 +15637,23 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sirv": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", - "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mrmime": "^1.0.0", + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", "totalist": "^3.0.0" }, "engines": { "node": ">= 10" } }, + "node_modules/sister": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sister/-/sister-3.0.2.tgz", + "integrity": "sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA==" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -16082,11 +15737,11 @@ } }, "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, "node_modules/source-map-js": { @@ -16106,6 +15761,14 @@ "source-map": "^0.6.0" } }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -16168,9 +15831,9 @@ } }, "node_modules/std-env": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.0.tgz", - "integrity": "sha512-cNNS+VYsXIs5gI6gJipO4qZ8YYT274JHvNnQ1/R/x8Q8mdP0qj0zoMchRXmBNPqp/0eOEhX+3g7g6Fgb7meLIQ==" + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" }, "node_modules/string_decoder": { "version": "1.3.0", @@ -16180,6 +15843,11 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==" + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -16208,9 +15876,9 @@ } }, "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -16222,9 +15890,9 @@ } }, "node_modules/stringify-entities": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz", - "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" @@ -16309,9 +15977,9 @@ } }, "node_modules/stylis": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", - "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" }, "node_modules/supports-color": { "version": "7.2.0", @@ -16341,9 +16009,9 @@ "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, "node_modules/svgo": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.0.tgz", - "integrity": "sha512-y350OL6eAmhDbWcASdukXoG0MbpdfJQPHwEUAaTW1HBNSO2VErJ35fs7uNLSWjzFDhfua517RcouBzjZoO1JFg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -16354,7 +16022,7 @@ "picocolors": "^1.0.0" }, "bin": { - "svgo": "bin/svgo.js" + "svgo": "bin/svgo" }, "engines": { "node": ">=14.0.0" @@ -16381,9 +16049,9 @@ } }, "node_modules/terser": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", - "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "version": "5.31.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.1.tgz", + "integrity": "sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -16398,15 +16066,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -16430,6 +16098,29 @@ } } }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -16443,10 +16134,15 @@ "node": ">= 10.13.0" } }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -16490,9 +16186,9 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, "node_modules/tiny-invariant": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", - "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, "node_modules/tiny-warning": { "version": "1.0.3", @@ -16544,9 +16240,9 @@ } }, "node_modules/trough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", - "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -16561,9 +16257,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/type-fest": { "version": "2.19.0", @@ -16616,18 +16312,23 @@ } }, "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.7.tgz", + "integrity": "sha512-MmQdgo/XenfZPvVLtKZOq9jQQvzaUAUpcKW8Z43x9B2fOm4S5g//tPtMweZUIP+SoBqrVPEIm+dJeQ9dfO0QdA==", "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -16724,9 +16425,12 @@ } }, "node_modules/unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -16769,10 +16473,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-remove-position/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { "@types/unist": "^3.0.0" }, @@ -16781,7 +16485,7 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-remove-position/node_modules/unist-util-visit": { + "node_modules/unist-util-visit": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", @@ -16795,7 +16499,7 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-remove-position/node_modules/unist-util-visit-parents": { + "node_modules/unist-util-visit-parents": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", @@ -16808,59 +16512,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, - "node_modules/unist-util-visit/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "engines": { "node": ">= 10.0.0" } @@ -16874,9 +16529,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "funding": [ { "type": "opencollective", @@ -16892,8 +16547,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -16981,9 +16636,9 @@ } }, "node_modules/uri-js/node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -17014,6 +16669,34 @@ } } }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/url-loader/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -17034,9 +16717,9 @@ } }, "node_modules/url-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -17061,9 +16744,9 @@ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" }, "node_modules/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", "engines": { "node": ">= 4" } @@ -17179,9 +16862,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -17207,39 +16890,47 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, "node_modules/web-worker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", - "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", + "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==" }, "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "version": "5.92.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.0.tgz", + "integrity": "sha512-Bsw2X39MYIgxouNATyVpCNVWBCuUwDgWtN78g6lSdPJRLaQ/PUVm/oXcaRAyY/sMFoKFQrsPeqvTizWtq7QPCA==", "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.0", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -17259,9 +16950,9 @@ } }, "node_modules/webpack-bundle-analyzer": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz", - "integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==", + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", @@ -17271,7 +16962,6 @@ "escape-string-regexp": "^4.0.0", "gzip-size": "^6.0.0", "html-escaper": "^2.0.2", - "is-plain-object": "^5.0.0", "opener": "^1.5.2", "picocolors": "^1.0.0", "sirv": "^2.0.3", @@ -17293,9 +16983,9 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", @@ -17342,9 +17032,9 @@ } }, "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -17374,7 +17064,7 @@ "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", + "webpack-dev-middleware": "^5.3.4", "ws": "^8.13.0" }, "bin": { @@ -17400,9 +17090,9 @@ } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "engines": { "node": ">=10.0.0" }, @@ -17440,6 +17130,34 @@ "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/webpack/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -17586,9 +17304,9 @@ } }, "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -17666,9 +17384,9 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { "version": "1.10.2", @@ -17679,16 +17397,39 @@ } }, "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/youtube-player": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz", + "integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==", + "dependencies": { + "debug": "^2.6.6", + "load-script": "^1.0.0", + "sister": "^3.0.0" + } + }, + "node_modules/youtube-player/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/youtube-player/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/website/package.json b/website/package.json index bfb810032..7dc23755e 100644 --- a/website/package.json +++ b/website/package.json @@ -20,6 +20,7 @@ "@docusaurus/plugin-google-tag-manager": "^3.4.0", "@docusaurus/preset-classic": "^3.4.0", "@docusaurus/theme-mermaid": "^3.4.0", + "@excalidraw/excalidraw": "^0.17.6", "@fortawesome/fontawesome-svg-core": "^6.5.2", "@fortawesome/free-brands-svg-icons": "^6.5.2", "@fortawesome/free-regular-svg-icons": "^6.5.2", @@ -30,13 +31,20 @@ "clsx": "^2.1.1", "custom-loaders": "file:plugins/custom-loaders", "docusaurus-plugin-image-zoom": "^2.0.0", + "docusaurus-plugin-sentry": "^2.0.0", "html-loader": "^5.0.0", "marked": "^13.0.0", + "node-fetch": "^3.3.2", + "posthog-docusaurus": "^2.0.0", + "posthog-js": "^1.140.1", "prism-react-renderer": "^2.3.1", + "raw-loader": "^4.0.2", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-hubspot-form": "^1.3.7", "react-image-gallery": "^1.3.0", "react-player": "^2.16.0", + "react-social-media-embed": "^2.5.13", "react-table": "^7.8.0", "remark-html": "^16.0.1", "remark-parse": "^11.0.0", diff --git a/website/plugins/custom-loaders/index.js b/website/plugins/custom-loaders/index.js index e448def55..cdf9f4733 100644 --- a/website/plugins/custom-loaders/index.js +++ b/website/plugins/custom-loaders/index.js @@ -4,7 +4,8 @@ // https://github.com/facebook/docusaurus/issues/2097 // https://webpack.js.org/concepts/#loaders -const path = require('html-loader'); +const html = require('html-loader'); +const path = require('path'); module.exports = function (context, options) { return { @@ -29,8 +30,18 @@ module.exports = function (context, options) { }, }, }, + { + test: /\.(yml|yaml|tf)$/, + use: 'raw-loader' + } ], }, + + resolve: { + alias: { + '@examples': path.resolve(__dirname, 'examples'), + } + } }; }, }; diff --git a/website/plugins/fetch-latest-release/index.js b/website/plugins/fetch-latest-release/index.js new file mode 100644 index 000000000..d3bf0f726 --- /dev/null +++ b/website/plugins/fetch-latest-release/index.js @@ -0,0 +1,32 @@ +const fetch = require('node-fetch'); +//require('dotenv').config(); + +async function fetchLatestRelease() { + const response = await fetch(`https://api.github.com/repos/cloudposse/atmos/releases/latest`, { + headers: { +// 'Authorization': `token ${process.env.GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github.v3+json' + } + }); + + if (!response.ok) { + throw new Error(`GitHub API responded with ${response.status}`); + } + + const release = await response.json(); + return release.tag_name; +} + +module.exports = function(context, options) { + return { + name: 'fetch-latest-release', + async loadContent() { + const latestRelease = await fetchLatestRelease(); + return { latestRelease }; + }, + async contentLoaded({ content, actions }) { + const { setGlobalData } = actions; + setGlobalData(content); + } + }; +}; diff --git a/website/plugins/fetch-latest-release/package.json b/website/plugins/fetch-latest-release/package.json new file mode 100644 index 000000000..865e68447 --- /dev/null +++ b/website/plugins/fetch-latest-release/package.json @@ -0,0 +1,5 @@ +{ + "name": "fetch-latest-release", + "version": "0.0.0", + "private": true +} diff --git a/website/sidebars.js b/website/sidebars.js index 330b8413e..0c656faca 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -12,16 +12,214 @@ // @ts-check module.exports = { + tutorials: [ + { + type: 'category', + label: 'Tutorials Index Page', + link: { + type: 'doc', + id: 'tutorials/tutorials' + }, + items: [ + { + type: 'autogenerated', + dirName: 'tutorials', + } + ] + } + ], + community: [ + { + type: 'category', + label: 'Community', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + link: {type: 'doc', id: 'community/community'}, + items: [ 'community/slack', 'community/office-hours' ] + }, + { + type: 'category', + label: 'Contribute', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'contribute', + } + ] + } + ], docs: [ + + { + type: 'category', + label: 'Get Started', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'introduction', + }, + { + type: 'category', + label: 'Quick Start', + collapsible: true, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'quick-start', + }, + ] + }, + ] + }, + + ,/* { - type: 'autogenerated', - dirName: '.', + type: 'html', + value: 'Core Concepts', + className: 'sidebar-title', + },*/ + { + type: 'category', + label: 'Learn Atmos', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'core-concepts', + }, + + { + type: 'category', + label: 'Troubleshoot', + collapsible: true, + collapsed: true, + items: [ + { + type: 'autogenerated', + dirName: 'troubleshoot', + }, + ] + } + ] + }, + { + type: 'category', + label: 'Best Practices', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + link: {type: 'doc', id: 'best-practices/best-practices'}, + items: [ + { + type: 'autogenerated', + dirName: 'best-practices', + }, + { + type: 'category', + label: 'Use Design Patterns', + collapsible: true, + collapsed: true, + link: {type: 'doc', id: 'design-patterns/design-patterns'}, + items: [ + { + type: 'autogenerated', + dirName: 'design-patterns', + }, + ] + } + ] }, + { + type: 'category', + label: 'Cheat Sheets', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'cheatsheets', + }, + ] + } ], cli: [ { - type: 'autogenerated', - dirName: 'cli', + type: 'category', + label: 'Configuration', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'cli', + }, + ] + }, + + { + type: 'category', + label: 'Commands', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + link: {type: 'doc', id: 'cli/commands/commands'}, + items: [ + { + type: 'autogenerated', + dirName: 'cli/commands', + }, + ] + }, + { + type: 'category', + label: 'CI/CD (GitOps)', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'integrations', + } + ] + }, + { + type: 'category', + label: 'Resources', + className: 'sidebar-title', + collapsible: false, + collapsed: false, + items: [ + { + type: 'autogenerated', + dirName: 'reference', + }, + { + type: 'category', + label: 'Glossary', + collapsible: true, + collapsed: true, + link: {type: 'doc', id: 'glossary/glossary'}, + items: [ + { + type: 'autogenerated', + dirName: 'glossary', + }, + ] + } + ] }, ] }; diff --git a/website/src/components/ActionCard/index.css b/website/src/components/ActionCard/index.css new file mode 100644 index 000000000..37074336b --- /dev/null +++ b/website/src/components/ActionCard/index.css @@ -0,0 +1,43 @@ +.action-card { + background-color: #2c2c2c; + color: #cccccc; + padding: 2em; + border: 1px solid #cccccc36; + border-radius: 1.3em; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + margin-top: 4em; +} + +.action-card h2 { + margin-bottom: 10px; +} + +.action-card p { + font-size: 20px; + margin-bottom: 20px; + display: block; +} + +.action-card .button--lg { + padding-top: 0.7em; + padding-bottom: 0.7em; +} + +.action-card a.button.button--lg.button--primary { + margin-left: inherit; + margin-right: 100%; +} + +.action-card p > div a.button.button--lg.button--primary, .action-card div > div a.button.button--lg.button--primary { + margin-right: inherit; +} + +.action-card a.button { + margin-top: 2em; + margin-bottom: 0; +} + +.action-card div a.button { + margin-top: 1em; + margin-bottom: 0; +} diff --git a/website/src/components/ActionCard/index.js b/website/src/components/ActionCard/index.js new file mode 100644 index 000000000..e55136b41 --- /dev/null +++ b/website/src/components/ActionCard/index.js @@ -0,0 +1,37 @@ +import React from 'react' +import Link from '@docusaurus/Link' +import PrimaryCTA from '@site/src/components/PrimaryCTA' +import SecondaryCTA from '@site/src/components/SecondaryCTA' +import './index.css' + +const ActionCard = ({ title = "Ready to learn this topic?", + ctaText, + ctaLink, + primaryCtaText, + primaryCtaLink, + secondaryCtaText, + secondaryCtaLink, + children }) => { + // Determine primary CTA text and link + const primaryText = ctaText || primaryCtaText; + const primaryLink = ctaLink || primaryCtaLink; + + return ( +
+

{title}

+
{children}
+ {primaryLink && ( + + {primaryText || "Read More"} + + )} + {secondaryCtaLink && ( + + {secondaryCtaText || "Read More"} + + )} +
+ ); +}; + +export default ActionCard; diff --git a/website/src/components/Card.tsx b/website/src/components/Card/index.tsx similarity index 100% rename from website/src/components/Card.tsx rename to website/src/components/Card/index.tsx diff --git a/website/src/components/CardGroup/cheatsheet.css b/website/src/components/CardGroup/cheatsheet.css new file mode 100644 index 000000000..b2a85a097 --- /dev/null +++ b/website/src/components/CardGroup/cheatsheet.css @@ -0,0 +1,63 @@ +.cheatsheet { + display: flex; + flex-direction: row; + flex-wrap: wrap; + background: #7d829e0f; + border-radius: 10px; + padding: 0; + margin: 0; + margin-top: 2em; +} + +.cheatsheet .card { + background: var(--ifm-card-background-color); + display: flex; + flex-direction: column; + padding: 0.5em; + width: auto; + margin: 0.5em; + align-self: flex-start; + max-width: 55vw; + overflow: auto; +} + +.cheatsheet .theme-code-block { + margin-bottom: 0.2em; +} + +.cheatsheet .theme-code-block .codeBlockTitle_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Content-styles-module { + padding: 0.1em; + padding-left: 1.5em; + color: #666; + font-family: monospace; +} + +.cheatsheet h2 { + font-size: 1.2em; + margin-bottom: 0.2em; + margin-left: 0.2em; + display: flex; + width: auto; +} + +.cheatsheet > h2 { + flex-basis: 100%; + font-size: 2em; +} + +.cheatsheet .card p { + flex-basis: 100%; + margin-top: 0.2em; + margin-bottom: 0; +} + +.cheatsheet .card .card-body { + padding: 0; + display: flex; + flex-wrap: wrap; +} +.cheatsheet .card-group { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} diff --git a/website/src/components/CardGroup.tsx b/website/src/components/CardGroup/index.tsx similarity index 90% rename from website/src/components/CardGroup.tsx rename to website/src/components/CardGroup/index.tsx index 1d369f990..ec8638662 100644 --- a/website/src/components/CardGroup.tsx +++ b/website/src/components/CardGroup/index.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import './cheatsheet.css'; export default function CardGroup({ title, className, children }) { return ( diff --git a/website/src/components/CollapsibleText/index.css b/website/src/components/CollapsibleText/index.css new file mode 100644 index 000000000..ceb1c5bb9 --- /dev/null +++ b/website/src/components/CollapsibleText/index.css @@ -0,0 +1,57 @@ +.collapsible { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.collapsible button { + display: flex; + align-self: center; + padding: 0.5em; + padding-left: 1em; + padding-right: 1em; + background: #cccccc57; + border-radius: 3px; + border: none; +} + +.collapsible > .text { + position: relative; + max-height: 150px; + overflow: hidden; + transition: max-height 1s ease, filter 1s ease; +} + +.collapsible > .text.short { + max-height: 150px; +} + +.collapsible > .text.medium { + max-height: 300px; +} + +.collapsible > .text.tall { + max-height: 600px; +} + +.collapsible > .text.expanded { + max-height: 1000px; /* A large value to ensure full expansion */ +} + +.collapsible > .text::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 50px; /* Height of the blurred area */ + background: linear-gradient(transparent, rgba(255, 255, 255, 0)); + backdrop-filter: blur(2px); + pointer-events: none; + display: block; + transition: opacity 0.3s ease-in-out; +} + +.collapsible > .text.expanded::after { + opacity: 0; +} diff --git a/website/src/components/CollapsibleText/index.js b/website/src/components/CollapsibleText/index.js new file mode 100644 index 000000000..fb63d621e --- /dev/null +++ b/website/src/components/CollapsibleText/index.js @@ -0,0 +1,23 @@ +import React, { useState } from 'react'; +import './index.css'; + +const CollapsibleText = ({ open = "Read More", close = "Show Less", type="medium", children }) => { + const [isExpanded, setIsExpanded] = useState(false); + + const handleToggle = () => { + setIsExpanded(!isExpanded); + }; + + return ( +
+
+ {children} +
+ +
+ ); +}; + +export default CollapsibleText; diff --git a/website/src/components/Definition/index.css b/website/src/components/Definition/index.css new file mode 100644 index 000000000..91ba5f555 --- /dev/null +++ b/website/src/components/Definition/index.css @@ -0,0 +1,35 @@ +.definition { + margin: 1em 0; + border: 1px solid #cccccc2b; + border-radius: 20px; + padding: 1em; + padding-left: 2em; + padding-right: 2em; + background: #ffffff0d; +} + +.definition summary { + font-weight: bold; + cursor: pointer; + list-style-type: none; + margin-left: 15px; /* Space for the custom marker */ + padding-left: 10px; + position: relative; +} + +/* Custom marker */ +.definition summary::before { + content: '▶'; /* Custom marker character */ + position: absolute; + left: -15px; /* Adjust the position of the marker */ + font-size: 1.2em; /* Marker size */ + color: rgb(71, 71, 72); +} + +.definition div { + margin-top: 0.5em; +} + +details[open].definition > summary::before { + content: '▼'; /* Change marker character when open */ +} diff --git a/website/src/components/Definition/index.js b/website/src/components/Definition/index.js new file mode 100644 index 000000000..15c071e3b --- /dev/null +++ b/website/src/components/Definition/index.js @@ -0,0 +1,50 @@ +import React, { useState, useEffect } from 'react'; +import { MDXProvider } from '@mdx-js/react'; +import './index.css'; + +const Definition = ({ term, children }) => { + const [Content, setContent] = useState(null); + const [error, setError] = useState(false); + + useEffect(() => { + const loadContent = async () => { + try { + console.log(`Trying to load ${term}.mdx`); + const mdxContent = await import(`@site/docs/glossary/${term}.mdx`); + setContent(() => mdxContent.default); + console.log(`${term}.mdx loaded successfully`); + } catch (err1) { + console.log(`Failed to load ${term}.mdx, trying ${term}.md`); + try { + const mdContent = await import(`@site/docs/glossary/${term}.md`); + setContent(() => mdContent.default); + console.log(`${term}.md loaded successfully`); + } catch (err2) { + console.error(`Failed to load both ${term}.mdx and ${term}.md`); + setError(true); + } + } + }; + + loadContent(); + }, [term]); + + return ( +
+ {children || `What is a ${term}?`} +
+ {error ? ( +

Definition not found.

+ ) : Content ? ( + + + + ) : ( +

Loading...

+ )} +
+
+ ); +}; + +export default Definition; diff --git a/website/src/components/EmbedFile/index.js b/website/src/components/EmbedFile/index.js new file mode 100644 index 000000000..a02d45793 --- /dev/null +++ b/website/src/components/EmbedFile/index.js @@ -0,0 +1,47 @@ +// src/components/EmbedFile.js +import React, { useState, useEffect } from 'react'; +import File from '@site/src/components/File' +import CodeBlock from '@theme/CodeBlock'; + +// Function to guess the type based on the filePath +const guessLanguageFromFilePath = (filePath) => { + if (/\.ya?ml$/i.test(filePath)) { + return 'yaml'; + } + if (/\.json$/i.test(filePath)) { + return 'json'; + } + if (/\.tf$/i.test(filePath)) { + return 'hcl'; + } + // Add more patterns as needed + return 'plain'; // Default to 'plain' + }; + +const EmbedFile = ({ filePath, language }) => { + const [content, setContent] = useState(''); + + const guessedLanguage = language || guessLanguageFromFilePath(filePath); + + useEffect(() => { + const loadFile = async () => { + try { + // Dynamically import the file content using raw-loader + const fileContent = await import(`!!raw-loader!@site/${filePath}`); + setContent(fileContent.default); + } catch (error) { + setContent(`Error loading file: ${error.message}`); + } + }; + + loadFile(); + }, [filePath]); + + return ( + + {content} + + ); +}; + +export default EmbedFile; diff --git a/website/src/components/File/index.css b/website/src/components/File/index.css new file mode 100644 index 000000000..46de4197d --- /dev/null +++ b/website/src/components/File/index.css @@ -0,0 +1,102 @@ +.file { + margin-bottom: 3em; + margin-top: 3em; +} + +.file pre>code>span.token-line::before { + content: '1'; + display: inline-block; + padding: 0 .5em; + margin-right: .5em; + color: #888; +} + +.file pre code span.token-line { + line-height: 1em; + counter-increment: line; +} + +.file pre code span.token-line::before { + content: counter(line); + display: inline-block; + padding: 0 .5em; + margin-right: .5em; + color: #888; + text-align: right; + min-width: 20px; + border-right: 1px solid #cccccc47; +} + +.file pre { + margin-bottom: inherit; +} + +.file div.tab { + position: relative; + top: 2px; + z-index: 2; + display: inline-block; + padding: 0.5em; + transform: perspective(0.6em) rotateX(1deg); + transform-origin: bottom; +} + +.file div.tab > h1 { + font-size: 0.98em; + line-height: 1.2em; + margin-top: 5px; + margin-bottom: 0; + margin-left: 0.5em; + margin-right: 0.5em; + font-weight: 500; + font-family: var(--ifm-font-family-monospace); + color: #ccc; + transform-style: preserve-3d; + transform: perspective(0.6em) rotateX(-1deg); +} +.file div.tab > h1 svg.svg-inline--fa { + margin-right: 0.5em; +} + +html[data-theme='dark'] .file div.tab > h1 { + color: var(--ifm-heading-color); +} + +.file div.tab::before { + content: ''; /* To generate the box */ + position: absolute; + top: 0; right: 0; bottom: 0; left: 0; + z-index: -1; + background: rgb(16, 36, 69); + transform-origin: bottom; + border: 1px solid #cccccc38; + border-bottom: 1px solid rgb(16, 36, 69); + border-radius: 10px 10px 0 0; +} + +.file div.viewport { + border: 1px solid #cccccc38; + border-radius: 6px; + border-top-left-radius: 4px; +} + +.file .language-yaml.theme-code-block { + margin-bottom: 0; +} + +.file .language-hcl.theme-code-block { + margin-bottom: 0; +} + +.file .language-json.theme-code-block { + margin-bottom: 0; +} + +.file .language-console.theme-code-block { + margin-bottom: 0; +} + +.file div.viewport { + padding: 5px; + background: rgb(16, 36, 69); +} diff --git a/website/src/components/File.tsx b/website/src/components/File/index.tsx similarity index 94% rename from website/src/components/File.tsx rename to website/src/components/File/index.tsx index b727f6ab4..5398d4883 100644 --- a/website/src/components/File.tsx +++ b/website/src/components/File/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; - +import './index.css'; // Import the original mapper import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; // Import the FontAwesomeIcon component. @@ -28,16 +28,16 @@ const iconMap = { // Add more mappings as needed }; - // Function to guess the type based on the title +// Function to guess the type based on the title const guessTypeFromTitle = (title) => { if (/\.tf\.json$/i.test(title)) { return 'code'; } - if (/.*stack.*\.ya?ml$/i.test(title)) { - return 'stack'; - } if (/atmos\.ya?ml$/i.test(title)) { return 'config'; + } + if (/.*stack.*\.ya?ml$/i.test(title)) { + return 'stack'; } if (/\.ya?ml$/i.test(title)) { return 'yaml'; @@ -64,7 +64,7 @@ export default function File({ title, className, type, icon, size = '1x', childr return (
-
+

{title}

{children}
diff --git a/website/src/components/glossary/Glossary.tsx b/website/src/components/Glossary/Glossary.tsx similarity index 100% rename from website/src/components/glossary/Glossary.tsx rename to website/src/components/Glossary/Glossary.tsx diff --git a/website/src/components/Intro/index.css b/website/src/components/Intro/index.css new file mode 100644 index 000000000..85336356d --- /dev/null +++ b/website/src/components/Intro/index.css @@ -0,0 +1,6 @@ +.markdown .intro { + font-size: 20px; + border-bottom: 1px solid rgb(102, 102, 102); + margin-bottom: 2em; + line-height: 1.625; +} diff --git a/website/src/components/Intro/index.js b/website/src/components/Intro/index.js new file mode 100644 index 000000000..038985528 --- /dev/null +++ b/website/src/components/Intro/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import './index.css'; + +const Intro = ({ children }) => { + return ( +
{children}
+ ); +}; + +export default Intro; diff --git a/website/src/components/KeyPoints/index.css b/website/src/components/KeyPoints/index.css new file mode 100644 index 000000000..126a2cc9e --- /dev/null +++ b/website/src/components/KeyPoints/index.css @@ -0,0 +1,29 @@ +.key-points { + background-color: transparent; /* Light background color for the container */ + border: 1px solid #ddd; /* Light border around the container */ + border-radius: 20px; /* Rounded corners */ + padding: 20px; /* Padding inside the container */ + margin-top: 3em; + margin-bottom: 3em; + +} + +[data-theme='dark'] .key-points { + color: #67ffded2; + border: 1px solid #67ffded2; +} + +.key-points h2 { + margin-top: 0; /* Remove top margin */ + font-size: 1.5em; /* Adjust font size */ +} + +.key-points ul { + padding-left: 20px; /* Indent the list */ + margin: 10px 0; /* Margin for the list */ +} + +.key-points li { + margin-bottom: 10px; /* Space between list items */ + font-size: 1.1em; /* Slightly larger font size for list items */ +} diff --git a/website/src/components/KeyPoints/index.js b/website/src/components/KeyPoints/index.js new file mode 100644 index 000000000..5c7d8859d --- /dev/null +++ b/website/src/components/KeyPoints/index.js @@ -0,0 +1,13 @@ +import React from 'react'; +import './index.css'; + +const KeyPoints = ({ title = "You will learn", children }) => { + return ( +
+

{title}

+
{children}
+
+ ); +}; + +export default KeyPoints; diff --git a/website/src/components/LatestRelease/index.js b/website/src/components/LatestRelease/index.js new file mode 100644 index 000000000..5c70f49aa --- /dev/null +++ b/website/src/components/LatestRelease/index.js @@ -0,0 +1,12 @@ +import React from 'react'; +import useGlobalData from '@docusaurus/useGlobalData'; + +const LatestRelease = () => { + const globalData = useGlobalData(); + const latestRelease = globalData['fetch-latest-release']?.default?.latestRelease || 'v0.0.0'; + return ( + {latestRelease} + ); +}; + +export default LatestRelease; diff --git a/website/src/components/Note/index.css b/website/src/components/Note/index.css new file mode 100644 index 000000000..877d11a10 --- /dev/null +++ b/website/src/components/Note/index.css @@ -0,0 +1,19 @@ +.note { + margin-top: 1em; + margin-bottom: 1em; + display: flex; +} + +.note > div:last-child { + margin-bottom: 0; +} + +.note > strong { + color: #177bb6; + margin-right: 0.5em; + text-wrap: nowrap; +} + +[data-theme='dark'] .note > div { + filter: opacity(0.5); +} diff --git a/website/src/components/Note/index.tsx b/website/src/components/Note/index.tsx new file mode 100644 index 000000000..c2e4a879c --- /dev/null +++ b/website/src/components/Note/index.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import './index.css'; + +// Display a more subtle note than an admonition, with a title and content +const Note = ({ title = "NOTE", children }) => { + return ( +
+ {title}: +
{children}
+
+ ); +}; + +export default Note; diff --git a/website/src/components/PillBox/index.css b/website/src/components/PillBox/index.css new file mode 100644 index 000000000..ca9a391eb --- /dev/null +++ b/website/src/components/PillBox/index.css @@ -0,0 +1,18 @@ +.pill-box { + display: inline-block; + padding: 0.2em 1em; + margin-bottom: 3em; + border-radius: 15px; + background-color: rgb(0 255 0 / 15%); + color: #000; + font-size: 1em; + text-align: center; + text-transform: uppercase; + font-weight: 600; + font-size: 0.8em; +} + +[data-theme='dark'] .pill-box { + background-color: rgb(0 255 0 / 31%); + color: rgb(255 255 255 / 89%); +} diff --git a/website/src/components/PillBox/index.tsx b/website/src/components/PillBox/index.tsx new file mode 100644 index 000000000..5fb00d56c --- /dev/null +++ b/website/src/components/PillBox/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import './index.css'; + +const PillBox = ({ children }) => { + return ( +
+ {children} +
+ ); +}; + +export default PillBox; diff --git a/website/src/components/PrimaryCTA/index.css b/website/src/components/PrimaryCTA/index.css new file mode 100644 index 000000000..e69de29bb diff --git a/website/src/components/PrimaryCTA/index.js b/website/src/components/PrimaryCTA/index.js new file mode 100644 index 000000000..c1eb7d621 --- /dev/null +++ b/website/src/components/PrimaryCTA/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import './index.css'; + +const PrimaryCTA = ({ to, children }) => { + return ( + {children} + ) +}; + +export default PrimaryCTA; diff --git a/website/src/components/Screengrab.tsx b/website/src/components/Screengrab/index.tsx similarity index 94% rename from website/src/components/Screengrab.tsx rename to website/src/components/Screengrab/index.tsx index 488e43785..a3b04bfa0 100644 --- a/website/src/components/Screengrab.tsx +++ b/website/src/components/Screengrab/index.tsx @@ -5,7 +5,7 @@ export default function Screengrab({ title, command, className, slug, children } const [html, setHtml] = useState(null); useEffect(() => { - import(`@site/src/components/screengrabs/${slug}.html`) + import(`@site/src/components/Screengrabs/${slug}.html`) .then(module => { setHtml(module.default); }); diff --git a/website/src/components/screengrabs/atmos--help.html b/website/src/components/Screengrabs/atmos--help.html similarity index 100% rename from website/src/components/screengrabs/atmos--help.html rename to website/src/components/Screengrabs/atmos--help.html diff --git a/website/src/components/screengrabs/atmos-atlantis--help.html b/website/src/components/Screengrabs/atmos-atlantis--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-atlantis--help.html rename to website/src/components/Screengrabs/atmos-atlantis--help.html diff --git a/website/src/components/screengrabs/atmos-atlantis-generate--help.html b/website/src/components/Screengrabs/atmos-atlantis-generate--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-atlantis-generate--help.html rename to website/src/components/Screengrabs/atmos-atlantis-generate--help.html diff --git a/website/src/components/screengrabs/atmos-atlantis-generate-repo-config--help.html b/website/src/components/Screengrabs/atmos-atlantis-generate-repo-config--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-atlantis-generate-repo-config--help.html rename to website/src/components/Screengrabs/atmos-atlantis-generate-repo-config--help.html diff --git a/website/src/components/screengrabs/atmos-aws--help.html b/website/src/components/Screengrabs/atmos-aws--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-aws--help.html rename to website/src/components/Screengrabs/atmos-aws--help.html diff --git a/website/src/components/screengrabs/atmos-aws-eks--help.html b/website/src/components/Screengrabs/atmos-aws-eks--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-aws-eks--help.html rename to website/src/components/Screengrabs/atmos-aws-eks--help.html diff --git a/website/src/components/screengrabs/atmos-aws-eks-update-kubeconfig--help.html b/website/src/components/Screengrabs/atmos-aws-eks-update-kubeconfig--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-aws-eks-update-kubeconfig--help.html rename to website/src/components/Screengrabs/atmos-aws-eks-update-kubeconfig--help.html diff --git a/website/src/components/screengrabs/atmos-completion--help.html b/website/src/components/Screengrabs/atmos-completion--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-completion--help.html rename to website/src/components/Screengrabs/atmos-completion--help.html diff --git a/website/src/components/screengrabs/atmos-completion-bash.html b/website/src/components/Screengrabs/atmos-completion-bash.html similarity index 100% rename from website/src/components/screengrabs/atmos-completion-bash.html rename to website/src/components/Screengrabs/atmos-completion-bash.html diff --git a/website/src/components/screengrabs/atmos-completion-fish.html b/website/src/components/Screengrabs/atmos-completion-fish.html similarity index 100% rename from website/src/components/screengrabs/atmos-completion-fish.html rename to website/src/components/Screengrabs/atmos-completion-fish.html diff --git a/website/src/components/screengrabs/atmos-completion-powershell.html b/website/src/components/Screengrabs/atmos-completion-powershell.html similarity index 100% rename from website/src/components/screengrabs/atmos-completion-powershell.html rename to website/src/components/Screengrabs/atmos-completion-powershell.html diff --git a/website/src/components/screengrabs/atmos-completion-zsh.html b/website/src/components/Screengrabs/atmos-completion-zsh.html similarity index 100% rename from website/src/components/screengrabs/atmos-completion-zsh.html rename to website/src/components/Screengrabs/atmos-completion-zsh.html diff --git a/website/src/components/screengrabs/atmos-describe--help.html b/website/src/components/Screengrabs/atmos-describe--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-describe--help.html rename to website/src/components/Screengrabs/atmos-describe--help.html diff --git a/website/src/components/screengrabs/atmos-describe-affected--help.html b/website/src/components/Screengrabs/atmos-describe-affected--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-describe-affected--help.html rename to website/src/components/Screengrabs/atmos-describe-affected--help.html diff --git a/website/src/components/screengrabs/atmos-describe-component--help.html b/website/src/components/Screengrabs/atmos-describe-component--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-describe-component--help.html rename to website/src/components/Screengrabs/atmos-describe-component--help.html diff --git a/website/src/components/screengrabs/atmos-describe-config--help.html b/website/src/components/Screengrabs/atmos-describe-config--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-describe-config--help.html rename to website/src/components/Screengrabs/atmos-describe-config--help.html diff --git a/website/src/components/screengrabs/atmos-describe-dependents--help.html b/website/src/components/Screengrabs/atmos-describe-dependents--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-describe-dependents--help.html rename to website/src/components/Screengrabs/atmos-describe-dependents--help.html diff --git a/website/src/components/screengrabs/atmos-describe-stacks--help.html b/website/src/components/Screengrabs/atmos-describe-stacks--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-describe-stacks--help.html rename to website/src/components/Screengrabs/atmos-describe-stacks--help.html diff --git a/website/src/components/screengrabs/atmos-describe-workflows--help.html b/website/src/components/Screengrabs/atmos-describe-workflows--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-describe-workflows--help.html rename to website/src/components/Screengrabs/atmos-describe-workflows--help.html diff --git a/website/src/components/screengrabs/atmos-docs--help.html b/website/src/components/Screengrabs/atmos-docs--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-docs--help.html rename to website/src/components/Screengrabs/atmos-docs--help.html diff --git a/website/src/components/screengrabs/atmos-helmfile--help.html b/website/src/components/Screengrabs/atmos-helmfile--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-helmfile--help.html rename to website/src/components/Screengrabs/atmos-helmfile--help.html diff --git a/website/src/components/screengrabs/atmos-helmfile-generate--help.html b/website/src/components/Screengrabs/atmos-helmfile-generate--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-helmfile-generate--help.html rename to website/src/components/Screengrabs/atmos-helmfile-generate--help.html diff --git a/website/src/components/screengrabs/atmos-helmfile-generate-varfile--help.html b/website/src/components/Screengrabs/atmos-helmfile-generate-varfile--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-helmfile-generate-varfile--help.html rename to website/src/components/Screengrabs/atmos-helmfile-generate-varfile--help.html diff --git a/website/src/components/screengrabs/atmos-terraform--help.html b/website/src/components/Screengrabs/atmos-terraform--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform--help.html rename to website/src/components/Screengrabs/atmos-terraform--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-clean--help.html b/website/src/components/Screengrabs/atmos-terraform-clean--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-clean--help.html rename to website/src/components/Screengrabs/atmos-terraform-clean--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-deploy--help.html b/website/src/components/Screengrabs/atmos-terraform-deploy--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-deploy--help.html rename to website/src/components/Screengrabs/atmos-terraform-deploy--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-generate--help.html b/website/src/components/Screengrabs/atmos-terraform-generate--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-generate--help.html rename to website/src/components/Screengrabs/atmos-terraform-generate--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-generate-backend--help.html b/website/src/components/Screengrabs/atmos-terraform-generate-backend--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-generate-backend--help.html rename to website/src/components/Screengrabs/atmos-terraform-generate-backend--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-generate-backends--help.html b/website/src/components/Screengrabs/atmos-terraform-generate-backends--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-generate-backends--help.html rename to website/src/components/Screengrabs/atmos-terraform-generate-backends--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-generate-varfile--help.html b/website/src/components/Screengrabs/atmos-terraform-generate-varfile--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-generate-varfile--help.html rename to website/src/components/Screengrabs/atmos-terraform-generate-varfile--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-generate-varfiles--help.html b/website/src/components/Screengrabs/atmos-terraform-generate-varfiles--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-generate-varfiles--help.html rename to website/src/components/Screengrabs/atmos-terraform-generate-varfiles--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-shell--help.html b/website/src/components/Screengrabs/atmos-terraform-shell--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-shell--help.html rename to website/src/components/Screengrabs/atmos-terraform-shell--help.html diff --git a/website/src/components/screengrabs/atmos-terraform-workspace--help.html b/website/src/components/Screengrabs/atmos-terraform-workspace--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-terraform-workspace--help.html rename to website/src/components/Screengrabs/atmos-terraform-workspace--help.html diff --git a/website/src/components/screengrabs/atmos-validate--help.html b/website/src/components/Screengrabs/atmos-validate--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-validate--help.html rename to website/src/components/Screengrabs/atmos-validate--help.html diff --git a/website/src/components/screengrabs/atmos-validate-component--help.html b/website/src/components/Screengrabs/atmos-validate-component--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-validate-component--help.html rename to website/src/components/Screengrabs/atmos-validate-component--help.html diff --git a/website/src/components/screengrabs/atmos-validate-stacks--help.html b/website/src/components/Screengrabs/atmos-validate-stacks--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-validate-stacks--help.html rename to website/src/components/Screengrabs/atmos-validate-stacks--help.html diff --git a/website/src/components/screengrabs/atmos-vendor--help.html b/website/src/components/Screengrabs/atmos-vendor--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-vendor--help.html rename to website/src/components/Screengrabs/atmos-vendor--help.html diff --git a/website/src/components/screengrabs/atmos-vendor-pull--help.html b/website/src/components/Screengrabs/atmos-vendor-pull--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-vendor-pull--help.html rename to website/src/components/Screengrabs/atmos-vendor-pull--help.html diff --git a/website/src/components/screengrabs/atmos-version.html b/website/src/components/Screengrabs/atmos-version.html similarity index 99% rename from website/src/components/screengrabs/atmos-version.html rename to website/src/components/Screengrabs/atmos-version.html index c7007cdfe..27592995d 100644 --- a/website/src/components/screengrabs/atmos-version.html +++ b/website/src/components/Screengrabs/atmos-version.html @@ -17,5 +17,5 @@ https://github.com/cloudposse/atmos/releases Install Atmos: -https://atmos.tools/quick-start/install-atmos +https://atmos.tools/install diff --git a/website/src/components/screengrabs/atmos-workflow--help.html b/website/src/components/Screengrabs/atmos-workflow--help.html similarity index 100% rename from website/src/components/screengrabs/atmos-workflow--help.html rename to website/src/components/Screengrabs/atmos-workflow--help.html diff --git a/website/src/components/screengrabs/demo-stacks/define-your-stacks.html b/website/src/components/Screengrabs/demo-stacks/define-your-stacks.html similarity index 100% rename from website/src/components/screengrabs/demo-stacks/define-your-stacks.html rename to website/src/components/Screengrabs/demo-stacks/define-your-stacks.html diff --git a/website/src/components/screengrabs/demo-stacks/deploy-dev.ansi b/website/src/components/Screengrabs/demo-stacks/deploy-dev.ansi similarity index 100% rename from website/src/components/screengrabs/demo-stacks/deploy-dev.ansi rename to website/src/components/Screengrabs/demo-stacks/deploy-dev.ansi diff --git a/website/src/components/screengrabs/demo-stacks/deploy-dev.html b/website/src/components/Screengrabs/demo-stacks/deploy-dev.html similarity index 100% rename from website/src/components/screengrabs/demo-stacks/deploy-dev.html rename to website/src/components/Screengrabs/demo-stacks/deploy-dev.html diff --git a/website/src/components/screengrabs/demo-stacks/deploy-prod.html b/website/src/components/Screengrabs/demo-stacks/deploy-prod.html similarity index 100% rename from website/src/components/screengrabs/demo-stacks/deploy-prod.html rename to website/src/components/Screengrabs/demo-stacks/deploy-prod.html diff --git a/website/src/components/screengrabs/demo-stacks/deploy-staging.html b/website/src/components/Screengrabs/demo-stacks/deploy-staging.html similarity index 100% rename from website/src/components/screengrabs/demo-stacks/deploy-staging.html rename to website/src/components/Screengrabs/demo-stacks/deploy-staging.html diff --git a/website/src/components/screengrabs/demo-stacks/deploy.html b/website/src/components/Screengrabs/demo-stacks/deploy.html similarity index 100% rename from website/src/components/screengrabs/demo-stacks/deploy.html rename to website/src/components/Screengrabs/demo-stacks/deploy.html diff --git a/website/src/components/screengrabs/demo-stacks/start-your-project.html b/website/src/components/Screengrabs/demo-stacks/start-your-project.html similarity index 100% rename from website/src/components/screengrabs/demo-stacks/start-your-project.html rename to website/src/components/Screengrabs/demo-stacks/start-your-project.html diff --git a/website/src/components/screengrabs/demo-stacks/write-your-components.html b/website/src/components/Screengrabs/demo-stacks/write-your-components.html similarity index 100% rename from website/src/components/screengrabs/demo-stacks/write-your-components.html rename to website/src/components/Screengrabs/demo-stacks/write-your-components.html diff --git a/website/src/components/screengrabs/tree-CAF--gitignore.html b/website/src/components/Screengrabs/tree-CAF--gitignore.html similarity index 100% rename from website/src/components/screengrabs/tree-CAF--gitignore.html rename to website/src/components/Screengrabs/tree-CAF--gitignore.html diff --git a/website/src/components/screengrabs/tree.html b/website/src/components/Screengrabs/tree.html similarity index 100% rename from website/src/components/screengrabs/tree.html rename to website/src/components/Screengrabs/tree.html diff --git a/website/src/components/SecondaryCTA/index.css b/website/src/components/SecondaryCTA/index.css new file mode 100644 index 000000000..e69de29bb diff --git a/website/src/components/SecondaryCTA/index.js b/website/src/components/SecondaryCTA/index.js new file mode 100644 index 000000000..53e746913 --- /dev/null +++ b/website/src/components/SecondaryCTA/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import './index.css'; + +const SecondaryCTA = ({ to, children }) => { + return ( + {children} + ) +}; + +export default SecondaryCTA; diff --git a/website/src/components/slides/slides.js b/website/src/components/Slides/index.js similarity index 91% rename from website/src/components/slides/slides.js rename to website/src/components/Slides/index.js index ca392f7ed..b046c9f9c 100644 --- a/website/src/components/slides/slides.js +++ b/website/src/components/Slides/index.js @@ -1,7 +1,7 @@ import React from "react"; -import styles from "@site/src/components/slides/slides.module.css"; import ImageGallery from "react-image-gallery"; import "react-image-gallery/styles/css/image-gallery.css" +import Styles from "./index.module.css"; // https://github.com/xiaolin/react-image-gallery // https://stackoverflow.com/questions/3746725/how-to-create-an-array-containing-1-n @@ -22,7 +22,7 @@ const images = Array.from({length: 27}, (_, i) => { export default function Slides() { return (
-
+
i, html[data-theme='dark'] .step h2 > i { + font-style: normal; + color: #000; +} + +html[data-theme='dark'] .step h3 > i, html[data-theme='dark'] .step h2 > i { + color: #fff; +} + +.docusaurus-mermaid-container { + display: flex; + justify-content: center; +} diff --git a/website/src/components/Step/index.js b/website/src/components/Step/index.js new file mode 100644 index 000000000..ae24a00bf --- /dev/null +++ b/website/src/components/Step/index.js @@ -0,0 +1,31 @@ +// src/components/Step.js +import React, { useEffect, useState, createContext, useContext } from 'react'; +import './index.css'; + +let stepCounter = 0; + +export const StepContext = createContext(0); + +export const resetStepCounter = () => { + stepCounter = 0; +}; + +const Step = ({ title, children }) => { + const [stepNumber, setStepNumber] = useState(stepCounter); + + useEffect(() => { + stepCounter += 1; + setStepNumber(stepCounter); + }, []); + + return ( + +
+ {title &&

{`Step ${stepNumber}: ${title}`}

} +
{children}
+
+
+ ); +}; + +export default Step; diff --git a/website/src/components/StepNumber/index.js b/website/src/components/StepNumber/index.js new file mode 100644 index 000000000..b917ab11c --- /dev/null +++ b/website/src/components/StepNumber/index.js @@ -0,0 +1,9 @@ +import React, { useContext } from 'react'; +import { StepContext } from '@site/src/components/Step'; + +const StepNumber = () => { + const stepNumber = useContext(StepContext); + return ({`Step ${stepNumber}:`}); +}; + +export default StepNumber; diff --git a/website/src/components/Terminal.tsx b/website/src/components/Terminal.tsx deleted file mode 100644 index f88724233..000000000 --- a/website/src/components/Terminal.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; - -export default function Terminal({ title, className, children }) { - return ( -
-
-
-
-
-
-
-
-

{title}

-
-
{children}
-
-
- ); -}; - diff --git a/website/src/components/Terminal/index.css b/website/src/components/Terminal/index.css new file mode 100644 index 000000000..6ec8e6b82 --- /dev/null +++ b/website/src/components/Terminal/index.css @@ -0,0 +1,155 @@ +/* Terminal Styling */ +.terminal { + min-width: 100%; + color: #ccc; + /*background: #171717; */ + background: #070e12; + margin-top: 10px; + margin-bottom: 1em; + line-height: 0.8em; + border-radius: 10px; + padding: 0.5em; + border: 1px solid #cccccc36; + box-shadow: 0 0 20px 3px rgb(8 115 115 / 29%); +} + +.markdown .terminal { + margin-top: 3em; + margin-bottom: 3em; +} + +.terminal span.token.plain { + /* Add little dots to the terminal that represent spaces */ + background-image: radial-gradient(circle, #ffffff38 1px, transparent 1px); + background-size: 9px 20px; +} + +.terminal h1 { + text-align: center; + font-size: 1em; + font-family: monospace; + flex-grow: 1; + + align-items: center; + width: 100%; + min-width: 100%; + position: relative; + left: -60px; + color: #fff; + font-weight: bold; + padding-right: 80px; + padding-left: 80px; + + white-space: nowrap; + overflow: hidden; + max-width: 60%; + text-overflow: ellipsis; +} + +/* The container for the dots, representing a window control bar */ +.terminal .window-bar { + display: flex; + justify-content: space-between; +} + +.terminal .language-shell.theme-code-block { + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal pre.prism-code.language-console { + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal .language-yaml.theme-code-block { + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal .language-json.theme-code-block { + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal .language-console.theme-code-block +{ + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal pre.prism-code.language-json { + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal pre.prism-code.language-yaml { + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal pre.prism-code.language-shell { + --prism-background-color: transparent !important; + background-color: transparent !important; + background: transparent !important; +} + +.terminal .viewport { + max-height: 450px; + overflow: auto; +} +.terminal .window-controls { + display: flex; + align-items: flex-start; + justify-content: space-between; + width: 60px; /* Adjust the width as needed */ +} + +/* General styles for each dot */ +.terminal .control-dot { + width: 12px; /* Dot size */ + height: 12px; /* Dot size */ + border-radius: 50%; /* Makes the dot circular */ + margin: 0 4px; /* Spacing between dots */ +} + +/* Specific color for each dot */ +.terminal .close-dot { + background-color: #ff605c; /* Red color */ +} + +.terminal .minimize-dot { + background-color: #ffbd44; /* Yellow color */ +} + +.terminal .maximize-dot { + background-color: #00ca56; /* Green color */ +} + +.terminal pre.screengrab { + line-height: 0.95em; + letter-spacing: -0.009em; + padding: 0.3em; + background: transparent; +} + +.terminal .command .prompt { + color: green; + padding-left: 0; + font-weight: bold; + font-size: 1.2em; + position: relative; + top: 2px; +} + +.terminal .command { + padding-left: 1em; + display: flex; +} diff --git a/website/src/components/Terminal/index.tsx b/website/src/components/Terminal/index.tsx new file mode 100644 index 000000000..ec9fe30ae --- /dev/null +++ b/website/src/components/Terminal/index.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import Typewriter from '@site/src/components/Typewriter'; +import './index.css'; + +export default function Terminal({ title, command, className, children }) { + return ( +
+
+
+
+
+
+
+
+

{title}

+
+
{command &&
>{command}
}
{children}
+
+
+ ); +}; + diff --git a/website/src/components/Typewriter/index.css b/website/src/components/Typewriter/index.css new file mode 100644 index 000000000..8320652d5 --- /dev/null +++ b/website/src/components/Typewriter/index.css @@ -0,0 +1,37 @@ +.typewriter { + display: flex; + flex: 0 1 auto; +} + +.typewriter > tt { + display: flex; + width: auto; + font-size: 1.15em; + line-height: 1.2em; + margin: 0.5em; + border-right: 6px solid rgba(2, 181, 9,1); + flex-basis: content; + white-space: nowrap; + overflow: hidden; + transform: translateY(-50%); +} + +/* Animation */ +.animate .typing { + animation: typing 3s steps(18) 1s 1 normal both, + blinkTextCursor 500ms steps(44) 5 normal; +} + +.hiddenCursor .typewriter > tt { + border-right: none; +} + +@keyframes typing { + from{max-width: 0; } + to{max-width: 100vw; padding-right: 0.3em;} +} + +@keyframes blinkTextCursor{ + from{border-right-color: rgba(2, 181, 9,.75);} + to{border-right-color: transparent;} +} diff --git a/website/src/components/Typewriter.tsx b/website/src/components/Typewriter/index.tsx similarity index 67% rename from website/src/components/Typewriter.tsx rename to website/src/components/Typewriter/index.tsx index ac4fd8ec2..012194453 100644 --- a/website/src/components/Typewriter.tsx +++ b/website/src/components/Typewriter/index.tsx @@ -1,23 +1,29 @@ import React, { useEffect, useRef } from 'react'; +import './index.css'; export default function Typewriter({ className, children }) { const ref = useRef(); useEffect(() => { + let timer; const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate'); + timer = setTimeout(() => { + entry.target.classList.add('hiddenCursor'); + }, 3000); // Adjust the timeout duration as needed } else { - entry.target.classList.remove('animate'); + entry.target.classList.remove('animate', 'hiddenCursor'); + clearTimeout(timer); } }); }); - + if (ref.current) { observer.observe(ref.current); } - + return () => { if (ref.current) { observer.unobserve(ref.current); @@ -28,7 +34,7 @@ export default function Typewriter({ className, children }) { return (
- {children} + {children}
); diff --git a/website/src/css/custom.css b/website/src/css/custom.css index 9b173d35e..78497db7d 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -14,6 +14,17 @@ html[data-theme='dark'] nav.navbar { background: rgba(3, 7, 17, .75); } +a.navbar__item.navbar__link.latest-release-link { + color: #cccccc6e; + font-size: 0.8em; + padding: 0; + margin-right: 1em; + border-radius: 6px; + padding-left: 1em; + padding-right: 1em; + background: #cccccc1c; +} + .navbar__title { font-size: 2em; } @@ -22,6 +33,7 @@ html[data-theme='dark'] nav.navbar { { position: relative; bottom: 2px; + margin-right: 0; } div.atmos__effect, html[data-theme='dark'] div.navbar__logo { @@ -81,7 +93,10 @@ body { background-repeat: no-repeat; background-size: 15em; background-attachment: fixed; - font-family: "Lato", sans-serif; + font-family: 'Optimistic Text', -apple-system, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + font-size: 17px; + line-height: 30px; + } .language-console pre > code, .language-text pre > code { @@ -95,12 +110,41 @@ nav.navbar { } */ -/* Uncomment to shift carets to the left +/* Uncomment to shift carets to the left .menu__link { order: 1; } */ +li.sidebar-title > div > a.menu__link { + text-transform: uppercase; + color: #b1b1b1; +} + +li.sidebar-title { + border-top: 1px solid #6666663b; + padding-top: 1.2em; + margin-top: 1.2em; +} + +li.sidebar-title:first-child { + border-top: none; + margin-top: inherit; +} + +li.sidebar-title.menu__list-item:not(:first-child) { + margin-top: 1.2em !important; +} + +li.sidebar-title > ul:first .menu__list .menu__list { + padding-left: 0; +} + +.sidebar-title > ul.menu__list { + margin-left: 0; + padding-left: 0; +} + .menu__caret:before { background: var(--ifm-menu-link-sublist-icon) 50% / 2rem 1.5rem; } @@ -110,7 +154,7 @@ li > ul.menu__list { } html[data-theme='dark'] article ul strong, html[data-theme='dark'] article ol strong { - color: #654dfe; + color: #9589e3; } article ul strong, article ol strong { @@ -121,10 +165,47 @@ article .theme-admonition-danger ul li strong, article .theme-admonition-danger color: #ff8a8a } +/* disable left border on adminitions in dark mode */ +.theme-admonition { + border-left: none; + padding: 2em; + border-radius: 1.3em; + margin-top: 2.5em; + margin-bottom: 2.5em; +} + +.theme-admonition.alert{ + margin-top: 3em; + margin-bottom: 4em; +} + +html[data-theme='dark'] .theme-admonition details { + background: #00000054; + border: 1px solid #ffffff52; +} + +html[data-theme='dark'] .theme-admonition > .admonitionHeading_node_modules-\@docusaurus-theme-classic-lib-theme-Admonition-Layout-styles-module:not(:last-child) { + margin-bottom: 1em; + font-size: 1.2em; +} + +html[data-theme='dark'] .admonitionContent_node_modules-\@docusaurus-theme-classic-lib-theme-Admonition-Layout-styles-module > ul:last-child { + margin-bottom: 0; + padding-left: 1.6em; +} + article ul >li, article ol > li { margin-bottom: 1em; } +article ul >li::marker, article ol > li::marker { + font-weight: bold; +} + +article ul li a:first-child, article ol li a:first-child { + font-weight: bold; +} + article h1 { margin-top: 1em; } @@ -162,12 +243,20 @@ article h1 { --ifm-card-background-color: #eeeeee14; --ifm-button-color: #ccc; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); - +} + +html[data-theme='dark'] { + --docsearch-searchbox-background: #121526 !important; } [data-theme='dark'] .alert--secondary { - --ifm-color-secondary-contrast-background: #000; - --ifm-alert-background-color: #000; + --ifm-color-secondary-contrast-background: rgb(145 161 217 / 24%); + --ifm-alert-background-color: rgb(145 161 217 / 24%); +} + +[data-theme='dark'] .alert--info { + --ifm-color-info-contrast-background: rgb(25, 60, 71, 0.50); + --ifm-alert-background-color: rgb(25, 60, 71, 0.50); } .alert--secondary { @@ -184,6 +273,16 @@ article h1 { margin-bottom: 0.85em; } +details a.button.button--lg.button--primary { + padding-top: inherit; + padding-bottom: inherit; + text-decoration: none; +} + +details a.button.button--lg.button--primary p { + margin-bottom: inherit; +} + .header-github-link:hover { opacity: 0.6; } @@ -222,17 +321,21 @@ table tr td { aspect-ratio: 16/9 !important; } - div > ul > li > a.table-of-contents__link.toc-highlight { font-weight: 600; } +a.table-of-contents__link { + line-height: 1.45em; +} + .pagination-nav__link { background-color: #fffc; } [data-theme='dark'] .pagination-nav__link { background-color: rgb(16 36 69 / 23%); + border: none; } pre code { @@ -251,6 +354,10 @@ li.menu__list-item.hidden { border-radius: 32px; } +.DocSearch-Button-Placeholder { + min-width: 200px; +} + .aa-Autocomplete { min-width: 150px; } @@ -262,6 +369,16 @@ li.menu__list-item.hidden { .navbar-cta-button { color: var(--ifm-button-color); font-weight: bolder; + order: 2; + margin-left: 2em; +} + +.navbar-sidebar--show { + backdrop-filter: none !important; +} + +.navbar-sidebar__item .navbar-cta-button { + margin-left: inherit; } .navbar-cta-button:hover { @@ -288,6 +405,7 @@ q::before { width: 0; display: inline-block; } + q::after { content: close-quote; display: none; @@ -304,17 +422,27 @@ q .author { } dl dt { - font-weight: bold; + font-weight: bold; +} + +dt > em { + font-weight: 500; } dl dd { - font-style: italic + font-style: italic; + color: #929292; } dd p { margin: 0; } +dd { + + margin-bottom: 1em; +} + dd.disambiguation label { font-weight: bold; } @@ -344,606 +472,39 @@ dd.disambiguation a { } } - -/* Homepage */ - -html.plugin-pages body, html[data-theme='dark'].plugin-pages body{ - background-image: none; -} - -.landing-page .section__description { - font-size: 1em; - margin-left: 1.5em; - margin-right: 1.5em; - display: flex; - flex-direction: column; -} - -.landing-page .section__description > p { - font-size: 1.5em; -} - -html[data-theme='dark'] .landing-page .section__description > p { - color: #ccc; -} - -.landing-page .section__description > h2 { - font-size: 2.5rem; - margin-bottom: 0.5em; -} - -html[data-theme='dark'] .landing-page .section__description > h2 { - color: #fff; -} - -.landing-page .section__description .button { - margin-left: auto; - margin-right: auto; -} - -.landing-page main section { - max-width: 1600px; - overflow: hidden; -} - -.landing-page main { - display: flex; - flex-direction: column; - align-items: center; -} - -.landing-page .main-wrapper { - align-items: center; -} - -.landing-page img.screenshot { - max-width: 50%; - height: auto; - box-shadow: 0 0 20px 3px rgb(8 115 115 / 29%); - border-radius: 10px; - align-self: center; -} - -.landing-page .intro { - display: flex; - flex-direction: column; - min-width: 70%; - align-items: center; -} - -.landing-page header { - display: flex; - max-height: 90vh; - min-height: 700px; - height: 100vh; - width: 100vw; - justify-content: center; - margin-top: 2em; - margin-bottom: 2em; -} - -.landing-page header img.screenshot { - margin: 2em; -} - -.landing-page .intro h1 { - font-size: 3em; -} - -.landing-page .intro h2 { - margin-bottom: 1rem; - color: #ccc; -} - -.landing-page .intro h3 { - font-size: 1.5em; -} - -.landing-page header h1, .landing-page header h3 { - text-align: center; -} - -.landing-page .hero img { - min-width: 50%; - width: 100%; - height: auto; -} - -.hero--full-height { - box-sizing: border-box; - height: calc(90vh); - flex-direction: column; - justify-content: space-between; - padding: 0px 0; -} - -.hero__cta { - gap: 1rem; - justify-content: center; - display: flex; - -} -.landing-page main h2 { - text-align: center; - font-size: 2.5em; - margin-bottom: 2em; - color: #ccc; -} - -.landing-page main h2.section { - background: #030711; - min-height: 4em; - justify-content: center; - flex-direction: column; - display: flex; - flex-grow: 1; - flex-basis: 100%; - width: 100vw; - vertical-align: middle; - align-items: center; - -} -html[data-theme='dark'] .landing-page main h2.section { - background: rgb(0 0 0 / 21%); -} -html[data-theme='dark'] .hero h1, html[data-theme='dark'] .section__description h2 { - color: unset; - background: linear-gradient(to right bottom, rgb(255, 255, 255) 30%, rgba(255, 255, 255, 0.50)) text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; -} - -.landing-page main h3 { - text-align: center; -} - -.landing-page footer h2 { - color: #ccc; -} - -.landing-page footer h3 { - font-size: 2em; - line-height: 1.7em; - color: #7c7b7b; - text-align: center; -} - -.landing-page footer { - background: #0a1922; - min-width: 100vw; - padding: 3em; - text-align: center; -} - -html[data-theme='dark'] .landing-page footer { - background: rgb(0 0 0 / 21%); -} - -.landing-page main h2 strong { - color: #fff; -} - -.alternate-section { - display: flex; - gap: 2rem; - margin-bottom: 10rem; - flex-wrap: nowrap; - padding: 2rem; -} - -.landing-page .alternate-section .terminal { - max-width: 52%; -} - -.landing-page .terminal pre.screengrab { - /* for the atmos logo, it's best to have 0.95em, but no logos on this page */ - line-height: 1.1em; -} - -@media screen and (max-width: 996px) -{ - .landing-page header { - justify-content: flex-start; - max-width: 100vw; - overflow: hidden;; - } - - .hero__cta { - gap: 1rem; - display: flex; - max-width: 100vw; - flex-wrap: wrap; - } - - .alternate-section { - flex-wrap: wrap; - } - .landing-page main { - max-width: 100vw; - overflow: hidden; - } - .landing-page img.screenshot { - max-width: 98%; - } - - .landing-page .alternate-section .terminal { - max-width: 98vw; - } - - .landing-page .alternate-section { - margin-bottom: 0; - } - - .landing-page footer h2 { - display: flex; - flex-direction: column; - } -} - -.section--image-left { - flex-direction: row; -} - -.section--image-right { - flex-direction: row-reverse; -} - -.cta-section { - text-align: center; - padding: 2rem 0; -} - -strong.underline { - position: relative; - text-wrap: nowrap; -} - -strong.underline::after { - content: ""; - position: absolute; - bottom: -0.855rem; - left: -0.5rem; - right: -0.5rem; - height: 1rem; - - z-index: 1; - background-image: url("/img/underline.svg"); - background-repeat: no-repeat; - background-size: cover; -} - -strong.underline { - font-weight: inherit; -} - -strong.underline::after { -} - -.cheatsheet { - display: flex; - flex-direction: row; - flex-wrap: wrap; - background: #7d829e0f; - border-radius: 10px; - padding: 0; - margin: 0; - margin-top: 2em; -} - -.cheatsheet .card { - background: var(--ifm-card-background-color); - display: flex; - flex-direction: column; - padding: 0.5em; - width: auto; - margin: 0.5em; - align-self: flex-start; - max-width: 55vw; - overflow: auto; -} - -.cheatsheet .theme-code-block { - margin-bottom: 0.2em; +.markdown > a.button:last-child { + margin-bottom: 1em !important; } -.cheatsheet .theme-code-block .codeBlockTitle_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Content-styles-module { - padding: 0.1em; - padding-left: 1.5em; +.markdown h3 { color: #666; - font-family: monospace; } -.cheatsheet h2 { - font-size: 1.2em; - margin-bottom: 0.2em; - margin-left: 0.2em; - display: flex; - width: auto; -} +.mermaid { + background-color: transparent !important; + } -.cheatsheet > h2 { - flex-basis: 100%; - font-size: 2em; +html[data-theme='dark'] .markdown h3 { + color: #b1b1b1; } -.cheatsheet .card p { - flex-basis: 100%; - margin-top: 0.2em; - margin-bottom: 0; +.docusaurus-mermaid-container { + margin-top: 3em; } -.cheatsheet .card .card-body { - padding: 0; - display: flex; - flex-wrap: wrap; -} -.cheatsheet .card-group { - display: flex; - flex-direction: row; - flex-wrap: wrap; +.docusaurus-mermaid-container:not(:last-child):not(:has(+ i)) { + margin-bottom: 3em; } - -/* Terminal Styling */ -.terminal { - min-width: 100%; - color: #ccc; - /*background: #171717; */ - background: #070e12; - margin-top: 10px; +.docusaurus-mermaid-container + i { + display: block; margin-bottom: 1em; - line-height: 0.8em; - border-radius: 10px; - padding: 0.5em; - border: 1px solid #cccccc36; - box-shadow: 0 0 20px 3px rgb(8 115 115 / 29%); -} - -.terminal h1 { - text-align: center; - font-size: 1em; - font-family: monospace; - flex-grow: 1; - - align-items: center; - width: 100%; - min-width: 100%; - position: relative; - left: -60px; - color: #fff; - font-weight: bold; - padding-right: 80px; - padding-left: 80px; - - white-space: nowrap; - overflow: hidden; - max-width: 60%; - text-overflow: ellipsis; -} - -/* The container for the dots, representing a window control bar */ -.terminal .window-bar { - display: flex; - justify-content: space-between; -} - -.terminal .language-shell.theme-code-block { - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal pre.prism-code.language-console { - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal .language-yaml.theme-code-block { - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal .language-json.theme-code-block { - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal .language-console.theme-code-block -{ - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal pre.prism-code.language-json { - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal pre.prism-code.language-yaml { - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal pre.prism-code.language-shell { - --prism-background-color: transparent !important; - background-color: transparent !important; - background: transparent !important; -} - -.terminal .viewport { - max-height: 450px; - overflow: auto; -} -.terminal .window-controls { - display: flex; - align-items: flex-start; - justify-content: space-between; - width: 60px; /* Adjust the width as needed */ -} - -/* General styles for each dot */ -.terminal .control-dot { - width: 12px; /* Dot size */ - height: 12px; /* Dot size */ - border-radius: 50%; /* Makes the dot circular */ - margin: 0 4px; /* Spacing between dots */ -} - -/* Specific color for each dot */ -.terminal .close-dot { - background-color: #ff605c; /* Red color */ -} - -.terminal .minimize-dot { - background-color: #ffbd44; /* Yellow color */ -} - -.terminal .maximize-dot { - background-color: #00ca56; /* Green color */ -} - -.terminal pre.screengrab { - line-height: 0.95em; - letter-spacing: -0.009em; - padding: 0.3em; - background: transparent; -} - -.file { - margin-bottom: 1em; - -} - -.file pre>code>span.token-line::before { - content: '1'; - display: inline-block; - padding: 0 .5em; - margin-right: .5em; - color: #888; -} - -.file pre code span.token-line { - line-height: 1em; - counter-increment: line; -} - -.file pre code span.token-line::before { - content: counter(line); - display: inline-block; - padding: 0 .5em; - margin-right: .5em; - color: #888; - text-align: right; - min-width: 20px; - border-right: 1px solid #cccccc47; -} - -.file div.tab { - position: relative; - top: 2px; - z-index: 2; - display: inline-block; - padding: 0.5em; - transform: perspective(0.6em) rotateX(1deg); - transform-origin: bottom; -} - -.file div.tab > h1 { - font-size: 0.98em; - line-height: 1.2em; - margin-top: 5px; - margin-bottom: 0; - margin-left: 0.5em; - margin-right: 0.5em; - font-weight: 500; - font-family: var(--ifm-font-family-monospace); - color: #ccc; - transform-style: preserve-3d; - transform: perspective(0.6em) rotateX(-1deg); -} -.file div.tab > h1 svg.svg-inline--fa { - margin-right: 0.5em; -} - -html[data-theme='dark'] .file div.tab > h1 { - color: var(--ifm-heading-color); -} - -.file div.tab::before { - content: ''; /* To generate the box */ - position: absolute; - top: 0; right: 0; bottom: 0; left: 0; - z-index: -1; - background: rgb(16, 36, 69); - transform-origin: bottom; - border: 1px solid #cccccc38; - border-bottom: 1px solid rgb(16, 36, 69); - border-radius: 10px 10px 0 0; -} - -.file div.viewport { - border: 1px solid #cccccc38; - border-radius: 6px; - border-top-left-radius: 4px; -} - -.file .language-yaml.theme-code-block { - margin-bottom: 0; -} - -.file .language-hcl.theme-code-block { - margin-bottom: 0; -} - -.file .language-json.theme-code-block { - margin-bottom: 0; -} - -.file .language-console.theme-code-block { - margin-bottom: 0; -} - -.file div.viewport { - padding: 5px; - background: rgb(16, 36, 69); -} - -.typewriter { - display: flex; - flex: 0 1 auto; -} - -.typewriter > tt { - display: flex; - width: auto; - font-size: 1.15em; - line-height: 1.2em; - margin: 0.5em; - border-right: 6px solid rgba(2, 181, 9,1); - flex-basis: content; - white-space: nowrap; - overflow: hidden; - transform: translateY(-50%); -} - -/* Animation */ -.animate .typing { - animation: typing 3s steps(18) 1s 1 normal both, - blinkTextCursor 500ms steps(44) infinite normal; } -@keyframes typing { - from{max-width: 0; } - to{max-width: 100vw; padding-right: 0.3em;} +sub { + filter: opacity(0.5); } -@keyframes blinkTextCursor{ - from{border-right-color: rgba(2, 181, 9,.75);} - to{border-right-color: transparent;} +.markdown h3 { + margin-top: 3em; } diff --git a/website/src/css/landing-page.css b/website/src/css/landing-page.css new file mode 100644 index 000000000..87f389008 --- /dev/null +++ b/website/src/css/landing-page.css @@ -0,0 +1,275 @@ +html[data-theme='dark'] .landing-page footer { + background: rgb(0 0 0 / 21%); +} + +.landing-page main h2 strong { + color: #fff; +} + + + +/* Homepage */ + +html.plugin-pages body, html[data-theme='dark'].plugin-pages body{ + background-image: none; +} + +.landing-page .section__description { + font-size: 1em; + margin-left: 1.5em; + margin-right: 1.5em; + display: flex; + flex-direction: column; +} + +.landing-page .section__description > p { + font-size: 1.5em; +} + +html[data-theme='dark'] .landing-page .section__description > p { + color: #ccc; +} + +.landing-page .section__description > h2 { + font-size: 2.5rem; + margin-bottom: 0.5em; +} + +html[data-theme='dark'] .landing-page .section__description > h2 { + color: #fff; +} + +.landing-page .section__description .button { + margin-left: auto; + margin-right: auto; +} + +.landing-page main section { + max-width: 1600px; + overflow: hidden; +} + +.landing-page main { + display: flex; + flex-direction: column; + align-items: center; +} + +.landing-page .main-wrapper { + align-items: center; +} + +.landing-page img.screenshot { + max-width: 50%; + height: auto; + box-shadow: 0 0 20px 3px rgb(8 115 115 / 29%); + border-radius: 10px; + align-self: center; +} + +.landing-page .intro { + display: flex; + flex-direction: column; + min-width: 70%; + align-items: center; +} + +.landing-page header { + display: flex; + max-height: 90vh; + min-height: 700px; + height: 100vh; + width: 100vw; + justify-content: center; + margin-top: 2em; + margin-bottom: 2em; +} + +.landing-page header img.screenshot { + margin: 2em; +} + +.landing-page .intro h1 { + font-size: 3em; +} + +.landing-page .intro h2 { + margin-bottom: 1rem; + color: #ccc; +} + +.landing-page .intro h3 { + font-size: 1.5em; +} + +.landing-page header h1, .landing-page header h3 { + text-align: center; +} + +.landing-page .hero img { + min-width: 50%; + width: 100%; + height: auto; +} + +.hero--full-height { + box-sizing: border-box; + height: calc(90vh); + flex-direction: column; + justify-content: space-between; + padding: 0px 0; +} + +.hero__cta { + gap: 1rem; + justify-content: center; + display: flex; + +} +.landing-page main h2 { + text-align: center; + font-size: 2.5em; + margin-bottom: 2em; + color: #ccc; +} + +.landing-page main h2.section { + background: #030711; + min-height: 4em; + justify-content: center; + flex-direction: column; + display: flex; + flex-grow: 1; + flex-basis: 100%; + width: 100vw; + vertical-align: middle; + align-items: center; + +} +html[data-theme='dark'] .landing-page main h2.section { + background: rgb(0 0 0 / 21%); +} +html[data-theme='dark'] .hero h1, html[data-theme='dark'] .section__description h2 { + color: unset; + background: linear-gradient(to right bottom, rgb(255, 255, 255) 30%, rgba(255, 255, 255, 0.50)) text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.landing-page main h3 { + text-align: center; +} + +.landing-page footer h2 { + color: #ccc; +} + +.landing-page footer h3 { + font-size: 2em; + line-height: 1.7em; + color: #7c7b7b; + text-align: center; +} + +.landing-page footer { + background: #0a1922; + min-width: 100vw; + padding: 3em; + text-align: center; +} + +strong.underline { + position: relative; + text-wrap: nowrap; +} + +strong.underline::after { + content: ""; + position: absolute; + bottom: -0.855rem; + left: -0.5rem; + right: -0.5rem; + height: 1rem; + + z-index: 1; + background-image: url("/img/underline.svg"); + background-repeat: no-repeat; + background-size: cover; +} + +strong.underline { + font-weight: inherit; +} + +strong.underline::after { +} + +.alternate-section { + display: flex; + gap: 2rem; + margin-bottom: 10rem; + flex-wrap: nowrap; + padding: 2rem; +} + +.landing-page .alternate-section .terminal { + max-width: 50vw; +} + +.landing-page .terminal pre.screengrab { + /* for the atmos logo, it's best to have 0.95em, but no logos on this page */ + line-height: 1.1em; +} + +@media screen and (max-width: 996px) +{ + .landing-page header { + justify-content: flex-start; + max-width: 100vw; + overflow: hidden;; + } + + .hero__cta { + gap: 1rem; + display: flex; + max-width: 100vw; + flex-wrap: wrap; + } + + .alternate-section { + flex-wrap: wrap; + } + .landing-page main { + max-width: 100vw; + overflow: hidden; + } + .landing-page img.screenshot { + max-width: 98%; + } + + .landing-page .alternate-section .terminal { + max-width: 98vw; + } + + .landing-page .alternate-section { + margin-bottom: 0; + } + + .landing-page footer h2 { + display: flex; + flex-direction: column; + } +} + +.section--image-left { + flex-direction: row; +} + +.section--image-right { + flex-direction: row-reverse; +} + +.cta-section { + text-align: center; + padding: 2rem 0; +} diff --git a/website/src/pages/index.js b/website/src/pages/index.js index a7363e8e0..f9a5c0130 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -4,67 +4,68 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Link from '@docusaurus/Link'; import useBaseUrl from '@docusaurus/useBaseUrl' import Screengrab from '@site/src/components/Screengrab' +import '../css/landing-page.css'; function Home() { const context = useDocusaurusContext(); const {siteConfig = {}} = context; return ( -
+
-
-
+
+

Manage Environments Easily in Terraform

- Product Screenshot -
-

Try the Quick Start

-

Learn More

+ Product Screenshot +
+

Try the Quick Start

+

Learn More

-

Frustrated using Terraform the old fashion way? There's a smarter option.

+

Use a Modern Composable Framework for Terraform backed by YAML

-

Simplify complex architectures with DRY configuration

-
+

Simplify complex architectures with DRY configuration

+
-
+

Start Your Project

Create a solid foundation with a well-structured folder layout, embracing best practices and conventions for a consistently organized project.

-

Learn More

+

Learn More

-
+
-
+

Write your Components

Use your existing Terraform root modules or create new ones. Component libraries make sharing easy. Use vendoring to pull down remote dependencies.

-

Learn More

+

Learn More

-
+
-
+

Define your Stacks

Configure your environments—development, staging, production—each tailored to different stages of the lifecycle, ensuring smooth transitions and robust deployment strategies. Inherit from a common baseline to keep it DRY.

-

Learn More

+

Learn More

-
+
-
+

Deploy 🚀

Execute deployments with precision using Terraform's plan and apply commands, fully integrated with native GitOps workflows through GitHub Actions for seamless automation.

-

Learn More

+

Learn More

-

What are you waiting for? It's FREE and Open Source

-

Your team can succeed with Terraform today.

-
-

Try the Quick Start

+

What are you waiting for? It's FREE and Open Source

+

Your team can succeed with Terraform today.

+
+

Try the Quick Start

diff --git a/website/src/theme/DocItem/Layout/index.js b/website/src/theme/DocItem/Layout/index.js new file mode 100644 index 000000000..a3f6452f3 --- /dev/null +++ b/website/src/theme/DocItem/Layout/index.js @@ -0,0 +1,15 @@ +import React, { useEffect } from 'react'; +import Layout from '@theme-original/DocItem/Layout'; +import { resetStepCounter } from '@site/src/components/Step'; + +export default function LayoutWrapper(props) { + useEffect(() => { + resetStepCounter(); // Reset the counter whenever the layout is rendered + }, []); + + return ( + <> + + + ); +} diff --git a/website/src/theme/NavbarItem.js b/website/src/theme/NavbarItem.js new file mode 100644 index 000000000..a9eba9e37 --- /dev/null +++ b/website/src/theme/NavbarItem.js @@ -0,0 +1,21 @@ +import React, { useEffect } from 'react'; +import OriginalNavBarItem from '@theme-original/NavbarItem'; +import useGlobalData from '@docusaurus/useGlobalData'; + +export default function NavbarItem(props) { + const globalData = useGlobalData(); + + //console.log('Global Data:', JSON.stringify(globalData['fetch-latest-release'])); + + const latestRelease = globalData['fetch-latest-release']?.default?.latestRelease || 'v0.0.0'; + + useEffect(() => { + const latestReleaseLink = document.querySelector('.latest-release-link'); + if (latestReleaseLink) { + latestReleaseLink.href = `https://github.com/cloudposse/atmos/releases/tag/${latestRelease}`; + latestReleaseLink.innerText = `${latestRelease}`; + } + }, [latestRelease]); + + return ; +}