-
Notifications
You must be signed in to change notification settings - Fork 524
/
configure.go
310 lines (254 loc) 路 8.12 KB
/
configure.go
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
package main
import (
"fmt"
"strconv"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/infracost/infracost/internal/config"
"github.com/infracost/infracost/internal/logging"
"github.com/infracost/infracost/internal/ui"
)
var supportedConfigureKeys = map[string]struct{}{
"api_key": {},
"currency": {},
"pricing_api_endpoint": {},
"enable_dashboard": {},
"enable_cloud": {},
"disable_hcl": {},
"tls_insecure_skip_verify": {},
"tls_ca_cert_file": {},
}
func configureCmd(ctx *config.RunContext) *cobra.Command {
cmd := &cobra.Command{
Use: "configure",
Short: "Display or change global configuration",
Long: supportedConfigureSettingsOutput("Display or change global configuration"),
RunE: func(cmd *cobra.Command, args []string) error {
// Show the help
return cmd.Help()
},
}
cmd.AddCommand(configureSetCmd(ctx), configureGetCmd(ctx))
return cmd
}
func configureSetCmd(ctx *config.RunContext) *cobra.Command {
cmd := &cobra.Command{
Use: "set <key> <value>",
Short: "Set global configuration",
Long: supportedConfigureSettingsOutput("Set global configuration"),
Example: ` Set your Infracost API key:
infracost configure set api_key MY_API_KEY
Set your Cloud Pricing API endpoint:
infracost configure set pricing_api_endpoint https://cloud-pricing-api
Set your preferred currency code (ISO 4217):
infracost configure set currency EUR
`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 2 {
return errors.New("Too many arguments")
}
if len(args) < 2 {
return errors.New("You must specify a key and a value")
}
if !isValidConfigureKey(args[0]) {
return fmt.Errorf("Invalid key, valid keys are: %s", strings.Join(validConfigureKeys(), ", "))
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
key := args[0]
value := args[1]
saveCredentials := false
saveConfiguration := false
switch key {
case "pricing_api_endpoint":
ctx.Config.Credentials.PricingAPIEndpoint = value
saveCredentials = true
case "api_key":
ctx.Config.Credentials.APIKey = value
saveCredentials = true
case "tls_insecure_skip_verify":
if value == "" {
ctx.Config.Configuration.TLSInsecureSkipVerify = nil
} else {
b, err := strconv.ParseBool(value)
if err != nil {
return errors.New("Invalid value, must be true or false")
}
ctx.Config.Configuration.TLSInsecureSkipVerify = &b
}
saveConfiguration = true
case "tls_ca_cert_file":
ctx.Config.Configuration.TLSCACertFile = value
saveConfiguration = true
case "currency":
ctx.Config.Configuration.Currency = value
saveConfiguration = true
case "disable_hcl":
b, err := strconv.ParseBool(value)
if err != nil {
return errors.New("Invalid value, must be true or false")
}
ctx.Config.Configuration.DisableHCLParsing = &b
saveConfiguration = true
case "enable_dashboard":
b, err := strconv.ParseBool(value)
if err != nil {
return errors.New("Invalid value, must be true or false")
}
if b && ctx.Config.IsSelfHosted() {
return errors.New("The dashboard is part of Infracost's hosted services. Contact hello@infracost.io for help")
}
ctx.Config.Configuration.EnableDashboard = &b
saveConfiguration = true
case "enable_cloud":
b, err := strconv.ParseBool(value)
if err != nil {
return errors.New("Invalid value, must be true or false")
}
if b && ctx.Config.IsSelfHosted() {
return errors.New("Infracost Cloud is part of Infracost's hosted services. Contact hello@infracost.io for help")
}
ctx.Config.Configuration.EnableCloud = &b
saveConfiguration = true
}
if saveCredentials {
err := ctx.Config.Credentials.Save()
if err != nil {
return err
}
}
if saveConfiguration {
err := ctx.Config.Configuration.Save()
if err != nil {
return err
}
}
return nil
},
}
return cmd
}
func configureGetCmd(ctx *config.RunContext) *cobra.Command {
cmd := &cobra.Command{
Use: "get <key>",
Short: "Get global configuration",
Long: supportedConfigureSettingsOutput("Get global configuration"),
Example: ` Get your saved Infracost API key:
infracost configure get api_key
Get your saved Cloud Pricing API endpoint:
infracost configure get pricing_api_endpoint
Get your preferred currency:
infracost configure get currency
`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 1 {
return errors.New("Too many arguments")
}
if len(args) < 1 {
return errors.New("You must specify a key")
}
if !isValidConfigureKey(args[0]) {
return fmt.Errorf("Invalid key, valid keys are: %s", strings.Join(validConfigureKeys(), ", "))
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
key := args[0]
var value string
switch key {
case "pricing_api_endpoint":
value = ctx.Config.Credentials.PricingAPIEndpoint
if value == "" {
msg := fmt.Sprintf("No Cloud Pricing API endpoint in your saved config (%s).\nSet an API key using %s.",
config.CredentialsFilePath(),
ui.PrimaryString("infracost configure set pricing_api_endpoint https://cloud-pricing-api"),
)
logging.Logger.Warn().Msg(msg)
}
case "api_key":
value = ctx.Config.Credentials.APIKey
if value == "" {
msg := fmt.Sprintf("No API key in your saved config (%s).\nSet an API key using %s.",
config.CredentialsFilePath(),
ui.PrimaryString("infracost configure set api_key MY_API_KEY"),
)
logging.Logger.Warn().Msg(msg)
}
case "currency":
value = ctx.Config.Configuration.Currency
if value == "" {
msg := fmt.Sprintf("No currency in your saved config (%s), defaulting to USD.\nSet a currency using %s.",
config.ConfigurationFilePath(),
ui.PrimaryString("infracost configure set currency CURRENCY"),
)
logging.Logger.Warn().Msg(msg)
}
case "tls_insecure_skip_verify":
if ctx.Config.Configuration.TLSInsecureSkipVerify == nil {
value = ""
} else {
value = fmt.Sprintf("%t", *ctx.Config.Configuration.TLSInsecureSkipVerify)
}
if value == "" {
msg := fmt.Sprintf("Skipping TLS verification is not set in your saved config (%s).\nSet it using %s.",
config.ConfigurationFilePath(),
ui.PrimaryString("infracost configure set tls_insecure_skip_verify true"),
)
logging.Logger.Warn().Msg(msg)
}
case "tls_ca_cert_file":
value = ctx.Config.Configuration.TLSCACertFile
if value == "" {
msg := fmt.Sprintf("No CA cert file in your saved config (%s).\nSet a CA certificate using %s.",
config.ConfigurationFilePath(),
ui.PrimaryString("infracost configure set tls_ca_cert_file /path/to/ca.crt"),
)
logging.Logger.Warn().Msg(msg)
}
case "enable_dashboard":
if ctx.Config.Configuration.EnableDashboard == nil {
value = ""
} else {
value = strconv.FormatBool(*ctx.Config.Configuration.EnableDashboard)
}
case "enable_cloud":
if ctx.Config.Configuration.EnableCloud == nil {
value = ""
} else {
value = strconv.FormatBool(*ctx.Config.Configuration.EnableCloud)
}
}
if value != "" {
fmt.Println(value)
}
return nil
},
}
return cmd
}
func isValidConfigureKey(key string) bool {
_, ok := supportedConfigureKeys[key]
return ok
}
func supportedConfigureSettingsOutput(description string) string {
settings := `
Supported settings:
- api_key: Infracost API key
- pricing_api_endpoint: endpoint of the Cloud Pricing API
- currency: convert output from USD to your preferred currency
- tls_insecure_skip_verify: skip TLS certificate checks for a self-hosted Cloud Pricing API
- tls_ca_cert_file: verify certificate of a self-hosted Cloud Pricing API using this CA certificate
`
return fmt.Sprintf("%s.\n%s", description, settings)
}
func validConfigureKeys() []string {
keys := make([]string, len(supportedConfigureKeys))
i := 0
for k := range supportedConfigureKeys {
keys[i] = k
i++
}
return keys
}