Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/v1alpha1/gitopsservice_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type GitopsServiceSpec struct {
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
// ConsolePlugin defines the Resource configuration for the Console Plugin components
ConsolePlugin *ConsolePluginStruct `json:"consolePlugin,omitempty"`
// ImagePullPolicy defines the image pull policy for GitOps workloads
// +kubebuilder:validation:Enum=Always;IfNotPresent;Never
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
}

// ConsolePluginStruct defines the resource configuration for the Console Plugin components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ metadata:
capabilities: Deep Insights
console.openshift.io/plugins: '["gitops-plugin"]'
containerImage: quay.io/redhat-developer/gitops-operator
createdAt: "2025-11-03T15:21:29Z"
createdAt: "2025-11-04T06:20:36Z"
description: Enables teams to adopt GitOps principles for managing cluster configurations
and application delivery across hybrid multi-cluster Kubernetes environments.
features.operators.openshift.io/disconnected: "true"
Expand Down
8 changes: 8 additions & 0 deletions bundle/manifests/pipelines.openshift.io_gitopsservices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ spec:
type: object
type: object
type: object
imagePullPolicy:
description: ImagePullPolicy defines the image pull policy for GitOps
workloads
enum:
- Always
- IfNotPresent
- Never
type: string
nodeSelector:
additionalProperties:
type: string
Expand Down
6 changes: 5 additions & 1 deletion common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ limitations under the License.

package common

import "os"
import (
"os"
)

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

// InfraNodeSelector returns openshift label for infrastructure nodes
Expand Down
8 changes: 8 additions & 0 deletions config/crd/bases/pipelines.openshift.io_gitopsservices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ spec:
type: object
type: object
type: object
imagePullPolicy:
description: ImagePullPolicy defines the image pull policy for GitOps
workloads
enum:
- Always
- IfNotPresent
- Never
type: string
nodeSelector:
additionalProperties:
type: string
Expand Down
10 changes: 5 additions & 5 deletions controllers/consoleplugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const (
kubeAppLabelName = "app.kubernetes.io/name"
)

func getPluginPodSpec() corev1.PodSpec {
func getPluginPodSpec(crImagePullPolicy corev1.PullPolicy) corev1.PodSpec {
consolePluginImage := os.Getenv(pluginImageEnv)
if consolePluginImage == "" {
image := common.DefaultConsoleImage
Expand All @@ -58,7 +58,7 @@ func getPluginPodSpec() corev1.PodSpec {
Env: util.ProxyEnvVars(),
Name: gitopsPluginName,
Image: consolePluginImage,
ImagePullPolicy: corev1.PullAlways,
ImagePullPolicy: argocdutil.GetImagePullPolicy(crImagePullPolicy),
Ports: []corev1.ContainerPort{
{
Name: "http",
Expand Down Expand Up @@ -133,8 +133,8 @@ func getPluginPodSpec() corev1.PodSpec {
return podSpec
}

func pluginDeployment() *appsv1.Deployment {
podSpec := getPluginPodSpec()
func pluginDeployment(crImagePullPolicy corev1.PullPolicy) *appsv1.Deployment {
podSpec := getPluginPodSpec(crImagePullPolicy)
template := corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
Expand Down Expand Up @@ -269,7 +269,7 @@ func pluginConfigMap() *corev1.ConfigMap {

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

if err := controllerutil.SetControllerReference(cr, newPluginDeployment, r.Scheme); err != nil {
return reconcile.Result{}, err
Expand Down
2 changes: 1 addition & 1 deletion controllers/consoleplugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ func TestPlugin_reconcileDeployment_changedContainers(t *testing.T) {
consoleImage := common.DefaultConsoleImage + ":" + common.DefaultConsoleVersion
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Name, "gitops-plugin")
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Image, consoleImage)
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy, corev1.PullAlways)
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy, corev1.PullIfNotPresent)
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Ports[0].Name, "http")
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Ports[0].Protocol, corev1.ProtocolTCP)
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort, int32(9001))
Expand Down
13 changes: 9 additions & 4 deletions controllers/gitopsservice_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ func (r *ReconcileGitopsService) reconcileBackend(gitopsserviceNamespacedName ty

// Define a new backend Deployment
{
deploymentObj := newBackendDeployment(gitopsserviceNamespacedName)
deploymentObj := newBackendDeployment(gitopsserviceNamespacedName, instance.Spec.ImagePullPolicy)

// Add SeccompProfile based on cluster version
util.AddSeccompProfileForOpenShift(r.Client, &deploymentObj.Spec.Template.Spec)
Expand Down Expand Up @@ -654,6 +654,10 @@ func (r *ReconcileGitopsService) reconcileBackend(gitopsserviceNamespacedName ty
found.Spec.Template.Spec.Containers[0].Env = deploymentObj.Spec.Template.Spec.Containers[0].Env
changed = true
}
if !reflect.DeepEqual(found.Spec.Template.Spec.Containers[0].ImagePullPolicy, deploymentObj.Spec.Template.Spec.Containers[0].ImagePullPolicy) {
found.Spec.Template.Spec.Containers[0].ImagePullPolicy = deploymentObj.Spec.Template.Spec.Containers[0].ImagePullPolicy
changed = true
}
if !reflect.DeepEqual(found.Spec.Template.Spec.Containers[0].Resources, deploymentObj.Spec.Template.Spec.Containers[0].Resources) {
found.Spec.Template.Spec.Containers[0].Resources = deploymentObj.Spec.Template.Spec.Containers[0].Resources
changed = true
Expand Down Expand Up @@ -744,16 +748,17 @@ func objectMeta(resourceName string, namespace string, opts ...func(*metav1.Obje
return objectMeta
}

func newBackendDeployment(ns types.NamespacedName) *appsv1.Deployment {
func newBackendDeployment(ns types.NamespacedName, crImagePullPolicy corev1.PullPolicy) *appsv1.Deployment {
image := os.Getenv(backendImageEnvName)
if image == "" {
image = backendImage
}
podSpec := corev1.PodSpec{
Containers: []corev1.Container{
{
Name: ns.Name,
Image: image,
Name: ns.Name,
Image: image,
ImagePullPolicy: argocdutil.GetImagePullPolicy(crImagePullPolicy),
Ports: []corev1.ContainerPort{
{
Name: "http",
Expand Down
4 changes: 2 additions & 2 deletions controllers/gitopsservice_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ func TestImageFromEnvVariable(t *testing.T) {
image := "quay.io/org/test"
t.Setenv(backendImageEnvName, image)

deployment := newBackendDeployment(ns)
deployment := newBackendDeployment(ns, corev1.PullPolicy(corev1.PullIfNotPresent))

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

got := deployment.Spec.Template.Spec.Containers[0].Image
if got != backendImage {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.24.6

require (
github.com/argoproj-labs/argo-rollouts-manager v0.0.7-0.20251029155400-4619e3168941
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251024105544-f7c3f5b0cc95
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251104052658-38b9581ce39a
github.com/argoproj/argo-cd/v3 v3.1.8
github.com/argoproj/gitops-engine v0.7.1-0.20250905160054-e48120133eec
github.com/go-logr/logr v1.4.3
Expand All @@ -16,7 +16,7 @@ require (
github.com/openshift/api v0.0.0-20240906151052-5d963dce87aa
github.com/operator-framework/api v0.17.5
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.73.2
github.com/stretchr/testify v1.10.0
github.com/stretchr/testify v1.11.1
go.uber.org/zap v1.27.0
golang.org/x/mod v0.28.0
gotest.tools v2.2.0+incompatible
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/argoproj-labs/argo-rollouts-manager v0.0.7-0.20251029155400-4619e3168941 h1:uqkUVemiOX050ktlgbyYs4jef38HRU17C9sTzHTL9JU=
github.com/argoproj-labs/argo-rollouts-manager v0.0.7-0.20251029155400-4619e3168941/go.mod h1:WPyZkNHZjir/OTt8mrRwcUZKe1euHrHPJsRv1Wp/F/0=
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251024105544-f7c3f5b0cc95 h1:v2J4IPd8Fab5udUD7nMZsYflqGDhkVGx30q5uenMBbE=
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251024105544-f7c3f5b0cc95/go.mod h1:LTBNqNbKk9Us5xiCrK612HLOr8SJFfyxlMJQErzMghg=
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251104052658-38b9581ce39a h1:MruEtChFnhTI8Owa1Boqo7BChWxnVRkyhN1/dsg/VgQ=
github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20251104052658-38b9581ce39a/go.mod h1:ABtgKWsvMlUp6Xys8BVi0CHKdT9ZoFP+rYCqRsY0wvg=
github.com/argoproj/argo-cd/v3 v3.1.8 h1:NkLPiRI5qGkV+q1EN3O7/0Wb9O/MVl62vadKteZqMUw=
github.com/argoproj/argo-cd/v3 v3.1.8/go.mod h1:ZHb/LOz/hr88VWMJiVTd8DGYL7MheHCAT8S6DgYOBFo=
github.com/argoproj/gitops-engine v0.7.1-0.20250905160054-e48120133eec h1:rNAwbRQFvRIuW/e2bU+B10mlzghYXsnwZedYeA7Drz4=
Expand Down Expand Up @@ -358,8 +358,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/vmihailenco/go-tinylfu v0.2.2 h1:H1eiG6HM36iniK6+21n9LLpzx1G9R3DJa2UjUjbynsI=
github.com/vmihailenco/go-tinylfu v0.2.2/go.mod h1:CutYi2Q9puTxfcolkliPq4npPuofg9N9t8JVrjzwa3Q=
github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
Expand Down
2 changes: 1 addition & 1 deletion test/openshift/e2e/ginkgo/fixture/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ func RestoreSubcriptionToDefault() {
Expect(err).ToNot(HaveOccurred())

// optionalEnvVarsToRemove is a non-exhaustive list of environment variables that are known to be added to Subscription or operator Deployment by tests
optionalEnvVarsToRemove := []string{"DISABLE_DEFAULT_ARGOCD_CONSOLELINK", "CONTROLLER_CLUSTER_ROLE", "SERVER_CLUSTER_ROLE", "ARGOCD_LABEL_SELECTOR", "ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES"}
optionalEnvVarsToRemove := []string{"DISABLE_DEFAULT_ARGOCD_CONSOLELINK", "CONTROLLER_CLUSTER_ROLE", "SERVER_CLUSTER_ROLE", "ARGOCD_LABEL_SELECTOR", "ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "IMAGE_PULL_POLICY"}

if EnvNonOLM() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
)

Expand Down Expand Up @@ -61,7 +60,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() {
argoCD := &argov1beta1api.ArgoCD{
ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name},
Spec: argov1beta1api.ArgoCDSpec{
ImagePullPolicy: &policy,
ImagePullPolicy: policy,
},
}
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
Expand Down Expand Up @@ -115,7 +114,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() {
By("updating ArgoCD instance to use imagePullPolicy IfNotPresent")
policy = corev1.PullIfNotPresent
argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
ac.Spec.ImagePullPolicy = &policy
ac.Spec.ImagePullPolicy = policy
})

By("waiting for ArgoCD to reconcile the change")
Expand Down Expand Up @@ -150,13 +149,13 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() {

By("updating openshift-gitops ArgoCD to set imagePullPolicy to Always")
argocdFixture.Update(openshiftGitopsArgoCD, func(ac *argov1beta1api.ArgoCD) {
ac.Spec.ImagePullPolicy = ptr.To(corev1.PullAlways)
ac.Spec.ImagePullPolicy = corev1.PullAlways
})

defer func() {
By("restoring openshift-gitops ArgoCD imagePullPolicy to default after test")
argocdFixture.Update(openshiftGitopsArgoCD, func(ac *argov1beta1api.ArgoCD) {
ac.Spec.ImagePullPolicy = nil
ac.Spec.ImagePullPolicy = ""
})
}()

Expand Down Expand Up @@ -361,7 +360,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() {
argoCD3 := &argov1beta1api.ArgoCD{
ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns3.Name},
Spec: argov1beta1api.ArgoCDSpec{
ImagePullPolicy: &policy,
ImagePullPolicy: policy,
},
}
Expect(k8sClient.Create(ctx, argoCD3)).To(Succeed())
Expand Down
Loading