diff --git a/api/v1alpha2/reference_types.go b/api/v1alpha2/reference_types.go index cd78e8f61..ddccdd122 100644 --- a/api/v1alpha2/reference_types.go +++ b/api/v1alpha2/reference_types.go @@ -163,6 +163,10 @@ type RunnerPodSpec struct { // +optional Image string `json:"image,omitempty"` + // Runner pod ImagePullPolicy to use other than default + // +optional + ImagePullPolicy string `json:"imagePullPolicy,omitempty"` + // List of sources to populate environment variables in the container. // The keys defined within a source must be a C_IDENTIFIER. All invalid keys // will be reported as an event when the container is starting. When a key exists in multiple diff --git a/charts/tofu-controller/README.md b/charts/tofu-controller/README.md index 2d45c7dd3..503b227d1 100644 --- a/charts/tofu-controller/README.md +++ b/charts/tofu-controller/README.md @@ -84,6 +84,7 @@ __Note__: If you need to use the `imagePullSecrets` it would be best to set `ser | runner.grpc.maxMessageSize | int | `4` | Maximum GRPC message size (Controller) | | runner.image.repository | string | `"ghcr.io/flux-iac/tf-runner"` | Runner image repository | | runner.image.tag | string | `.Chart.AppVersion` | Runner image tag | +| runner.imagePullPolicy | string | `IfNotPresent, Always, Never` | Runner image pull policy | | runner.serviceAccount.allowedNamespaces | list | `["flux-system"]` | List of namespaces that the runner may run within (in addition to namespace of the controller itself) | | runner.serviceAccount.annotations | object | `{}` | Additional runner service Account annotations | | runner.serviceAccount.create | bool | `true` | If `true`, create a new runner service account | diff --git a/charts/tofu-controller/crds/crds.yaml b/charts/tofu-controller/crds/crds.yaml index 2f6cd7245..5f5a8c2d2 100644 --- a/charts/tofu-controller/crds/crds.yaml +++ b/charts/tofu-controller/crds/crds.yaml @@ -6743,6 +6743,10 @@ spec: image: description: Runner pod image to use other than default type: string + imagePullPolicy: + description: Runner pod ImagePullPolicy to use other than + default + type: string initContainers: description: Set up Init Containers for the Runner items: diff --git a/config/crd/bases/infra.contrib.fluxcd.io_terraforms.yaml b/config/crd/bases/infra.contrib.fluxcd.io_terraforms.yaml index 2f6cd7245..5f5a8c2d2 100644 --- a/config/crd/bases/infra.contrib.fluxcd.io_terraforms.yaml +++ b/config/crd/bases/infra.contrib.fluxcd.io_terraforms.yaml @@ -6743,6 +6743,10 @@ spec: image: description: Runner pod image to use other than default type: string + imagePullPolicy: + description: Runner pod ImagePullPolicy to use other than + default + type: string initContainers: description: Set up Init Containers for the Runner items: diff --git a/controllers/tc000260_runner_pod_test.go b/controllers/tc000260_runner_pod_test.go index 8830b68d0..e25366196 100644 --- a/controllers/tc000260_runner_pod_test.go +++ b/controllers/tc000260_runner_pod_test.go @@ -73,6 +73,7 @@ func Test_000260_runner_pod_test(t *testing.T) { spec := reconciler.runnerPodSpec(helloWorldTF, "runner.tls-123") g.Expect(spec.ServiceAccountName).To(Equal(serviceAccountName)) g.Expect(spec.Containers[0].Image).To(Equal(runnerPodImage)) + g.Expect(spec.Containers[0].ImagePullPolicy).To(Equal(corev1.PullIfNotPresent)) g.Expect(spec.HostAliases[0].Hostnames).To(Equal([]string{"foo", "bar"})) podTemplate, err := runnerPodTemplate(helloWorldTF, "runner.tls-123", revision) @@ -178,6 +179,76 @@ func Test_000260_runner_pod_test_env_vars(t *testing.T) { }()).To(BeTrue()) } +func Test_000260_runner_pod_a_test_image_pull_policy(t *testing.T) { + Spec("This spec describes a runner pod creation process") + + const ( + terraformName = "runner-pod-test" + sourceName = "runner-pod-test" + serviceAccountName = "helloworld-tf-runner" + runnerPodImage = "ghcr.io/weaveworks/tf-runner:test" + revision = "v2.6@sha256:c7fd0cc69b924aa5f9a6928477311737e439ca1b9e444855b0377e8a8ec65bb5" + ) + + var stringMap = map[string]string{ + "company.com/abc": "xyz", + "company.com/xyz": "abc", + "tf.weave.works/tls-secret-name": "runner.tls-123", + } + + g := NewWithT(t) + + It("generate a runner pod template") + By("passing a terraform object, the runner pod template should be accurate") + helloWorldTF := infrav1.Terraform{ + ObjectMeta: metav1.ObjectMeta{ + Name: terraformName, + Namespace: "flux-system", + }, + Spec: infrav1.TerraformSpec{ + ApprovePlan: "auto", + Path: "./terraform-hello-world-example", + SourceRef: infrav1.CrossNamespaceSourceReference{ + Kind: "GitRepository", + Name: sourceName, + Namespace: "flux-system", + }, + ServiceAccountName: serviceAccountName, + RunnerPodTemplate: infrav1.RunnerPodTemplate{ + Metadata: infrav1.RunnerPodMetadata{ + Labels: stringMap, + Annotations: stringMap, + }, + Spec: infrav1.RunnerPodSpec{ + Image: runnerPodImage, + ImagePullPolicy: "Always", + }, + }, + }, + } + + spec := reconciler.runnerPodSpec(helloWorldTF, "runner.tls-123") + g.Expect(spec.ServiceAccountName).To(Equal(serviceAccountName)) + g.Expect(spec.Containers[0].Image).To(Equal(runnerPodImage)) + g.Expect(spec.Containers[0].ImagePullPolicy).To(Equal(corev1.PullAlways)) + + podTemplate, err := runnerPodTemplate(helloWorldTF, "runner.tls-123", revision) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(func() bool { + for k, v := range stringMap { + if v != podTemplate.ObjectMeta.Labels[k] { + return false + } + } + for k, v := range stringMap { + if v != podTemplate.ObjectMeta.Annotations[k] { + return false + } + } + return true + }()).To(BeTrue()) +} + func Test_000260_runner_pod_test_env_vars_proxy(t *testing.T) { Spec("This spec describes a runner pod creation process") diff --git a/controllers/tf_controller_runner.go b/controllers/tf_controller_runner.go index 94f8c5d3a..743d499ed 100644 --- a/controllers/tf_controller_runner.go +++ b/controllers/tf_controller_runner.go @@ -39,6 +39,14 @@ func getRunnerPodImage(image string) string { return runnerPodImage } +func getRunnerImagePullPolicy(imagePullPolicy string) v1.PullPolicy { + runnerImagePullPolicy := v1.PullPolicy(imagePullPolicy) + if runnerImagePullPolicy == "" { + runnerImagePullPolicy = v1.PullIfNotPresent + } + return runnerImagePullPolicy +} + func runnerPodTemplate(terraform infrav1.Terraform, secretName string, revision string) (v1.Pod, error) { podNamespace := terraform.Namespace podName := fmt.Sprintf("%s-tf-runner", terraform.Name) @@ -272,7 +280,7 @@ func (r *TerraformReconciler) runnerPodSpec(terraform infrav1.Terraform, tlsSecr "--grpc-max-message-size", fmt.Sprintf("%d", r.RunnerGRPCMaxMessageSize), }, Image: getRunnerPodImage(terraform.Spec.RunnerPodTemplate.Spec.Image), - ImagePullPolicy: v1.PullIfNotPresent, + ImagePullPolicy: getRunnerImagePullPolicy(terraform.Spec.RunnerPodTemplate.Spec.ImagePullPolicy), Ports: []v1.ContainerPort{ { Name: "grpc", diff --git a/docs/References/terraform.md b/docs/References/terraform.md index b447fe30a..1d8f43e94 100644 --- a/docs/References/terraform.md +++ b/docs/References/terraform.md @@ -868,6 +868,18 @@ string
imagePullPolicy
Runner pod ImagePullPolicy to use other than default
+envFrom
imagePullPolicy
Runner pod ImagePullPolicy to use other than default
+envFrom