-
-
Notifications
You must be signed in to change notification settings - Fork 153
Expand file tree
/
Copy pathprovision.go
More file actions
171 lines (143 loc) · 5.74 KB
/
provision.go
File metadata and controls
171 lines (143 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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
}