From c7d3e33229a1a320e910fc1ea160d0b4e23f4cef Mon Sep 17 00:00:00 2001 From: Nikolas Skoufis Date: Mon, 24 Apr 2023 18:14:13 +1000 Subject: [PATCH 01/13] Allow notifications controller to notify on all namespaces This adds functionality to the notifications controller to be notified of and send notifications for applications in any namespace. The namespaces to watch are controlled by the same --application-namespaces and ARGOCD_APPLICATION_NAMESPACES variables as in the application controller. Signed-off-by: Nikolas Skoufis --- Procfile | 2 +- .../commands/controller.go | 4 +- .../controller/controller.go | 51 +++++++++++++------ 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/Procfile b/Procfile index d8557c81ea19a..fc73798547083 100644 --- a/Procfile +++ b/Procfile @@ -9,4 +9,4 @@ git-server: test/fixture/testrepos/start-git.sh helm-registry: test/fixture/testrepos/start-helm-registry.sh dev-mounter: [[ "$ARGOCD_E2E_TEST" != "true" ]] && go run hack/dev-mounter/main.go --configmap argocd-ssh-known-hosts-cm=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} --configmap argocd-tls-certs-cm=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} --configmap argocd-gpg-keys-cm=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} applicationset-controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_ASK_PASS_SOCK=/tmp/applicationset-ask-pass.sock ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-applicationset-controller $COMMAND --loglevel debug --metrics-addr localhost:12345 --probe-addr localhost:12346 --argocd-repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}" -notification: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_BINARY_NAME=argocd-notifications $COMMAND --loglevel debug" +notification: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_BINARY_NAME=argocd-notifications $COMMAND --loglevel debug --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}" diff --git a/cmd/argocd-notification/commands/controller.go b/cmd/argocd-notification/commands/controller.go index f9494ea966313..e07340233bd39 100644 --- a/cmd/argocd-notification/commands/controller.go +++ b/cmd/argocd-notification/commands/controller.go @@ -55,6 +55,7 @@ func NewCommand() *cobra.Command { argocdRepoServerStrictTLS bool configMapName string secretName string + applicationNamespaces []string ) var command = cobra.Command{ Use: "controller", @@ -138,7 +139,7 @@ func NewCommand() *cobra.Command { log.Infof("serving metrics on port %d", metricsPort) log.Infof("loading configuration %d", metricsPort) - ctrl := notificationscontroller.NewController(k8sClient, dynamicClient, argocdService, namespace, appLabelSelector, registry, secretName, configMapName) + ctrl := notificationscontroller.NewController(k8sClient, dynamicClient, argocdService, namespace, applicationNamespaces, appLabelSelector, registry, secretName, configMapName) err = ctrl.Init(ctx) if err != nil { return err @@ -161,5 +162,6 @@ func NewCommand() *cobra.Command { command.Flags().BoolVar(&argocdRepoServerStrictTLS, "argocd-repo-server-strict-tls", false, "Perform strict validation of TLS certificates when connecting to repo server") command.Flags().StringVar(&configMapName, "config-map-name", "argocd-notifications-cm", "Set notifications ConfigMap name") command.Flags().StringVar(&secretName, "secret-name", "argocd-notifications-secret", "Set notifications Secret name") + command.Flags().StringSliceVar(&applicationNamespaces, "application-namespaces", env.StringsFromEnv("ARGOCD_APPLICATION_NAMESPACES", []string{}, ","), "List of additional namespaces that this controller should send notifications for") return &command } diff --git a/notification_controller/controller/controller.go b/notification_controller/controller/controller.go index e975b5c2ded03..88a4028566d7a 100644 --- a/notification_controller/controller/controller.go +++ b/notification_controller/controller/controller.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/argoproj/argo-cd/v2/util/glob" "time" "github.com/argoproj/argo-cd/v2/util/notification/k8s" @@ -38,8 +39,8 @@ var ( appProjects = schema.GroupVersionResource{Group: application.Group, Version: "v1alpha1", Resource: application.AppProjectPlural} ) -func newAppProjClient(client dynamic.Interface, namespace string) dynamic.ResourceInterface { - resClient := client.Resource(appProjects).Namespace(namespace) +func newAppProjClient(client dynamic.Interface) dynamic.ResourceInterface { + resClient := client.Resource(appProjects) return resClient } @@ -53,14 +54,15 @@ func NewController( client dynamic.Interface, argocdService service.Service, namespace string, + applicationNamespaces []string, appLabelSelector string, registry *controller.MetricsRegistry, secretName string, configMapName string, ) *notificationController { appClient := client.Resource(applications) - appInformer := newInformer(appClient.Namespace(namespace), appLabelSelector) - appProjInformer := newInformer(newAppProjClient(client, namespace), "") + appInformer := newInformer(appClient, namespace, applicationNamespaces, appLabelSelector) + appProjInformer := newInformer(newAppProjClient(client), namespace, applicationNamespaces, "") secretInformer := k8s.NewSecretInformer(k8sClient, namespace, secretName) configMapInformer := k8s.NewConfigMapInformer(k8sClient, namespace, configMapName) apiFactory := api.NewFactory(settings.GetFactorySettings(argocdService, secretName, configMapName), namespace, secretInformer, configMapInformer) @@ -97,32 +99,51 @@ func (c *notificationController) alterDestinations(obj v1.Object, destinations s return destinations } -func newInformer(resClient dynamic.ResourceInterface, selector string) cache.SharedIndexInformer { +func newInformer(resClient dynamic.ResourceInterface, controllerNamespace string, applicationNamespaces []string, selector string) cache.SharedIndexInformer { informer := cache.NewSharedIndexInformer( &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (object runtime.Object, err error) { + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + // We are only interested in apps that exist in namespaces the + // user wants to be enabled. options.LabelSelector = selector - return resClient.List(context.Background(), options) + appList, err := resClient.List(context.TODO(), options) + if err != nil { + return nil, err + } + newItems := []unstructured.Unstructured{} + for _, res := range appList.Items { + if controllerNamespace == res.GetNamespace() || glob.MatchStringInList(applicationNamespaces, res.GetNamespace(), false) { + newItems = append(newItems, res) + } + } + appList.Items = newItems + return appList, nil }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { options.LabelSelector = selector - return resClient.Watch(context.Background(), options) + return resClient.Watch(context.TODO(), options) }, }, &unstructured.Unstructured{}, resyncPeriod, - cache.Indexers{}, + cache.Indexers{ + cache.NamespaceIndex: func(obj interface{}) ([]string, error) { + return cache.MetaNamespaceIndexFunc(obj) + }, + }, ) return informer } type notificationController struct { - apiFactory api.Factory - ctrl controller.NotificationController - appInformer cache.SharedIndexInformer - appProjInformer cache.SharedIndexInformer - secretInformer cache.SharedIndexInformer - configMapInformer cache.SharedIndexInformer + namespace string + applicationNamespaces []string + apiFactory api.Factory + ctrl controller.NotificationController + appInformer cache.SharedIndexInformer + appProjInformer cache.SharedIndexInformer + secretInformer cache.SharedIndexInformer + configMapInformer cache.SharedIndexInformer } func (c *notificationController) Init(ctx context.Context) error { From 0398dfc94a94a2f16f42399c4a7320b1a490b1a3 Mon Sep 17 00:00:00 2001 From: Nikolas Skoufis Date: Wed, 26 Apr 2023 09:25:50 +1000 Subject: [PATCH 02/13] Add SEEK to users.md Signed-off-by: Nikolas Skoufis --- USERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/USERS.md b/USERS.md index de1d62c741695..098dff6268c7b 100644 --- a/USERS.md +++ b/USERS.md @@ -218,6 +218,7 @@ Currently, the following organizations are **officially** using Argo CD: 1. [Sap Labs](http://sap.com) 1. [Sauce Labs](https://saucelabs.com/) 1. [Schwarz IT](https://jobs.schwarz/it-mission) +1. [SEEK](https://seek.com.au) 1. [SI Analytics](https://si-analytics.ai) 1. [Skit](https://skit.ai/) 1. [Skyscanner](https://www.skyscanner.net/) From 6f5979e1015f636cf072f0113e320f1609f3d09c Mon Sep 17 00:00:00 2001 From: Nikolas Skoufis Date: Wed, 26 Apr 2023 11:02:03 +1000 Subject: [PATCH 03/13] Remove unused fields Signed-off-by: Nikolas Skoufis --- notification_controller/controller/controller.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/notification_controller/controller/controller.go b/notification_controller/controller/controller.go index 88a4028566d7a..4356a8394b54b 100644 --- a/notification_controller/controller/controller.go +++ b/notification_controller/controller/controller.go @@ -136,14 +136,12 @@ func newInformer(resClient dynamic.ResourceInterface, controllerNamespace string } type notificationController struct { - namespace string - applicationNamespaces []string - apiFactory api.Factory - ctrl controller.NotificationController - appInformer cache.SharedIndexInformer - appProjInformer cache.SharedIndexInformer - secretInformer cache.SharedIndexInformer - configMapInformer cache.SharedIndexInformer + apiFactory api.Factory + ctrl controller.NotificationController + appInformer cache.SharedIndexInformer + appProjInformer cache.SharedIndexInformer + secretInformer cache.SharedIndexInformer + configMapInformer cache.SharedIndexInformer } func (c *notificationController) Init(ctx context.Context) error { From c3c16039f8eddc34223de0e0feedbf16e3115e42 Mon Sep 17 00:00:00 2001 From: Nik Skoufis Date: Fri, 28 Apr 2023 10:04:27 +1000 Subject: [PATCH 04/13] Revert changes to Procfile Signed-off-by: Nik Skoufis --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index fc73798547083..d8557c81ea19a 100644 --- a/Procfile +++ b/Procfile @@ -9,4 +9,4 @@ git-server: test/fixture/testrepos/start-git.sh helm-registry: test/fixture/testrepos/start-helm-registry.sh dev-mounter: [[ "$ARGOCD_E2E_TEST" != "true" ]] && go run hack/dev-mounter/main.go --configmap argocd-ssh-known-hosts-cm=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} --configmap argocd-tls-certs-cm=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} --configmap argocd-gpg-keys-cm=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} applicationset-controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_ASK_PASS_SOCK=/tmp/applicationset-ask-pass.sock ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-applicationset-controller $COMMAND --loglevel debug --metrics-addr localhost:12345 --probe-addr localhost:12346 --argocd-repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}" -notification: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_BINARY_NAME=argocd-notifications $COMMAND --loglevel debug --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}" +notification: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_BINARY_NAME=argocd-notifications $COMMAND --loglevel debug" From ee4ab23965576442016bcc60bdbefbefde708fb6 Mon Sep 17 00:00:00 2001 From: Nikolas Skoufis Date: Fri, 28 Apr 2023 10:18:09 +1000 Subject: [PATCH 05/13] Fix unit tests Signed-off-by: Nikolas Skoufis --- notification_controller/controller/controller_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notification_controller/controller/controller_test.go b/notification_controller/controller/controller_test.go index fdbd683722279..86681acc5554a 100644 --- a/notification_controller/controller/controller_test.go +++ b/notification_controller/controller/controller_test.go @@ -115,6 +115,7 @@ func TestInit(t *testing.T) { dynamicClient, nil, "default", + []string{}, appLabelSelector, nil, "my-secret", @@ -146,6 +147,7 @@ func TestInitTimeout(t *testing.T) { dynamicClient, nil, "default", + []string{}, appLabelSelector, nil, "my-secret", From 863d6d4a2641004d4a132978e4d59e4675b3e627 Mon Sep 17 00:00:00 2001 From: Stewart Thomson Date: Fri, 25 Aug 2023 11:54:58 -0400 Subject: [PATCH 06/13] - add argocd namespaces environment variable to notifications controller Signed-off-by: Stewart Thomson --- manifests/install.yaml | 7 +++++++ manifests/namespace-install.yaml | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/manifests/install.yaml b/manifests/install.yaml index 00bea1cae1917..6e481bbf5bd46 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -17242,6 +17242,13 @@ spec: containers: - args: - /usr/local/bin/argocd-notifications + env: + - name: ARGOCD_APPLICATION_NAMESPACES + valueFrom: + configMapKeyRef: + key: application.namespaces + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always livenessProbe: diff --git a/manifests/namespace-install.yaml b/manifests/namespace-install.yaml index 9b0d1a70169e7..cb4e519daa0c3 100644 --- a/manifests/namespace-install.yaml +++ b/manifests/namespace-install.yaml @@ -902,6 +902,13 @@ spec: containers: - args: - /usr/local/bin/argocd-notifications + env: + - name: ARGOCD_APPLICATION_NAMESPACES + valueFrom: + configMapKeyRef: + key: application.namespaces + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always livenessProbe: From b36ed87325d4b9bff0fba9fe8781326d1f168f32 Mon Sep 17 00:00:00 2001 From: Stewart Thomson Date: Fri, 25 Aug 2023 13:20:24 -0400 Subject: [PATCH 07/13] - add example cluster role rbac Signed-off-by: Stewart Thomson --- ...fications-controller-rbac-clusterrole.yaml | 20 +++++++++++++++++++ ...ns-controller-rbac-clusterrolebinding.yaml | 16 +++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml create mode 100644 examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrolebinding.yaml diff --git a/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml b/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml new file mode 100644 index 0000000000000..3fdc89eb45afd --- /dev/null +++ b/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml @@ -0,0 +1,20 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: argocd-notifications-controller-cluster-apps + app.kubernetes.io/part-of: argocd + app.kubernetes.io/component: notifications-controller + name: argocd-notifications-controller-cluster-apps +rules: +- apiGroups: + - "argoproj.io" + resources: + - "applications" + - "appprojects" + verbs: + - get + - list + - watch + - update + - patch \ No newline at end of file diff --git a/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrolebinding.yaml b/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrolebinding.yaml new file mode 100644 index 0000000000000..c28ab688c0716 --- /dev/null +++ b/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrolebinding.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: argocd-notifications-controller-cluster-apps + app.kubernetes.io/part-of: argocd + app.kubernetes.io/component: notifications-controller + name: argocd-notifications-controller-cluster-apps +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: argocd-notifications-controller-cluster-apps +subjects: +- kind: ServiceAccount + name: argocd-notifications-controller + namespace: argocd From e4d963e545d80ad0ccf6fab24cf96feba77e18e7 Mon Sep 17 00:00:00 2001 From: Stewart Thomson Date: Fri, 25 Aug 2023 13:26:22 -0400 Subject: [PATCH 08/13] - only look for projects in the controller's namespace (argocd by default) Signed-off-by: Stewart Thomson --- notification_controller/controller/controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notification_controller/controller/controller.go b/notification_controller/controller/controller.go index 4356a8394b54b..6e7880c59090a 100644 --- a/notification_controller/controller/controller.go +++ b/notification_controller/controller/controller.go @@ -62,7 +62,7 @@ func NewController( ) *notificationController { appClient := client.Resource(applications) appInformer := newInformer(appClient, namespace, applicationNamespaces, appLabelSelector) - appProjInformer := newInformer(newAppProjClient(client), namespace, applicationNamespaces, "") + appProjInformer := newInformer(newAppProjClient(client), namespace, []string{namespace}, "") secretInformer := k8s.NewSecretInformer(k8sClient, namespace, secretName) configMapInformer := k8s.NewConfigMapInformer(k8sClient, namespace, configMapName) apiFactory := api.NewFactory(settings.GetFactorySettings(argocdService, secretName, configMapName), namespace, secretInformer, configMapInformer) From 4996eeab2bd841c14bd565de97c84009c2b7e6b0 Mon Sep 17 00:00:00 2001 From: Stewart Thomson Date: Fri, 25 Aug 2023 14:09:45 -0400 Subject: [PATCH 09/13] - update base manifest Signed-off-by: Stewart Thomson --- .../argocd-notifications-controller-deployment.yaml | 6 ++++++ manifests/ha/install.yaml | 6 ++++++ manifests/ha/namespace-install.yaml | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/manifests/base/notification/argocd-notifications-controller-deployment.yaml b/manifests/base/notification/argocd-notifications-controller-deployment.yaml index 8eab1f95570c5..9cd1a068808b1 100644 --- a/manifests/base/notification/argocd-notifications-controller-deployment.yaml +++ b/manifests/base/notification/argocd-notifications-controller-deployment.yaml @@ -48,6 +48,12 @@ spec: key: notificationscontroller.log.level name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATION_NAMESPACES + valueFrom: + configMapKeyRef: + key: application.namespaces + name: argocd-cmd-params-cm + optional: true workingDir: /app livenessProbe: tcpSocket: diff --git a/manifests/ha/install.yaml b/manifests/ha/install.yaml index c5f45e932a4eb..dd4d629c7ded7 100644 --- a/manifests/ha/install.yaml +++ b/manifests/ha/install.yaml @@ -20329,6 +20329,12 @@ spec: key: notificationscontroller.log.level name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATION_NAMESPACES + valueFrom: + configMapKeyRef: + key: application.namespaces + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always livenessProbe: diff --git a/manifests/ha/namespace-install.yaml b/manifests/ha/namespace-install.yaml index 03e2dd32f2395..c9ff8f693e98d 100644 --- a/manifests/ha/namespace-install.yaml +++ b/manifests/ha/namespace-install.yaml @@ -1829,6 +1829,12 @@ spec: key: notificationscontroller.log.level name: argocd-cmd-params-cm optional: true + - name: ARGOCD_APPLICATION_NAMESPACES + valueFrom: + configMapKeyRef: + key: application.namespaces + name: argocd-cmd-params-cm + optional: true image: quay.io/argoproj/argocd:latest imagePullPolicy: Always livenessProbe: From baa28c84e3adc2efe4d035ae0f6278663f3a0ab2 Mon Sep 17 00:00:00 2001 From: Stewart Thomson Date: Mon, 11 Sep 2023 14:37:21 +0200 Subject: [PATCH 10/13] - skip app processing in notification controller Signed-off-by: Stewart Thomson --- notification_controller/controller/controller.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/notification_controller/controller/controller.go b/notification_controller/controller/controller.go index 6e7880c59090a..5e524aa52df5a 100644 --- a/notification_controller/controller/controller.go +++ b/notification_controller/controller/controller.go @@ -79,6 +79,9 @@ func NewController( if !ok { return false, "" } + if namespace != app.GetNamespace() && !glob.MatchStringInList(applicationNamespaces, app.GetNamespace(), false) { + return true, "app is not in one of the application-namespaces, nor the notification controller namespace" + } return !isAppSyncStatusRefreshed(app, log.WithField("app", obj.GetName())), "sync status out of date" }), controller.WithMetricsRegistry(registry), From 6ede79bfdcae2fe72277050080c37fe991baea59 Mon Sep 17 00:00:00 2001 From: May Zhang Date: Wed, 27 Sep 2023 13:20:55 -0700 Subject: [PATCH 11/13] added unit test and updated doc Signed-off-by: May Zhang --- docs/operator-manual/app-any-namespace.md | 1 + ...fications-controller-rbac-clusterrole.yaml | 1 - .../controller/controller.go | 18 +++++++++----- .../controller/controller_test.go | 24 +++++++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/docs/operator-manual/app-any-namespace.md b/docs/operator-manual/app-any-namespace.md index b59b046d3746b..f202ecc107494 100644 --- a/docs/operator-manual/app-any-namespace.md +++ b/docs/operator-manual/app-any-namespace.md @@ -71,6 +71,7 @@ We supply a `ClusterRole` and `ClusterRoleBinding` suitable for this purpose in kubectl apply -f examples/k8s-rbac/argocd-server-applications/ ``` +`argocd-notifications-controller-rbac-clusterrole.yaml` and `argocd-notifications-controller-rbac-clusterrolebinding.yaml` are used to support notifications controller to notify apps in all namespaces. !!! note At some later point in time, we may make this cluster role part of the default installation manifests. diff --git a/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml b/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml index 3fdc89eb45afd..05f92abb11717 100644 --- a/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml +++ b/examples/k8s-rbac/argocd-server-applications/argocd-notifications-controller-rbac-clusterrole.yaml @@ -11,7 +11,6 @@ rules: - "argoproj.io" resources: - "applications" - - "appprojects" verbs: - get - list diff --git a/notification_controller/controller/controller.go b/notification_controller/controller/controller.go index 5e524aa52df5a..1ad2ab361ab93 100644 --- a/notification_controller/controller/controller.go +++ b/notification_controller/controller/controller.go @@ -4,9 +4,10 @@ import ( "context" "errors" "fmt" - "github.com/argoproj/argo-cd/v2/util/glob" "time" + "github.com/argoproj/argo-cd/v2/util/glob" + "github.com/argoproj/argo-cd/v2/util/notification/k8s" service "github.com/argoproj/argo-cd/v2/util/notification/argocd" @@ -39,8 +40,8 @@ var ( appProjects = schema.GroupVersionResource{Group: application.Group, Version: "v1alpha1", Resource: application.AppProjectPlural} ) -func newAppProjClient(client dynamic.Interface) dynamic.ResourceInterface { - resClient := client.Resource(appProjects) +func newAppProjClient(client dynamic.Interface, namespace string) dynamic.ResourceInterface { + resClient := client.Resource(appProjects).Namespace(namespace) return resClient } @@ -62,7 +63,7 @@ func NewController( ) *notificationController { appClient := client.Resource(applications) appInformer := newInformer(appClient, namespace, applicationNamespaces, appLabelSelector) - appProjInformer := newInformer(newAppProjClient(client), namespace, []string{namespace}, "") + appProjInformer := newInformer(newAppProjClient(client, namespace), namespace, []string{namespace}, "") secretInformer := k8s.NewSecretInformer(k8sClient, namespace, secretName) configMapInformer := k8s.NewConfigMapInformer(k8sClient, namespace, configMapName) apiFactory := api.NewFactory(settings.GetFactorySettings(argocdService, secretName, configMapName), namespace, secretInformer, configMapInformer) @@ -79,7 +80,7 @@ func NewController( if !ok { return false, "" } - if namespace != app.GetNamespace() && !glob.MatchStringInList(applicationNamespaces, app.GetNamespace(), false) { + if checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces) { return true, "app is not in one of the application-namespaces, nor the notification controller namespace" } return !isAppSyncStatusRefreshed(app, log.WithField("app", obj.GetName())), "sync status out of date" @@ -89,6 +90,11 @@ func NewController( return res } +// Check if app is not in the namespace where the controller is in, and also app is not in one of the applicationNamespaces +func checkAppNotInAdditionalNamespaces(app *unstructured.Unstructured, namespace string, applicationNamespaces []string) bool { + return namespace != app.GetNamespace() && !glob.MatchStringInList(applicationNamespaces, app.GetNamespace(), false) +} + func (c *notificationController) alterDestinations(obj v1.Object, destinations services.Destinations, cfg api.Config) services.Destinations { app, ok := (obj).(*unstructured.Unstructured) if !ok { @@ -111,7 +117,7 @@ func newInformer(resClient dynamic.ResourceInterface, controllerNamespace string options.LabelSelector = selector appList, err := resClient.List(context.TODO(), options) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to list applications: %w", err) } newItems := []unstructured.Unstructured{} for _, res := range appList.Items { diff --git a/notification_controller/controller/controller_test.go b/notification_controller/controller/controller_test.go index 86681acc5554a..5ad1e520502a3 100644 --- a/notification_controller/controller/controller_test.go +++ b/notification_controller/controller/controller_test.go @@ -166,3 +166,27 @@ func TestInitTimeout(t *testing.T) { assert.Error(t, err) assert.Equal(t, "Timed out waiting for caches to sync", err.Error()) } + +func TestCheckAppNotInAdditionalNamespaces(t *testing.T) { + app := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "spec": map[string]interface{}{}, + }, + } + namespace := "argocd" + var applicationNamespaces []string + applicationNamespaces = append(applicationNamespaces, "namespace1") + applicationNamespaces = append(applicationNamespaces, "namespace2") + + // app is in same namespace as controller's namespace + app.SetNamespace(namespace) + assert.False(t, checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces)) + + // app is not in the namespace as controller's namespace, but it is in one of the applicationNamespaces + app.SetNamespace("namespace2") + assert.False(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces)) + + // app is not in the namespace as controller's namespace, and it is not in any of the applicationNamespaces + app.SetNamespace("namespace3") + assert.True(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces)) +} From de662b3f9b0eac65f263ddf974b87ea46e9eb395 Mon Sep 17 00:00:00 2001 From: May Zhang Date: Wed, 27 Sep 2023 13:38:39 -0700 Subject: [PATCH 12/13] added unit test and updated doc Signed-off-by: May Zhang --- docs/operator-manual/app-any-namespace.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/operator-manual/app-any-namespace.md b/docs/operator-manual/app-any-namespace.md index f202ecc107494..00881aaa7c9dc 100644 --- a/docs/operator-manual/app-any-namespace.md +++ b/docs/operator-manual/app-any-namespace.md @@ -72,6 +72,7 @@ kubectl apply -f examples/k8s-rbac/argocd-server-applications/ ``` `argocd-notifications-controller-rbac-clusterrole.yaml` and `argocd-notifications-controller-rbac-clusterrolebinding.yaml` are used to support notifications controller to notify apps in all namespaces. + !!! note At some later point in time, we may make this cluster role part of the default installation manifests. From 4de11d5df50d68a94e47d5322dc55acfb5c481bc Mon Sep 17 00:00:00 2001 From: May Zhang Date: Wed, 4 Oct 2023 14:33:44 -0700 Subject: [PATCH 13/13] updated examples/k8s-rbac/argocd-server-applications/kustomization.yaml's resources Signed-off-by: May Zhang --- examples/k8s-rbac/argocd-server-applications/kustomization.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/k8s-rbac/argocd-server-applications/kustomization.yaml b/examples/k8s-rbac/argocd-server-applications/kustomization.yaml index 67d8d57d3f72f..330dde4a914d2 100644 --- a/examples/k8s-rbac/argocd-server-applications/kustomization.yaml +++ b/examples/k8s-rbac/argocd-server-applications/kustomization.yaml @@ -3,3 +3,5 @@ kind: Kustomization resources: - argocd-server-rbac-clusterrole.yaml - argocd-server-rbac-clusterrolebinding.yaml +- argocd-notifications-controller-rbac-clusterrole.yaml +- argocd-notifications-controller-rbac-clusterrolebinding.yaml