github.com/databricks/cli@v0.203.0/bundle/deploy/terraform/plan.go (about) 1 package terraform 2 3 import ( 4 "context" 5 "fmt" 6 "path/filepath" 7 8 "github.com/databricks/cli/bundle" 9 "github.com/databricks/cli/libs/cmdio" 10 "github.com/databricks/cli/libs/terraform" 11 "github.com/hashicorp/terraform-exec/tfexec" 12 ) 13 14 type PlanGoal string 15 16 var ( 17 PlanDeploy = PlanGoal("deploy") 18 PlanDestroy = PlanGoal("destroy") 19 ) 20 21 type plan struct { 22 goal PlanGoal 23 } 24 25 func (p *plan) Name() string { 26 return "terraform.Plan" 27 } 28 29 func (p *plan) Apply(ctx context.Context, b *bundle.Bundle) error { 30 tf := b.Terraform 31 if tf == nil { 32 return fmt.Errorf("terraform not initialized") 33 } 34 35 cmdio.LogString(ctx, "Starting plan computation") 36 37 err := tf.Init(ctx, tfexec.Upgrade(true)) 38 if err != nil { 39 return fmt.Errorf("terraform init: %w", err) 40 } 41 42 // Persist computed plan 43 tfDir, err := Dir(b) 44 if err != nil { 45 return err 46 } 47 planPath := filepath.Join(tfDir, "plan") 48 destroy := p.goal == PlanDestroy 49 50 notEmpty, err := tf.Plan(ctx, tfexec.Destroy(destroy), tfexec.Out(planPath)) 51 if err != nil { 52 return err 53 } 54 55 // Set plan in main bundle struct for downstream mutators 56 b.Plan = &terraform.Plan{ 57 Path: planPath, 58 ConfirmApply: b.AutoApprove, 59 IsEmpty: !notEmpty, 60 } 61 62 cmdio.LogString(ctx, fmt.Sprintf("Planning complete and persisted at %s\n", planPath)) 63 return nil 64 } 65 66 // Plan returns a [bundle.Mutator] that runs the equivalent of `terraform plan -out ./plan` 67 // from the bundle's ephemeral working directory for Terraform. 68 func Plan(goal PlanGoal) bundle.Mutator { 69 return &plan{ 70 goal: goal, 71 } 72 }