cmd

package
v1.202.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2025 License: Apache-2.0 Imports: 90 Imported by: 0

Documentation

Index

Constants

View Source
const (
	IdentityFlagName = "identity"
	// IdentityFlagSelectValue is imported from cfg.IdentityFlagSelectValue.
	IdentityFlagSelectValue = cfg.IdentityFlagSelectValue
)
View Source
const FlagStack = "stack"

FlagStack is the name of the stack flag used across commands.

Variables

View Source
var (
	ErrInvalidOutputType = fmt.Errorf("invalid output type specified. Valid values are 'list', 'map', and 'all'")
	ErrInvalidFormat     = fmt.Errorf("invalid format specified. Valid values are 'yaml' and 'json'")
)
View Source
var RootCmd = &cobra.Command{
	Use:   "atmos",
	Short: "Framework for Infrastructure Orchestration",
	Long:  `Atmos is a framework for orchestrating and operating infrastructure workflows across multiple cloud and DevOps toolchains.`,

	PersistentPreRun: func(cmd *cobra.Command, args []string) {

		if cmd.Flags().Changed(verboseFlagName) {

			verbose, flagErr := cmd.Flags().GetBool(verboseFlagName)
			if flagErr != nil {
				errUtils.CheckErrorPrintAndExit(flagErr, "", "")
			}
			errUtils.SetVerboseFlag(verbose)
		} else if viper.IsSet(verboseFlagName) {

			verbose := viper.GetBool(verboseFlagName)
			errUtils.SetVerboseFlag(verbose)
		}

		isHelpCommand := cmd.Name() == "help"
		helpFlag := cmd.Flags().Changed("help")

		isHelpRequested := isHelpCommand || helpFlag

		if isHelpRequested {

			cmd.SilenceUsage = false
			cmd.SilenceErrors = false
		} else {
			cmd.SilenceUsage = true
			cmd.SilenceErrors = true
		}

		if err := processChdirFlag(cmd); err != nil {
			errUtils.CheckErrorPrintAndExit(err, "", "")
		}

		configureEarlyColorProfile(cmd)

		syncGlobalFlagsToViper(cmd)

		configAndStacksInfo := schema.ConfigAndStacksInfo{}

		if bp, _ := cmd.Flags().GetString("base-path"); bp != "" {
			configAndStacksInfo.AtmosBasePath = bp
		}
		if cfgFiles, _ := cmd.Flags().GetStringSlice("config"); len(cfgFiles) > 0 {
			configAndStacksInfo.AtmosConfigFilesFromArg = cfgFiles
		}
		if cfgDirs, _ := cmd.Flags().GetStringSlice("config-path"); len(cfgDirs) > 0 {
			configAndStacksInfo.AtmosConfigDirsFromArg = cfgDirs
		}

		tmpConfig, err := cfg.InitCliConfig(configAndStacksInfo, false)
		if err != nil {
			if errors.Is(err, cfg.NotFound) {

				if !isHelpRequested {
					log.Warn(err.Error())
				}
			} else if isVersionCommand() {

				log.Debug("CLI configuration error (continuing for version command)", "error", err)
			} else {

				enrichedErr := errUtils.Build(err).
					WithHint("Verify your atmos.yaml syntax and configuration").
					WithHint("Run 'atmos version' to check if Atmos is working").
					WithExitCode(2).
					Err()
				errUtils.CheckErrorPrintAndExit(enrichedErr, "", "")
			}
		}

		if !isHelpRequested {
			if setupErr := setupProfiler(cmd, &tmpConfig); setupErr != nil {
				errUtils.CheckErrorPrintAndExit(setupErr, "Failed to setup profiler", "")
			}
		}

		if showHeatmap, _ := cmd.Flags().GetBool("heatmap"); showHeatmap {
			perf.EnableTracking(true)
		}

		if !isCompletionCommand(cmd) && err == nil {
			telemetry.PrintTelemetryDisclosure()
		}

		if ioErr := iolib.Initialize(); ioErr != nil {
			errUtils.CheckErrorPrintAndExit(fmt.Errorf("failed to initialize I/O context: %w", ioErr), "", "")
		}
		ioCtx := iolib.GetContext()
		ui.InitFormatter(ioCtx)
		data.InitWriter(ioCtx)
		data.SetMarkdownRenderer(ui.Format)

		term := terminal.New()
		lipgloss.SetColorProfile(convertToTermenvProfile(term.ColorProfile()))
	},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {

		if profilerServer != nil {
			if stopErr := profilerServer.Stop(); stopErr != nil {
				log.Error("Failed to stop profiler", "error", stopErr)
			}
		}

		showHeatmap, _ := cmd.Flags().GetBool("heatmap")
		if showHeatmap {
			heatmapMode, _ := cmd.Flags().GetString("heatmap-mode")
			if err := displayPerformanceHeatmap(cmd, heatmapMode); err != nil {
				log.Error("Failed to display performance heatmap", "error", err)
			}
		}
	},
	RunE: func(cmd *cobra.Command, args []string) error {

		checkAtmosConfig()

		err := e.ExecuteAtmosCmd()
		return err
	},
}

RootCmd represents the base command when called without any subcommands.

View Source
var SupportedFormats = []string{"json", "bash", "dotenv"}
View Source
var ValidateSchemaCmd = &cobra.Command{
	Use:   "schema",
	Short: "Validate YAML files against JSON schemas defined in atmos.yaml",
	Long: `The validate schema command reads the ` + "`" + `schemas` + "`" + ` section of the atmos.yaml file
and validates matching YAML files against their corresponding JSON schemas.

Each entry under ` + "`" + `schemas` + "`" + ` should define:
  - ` + "`" + `schema` + "`" + `: The path to the JSON schema file.
  - ` + "`" + `matches` + "`" + `: A glob pattern that specifies which YAML files to validate.

For every schema entry:
  - The JSON schema is loaded from the specified path.
  - All files matching the glob pattern are collected.
  - Each matching YAML file is parsed and converted to JSON.
  - The converted YAML is validated against the schema.

This command helps ensure that configuration files follow a defined structure
and are compliant with expected formats, reducing configuration drift and runtime errors.
`,
	FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
	Args:               cobra.MaximumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {

		checkAtmosConfig()

		schema := ""
		key := ""
		if len(args) > 0 {
			key = args[0]
		}

		if cmd.Flags().Changed("schemas-atmos-manifest") {
			schema, _ = cmd.Flags().GetString("schemas-atmos-manifest")
		}

		if key == "" && schema != "" {
			log.Error("key not provided for the schema to be used")
			errUtils.OsExit(1)
		}

		if err := exec.NewAtmosValidatorExecutor(&atmosConfig).ExecuteAtmosValidateSchemaCmd(key, schema); err != nil {
			if errors.Is(err, exec.ErrInvalidYAML) {
				errUtils.OsExit(1)
			}
			return err
		}

		return nil
	},
}

ValidateSchemaCmd represents the 'atmos validate schema' command.

This command reads the 'schemas' section from the atmos.yaml configuration file, where each schema entry specifies a JSON schema path and a glob pattern for matching YAML files.

For each entry:

  • The JSON schema is loaded.
  • All YAML files matching the glob pattern are discovered.
  • Each YAML file is converted to JSON and validated against the schema.

This command ensures that configuration files conform to expected structures and helps catch errors early in the development or deployment process.

View Source
var ValidateStacksCmd = &cobra.Command{
	Use:                "stacks",
	Short:              "Validate stack manifest configurations",
	Long:               "This command validates the configuration of stack manifests in Atmos to ensure proper setup and compliance.",
	Example:            "validate stacks",
	FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
	Args:               cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {

		checkAtmosConfig()

		err := exec.ExecuteValidateStacksCmd(cmd, args)
		if err != nil {
			return err
		}

		return nil
	},
}

ValidateStacksCmd validates stacks

Functions

func AddIdentityCompletion added in v1.195.0

func AddIdentityCompletion(cmd *cobra.Command)

AddIdentityCompletion registers shell completion for the identity flag if present on the command.

func AddStackCompletion added in v1.161.0

func AddStackCompletion(cmd *cobra.Command)

func CheckForAtmosUpdateAndPrintMessage added in v1.127.0

func CheckForAtmosUpdateAndPrintMessage(atmosConfig schema.AtmosConfiguration)

CheckForAtmosUpdateAndPrintMessage checks if a version update is needed and prints a message if a newer version is found. It loads the cache, decides if it's time to check for updates, compares the current version to the latest available release, and if newer, prints the update message. It also updates the cache's timestamp after printing.

func Cleanup added in v1.192.0

func Cleanup()

Cleanup performs cleanup operations before the program exits. This should be called by main when the program is terminating.

func ComponentsArgCompletion added in v1.161.0

func ComponentsArgCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)

func Contains added in v1.137.0

func Contains(slice []string, target string) bool

Contains checks if a slice of strings contains an exact match for the target string.

func CreateAuthManager added in v1.202.0

func CreateAuthManager(authConfig *schema.AuthConfig) (auth.AuthManager, error)

CreateAuthManager creates a new auth manager with all required dependencies. Exported for use by command packages (e.g., terraform package).

func CreateAuthManagerFromIdentity added in v1.197.0

func CreateAuthManagerFromIdentity(
	identityName string,
	authConfig *schema.AuthConfig,
) (auth.AuthManager, error)

CreateAuthManagerFromIdentity creates and authenticates an AuthManager from an identity name. Returns nil if identityName is empty (no authentication requested). Returns error if identityName is provided but auth is not configured in atmos.yaml. This helper reduces nested complexity in describe commands.

This function delegates to auth.CreateAndAuthenticateManager to ensure consistent authentication behavior across CLI commands and internal execution logic.

Note: This function does not load stack configs for default identities. Use CreateAuthManagerFromIdentityWithAtmosConfig if you need stack-level default identity resolution.

func CreateAuthManagerFromIdentityWithAtmosConfig added in v1.201.0

func CreateAuthManagerFromIdentityWithAtmosConfig(
	identityName string,
	authConfig *schema.AuthConfig,
	atmosConfig *schema.AtmosConfiguration,
) (auth.AuthManager, error)

CreateAuthManagerFromIdentityWithAtmosConfig creates and authenticates an AuthManager from an identity name. This version accepts the full atmosConfig to enable loading stack configs for default identities.

When identityName is empty and atmosConfig is provided:

  • Loads stack configuration files for auth identity defaults
  • Applies stack-level defaults on top of atmos.yaml defaults
  • When stack defaults are present, they override atmos.yaml identity defaults (stack > atmos.yaml)

This solves the chicken-and-egg problem where:

  • We need to know the default identity to authenticate
  • But stack configs are only loaded after authentication is configured
  • Stack-level defaults (auth.identities.*.default: true) would otherwise be ignored

func Execute

func Execute() error

Execute adds all child commands to the root command and sets flags appropriately. Execute runs the root CLI command and performs one-time global startup tasks. It processes a leading --chdir before loading configuration, loads and wires the CLI configuration to subsystems, initializes markdown rendering and logging, registers custom commands and aliases (unless running the version command), executes the root command, captures telemetry, and handles unknown-command errors by showing usage. This function is invoked once from main.main.

func ExecuteVersion added in v1.200.0

func ExecuteVersion() error

ExecuteVersion prints the version information. This is called by main.main() when --version flag is detected at the application entry point. Handling version here (instead of in PersistentPreRun) eliminates the deep exit, allowing tests to run normally without triggering os.Exit in Go 1.25+.

func GetConfigAndStacksInfo added in v1.202.0

func GetConfigAndStacksInfo(commandName string, cmd *cobra.Command, args []string) (schema.ConfigAndStacksInfo, error)

GetConfigAndStacksInfo processes the CLI config and stacks. Exported for use by command packages (e.g., terraform package).

func GetIdentityFromFlags added in v1.197.0

func GetIdentityFromFlags(cmd *cobra.Command, osArgs []string) string

GetIdentityFromFlags retrieves the identity value from command-line flags and environment variables. This function handles the Cobra NoOptDefVal quirk where --identity <value> with positional args can be misinterpreted as --identity (without value).

Returns:

  • identity value if explicitly provided
  • cfg.IdentityFlagSelectValue if --identity was used without a value (interactive selection)
  • cfg.IdentityFlagDisabledValue if --identity=false (authentication disabled)
  • value from ATMOS_IDENTITY env var if flag not provided
  • empty string if no identity specified anywhere

Usage:

identity := GetIdentityFromFlags(cmd, os.Args)
if identity == cfg.IdentityFlagSelectValue {
    // Show interactive selector
} else if identity == cfg.IdentityFlagDisabledValue {
    // Skip authentication
} else if identity != "" {
    // Use explicit identity
}

func SetupLogger added in v1.198.0

func SetupLogger(atmosConfig *schema.AtmosConfiguration)

SetupLogger configures the global logger based on the provided Atmos configuration.

func StackFlagCompletion added in v1.202.0

func StackFlagCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)

StackFlagCompletion provides shell completion for the --stack flag. If a component was provided as the first positional argument, it filters stacks to only those containing that component.

Types

type AtmosValidateOption added in v1.97.0

type AtmosValidateOption func(*ValidateConfig)

func WithStackValidation added in v1.97.0

func WithStackValidation(check bool) AtmosValidateOption

type ComponentResolver added in v1.201.0

type ComponentResolver interface {
	// ResolveComponentPath resolves a path-based component reference to its component name.
	ResolveComponentPath(component, stack string) (string, error)
}

ComponentResolver handles resolving component paths to component names.

type DefaultComponentResolver added in v1.201.0

type DefaultComponentResolver struct{}

DefaultComponentResolver implements ComponentResolver using the standard Atmos config.

func (*DefaultComponentResolver) ResolveComponentPath added in v1.201.0

func (r *DefaultComponentResolver) ResolveComponentPath(component, stack string) (string, error)

ResolveComponentPath resolves a path-based component reference using Atmos configuration.

type ExampleContent added in v1.162.0

type ExampleContent struct {
	Content    string
	Suggestion string
}

type SeparatedArgs added in v1.197.0

type SeparatedArgs struct {
	// AfterDash contains all arguments after the -- separator.
	// These are typically passed through to a subprocess or external command.
	// Returns nil if no -- separator was found.
	AfterDash []string

	// ArgsLenAtDash is the position where -- was found in the original args.
	// Returns -1 if no -- separator was present.
	// This is useful for validation or error messages.
	ArgsLenAtDash int
}

SeparatedArgs represents parsed arguments split by the -- separator. This follows the kubectl pattern where flags before -- are parsed by Cobra, and arguments after -- are passed through to a subprocess or subcommand.

Example: atmos auth exec --identity admin -- terraform apply -auto-approve

BeforeDash: ["--identity", "admin"]  (parsed by Cobra into flags)
AfterDash:  ["terraform", "apply", "-auto-approve"]  (passed to subprocess)

func ParseSeparatedArgs added in v1.197.0

func ParseSeparatedArgs(cmd *cobra.Command, args []string) *SeparatedArgs

ParseSeparatedArgs extracts arguments after the -- separator using Cobra's built-in ArgsLenAtDash(). This is the standard pattern used by kubectl and other tools that need to separate their own flags from arguments passed to a subprocess.

Usage:

func myCommandRun(cmd *cobra.Command, args []string) error {
    separated := ParseSeparatedArgs(cmd, args)

    // Cobra has already parsed your command's flags
    myFlag, _ := cmd.Flags().GetString("my-flag")

    // Get arguments to pass to subprocess
    if len(separated.AfterDash) == 0 {
        return fmt.Errorf("no command specified after --")
    }

    // Execute subprocess with separated.AfterDash
    return executeCommand(separated.AfterDash)
}

Command setup:

cmd := &cobra.Command{
    Use: "mycommand [flags] -- COMMAND [args...]",
    // NOTE: Do NOT use DisableFlagParsing
    RunE: myCommandRun,
}
cmd.Flags().String("my-flag", "", "My command's flag")

The key insight is that Cobra's normal flag parsing works correctly with --:

  • Flags before -- are parsed by Cobra
  • Arguments after -- are available via ArgsLenAtDash()
  • No custom parsing required

func (*SeparatedArgs) CommandArgs added in v1.197.0

func (s *SeparatedArgs) CommandArgs() []string

CommandArgs returns the arguments after --, or nil if no separator was found. This is a convenience method equivalent to accessing AfterDash directly.

func (*SeparatedArgs) HasSeparator added in v1.197.0

func (s *SeparatedArgs) HasSeparator() bool

HasSeparator returns true if the -- separator was present in the arguments.

type SeparatedCommandArgs added in v1.197.0

type SeparatedCommandArgs struct {
	// BeforeSeparator contains arguments before the -- marker.
	// These are processed by Atmos (stack, component, identity, etc.)
	BeforeSeparator []string

	// AfterSeparator contains arguments after the -- marker.
	// These are passed through to the native command (terraform, helmfile, subprocess, etc.)
	AfterSeparator []string

	// SeparatorIndex is the position of -- in os.Args, or -1 if not found.
	SeparatorIndex int

	// HasSeparator returns true if -- was found in the arguments.
	HasSeparator bool
}

SeparatedCommandArgs represents arguments split by the -- separator. This pattern is used across multiple Atmos commands (terraform, helmfile, packer, custom commands, auth exec/shell) to separate Atmos-specific flags from native command flags.

Pattern:

atmos <command> <atmos-flags> -- <native-flags>

Examples:

atmos terraform plan myapp -s dev -- -var foo=bar
atmos auth exec --identity admin -- terraform apply -auto-approve
atmos helmfile apply -s prod -- --set image.tag=v1.0

func ExtractSeparatedArgs added in v1.197.0

func ExtractSeparatedArgs(cmd *cobra.Command, args []string, osArgs []string) *SeparatedCommandArgs

ExtractSeparatedArgs extracts arguments before and after the -- separator. This is the unified implementation used by all Atmos commands that support the -- end-of-args pattern.

Why we need os.Args:

When DisableFlagParsing=true, Cobra consumes the -- separator and we lose
information about where it was. We need os.Args to find the original position
and extract trailing args correctly.

Parameters:

  • cmd: The Cobra command (may have DisableFlagParsing=true)
  • args: The args passed to RunE (after Cobra processing)
  • osArgs: Usually os.Args - the raw command line arguments

Usage:

func myCommandRun(cmd *cobra.Command, args []string) error {
    separated := ExtractSeparatedArgs(cmd, args, os.Args)

    if separated.HasSeparator {
        // Process Atmos flags from separated.BeforeSeparator
        // Pass native flags from separated.AfterSeparator
    }
}

func (*SeparatedCommandArgs) GetAfterSeparator added in v1.197.0

func (s *SeparatedCommandArgs) GetAfterSeparator() []string

GetAfterSeparator returns arguments after --, or nil if no separator. This is a convenience method for commands that only care about trailing args.

func (*SeparatedCommandArgs) GetAfterSeparatorAsQuotedString added in v1.197.0

func (s *SeparatedCommandArgs) GetAfterSeparatorAsQuotedString() (string, error)

GetAfterSeparatorAsQuotedString returns arguments after -- as a shell-quoted string. Each argument is properly quoted for shell safety, preserving whitespace and special characters. Returns empty string if no separator or no trailing args.

This is the CORRECT method to use for custom commands that pass trailing args to shell execution, as it ensures argument boundaries and whitespace are preserved when the shell re-parses the string.

Example:

args after --: ["echo", "hello  world"]  (note: two spaces)
GetAfterSeparatorAsString():       "echo hello  world"  (when shell re-parses: loses boundary!)
GetAfterSeparatorAsQuotedString(): "echo 'hello  world'" (shell correctly preserves!)

func (*SeparatedCommandArgs) GetAfterSeparatorAsString added in v1.197.0

func (s *SeparatedCommandArgs) GetAfterSeparatorAsString() string

GetAfterSeparatorAsString returns arguments after -- joined as a space-separated string. Returns empty string if no separator or no trailing args.

WARNING: This method uses plain strings.Join() which does NOT preserve argument boundaries or whitespace when the result is later parsed by a shell. For shell-safe quoting that preserves whitespace and special characters, use GetAfterSeparatorAsQuotedString() instead.

This method exists for backwards compatibility and non-shell use cases.

func (*SeparatedCommandArgs) GetBeforeSeparator added in v1.197.0

func (s *SeparatedCommandArgs) GetBeforeSeparator() []string

GetBeforeSeparator returns arguments before --, or all args if no separator.

type ValidateConfig added in v1.97.0

type ValidateConfig struct {
	CheckStack bool
}

ValidateConfig holds configuration options for Atmos validation. CheckStack determines whether stack configuration validation should be performed.

Directories

Path Synopsis
shared
Package shared provides utilities shared between terraform and its subpackages.
Package shared provides utilities shared between terraform and its subpackages.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL