Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
f83367d
feat: Add automatic backend provisioning with S3 support
osterman Nov 20, 2025
e972b3e
docs: Document provision block configuration hierarchy
osterman Nov 20, 2025
ead68a1
fix: Address CodeRabbit review feedback for backend provisioning
osterman Nov 20, 2025
70f808f
test: Add comprehensive test coverage for backend provisioning
osterman Nov 21, 2025
d7200b9
test: Add interface-based mocking for S3 provisioner
osterman Nov 21, 2025
461e596
test: Regenerate snapshots for provision command
osterman Nov 21, 2025
79b874e
Merge branch 'main' into osterman/auto-backend-provision
osterman Nov 22, 2025
074bfe2
Merge branch 'main' into osterman/auto-backend-provision
osterman Nov 23, 2025
26aa9de
fix: Remove BucketKeyEnabled from AES-256 encryption config
osterman Nov 23, 2025
9a6e9f1
docs: Add use_lockfile to S3 backend provisioning examples
osterman Nov 23, 2025
d1067cb
docs: Streamline blog post and refocus on Terraform compatibility
osterman Nov 23, 2025
80aaeb4
docs: Reframe blog post section as solving Terraform bootstrap problem
osterman Nov 23, 2025
ff06678
docs: Remove unnecessary step to disable automatic provisioning
osterman Nov 23, 2025
61eced2
feat: Add CRUD operations for backend provisioning
osterman Nov 24, 2025
21f318e
refactor: Eliminate code duplication in backend commands
osterman Nov 24, 2025
a84289e
docs: Update backend provisioning command documentation
osterman Nov 24, 2025
f1770dd
docs: Update backend provisioning docs to emphasize Terraform compati…
osterman Nov 24, 2025
8b4209e
docs: Fix documentation links and restructure provision command docs
osterman Nov 24, 2025
d963787
Merge remote-tracking branch 'origin/main' into osterman/auto-backend…
osterman Nov 24, 2025
3ee21c7
test: update snapshots for provision command move to terraform subcom…
osterman Nov 25, 2025
dc7a632
test: increase coverage for backend provision and TUI templates
osterman Nov 26, 2025
60ce6f0
fix: resolve lintroller errors for performance tracking and test isol…
osterman Nov 26, 2025
a3bfde7
refactor: eliminate code duplication and reduce test complexity
osterman Nov 26, 2025
ca8b98c
docs: fix backend_type placement in YAML examples and godot linter vi…
osterman Nov 26, 2025
16e8d85
fix(ci): configure git authentication for golangci-lint custom build
osterman Nov 26, 2025
ab18ce0
refactor: simplify backend commands by removing provision namespace
osterman Nov 26, 2025
843eeb1
refactor: consolidate provisioner packages and adopt CRUD naming
osterman Nov 26, 2025
5d832a6
feat: add component-level auth support for backend commands
osterman Nov 26, 2025
98f6063
docs: add component-level auth documentation for backend commands
osterman Nov 26, 2025
1a0f8af
test: regenerate snapshot for atmos terraform help
osterman Nov 27, 2025
607a918
Merge branch 'main' into osterman/auto-backend-provision
osterman Nov 27, 2025
57c7ef9
fix: enforce force flag requirement in DeleteS3Backend
osterman Nov 27, 2025
e48531e
refactor: improve DeleteS3Backend function structure and test coverage
osterman Nov 27, 2025
45fa45a
test: increase cmd/terraform/backend test coverage to 75%
osterman Nov 27, 2025
0d40d27
docs: refactor backend documentation into 3 focused pages
osterman Nov 28, 2025
627edd1
docs: convert backend lists to Terraform/OpenTofu tabs
osterman Nov 28, 2025
a3a2b95
docs: update backend docs to use native S3 locking and lead with Atmo…
osterman Nov 28, 2025
a61b9bb
docs: fix S3 bucket naming to follow null label format
osterman Nov 29, 2025
058109f
Merge branch 'main' into osterman/auto-backend-provision
osterman Nov 29, 2025
b378ab0
fix: remove unused Screengrab import and add period to comment
osterman Nov 29, 2025
557b83d
docs: replace :::note Purpose with <Intro> component
osterman Nov 29, 2025
ea9c010
docs: add screengrab for atmos terraform backend command
osterman Nov 29, 2025
054ac1f
docs: move Backend Provisioning link from bullet to CTA
osterman Nov 30, 2025
bf8b477
docs: add tip about committing backend.tf.json
osterman Nov 30, 2025
81c03a4
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 1, 2025
8305606
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 5, 2025
7b3eeb3
docs: reorganize backend documentation with MDX partials
osterman Dec 5, 2025
1c1f192
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 6, 2025
f01e73c
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 7, 2025
7c47fc9
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 8, 2025
b457df3
refactor: consolidate AWS config error to ErrLoadAWSConfig
osterman Dec 8, 2025
f089e6f
test: add tests for help printer empty lines handling
osterman Dec 8, 2025
bb38566
Merge remote-tracking branch 'origin/main' into osterman/auto-backend…
osterman Dec 9, 2025
06c050f
test: add init() verification tests for backend commands
osterman Dec 9, 2025
72371af
docs: fix hard tab in auth-context-multi-identity.md line 559
osterman Dec 9, 2025
5a18e15
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 9, 2025
a9522f0
refactor: remove duplicate ErrLoadAwsConfig sentinel error
osterman Dec 9, 2025
9cad4f8
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 10, 2025
9670bec
Merge branch 'main' into osterman/auto-backend-provision
osterman Dec 10, 2025
fab1c6c
Merge branch 'main' into osterman/auto-backend-provision
aknysh Dec 10, 2025
3fe5e75
Merge branch 'main' into osterman/auto-backend-provision
aknysh Dec 12, 2025
c60a3ab
update docs, add tests
aknysh Dec 12, 2025
33a196d
Merge branch 'main' into osterman/auto-backend-provision
aknysh Dec 12, 2025
ff69265
Merge branch 'main' into osterman/auto-backend-provision
aknysh Dec 12, 2025
88f00fe
address comments, update docs, add tests
aknysh Dec 12, 2025
e64b79e
address comments, update docs
aknysh Dec 12, 2025
8e9cb73
fix: Address final CodeRabbit review comments
aknysh Dec 12, 2025
79d49b1
refactor: Use ErrorBuilder for user-facing errors in s3_delete.go
aknysh Dec 12, 2025
9423186
fix: Use params.AtmosConfig for perf.Track in provisioner functions
aknysh Dec 12, 2025
811d4bd
fix: Replace hard tabs with spaces in PRD Go code blocks (MD010)
aknysh Dec 13, 2025
3e43c02
fix: Add missing errors import to PRD Go example
aknysh Dec 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions cmd/provision/provision.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package provision

import (
"errors"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/cloudposse/atmos/cmd/internal"
errUtils "github.com/cloudposse/atmos/errors"
e "github.com/cloudposse/atmos/internal/exec"
"github.com/cloudposse/atmos/pkg/auth"
cfg "github.com/cloudposse/atmos/pkg/config"
"github.com/cloudposse/atmos/pkg/flags"
"github.com/cloudposse/atmos/pkg/flags/global"
"github.com/cloudposse/atmos/pkg/perf"
"github.com/cloudposse/atmos/pkg/provision"
"github.com/cloudposse/atmos/pkg/schema"
)

var (
// AtmosConfigPtr will be set by SetAtmosConfig before command execution.
atmosConfigPtr *schema.AtmosConfiguration
// ProvisionParser handles flag parsing for the provision command.
provisionParser *flags.StandardParser
)

// ProvisionOptions contains parsed flags for the provision command.
type ProvisionOptions struct {
global.Flags
Stack string
Identity string
}

// SetAtmosConfig sets the Atmos configuration for the provision command.
// This is called from root.go after atmosConfig is initialized.
func SetAtmosConfig(config *schema.AtmosConfiguration) {
atmosConfigPtr = config
}

// provisionCmd represents the provision command.
var provisionCmd = &cobra.Command{
Use: "provision backend <component> --stack <stack>",
Short: "Provision backend infrastructure for Terraform state storage",
Long: `Provision backend infrastructure resources using Atmos components. Currently supports provisioning
S3 backends for Terraform state storage with opinionated, secure defaults (versioning, encryption, public access blocking).

This is designed for quick setup of state backends. For production use, consider migrating to the
terraform-aws-tfstate-backend module for more control over bucket configuration.`,
Example: ` atmos provision backend vpc --stack dev
atmos provision backend eks --stack prod`,
Args: cobra.ExactArgs(2),
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
DisableFlagsInUseLine: false,
RunE: func(cmd *cobra.Command, args []string) error {
defer perf.Track(atmosConfigPtr, "provision.RunE")()

if len(args) != 2 {
return errUtils.ErrInvalidArguments
}

provisionerType := args[0]
component := args[1]

// Parse flags using StandardParser with Viper precedence.
v := viper.GetViper()
if err := provisionParser.BindFlagsToViper(cmd, v); err != nil {
return err
}

opts := &ProvisionOptions{
Flags: flags.ParseGlobalFlags(cmd, v),
Stack: v.GetString("stack"),
Identity: v.GetString("identity"),
}

if opts.Stack == "" {
return errUtils.ErrRequiredFlagNotProvided
}

// Load atmos configuration.
atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{
ComponentFromArg: component,
Stack: opts.Stack,
}, false)
if err != nil {
return errors.Join(errUtils.ErrFailedToInitConfig, err)
}

// Create AuthManager from identity flag if provided.
// Use auth.CreateAndAuthenticateManager directly to avoid import cycle with cmd package.
var authManager auth.AuthManager
if opts.Identity != "" {
authManager, err = auth.CreateAndAuthenticateManager(opts.Identity, &atmosConfig.Auth, cfg.IdentityFlagSelectValue)
if err != nil {
return err
}
}

// Create describe component function that calls internal/exec.
describeComponent := func(component, stack string) (map[string]any, error) {
return e.ExecuteDescribeComponent(&e.ExecuteDescribeComponentParams{
Component: component,
Stack: stack,
ProcessTemplates: false,
ProcessYamlFunctions: false,
Skip: nil,
AuthManager: authManager,
})
}

// Execute provision command using pkg/provision.
return provision.Provision(&atmosConfig, provisionerType, component, opts.Stack, describeComponent, authManager)
},
}

func init() {
provisionCmd.DisableFlagParsing = false

// Create parser with provision-specific flags using functional options.
// Note: Stack and Identity are validated in RunE to allow environment variable precedence.
provisionParser = flags.NewStandardParser(
flags.WithStringFlag("stack", "s", "", "Atmos stack"),
flags.WithStringFlag("identity", "i", "", "Specify the target identity to assume. Use without value to interactively select."),
flags.WithEnvVars("stack", "ATMOS_STACK"),
flags.WithEnvVars("identity", "ATMOS_IDENTITY", "IDENTITY"),
)

// Register flags with the command.
provisionParser.RegisterFlags(provisionCmd)

// Set NoOptDefVal for identity flag to enable optional flag value.
// When --identity is used without a value, it will receive cfg.IdentityFlagSelectValue.
identityFlag := provisionCmd.Flags().Lookup("identity")
if identityFlag != nil {
identityFlag.NoOptDefVal = cfg.IdentityFlagSelectValue
}

// Bind flags to Viper for environment variable support and precedence handling.
if err := provisionParser.BindToViper(viper.GetViper()); err != nil {
panic(err)
}

// Register this command with the registry.
// This happens during package initialization via blank import in cmd/root.go.
internal.Register(&ProvisionCommandProvider{})
}

// ProvisionCommandProvider implements the CommandProvider interface.
type ProvisionCommandProvider struct{}

// GetCommand returns the provision command.
func (p *ProvisionCommandProvider) GetCommand() *cobra.Command {
return provisionCmd
}

// GetName returns the command name.
func (p *ProvisionCommandProvider) GetName() string {
return "provision"
}

// GetGroup returns the command group for help organization.
func (p *ProvisionCommandProvider) GetGroup() string {
return "Core Stack Commands"
}

// GetAliases returns a list of command aliases to register.
// The provision command has no aliases.
func (p *ProvisionCommandProvider) GetAliases() []internal.CommandAlias {
return nil
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"github.com/cloudposse/atmos/cmd/internal"
_ "github.com/cloudposse/atmos/cmd/list"
_ "github.com/cloudposse/atmos/cmd/profile"
_ "github.com/cloudposse/atmos/cmd/provision"
themeCmd "github.com/cloudposse/atmos/cmd/theme"
"github.com/cloudposse/atmos/cmd/version"
)
Expand Down
Loading
Loading