Skip to content

Commit 993a736

Browse files
ImagePullPolicy support for GitOps Service (#992)
* added imagePullPolicy config for gitops-service Signed-off-by: Alka Kumari <[email protected]> * added ginkgo test cases for imagePullPolicy feature in Gitops Servicee Signed-off-by: Alka Kumari <[email protected]> * updated the manifest files Signed-off-by: Alka Kumari <[email protected]> * added ginkgo test case for subscription env variable for imagePullPolicy Signed-off-by: Alka Kumari <[email protected]> * moved imagepullpolicy test for backend deployment and plugin deployment to sequential folder Signed-off-by: Alka Kumari <[email protected]> * Enabled plugin deployment in ginkgo test cases Signed-off-by: Alka Kumari <[email protected]> * corrected setting up emv var Signed-off-by: Alka Kumari <[email protected]> * typo in ginkgo test case Signed-off-by: Alka Kumari <[email protected]> * changed os.setenv in ginkgo tes cases Signed-off-by: Alka Kumari <[email protected]> * Reused upstream GetImagePullPolicy Signed-off-by: Alka Kumari <[email protected]> * downstreamed new GetImagePullPolicy function from argocd-operator Signed-off-by: Alka Kumari <[email protected]> * changed logic to set env variable in csv Signed-off-by: Alka Kumari <[email protected]> * removed unwanted code from imagepullpolicy ginkgo test case Signed-off-by: Alka Kumari <[email protected]> * commented ginkgo test case which was not working as expected Signed-off-by: Alka Kumari <[email protected]> --------- Signed-off-by: Alka Kumari <[email protected]>
1 parent 35d543b commit 993a736

14 files changed

+466
-27
lines changed

api/v1alpha1/gitopsservice_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type GitopsServiceSpec struct {
3434
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
3535
// ConsolePlugin defines the Resource configuration for the Console Plugin components
3636
ConsolePlugin *ConsolePluginStruct `json:"consolePlugin,omitempty"`
37+
// ImagePullPolicy defines the image pull policy for GitOps workloads
38+
// +kubebuilder:validation:Enum=Always;IfNotPresent;Never
39+
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
3740
}
3841

3942
// ConsolePluginStruct defines the resource configuration for the Console Plugin components

bundle/manifests/gitops-operator.clusterserviceversion.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ metadata:
180180
capabilities: Deep Insights
181181
console.openshift.io/plugins: '["gitops-plugin"]'
182182
containerImage: quay.io/redhat-developer/gitops-operator
183-
createdAt: "2025-11-03T15:21:29Z"
183+
createdAt: "2025-11-04T06:20:36Z"
184184
description: Enables teams to adopt GitOps principles for managing cluster configurations
185185
and application delivery across hybrid multi-cluster Kubernetes environments.
186186
features.operators.openshift.io/disconnected: "true"

bundle/manifests/pipelines.openshift.io_gitopsservices.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,14 @@ spec:
174174
type: object
175175
type: object
176176
type: object
177+
imagePullPolicy:
178+
description: ImagePullPolicy defines the image pull policy for GitOps
179+
workloads
180+
enum:
181+
- Always
182+
- IfNotPresent
183+
- Never
184+
type: string
177185
nodeSelector:
178186
additionalProperties:
179187
type: string

common/common.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ limitations under the License.
1616

1717
package common
1818

19-
import "os"
19+
import (
20+
"os"
21+
)
2022

2123
const (
2224
// ArgoCDInstanceName is the default Argo CD instance name
@@ -33,6 +35,8 @@ const (
3335
DefaultConsoleVersion = "v0.1.0"
3436
// Default console plugin installation OCP version
3537
DefaultDynamicPluginStartOCPVersion = "4.15.0"
38+
// ImagePullPolicyEnvVar is the environment variable for configuring image pull policy
39+
ImagePullPolicy = "IMAGE_PULL_POLICY"
3640
)
3741

3842
// InfraNodeSelector returns openshift label for infrastructure nodes

config/crd/bases/pipelines.openshift.io_gitopsservices.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,14 @@ spec:
174174
type: object
175175
type: object
176176
type: object
177+
imagePullPolicy:
178+
description: ImagePullPolicy defines the image pull policy for GitOps
179+
workloads
180+
enum:
181+
- Always
182+
- IfNotPresent
183+
- Never
184+
type: string
177185
nodeSelector:
178186
additionalProperties:
179187
type: string

controllers/consoleplugin.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const (
4444
kubeAppLabelName = "app.kubernetes.io/name"
4545
)
4646

47-
func getPluginPodSpec() corev1.PodSpec {
47+
func getPluginPodSpec(crImagePullPolicy corev1.PullPolicy) corev1.PodSpec {
4848
consolePluginImage := os.Getenv(pluginImageEnv)
4949
if consolePluginImage == "" {
5050
image := common.DefaultConsoleImage
@@ -58,7 +58,7 @@ func getPluginPodSpec() corev1.PodSpec {
5858
Env: util.ProxyEnvVars(),
5959
Name: gitopsPluginName,
6060
Image: consolePluginImage,
61-
ImagePullPolicy: corev1.PullAlways,
61+
ImagePullPolicy: argocdutil.GetImagePullPolicy(crImagePullPolicy),
6262
Ports: []corev1.ContainerPort{
6363
{
6464
Name: "http",
@@ -133,8 +133,8 @@ func getPluginPodSpec() corev1.PodSpec {
133133
return podSpec
134134
}
135135

136-
func pluginDeployment() *appsv1.Deployment {
137-
podSpec := getPluginPodSpec()
136+
func pluginDeployment(crImagePullPolicy corev1.PullPolicy) *appsv1.Deployment {
137+
podSpec := getPluginPodSpec(crImagePullPolicy)
138138
template := corev1.PodTemplateSpec{
139139
ObjectMeta: metav1.ObjectMeta{
140140
Labels: map[string]string{
@@ -269,7 +269,7 @@ func pluginConfigMap() *corev1.ConfigMap {
269269

270270
func (r *ReconcileGitopsService) reconcileDeployment(cr *pipelinesv1alpha1.GitopsService, request reconcile.Request) (reconcile.Result, error) {
271271
reqLogger := logs.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
272-
newPluginDeployment := pluginDeployment()
272+
newPluginDeployment := pluginDeployment(cr.Spec.ImagePullPolicy)
273273

274274
if err := controllerutil.SetControllerReference(cr, newPluginDeployment, r.Scheme); err != nil {
275275
return reconcile.Result{}, err

controllers/consoleplugin_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ func TestPlugin_reconcileDeployment_changedContainers(t *testing.T) {
625625
consoleImage := common.DefaultConsoleImage + ":" + common.DefaultConsoleVersion
626626
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Name, "gitops-plugin")
627627
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Image, consoleImage)
628-
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy, corev1.PullAlways)
628+
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy, corev1.PullIfNotPresent)
629629
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Ports[0].Name, "http")
630630
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Ports[0].Protocol, corev1.ProtocolTCP)
631631
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort, int32(9001))

controllers/gitopsservice_controller.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ func (r *ReconcileGitopsService) reconcileBackend(gitopsserviceNamespacedName ty
607607

608608
// Define a new backend Deployment
609609
{
610-
deploymentObj := newBackendDeployment(gitopsserviceNamespacedName)
610+
deploymentObj := newBackendDeployment(gitopsserviceNamespacedName, instance.Spec.ImagePullPolicy)
611611

612612
// Add SeccompProfile based on cluster version
613613
util.AddSeccompProfileForOpenShift(r.Client, &deploymentObj.Spec.Template.Spec)
@@ -654,6 +654,10 @@ func (r *ReconcileGitopsService) reconcileBackend(gitopsserviceNamespacedName ty
654654
found.Spec.Template.Spec.Containers[0].Env = deploymentObj.Spec.Template.Spec.Containers[0].Env
655655
changed = true
656656
}
657+
if !reflect.DeepEqual(found.Spec.Template.Spec.Containers[0].ImagePullPolicy, deploymentObj.Spec.Template.Spec.Containers[0].ImagePullPolicy) {
658+
found.Spec.Template.Spec.Containers[0].ImagePullPolicy = deploymentObj.Spec.Template.Spec.Containers[0].ImagePullPolicy
659+
changed = true
660+
}
657661
if !reflect.DeepEqual(found.Spec.Template.Spec.Containers[0].Resources, deploymentObj.Spec.Template.Spec.Containers[0].Resources) {
658662
found.Spec.Template.Spec.Containers[0].Resources = deploymentObj.Spec.Template.Spec.Containers[0].Resources
659663
changed = true
@@ -744,16 +748,17 @@ func objectMeta(resourceName string, namespace string, opts ...func(*metav1.Obje
744748
return objectMeta
745749
}
746750

747-
func newBackendDeployment(ns types.NamespacedName) *appsv1.Deployment {
751+
func newBackendDeployment(ns types.NamespacedName, crImagePullPolicy corev1.PullPolicy) *appsv1.Deployment {
748752
image := os.Getenv(backendImageEnvName)
749753
if image == "" {
750754
image = backendImage
751755
}
752756
podSpec := corev1.PodSpec{
753757
Containers: []corev1.Container{
754758
{
755-
Name: ns.Name,
756-
Image: image,
759+
Name: ns.Name,
760+
Image: image,
761+
ImagePullPolicy: argocdutil.GetImagePullPolicy(crImagePullPolicy),
757762
Ports: []corev1.ContainerPort{
758763
{
759764
Name: "http",

controllers/gitopsservice_controller_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ func TestImageFromEnvVariable(t *testing.T) {
5454
image := "quay.io/org/test"
5555
t.Setenv(backendImageEnvName, image)
5656

57-
deployment := newBackendDeployment(ns)
57+
deployment := newBackendDeployment(ns, corev1.PullPolicy(corev1.PullIfNotPresent))
5858

5959
got := deployment.Spec.Template.Spec.Containers[0].Image
6060
if got != image {
6161
t.Errorf("Image mismatch: got %s, want %s", got, image)
6262
}
6363
})
6464
t.Run("env variable for image not found", func(t *testing.T) {
65-
deployment := newBackendDeployment(ns)
65+
deployment := newBackendDeployment(ns, corev1.PullPolicy(corev1.PullIfNotPresent))
6666

6767
got := deployment.Spec.Template.Spec.Containers[0].Image
6868
if got != backendImage {

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.24.6
44

55
require (
66
github.com/argoproj-labs/argo-rollouts-manager v0.0.7-0.20251029155400-4619e3168941
7-
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251024105544-f7c3f5b0cc95
7+
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251104052658-38b9581ce39a
88
github.com/argoproj/argo-cd/v3 v3.1.8
99
github.com/argoproj/gitops-engine v0.7.1-0.20250905160054-e48120133eec
1010
github.com/go-logr/logr v1.4.3
@@ -16,7 +16,7 @@ require (
1616
github.com/openshift/api v0.0.0-20240906151052-5d963dce87aa
1717
github.com/operator-framework/api v0.17.5
1818
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.73.2
19-
github.com/stretchr/testify v1.10.0
19+
github.com/stretchr/testify v1.11.1
2020
go.uber.org/zap v1.27.0
2121
golang.org/x/mod v0.28.0
2222
gotest.tools v2.2.0+incompatible

0 commit comments

Comments
 (0)