From 21d3c09991621ae66a037a0ba91f5dbabff3470f Mon Sep 17 00:00:00 2001
From: Mark Hughes <mrsheepuk@users.noreply.github.com>
Date: Mon, 9 Sep 2024 17:34:33 +0200
Subject: [PATCH] Ensure TFVars file included in volume mount when creating job
 (#1512)

---
 pkg/assets/job.yaml.tpl     |  4 +++
 pkg/utils/jobs/jobs.go      |  1 +
 pkg/utils/jobs/jobs_test.go | 69 +++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)
 create mode 100644 pkg/utils/jobs/jobs_test.go

diff --git a/pkg/assets/job.yaml.tpl b/pkg/assets/job.yaml.tpl
index 2dc3ea0ae..08284495a 100644
--- a/pkg/assets/job.yaml.tpl
+++ b/pkg/assets/job.yaml.tpl
@@ -57,6 +57,10 @@ spec:
               - key: variables.tfvars.json
                 path: variables.tfvars.json
               {{- end }}
+              {{- if .EnableTFVars }}
+              - key: variables.tfvars
+                path: variables.tfvars
+              {{- end }}
         {{- if eq .Stage "apply" }}
         - name: planout
           secret:
diff --git a/pkg/utils/jobs/jobs.go b/pkg/utils/jobs/jobs.go
index bb4434a79..48da9ae73 100644
--- a/pkg/utils/jobs/jobs.go
+++ b/pkg/utils/jobs/jobs.go
@@ -227,6 +227,7 @@ func (r *Render) createTerraformFromTemplate(options Options, stage string) (*ba
 		},
 		"EnableInfraCosts":       options.EnableInfraCosts,
 		"EnableVariables":        r.configuration.Spec.HasVariables(),
+		"EnableTFVars":           r.configuration.Spec.TFVars != "",
 		"ExecutorSecrets":        options.ExecutorSecrets,
 		"ImagePullPolicy":        "IfNotPresent",
 		"Policy":                 options.PolicyConstraint,
diff --git a/pkg/utils/jobs/jobs_test.go b/pkg/utils/jobs/jobs_test.go
new file mode 100644
index 000000000..27324d07a
--- /dev/null
+++ b/pkg/utils/jobs/jobs_test.go
@@ -0,0 +1,69 @@
+package jobs_test
+
+import (
+	"testing"
+
+	batchv1 "k8s.io/api/batch/v1"
+
+	"github.com/appvia/terranetes-controller/pkg/apis/terraform/v1alpha1"
+	"github.com/appvia/terranetes-controller/pkg/assets"
+	"github.com/appvia/terranetes-controller/pkg/utils/jobs"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestNewTerraformPlan(t *testing.T) {
+	cases := []struct {
+		name     string
+		conf     *v1alpha1.Configuration
+		provider *v1alpha1.Provider
+		opts     jobs.Options
+		checkJob func(*testing.T, *batchv1.Job)
+	}{
+		{
+			name: "When TFVars specified, variables.tfvars is mounted and included in args",
+			conf: &v1alpha1.Configuration{
+				Spec: v1alpha1.ConfigurationSpec{
+					TFVars: `horse = "strong"`,
+				},
+			},
+			provider: &v1alpha1.Provider{},
+			opts: jobs.Options{
+				Template: assets.MustAsset("job.yaml.tpl"),
+			},
+			checkJob: func(t *testing.T, job *batchv1.Job) {
+				require.GreaterOrEqual(t, len(job.Spec.Template.Spec.Volumes), 3, "Expected at least 3 volumes")
+				require.GreaterOrEqual(t, len(job.Spec.Template.Spec.Volumes[2].Secret.Items), 3, "Expected at least 3 entries in volume mount")
+				assert.Equal(t, "variables.tfvars", job.Spec.Template.Spec.Volumes[2].Secret.Items[2].Key)
+				assert.Contains(t, job.Spec.Template.Spec.Containers[0].Args[1], "--var-file variables.tfvars")
+			},
+		},
+		{
+			name: "When TFVars unspecified, variables.tfvars is not mounted and not included in args",
+			conf: &v1alpha1.Configuration{
+				Spec: v1alpha1.ConfigurationSpec{},
+			},
+			provider: &v1alpha1.Provider{},
+			opts: jobs.Options{
+				Template: assets.MustAsset("job.yaml.tpl"),
+			},
+			checkJob: func(t *testing.T, job *batchv1.Job) {
+				require.GreaterOrEqual(t, len(job.Spec.Template.Spec.Volumes), 3, "Expected at least 3 volumes")
+				require.GreaterOrEqual(t, len(job.Spec.Template.Spec.Volumes[2].Secret.Items), 2, "Expected only 2 entries in volume mount")
+				assert.NotContains(t, job.Spec.Template.Spec.Containers[0].Args[1], "--var-file variables.tfvars")
+			},
+		},
+	}
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			job, err := jobs.New(tc.conf, tc.provider).NewTerraformPlan(tc.opts)
+			if err != nil {
+				t.Error(err)
+				t.Fail()
+			}
+			if tc.checkJob != nil {
+				tc.checkJob(t, job)
+			}
+		})
+	}
+}