Skip to content

Commit

Permalink
Add labelSelector option to filter the ArgoCD instances for reconcili…
Browse files Browse the repository at this point in the history
…ation (#961)

* Added labelselector string to map conversion

Signed-off-by: Raghavi Shirur <[email protected]>

* Changed data-type for labelSelector to parse string

Signed-off-by: Raghavi Shirur <[email protected]>

* Added code to reconcile selected ArgoCD instances based on label selector

Signed-off-by: Raghavi Shirur <[email protected]>

* remove comments

Signed-off-by: Raghavi Shirur <[email protected]>

* Updated argoCD label fetch, renamed env var

Signed-off-by: Raghavi Shirur <[email protected]>

* Updated unit test and yaml

Signed-off-by: Raghavi Shirur <[email protected]>

* Updated unit test

Signed-off-by: Raghavi Shirur <[email protected]>

* Fix yaml env ValueFrom field

Signed-off-by: Raghavi Shirur <[email protected]>

* Added comments and labelSelector check in main.go

Signed-off-by: Raghavi Shirur <[email protected]>

* removed label-selector option from manifest

Signed-off-by: Raghavi Shirur <[email protected]>

* updated label-selector format in manifests

Signed-off-by: Raghavi Shirur <[email protected]>

* added label selector logs

Signed-off-by: Raghavi Shirur <[email protected]>

* go mod tidy

Signed-off-by: Raghavi Shirur <[email protected]>

* added e2e tests for label-selector

Signed-off-by: Raghavi Shirur <[email protected]>

* restructured kuttl files and added operator patch file

Signed-off-by: Raghavi Shirur <[email protected]>

* go mod tidy

Signed-off-by: Raghavi Shirur <[email protected]>

* corrected kuttl tests for cm failure

Signed-off-by: Raghavi Shirur <[email protected]>

* Added documentation for Environment Variable ARGOCD_LABEL_SELECTOR

Signed-off-by: Raghavi Shirur <[email protected]>

* cleanup

Signed-off-by: Raghavi Shirur <[email protected]>

* improved unit tests and some minor changes

Signed-off-by: Raghavi Shirur <[email protected]>

* kuttl rerun

Signed-off-by: Raghavi Shirur <[email protected]>

* removed env var

Signed-off-by: Raghavi Shirur <[email protected]>

* misc modifications

Signed-off-by: Raghavi Shirur <[email protected]>

* argocd-operator csv correction

Signed-off-by: Raghavi Shirur <[email protected]>

* fix bundle error

Signed-off-by: Raghavi Shirur <[email protected]>

* fix bundle error

Signed-off-by: Raghavi Shirur <[email protected]>

* fix manifests build

Signed-off-by: Raghavi Shirur <[email protected]>
Signed-off-by: Ishita Sequeira <[email protected]>
Signed-off-by: Raghavi Shirur <[email protected]>

* Added more unit test cases

Signed-off-by: Raghavi Shirur <[email protected]>

* rebase

Signed-off-by: Raghavi Shirur <[email protected]>

* removed excess reconcilers

Signed-off-by: Raghavi Shirur <[email protected]>

* minor fix

Signed-off-by: Raghavi Shirur <[email protected]>

* removed extraneous test case and cleaned manager.yaml

Signed-off-by: Raghavi Shirur <[email protected]>

* cleaned manager.yaml

Signed-off-by: Raghavi Shirur <[email protected]>

* fix make bundle issue

Signed-off-by: Raghavi Shirur <[email protected]>

* fix make bundle issue

Signed-off-by: Raghavi Shirur <[email protected]>

---------

Signed-off-by: Raghavi Shirur <[email protected]>
Signed-off-by: Ishita Sequeira <[email protected]>
Co-authored-by: ishitasequeira <[email protected]>
  • Loading branch information
raghavi101 and ishitasequeira authored Oct 19, 2023
1 parent 6b3fbb6 commit 5a2e6c4
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 2 deletions.
3 changes: 3 additions & 0 deletions common/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ const (
// ArgoCDKeycloakImage is the default Keycloak Image used for the non-openshift platforms when not specified.
ArgoCDKeycloakImage = "quay.io/keycloak/keycloak"

// ArgoCDDefaultLabelSelector is the default Label Selector which will reconcile all ArgoCD instances.
ArgoCDDefaultLabelSelector = ""

// ArgoCDKeycloakVersion is the default Keycloak version used for the non-openshift platform when not specified.
// Version: 15.0.2
ArgoCDKeycloakVersion = "sha256:64fb81886fde61dee55091e6033481fa5ccdac62ae30a4fd29b54eb5e97df6a9"
Expand Down
3 changes: 3 additions & 0 deletions common/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,7 @@ const (

// ArgoCDDexSecretKey is used to reference Dex secret from Argo CD secret into Argo CD configmap
ArgoCDDexSecretKey = "oidc.dex.clientSecret"

// Label Selector is an env variable for ArgoCD instance reconcilliation.
ArgoCDLabelSelectorKey = "ARGOCD_LABEL_SELECTOR"
)
15 changes: 15 additions & 0 deletions controllers/argocd/argocd_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"

ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -46,6 +47,8 @@ type ReconcileArgoCD struct {
ManagedNamespaces *corev1.NamespaceList
// Stores a list of SourceNamespaces as values
ManagedSourceNamespaces map[string]string
// Stores label selector used to reconcile a subset of ArgoCD
LabelSelector string
}

var log = logr.Log.WithName("controller_argocd")
Expand Down Expand Up @@ -105,6 +108,18 @@ func (r *ReconcileArgoCD) Reconcile(ctx context.Context, request ctrl.Request) (
return reconcile.Result{}, err
}

// Fetch labelSelector from r.LabelSelector (command-line option)
labelSelector, err := labels.Parse(r.LabelSelector)
if err != nil {
reqLogger.Info(fmt.Sprintf("error parsing the labelSelector '%s'.", labelSelector))
return reconcile.Result{}, err
}
// Match the value of labelSelector from ReconcileArgoCD to labels from the argocd instance
if !labelSelector.Matches(labels.Set(argocd.Labels)) {
reqLogger.Info(fmt.Sprintf("the ArgoCD instance '%s' does not match the label selector '%s' and skipping for reconciliation", request.NamespacedName, r.LabelSelector))
return reconcile.Result{}, fmt.Errorf("Error: failed to reconcile ArgoCD instance: '%s'", request.NamespacedName)
}

newPhase := argocd.Status.Phase
// If we discover a new Argo CD instance in a previously un-seen namespace
// we add it to the map and increment active instance count by phase
Expand Down
101 changes: 101 additions & 0 deletions controllers/argocd/argocd_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,107 @@ func TestReconcileArgoCD_Reconcile(t *testing.T) {
}
}

func TestReconcileArgoCD_LabelSelector(t *testing.T) {
logf.SetLogger(ZapLogger(true))
//ctx := context.Background()
a := makeTestArgoCD(func(ac *argoproj.ArgoCD) {
ac.Name = "argo-test-1"
ac.Labels = map[string]string{"foo": "bar"}
})
b := makeTestArgoCD(func(ac *argoproj.ArgoCD) {
ac.Name = "argo-test-2"
ac.Labels = map[string]string{"testfoo": "testbar"}
})
c := makeTestArgoCD(func(ac *argoproj.ArgoCD) {
ac.Name = "argo-test-3"
})
rt := makeTestReconciler(t, a, b, c)
assert.NoError(t, createNamespace(rt, a.Namespace, ""))

// All ArgoCD instances should be reconciled if no label-selctor is applied to the operator.

// Instance 'a'
req1 := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: a.Name,
Namespace: a.Namespace,
},
}
res1, err := rt.Reconcile(context.TODO(), req1)
assert.NoError(t, err)
if res1.Requeue {
t.Fatal("reconcile requeued request")
}

//Instance 'b'
req2 := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: b.Name,
Namespace: b.Namespace,
},
}
res2, err := rt.Reconcile(context.TODO(), req2)
assert.NoError(t, err)
if res2.Requeue {
t.Fatal("reconcile requeued request")
}

//Instance 'c'
req3 := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: c.Name,
Namespace: c.Namespace,
},
}
res3, err := rt.Reconcile(context.TODO(), req3)
assert.NoError(t, err)
if res3.Requeue {
t.Fatal("reconcile requeued request")
}

// Apply label-selector foo=bar to the operator.
// Only Instance a should reconcile with matching label "foo=bar"
// No reconciliation is expected for instance b and c and an error is expected.
rt.LabelSelector = "foo=bar"
reqTest := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: a.Name,
Namespace: a.Namespace,
},
}
resTest, err := rt.Reconcile(context.TODO(), reqTest)
assert.NoError(t, err)
if resTest.Requeue {
t.Fatal("reconcile requeued request")
}

// Instance 'b' is not reconciled as the label does not match, error expected
reqTest2 := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: b.Name,
Namespace: b.Namespace,
},
}
resTest2, err := rt.Reconcile(context.TODO(), reqTest2)
assert.Error(t, err)
if resTest2.Requeue {
t.Fatal("reconcile requeued request")
}

//Instance 'c' is not reconciled as there is no label, error expected
reqTest3 := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: c.Name,
Namespace: c.Namespace,
},
}
resTest3, err := rt.Reconcile(context.TODO(), reqTest3)
assert.Error(t, err)
if resTest3.Requeue {
t.Fatal("reconcile requeued request")
}
}

func TestReconcileArgoCD_Reconcile_RemoveManagedByLabelOnArgocdDeletion(t *testing.T) {
logf.SetLogger(ZapLogger(true))

Expand Down
1 change: 1 addition & 0 deletions docs/usage/environment_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The following environment variables are available in `argocd-operator`:
| `CONTROLLER_CLUSTER_ROLE` | none | Administrators can configure a common cluster role for all the managed namespaces in role bindings for the Argo CD application controller with this environment variable. Note: If this environment variable contains custom roles, the Operator doesn't create the default admin role. Instead, it uses the existing custom role for all managed namespaces. |
| `SERVER_CLUSTER_ROLE` | none | Administrators can configure a common cluster role for all the managed namespaces in role bindings for the Argo CD server with this environment variable. Note: If this environment variable contains custom roles, the Operator doesn’t create the default admin role. Instead, it uses the existing custom role for all managed namespaces. |
| `REMOVE_MANAGED_BY_LABEL_ON_ARGOCD_DELETION` | false | When an Argo CD instance is deleted, namespaces managed by that instance (via the `argocd.argoproj.io/managed-by` label ) will retain the label by default. Users can change this behavior by setting the environment variable `REMOVE_MANAGED_BY_LABEL_ON_ARGOCD_DELETION` to `true` in the Subscription. |
| `ARGOCD_LABEL_SELECTOR` | none | The label selector can be set on argocd-opertor by exporting `ARGOCD_LABEL_SELECTOR` (eg: `export ARGOCD_LABEL_SELECTOR=foo=bar`). The labels can be added to the argocd instances using the command `kubectl label argocd test1 foo=bar -n test-argocd`. This will enable the operator instance to be tailored to oversee only the corresponding ArgoCD instances having the matching label selector. |

Custom Environment Variables are supported in `applicationSet`, `controller`, `notifications`, `repo` and `server` components. For example:

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ require (
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down Expand Up @@ -63,6 +64,7 @@ require (
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.43.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
Expand Down
Loading

0 comments on commit 5a2e6c4

Please sign in to comment.