diff --git a/api/v1/installation_types.go b/api/v1/installation_types.go index b080d6a628..5c8ef6b222 100644 --- a/api/v1/installation_types.go +++ b/api/v1/installation_types.go @@ -97,6 +97,14 @@ type InstallationSpec struct { // +optional ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // ImagePullPolicy is the pull policy applied to containers in pods rendered by the operator + // that do not explicitly set their own pull policy. If unset, defaults to IfNotPresent. + // This is useful in air-gapped environments where images are pre-loaded onto nodes and + // must not be re-pulled from a remote registry. + // +optional + // +kubebuilder:validation:Enum=Always;IfNotPresent;Never + ImagePullPolicy *v1.PullPolicy `json:"imagePullPolicy,omitempty"` + // KubernetesProvider specifies a particular provider of the Kubernetes platform and enables provider-specific configuration. // If the specified value is empty, the Operator will attempt to automatically determine the current provider. // If the specified value is not empty, the Operator will still attempt auto-detection, but diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 271a0f0956..7a26d77a2f 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -5937,6 +5937,11 @@ func (in *InstallationSpec) DeepCopyInto(out *InstallationSpec) { *out = make([]corev1.LocalObjectReference, len(*in)) copy(*out, *in) } + if in.ImagePullPolicy != nil { + in, out := &in.ImagePullPolicy, &out.ImagePullPolicy + *out = new(corev1.PullPolicy) + **out = **in + } if in.CNI != nil { in, out := &in.CNI, &out.CNI *out = new(CNISpec) diff --git a/pkg/controller/utils/component.go b/pkg/controller/utils/component.go index 10ffc062c8..b6679a2647 100644 --- a/pkg/controller/utils/component.go +++ b/pkg/controller/utils/component.go @@ -42,6 +42,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" v3 "github.com/tigera/api/pkg/apis/projectcalico/v3" + operatorv1 "github.com/tigera/operator/api/v1" "github.com/tigera/operator/pkg/apigroup" "github.com/tigera/operator/pkg/common" "github.com/tigera/operator/pkg/controller/status" @@ -230,8 +231,21 @@ func (c *componentHandler) createOrUpdateObject(ctx context.Context, obj client. // system as specified by the osType. ensureOSSchedulingRestrictions(obj, osType) - // Make sure any objects with images also have an image pull policy. - modifyPodSpec(obj, setImagePullPolicy) + // Look up the InstallationSpec once and reuse it for the passes that need it + // (image pull policy and TLS ciphers), so we don't pay for the same Get twice. + var installationSpec *operatorv1.InstallationSpec + if _, spec, err := GetInstallationSpec(ctx, c.client); err == nil { + installationSpec = spec + } + + // Set image pull policy based on user input, if specified. + var configuredPolicy *v1.PullPolicy + if installationSpec != nil { + configuredPolicy = installationSpec.ImagePullPolicy + } + modifyPodSpec(obj, func(podSpec *v1.PodSpec) { + setImagePullPolicy(podSpec, configuredPolicy) + }) // Order volumes and volume mounts modifyPodSpec(obj, orderVolumes) modifyPodSpec(obj, orderVolumeMounts) @@ -242,7 +256,7 @@ func (c *componentHandler) createOrUpdateObject(ctx context.Context, obj client. // Make sure we have our standard selector and pod labels setStandardSelectorAndLabels(obj, c.cr) - if err := ensureTLSCiphers(ctx, obj, c.client); err != nil { + if err := ensureTLSCiphers(obj, installationSpec); err != nil { return fmt.Errorf("failed to set TLS Ciphers: %w", err) } @@ -796,17 +810,33 @@ func modifyPodSpec(obj client.Object, f func(*v1.PodSpec)) { } } -// setImagePullPolicy ensures that an image pull policy is set if not set already. -func setImagePullPolicy(podSpec *v1.PodSpec) { - for i := range podSpec.Containers { - if len(podSpec.Containers[i].ImagePullPolicy) == 0 { - podSpec.Containers[i].ImagePullPolicy = v1.PullIfNotPresent +// setImagePullPolicy applies an image pull policy to all containers and init containers in +// the given pod spec. If configuredPolicy is non-nil it is applied to every container, +// overriding any policy the renderer set — this is what lets a user force IfNotPresent or +// Never for air-gapped clusters. If configuredPolicy is nil, containers that do not already +// specify a policy fall back to IfNotPresent. +func setImagePullPolicy(podSpec *v1.PodSpec, configuredPolicy *v1.PullPolicy) { + apply := func(c *v1.Container) { + switch { + case configuredPolicy != nil: + c.ImagePullPolicy = *configuredPolicy + case c.ImagePullPolicy == "": + c.ImagePullPolicy = v1.PullIfNotPresent } } + for i := range podSpec.Containers { + apply(&podSpec.Containers[i]) + } + for i := range podSpec.InitContainers { + apply(&podSpec.InitContainers[i]) + } } // ensureTLSCiphers sets the TLSCipherSuites configuration as a Env Var to the Deployments and DaemonSets. -func ensureTLSCiphers(ctx context.Context, obj client.Object, c client.Client) error { +func ensureTLSCiphers(obj client.Object, installationSpec *operatorv1.InstallationSpec) error { + if installationSpec == nil { + return nil + } var containers []v1.Container switch obj := obj.(type) { case *apps.Deployment: @@ -817,15 +847,6 @@ func ensureTLSCiphers(ctx context.Context, obj client.Object, c client.Client) e return nil } - _, installationSpec, err := GetInstallationSpec(ctx, c) - if err != nil { - if errors.IsNotFound(err) { - return nil - } else { - return err - } - } - for i := range containers { exists := false for _, envVar := range containers[i].Env { diff --git a/pkg/controller/utils/component_test.go b/pkg/controller/utils/component_test.go index 6716fa9221..d2e18c8482 100644 --- a/pkg/controller/utils/component_test.go +++ b/pkg/controller/utils/component_test.go @@ -35,6 +35,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -603,7 +604,7 @@ var _ = Describe("Component handler tests", func() { }, } Expect(c.Create(ctx, installation)).To(BeNil()) - Expect(ensureTLSCiphers(ctx, obj, c)).To(BeNil()) + Expect(ensureTLSCiphers(obj, &installation.Spec)).To(BeNil()) var containers []corev1.Container switch o := obj.(type) { @@ -693,7 +694,7 @@ var _ = Describe("Component handler tests", func() { ) }) DescribeTable("ensuring ImagePullPolicy is set", func(obj client.Object) { - modifyPodSpec(obj, setImagePullPolicy) + modifyPodSpec(obj, func(p *corev1.PodSpec) { setImagePullPolicy(p, nil) }) switch o := obj.(type) { case *apps.Deployment: @@ -742,6 +743,30 @@ var _ = Describe("Component handler tests", func() { ), ) + Describe("setImagePullPolicy", func() { + It("fills missing policies with IfNotPresent and leaves explicit policies alone when no policy is configured", func() { + ps := &corev1.PodSpec{ + Containers: []corev1.Container{{Image: "a"}, {Image: "b", ImagePullPolicy: corev1.PullAlways}}, + InitContainers: []corev1.Container{{Image: "init"}}, + } + setImagePullPolicy(ps, nil) + Expect(ps.Containers[0].ImagePullPolicy).To(Equal(corev1.PullIfNotPresent)) + Expect(ps.Containers[1].ImagePullPolicy).To(Equal(corev1.PullAlways), "should not override an explicitly set policy") + Expect(ps.InitContainers[0].ImagePullPolicy).To(Equal(corev1.PullIfNotPresent)) + }) + + It("overrides every container's policy when a policy is configured on the Installation", func() { + ps := &corev1.PodSpec{ + Containers: []corev1.Container{{Image: "a"}, {Image: "b", ImagePullPolicy: corev1.PullAlways}}, + InitContainers: []corev1.Container{{Image: "init", ImagePullPolicy: corev1.PullAlways}}, + } + setImagePullPolicy(ps, ptr.To(corev1.PullNever)) + Expect(ps.Containers[0].ImagePullPolicy).To(Equal(corev1.PullNever)) + Expect(ps.Containers[1].ImagePullPolicy).To(Equal(corev1.PullNever), "configured policy must win over renderer defaults") + Expect(ps.InitContainers[0].ImagePullPolicy).To(Equal(corev1.PullNever)) + }) + }) + DescribeTable("ensuring os node selectors", func(component render.Component, key client.ObjectKey, obj client.Object, expectedNodeSelectors map[string]string) { Expect(handler.CreateOrUpdateOrDelete(ctx, component, sm)).ShouldNot(HaveOccurred()) Expect(c.Get(ctx, key, obj)).ShouldNot(HaveOccurred()) @@ -2190,7 +2215,15 @@ var _ = Describe("Mocked client Component handler tests", func() { objs: []client.Object{baseNP}, } + // Two Get calls are issued up-front to load the InstallationSpec + // (one for the Installation, one for the overlay). + installationGets := func() { + mc.Info = append(mc.Info, mockReturn{Method: "Get", Return: nil}) + mc.Info = append(mc.Info, mockReturn{Method: "Get", Return: nil}) + } + It("NetworkPolicy updates are omitted if there is no change", func() { + installationGets() mc.Info = append(mc.Info, mockReturn{ Method: "Get", Return: nil, @@ -2199,7 +2232,7 @@ var _ = Describe("Mocked client Component handler tests", func() { err := handler.CreateOrUpdateOrDelete(ctx, fc, nil) Expect(err).To(BeNil()) - Expect(mc.Index).To(Equal(1)) + Expect(mc.Index).To(Equal(3)) }) It("NetworkPolicy updates are applied if there is a change", func() { @@ -2211,6 +2244,7 @@ var _ = Describe("Mocked client Component handler tests", func() { } } + installationGets() mc.Info = append(mc.Info, mockReturn{ Method: "Get", Return: nil, @@ -2225,7 +2259,7 @@ var _ = Describe("Mocked client Component handler tests", func() { err := handler.CreateOrUpdateOrDelete(ctx, fc, nil) Expect(err).To(BeNil()) - Expect(mc.Index).To(Equal(2)) + Expect(mc.Index).To(Equal(4)) }) }) @@ -2246,7 +2280,15 @@ var _ = Describe("Mocked client Component handler tests", func() { objs: []client.Object{baseTier}, } + // Two Get calls are issued up-front to load the InstallationSpec + // (one for the Installation, one for the overlay). + installationGets := func() { + mc.Info = append(mc.Info, mockReturn{Method: "Get", Return: nil}) + mc.Info = append(mc.Info, mockReturn{Method: "Get", Return: nil}) + } + It("Tier updates are omitted if there is no change", func() { + installationGets() mc.Info = append(mc.Info, mockReturn{ Method: "Get", Return: nil, @@ -2255,7 +2297,7 @@ var _ = Describe("Mocked client Component handler tests", func() { err := handler.CreateOrUpdateOrDelete(ctx, fc, nil) Expect(err).To(BeNil()) - Expect(mc.Index).To(Equal(1)) + Expect(mc.Index).To(Equal(3)) }) It("Tier updates are applied if there is a change", func() { @@ -2268,6 +2310,7 @@ var _ = Describe("Mocked client Component handler tests", func() { } } + installationGets() mc.Info = append(mc.Info, mockReturn{ Method: "Get", Return: nil, @@ -2282,7 +2325,7 @@ var _ = Describe("Mocked client Component handler tests", func() { err := handler.CreateOrUpdateOrDelete(ctx, fc, nil) Expect(err).To(BeNil()) - Expect(mc.Index).To(Equal(2)) + Expect(mc.Index).To(Equal(4)) }) }) }) diff --git a/pkg/controller/utils/merge.go b/pkg/controller/utils/merge.go index f729bbcbd9..606b5e34d5 100644 --- a/pkg/controller/utils/merge.go +++ b/pkg/controller/utils/merge.go @@ -18,6 +18,7 @@ import ( "reflect" v1 "k8s.io/api/core/v1" + "k8s.io/utils/ptr" operatorv1 "github.com/tigera/operator/api/v1" ) @@ -60,6 +61,11 @@ func OverrideInstallationSpec(cfg, override operatorv1.InstallationSpec) operato copy(inst.ImagePullSecrets, override.ImagePullSecrets) } + switch compareFields(inst.ImagePullPolicy, override.ImagePullPolicy) { + case BOnlySet, Different: + inst.ImagePullPolicy = ptr.To(*override.ImagePullPolicy) + } + switch compareFields(inst.KubernetesProvider, override.KubernetesProvider) { case BOnlySet, Different: inst.KubernetesProvider = override.KubernetesProvider diff --git a/pkg/controller/utils/merge_test.go b/pkg/controller/utils/merge_test.go index 8aefe13fb6..d02f3e26e6 100644 --- a/pkg/controller/utils/merge_test.go +++ b/pkg/controller/utils/merge_test.go @@ -26,6 +26,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" opv1 "github.com/tigera/operator/api/v1" "github.com/tigera/operator/test" @@ -115,6 +116,24 @@ var _ = Describe("Installation merge tests", func() { Entry("Both set not matching", []v1.LocalObjectReference{{Name: "pull-secret"}}, []v1.LocalObjectReference{{Name: "other-pull-secret"}}, []v1.LocalObjectReference{{Name: "other-pull-secret"}}), ) + DescribeTable("merge ImagePullPolicy", func(main, second, expect *v1.PullPolicy) { + m := opv1.InstallationSpec{ImagePullPolicy: main} + s := opv1.InstallationSpec{ImagePullPolicy: second} + inst := OverrideInstallationSpec(m, s) + if expect == nil { + Expect(inst.ImagePullPolicy).To(BeNil()) + } else { + Expect(inst.ImagePullPolicy).NotTo(BeNil()) + Expect(*inst.ImagePullPolicy).To(Equal(*expect)) + } + }, + Entry("Both unset", nil, nil, nil), + Entry("Main only set", ptr.To(v1.PullIfNotPresent), nil, ptr.To(v1.PullIfNotPresent)), + Entry("Second only set", nil, ptr.To(v1.PullAlways), ptr.To(v1.PullAlways)), + Entry("Both set equal", ptr.To(v1.PullIfNotPresent), ptr.To(v1.PullIfNotPresent), ptr.To(v1.PullIfNotPresent)), + Entry("Both set not matching", ptr.To(v1.PullAlways), ptr.To(v1.PullNever), ptr.To(v1.PullNever)), + ) + DescribeTable("merge KubernetesProvider", func(main, second, expect *opv1.Provider) { m := opv1.InstallationSpec{} s := opv1.InstallationSpec{} diff --git a/pkg/imports/crds/operator/operator.tigera.io_installations.yaml b/pkg/imports/crds/operator/operator.tigera.io_installations.yaml index 75f6bfedee..1e04c6eb26 100644 --- a/pkg/imports/crds/operator/operator.tigera.io_installations.yaml +++ b/pkg/imports/crds/operator/operator.tigera.io_installations.yaml @@ -7184,6 +7184,17 @@ spec: `/:` This option allows configuring the `` portion of the above format. type: string + imagePullPolicy: + description: |- + ImagePullPolicy is the pull policy applied to containers in pods rendered by the operator + that do not explicitly set their own pull policy. If unset, defaults to IfNotPresent. + This is useful in air-gapped environments where images are pre-loaded onto nodes and + must not be re-pulled from a remote registry. + enum: + - Always + - IfNotPresent + - Never + type: string imagePullSecrets: description: |- ImagePullSecrets is an array of references to container registry pull secrets to use. These are @@ -16524,6 +16535,17 @@ spec: `/:` This option allows configuring the `` portion of the above format. type: string + imagePullPolicy: + description: |- + ImagePullPolicy is the pull policy applied to containers in pods rendered by the operator + that do not explicitly set their own pull policy. If unset, defaults to IfNotPresent. + This is useful in air-gapped environments where images are pre-loaded onto nodes and + must not be re-pulled from a remote registry. + enum: + - Always + - IfNotPresent + - Never + type: string imagePullSecrets: description: |- ImagePullSecrets is an array of references to container registry pull secrets to use. These are diff --git a/pkg/render/apiserver.go b/pkg/render/apiserver.go index 5eb55c14a1..143497f034 100644 --- a/pkg/render/apiserver.go +++ b/pkg/render/apiserver.go @@ -1176,13 +1176,12 @@ func (c *apiServerComponent) apiServerContainer() corev1.Container { apiServerTargetPort := getContainerPort(c.cfg, APIServerContainerName).ContainerPort apiServer := corev1.Container{ - Name: string(APIServerContainerName), - Image: c.apiServerImage, - Command: []string{components.CalicoBinaryPath, "component", "apiserver"}, - ImagePullPolicy: ImagePullPolicy(), - Args: c.startUpArgs(), - Env: env, - VolumeMounts: volumeMounts, + Name: string(APIServerContainerName), + Image: c.apiServerImage, + Command: []string{components.CalicoBinaryPath, "component", "apiserver"}, + Args: c.startUpArgs(), + Env: env, + VolumeMounts: volumeMounts, ReadinessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ @@ -1317,11 +1316,10 @@ func (c *apiServerComponent) queryServerContainer() corev1.Container { } container := corev1.Container{ - Name: string(TigeraAPIServerQueryServerContainerName), - Image: c.queryServerImage, - ImagePullPolicy: ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "queryserver"}, - Env: env, + Name: string(TigeraAPIServerQueryServerContainerName), + Image: c.queryServerImage, + Command: []string{components.CalicoBinaryPath, "component", "queryserver"}, + Env: env, LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ @@ -2305,10 +2303,9 @@ func (c *apiServerComponent) l7AdmissionControllerContainer() corev1.Container { } l7AdmssCtrl := corev1.Container{ - Name: string(L7AdmissionControllerContainerName), - Image: c.l7AdmissionControllerImage, - ImagePullPolicy: ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "l7-admission-controller"}, + Name: string(L7AdmissionControllerContainerName), + Image: c.l7AdmissionControllerImage, + Command: []string{components.CalicoBinaryPath, "component", "l7-admission-controller"}, Env: []corev1.EnvVar{ { Name: "L7ADMCTRL_TLSCERTPATH", diff --git a/pkg/render/applicationlayer/applicationlayer.go b/pkg/render/applicationlayer/applicationlayer.go index 99ffe7eeb5..844fd6ce58 100644 --- a/pkg/render/applicationlayer/applicationlayer.go +++ b/pkg/render/applicationlayer/applicationlayer.go @@ -271,9 +271,8 @@ func (c *component) containers() []corev1.Container { "NET_RAW", } proxy := corev1.Container{ - Name: ProxyContainerName, - Image: c.config.proxyImage, - ImagePullPolicy: render.ImagePullPolicy(), + Name: ProxyContainerName, + Image: c.config.proxyImage, Command: []string{ "envoy", "-c", "/etc/envoy/envoy-config.yaml", }, @@ -290,7 +289,6 @@ func (c *component) containers() []corev1.Container { collector := corev1.Container{ Name: L7CollectorContainerName, Image: c.config.collectorImage, - ImagePullPolicy: render.ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "l7-collector"}, Env: c.collectorEnv(), SecurityContext: securitycontext.NewRootContext(false), @@ -349,10 +347,9 @@ func (c *component) containers() []corev1.Container { } dikastes := corev1.Container{ - Name: DikastesContainerName, - Image: c.config.dikastesImage, - ImagePullPolicy: render.ImagePullPolicy(), - Command: commandArgs, + Name: DikastesContainerName, + Image: c.config.dikastesImage, + Command: commandArgs, Env: []corev1.EnvVar{ {Name: "LOG_LEVEL", Value: "Info"}, {Name: "DIKASTES_SUBSCRIPTION_TYPE", Value: "per-host-policies"}, diff --git a/pkg/render/aws-securitygroup-setup.go b/pkg/render/aws-securitygroup-setup.go index 451dc61d97..c177728e9b 100644 --- a/pkg/render/aws-securitygroup-setup.go +++ b/pkg/render/aws-securitygroup-setup.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2024 Tigera, Inc. All rights reserved. +// Copyright (c) 2019-2026 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -117,7 +117,6 @@ func (c *awsSGSetupComponent) setupJob() *batchv1.Job { Containers: []corev1.Container{{ Name: "aws-security-group-setup", Image: c.image, - ImagePullPolicy: ImagePullPolicy(), Args: []string{"--aws-sg-setup"}, Env: envVars, SecurityContext: securitycontext.NewNonRootContext(), diff --git a/pkg/render/compliance.go b/pkg/render/compliance.go index b1e7a8ba8c..b2039d2d0f 100644 --- a/pkg/render/compliance.go +++ b/pkg/render/compliance.go @@ -483,11 +483,10 @@ func (c *complianceComponent) complianceControllerDeployment() *appsv1.Deploymen InitContainers: initContainers, Containers: []corev1.Container{ { - Name: ComplianceControllerName, - Image: c.controllerImage, - ImagePullPolicy: ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "compliance-controller"}, - Env: envVars, + Name: ComplianceControllerName, + Image: c.controllerImage, + Command: []string{components.CalicoBinaryPath, "component", "compliance-controller"}, + Env: envVars, LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ @@ -684,11 +683,10 @@ func (c *complianceComponent) complianceReporterPodTemplate() *corev1.PodTemplat InitContainers: initContainers, Containers: []corev1.Container{ { - Name: "reporter", - Image: c.reporterImage, - ImagePullPolicy: ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "compliance-reporter"}, - Env: envVars, + Name: "reporter", + Image: c.reporterImage, + Command: []string{components.CalicoBinaryPath, "component", "compliance-reporter"}, + Env: envVars, LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ @@ -893,11 +891,10 @@ func (c *complianceComponent) complianceServerDeployment() *appsv1.Deployment { InitContainers: initContainers, Containers: []corev1.Container{ { - Name: ComplianceServerName, - Image: c.serverImage, - Command: []string{components.CalicoBinaryPath, "component", "compliance-server"}, - ImagePullPolicy: ImagePullPolicy(), - Env: envVars, + Name: ComplianceServerName, + Image: c.serverImage, + Command: []string{components.CalicoBinaryPath, "component", "compliance-server"}, + Env: envVars, LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ @@ -1107,11 +1104,10 @@ func (c *complianceComponent) complianceSnapshotterDeployment() *appsv1.Deployme InitContainers: initContainers, Containers: []corev1.Container{ { - Name: ComplianceSnapshotterName, - Image: c.snapshotterImage, - ImagePullPolicy: ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "compliance-snapshotter"}, - Env: envVars, + Name: ComplianceSnapshotterName, + Image: c.snapshotterImage, + Command: []string{components.CalicoBinaryPath, "component", "compliance-snapshotter"}, + Env: envVars, LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ @@ -1316,7 +1312,6 @@ func (c *complianceComponent) complianceBenchmarkerDaemonSet() *appsv1.DaemonSet { Name: ComplianceBenchmarkerName, Image: c.benchmarkerImage, - ImagePullPolicy: ImagePullPolicy(), Env: envVars, SecurityContext: sc, VolumeMounts: volMounts, diff --git a/pkg/render/csi.go b/pkg/render/csi.go index d34faf2c68..0fc7a81f04 100644 --- a/pkg/render/csi.go +++ b/pkg/render/csi.go @@ -139,10 +139,9 @@ func (c *csiComponent) csiAffinities() *corev1.Affinity { func (c *csiComponent) csiContainers() []corev1.Container { mountPropagation := corev1.MountPropagationBidirectional csiContainer := corev1.Container{ - Name: CSIContainerName, - Image: c.csiImage, - Command: []string{components.CalicoBinaryPath, "component", "csi"}, - ImagePullPolicy: ImagePullPolicy(), + Name: CSIContainerName, + Image: c.csiImage, + Command: []string{components.CalicoBinaryPath, "component", "csi"}, Args: []string{ "--nodeid=$(KUBE_NODE_NAME)", "--loglevel=$(LOG_LEVEL)", @@ -181,10 +180,9 @@ func (c *csiComponent) csiContainers() []corev1.Container { // Construct "csi-node-driver-registrar" container registrarContainer := corev1.Container{ - Name: CSIRegistrarContainerName, - Image: c.csiRegistrarImage, - Command: []string{"/usr/bin/csi-node-driver-registrar"}, - ImagePullPolicy: ImagePullPolicy(), + Name: CSIRegistrarContainerName, + Image: c.csiRegistrarImage, + Command: []string{"/usr/bin/csi-node-driver-registrar"}, Args: []string{ "--v=5", "--csi-address=$(ADDRESS)", diff --git a/pkg/render/dex.go b/pkg/render/dex.go index 1dcff4dd69..b9a0675b40 100644 --- a/pkg/render/dex.go +++ b/pkg/render/dex.go @@ -321,7 +321,6 @@ func (c *dexComponent) deployment() client.Object { { Name: DexObjectName, Image: c.image, - ImagePullPolicy: ImagePullPolicy(), Env: envVars, LivenessProbe: c.probe(), SecurityContext: sc, diff --git a/pkg/render/egressgateway/egressgateway.go b/pkg/render/egressgateway/egressgateway.go index 8af4b95d35..84c675e75c 100644 --- a/pkg/render/egressgateway/egressgateway.go +++ b/pkg/render/egressgateway/egressgateway.go @@ -201,7 +201,6 @@ func (c *component) egwInitContainer() *corev1.Container { return &corev1.Container{ Name: "egress-gateway-init", Image: c.config.egwImage, - ImagePullPolicy: render.ImagePullPolicy(), Command: []string{"/init-gateway.sh"}, SecurityContext: securitycontext.NewRootContext(true), Env: c.egwInitEnvVars(), @@ -215,7 +214,6 @@ func (c *component) egwContainer() *corev1.Container { return &corev1.Container{ Name: "egress-gateway", Image: c.config.egwImage, - ImagePullPolicy: render.ImagePullPolicy(), Env: c.egwEnvVars(), VolumeMounts: c.egwVolumeMounts(), Ports: c.egwPorts(), diff --git a/pkg/render/fluentd.go b/pkg/render/fluentd.go index 790d832a01..9673bcc1e6 100644 --- a/pkg/render/fluentd.go +++ b/pkg/render/fluentd.go @@ -639,10 +639,9 @@ func (c *fluentdComponent) container() corev1.Container { } return corev1.Container{ - Name: "fluentd", - Image: c.image, - ImagePullPolicy: ImagePullPolicy(), - Env: envs, + Name: "fluentd", + Image: c.image, + Env: envs, // On OpenShift Fluentd needs privileged access to access logs on host path volume SecurityContext: c.securityContext(c.cfg.Installation.KubernetesProvider.IsOpenShift()), VolumeMounts: volumeMounts, @@ -1123,7 +1122,6 @@ func (c *fluentdComponent) eksLogForwarderDeployment() *appsv1.Deployment { InitContainers: []corev1.Container{{ Name: EKSLogForwarderName + "-startup", Image: c.image, - ImagePullPolicy: ImagePullPolicy(), Command: []string{c.path("/bin/eks-log-forwarder-startup")}, Env: envVars, SecurityContext: c.securityContext(false), @@ -1132,7 +1130,6 @@ func (c *fluentdComponent) eksLogForwarderDeployment() *appsv1.Deployment { Containers: []corev1.Container{{ Name: EKSLogForwarderName, Image: c.image, - ImagePullPolicy: ImagePullPolicy(), Env: envVars, SecurityContext: c.securityContext(false), VolumeMounts: c.eksLogForwarderVolumeMounts(), diff --git a/pkg/render/goldmane/component.go b/pkg/render/goldmane/component.go index 3290f7b1f2..d6ee4c98bf 100644 --- a/pkg/render/goldmane/component.go +++ b/pkg/render/goldmane/component.go @@ -235,7 +235,6 @@ func (c *Component) goldmaneContainer() corev1.Container { return corev1.Container{ Name: GoldmaneContainerName, Image: c.goldmaneImage, - ImagePullPolicy: render.ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "goldmane"}, Env: env, SecurityContext: securitycontext.NewNonRootContext(), diff --git a/pkg/render/goldmane/component_test.go b/pkg/render/goldmane/component_test.go index bbc55f20c3..6d3f33e845 100644 --- a/pkg/render/goldmane/component_test.go +++ b/pkg/render/goldmane/component_test.go @@ -30,7 +30,6 @@ import ( v3 "github.com/tigera/api/pkg/apis/projectcalico/v3" operatorv1 "github.com/tigera/operator/api/v1" - "github.com/tigera/operator/pkg/render" rmeta "github.com/tigera/operator/pkg/render/common/meta" "github.com/tigera/operator/pkg/render/common/securitycontext" rtest "github.com/tigera/operator/pkg/render/common/test" @@ -140,10 +139,9 @@ var _ = Describe("ComponentRendering", func() { Tolerations: append(rmeta.TolerateCriticalAddonsAndControlPlane, rmeta.TolerateGKEARM64NoSchedule), Containers: []corev1.Container{ { - Name: goldmane.GoldmaneContainerName, - Image: "quay.io/calico/calico:master", - Command: []string{"/usr/bin/calico", "component", "goldmane"}, - ImagePullPolicy: render.ImagePullPolicy(), + Name: goldmane.GoldmaneContainerName, + Image: "quay.io/calico/calico:master", + Command: []string{"/usr/bin/calico", "component", "goldmane"}, Env: []corev1.EnvVar{ {Name: "LOG_LEVEL", Value: "INFO"}, {Name: "PORT", Value: "7443"}, diff --git a/pkg/render/guardian.go b/pkg/render/guardian.go index b4f247b7e9..52ee44ed01 100644 --- a/pkg/render/guardian.go +++ b/pkg/render/guardian.go @@ -495,12 +495,11 @@ func (c *GuardianComponent) container() []corev1.Container { return []corev1.Container{ { - Name: GuardianContainerName, - Image: c.image, - Command: []string{components.CalicoBinaryPath, "component", "guardian"}, - ImagePullPolicy: ImagePullPolicy(), - Env: envVars, - VolumeMounts: c.volumeMounts(), + Name: GuardianContainerName, + Image: c.image, + Command: []string{components.CalicoBinaryPath, "component", "guardian"}, + Env: envVars, + VolumeMounts: c.volumeMounts(), LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ diff --git a/pkg/render/intrusion_detection.go b/pkg/render/intrusion_detection.go index 8577ea205a..027d64cadf 100644 --- a/pkg/render/intrusion_detection.go +++ b/pkg/render/intrusion_detection.go @@ -687,7 +687,6 @@ func (c *intrusionDetectionComponent) webhooksControllerContainer() corev1.Conta return corev1.Container{ Name: "webhooks-processor", Image: c.webhooksProcessorImage, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "webhooks-processor"}, Env: envVars, SecurityContext: securitycontext.NewNonRootContext(), @@ -767,11 +766,10 @@ func (c *intrusionDetectionComponent) intrusionDetectionControllerContainer() co } return corev1.Container{ - Name: "controller", - Image: c.controllerImage, - ImagePullPolicy: ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "intrusion-detection-controller"}, - Env: envs, + Name: "controller", + Image: c.controllerImage, + Command: []string{components.CalicoBinaryPath, "component", "intrusion-detection-controller"}, + Env: envs, LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ diff --git a/pkg/render/intrusiondetection/dpi/dpi.go b/pkg/render/intrusiondetection/dpi/dpi.go index 33952c01e7..ef2611e69a 100644 --- a/pkg/render/intrusiondetection/dpi/dpi.go +++ b/pkg/render/intrusiondetection/dpi/dpi.go @@ -190,9 +190,8 @@ func (d *dpiComponent) dpiDaemonset() *appsv1.DaemonSet { if d.dpiInitContainers() { for _, initContainer := range d.cfg.IntrusionDetection.Spec.DeepPacketInspectionDaemonset.Spec.Template.Spec.InitContainers { container := corev1.Container{ - Name: initContainer.Name, - Image: initContainer.Image, - ImagePullPolicy: render.ImagePullPolicy(), + Name: initContainer.Name, + Image: initContainer.Image, VolumeMounts: []corev1.VolumeMount{ { Name: DeepPacketInspectionSnortRulesVolumeName, @@ -243,12 +242,11 @@ func (d *dpiComponent) dpiContainer() corev1.Container { "NET_RAW", } dpiContainer := corev1.Container{ - Name: DeepPacketInspectionName, - Image: d.dpiImage, - ImagePullPolicy: render.ImagePullPolicy(), - Resources: *d.cfg.IntrusionDetection.Spec.ComponentResources[0].ResourceRequirements, - Env: d.dpiEnvVars(), - VolumeMounts: d.dpiVolumeMounts(), + Name: DeepPacketInspectionName, + Image: d.dpiImage, + Resources: *d.cfg.IntrusionDetection.Spec.ComponentResources[0].ResourceRequirements, + Env: d.dpiEnvVars(), + VolumeMounts: d.dpiVolumeMounts(), // On OpenShift Snort needs privileged access to access host network SecurityContext: sc, ReadinessProbe: d.dpiReadinessProbes(), diff --git a/pkg/render/kubecontrollers/kube-controllers.go b/pkg/render/kubecontrollers/kube-controllers.go index af72b72c1e..e6596b70b9 100644 --- a/pkg/render/kubecontrollers/kube-controllers.go +++ b/pkg/render/kubecontrollers/kube-controllers.go @@ -615,7 +615,6 @@ func (c *kubeControllersComponent) controllersDeployment() *appsv1.Deployment { Name: c.kubeControllerName, Image: c.image, Command: containerCommand, - ImagePullPolicy: render.ImagePullPolicy(), Env: env, Resources: c.kubeControllersResources(), ReadinessProbe: readinessProbe, diff --git a/pkg/render/logstorage.go b/pkg/render/logstorage.go index 1c33d07297..e845a25b2c 100644 --- a/pkg/render/logstorage.go +++ b/pkg/render/logstorage.go @@ -402,9 +402,8 @@ func (es *elasticsearchComponent) podTemplate() corev1.PodTemplateSpec { // https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html initOSSettingsContainer := corev1.Container{ - Name: "elastic-internal-init-os-settings", - Image: es.esImage, - ImagePullPolicy: ImagePullPolicy(), + Name: "elastic-internal-init-os-settings", + Image: es.esImage, Command: []string{ "/bin/sh", }, @@ -417,9 +416,8 @@ func (es *elasticsearchComponent) podTemplate() corev1.PodTemplateSpec { initContainers := []corev1.Container{initOSSettingsContainer} initFSContainer := corev1.Container{ - Name: "elastic-internal-init-filesystem", - Image: es.esImage, - ImagePullPolicy: ImagePullPolicy(), + Name: "elastic-internal-init-filesystem", + Image: es.esImage, Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ "cpu": resource.MustParse("100m"), @@ -435,9 +433,8 @@ func (es *elasticsearchComponent) podTemplate() corev1.PodTemplateSpec { } suspendContainer := corev1.Container{ - Name: "elastic-internal-suspend", - Image: es.esImage, - ImagePullPolicy: ImagePullPolicy(), + Name: "elastic-internal-suspend", + Image: es.esImage, // Without a root context, it is not able to start. SecurityContext: securitycontext.NewRootContext(true), } diff --git a/pkg/render/logstorage/dashboards/dashboards.go b/pkg/render/logstorage/dashboards/dashboards.go index 3c7075bda9..40304d9315 100644 --- a/pkg/render/logstorage/dashboards/dashboards.go +++ b/pkg/render/logstorage/dashboards/dashboards.go @@ -283,7 +283,6 @@ func (d *dashboards) Job() *batchv1.Job { { Name: Name, Image: d.image, - ImagePullPolicy: render.ImagePullPolicy(), Env: envVars, SecurityContext: securitycontext.NewNonRootContext(), VolumeMounts: volumeMounts, diff --git a/pkg/render/logstorage/dashboards/dashboards_test.go b/pkg/render/logstorage/dashboards/dashboards_test.go index 0d4a365979..8a0b9a5037 100644 --- a/pkg/render/logstorage/dashboards/dashboards_test.go +++ b/pkg/render/logstorage/dashboards/dashboards_test.go @@ -609,8 +609,7 @@ func expectedVolumes() []corev1.Volume { func expectedContainers() []corev1.Container { return []corev1.Container{ { - Name: Name, - ImagePullPolicy: render.ImagePullPolicy(), + Name: Name, SecurityContext: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}, AllowPrivilegeEscalation: ptr.To(false), diff --git a/pkg/render/logstorage/eck/eck.go b/pkg/render/logstorage/eck/eck.go index 25e733959a..475fe971b9 100644 --- a/pkg/render/logstorage/eck/eck.go +++ b/pkg/render/logstorage/eck/eck.go @@ -363,9 +363,8 @@ func (e *eck) operatorStatefulSet() *appsv1.StatefulSet { NodeSelector: e.cfg.Installation.ControlPlaneNodeSelector, Tolerations: tolerations, Containers: []corev1.Container{{ - Image: e.esOperatorImage, - ImagePullPolicy: render.ImagePullPolicy(), - Name: "manager", + Image: e.esOperatorImage, + Name: "manager", // Verbosity level of logs. -2=Error, -1=Warn, 0=Info, 0 and above=Debug Args: []string{ "manager", diff --git a/pkg/render/logstorage/esgateway/esgateway.go b/pkg/render/logstorage/esgateway/esgateway.go index ec217ae11e..7c46e9d0d8 100644 --- a/pkg/render/logstorage/esgateway/esgateway.go +++ b/pkg/render/logstorage/esgateway/esgateway.go @@ -251,12 +251,11 @@ func (e *esGateway) esGatewayDeployment() *appsv1.Deployment { InitContainers: initContainers, Containers: []corev1.Container{ { - Name: DeploymentName, - Image: e.esGatewayImage, - ImagePullPolicy: render.ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "es-gateway"}, - Env: envVars, - VolumeMounts: volumeMounts, + Name: DeploymentName, + Image: e.esGatewayImage, + Command: []string{components.CalicoBinaryPath, "component", "es-gateway"}, + Env: envVars, + VolumeMounts: volumeMounts, ReadinessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ diff --git a/pkg/render/logstorage/esmetrics/elasticsearch_metrics.go b/pkg/render/logstorage/esmetrics/elasticsearch_metrics.go index 97e09f71ba..2db85cc9db 100644 --- a/pkg/render/logstorage/esmetrics/elasticsearch_metrics.go +++ b/pkg/render/logstorage/esmetrics/elasticsearch_metrics.go @@ -235,7 +235,6 @@ func (e *elasticsearchMetrics) metricsDeployment() *appsv1.Deployment { { Name: ElasticsearchMetricsName, Image: e.esMetricsImage, - ImagePullPolicy: render.ImagePullPolicy(), SecurityContext: sc, Command: []string{components.CalicoBinaryPath, "component", "elasticsearch-metrics"}, Args: []string{ diff --git a/pkg/render/logstorage/linseed/linseed.go b/pkg/render/logstorage/linseed/linseed.go index 9ab6cae0ef..e1e82c3b84 100644 --- a/pkg/render/logstorage/linseed/linseed.go +++ b/pkg/render/logstorage/linseed/linseed.go @@ -460,7 +460,6 @@ func (l *linseed) linseedDeployment() *appsv1.Deployment { { Name: DeploymentName, Image: l.linseedImage, - ImagePullPolicy: render.ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "linseed"}, Env: envVars, VolumeMounts: volumeMounts, diff --git a/pkg/render/logstorage/linseed/linseed_test.go b/pkg/render/logstorage/linseed/linseed_test.go index bae479e483..936db2f3bc 100644 --- a/pkg/render/logstorage/linseed/linseed_test.go +++ b/pkg/render/logstorage/linseed/linseed_test.go @@ -1029,9 +1029,8 @@ func expectedVolumes(useCSR bool) []corev1.Volume { func expectedContainers() []corev1.Container { return []corev1.Container{ { - Name: DeploymentName, - ImagePullPolicy: render.ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "linseed"}, + Name: DeploymentName, + Command: []string{components.CalicoBinaryPath, "component", "linseed"}, SecurityContext: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}, AllowPrivilegeEscalation: ptr.To(false), diff --git a/pkg/render/manager.go b/pkg/render/manager.go index dcaf37e87e..189d14ca73 100644 --- a/pkg/render/manager.go +++ b/pkg/render/manager.go @@ -508,7 +508,6 @@ func (c *managerComponent) managerContainer() corev1.Container { return corev1.Container{ Name: ManagerName, Image: c.managerImage, - ImagePullPolicy: ImagePullPolicy(), Env: c.managerEnvVars(), LivenessProbe: c.managerProbe(), SecurityContext: securitycontext.NewNonRootContext(), @@ -669,7 +668,6 @@ func (c *managerComponent) voltronContainer() corev1.Container { return corev1.Container{ Name: VoltronName, Image: c.voltronImage, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "voltron"}, Env: env, VolumeMounts: mounts, @@ -704,7 +702,6 @@ func (c *managerComponent) dashboardContainer() corev1.Container { return corev1.Container{ Name: DashboardAPIName, Image: c.uiAPIsImage, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "dashboards"}, Env: env, VolumeMounts: mounts, @@ -795,7 +792,6 @@ func (c *managerComponent) managerUIAPIsContainer() corev1.Container { return corev1.Container{ Name: UIAPIsName, Image: c.uiAPIsImage, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "ui-apis"}, LivenessProbe: c.managerUIAPIsProbe(), SecurityContext: securitycontext.NewNonRootContext(), diff --git a/pkg/render/monitor/monitor.go b/pkg/render/monitor/monitor.go index f966046b0f..fa3473df5c 100644 --- a/pkg/render/monitor/monitor.go +++ b/pkg/render/monitor/monitor.go @@ -520,7 +520,6 @@ func (mc *monitorComponent) alertmanager() *monitoringv1.Alertmanager { }, Spec: monitoringv1.AlertmanagerSpec{ Image: &mc.alertmanagerImage, - ImagePullPolicy: render.ImagePullPolicy(), ImagePullSecrets: secret.GetReferenceList(mc.cfg.PullSecrets), NodeSelector: mc.cfg.Installation.ControlPlaneNodeSelector, Replicas: mc.cfg.Monitor.Alertmanager.AlertmanagerSpec.Replicas, @@ -639,10 +638,9 @@ func (mc *monitorComponent) prometheus() *monitoringv1.Prometheus { }, Containers: []corev1.Container{ { - Name: "authn-proxy", - Image: mc.prometheusServiceImage, - ImagePullPolicy: render.ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "prometheus-service"}, + Name: "authn-proxy", + Image: mc.prometheusServiceImage, + Command: []string{components.CalicoBinaryPath, "component", "prometheus-service"}, Ports: []corev1.ContainerPort{ { ContainerPort: PrometheusProxyPort, @@ -672,7 +670,6 @@ func (mc *monitorComponent) prometheus() *monitoringv1.Prometheus { }, }, Image: &mc.prometheusImage, - ImagePullPolicy: render.ImagePullPolicy(), ImagePullSecrets: secret.GetReferenceList(mc.cfg.PullSecrets), InitContainers: initContainers, // ListenLocal makes the Prometheus server listen on loopback, so that it diff --git a/pkg/render/node.go b/pkg/render/node.go index e6c088cb6c..91aa1ef3ba 100644 --- a/pkg/render/node.go +++ b/pkg/render/node.go @@ -1212,7 +1212,6 @@ func (c *nodeComponent) cniContainer() corev1.Container { return corev1.Container{ Name: "install-cni", Image: c.cniImage, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "cni", "install"}, Env: cniEnv, SecurityContext: securitycontext.NewRootContext(true), @@ -1231,7 +1230,6 @@ func (c *nodeComponent) flexVolumeContainer() corev1.Container { Name: "flexvol-driver", Image: c.flexvolImage, Command: []string{components.CalicoBinaryPath, "component", "flexvol", "install", "--target", "/host/driver/uds"}, - ImagePullPolicy: ImagePullPolicy(), SecurityContext: securitycontext.NewRootContext(true), VolumeMounts: flexVolumeMounts, } @@ -1272,7 +1270,6 @@ func (c *nodeComponent) bpfBootstrapInitContainer() corev1.Container { return corev1.Container{ Name: "ebpf-bootstrap", Image: c.nodeImage, - ImagePullPolicy: ImagePullPolicy(), Env: c.bpffsEnvvars(), Command: command, SecurityContext: securitycontext.NewRootContext(true), @@ -1355,7 +1352,6 @@ func (c *nodeComponent) nodeContainer() corev1.Container { return corev1.Container{ Name: CalicoNodeObjectName, Image: c.nodeImage, - ImagePullPolicy: ImagePullPolicy(), Resources: c.nodeResources(), SecurityContext: sc, Env: c.nodeEnvVars(), diff --git a/pkg/render/packet_capture_api.go b/pkg/render/packet_capture_api.go index 8015fc443c..0e43bd1dbc 100644 --- a/pkg/render/packet_capture_api.go +++ b/pkg/render/packet_capture_api.go @@ -304,7 +304,6 @@ func (pc *packetCaptureApiComponent) container() corev1.Container { return corev1.Container{ Name: PacketCaptureContainerName, Image: pc.image, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "packetcapture"}, LivenessProbe: pc.healthProbe(), ReadinessProbe: pc.healthProbe(), diff --git a/pkg/render/packet_capture_api_test.go b/pkg/render/packet_capture_api_test.go index f0cea6e85a..d4b1839b7f 100644 --- a/pkg/render/packet_capture_api_test.go +++ b/pkg/render/packet_capture_api_test.go @@ -191,10 +191,9 @@ var _ = Describe("Rendering tests for PacketCapture API component", func() { return []corev1.Container{ { - Name: render.PacketCaptureContainerName, - Image: fmt.Sprintf("%s%s%s:%s", components.TigeraRegistry, components.TigeraImagePath, components.ComponentTigeraCalico.Image, components.ComponentTigeraCalico.Version), - Command: []string{components.CalicoBinaryPath, "component", "packetcapture"}, - ImagePullPolicy: render.ImagePullPolicy(), + Name: render.PacketCaptureContainerName, + Image: fmt.Sprintf("%s%s%s:%s", components.TigeraRegistry, components.TigeraImagePath, components.ComponentTigeraCalico.Image, components.ComponentTigeraCalico.Version), + Command: []string{components.CalicoBinaryPath, "component", "packetcapture"}, SecurityContext: &corev1.SecurityContext{ AllowPrivilegeEscalation: ptr.To(false), Capabilities: &corev1.Capabilities{ diff --git a/pkg/render/policyrecommendation.go b/pkg/render/policyrecommendation.go index 9526d9d2a9..7d2a9afdb9 100644 --- a/pkg/render/policyrecommendation.go +++ b/pkg/render/policyrecommendation.go @@ -360,7 +360,6 @@ func (pr *policyRecommendationComponent) deployment() *appsv1.Deployment { controllerContainer := corev1.Container{ Name: "policy-recommendation-controller", Image: pr.image, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "policy-recommendation"}, Env: envs, SecurityContext: securitycontext.NewNonRootContext(), diff --git a/pkg/render/render.go b/pkg/render/render.go index 60993124c2..28fe4537c2 100644 --- a/pkg/render/render.go +++ b/pkg/render/render.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2024 Tigera, Inc. All rights reserved. +// Copyright (c) 2019-2026 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -44,8 +44,3 @@ func setNodeCriticalPod(t *corev1.PodTemplateSpec) { func SetClusterCriticalPod(t *corev1.PodTemplateSpec) { t.Spec.PriorityClassName = ClusterPriorityClassName } - -// ImagePullPolicy returns the image pull policy to use for all components. -func ImagePullPolicy() corev1.PullPolicy { - return corev1.PullIfNotPresent -} diff --git a/pkg/render/render_test.go b/pkg/render/render_test.go index 28f320109a..2b97cfaeb9 100644 --- a/pkg/render/render_test.go +++ b/pkg/render/render_test.go @@ -208,12 +208,6 @@ var _ = Describe("Rendering tests", func() { } }) - It("should render IfNotPresent image pull policy", func() { - // This test ensures we don't accidentally commit a change that switches the - // default image pull policy to Always as part of development. - Expect(render.ImagePullPolicy()).To(Equal(corev1.PullIfNotPresent)) - }) - It("should render all resources for a default configuration", func() { // For this scenario, we expect the basic resources // created by the controller without any optional ones. These include: diff --git a/pkg/render/typha.go b/pkg/render/typha.go index 19350ab571..c83f2d3544 100644 --- a/pkg/render/typha.go +++ b/pkg/render/typha.go @@ -561,7 +561,6 @@ func (c *typhaComponent) typhaContainer() corev1.Container { return corev1.Container{ Name: TyphaContainerName, Image: c.typhaImage, - ImagePullPolicy: ImagePullPolicy(), Command: []string{components.CalicoBinaryPath, "component", "typha"}, Resources: c.typhaResources(), Env: c.typhaEnvVars(c.cfg.TLS.TyphaSecret), diff --git a/pkg/render/whisker/component.go b/pkg/render/whisker/component.go index d87a8f052d..2642021f6b 100644 --- a/pkg/render/whisker/component.go +++ b/pkg/render/whisker/component.go @@ -157,9 +157,8 @@ func (c *Component) serviceAccount() *corev1.ServiceAccount { func (c *Component) whiskerContainer() corev1.Container { return corev1.Container{ - Name: WhiskerContainerName, - Image: c.whiskerImage, - ImagePullPolicy: render.ImagePullPolicy(), + Name: WhiskerContainerName, + Image: c.whiskerImage, Env: []corev1.EnvVar{ {Name: "LOG_LEVEL", Value: "INFO"}, {Name: "CALICO_VERSION", Value: c.cfg.CalicoVersion}, @@ -195,10 +194,9 @@ func (c *Component) whiskerService() *corev1.Service { func (c *Component) whiskerBackendContainer() corev1.Container { return corev1.Container{ - Name: WhiskerBackendContainerName, - Image: c.whiskerBackendImage, - ImagePullPolicy: render.ImagePullPolicy(), - Command: []string{components.CalicoBinaryPath, "component", "whisker-backend"}, + Name: WhiskerBackendContainerName, + Image: c.whiskerBackendImage, + Command: []string{components.CalicoBinaryPath, "component", "whisker-backend"}, Env: []corev1.EnvVar{ {Name: "LOG_LEVEL", Value: "INFO"}, {Name: "PORT", Value: "3002"}, diff --git a/pkg/render/whisker/component_test.go b/pkg/render/whisker/component_test.go index 9ceda16a98..3fae01728c 100644 --- a/pkg/render/whisker/component_test.go +++ b/pkg/render/whisker/component_test.go @@ -27,7 +27,6 @@ import ( "k8s.io/utils/ptr" operatorv1 "github.com/tigera/operator/api/v1" - "github.com/tigera/operator/pkg/render" rmeta "github.com/tigera/operator/pkg/render/common/meta" "github.com/tigera/operator/pkg/render/common/securitycontext" rtest "github.com/tigera/operator/pkg/render/common/test" @@ -118,9 +117,8 @@ var _ = Describe("ComponentRendering", func() { Tolerations: append(rmeta.TolerateCriticalAddonsAndControlPlane, rmeta.TolerateGKEARM64NoSchedule), Containers: []corev1.Container{ { - Name: whisker.WhiskerContainerName, - Image: "quay.io/calico/whisker:master", - ImagePullPolicy: render.ImagePullPolicy(), + Name: whisker.WhiskerContainerName, + Image: "quay.io/calico/whisker:master", Env: []corev1.EnvVar{ {Name: "LOG_LEVEL", Value: "INFO"}, {Name: "CALICO_VERSION", Value: "test-calico-version"}, @@ -138,10 +136,9 @@ var _ = Describe("ComponentRendering", func() { }, }, { - Name: whisker.WhiskerBackendContainerName, - Image: "quay.io/calico/calico:master", - Command: []string{"/usr/bin/calico", "component", "whisker-backend"}, - ImagePullPolicy: render.ImagePullPolicy(), + Name: whisker.WhiskerBackendContainerName, + Image: "quay.io/calico/calico:master", + Command: []string{"/usr/bin/calico", "component", "whisker-backend"}, Env: []corev1.EnvVar{ {Name: "LOG_LEVEL", Value: "INFO"}, {Name: "PORT", Value: "3002"},