Skip to content

Commit bcf75fa

Browse files
authored
Merge pull request #1304 from flux-iac/print-plan
Print plan before apply
2 parents d0a4fbb + bde16cc commit bcf75fa

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

docs/use-tf-controller/with-tf-runner-logging.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ the `DISABLE_TF_LOGS` variable must also be set to "1".
1919

2020
For more information on configuring the Terraform Runner and its environment variables,
2121
please consult the documentation on [customizing runners](provision-resources-with-customized-runner-pods.md) within the Weave TF-controller.
22+
23+
## Logging human-readable plan
24+
25+
The plan can be logged in a human-readable format just before the applying it in the `tf-runner`.
26+
To enable this, set the environment variable `LOG_HUMAN_READABLE_PLAN` to "1" on the runner.

runner/server.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,11 @@ func (r *TerraformRunnerServer) Apply(ctx context.Context, req *ApplyRequest) (*
382382
applyOpt = append(applyOpt, tfexec.Parallelism(int(req.Parallelism)))
383383
}
384384

385+
if err := printHumanReadablePlanIfEnabled(ctx, req.DirOrPlan, r.tfShowPlanFileRaw); err != nil {
386+
log.Error(err, "unable to print plan")
387+
return nil, err
388+
}
389+
385390
if err := r.tf.Apply(ctx, applyOpt...); err != nil {
386391
st := status.New(codes.Internal, err.Error())
387392
var stateErr *tfexec.ErrStateLocked
@@ -401,6 +406,23 @@ func (r *TerraformRunnerServer) Apply(ctx context.Context, req *ApplyRequest) (*
401406
return &ApplyReply{Message: "ok"}, nil
402407
}
403408

409+
func printHumanReadablePlanIfEnabled(ctx context.Context, planName string, tfShowPlanFileRaw func(ctx context.Context, planPath string, opts ...tfexec.ShowOption) (string, error)) error {
410+
if os.Getenv("LOG_HUMAN_READABLE_PLAN") == "1" {
411+
if planName == "" {
412+
planName = TFPlanName
413+
}
414+
415+
rawOutput, err := tfShowPlanFileRaw(ctx, planName)
416+
if err != nil {
417+
return err
418+
}
419+
420+
fmt.Println(rawOutput)
421+
}
422+
423+
return nil
424+
}
425+
404426
func getInventoryFromTerraformModule(m *tfjson.StateModule) []*Inventory {
405427
var result []*Inventory
406428
for _, r := range m.Resources {

runner/server_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package runner
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-exec/tfexec"
10+
. "github.com/onsi/gomega"
11+
)
12+
13+
func Test_printHumanReadablePlanIfEnabled(t *testing.T) {
14+
g := NewGomegaWithT(t)
15+
ctx := context.Background()
16+
17+
defer func() {
18+
g.Expect(os.Unsetenv("LOG_HUMAN_READABLE_PLAN")).Should(Succeed())
19+
}()
20+
21+
var tfShowPlanFileRawCalled int
22+
expectedPlan := TFPlanName
23+
tfShowPlanFileRaw := func(ctx context.Context, planPath string, opts ...tfexec.ShowOption) (string, error) {
24+
g.Expect(planPath).To(Equal(expectedPlan))
25+
tfShowPlanFileRawCalled++
26+
return "", nil
27+
}
28+
29+
// When plan is enabled, then it should be called once
30+
g.Expect(os.Setenv("LOG_HUMAN_READABLE_PLAN", "1")).Should(Succeed())
31+
g.Expect(printHumanReadablePlanIfEnabled(ctx, "", tfShowPlanFileRaw)).Should(Succeed())
32+
g.Expect(tfShowPlanFileRawCalled).To(Equal(1))
33+
34+
// When the planName is non-empty, then it should use the planName
35+
expectedPlan = "foo"
36+
g.Expect(printHumanReadablePlanIfEnabled(ctx, expectedPlan, tfShowPlanFileRaw)).Should(Succeed())
37+
g.Expect(tfShowPlanFileRawCalled).To(Equal(2))
38+
39+
// When it is disabled, then it should not be called
40+
expectedPlan = TFPlanName
41+
g.Expect(os.Setenv("LOG_HUMAN_READABLE_PLAN", "0")).Should(Succeed())
42+
g.Expect(printHumanReadablePlanIfEnabled(ctx, "", tfShowPlanFileRaw)).Should(Succeed())
43+
g.Expect(tfShowPlanFileRawCalled).To(Equal(2))
44+
45+
// When tfShowPlanFileRaw fails, then it should return an error
46+
g.Expect(os.Setenv("LOG_HUMAN_READABLE_PLAN", "1")).Should(Succeed())
47+
tfShowPlanFileRaw = func(ctx context.Context, planPath string, opts ...tfexec.ShowOption) (string, error) {
48+
return "", fmt.Errorf("error")
49+
}
50+
51+
g.Expect(printHumanReadablePlanIfEnabled(ctx, "", tfShowPlanFileRaw)).ShouldNot(Succeed())
52+
}

0 commit comments

Comments
 (0)