Repository: argoproj-labs/argocd-operator
Pull request #794 (2022-10-12 17:38:05)

changes to support the feature apps in any namespaces
**What type of PR is this?**
/kind enhancement

**What does this PR do / why we need it**:
The PR adds support for the feature apps in any namespace added upstream. To do so, the PR adds new command args `--additional-namespace` to ArgoCD ApplicationController and ArgoCD Server components. Also, the PR adds new roles in the respective namespaces for ArgoCD Server to perform actions in the namespace.

**Have you updated the necessary documentation?**

* [x] Documentation update is required by this PR.
* [x] Documentation has been updated.

**Which issue(s) this PR fixes**:
https://issues.redhat.com/browse/GITOPS-2341

**How to test changes / Special notes to the reviewer**:
* Run `make install run`
* Create namespaces `argocd-test` and `argocd-1`
* Deploy an ArgoCD instance using below yaml file
```
apiVersion: argoproj.io/v1alpha1
kind: ArgoCD
metadata:
  name: example-argocd
spec:
  controller:
    sourceNamespaces:
    - argocd
    - argocd-1
  notifications:
    enabled: True
    env:
      - name: foo
        value: bar
  server:
    ingress:
      enabled: true
    sourceNamespaces:
    - argocd-test
    - argocd-1
```
* Check if the ArgoCD pods came up successfully using command `kubectl get pods | grep example-argocd`
* Check whether the new roles were created in namespaces `argocd-test` and `argocd-1`
* Check if the namespaces `argocd-test` and `argocd-1` have a new label `argocd.argoproj.io/managed-by-cluster-argocd`

* e2e test for the PR.
`kubectl kuttl test ./tests/k8s --config ./tests/kuttl-tests.yaml --test 1-024_validate_apps_in_any_namespace`

jaideepr97: @ishitasequeira 

what happens if the same namespace features in the "sourceNamespaces" list of 2 different argo-cd instances?
would both instances try to manage the same application?

I think it would also be good to have some e2e tests written out that can cover scenarios like this 
ishitasequeira: > @ishitasequeira
> 
> what happens if the same namespace features in the "sourceNamespaces" list of 2 different argo-cd instances? would both instances try to manage the same application?
> 

Yes, we would reconcile the roles for both the argo-cd instances.

jaideepr97: @ishitasequeira that might be a problem, no?
having multiple argo-cd instances managing the same application doesn't sound like a good idea to me
ishitasequeira: > @ishitasequeira that might be a problem, no? having multiple argo-cd instances managing the same application doesn't sound like a good idea to me
> 
> should we maybe consider some kind of mechanism to check if an app is already being managed by some other instance?

As mentioned in @jannfis's upstream [PR](https://github.com/argoproj/argo-cd/pull/9755) description,

```
If there are multiple instances of Argo CD installed to the same cluster, the behavior when more than one instance specifies same allowed namespace patterns (and have access to those namespaces) is undefined. This scenario should be avoided (needs to be documented).
```

I will update our documentation with this comment. 

jaideepr97: @ishitasequeira 
I see
I suppose we could leave it to the users to be careful...however, I think since we are an operator (as opposed to upstream) maybe there is some level of expectation that we would go further to make the users' experience more convenient? 
I'm fine with leaving it up to the user, but I think it might be worth discussing if we should try and put some guardrails in place all the same 
sbose78: @jaideepr97 Agreed. A little over-engineered solution could be having an admission webhook disallow specification of a namespace in `sourceNamespaces` if it was already specified for a different ArgoCD instance.
jaideepr97: @sbose78 that could work 
maybe a slightly more straightforward way could be to just maintain a map to track which namespaces are watched by which instances, and not create roles when we encounter a namespace that's already being watched by a different instance 
(Also log it the operator and emit a warning event if necessary mentioning that xyz namespace is already being watched?)
ishitasequeira: > @sbose78 that could work maybe a slightly more straightforward way could be to just maintain a map to track which namespaces are watched by which instances, and not create roles when we encounter a namespace that's already being watched by a different instance (Also log it the operator and emit a warning event if necessary mentioning that xyz namespace is already being watched?)

I think managing a map might be difficult as we would have to take care of cleaning it up too if the ArgoCD instance is updated later and a namespace is removed from it.. I was wondering if we could use a label like `[argocd.argoproj.io/managed-by](http://argocd.argoproj.io/managed-by)` and we check if the namespace has this label or not.
jaideepr97: > I think managing a map might be difficult as we would have to take care of cleaning it up too if the ArgoCD instance is updated later and a namespace is removed from it.

@ishitasequeira FWIW I don't think cleanup would be too bad, we would just need to watch for changes in the CR when a namespace is removed from the watch list, and when a namespace is deleted - in both cases we check if that namespace has any roles that need to be cleaned up & then remove that entry from the map

(We already have similar watches in place to react to different events like removal of SSO in CR or deletion of managed namespace)
ishitasequeira: As agreed in the [slack conversation](https://coreos.slack.com/archives/C01RQH8KQ87/p1666799197470809), we are attaching a label `argocd.argoproj.io/managed-by-cluster-argocd` to every namespace added as a `SourceNamespace`.
ishitasequeira: @iam-veeramalla @jopit @jaideepr97 could you review the PR?
jaideepr97: @ishitasequeira should we maybe include the name/namespace of the managing cluster argo-cd in the label? in case we have multiple cluster scoped instances on the same cluster it could get difficult to tell who is managing that namespace (even though there's no risk of multiple instances managing that namespace)
jaideepr97: I have tested this PR locally and it works as expected for the most part 
Couple things I have discussed with @ishitasequeira that we should document :

1. No namespace can be managed by multiple argo-cd instances (cluster scoped or namespace scoped) i.e, only one of either `managed-by` or `managed-by-cluster-argocd` labels can be applied to a given namespace. We will be prioritizing `managed-by` label in case of a conflict as this feature is currently in beta, so the new roles/rolebindings will not be created if namespace is already labelled with `managed-by` label, and they will be deleted if a namespace is first added to the `sourceNamespacs` list and is later also labelled with `managed-by` label 

2. This also means users cannot currently create/manage apps and create app resources in the same non-control plane namespace (as they both require their own labels) out of the box 
as a workaround users will have to create custom roles

@ishitasequeira please update the e2e test to ensure proper cleanup of roles/rolebindings as discussed


jaideepr97: other than that this LGTM, thanks a lot @ishitasequeira !!
jaideepr97: /lgtm
ishitasequeira: @jaideepr97 I have updated the documentation and the e2e test.

@iam-veeramalla @wtam2018 PTAL.
jaideepr97: /lgtm

Patch:
diff --git a/api/v1alpha1/argocd_types.go b/api/v1alpha1/argocd_types.go
index 67ba48e6..c618b5c6 100644
--- a/api/v1alpha1/argocd_types.go
+++ b/api/v1alpha1/argocd_types.go
@@ -708,6 +708,9 @@ type ArgoCDSpec struct {
 	// Server defines the options for the ArgoCD Server component.
 	Server ArgoCDServerSpec `json:"server,omitempty"`
 
+	// SourceNamespaces defines the namespaces application resources are allowed to be created in
+	SourceNamespaces []string `json:"sourceNamespaces,omitempty"`
+
 	// SSO defines the Single Sign-on configuration for Argo CD
 	SSO *ArgoCDSSOSpec `json:"sso,omitempty"`
 
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 95db82bf..79f4b023 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -904,6 +904,11 @@ func (in *ArgoCDSpec) DeepCopyInto(out *ArgoCDSpec) {
 	in.Redis.DeepCopyInto(&out.Redis)
 	in.Repo.DeepCopyInto(&out.Repo)
 	in.Server.DeepCopyInto(&out.Server)
+	if in.SourceNamespaces != nil {
+		in, out := &in.SourceNamespaces, &out.SourceNamespaces
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	if in.SSO != nil {
 		in, out := &in.SSO, &out.SSO
 		*out = new(ArgoCDSSOSpec)
diff --git a/build/util/Dockerfile b/build/util/Dockerfile
index 490a4983..ee614c98 100644
--- a/build/util/Dockerfile
+++ b/build/util/Dockerfile
@@ -1,5 +1,5 @@
-# Argo CD v2.4.7
-FROM quay.io/argoproj/argocd@sha256:f887f854ab22f7f29f915aae2b765f2948d1555d61e9ce3ca9e659f8df22ab2b
+# Argo CD v2.5.2
+FROM quay.io/argoproj/argocd@sha256:9df610ec57cb8ec08001ffaeeedfe1c248e7906707a654801f8d7b4d07905693
 
 USER root
 
diff --git a/bundle/manifests/argoproj.io_applications.yaml b/bundle/manifests/argoproj.io_applications.yaml
index 09f9976b..b4b9bcb8 100644
--- a/bundle/manifests/argoproj.io_applications.yaml
+++ b/bundle/manifests/argoproj.io_applications.yaml
@@ -1806,6 +1806,10 @@ spec:
                   reconciled using the latest git version
                 format: date-time
                 type: string
+              resourceHealthSource:
+                description: 'ResourceHealthSource indicates where the resource health
+                  status is stored: inline if not set or appTree'
+                type: string
               resources:
                 description: Resources is a list of Kubernetes resources managed by
                   this application
diff --git a/bundle/manifests/argoproj.io_applicationsets.yaml b/bundle/manifests/argoproj.io_applicationsets.yaml
index 4203a739..c83c4d00 100644
--- a/bundle/manifests/argoproj.io_applicationsets.yaml
+++ b/bundle/manifests/argoproj.io_applicationsets.yaml
@@ -2372,6 +2372,8 @@ spec:
                                     properties:
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       labels:
                                         items:
                                           type: string
@@ -2394,6 +2396,31 @@ spec:
                                     - owner
                                     - repo
                                     type: object
+                                  gitlab:
+                                    properties:
+                                      api:
+                                        type: string
+                                      labels:
+                                        items:
+                                          type: string
+                                        type: array
+                                      project:
+                                        type: string
+                                      pullRequestState:
+                                        type: string
+                                      tokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                    required:
+                                    - project
+                                    type: object
                                   requeueAfterSeconds:
                                     format: int64
                                     type: integer
@@ -2655,6 +2682,31 @@ spec:
                                 type: object
                               scmProvider:
                                 properties:
+                                  azureDevOps:
+                                    properties:
+                                      accessTokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                      allBranches:
+                                        type: boolean
+                                      api:
+                                        type: string
+                                      organization:
+                                        type: string
+                                      teamProject:
+                                        type: string
+                                    required:
+                                    - accessTokenRef
+                                    - organization
+                                    - teamProject
+                                    type: object
                                   bitbucket:
                                     properties:
                                       allBranches:
@@ -2759,6 +2811,8 @@ spec:
                                         type: boolean
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       organization:
                                         type: string
                                       tokenRef:
@@ -3056,6 +3110,29 @@ spec:
                                     - spec
                                     type: object
                                 type: object
+                              selector:
+                                properties:
+                                  matchExpressions:
+                                    items:
+                                      properties:
+                                        key:
+                                          type: string
+                                        operator:
+                                          type: string
+                                        values:
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    type: object
+                                type: object
                             type: object
                           type: array
                         template:
@@ -4525,6 +4602,8 @@ spec:
                                     properties:
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       labels:
                                         items:
                                           type: string
@@ -4547,6 +4626,31 @@ spec:
                                     - owner
                                     - repo
                                     type: object
+                                  gitlab:
+                                    properties:
+                                      api:
+                                        type: string
+                                      labels:
+                                        items:
+                                          type: string
+                                        type: array
+                                      project:
+                                        type: string
+                                      pullRequestState:
+                                        type: string
+                                      tokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                    required:
+                                    - project
+                                    type: object
                                   requeueAfterSeconds:
                                     format: int64
                                     type: integer
@@ -4808,6 +4912,31 @@ spec:
                                 type: object
                               scmProvider:
                                 properties:
+                                  azureDevOps:
+                                    properties:
+                                      accessTokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                      allBranches:
+                                        type: boolean
+                                      api:
+                                        type: string
+                                      organization:
+                                        type: string
+                                      teamProject:
+                                        type: string
+                                    required:
+                                    - accessTokenRef
+                                    - organization
+                                    - teamProject
+                                    type: object
                                   bitbucket:
                                     properties:
                                       allBranches:
@@ -4912,6 +5041,8 @@ spec:
                                         type: boolean
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       organization:
                                         type: string
                                       tokenRef:
@@ -5209,6 +5340,29 @@ spec:
                                     - spec
                                     type: object
                                 type: object
+                              selector:
+                                properties:
+                                  matchExpressions:
+                                    items:
+                                      properties:
+                                        key:
+                                          type: string
+                                        operator:
+                                          type: string
+                                        values:
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    type: object
+                                type: object
                             type: object
                           type: array
                         mergeKeys:
@@ -5543,6 +5697,8 @@ spec:
                           properties:
                             api:
                               type: string
+                            appSecretName:
+                              type: string
                             labels:
                               items:
                                 type: string
@@ -5565,6 +5721,31 @@ spec:
                           - owner
                           - repo
                           type: object
+                        gitlab:
+                          properties:
+                            api:
+                              type: string
+                            labels:
+                              items:
+                                type: string
+                              type: array
+                            project:
+                              type: string
+                            pullRequestState:
+                              type: string
+                            tokenRef:
+                              properties:
+                                key:
+                                  type: string
+                                secretName:
+                                  type: string
+                              required:
+                              - key
+                              - secretName
+                              type: object
+                          required:
+                          - project
+                          type: object
                         requeueAfterSeconds:
                           format: int64
                           type: integer
@@ -5826,6 +6007,31 @@ spec:
                       type: object
                     scmProvider:
                       properties:
+                        azureDevOps:
+                          properties:
+                            accessTokenRef:
+                              properties:
+                                key:
+                                  type: string
+                                secretName:
+                                  type: string
+                              required:
+                              - key
+                              - secretName
+                              type: object
+                            allBranches:
+                              type: boolean
+                            api:
+                              type: string
+                            organization:
+                              type: string
+                            teamProject:
+                              type: string
+                          required:
+                          - accessTokenRef
+                          - organization
+                          - teamProject
+                          type: object
                         bitbucket:
                           properties:
                             allBranches:
@@ -5930,6 +6136,8 @@ spec:
                               type: boolean
                             api:
                               type: string
+                            appSecretName:
+                              type: string
                             organization:
                               type: string
                             tokenRef:
@@ -6227,8 +6435,33 @@ spec:
                           - spec
                           type: object
                       type: object
+                    selector:
+                      properties:
+                        matchExpressions:
+                          items:
+                            properties:
+                              key:
+                                type: string
+                              operator:
+                                type: string
+                              values:
+                                items:
+                                  type: string
+                                type: array
+                            required:
+                            - key
+                            - operator
+                            type: object
+                          type: array
+                        matchLabels:
+                          additionalProperties:
+                            type: string
+                          type: object
+                      type: object
                   type: object
                 type: array
+              goTemplate:
+                type: boolean
               syncPolicy:
                 properties:
                   preserveResourcesOnDeletion:
diff --git a/bundle/manifests/argoproj.io_appprojects.yaml b/bundle/manifests/argoproj.io_appprojects.yaml
index 1b6aed00..8504d6ff 100644
--- a/bundle/manifests/argoproj.io_appprojects.yaml
+++ b/bundle/manifests/argoproj.io_appprojects.yaml
@@ -160,6 +160,10 @@ spec:
                       for apps which have orphaned resources
                     type: boolean
                 type: object
+              permitOnlyProjectScopedClusters:
+                description: PermitOnlyProjectScopedClusters determines whether destinations
+                  can only reference clusters which are project-scoped
+                type: boolean
               roles:
                 description: Roles are user defined RBAC roles associated with this
                   project
@@ -222,6 +226,12 @@ spec:
                   - keyID
                   type: object
                 type: array
+              sourceNamespaces:
+                description: SourceNamespaces defines the namespaces application resources
+                  are allowed to be created in
+                items:
+                  type: string
+                type: array
               sourceRepos:
                 description: SourceRepos contains list of repository URLs which can
                   be used for deployment
diff --git a/bundle/manifests/argoproj.io_argocds.yaml b/bundle/manifests/argoproj.io_argocds.yaml
index 7f22c8c7..d0aab458 100644
--- a/bundle/manifests/argoproj.io_argocds.yaml
+++ b/bundle/manifests/argoproj.io_argocds.yaml
@@ -5926,6 +5926,12 @@ spec:
                     - type
                     type: object
                 type: object
+              sourceNamespaces:
+                description: SourceNamespaces defines the namespaces application resources
+                  are allowed to be created in
+                items:
+                  type: string
+                type: array
               sso:
                 description: SSO defines the Single Sign-on configuration for Argo
                   CD
diff --git a/common/defaults.go b/common/defaults.go
index 0f5e6755..a1660386 100644
--- a/common/defaults.go
+++ b/common/defaults.go
@@ -61,7 +61,7 @@ const (
 	ArgoCDDefaultArgoImage = "quay.io/argoproj/argocd"
 
 	// ArgoCDDefaultArgoVersion is the Argo CD container image digest to use when version not specified.
-	ArgoCDDefaultArgoVersion = "sha256:f887f854ab22f7f29f915aae2b765f2948d1555d61e9ce3ca9e659f8df22ab2b" // v2.4.7
+	ArgoCDDefaultArgoVersion = "sha256:9df610ec57cb8ec08001ffaeeedfe1c248e7906707a654801f8d7b4d07905693" // v2.5.2
 
 	// ArgoCDDefaultBackupKeyLength is the length of the generated default backup key.
 	ArgoCDDefaultBackupKeyLength = 32
diff --git a/common/keys.go b/common/keys.go
index 6b12a32d..04aa48a6 100644
--- a/common/keys.go
+++ b/common/keys.go
@@ -220,6 +220,9 @@ const (
 	// ArgoCDManagedByLabel is needed to identify namespace managed by an instance on ArgoCD
 	ArgoCDManagedByLabel = "argocd.argoproj.io/managed-by"
 
+	// ArgoCDManagedByClusterArgoCDLabel is needed to identify namespace mentioned as sourceNamespace on ArgoCD
+	ArgoCDManagedByClusterArgoCDLabel = "argocd.argoproj.io/managed-by-cluster-argocd"
+
 	// ArgoCDControllerClusterRoleEnvName is an environment variable to specify a custom cluster role for Argo CD application controller
 	ArgoCDControllerClusterRoleEnvName = "CONTROLLER_CLUSTER_ROLE"
 
diff --git a/config/crd/bases/argoproj.io_applications.yaml b/config/crd/bases/argoproj.io_applications.yaml
index 7e6828e2..60c05f0d 100644
--- a/config/crd/bases/argoproj.io_applications.yaml
+++ b/config/crd/bases/argoproj.io_applications.yaml
@@ -1805,6 +1805,10 @@ spec:
                   reconciled using the latest git version
                 format: date-time
                 type: string
+              resourceHealthSource:
+                description: 'ResourceHealthSource indicates where the resource health
+                  status is stored: inline if not set or appTree'
+                type: string
               resources:
                 description: Resources is a list of Kubernetes resources managed by
                   this application
diff --git a/config/crd/bases/argoproj.io_applicationsets.yaml b/config/crd/bases/argoproj.io_applicationsets.yaml
index 0c0c98a4..4ff92c56 100644
--- a/config/crd/bases/argoproj.io_applicationsets.yaml
+++ b/config/crd/bases/argoproj.io_applicationsets.yaml
@@ -1,5 +1,3 @@
-
----
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
@@ -2373,6 +2371,8 @@ spec:
                                     properties:
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       labels:
                                         items:
                                           type: string
@@ -2395,6 +2395,31 @@ spec:
                                     - owner
                                     - repo
                                     type: object
+                                  gitlab:
+                                    properties:
+                                      api:
+                                        type: string
+                                      labels:
+                                        items:
+                                          type: string
+                                        type: array
+                                      project:
+                                        type: string
+                                      pullRequestState:
+                                        type: string
+                                      tokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                    required:
+                                    - project
+                                    type: object
                                   requeueAfterSeconds:
                                     format: int64
                                     type: integer
@@ -2656,6 +2681,31 @@ spec:
                                 type: object
                               scmProvider:
                                 properties:
+                                  azureDevOps:
+                                    properties:
+                                      accessTokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                      allBranches:
+                                        type: boolean
+                                      api:
+                                        type: string
+                                      organization:
+                                        type: string
+                                      teamProject:
+                                        type: string
+                                    required:
+                                    - accessTokenRef
+                                    - organization
+                                    - teamProject
+                                    type: object
                                   bitbucket:
                                     properties:
                                       allBranches:
@@ -2760,6 +2810,8 @@ spec:
                                         type: boolean
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       organization:
                                         type: string
                                       tokenRef:
@@ -3057,6 +3109,29 @@ spec:
                                     - spec
                                     type: object
                                 type: object
+                              selector:
+                                properties:
+                                  matchExpressions:
+                                    items:
+                                      properties:
+                                        key:
+                                          type: string
+                                        operator:
+                                          type: string
+                                        values:
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    type: object
+                                type: object
                             type: object
                           type: array
                         template:
@@ -4526,6 +4601,8 @@ spec:
                                     properties:
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       labels:
                                         items:
                                           type: string
@@ -4548,6 +4625,31 @@ spec:
                                     - owner
                                     - repo
                                     type: object
+                                  gitlab:
+                                    properties:
+                                      api:
+                                        type: string
+                                      labels:
+                                        items:
+                                          type: string
+                                        type: array
+                                      project:
+                                        type: string
+                                      pullRequestState:
+                                        type: string
+                                      tokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                    required:
+                                    - project
+                                    type: object
                                   requeueAfterSeconds:
                                     format: int64
                                     type: integer
@@ -4809,6 +4911,31 @@ spec:
                                 type: object
                               scmProvider:
                                 properties:
+                                  azureDevOps:
+                                    properties:
+                                      accessTokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                      allBranches:
+                                        type: boolean
+                                      api:
+                                        type: string
+                                      organization:
+                                        type: string
+                                      teamProject:
+                                        type: string
+                                    required:
+                                    - accessTokenRef
+                                    - organization
+                                    - teamProject
+                                    type: object
                                   bitbucket:
                                     properties:
                                       allBranches:
@@ -4913,6 +5040,8 @@ spec:
                                         type: boolean
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       organization:
                                         type: string
                                       tokenRef:
@@ -5210,6 +5339,29 @@ spec:
                                     - spec
                                     type: object
                                 type: object
+                              selector:
+                                properties:
+                                  matchExpressions:
+                                    items:
+                                      properties:
+                                        key:
+                                          type: string
+                                        operator:
+                                          type: string
+                                        values:
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    type: object
+                                type: object
                             type: object
                           type: array
                         mergeKeys:
@@ -5544,6 +5696,8 @@ spec:
                           properties:
                             api:
                               type: string
+                            appSecretName:
+                              type: string
                             labels:
                               items:
                                 type: string
@@ -5566,6 +5720,31 @@ spec:
                           - owner
                           - repo
                           type: object
+                        gitlab:
+                          properties:
+                            api:
+                              type: string
+                            labels:
+                              items:
+                                type: string
+                              type: array
+                            project:
+                              type: string
+                            pullRequestState:
+                              type: string
+                            tokenRef:
+                              properties:
+                                key:
+                                  type: string
+                                secretName:
+                                  type: string
+                              required:
+                              - key
+                              - secretName
+                              type: object
+                          required:
+                          - project
+                          type: object
                         requeueAfterSeconds:
                           format: int64
                           type: integer
@@ -5827,6 +6006,31 @@ spec:
                       type: object
                     scmProvider:
                       properties:
+                        azureDevOps:
+                          properties:
+                            accessTokenRef:
+                              properties:
+                                key:
+                                  type: string
+                                secretName:
+                                  type: string
+                              required:
+                              - key
+                              - secretName
+                              type: object
+                            allBranches:
+                              type: boolean
+                            api:
+                              type: string
+                            organization:
+                              type: string
+                            teamProject:
+                              type: string
+                          required:
+                          - accessTokenRef
+                          - organization
+                          - teamProject
+                          type: object
                         bitbucket:
                           properties:
                             allBranches:
@@ -5931,6 +6135,8 @@ spec:
                               type: boolean
                             api:
                               type: string
+                            appSecretName:
+                              type: string
                             organization:
                               type: string
                             tokenRef:
@@ -6228,8 +6434,33 @@ spec:
                           - spec
                           type: object
                       type: object
+                    selector:
+                      properties:
+                        matchExpressions:
+                          items:
+                            properties:
+                              key:
+                                type: string
+                              operator:
+                                type: string
+                              values:
+                                items:
+                                  type: string
+                                type: array
+                            required:
+                            - key
+                            - operator
+                            type: object
+                          type: array
+                        matchLabels:
+                          additionalProperties:
+                            type: string
+                          type: object
+                      type: object
                   type: object
                 type: array
+              goTemplate:
+                type: boolean
               syncPolicy:
                 properties:
                   preserveResourcesOnDeletion:
diff --git a/config/crd/bases/argoproj.io_appprojects.yaml b/config/crd/bases/argoproj.io_appprojects.yaml
index f8762fce..9fdc4e31 100644
--- a/config/crd/bases/argoproj.io_appprojects.yaml
+++ b/config/crd/bases/argoproj.io_appprojects.yaml
@@ -159,6 +159,10 @@ spec:
                       for apps which have orphaned resources
                     type: boolean
                 type: object
+              permitOnlyProjectScopedClusters:
+                description: PermitOnlyProjectScopedClusters determines whether destinations
+                  can only reference clusters which are project-scoped
+                type: boolean
               roles:
                 description: Roles are user defined RBAC roles associated with this
                   project
@@ -221,6 +225,12 @@ spec:
                   - keyID
                   type: object
                 type: array
+              sourceNamespaces:
+                description: SourceNamespaces defines the namespaces application resources
+                  are allowed to be created in
+                items:
+                  type: string
+                type: array
               sourceRepos:
                 description: SourceRepos contains list of repository URLs which can
                   be used for deployment
diff --git a/config/crd/bases/argoproj.io_argocds.yaml b/config/crd/bases/argoproj.io_argocds.yaml
index e56ef2a9..7fbf7dd5 100644
--- a/config/crd/bases/argoproj.io_argocds.yaml
+++ b/config/crd/bases/argoproj.io_argocds.yaml
@@ -5928,6 +5928,12 @@ spec:
                     - type
                     type: object
                 type: object
+              sourceNamespaces:
+                description: SourceNamespaces defines the namespaces application resources
+                  are allowed to be created in
+                items:
+                  type: string
+                type: array
               sso:
                 description: SSO defines the Single Sign-on configuration for Argo
                   CD
diff --git a/controllers/argocd/argocd_controller.go b/controllers/argocd/argocd_controller.go
index ffe7952d..0e8baeb7 100644
--- a/controllers/argocd/argocd_controller.go
+++ b/controllers/argocd/argocd_controller.go
@@ -41,6 +41,8 @@ type ReconcileArgoCD struct {
 	client.Client
 	Scheme            *runtime.Scheme
 	ManagedNamespaces *corev1.NamespaceList
+	// Stores a list of SourceNamespaces as values
+	ManagedSourceNamespaces map[string]string
 }
 
 var log = logr.Log.WithName("controller_argocd")
@@ -100,6 +102,10 @@ func (r *ReconcileArgoCD) Reconcile(ctx context.Context, request ctrl.Request) (
 				}
 			}
 
+			if err := r.removeUnmanagedSourceNamespaceResources(argocd); err != nil {
+				return reconcile.Result{}, fmt.Errorf("failed to remove resources from sourceNamespaces, error: %w", err)
+			}
+
 			if err := r.removeDeletionFinalizer(argocd); err != nil {
 				return reconcile.Result{}, err
 			}
@@ -128,6 +134,10 @@ func (r *ReconcileArgoCD) Reconcile(ctx context.Context, request ctrl.Request) (
 		return reconcile.Result{}, err
 	}
 
+	if err = r.setManagedSourceNamespaces(argocd); err != nil {
+		return reconcile.Result{}, err
+	}
+
 	if err := r.reconcileResources(argocd); err != nil {
 		// Error reconciling ArgoCD sub-resources - requeue the request.
 		return reconcile.Result{}, err
diff --git a/controllers/argocd/deployment.go b/controllers/argocd/deployment.go
index b316ffae..7add740c 100644
--- a/controllers/argocd/deployment.go
+++ b/controllers/argocd/deployment.go
@@ -308,6 +308,9 @@ func getArgoServerCommand(cr *argoprojv1a1.ArgoCD, useTLSForRedis bool) []string
 	if err != nil {
 		return cmd
 	}
+	if cr.Spec.SourceNamespaces != nil && len(cr.Spec.SourceNamespaces) > 0 {
+		cmd = append(cmd, "--application-namespaces", fmt.Sprint(strings.Join(cr.Spec.SourceNamespaces, ",")))
+	}
 
 	cmd = append(cmd, extraArgs...)
 	return cmd
diff --git a/controllers/argocd/policyrule.go b/controllers/argocd/policyrule.go
index f8d8e399..6f09376c 100644
--- a/controllers/argocd/policyrule.go
+++ b/controllers/argocd/policyrule.go
@@ -209,6 +209,27 @@ func policyRuleForNotificationsController() []v1.PolicyRule {
 	}
 }
 
+func policyRuleForServerApplicationSourceNamespaces() []v1.PolicyRule {
+	return []v1.PolicyRule{
+		{
+			APIGroups: []string{
+				"argoproj.io",
+			},
+			Resources: []string{
+				"applications",
+			},
+			Verbs: []string{
+				"get",
+				"list",
+				"patch",
+				"update",
+				"watch",
+				"delete",
+			},
+		},
+	}
+}
+
 func policyRuleForServerClusterRole() []v1.PolicyRule {
 	return []v1.PolicyRule{
 		{
diff --git a/controllers/argocd/role.go b/controllers/argocd/role.go
index 1874661e..eff8c1db 100644
--- a/controllers/argocd/role.go
+++ b/controllers/argocd/role.go
@@ -6,6 +6,7 @@ import (
 	"os"
 	"reflect"
 
+	corev1 "k8s.io/api/core/v1"
 	v1 "k8s.io/api/rbac/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -30,6 +31,17 @@ func newRole(name string, rules []v1.PolicyRule, cr *argoprojv1a1.ArgoCD) *v1.Ro
 	}
 }
 
+func newRoleForApplicationSourceNamespaces(name, namespace string, rules []v1.PolicyRule, cr *argoprojv1a1.ArgoCD) *v1.Role {
+	return &v1.Role{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      getRoleNameForApplicationSourceNamespaces(namespace, cr),
+			Namespace: namespace,
+			Labels:    argoutil.LabelsForCluster(cr),
+		},
+		Rules: rules,
+	}
+}
+
 func generateResourceName(argoComponentName string, cr *argoprojv1a1.ArgoCD) string {
 	return cr.Name + "-" + argoComponentName
 }
@@ -68,6 +80,19 @@ func (r *ReconcileArgoCD) reconcileRoles(cr *argoprojv1a1.ArgoCD) error {
 		}
 	}
 
+	log.Info("reconciling roles for source namespaces")
+	policyRuleForApplicationSourceNamespaces := policyRuleForServerApplicationSourceNamespaces()
+	// reconcile roles is source namespaces for ArgoCD Server
+	if _, err := r.reconcileRoleForApplicationSourceNamespaces(common.ArgoCDServerComponent, policyRuleForApplicationSourceNamespaces, cr); err != nil {
+		return err
+	}
+
+	log.Info("performing cleanup for source namespaces")
+	// remove resources for namespaces not part of SourceNamespaces
+	if err := r.removeUnmanagedSourceNamespaceResources(cr); err != nil {
+		return err
+	}
+
 	return nil
 }
 
@@ -156,6 +181,92 @@ func (r *ReconcileArgoCD) reconcileRole(name string, policyRules []v1.PolicyRule
 	return roles, nil
 }
 
+func (r *ReconcileArgoCD) reconcileRoleForApplicationSourceNamespaces(name string, policyRules []v1.PolicyRule, cr *argoprojv1a1.ArgoCD) ([]*v1.Role, error) {
+	var roles []*v1.Role
+
+	// create policy rules for each source namespace for ArgoCD Server
+	for _, sourceNamespace := range cr.Spec.SourceNamespaces {
+
+		namespace := &corev1.Namespace{}
+		if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: sourceNamespace}, namespace); err != nil {
+			return nil, err
+		}
+
+		// do not reconcile roles for namespaces already containing managed-by label
+		// as it already contains roles with permissions to manipulate application resources
+		// reconciled during reconcilation of ManagedNamespaces
+		if value, ok := namespace.Labels[common.ArgoCDManagedByLabel]; ok && value != "" {
+			log.Info(fmt.Sprintf("Skipping reconciling resources for namespace %s as it is already managed-by namespace %s.", namespace.Name, value))
+			// if managed-by-cluster-argocd label is also present, remove the namespace from the ManagedSourceNamespaces.
+			if val, ok1 := namespace.Labels[common.ArgoCDManagedByClusterArgoCDLabel]; ok1 && val == cr.Namespace {
+				delete(r.ManagedSourceNamespaces, namespace.Name)
+				if err := r.cleanupUnmanagedSourceNamespaceResources(cr, namespace.Name); err != nil {
+					log.Error(err, fmt.Sprintf("error cleaning up resources for namespace %s", namespace.Name))
+				}
+			}
+			continue
+		}
+
+		log.Info(fmt.Sprintf("Reconciling role for %s", namespace.Name))
+
+		role := newRoleForApplicationSourceNamespaces(name, namespace.Name, policyRules, cr)
+		if err := applyReconcilerHook(cr, role, ""); err != nil {
+			return nil, err
+		}
+		role.Namespace = namespace.Name
+		existingRole := v1.Role{}
+		err := r.Client.Get(context.TODO(), types.NamespacedName{Name: role.Name, Namespace: namespace.Name}, &existingRole)
+		if err != nil {
+			if !errors.IsNotFound(err) {
+				return nil, fmt.Errorf("failed to reconcile the role for the service account associated with %s : %s", name, err)
+			}
+		}
+
+		// do not reconcile roles for namespaces already containing managed-by-cluster-argocd label
+		// as it already contains roles reconciled during reconcilation of ManagedNamespaces
+		if _, ok := r.ManagedSourceNamespaces[sourceNamespace]; ok {
+			// If sourceNamespace includes the name but role is missing in the namespace, create the role
+			if reflect.DeepEqual(existingRole, v1.Role{}) {
+				log.Info(fmt.Sprintf("creating role %s for Argo CD instance %s in namespace %s", role.Name, cr.Name, namespace))
+				if err := r.Client.Create(context.TODO(), role); err != nil {
+					return nil, err
+				}
+			}
+			continue
+		}
+
+		// reconcile roles only if another ArgoCD instance is not already set as value for managed-by-cluster-argocd label
+		if value, ok := namespace.Labels[common.ArgoCDManagedByClusterArgoCDLabel]; ok && value != "" {
+			log.Info(fmt.Sprintf("Namespace already has label set to argocd instance %s. Thus, skipping namespace %s", value, namespace.Name))
+			continue
+		}
+
+		// Get the latest value of namespace before updating it
+		if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: namespace.Name}, namespace); err != nil {
+			return nil, err
+		}
+		// Update namespace with managed-by-cluster-argocd label
+		namespace.Labels[common.ArgoCDManagedByClusterArgoCDLabel] = cr.Namespace
+		if err := r.Client.Update(context.TODO(), namespace); err != nil {
+			log.Error(err, fmt.Sprintf("failed to add label from namespace [%s]", namespace.Name))
+		}
+		// if the Rules differ, update the Role
+		if !reflect.DeepEqual(existingRole.Rules, role.Rules) {
+			existingRole.Rules = role.Rules
+			if err := r.Client.Update(context.TODO(), &existingRole); err != nil {
+				return nil, err
+			}
+		}
+		roles = append(roles, &existingRole)
+
+		if _, ok := r.ManagedSourceNamespaces[sourceNamespace]; !ok {
+			r.ManagedSourceNamespaces[sourceNamespace] = ""
+		}
+
+	}
+	return roles, nil
+}
+
 func (r *ReconcileArgoCD) reconcileClusterRole(name string, policyRules []v1.PolicyRule, cr *argoprojv1a1.ArgoCD) (*v1.ClusterRole, error) {
 	allowed := false
 	if allowedNamespace(cr.Namespace, os.Getenv("ARGOCD_CLUSTER_CONFIG_NAMESPACES")) {
diff --git a/controllers/argocd/rolebinding.go b/controllers/argocd/rolebinding.go
index 1c9f32df..353e1196 100644
--- a/controllers/argocd/rolebinding.go
+++ b/controllers/argocd/rolebinding.go
@@ -54,6 +54,22 @@ func newRoleBinding(cr *argoprojv1a1.ArgoCD) *v1.RoleBinding {
 	}
 }
 
+// newRoleBindingForSupportNamespaces returns a new RoleBinding instance.
+func newRoleBindingForSupportNamespaces(cr *argoprojv1a1.ArgoCD, namespace string) *v1.RoleBinding {
+	return &v1.RoleBinding{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:        getRoleBindingNameForSourceNamespaces(cr.Name, cr.Namespace, namespace),
+			Labels:      argoutil.LabelsForCluster(cr),
+			Annotations: argoutil.AnnotationsForCluster(cr),
+			Namespace:   namespace,
+		},
+	}
+}
+
+func getRoleBindingNameForSourceNamespaces(argocdName, argocdNamespace, targetNamespace string) string {
+	return fmt.Sprintf("%s_%s", argocdName, targetNamespace)
+}
+
 // newRoleBindingWithname creates a new RoleBinding with the given name for the given ArgCD.
 func newRoleBindingWithname(name string, cr *argoprojv1a1.ArgoCD) *v1.RoleBinding {
 	roleBinding := newRoleBinding(cr)
@@ -68,7 +84,6 @@ func newRoleBindingWithname(name string, cr *argoprojv1a1.ArgoCD) *v1.RoleBindin
 
 // reconcileRoleBindings will ensure that all ArgoCD RoleBindings are configured.
 func (r *ReconcileArgoCD) reconcileRoleBindings(cr *argoprojv1a1.ArgoCD) error {
-
 	params := getPolicyRuleList(r.Client)
 
 	for _, param := range params {
@@ -195,6 +210,91 @@ func (r *ReconcileArgoCD) reconcileRoleBinding(name string, rules []v1.PolicyRul
 			return err
 		}
 	}
+
+	// reconcile rolebindings only for ArgoCDServerComponent
+	if name == common.ArgoCDServerComponent {
+
+		// reconcile rolebindings for all source namespaces for argocd-server
+		for _, sourceNamespace := range cr.Spec.SourceNamespaces {
+			namespace := &corev1.Namespace{}
+			if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: sourceNamespace}, namespace); err != nil {
+				return err
+			}
+
+			// do not reconcile rolebindings for namespaces already containing managed-by label
+			// as it already contains rolebindings with permissions to manipulate application resources
+			// reconciled during reconcilation of ManagedNamespaces
+			if value, ok := namespace.Labels[common.ArgoCDManagedByLabel]; ok {
+				log.Info(fmt.Sprintf("Skipping reconciling resources for namespace %s as it is already managed-by namespace %s.", namespace.Name, value))
+				continue
+			}
+
+			list := &argoprojv1a1.ArgoCDList{}
+			listOption := &client.ListOptions{Namespace: namespace.Name}
+			err := r.Client.List(context.TODO(), list, listOption)
+			if err != nil {
+				log.Info(err.Error())
+				return err
+			}
+
+			// get expected name
+			roleBinding := newRoleBindingWithNameForApplicationSourceNamespaces(name, namespace.Name, cr)
+			roleBinding.Namespace = namespace.Name
+
+			roleBinding.RoleRef = v1.RoleRef{
+				APIGroup: v1.GroupName,
+				Kind:     "Role",
+				Name:     getRoleNameForApplicationSourceNamespaces(namespace.Name, cr),
+			}
+
+			// fetch existing rolebinding by name
+			existingRoleBinding := &v1.RoleBinding{}
+			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: roleBinding.Name, Namespace: roleBinding.Namespace}, existingRoleBinding)
+			roleBindingExists := true
+			if err != nil {
+				if !errors.IsNotFound(err) {
+					return fmt.Errorf("failed to get the rolebinding associated with %s : %s", name, err)
+				}
+				log.Info(fmt.Sprintf("Existing rolebinding %s", err.Error()))
+				roleBindingExists = false
+			}
+
+			roleBinding.Subjects = []v1.Subject{
+				{
+					Kind:      v1.ServiceAccountKind,
+					Name:      sa.Name,
+					Namespace: sa.Namespace,
+				},
+			}
+
+			if roleBindingExists {
+				// reconcile role bindings for namespaces already containing managed-by-cluster-argocd label only
+				if n, ok := namespace.Labels[common.ArgoCDManagedByClusterArgoCDLabel]; !ok || n == cr.Namespace {
+					continue
+				}
+				// if the RoleRef changes, delete the existing role binding and create a new one
+				if !reflect.DeepEqual(roleBinding.RoleRef, existingRoleBinding.RoleRef) {
+					if err = r.Client.Delete(context.TODO(), existingRoleBinding); err != nil {
+						return err
+					}
+				} else {
+					// if the Subjects differ, update the role bindings
+					if !reflect.DeepEqual(roleBinding.Subjects, existingRoleBinding.Subjects) {
+						existingRoleBinding.Subjects = roleBinding.Subjects
+						if err = r.Client.Update(context.TODO(), existingRoleBinding); err != nil {
+							return err
+						}
+					}
+					continue
+				}
+			}
+
+			log.Info(fmt.Sprintf("creating rolebinding %s for Argo CD instance %s in namespace %s", roleBinding.Name, cr.Name, namespace))
+			if err = r.Client.Create(context.TODO(), roleBinding); err != nil {
+				return err
+			}
+		}
+	}
 	return nil
 }
 
@@ -208,6 +308,22 @@ func getCustomRoleName(name string) string {
 	return ""
 }
 
+// Returns the name of the role for the source namespaces for ArgoCDServer in the format of "sourceNamespace_targetNamespace_argocd-server"
+func getRoleNameForApplicationSourceNamespaces(targetNamespace string, cr *argoprojv1a1.ArgoCD) string {
+	return fmt.Sprintf("%s_%s_%s", cr.Name, targetNamespace, common.ArgoCDServerComponent)
+}
+
+// newRoleBindingWithNameForApplicationSourceNamespaces creates a new RoleBinding with the given name for the source namespaces of ArgoCD Server.
+func newRoleBindingWithNameForApplicationSourceNamespaces(name, namespace string, cr *argoprojv1a1.ArgoCD) *v1.RoleBinding {
+	roleBinding := newRoleBindingForSupportNamespaces(cr, namespace)
+
+	labels := roleBinding.ObjectMeta.Labels
+	labels[common.ArgoCDKeyName] = roleBinding.ObjectMeta.Name
+	roleBinding.ObjectMeta.Labels = labels
+
+	return roleBinding
+}
+
 func (r *ReconcileArgoCD) reconcileClusterRoleBinding(name string, role *v1.ClusterRole, cr *argoprojv1a1.ArgoCD) error {
 
 	// get expected name
diff --git a/controllers/argocd/util.go b/controllers/argocd/util.go
index 36eb9a2c..3ad1b771 100644
--- a/controllers/argocd/util.go
+++ b/controllers/argocd/util.go
@@ -47,6 +47,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	networkingv1 "k8s.io/api/networking/v1"
 	v1 "k8s.io/api/rbac/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -136,6 +137,10 @@ func getArgoApplicationControllerCommand(cr *argoprojv1a1.ArgoCD, useTLSForRedis
 	cmd = append(cmd, "--status-processors", fmt.Sprint(getArgoServerStatusProcessors(cr)))
 	cmd = append(cmd, "--kubectl-parallelism-limit", fmt.Sprint(getArgoControllerParellismLimit(cr)))
 
+	if cr.Spec.SourceNamespaces != nil && len(cr.Spec.SourceNamespaces) > 0 {
+		cmd = append(cmd, "--application-namespaces", fmt.Sprint(strings.Join(cr.Spec.SourceNamespaces, ",")))
+	}
+
 	if cr.Spec.Controller.AppSync != nil {
 		cmd = append(cmd, "--app-resync", strconv.FormatInt(int64(cr.Spec.Controller.AppSync.Seconds()), 10))
 	}
@@ -721,16 +726,19 @@ func (r *ReconcileArgoCD) reconcileResources(cr *argoprojv1a1.ArgoCD) error {
 
 	log.Info("reconciling roles")
 	if err := r.reconcileRoles(cr); err != nil {
+		log.Info(err.Error())
 		return err
 	}
 
 	log.Info("reconciling rolebindings")
 	if err := r.reconcileRoleBindings(cr); err != nil {
+		log.Info(err.Error())
 		return err
 	}
 
 	log.Info("reconciling service accounts")
 	if err := r.reconcileServiceAccounts(cr); err != nil {
+		log.Info(err.Error())
 		return err
 	}
 
@@ -1360,6 +1368,94 @@ func (r *ReconcileArgoCD) setManagedNamespaces(cr *argoproj.ArgoCD) error {
 	return nil
 }
 
+func (r *ReconcileArgoCD) setManagedSourceNamespaces(cr *argoproj.ArgoCD) error {
+	r.ManagedSourceNamespaces = make(map[string]string)
+	namespaces := &corev1.NamespaceList{}
+	listOption := client.MatchingLabels{
+		common.ArgoCDManagedByClusterArgoCDLabel: cr.Namespace,
+	}
+
+	// get the list of namespaces managed by the Argo CD instance
+	if err := r.Client.List(context.TODO(), namespaces, listOption); err != nil {
+		return err
+	}
+
+	for _, namespace := range namespaces.Items {
+		r.ManagedSourceNamespaces[namespace.Name] = ""
+	}
+
+	return nil
+}
+
+// removeUnmanagedSourceNamespaceResources cleansup resources from SourceNamespaces if namespace is not managed by argocd instance.
+// It also removes the managed-by-cluster-argocd label from the namespace
+func (r *ReconcileArgoCD) removeUnmanagedSourceNamespaceResources(cr *argoproj.ArgoCD) error {
+
+	for ns, _ := range r.ManagedSourceNamespaces {
+		managedNamespace := false
+		if cr.GetDeletionTimestamp() == nil {
+			for _, namespace := range cr.Spec.SourceNamespaces {
+				if namespace == ns {
+					managedNamespace = true
+					break
+				}
+			}
+		}
+
+		if !managedNamespace {
+			if err := r.cleanupUnmanagedSourceNamespaceResources(cr, ns); err != nil {
+				log.Error(err, fmt.Sprintf("error cleaning up resources for namespace %s", ns))
+				continue
+			}
+			delete(r.ManagedSourceNamespaces, ns)
+		}
+	}
+	return nil
+}
+
+func (r *ReconcileArgoCD) cleanupUnmanagedSourceNamespaceResources(cr *argoproj.ArgoCD, ns string) error {
+	namespace := corev1.Namespace{}
+	if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: ns}, &namespace); err != nil {
+		if !errors.IsNotFound(err) {
+			return err
+		}
+		return nil
+	}
+	// Remove managed-by-cluster-argocd from the namespace
+	delete(namespace.Labels, common.ArgoCDManagedByClusterArgoCDLabel)
+	if err := r.Client.Update(context.TODO(), &namespace); err != nil {
+		log.Error(err, fmt.Sprintf("failed to remove label from namespace [%s]", namespace.Name))
+	}
+
+	// Delete Roles for SourceNamespaces
+	existingRole := v1.Role{}
+	roleName := getRoleNameForApplicationSourceNamespaces(namespace.Name, cr)
+	if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: roleName, Namespace: namespace.Name}, &existingRole); err != nil {
+		if !errors.IsNotFound(err) {
+			return fmt.Errorf("failed to fetch the role for the service account associated with %s : %s", common.ArgoCDServerComponent, err)
+		}
+	}
+	if existingRole.Name != "" {
+		if err := r.Client.Delete(context.TODO(), &existingRole); err != nil {
+			return err
+		}
+	}
+	// Delete RoleBindings for SourceNamespaces
+	existingRoleBinding := &v1.RoleBinding{}
+	roleBindingName := getRoleBindingNameForSourceNamespaces(cr.Name, cr.Namespace, namespace.Name)
+	if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: roleBindingName, Namespace: namespace.Name}, existingRoleBinding); err != nil {
+		if !errors.IsNotFound(err) {
+			return fmt.Errorf("failed to get the rolebinding associated with %s : %s", common.ArgoCDServerComponent, err)
+		}
+	}
+	if existingRoleBinding.Name != "" {
+		if err := r.Client.Delete(context.TODO(), existingRoleBinding); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
 func isProxyCluster() bool {
 	cfg, err := config.GetConfig()
 	if err != nil {
diff --git a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applications.yaml b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applications.yaml
index 09f9976b..b4b9bcb8 100644
--- a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applications.yaml
+++ b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applications.yaml
@@ -1806,6 +1806,10 @@ spec:
                   reconciled using the latest git version
                 format: date-time
                 type: string
+              resourceHealthSource:
+                description: 'ResourceHealthSource indicates where the resource health
+                  status is stored: inline if not set or appTree'
+                type: string
               resources:
                 description: Resources is a list of Kubernetes resources managed by
                   this application
diff --git a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applicationsets.yaml b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applicationsets.yaml
index 4203a739..c83c4d00 100644
--- a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applicationsets.yaml
+++ b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_applicationsets.yaml
@@ -2372,6 +2372,8 @@ spec:
                                     properties:
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       labels:
                                         items:
                                           type: string
@@ -2394,6 +2396,31 @@ spec:
                                     - owner
                                     - repo
                                     type: object
+                                  gitlab:
+                                    properties:
+                                      api:
+                                        type: string
+                                      labels:
+                                        items:
+                                          type: string
+                                        type: array
+                                      project:
+                                        type: string
+                                      pullRequestState:
+                                        type: string
+                                      tokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                    required:
+                                    - project
+                                    type: object
                                   requeueAfterSeconds:
                                     format: int64
                                     type: integer
@@ -2655,6 +2682,31 @@ spec:
                                 type: object
                               scmProvider:
                                 properties:
+                                  azureDevOps:
+                                    properties:
+                                      accessTokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                      allBranches:
+                                        type: boolean
+                                      api:
+                                        type: string
+                                      organization:
+                                        type: string
+                                      teamProject:
+                                        type: string
+                                    required:
+                                    - accessTokenRef
+                                    - organization
+                                    - teamProject
+                                    type: object
                                   bitbucket:
                                     properties:
                                       allBranches:
@@ -2759,6 +2811,8 @@ spec:
                                         type: boolean
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       organization:
                                         type: string
                                       tokenRef:
@@ -3056,6 +3110,29 @@ spec:
                                     - spec
                                     type: object
                                 type: object
+                              selector:
+                                properties:
+                                  matchExpressions:
+                                    items:
+                                      properties:
+                                        key:
+                                          type: string
+                                        operator:
+                                          type: string
+                                        values:
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    type: object
+                                type: object
                             type: object
                           type: array
                         template:
@@ -4525,6 +4602,8 @@ spec:
                                     properties:
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       labels:
                                         items:
                                           type: string
@@ -4547,6 +4626,31 @@ spec:
                                     - owner
                                     - repo
                                     type: object
+                                  gitlab:
+                                    properties:
+                                      api:
+                                        type: string
+                                      labels:
+                                        items:
+                                          type: string
+                                        type: array
+                                      project:
+                                        type: string
+                                      pullRequestState:
+                                        type: string
+                                      tokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                    required:
+                                    - project
+                                    type: object
                                   requeueAfterSeconds:
                                     format: int64
                                     type: integer
@@ -4808,6 +4912,31 @@ spec:
                                 type: object
                               scmProvider:
                                 properties:
+                                  azureDevOps:
+                                    properties:
+                                      accessTokenRef:
+                                        properties:
+                                          key:
+                                            type: string
+                                          secretName:
+                                            type: string
+                                        required:
+                                        - key
+                                        - secretName
+                                        type: object
+                                      allBranches:
+                                        type: boolean
+                                      api:
+                                        type: string
+                                      organization:
+                                        type: string
+                                      teamProject:
+                                        type: string
+                                    required:
+                                    - accessTokenRef
+                                    - organization
+                                    - teamProject
+                                    type: object
                                   bitbucket:
                                     properties:
                                       allBranches:
@@ -4912,6 +5041,8 @@ spec:
                                         type: boolean
                                       api:
                                         type: string
+                                      appSecretName:
+                                        type: string
                                       organization:
                                         type: string
                                       tokenRef:
@@ -5209,6 +5340,29 @@ spec:
                                     - spec
                                     type: object
                                 type: object
+                              selector:
+                                properties:
+                                  matchExpressions:
+                                    items:
+                                      properties:
+                                        key:
+                                          type: string
+                                        operator:
+                                          type: string
+                                        values:
+                                          items:
+                                            type: string
+                                          type: array
+                                      required:
+                                      - key
+                                      - operator
+                                      type: object
+                                    type: array
+                                  matchLabels:
+                                    additionalProperties:
+                                      type: string
+                                    type: object
+                                type: object
                             type: object
                           type: array
                         mergeKeys:
@@ -5543,6 +5697,8 @@ spec:
                           properties:
                             api:
                               type: string
+                            appSecretName:
+                              type: string
                             labels:
                               items:
                                 type: string
@@ -5565,6 +5721,31 @@ spec:
                           - owner
                           - repo
                           type: object
+                        gitlab:
+                          properties:
+                            api:
+                              type: string
+                            labels:
+                              items:
+                                type: string
+                              type: array
+                            project:
+                              type: string
+                            pullRequestState:
+                              type: string
+                            tokenRef:
+                              properties:
+                                key:
+                                  type: string
+                                secretName:
+                                  type: string
+                              required:
+                              - key
+                              - secretName
+                              type: object
+                          required:
+                          - project
+                          type: object
                         requeueAfterSeconds:
                           format: int64
                           type: integer
@@ -5826,6 +6007,31 @@ spec:
                       type: object
                     scmProvider:
                       properties:
+                        azureDevOps:
+                          properties:
+                            accessTokenRef:
+                              properties:
+                                key:
+                                  type: string
+                                secretName:
+                                  type: string
+                              required:
+                              - key
+                              - secretName
+                              type: object
+                            allBranches:
+                              type: boolean
+                            api:
+                              type: string
+                            organization:
+                              type: string
+                            teamProject:
+                              type: string
+                          required:
+                          - accessTokenRef
+                          - organization
+                          - teamProject
+                          type: object
                         bitbucket:
                           properties:
                             allBranches:
@@ -5930,6 +6136,8 @@ spec:
                               type: boolean
                             api:
                               type: string
+                            appSecretName:
+                              type: string
                             organization:
                               type: string
                             tokenRef:
@@ -6227,8 +6435,33 @@ spec:
                           - spec
                           type: object
                       type: object
+                    selector:
+                      properties:
+                        matchExpressions:
+                          items:
+                            properties:
+                              key:
+                                type: string
+                              operator:
+                                type: string
+                              values:
+                                items:
+                                  type: string
+                                type: array
+                            required:
+                            - key
+                            - operator
+                            type: object
+                          type: array
+                        matchLabels:
+                          additionalProperties:
+                            type: string
+                          type: object
+                      type: object
                   type: object
                 type: array
+              goTemplate:
+                type: boolean
               syncPolicy:
                 properties:
                   preserveResourcesOnDeletion:
diff --git a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_appprojects.yaml b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_appprojects.yaml
index 1b6aed00..8504d6ff 100644
--- a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_appprojects.yaml
+++ b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_appprojects.yaml
@@ -160,6 +160,10 @@ spec:
                       for apps which have orphaned resources
                     type: boolean
                 type: object
+              permitOnlyProjectScopedClusters:
+                description: PermitOnlyProjectScopedClusters determines whether destinations
+                  can only reference clusters which are project-scoped
+                type: boolean
               roles:
                 description: Roles are user defined RBAC roles associated with this
                   project
@@ -222,6 +226,12 @@ spec:
                   - keyID
                   type: object
                 type: array
+              sourceNamespaces:
+                description: SourceNamespaces defines the namespaces application resources
+                  are allowed to be created in
+                items:
+                  type: string
+                type: array
               sourceRepos:
                 description: SourceRepos contains list of repository URLs which can
                   be used for deployment
diff --git a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml
index 7f22c8c7..d0aab458 100644
--- a/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml
+++ b/deploy/olm-catalog/argocd-operator/0.5.0/argoproj.io_argocds.yaml
@@ -5926,6 +5926,12 @@ spec:
                     - type
                     type: object
                 type: object
+              sourceNamespaces:
+                description: SourceNamespaces defines the namespaces application resources
+                  are allowed to be created in
+                items:
+                  type: string
+                type: array
               sso:
                 description: SSO defines the Single Sign-on configuration for Argo
                   CD
diff --git a/docs/usage/apps-in-any-namespace.md b/docs/usage/apps-in-any-namespace.md
new file mode 100644
index 00000000..c401da6e
--- /dev/null
+++ b/docs/usage/apps-in-any-namespace.md
@@ -0,0 +1,49 @@
+# Applications in any namespace
+
+**Current feature state**: Beta
+
+Argo CD supports managing Application resources in namespaces other than the control plane's namespace (which is usally argocd), but this feature has to be explicitly enabled and configured appropriately.
+
+Argo CD administrators can define a certain set of namespaces where Application resources may be created, updated and reconciled in. However, applications in these additional namespaces will only be allowed to use certain AppProjects, as configured by the Argo CD administrators. This allows ordinary Argo CD users (e.g. application teams) to use patterns like declarative management of Application resources, implementing app-of-apps and others without the risk of a privilege escalation through usage of other AppProjects that would exceed the permissions granted to the application teams.
+
+!!! note
+    This feature is considered beta feature in upstream Argo CD as of now. Some of the implementation details may change over the course of time until it is promoted to a stable status.
+
+## Using application-namespaces
+In order to enable this feature, the Argo CD administrator must reconfigure the argocd-server and argocd-application-controller workloads to add the --application-namespaces parameter to the container's startup command.
+
+The `--application-namespaces` parameter takes a comma-separated list of namespaces where Applications are to be allowed in. Each entry of the list supports shell-style wildcards such as `*`, so for example the entry `app-team-*` would match `app-team-one` and `app-team-two`. To enable all namespaces on the cluster where Argo CD is running on, you can just `*`, i.e. `--application-namespaces=*`.
+
+You can set the namespaces for argocd-server and argocd-controller in the ArgoCD yaml by setting `spec.sourceNamespaces`.
+
+## Example
+
+```yaml
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+spec:
+  sourceNamespaces:
+    - some-namespace
+```
+
+When a namespace is specified under `sourceNamespaces`, operator adds `argocd.argoproj.io/managed-by-cluster-argocd` label to the specified namespace. For example, the namespace would look like below:
+
+```yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+  labels:
+    argocd.argoproj.io/managed-by-cluster-argocd: example-argocd
+    kubernetes.io/metadata.name: some-namespace
+  name: some-namespace
+```
+
+**Things to consider:**
+
+* No namespace can be managed by multiple argo-cd instances (cluster scoped or namespace scoped) i.e, only one of either `managed-by` or `managed-by-cluster-argocd` labels can be applied to a given namespace. We will be prioritizing `managed-by` label in case of a conflict as this feature is currently in beta, so the new roles/rolebindings will not be created if namespace is already labelled with `managed-by` label, and they will be deleted if a namespace is first added to the `sourceNamespacs` list and is later also labelled with `managed-by` label.
+
+* Users will not be create/manage apps and create app resources in the same namespace that is added to `sourceNamespaces` (as they both require their own labels) out of the box. As a workaround users will have to create custom roles to be able to create app resources in the namespace added to `sourceNamespaces`.
+
+
diff --git a/go.mod b/go.mod
index 914769cb..bc474744 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/argoproj-labs/argocd-operator
 go 1.18
 
 require (
-	github.com/argoproj/argo-cd/v2 v2.4.7
+	github.com/argoproj/argo-cd/v2 v2.5.2
 	github.com/coreos/prometheus-operator v0.40.0
 	github.com/go-logr/logr v1.2.3
 	github.com/google/go-cmp v0.5.8
@@ -19,8 +19,8 @@ require (
 	github.com/stretchr/testify v1.7.1
 	golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3
 	gopkg.in/yaml.v2 v2.4.0
-	k8s.io/api v0.23.3
-	k8s.io/apimachinery v0.23.3
+	k8s.io/api v0.24.2
+	k8s.io/apimachinery v0.24.2
 	k8s.io/client-go v12.0.0+incompatible
 	sigs.k8s.io/controller-runtime v0.11.0
 )
@@ -61,10 +61,10 @@ require (
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/nxadm/tail v1.4.8 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/prometheus/client_golang v1.11.0 // indirect
+	github.com/prometheus/client_golang v1.12.1 // indirect
 	github.com/prometheus/client_model v0.2.0 // indirect
-	github.com/prometheus/common v0.28.0 // indirect
-	github.com/prometheus/procfs v0.6.0 // indirect
+	github.com/prometheus/common v0.32.1 // indirect
+	github.com/prometheus/procfs v0.7.3 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	go.uber.org/atomic v1.7.0 // indirect
 	go.uber.org/multierr v1.6.0 // indirect
@@ -75,20 +75,20 @@ require (
 	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
 	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 	golang.org/x/text v0.3.7 // indirect
-	golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
+	golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
 	google.golang.org/protobuf v1.28.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
-	k8s.io/apiextensions-apiserver v0.23.1 // indirect
-	k8s.io/component-base v0.23.1 // indirect
-	k8s.io/klog/v2 v2.30.0 // indirect
-	k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
-	k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect
-	sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
-	sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect
+	k8s.io/apiextensions-apiserver v0.24.2 // indirect
+	k8s.io/component-base v0.24.2 // indirect
+	k8s.io/klog/v2 v2.70.1 // indirect
+	k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 // indirect
+	k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
+	sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
 	sigs.k8s.io/yaml v1.3.0 // indirect
 )
 
diff --git a/go.sum b/go.sum
index 6e577223..2708e7ab 100644
--- a/go.sum
+++ b/go.sum
@@ -147,8 +147,8 @@ github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.m
 github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
 github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/argoproj/argo-cd/v2 v2.4.7 h1:6rPiKhd9EamVguPS4IKdQFoWyD5gZd2b4a/PSrCNFAk=
-github.com/argoproj/argo-cd/v2 v2.4.7/go.mod h1:CnD0D1JGTSFxkALblVZiSm8sVgEKH1oaFQoMtpC7EaE=
+github.com/argoproj/argo-cd/v2 v2.5.2 h1:hyPi8NFXW3tG2yURslIMI20GfCdTN1/BDnt4+v5lpoA=
+github.com/argoproj/argo-cd/v2 v2.5.2/go.mod h1:3ToENm286PFVlZKNMutBzOwNyhevz4fw9dcgyiq3FIY=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -1013,8 +1013,9 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O
 github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
 github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
 github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -1034,8 +1035,9 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2
 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
 github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.28.0 h1:vGVfV9KrDTvWt5boZO0I19g2E3CsWfpPPKZM9dt3mEw=
 github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
+github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
+github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
 github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -1050,8 +1052,9 @@ github.com/prometheus/procfs v0.0.6/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
+github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/prometheus/prometheus v0.0.0-20180315085919-58e2a31db8de/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
 github.com/prometheus/prometheus v1.8.2-0.20200110114423-1e64d757f711/go.mod h1:7U90zPoLkWjEIQcy/rweQla82OCTUzxVHE51G3OhJbI=
 github.com/prometheus/prometheus v1.8.2-0.20200507164740-ecee9c8abfd1/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY=
@@ -1549,6 +1552,7 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1572,8 +1576,9 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1929,8 +1934,9 @@ k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
 k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
+k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
 k8s.io/kube-openapi v0.0.0-20210323165736-1a6458611d18 h1:BWMcoT2cx+iaBhcemnBAA0G58WbBWgfh1V05r/uSPJs=
 k8s.io/kube-openapi v0.0.0-20210323165736-1a6458611d18/go.mod h1:UDkTDGblU9FBGrWsHAJ8G3ukmPKbCiJL1gCuA1DFd4I=
 k8s.io/kube-state-metrics v1.7.2/go.mod h1:U2Y6DRi07sS85rmVPmBFlmv+2peBcL8IWGjM+IjYA/E=
@@ -1943,8 +1949,9 @@ k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl
 k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs=
 k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
+k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
@@ -1965,8 +1972,8 @@ sigs.k8s.io/kustomize/kustomize/v4 v4.4.1/go.mod h1:qOKJMMz2mBP+vcS7vK+mNz4HBLja
 sigs.k8s.io/kustomize/kyaml v0.13.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.0 h1:kDvPBbnPk+qYmkHmSo8vKGp438IASWofnbbUKDE/bv0=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.0/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
+sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
+sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=


Test patch:
diff --git a/controllers/argocd/role_test.go b/controllers/argocd/role_test.go
index 1f012965..eb84550e 100644
--- a/controllers/argocd/role_test.go
+++ b/controllers/argocd/role_test.go
@@ -14,6 +14,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 
+	"github.com/argoproj-labs/argocd-operator/api/v1alpha1"
 	"github.com/argoproj-labs/argocd-operator/common"
 )
 
@@ -121,6 +122,33 @@ func TestReconcileArgoCD_reconcileClusterRole(t *testing.T) {
 	assert.Contains(t, r.Client.Get(context.TODO(), types.NamespacedName{Name: clusterRoleName}, reconciledClusterRole).Error(), "not found")
 }
 
+func TestReconcileArgoCD_reconcileRoleForApplicationSourceNamespaces(t *testing.T) {
+	logf.SetLogger(ZapLogger(true))
+	sourceNamespace := "newNamespaceTest"
+	a := makeTestArgoCD()
+	a.Spec = v1alpha1.ArgoCDSpec{
+		SourceNamespaces: []string{
+			sourceNamespace,
+		},
+	}
+	r := makeTestReconciler(t, a)
+	assert.NoError(t, createNamespace(r, a.Namespace, ""))
+	assert.NoError(t, createNamespaceManagedByClusterArgoCDLabel(r, sourceNamespace, a.Namespace))
+
+	workloadIdentifier := common.ArgoCDServerComponent
+	expectedRules := policyRuleForServerApplicationSourceNamespaces()
+	_, err := r.reconcileRoleForApplicationSourceNamespaces(workloadIdentifier, expectedRules, a)
+	assert.NoError(t, err)
+
+	expectedName := getRoleNameForApplicationSourceNamespaces(sourceNamespace, a)
+	reconciledRole := &v1.Role{}
+
+	// check if roles are created for the new namespace
+	assert.NoError(t, r.Client.Get(context.TODO(), types.NamespacedName{Name: expectedName, Namespace: sourceNamespace}, reconciledRole))
+	assert.Equal(t, expectedRules, reconciledRole.Rules)
+
+}
+
 func TestReconcileArgoCD_RoleHooks(t *testing.T) {
 	defer resetHooks()()
 	a := makeTestArgoCD()
diff --git a/controllers/argocd/rolebinding_test.go b/controllers/argocd/rolebinding_test.go
index 27877aa2..89a5d376 100644
--- a/controllers/argocd/rolebinding_test.go
+++ b/controllers/argocd/rolebinding_test.go
@@ -12,6 +12,7 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 
+	"github.com/argoproj-labs/argocd-operator/api/v1alpha1"
 	"github.com/argoproj-labs/argocd-operator/common"
 )
 
@@ -197,3 +198,29 @@ func TestReconcileArgoCD_reconcileRoleBinding_custom_role(t *testing.T) {
 	expectedName = fmt.Sprintf("%s-%s", a.Name, "argocd-server")
 	checkForUpdatedRoleRef(t, "custom-server-role", expectedName)
 }
+
+func TestReconcileArgoCD_reconcileRoleBinding_forSourceNamespaces(t *testing.T) {
+	logf.SetLogger(ZapLogger(true))
+	sourceNamespace := "newNamespaceTest"
+	a := makeTestArgoCD()
+	a.Spec = v1alpha1.ArgoCDSpec{
+		SourceNamespaces: []string{
+			sourceNamespace,
+		},
+	}
+	r := makeTestReconciler(t, a)
+	p := policyRuleForApplicationController()
+
+	assert.NoError(t, createNamespace(r, a.Namespace, ""))
+	assert.NoError(t, createNamespaceManagedByClusterArgoCDLabel(r, sourceNamespace, a.Namespace))
+
+	workloadIdentifier := common.ArgoCDServerComponent
+
+	assert.NoError(t, r.reconcileRoleBinding(workloadIdentifier, p, a))
+
+	roleBinding := &rbacv1.RoleBinding{}
+	expectedName := getRoleBindingNameForSourceNamespaces(a.Name, a.Namespace, sourceNamespace)
+
+	assert.NoError(t, r.Client.Get(context.TODO(), types.NamespacedName{Name: expectedName, Namespace: sourceNamespace}, roleBinding))
+
+}
diff --git a/controllers/argocd/testing.go b/controllers/argocd/testing.go
index 5aa258f3..49ef7748 100644
--- a/controllers/argocd/testing.go
+++ b/controllers/argocd/testing.go
@@ -292,6 +292,20 @@ func createNamespace(r *ReconcileArgoCD, n string, managedBy string) error {
 	return r.Client.Create(context.TODO(), ns)
 }
 
+func createNamespaceManagedByClusterArgoCDLabel(r *ReconcileArgoCD, n string, managedBy string) error {
+	ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: n}}
+	if managedBy != "" {
+		ns.Labels = map[string]string{common.ArgoCDManagedByClusterArgoCDLabel: managedBy}
+	}
+
+	if r.ManagedSourceNamespaces == nil {
+		r.ManagedSourceNamespaces = make(map[string]string)
+	}
+	r.ManagedSourceNamespaces[ns.Name] = ""
+
+	return r.Client.Create(context.TODO(), ns)
+}
+
 func merge(base map[string]string, diff map[string]string) map[string]string {
 	result := make(map[string]string)
 
diff --git a/controllers/argocd/util_test.go b/controllers/argocd/util_test.go
index 107bdff5..4ac28f61 100644
--- a/controllers/argocd/util_test.go
+++ b/controllers/argocd/util_test.go
@@ -606,6 +606,34 @@ func TestSetManagedNamespaces(t *testing.T) {
 	}
 }
 
+func TestSetManagedSourceNamespaces(t *testing.T) {
+	a := makeTestArgoCD()
+	a.Spec = v1alpha1.ArgoCDSpec{
+		SourceNamespaces: []string{
+			"test-namespace-1",
+		},
+	}
+	nsList := &v1.NamespaceList{
+		Items: []v1.Namespace{
+			{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "test-namespace-1",
+					Labels: map[string]string{
+						common.ArgoCDManagedByClusterArgoCDLabel: testNamespace,
+					},
+				},
+			},
+		},
+	}
+	r := makeTestReconciler(t, nsList)
+
+	err := r.setManagedSourceNamespaces(a)
+	assert.NoError(t, err)
+
+	assert.Equal(t, 1, len(r.ManagedSourceNamespaces))
+	assert.Contains(t, r.ManagedSourceNamespaces, "test-namespace-1")
+}
+
 func TestGenerateRandomString(t *testing.T) {
 
 	// verify the creation of unique strings
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/01-argocd-with-source-namespaces.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/01-argocd-with-source-namespaces.yaml
new file mode 100644
index 00000000..b890b7dc
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/01-argocd-with-source-namespaces.yaml
@@ -0,0 +1,25 @@
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: central-argocd
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: test-1-24-custom
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: test-2-24-custom
+---
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+  namespace: central-argocd
+spec:
+  sourceNamespaces:
+  - test-1-24-custom
+  - test-2-24-custom
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/01-assert.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/01-assert.yaml
new file mode 100644
index 00000000..dd0c9c3f
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/01-assert.yaml
@@ -0,0 +1,54 @@
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  labels:
+    argocd.argoproj.io/managed-by-cluster-argocd: central-argocd
+    kubernetes.io/metadata.name: test-1-24-custom
+  name: test-1-24-custom
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: example-argocd_test-1-24-custom_argocd-server
+  namespace: test-1-24-custom
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: example-argocd_test-1-24-custom
+  namespace: test-1-24-custom
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: example-argocd_test-1-24-custom_argocd-server
+subjects:
+- kind: ServiceAccount
+  name: example-argocd-argocd-server
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  labels:
+    argocd.argoproj.io/managed-by-cluster-argocd: central-argocd
+    kubernetes.io/metadata.name: test-2-24-custom
+  name: test-2-24-custom
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: example-argocd_test-2-24-custom_argocd-server
+  namespace: test-2-24-custom
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: example-argocd_test-2-24-custom
+  namespace: test-2-24-custom
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: example-argocd_test-2-24-custom_argocd-server
+subjects:
+- kind: ServiceAccount
+  name: example-argocd-argocd-server
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/02-assert.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/02-assert.yaml
new file mode 100644
index 00000000..aca6c501
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/02-assert.yaml
@@ -0,0 +1,7 @@
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  labels:
+    kubernetes.io/metadata.name: test-1-24-custom
+  name: test-1-24-custom
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/02-change-source-namespaces.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/02-change-source-namespaces.yaml
new file mode 100644
index 00000000..0817778f
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/02-change-source-namespaces.yaml
@@ -0,0 +1,8 @@
+apiVersion: argoproj.io/v1alpha1
+kind: ArgoCD
+metadata:
+  name: example-argocd
+  namespace: central-argocd
+spec:
+  sourceNamespaces:
+  - test-2-24-custom
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/02-errors.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/02-errors.yaml
new file mode 100644
index 00000000..7333a07f
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/02-errors.yaml
@@ -0,0 +1,19 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: example-argocd_test-1-24-custom_argocd-server
+  namespace: test-1-24-custom
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: example-argocd_test-1-24-custom
+  namespace: test-1-24-custom
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: example-argocd_test-1-24-custom_argocd-server
+subjects:
+- kind: ServiceAccount
+  name: example-argocd-argocd-server
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/03-assert.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/03-assert.yaml
new file mode 100644
index 00000000..d5460cc7
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/03-assert.yaml
@@ -0,0 +1,7 @@
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  labels:
+    kubernetes.io/metadata.name: test-2-24-custom
+  name: test-2-24-custom
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/03-delete-argocd.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/03-delete-argocd.yaml
new file mode 100644
index 00000000..8f02301d
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/03-delete-argocd.yaml
@@ -0,0 +1,11 @@
+---
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+delete:
+- apiVersion: argoproj.io/v1alpha1
+  kind: ArgoCD
+  name: example-argocd
+  namespace: central-argocd
+commands:
+  # Sleep to allow resources to be completely deleted
+  - command: sleep 30s
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/03-errors.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/03-errors.yaml
new file mode 100644
index 00000000..03c7b977
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/03-errors.yaml
@@ -0,0 +1,19 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: example-argocd_test-2-24-custom_argocd-server
+  namespace: test-2-24-custom
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: example-argocd_test-2-24-custom
+  namespace: test-2-24-custom
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: example-argocd_test-2-24-custom_argocd-server
+subjects:
+- kind: ServiceAccount
+  name: example-argocd-argocd-server
\ No newline at end of file
diff --git a/tests/k8s/1-024_validate_apps_in_any_namespace/99-delete.yaml b/tests/k8s/1-024_validate_apps_in_any_namespace/99-delete.yaml
new file mode 100644
index 00000000..0d87c937
--- /dev/null
+++ b/tests/k8s/1-024_validate_apps_in_any_namespace/99-delete.yaml
@@ -0,0 +1,15 @@
+---
+apiVersion: kuttl.dev/v1beta1
+kind: TestStep
+delete:
+- apiVersion: v1
+  kind: Namespace
+  name: test-1-24-custom
+- apiVersion: v1
+  kind: Namespace
+  name: test-2-24-custom
+- apiVersion: v1
+  kind: Namespace
+  name: central-argocd
+commands:
+  - command: sleep 30s
\ No newline at end of file