mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
plannable import: improve gen config human plan output (#33194)
* renderer: remove hard-coded config gen path * mention config gen file in plan next steps
This commit is contained in:
parent
789e30dfc5
commit
b4d1146f58
@ -55,7 +55,6 @@ func (b *Local) opPlan(
|
||||
}
|
||||
|
||||
if len(op.GenerateConfigOut) > 0 {
|
||||
|
||||
if op.PlanMode != plans.NormalMode {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
@ -192,7 +191,7 @@ func (b *Local) opPlan(
|
||||
}
|
||||
|
||||
// Write out any generated config, before we render the plan.
|
||||
moreDiags = genconfig.MaybeWriteGeneratedConfig(plan, op.GenerateConfigOut)
|
||||
wroteConfig, moreDiags := genconfig.MaybeWriteGeneratedConfig(plan, op.GenerateConfigOut)
|
||||
diags = diags.Append(moreDiags)
|
||||
if moreDiags.HasErrors() {
|
||||
op.ReportResult(runningOp, diags)
|
||||
@ -209,6 +208,10 @@ func (b *Local) opPlan(
|
||||
op.ReportResult(runningOp, diags)
|
||||
|
||||
if !runningOp.PlanEmpty {
|
||||
op.View.PlanNextStep(op.PlanOutPath)
|
||||
if wroteConfig {
|
||||
op.View.PlanNextStep(op.PlanOutPath, op.GenerateConfigOut)
|
||||
} else {
|
||||
op.View.PlanNextStep(op.PlanOutPath, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -469,7 +469,7 @@ func resourceChangeComment(resource jsonplan.ResourceChange, action plans.Action
|
||||
if resource.Change.Importing != nil {
|
||||
buf.WriteString(fmt.Sprintf("[bold] # %s[reset] will be imported", dispAddr))
|
||||
if len(resource.Change.GeneratedConfig) > 0 {
|
||||
buf.WriteString("\n #[reset] (config will be written to generated_config.tf)")
|
||||
buf.WriteString("\n #[reset] (config will be generated)")
|
||||
}
|
||||
printedImported = true
|
||||
break
|
||||
|
@ -178,7 +178,7 @@ Plan: 1 to import, 0 to add, 0 to change, 0 to destroy.
|
||||
Terraform will perform the following actions:
|
||||
|
||||
# test_resource.resource will be imported
|
||||
# (config will be written to generated_config.tf)
|
||||
# (config will be generated)
|
||||
resource "test_resource" "resource" {
|
||||
id = "1D5F5E9E-F2E5-401B-9ED5-692A215AC67E"
|
||||
value = "Hello, World!"
|
||||
|
@ -31,7 +31,7 @@ type Operation interface {
|
||||
|
||||
PlannedChange(change *plans.ResourceInstanceChangeSrc)
|
||||
Plan(plan *plans.Plan, schemas *terraform.Schemas)
|
||||
PlanNextStep(planPath string)
|
||||
PlanNextStep(planPath string, genConfigPath string)
|
||||
|
||||
Diagnostics(diags tfdiags.Diagnostics)
|
||||
}
|
||||
@ -135,12 +135,18 @@ func (v *OperationHuman) PlannedChange(change *plans.ResourceInstanceChangeSrc)
|
||||
|
||||
// PlanNextStep gives the user some next-steps, unless we're running in an
|
||||
// automation tool which is presumed to provide its own UI for further actions.
|
||||
func (v *OperationHuman) PlanNextStep(planPath string) {
|
||||
func (v *OperationHuman) PlanNextStep(planPath string, genConfigPath string) {
|
||||
if v.inAutomation {
|
||||
return
|
||||
}
|
||||
v.view.outputHorizRule()
|
||||
|
||||
if genConfigPath != "" {
|
||||
v.view.streams.Printf(
|
||||
"\n"+strings.TrimSpace(format.WordWrap(planHeaderGenConfig, v.view.outputColumns()))+"\n", genConfigPath,
|
||||
)
|
||||
}
|
||||
|
||||
if planPath == "" {
|
||||
v.view.streams.Print(
|
||||
"\n" + strings.TrimSpace(format.WordWrap(planHeaderNoOutput, v.view.outputColumns())) + "\n",
|
||||
@ -261,7 +267,7 @@ func (v *OperationJSON) PlannedChange(change *plans.ResourceInstanceChangeSrc) {
|
||||
|
||||
// PlanNextStep does nothing for the JSON view as it is a hook for user-facing
|
||||
// output only applicable to human-readable UI.
|
||||
func (v *OperationJSON) PlanNextStep(planPath string) {
|
||||
func (v *OperationJSON) PlanNextStep(planPath string, genConfigPath string) {
|
||||
}
|
||||
|
||||
func (v *OperationJSON) Diagnostics(diags tfdiags.Diagnostics) {
|
||||
@ -288,3 +294,7 @@ Saved the plan to: %s
|
||||
To perform exactly these actions, run the following command to apply:
|
||||
terraform apply %q
|
||||
`
|
||||
|
||||
const planHeaderGenConfig = `
|
||||
Terraform has generated configuration and written it to %s. Please review the configuration and edit it as necessary before adding it to version control.
|
||||
`
|
||||
|
@ -450,7 +450,7 @@ func TestOperation_planNextStep(t *testing.T) {
|
||||
streams, done := terminal.StreamsForTesting(t)
|
||||
v := NewOperation(arguments.ViewHuman, false, NewView(streams))
|
||||
|
||||
v.PlanNextStep(tc.path)
|
||||
v.PlanNextStep(tc.path, "")
|
||||
|
||||
if got := done(t).Stdout(); !strings.Contains(got, tc.want) {
|
||||
t.Errorf("wrong result\ngot: %q\nwant: %q", got, tc.want)
|
||||
@ -465,7 +465,7 @@ func TestOperation_planNextStepInAutomation(t *testing.T) {
|
||||
streams, done := terminal.StreamsForTesting(t)
|
||||
v := NewOperation(arguments.ViewHuman, true, NewView(streams))
|
||||
|
||||
v.PlanNextStep("")
|
||||
v.PlanNextStep("", "")
|
||||
|
||||
if got := done(t).Stdout(); got != "" {
|
||||
t.Errorf("unexpected output\ngot: %q", got)
|
||||
|
@ -21,22 +21,21 @@ func ValidateTargetFile(out string) tfdiags.Diagnostics {
|
||||
return diags
|
||||
}
|
||||
|
||||
func MaybeWriteGeneratedConfig(plan *plans.Plan, out string) tfdiags.Diagnostics {
|
||||
func MaybeWriteGeneratedConfig(plan *plans.Plan, out string) (wroteConfig bool, diags tfdiags.Diagnostics) {
|
||||
if len(out) == 0 {
|
||||
// No specified out file, so don't write anything.
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
diags := ValidateTargetFile(out)
|
||||
diags = ValidateTargetFile(out)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
return false, diags
|
||||
}
|
||||
|
||||
var writer io.Writer
|
||||
|
||||
for _, change := range plan.Changes.Resources {
|
||||
if len(change.GeneratedConfig) > 0 {
|
||||
|
||||
if writer == nil {
|
||||
// Lazily create the generated file, in case we have no
|
||||
// generated config to create.
|
||||
@ -47,14 +46,14 @@ func MaybeWriteGeneratedConfig(plan *plans.Plan, out string) tfdiags.Diagnostics
|
||||
tfdiags.Error,
|
||||
"Failed to create target generated file",
|
||||
fmt.Sprintf("Terraform did not have permission to create the generated file (%s) in the target directory. Please modify permissions over the target directory, and try again.", out)))
|
||||
return diags
|
||||
return false, diags
|
||||
}
|
||||
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Failed to create target generated file",
|
||||
fmt.Sprintf("Terraform could not create the generated file (%s) in the target directory: %v. Depending on the error message, this may be a bug in Terraform itself. If so, please report it!", out, err)))
|
||||
return diags
|
||||
return false, diags
|
||||
}
|
||||
|
||||
header := "# __generated__ by Terraform\n# Please review these resources and move them into your main configuration files.\n"
|
||||
@ -74,8 +73,9 @@ func MaybeWriteGeneratedConfig(plan *plans.Plan, out string) tfdiags.Diagnostics
|
||||
"Failed to save generated config",
|
||||
fmt.Sprintf("Terraform encountered an error while writing generated config: %v. The config for %s must be created manually before applying. Depending on the error message, this may be a bug in Terraform itself. If so, please report it!", err, change.Addr.String())))
|
||||
}
|
||||
wroteConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
return diags
|
||||
return wroteConfig, diags
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user