-
-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Handle TF_DATA_DIR and Error Logging for !terraform.output #1037
Changes from all commits
09c61dc
2368e6e
0c86e59
83f6e2c
a9e74ff
317ff02
835ffa1
2c02448
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,6 +3,7 @@ | |||||||||||
import ( | ||||||||||||
"context" | ||||||||||||
"fmt" | ||||||||||||
"os" | ||||||||||||
"path/filepath" | ||||||||||||
"strings" | ||||||||||||
"sync" | ||||||||||||
|
@@ -13,6 +14,7 @@ | |||||||||||
|
||||||||||||
"github.com/charmbracelet/bubbles/spinner" | ||||||||||||
tea "github.com/charmbracelet/bubbletea" | ||||||||||||
l "github.com/charmbracelet/log" | ||||||||||||
cfg "github.com/cloudposse/atmos/pkg/config" | ||||||||||||
"github.com/cloudposse/atmos/pkg/schema" | ||||||||||||
"github.com/cloudposse/atmos/pkg/ui/theme" | ||||||||||||
|
@@ -78,8 +80,7 @@ | |||||||||||
if atmosConfig.Components.Terraform.AutoGenerateBackendFile { | ||||||||||||
backendFileName := filepath.Join(componentPath, "backend.tf.json") | ||||||||||||
|
||||||||||||
u.LogDebug("\nWriting the backend config to file:") | ||||||||||||
u.LogDebug(backendFileName) | ||||||||||||
l.Debug("Writing the backend config to file:", "file", backendFileName) | ||||||||||||
|
||||||||||||
backendTypeSection, ok := sections["backend_type"].(string) | ||||||||||||
if !ok { | ||||||||||||
|
@@ -101,8 +102,7 @@ | |||||||||||
return nil, err | ||||||||||||
} | ||||||||||||
|
||||||||||||
u.LogDebug("\nWrote the backend config to file:") | ||||||||||||
u.LogDebug(backendFileName) | ||||||||||||
l.Debug("Wrote the backend config to file:", "file", backendFileName) | ||||||||||||
} | ||||||||||||
|
||||||||||||
// Generate `providers_override.tf.json` file if the `providers` section is configured | ||||||||||||
|
@@ -111,17 +111,15 @@ | |||||||||||
if ok && len(providersSection) > 0 { | ||||||||||||
providerOverrideFileName := filepath.Join(componentPath, "providers_override.tf.json") | ||||||||||||
|
||||||||||||
u.LogDebug("\nWriting the provider overrides to file:") | ||||||||||||
u.LogDebug(providerOverrideFileName) | ||||||||||||
l.Debug("Writing the provider overrides to file:", "file", providerOverrideFileName) | ||||||||||||
|
||||||||||||
providerOverrides := generateComponentProviderOverrides(providersSection) | ||||||||||||
err = u.WriteToFileAsJSON(providerOverrideFileName, providerOverrides, 0o644) | ||||||||||||
if err != nil { | ||||||||||||
return nil, err | ||||||||||||
} | ||||||||||||
|
||||||||||||
u.LogDebug("\nWrote the provider overrides to file:") | ||||||||||||
u.LogDebug(providerOverrideFileName) | ||||||||||||
l.Debug("Wrote the provider overrides to file:", "file", providerOverrideFileName) | ||||||||||||
} | ||||||||||||
|
||||||||||||
// Initialize Terraform/OpenTofu | ||||||||||||
|
@@ -137,7 +135,7 @@ | |||||||||||
// Before executing `terraform init`, delete the `.terraform/environment` file from the component directory | ||||||||||||
cleanTerraformWorkspace(*atmosConfig, componentPath) | ||||||||||||
|
||||||||||||
u.LogDebug(fmt.Sprintf("\nExecuting 'terraform init %s -s %s'", component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Executing 'terraform init %s -s %s'", component, stack)) | ||||||||||||
|
||||||||||||
var initOptions []tfexec.InitOption | ||||||||||||
initOptions = append(initOptions, tfexec.Upgrade(false)) | ||||||||||||
|
@@ -149,50 +147,50 @@ | |||||||||||
if err != nil { | ||||||||||||
return nil, err | ||||||||||||
} | ||||||||||||
u.LogDebug(fmt.Sprintf("\nExecuted 'terraform init %s -s %s'", component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Executed 'terraform init %s -s %s'", component, stack)) | ||||||||||||
|
||||||||||||
// Terraform workspace | ||||||||||||
u.LogDebug(fmt.Sprintf("\nExecuting 'terraform workspace new %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Executing 'terraform workspace new %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
err = tf.WorkspaceNew(ctx, terraformWorkspace) | ||||||||||||
if err != nil { | ||||||||||||
u.LogDebug(fmt.Sprintf("\nWorkspace exists. Executing 'terraform workspace select %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Workspace exists. Executing 'terraform workspace select %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
err = tf.WorkspaceSelect(ctx, terraformWorkspace) | ||||||||||||
if err != nil { | ||||||||||||
return nil, err | ||||||||||||
} | ||||||||||||
u.LogDebug(fmt.Sprintf("\nExecuted 'terraform workspace select %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Executed 'terraform workspace select %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
} else { | ||||||||||||
u.LogDebug(fmt.Sprintf("\nExecuted 'terraform workspace new %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Executed 'terraform workspace new %s' for component '%s' in stack '%s'", terraformWorkspace, component, stack)) | ||||||||||||
} | ||||||||||||
|
||||||||||||
// Terraform output | ||||||||||||
u.LogDebug(fmt.Sprintf("\nExecuting 'terraform output %s -s %s'", component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Executing 'terraform output %s -s %s'", component, stack)) | ||||||||||||
outputMeta, err := tf.Output(ctx) | ||||||||||||
if err != nil { | ||||||||||||
return nil, err | ||||||||||||
} | ||||||||||||
u.LogDebug(fmt.Sprintf("\nExecuted 'terraform output %s -s %s'", component, stack)) | ||||||||||||
l.Debug(fmt.Sprintf("Executed 'terraform output %s -s %s'", component, stack)) | ||||||||||||
|
||||||||||||
if atmosConfig.Logs.Level == u.LogLevelTrace { | ||||||||||||
y, err2 := u.ConvertToYAML(outputMeta) | ||||||||||||
if err2 != nil { | ||||||||||||
u.LogError(err2) | ||||||||||||
l.Error("Error converting output to YAML:", "error", err2) | ||||||||||||
} else { | ||||||||||||
u.LogDebug(fmt.Sprintf("\nResult of 'terraform output %s -s %s' before processing it:\n%s\n", component, stack, y)) | ||||||||||||
l.Debug(fmt.Sprintf("Result of 'terraform output %s -s %s' before processing it:\n%s\n", component, stack, y)) | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
outputProcessed = lo.MapEntries(outputMeta, func(k string, v tfexec.OutputMeta) (string, any) { | ||||||||||||
s := string(v.Value) | ||||||||||||
u.LogDebug(fmt.Sprintf("Converting the variable '%s' with the value\n%s\nfrom JSON to 'Go' data type\n", k, s)) | ||||||||||||
l.Debug(fmt.Sprintf("Converting the variable '%s' with the value\n%s\nfrom JSON to 'Go' data type\n", k, s)) | ||||||||||||
|
||||||||||||
d, err2 := u.ConvertFromJSON(s) | ||||||||||||
|
||||||||||||
if err2 != nil { | ||||||||||||
u.LogError(fmt.Errorf("failed to convert output '%s': %w", k, err2)) | ||||||||||||
l.Error(fmt.Sprintf("failed to convert output '%s'", k), "error", err2) | ||||||||||||
return k, nil | ||||||||||||
} else { | ||||||||||||
u.LogDebug(fmt.Sprintf("Converted the variable '%s' with the value\n%s\nfrom JSON to 'Go' data type\nResult: %v\n", k, s, d)) | ||||||||||||
l.Debug(fmt.Sprintf("Converted the variable '%s' with the value\n%s\nfrom JSON to 'Go' data type\nResult: %v\n", k, s, d)) | ||||||||||||
} | ||||||||||||
|
||||||||||||
return k, d | ||||||||||||
|
@@ -202,7 +200,7 @@ | |||||||||||
if componentAbstract { | ||||||||||||
componentStatus = "abstract" | ||||||||||||
} | ||||||||||||
u.LogDebug(fmt.Sprintf("\nNot executing 'terraform output %s -s %s' because the component is %s", component, stack, componentStatus)) | ||||||||||||
l.Debug(fmt.Sprintf("Not executing 'terraform output %s -s %s' because the component is %s", component, stack, componentStatus)) | ||||||||||||
} | ||||||||||||
|
||||||||||||
return outputProcessed, nil | ||||||||||||
|
@@ -222,7 +220,7 @@ | |||||||||||
if !skipCache { | ||||||||||||
cachedOutputs, found := terraformOutputsCache.Load(stackSlug) | ||||||||||||
if found && cachedOutputs != nil { | ||||||||||||
u.LogDebug(fmt.Sprintf("Found the result of the Atmos YAML function '!terraform.output %s %s %s' in the cache", component, stack, output)) | ||||||||||||
l.Debug("Found the result of the Atmos YAML function '!terraform.output %s %s %s' in the cache", component, stack, output) | ||||||||||||
return getTerraformOutputVariable(atmosConfig, component, stack, cachedOutputs.(map[string]any), output) | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
@@ -235,7 +233,7 @@ | |||||||||||
if !CheckTTYSupport() { | ||||||||||||
// set tea.WithInput(nil) workaround tea program not run on not TTY mod issue | ||||||||||||
opts = []tea.ProgramOption{tea.WithoutRenderer(), tea.WithInput(nil)} | ||||||||||||
u.LogTrace("No TTY detected. Falling back to basic output. This can happen when no terminal is attached or when commands are pipelined.") | ||||||||||||
l.Trace("No TTY detected. Falling back to basic output. This can happen when no terminal is attached or when commands are pipelined.") | ||||||||||||
Check failure on line 236 in internal/exec/terraform_outputs.go
|
||||||||||||
fmt.Println(message) | ||||||||||||
} | ||||||||||||
|
||||||||||||
|
@@ -249,7 +247,7 @@ | |||||||||||
if _, err := p.Run(); err != nil { | ||||||||||||
// If there's any error running the spinner, just print the message | ||||||||||||
fmt.Println(message) | ||||||||||||
u.LogError(fmt.Errorf("failed to run spinner: %w", err)) | ||||||||||||
l.Error("Failed to run spinner:", "error", err) | ||||||||||||
} | ||||||||||||
close(spinnerDone) | ||||||||||||
}() | ||||||||||||
|
@@ -259,7 +257,8 @@ | |||||||||||
p.Quit() | ||||||||||||
<-spinnerDone | ||||||||||||
fmt.Printf("\r✗ %s\n", message) | ||||||||||||
u.LogErrorAndExit(err) | ||||||||||||
l.Error("Failed to describe the component", "component", component, "stack", stack, "error", err) | ||||||||||||
os.Exit(1) | ||||||||||||
Comment on lines
+260
to
+261
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
} | ||||||||||||
|
||||||||||||
// Check if the component in the stack is configured with the 'static' remote state backend, in which case get the | ||||||||||||
|
@@ -269,7 +268,8 @@ | |||||||||||
p.Quit() | ||||||||||||
<-spinnerDone | ||||||||||||
fmt.Printf("\r✗ %s\n", message) | ||||||||||||
u.LogErrorAndExit(err) | ||||||||||||
l.Error("Failed to get remote state backend static type outputs", "error", err) | ||||||||||||
os.Exit(1) | ||||||||||||
Comment on lines
+271
to
+272
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
} | ||||||||||||
|
||||||||||||
var result any | ||||||||||||
|
@@ -284,7 +284,8 @@ | |||||||||||
p.Quit() | ||||||||||||
<-spinnerDone | ||||||||||||
fmt.Printf("\r✗ %s\n", message) | ||||||||||||
u.LogErrorAndExit(err) | ||||||||||||
l.Error("Failed to execute terraform output", "component", component, "stack", stack, "error", err) | ||||||||||||
os.Exit(1) | ||||||||||||
Comment on lines
+287
to
+288
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
} | ||||||||||||
|
||||||||||||
// Cache the result | ||||||||||||
|
@@ -314,12 +315,8 @@ | |||||||||||
|
||||||||||||
res, err := u.EvaluateYqExpression(atmosConfig, outputs, val) | ||||||||||||
if err != nil { | ||||||||||||
u.LogErrorAndExit(fmt.Errorf("error evaluating terrform output '%s' for the component '%s' in the stack '%s':\n%v", | ||||||||||||
output, | ||||||||||||
component, | ||||||||||||
stack, | ||||||||||||
err, | ||||||||||||
)) | ||||||||||||
l.Error("Error evaluating terraform output", "output", output, "component", component, "stack", stack, "error", err) | ||||||||||||
u.Exit(1) | ||||||||||||
Check failure on line 319 in internal/exec/terraform_outputs.go
|
||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix undefined The static analysis indicates that Replace with the standard -u.Exit(1)
+os.Exit(1) 📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: Build (macos-latest, macos)[failure] 319-319: 🪛 GitHub Check: Build (ubuntu-latest, linux)[failure] 319-319:
Comment on lines
+318
to
+319
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
} | ||||||||||||
|
||||||||||||
return res | ||||||||||||
|
@@ -339,12 +336,8 @@ | |||||||||||
|
||||||||||||
res, err := u.EvaluateYqExpression(atmosConfig, remoteStateSection, val) | ||||||||||||
if err != nil { | ||||||||||||
u.LogErrorAndExit(fmt.Errorf("error evaluating the 'static' remote state backend output '%s' for the component '%s' in the stack '%s':\n%v", | ||||||||||||
output, | ||||||||||||
component, | ||||||||||||
stack, | ||||||||||||
err, | ||||||||||||
)) | ||||||||||||
l.Error("Error evaluating the 'static' remote state backend output", "output", output, "component", component, "stack", stack, "error", err) | ||||||||||||
os.Exit(1) | ||||||||||||
Comment on lines
+339
to
+340
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
} | ||||||||||||
|
||||||||||||
return res | ||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix undefined
l.Trace
method.The static analysis indicates that
l.Trace
is undefined.Replace with the correct logging level:
📝 Committable suggestion
🧰 Tools
🪛 GitHub Check: Build (macos-latest, macos)
[failure] 236-236:
undefined: l.Trace
🪛 GitHub Check: Build (ubuntu-latest, linux)
[failure] 236-236:
undefined: l.Trace