skills/cloudposse/atmos/atmos-schemas

atmos-schemas

SKILL.md

Atmos JSON Schema System

Overview

Atmos uses JSON Schema (Draft 2020-12) to validate stack manifests, provide IDE auto-completion, and catch configuration errors early. The schema system has three layers:

  1. Website manifest schema -- Published at website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json, served at https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json, and registered with SchemaStore as https://json.schemastore.org/atmos-manifest.json. This is the public-facing schema for IDE integration.

  2. Embedded schemas -- Located under pkg/datafetcher/schema/, compiled into the Atmos binary via Go embed. These are the schemas Atmos uses at runtime for validation. There are multiple embedded schemas:

    • pkg/datafetcher/schema/atmos/manifest/1.0.json -- Minimal manifest schema (fallback).
    • pkg/datafetcher/schema/stacks/stack-config/1.0.json -- Stack configuration validation schema. This is the primary schema used by atmos validate stacks.
    • pkg/datafetcher/schema/config/global/1.0.json -- Global Atmos configuration schema.
    • pkg/datafetcher/schema/vendor/package/1.0.json -- Vendor package manifest schema.
  3. User-provided schema -- Users can override the embedded schema by specifying a path or URL in atmos.yaml under schemas.atmos.manifest, or via --schemas-atmos-manifest flag or ATMOS_SCHEMAS_ATMOS_MANIFEST env var.

Schema Files and Their Locations

Website Schema (Public)

Path: website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

This is deployed to https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json and is the canonical public schema. It uses the SchemaStore $id:

{
  "$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"
}

Embedded Schemas (Runtime)

Path: pkg/datafetcher/schema/

The pkg/datafetcher/atmos_fetcher.go uses //go:embed schema/* to embed all schema files into the binary. The atmosFetcher.FetchData() method resolves atmos:// URIs to embedded schema files by stripping the prefix and appending .json.

Directory structure:

pkg/datafetcher/schema/
  atmos/manifest/1.0.json          -- Minimal manifest schema
  stacks/stack-config/1.0.json     -- Full stack config validation schema
  config/global/1.0.json           -- Global atmos.yaml config schema
  vendor/package/1.0.json          -- Vendor manifest schema

Vendor Package Schema

Path: pkg/datafetcher/schema/vendor/package/1.0.json

Validates vendor.yaml files with apiVersion, kind, metadata, and spec sections:

{
  "fileMatch": ["vendor.{yml,yaml}", "vendor.d/**/*.{yml,yaml}"],
  "properties": {
    "apiVersion": { "enum": ["atmos/v1"] },
    "kind": { "enum": ["AtmosVendorConfig"] },
    "metadata": { "required": ["name", "description"] },
    "spec": { "required": ["sources"] }
  },
  "required": ["apiVersion", "kind", "metadata", "spec"]
}

Schema Configuration in atmos.yaml

schemas:
  # JSON Schema for validating component configurations
  jsonschema:
    base_path: "stacks/schemas/jsonschema"

  # OPA policies for component validation
  opa:
    base_path: "stacks/schemas/opa"

  # JSON Schema for validating Atmos manifests themselves
  atmos:
    manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json"
    # Also supports URLs:
    # manifest: "https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json"

Configuration precedence:

  1. --schemas-atmos-manifest CLI flag
  2. ATMOS_SCHEMAS_ATMOS_MANIFEST environment variable
  3. schemas.atmos.manifest in atmos.yaml
  4. Default embedded schema (compiled into the binary)

Validating Stacks

atmos validate stacks

Validates all stack manifests against the Atmos manifest JSON Schema:

# Use default embedded schema
atmos validate stacks

# Use local schema file
atmos validate stacks --schemas-atmos-manifest schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

# Use remote schema
atmos validate stacks --schemas-atmos-manifest https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json

This command checks:

  • YAML syntax errors in all manifest files (template files .yaml.tmpl, .yml.tmpl are excluded)
  • Import validity -- correct references, no self-imports, valid data types
  • Schema validation of all manifest sections against the JSON Schema
  • Component duplication -- same component in same stack defined in multiple files with different configs

atmos validate schema

Validates files against custom schema validators configured in atmos.yaml:

schemas:
  my_custom_key:
    schema: !import https://example.com/schema.json
    matches:
      - folder/*.yaml
atmos validate schema
atmos validate schema my_custom_key

IDE Integration

JetBrains IDEs

JetBrains IDEs (IntelliJ, WebStorm, GoLand) automatically download schemas from SchemaStore. The Atmos manifest schema is registered with $id: https://json.schemastore.org/atmos-manifest.json.

To manually associate: Settings > Languages & Frameworks > Schemas and DTDs > JSON Schema Mappings, add the schema URL and map it to your stack YAML files.

VS Code

Enable SchemaStore in VS Code settings for YAML files:

{
  "yaml.schemaStore.enable": true
}

For manual association, add to .vscode/settings.json:

{
  "yaml.schemas": {
    "https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json": [
      "stacks/**/*.yaml",
      "stacks/**/*.yml"
    ]
  }
}

How to Update Schemas When Adding New Features

When you add a new feature to Atmos that introduces new configuration keys in stack manifests, you MUST update the JSON Schema files. Failure to do so causes validation errors for users who rely on atmos validate stacks or IDE auto-completion.

Which Schema Files to Update

For feature work, always update the website schema and stack-config schema first. Then update the other two when the new keys or structure apply to their domains.

File Purpose
website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json Public schema (website, SchemaStore, IDE)
pkg/datafetcher/schema/stacks/stack-config/1.0.json Primary embedded schema for validate stacks
pkg/datafetcher/schema/atmos/manifest/1.0.json Minimal embedded manifest schema
pkg/datafetcher/schema/config/global/1.0.json Global config validation schema

The website schema and the stack-config schema are the most complete and feature-rich. Update atmos/manifest and config/global when adding top-level or structural changes that affect their respective domains.

For vendor manifest changes, update:

  • pkg/datafetcher/schema/vendor/package/1.0.json

Step-by-Step: Adding a New Top-Level Property

  1. Add the property reference in the top-level properties object in each schema file:
{
  "properties": {
    "existing_prop": { "$ref": "#/definitions/existing_prop" },
    "my_new_prop": { "$ref": "#/definitions/my_new_prop" }
  }
}
  1. Add the definition in the definitions section. Follow the Atmos !include pattern:
{
  "definitions": {
    "my_new_prop": {
      "title": "my_new_prop",
      "description": "Description of the new property",
      "oneOf": [
        {
          "type": "string",
          "pattern": "^!include"
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "field_one": {
              "type": "string",
              "description": "Description of field_one"
            },
            "field_two": {
              "type": "boolean",
              "description": "Description of field_two"
            }
          },
          "required": []
        }
      ]
    }
  }
}
  1. If the property should make a manifest valid on its own, add it to the oneOf > anyOf array:
{
  "oneOf": [
    { "required": ["workflows"] },
    {
      "anyOf": [
        { "required": ["import"] },
        { "required": ["my_new_prop"] }
      ]
    }
  ]
}
  1. Update all four schema files with the same changes.

Step-by-Step: Adding a Property to a Component Manifest

To add a new property at the component level (inside components.terraform.<name>):

  1. Add the property to terraform_component_manifest (and/or helmfile_component_manifest, packer_component_manifest as appropriate):
{
  "definitions": {
    "terraform_component_manifest": {
      "oneOf": [
        { "type": "string", "pattern": "^!include" },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "metadata": { "$ref": "#/definitions/metadata" },
            "my_new_field": { "$ref": "#/definitions/my_new_field" }
          }
        }
      ]
    }
  }
}
  1. Create the definition for your new field as shown above.

Step-by-Step: Adding a Property to an Existing Definition

To add a new field to an existing definition (e.g., adding a field to metadata):

  1. Locate the definition in the definitions section.

  2. Add the property inside the object variant of the oneOf:

{
  "definitions": {
    "metadata": {
      "oneOf": [
        { "type": "string", "pattern": "^!include" },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "type": { "type": "string", "enum": ["abstract", "real"] },
            "enabled": { "type": "boolean" },
            "my_new_metadata_field": {
              "type": "string",
              "description": "Description of the new metadata field"
            }
          }
        }
      ]
    }
  }
}

The !include Pattern

Every definition in the Atmos schema supports the !include YAML tag pattern. This means every definition uses oneOf with the first option being a string matching ^!include and the second being the actual type definition:

"oneOf": [
  {
    "type": "string",
    "pattern": "^!include"
  },
  {
    "type": "object",
    ...
  }
]

Always include this pattern when creating new definitions. It enables users to use !include directives to load sections from external files.

JSON Schema 2020-12 Quick Reference

Common patterns used in Atmos schemas:

// String with enum
{ "type": "string", "enum": ["value1", "value2"] }

// Boolean
{ "type": "boolean", "description": "Flag description" }

// Integer with minimum
{ "type": "integer", "minimum": 0 }

// Array of strings with uniqueness
{ "type": "array", "uniqueItems": true, "items": { "type": "string" } }

// Object with free-form keys
{ "type": "object", "additionalProperties": true }

// Object with pattern-matched keys referencing a definition
{
  "type": "object",
  "patternProperties": {
    "^[/a-zA-Z0-9-_{}. ]+$": { "$ref": "#/definitions/my_definition" }
  },
  "additionalProperties": false
}

// Flexible type (string or number)
{ "anyOf": [{ "type": "number" }, { "type": "string" }] }

// Reference to another definition
{ "$ref": "#/definitions/my_definition" }

Differences Between Schema Files

The four manifest schema files are mostly identical but have some differences:

  • Website schema (website/static/) -- The most complete. Includes locals, dependencies, generate, provision, source, auth, and component_auth definitions. Has source_retry, auth_providers, auth_identities, auth_identity, auth_identity_via, auth_session, and auth_console definitions.

  • Stack-config schema (pkg/datafetcher/schema/stacks/) -- Has name as a top-level property (with description: "Logical name for this stack"). Has locals definition. May include additional definitions like name in the metadata section. Missing some newer definitions that are in the website schema (e.g., generate, provision, source, auth).

  • Atmos manifest schema (pkg/datafetcher/schema/atmos/) -- Minimal. Does not have locals, dependencies, generate, provision, source, or auth definitions.

  • Global config schema (pkg/datafetcher/schema/config/) -- Similar to atmos manifest, used for global config validation.

When adding new features, the minimum required updates are the website schema and the stack-config schema. Also update atmos/manifest when manifest-level validation is affected, and config/global when global config validation is affected.

Checklist for Schema Updates

When adding a new Atmos feature with configuration keys:

  • Add the definition to website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • Add the definition to pkg/datafetcher/schema/stacks/stack-config/1.0.json
  • Add the definition to pkg/datafetcher/schema/atmos/manifest/1.0.json (if applicable)
  • Add the definition to pkg/datafetcher/schema/config/global/1.0.json (if applicable)
  • Add property references in top-level properties or component manifest properties
  • Include the !include pattern in oneOf for all new object definitions
  • Add description fields for IDE auto-completion hover text
  • Test with atmos validate stacks to ensure no regressions
  • Verify IDE auto-completion works with the updated schema

Schema Structure Overview

The manifest schema defines these top-level properties (each referencing a definition):

  • import -- Import section (array of strings or objects with path)
  • terraform -- Global Terraform settings (vars, env, settings, backend, etc.)
  • helmfile -- Global Helmfile settings
  • packer -- Global Packer settings
  • vars -- Global variables
  • hooks -- Lifecycle hooks
  • env -- Environment variables
  • settings -- Settings including validation, depends_on, spacelift, atlantis, templates
  • locals -- File-scoped local variables for templates (do not inherit across imports)
  • components -- Component definitions (terraform, helmfile, packer)
  • overrides -- Override section
  • workflows -- Workflow definitions
  • dependencies -- Tool dependencies (tools with versions)
  • generate -- Declarative file generation

Key definitions in the definitions section:

Definition Description
terraform_components Map of Terraform component names to manifests
terraform_component_manifest Single Terraform component (metadata, vars, backend, hooks, etc.)
helmfile_components Map of Helmfile component names to manifests
helmfile_component_manifest Single Helmfile component
packer_components Map of Packer component names to manifests
packer_component_manifest Single Packer component
metadata Component metadata (type, enabled, component, inherits, workspace, custom, locked)
settings Settings with validation, depends_on, spacelift, atlantis, templates
validation / validation_manifest Validation rules (schema_type, schema_path, module_paths)
backend_type Backend type enum (local, s3, remote, vault, static, azurerm, gcs, cloud)
backend / backend_manifest Backend config per type
overrides Override section (command, vars, env, settings, providers)
workflows / workflow_manifest Workflow definitions with steps
depends_on / depends_on_manifest Dependency declarations
spacelift Spacelift integration settings
atlantis Atlantis integration settings
source / source_retry JIT vendoring source configuration
provision / provision_workdir Isolated workdir provisioner
dependencies / dependencies_tools Tool dependency declarations
component_auth Component-level auth (providers, identities)
generate Declarative file generation (string templates or objects)

Reference Files

  • Schema structure reference -- Detailed schema structure and definitions
  • Website schema: website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • Embedded schemas: pkg/datafetcher/schema/
  • Schema embedding: pkg/datafetcher/atmos_fetcher.go
  • Schema configuration docs: website/docs/cli/configuration/schemas.mdx
  • Validate stacks docs: website/docs/cli/commands/validate/validate-stacks.mdx
  • Validate schema docs: website/docs/cli/commands/validate/validate-schema.mdx
Weekly Installs
3
GitHub Stars
1.3K
First Seen
13 days ago
Installed on
amp3
cline3
opencode3
cursor3
kimi-cli3
codex3