Repository: argoproj-labs/applicationset
Pull request #20 (2020-08-19 21:42:08)

Reorg manifests & create kustomizations
Follows the naming & directory hierarchy used by [Argo CD](https://github.com/argoproj/argo-cd/tree/master/manifests). Also adds get/list/watch of secrets and applications.

Signed-off-by: Michael Goodness <michael.goodness@mlb.com>


Patch:
diff --git a/main.go b/main.go
index 615d745..919ce1c 100644
--- a/main.go
+++ b/main.go
@@ -44,12 +44,12 @@ func main() {
 	ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
 
 	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
-		Scheme:             scheme,
-		MetricsBindAddress: metricsAddr,
+		Scheme:                 scheme,
+		MetricsBindAddress:     metricsAddr,
 		HealthProbeBindAddress: probeBindAddr,
-		Port:               9443,
-		LeaderElection:     enableLeaderElection,
-		LeaderElectionID:   "58ac56fa.",
+		Port:                   9443,
+		LeaderElection:         enableLeaderElection,
+		LeaderElectionID:       "58ac56fa.",
 	})
 	if err != nil {
 		setupLog.Error(err, "unable to start manager")
@@ -57,8 +57,8 @@ func main() {
 	}
 
 	if err = (&controllers.ApplicationSetReconciler{
-		Client: mgr.GetClient(),
-		Scheme: mgr.GetScheme(),
+		Client:   mgr.GetClient(),
+		Scheme:   mgr.GetScheme(),
 		Recorder: mgr.GetEventRecorderFor("applicationset-controller"),
 	}).SetupWithManager(mgr); err != nil {
 		setupLog.Error(err, "unable to create controller", "controller", "ApplicationSet")
diff --git a/manifests/base/deployment.yaml b/manifests/base/deployment.yaml
index 1c4bbe2..b1cd8a7 100644
--- a/manifests/base/deployment.yaml
+++ b/manifests/base/deployment.yaml
@@ -3,8 +3,8 @@ kind: Deployment
 metadata:
   labels:
     app.kubernetes.io/name: argocd-applicationset-controller
-    app.kubernetes.io/part-of: argocd
-    app.kubernetes.io/component: applicationset-controller
+    app.kubernetes.io/part-of: argocd-applicationset
+    app.kubernetes.io/component: controller
   name: argocd-applicationset-controller
 spec:
   selector:
@@ -21,4 +21,4 @@ spec:
           image: registry.cn-hangzhou.aliyuncs.com/appcenter/argocd-applicationset:v0.1.0
           imagePullPolicy: Always
           name: argocd-applicationset-controller
-      serviceAccountName: default
+      serviceAccountName: argocd-applicationset-controller
diff --git a/manifests/base/kustomization.yaml b/manifests/base/kustomization.yaml
new file mode 100644
index 0000000..869f7ae
--- /dev/null
+++ b/manifests/base/kustomization.yaml
@@ -0,0 +1,6 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+  - deployment.yaml
+  - rbac.yaml
diff --git a/manifests/base/rbac.yaml b/manifests/base/rbac.yaml
new file mode 100644
index 0000000..c47e563
--- /dev/null
+++ b/manifests/base/rbac.yaml
@@ -0,0 +1,95 @@
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app.kubernetes.io/name: argocd-applicationset-controller
+    app.kubernetes.io/part-of: argocd-applicationset
+    app.kubernetes.io/component: controller
+  name: argocd-applicationset-controller
+
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  labels:
+    app.kubernetes.io/name: argocd-applicationset-controller
+    app.kubernetes.io/part-of: argocd-applicationset
+    app.kubernetes.io/component: controller
+  name: argocd-applicationset-controller
+rules:
+  - apiGroups:
+      - argoproj.io
+    resources:
+      - applications
+    verbs:
+      - get
+      - list
+      - watch
+  - apiGroups:
+      - argoproj.io
+    resources:
+      - applicationsets
+    verbs:
+      - create
+      - delete
+      - get
+      - list
+      - patch
+      - update
+      - watch
+  - apiGroups:
+      - argoproj.io
+    resources:
+      - applicationsets/status
+    verbs:
+      - get
+      - patch
+      - update
+  - apiGroups:
+      - ''
+    resources:
+      - events
+      - pods
+    verbs:
+      - create
+      - delete
+      - get
+      - list
+      - patch
+      - update
+      - watch
+  - apiGroups:
+      - ''
+    resources:
+      - secrets
+    verbs:
+      - get
+      - list
+      - watch
+  - apiGroups:
+      - apps
+      - extensions
+    resources:
+      - deployments
+    verbs:
+      - get
+      - list
+      - watch
+
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  labels:
+    app.kubernetes.io/name: argocd-applicationset-controller
+    app.kubernetes.io/part-of: argocd-applicationset
+    app.kubernetes.io/component: controller
+  name: argocd-applicationset-controller
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: argocd-applicationset-controller
+subjects:
+  - kind: ServiceAccount
+    name: argocd-applicationset-controller
diff --git a/manifests/cluster-install/kustomization.yaml b/manifests/cluster-install/kustomization.yaml
new file mode 100644
index 0000000..55f0aea
--- /dev/null
+++ b/manifests/cluster-install/kustomization.yaml
@@ -0,0 +1,6 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+  - ../namespace-install
+  - ../cluster-rbac
diff --git a/manifests/cluster-rbac/kustomization.yaml b/manifests/cluster-rbac/kustomization.yaml
new file mode 100644
index 0000000..4c4dbe4
--- /dev/null
+++ b/manifests/cluster-rbac/kustomization.yaml
@@ -0,0 +1,5 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+  - rbac.yaml
diff --git a/manifests/cluster-rbac/rbac.yaml b/manifests/cluster-rbac/rbac.yaml
new file mode 100644
index 0000000..00159df
--- /dev/null
+++ b/manifests/cluster-rbac/rbac.yaml
@@ -0,0 +1,68 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  labels:
+    app.kubernetes.io/name: argocd-applicationset-controller
+    app.kubernetes.io/part-of: argocd-applicationset
+    app.kubernetes.io/component: controller
+  name: argocd-applicationset-controller
+rules:
+  - apiGroups:
+      - argoproj.io
+    resources:
+      - applications
+    verbs:
+      - get
+      - list
+      - watch
+  - apiGroups:
+      - argoproj.io
+    resources:
+      - applicationsets
+    verbs:
+      - create
+      - delete
+      - get
+      - list
+      - patch
+      - update
+      - watch
+  - apiGroups:
+      - argoproj.io
+    resources:
+      - applicationsets/status
+    verbs:
+      - get
+      - patch
+      - update
+  - apiGroups:
+      - ''
+    resources:
+      - events
+      - pods
+    verbs:
+      - create
+      - delete
+      - get
+      - list
+      - patch
+      - update
+      - watch
+
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  labels:
+    app.kubernetes.io/name: argocd-applicationset-controller
+    app.kubernetes.io/part-of: argocd-applicationset
+    app.kubernetes.io/component: controller
+  name: argocd-applicationset-controller
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: argocd-applicationset-controller
+subjects:
+  - kind: ServiceAccount
+    name: argocd-applicationset-controller
diff --git a/manifests/crds/argoproj.io_applicationsets.yaml b/manifests/crds/applicationset-crd.yaml
similarity index 72%
rename from manifests/crds/argoproj.io_applicationsets.yaml
rename to manifests/crds/applicationset-crd.yaml
index 67b6456..eed0966 100644
--- a/manifests/crds/argoproj.io_applicationsets.yaml
+++ b/manifests/crds/applicationset-crd.yaml
@@ -1,9 +1,10 @@
-
 ---
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
-  creationTimestamp: null
+  labels:
+    app.kubernetes.io/name: applicationsets.argoproj.io
+    app.kubernetes.io/part-of: argocd-applicationset
   name: applicationsets.argoproj.io
 spec:
   group: argoproj.io
@@ -18,12 +19,14 @@ spec:
       description: ApplicationSet is a set of Application resources
       properties:
         apiVersion:
-          description: 'APIVersion defines the versioned schema of this representation
+          description:
+            'APIVersion defines the versioned schema of this representation
             of an object. Servers should convert recognized schemas to the latest
             internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
           type: string
         kind:
-          description: 'Kind is a string value representing the REST resource this
+          description:
+            'Kind is a string value representing the REST resource this
             object represents. Servers may infer this from the endpoint the client
             submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
           type: string
@@ -37,34 +40,41 @@ spec:
                 description: ApplicationSetGenerator include list item info
                 properties:
                   clusters:
-                    description: ClusterGenerator defines a generator to match against
+                    description:
+                      ClusterGenerator defines a generator to match against
                       clusters registered with ArgoCD.
                     properties:
                       selector:
-                        description: Selector defines a label selector to match against
+                        description:
+                          Selector defines a label selector to match against
                           all clusters registered with ArgoCD. Clusters today are
                           stored as Kubernetes Secrets, thus the Secret labels will
                           be used for matching the selector.
                         properties:
                           matchExpressions:
-                            description: matchExpressions is a list of label selector
+                            description:
+                              matchExpressions is a list of label selector
                               requirements. The requirements are ANDed.
                             items:
-                              description: A label selector requirement is a selector
+                              description:
+                                A label selector requirement is a selector
                                 that contains values, a key, and an operator that
                                 relates the key and values.
                               properties:
                                 key:
-                                  description: key is the label key that the selector
+                                  description:
+                                    key is the label key that the selector
                                     applies to.
                                   type: string
                                 operator:
-                                  description: operator represents a key's relationship
+                                  description:
+                                    operator represents a key's relationship
                                     to a set of values. Valid operators are In, NotIn,
                                     Exists and DoesNotExist.
                                   type: string
                                 values:
-                                  description: values is an array of string values.
+                                  description:
+                                    values is an array of string values.
                                     If the operator is In or NotIn, the values array
                                     must be non-empty. If the operator is Exists or
                                     DoesNotExist, the values array must be empty.
@@ -74,14 +84,15 @@ spec:
                                     type: string
                                   type: array
                               required:
-                              - key
-                              - operator
+                                - key
+                                - operator
                               type: object
                             type: array
                           matchLabels:
                             additionalProperties:
                               type: string
-                            description: matchLabels is a map of {key,value} pairs.
+                            description:
+                              matchLabels is a map of {key,value} pairs.
                               A single {key,value} in the matchLabels map is equivalent
                               to an element of matchExpressions, whose key field is
                               "key", the operator is "In", and the values array contains
@@ -97,13 +108,13 @@ spec:
                             path:
                               type: string
                           required:
-                          - path
+                            - path
                           type: object
                         type: array
                       repoURL:
                         type: string
                     required:
-                    - repoURL
+                      - repoURL
                     type: object
                   list:
                     description: ListGenerator include items info
@@ -117,30 +128,34 @@ spec:
                             url:
                               type: string
                           required:
-                          - cluster
-                          - url
+                            - cluster
+                            - url
                           type: object
                         type: array
                     required:
-                    - elements
+                      - elements
                     type: object
                 type: object
               type: array
             syncPolicy:
-              description: ApplicationSetSyncPolicy will provide a syncPolicy similar
+              description:
+                ApplicationSetSyncPolicy will provide a syncPolicy similar
                 to Applications
               properties:
                 automated:
-                  description: Automated will keep an application synced to the target
+                  description:
+                    Automated will keep an application synced to the target
                     revision
                   properties:
                     initial:
-                      description: Initial will perform an initial sync for any newly
+                      description:
+                        Initial will perform an initial sync for any newly
                         created Applications which do not have automated sync turned
                         on.
                       type: boolean
                     prune:
-                      description: 'Prune will prune resources automatically as part
+                      description:
+                        'Prune will prune resources automatically as part
                         of automated sync (default: false)'
                       type: boolean
                   type: object
@@ -151,28 +166,34 @@ spec:
                 metadata:
                   type: object
                 spec:
-                  description: ApplicationSpec represents desired application state.
+                  description:
+                    ApplicationSpec represents desired application state.
                     Contains link to repository with application definition and additional
                     parameters link definition revision.
                   properties:
                     destination:
-                      description: Destination overrides the kubernetes server and
+                      description:
+                        Destination overrides the kubernetes server and
                         namespace defined in the environment ksonnet app.yaml
                       properties:
                         namespace:
-                          description: Namespace overrides the environment namespace
+                          description:
+                            Namespace overrides the environment namespace
                             value in the ksonnet app.yaml
                           type: string
                         server:
-                          description: Server overrides the environment server value
+                          description:
+                            Server overrides the environment server value
                             in the ksonnet app.yaml
                           type: string
                       type: object
                     ignoreDifferences:
-                      description: IgnoreDifferences controls resources fields which
+                      description:
+                        IgnoreDifferences controls resources fields which
                         should be ignored during comparison
                       items:
-                        description: ResourceIgnoreDifferences contains resource filter
+                        description:
+                          ResourceIgnoreDifferences contains resource filter
                           and list of json paths which should be ignored during comparison
                           with live state.
                         properties:
@@ -189,12 +210,13 @@ spec:
                           namespace:
                             type: string
                         required:
-                        - jsonPointers
-                        - kind
+                          - jsonPointers
+                          - kind
                         type: object
                       type: array
                     info:
-                      description: Infos contains a list of useful information (URLs,
+                      description:
+                        Infos contains a list of useful information (URLs,
                         email addresses, and plain text) that relates to the application
                       items:
                         properties:
@@ -203,16 +225,18 @@ spec:
                           value:
                             type: string
                         required:
-                        - name
-                        - value
+                          - name
+                          - value
                         type: object
                       type: array
                     project:
-                      description: Project is a application project name. Empty name
+                      description:
+                        Project is a application project name. Empty name
                         means that application belongs to 'default' project.
                       type: string
                     revisionHistoryLimit:
-                      description: This limits this number of items kept in the apps
+                      description:
+                        This limits this number of items kept in the apps
                         revision history. This should only be changed in exceptional
                         circumstances. Setting to zero will store no history. This
                         will reduce storage used. Increasing will increase the space
@@ -221,7 +245,8 @@ spec:
                       format: int64
                       type: integer
                     source:
-                      description: Source is a reference to the location ksonnet application
+                      description:
+                        Source is a reference to the location ksonnet application
                         definition
                       properties:
                         chart:
@@ -231,11 +256,13 @@ spec:
                           description: Directory holds path/directory specific options
                           properties:
                             jsonnet:
-                              description: ApplicationSourceJsonnet holds jsonnet
+                              description:
+                                ApplicationSourceJsonnet holds jsonnet
                                 specific options
                               properties:
                                 extVars:
-                                  description: ExtVars is a list of Jsonnet External
+                                  description:
+                                    ExtVars is a list of Jsonnet External
                                     Variables
                                   items:
                                     description: JsonnetVar is a jsonnet variable
@@ -247,12 +274,13 @@ spec:
                                       value:
                                         type: string
                                     required:
-                                    - name
-                                    - value
+                                      - name
+                                      - value
                                     type: object
                                   type: array
                                 tlas:
-                                  description: TLAS is a list of Jsonnet Top-level
+                                  description:
+                                    TLAS is a list of Jsonnet Top-level
                                     Arguments
                                   items:
                                     description: JsonnetVar is a jsonnet variable
@@ -264,8 +292,8 @@ spec:
                                       value:
                                         type: string
                                     required:
-                                    - name
-                                    - value
+                                      - name
+                                      - value
                                     type: object
                                   type: array
                               type: object
@@ -276,17 +304,20 @@ spec:
                           description: Helm holds helm specific options
                           properties:
                             fileParameters:
-                              description: FileParameters are file parameters to the
+                              description:
+                                FileParameters are file parameters to the
                                 helm template
                               items:
-                                description: HelmFileParameter is a file parameter
+                                description:
+                                  HelmFileParameter is a file parameter
                                   to a helm template
                                 properties:
                                   name:
                                     description: Name is the name of the helm parameter
                                     type: string
                                   path:
-                                    description: Path is the path value for the helm
+                                    description:
+                                      Path is the path value for the helm
                                       parameter
                                     type: string
                                 type: object
@@ -294,11 +325,13 @@ spec:
                             parameters:
                               description: Parameters are parameters to the helm template
                               items:
-                                description: HelmParameter is a parameter to a helm
+                                description:
+                                  HelmParameter is a parameter to a helm
                                   template
                                 properties:
                                   forceString:
-                                    description: ForceString determines whether to
+                                    description:
+                                      ForceString determines whether to
                                       tell Helm to interpret booleans and numbers
                                       as strings
                                     type: boolean
@@ -311,17 +344,20 @@ spec:
                                 type: object
                               type: array
                             releaseName:
-                              description: The Helm release name. If omitted it will
+                              description:
+                                The Helm release name. If omitted it will
                                 use the application name
                               type: string
                             valueFiles:
-                              description: ValuesFiles is a list of Helm value files
+                              description:
+                                ValuesFiles is a list of Helm value files
                                 to use when generating a template
                               items:
                                 type: string
                               type: array
                             values:
-                              description: Values is Helm values, typically defined
+                              description:
+                                Values is Helm values, typically defined
                                 as a block
                               type: string
                           type: object
@@ -329,14 +365,17 @@ spec:
                           description: Ksonnet holds ksonnet specific options
                           properties:
                             environment:
-                              description: Environment is a ksonnet application environment
+                              description:
+                                Environment is a ksonnet application environment
                                 name
                               type: string
                             parameters:
-                              description: Parameters are a list of ksonnet component
+                              description:
+                                Parameters are a list of ksonnet component
                                 parameter override values
                               items:
-                                description: KsonnetParameter is a ksonnet component
+                                description:
+                                  KsonnetParameter is a ksonnet component
                                   parameter
                                 properties:
                                   component:
@@ -346,8 +385,8 @@ spec:
                                   value:
                                     type: string
                                 required:
-                                - name
-                                - value
+                                  - name
+                                  - value
                                 type: object
                               type: array
                           type: object
@@ -357,7 +396,8 @@ spec:
                             commonLabels:
                               additionalProperties:
                                 type: string
-                              description: CommonLabels adds additional kustomize
+                              description:
+                                CommonLabels adds additional kustomize
                                 commonLabels
                               type: object
                             images:
@@ -366,11 +406,13 @@ spec:
                                 type: string
                               type: array
                             namePrefix:
-                              description: NamePrefix is a prefix appended to resources
+                              description:
+                                NamePrefix is a prefix appended to resources
                                 for kustomize apps
                               type: string
                             nameSuffix:
-                              description: NameSuffix is a suffix appended to resources
+                              description:
+                                NameSuffix is a suffix appended to resources
                                 for kustomize apps
                               type: string
                             version:
@@ -381,7 +423,8 @@ spec:
                           description: Path is a directory path within the Git repository
                           type: string
                         plugin:
-                          description: ConfigManagementPlugin holds config management
+                          description:
+                            ConfigManagementPlugin holds config management
                             plugin specific options
                           properties:
                             env:
@@ -394,38 +437,43 @@ spec:
                                     description: the value
                                     type: string
                                 required:
-                                - name
-                                - value
+                                  - name
+                                  - value
                                 type: object
                               type: array
                             name:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the repository URL of the application
+                          description:
+                            RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
-                          description: TargetRevision defines the commit, tag, or
+                          description:
+                            TargetRevision defines the commit, tag, or
                             branch in which to sync the application to. If omitted,
                             will sync to HEAD
                           type: string
                       required:
-                      - repoURL
+                        - repoURL
                       type: object
                     syncPolicy:
                       description: SyncPolicy controls when a sync will be performed
                       properties:
                         automated:
-                          description: Automated will keep an application synced to
+                          description:
+                            Automated will keep an application synced to
                             the target revision
                           properties:
                             prune:
-                              description: 'Prune will prune resources automatically
+                              description:
+                                'Prune will prune resources automatically
                                 as part of automated sync (default: false)'
                               type: boolean
                             selfHeal:
-                              description: 'SelfHeal enables auto-syncing if  (default:
+                              description:
+                                'SelfHeal enables auto-syncing if  (default:
                                 false)'
                               type: boolean
                           type: object
@@ -436,30 +484,24 @@ spec:
                           type: array
                       type: object
                   required:
-                  - destination
-                  - project
-                  - source
+                    - destination
+                    - project
+                    - source
                   type: object
               required:
-              - metadata
-              - spec
+                - metadata
+                - spec
               type: object
           required:
-          - generators
-          - template
+            - generators
+            - template
           type: object
       required:
-      - metadata
-      - spec
+        - metadata
+        - spec
       type: object
   version: v1alpha1
   versions:
-  - name: v1alpha1
-    served: true
-    storage: true
-status:
-  acceptedNames:
-    kind: ""
-    plural: ""
-  conditions: []
-  storedVersions: []
+    - name: v1alpha1
+      served: true
+      storage: true
diff --git a/manifests/crds/kustomization.yaml b/manifests/crds/kustomization.yaml
new file mode 100644
index 0000000..e658daf
--- /dev/null
+++ b/manifests/crds/kustomization.yaml
@@ -0,0 +1,5 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+  - applicationset-crd.yaml
diff --git a/manifests/namespace-install/kustomization.yaml b/manifests/namespace-install/kustomization.yaml
new file mode 100644
index 0000000..82a46a0
--- /dev/null
+++ b/manifests/namespace-install/kustomization.yaml
@@ -0,0 +1,6 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+  - ../base
+  - ../crds
diff --git a/manifests/rbac/rbac.yaml b/manifests/rbac/rbac.yaml
deleted file mode 100644
index 6479eb2..0000000
--- a/manifests/rbac/rbac.yaml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
-  name: argo-cd-applicationset-role
-rules:
-- apiGroups:
-  - argoproj.io
-  resources:
-  - applicationsets
-  verbs:
-  - create
-  - delete
-  - get
-  - list
-  - patch
-  - update
-  - watch
-- apiGroups:
-  - argoproj.io
-  resources:
-  - applicationsets/status
-  verbs:
-  - get
-  - patch
-  - update
-- apiGroups:
-  - ""
-  resources:
-  - events
-  - pods
-  verbs:
-  - create
-  - delete
-  - get
-  - list
-  - patch
-  - update
-  - watch
-- apiGroups:
-  - apps
-  - extensions
-  resources:
-  - deployments
-  verbs:
-  - get
-  - list
-  - watch
-
----
-
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
-  name: argo-cd-applicationset-rolebinding
-roleRef:
-  apiGroup: rbac.authorization.k8s.io
-  kind: ClusterRole
-  name: argo-cd-applicationset-role
-subjects:
-- kind: ServiceAccount
-  name: default
-  namespace: default
\ No newline at end of file
diff --git a/pkg/controllers/clustereventhandler.go b/pkg/controllers/clustereventhandler.go
index 2935c5f..9b1460d 100644
--- a/pkg/controllers/clustereventhandler.go
+++ b/pkg/controllers/clustereventhandler.go
@@ -73,5 +73,3 @@ func (h *clusterSecretEventHandler) queueRelatedAppGenerators(q workqueue.RateLi
 		}
 	}
 }
-
-
diff --git a/pkg/generators/cluster.go b/pkg/generators/cluster.go
index 3ab77b7..a6edee4 100644
--- a/pkg/generators/cluster.go
+++ b/pkg/generators/cluster.go
@@ -9,8 +9,9 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
-	argov1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
 	argoprojiov1alpha1 "github.com/argoproj-labs/applicationset/api/v1alpha1"
+	"github.com/argoproj-labs/applicationset/pkg/utils"
+	argov1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
 )
 
 const (
@@ -56,9 +57,28 @@ func (g *ClusterGenerator) GenerateApplications(
 	}
 	log.Debug("clusters matching labels", "count", len(clusterSecretList.Items))
 
+	var tmplApplication argov1alpha1.Application
+	tmplApplication.Namespace = appSet.Spec.Template.Namespace
+	tmplApplication.Name = appSet.Spec.Template.Name
+	tmplApplication.Spec = appSet.Spec.Template.Spec
+
+	var resultingApplications []argov1alpha1.Application
+
 	for _, cluster := range clusterSecretList.Items {
+		params := make(map[string]string)
+		params["name"] = cluster.Name
+		params["server"] = string(cluster.Data["server"])
+		for key, value := range cluster.ObjectMeta.Labels {
+			params[fmt.Sprintf("metadata.labels.%s", key)] = value
+		}
 		log.WithField("cluster", cluster.Name).Info("matched cluster secret")
+		tmpApplication, err := utils.RenderTemplateParams(&tmplApplication, params)
+		if err != nil {
+			log.WithField("cluster", cluster.Name).Error("Error during rendering template params")
+			continue
+		}
+		resultingApplications = append(resultingApplications, *tmpApplication)
 	}
 
-	return nil, nil
+	return resultingApplications, nil
 }
diff --git a/pkg/utils/constants.go b/pkg/utils/constants.go
index 129519b..2ab8c49 100644
--- a/pkg/utils/constants.go
+++ b/pkg/utils/constants.go
@@ -2,5 +2,5 @@ package utils
 
 const (
 	ClusterListGeneratorKeyName = "cluster"
-	UrlGeneratorKeyName = "url"
+	UrlGeneratorKeyName         = "url"
 )


Test patch:
diff --git a/pkg/generators/cluster_test.go b/pkg/generators/cluster_test.go
new file mode 100644
index 0000000..e36e82d
--- /dev/null
+++ b/pkg/generators/cluster_test.go
@@ -0,0 +1,193 @@
+package generators
+
+import (
+	"context"
+	"encoding/base64"
+	"errors"
+	"fmt"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/kubernetes/scheme"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
+	argoprojiov1alpha1 "github.com/argoproj-labs/applicationset/api/v1alpha1"
+	argov1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
+
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+type possiblyErroringFakeCtrlRuntimeClient struct {
+	client.Client
+	shouldError bool
+}
+
+func (p *possiblyErroringFakeCtrlRuntimeClient) List(ctx context.Context, secretList runtime.Object, opts ...client.ListOption) error {
+	if p.shouldError {
+		return errors.New("Could not list Secrets.")
+	}
+	return p.Client.List(ctx, secretList, opts...)
+}
+
+func getRenderTemplate(appName, clusterName, server, environmentLabel string) *argov1alpha1.Application {
+	return &argov1alpha1.Application{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      fmt.Sprintf("%s-%s", clusterName, appName),
+			Namespace: "namespace",
+			Finalizers: []string{
+				"resources-finalizer.argocd.argoproj.io",
+			},
+		},
+		Spec: argov1alpha1.ApplicationSpec{
+			Source: argov1alpha1.ApplicationSource{
+				RepoURL:        "RepoURL",
+				Path:           fmt.Sprintf("%s/%s", appName, environmentLabel),
+				TargetRevision: "HEAD",
+			},
+			Destination: argov1alpha1.ApplicationDestination{
+				Server:    server,
+				Namespace: "destinationNamespace",
+			},
+			Project: "project",
+		},
+	}
+}
+
+func TestGenerateApplications(t *testing.T) {
+	clusters := []runtime.Object{
+		&corev1.Secret{
+			TypeMeta: metav1.TypeMeta{
+				Kind:       "Secret",
+				APIVersion: "v1",
+			},
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "staging-01",
+				Namespace: "namespace",
+				Labels: map[string]string{
+					"argocd.argoproj.io/secret-type": "cluster",
+					"environment":                    "staging",
+				},
+			},
+			Data: map[string][]byte{
+				"config": []byte(base64.StdEncoding.EncodeToString([]byte("foo"))),
+				"name":   []byte(base64.StdEncoding.EncodeToString([]byte("staging-01"))),
+				"server": []byte("https://staging-01.example.com"),
+			},
+			Type: corev1.SecretType("Opaque"),
+		},
+		&corev1.Secret{
+			TypeMeta: metav1.TypeMeta{
+				Kind:       "Secret",
+				APIVersion: "v1",
+			},
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "production-01",
+				Namespace: "namespace",
+				Labels: map[string]string{
+					"argocd.argoproj.io/secret-type": "cluster",
+					"environment":                    "production",
+				},
+			},
+			Data: map[string][]byte{
+				"config": []byte(base64.StdEncoding.EncodeToString([]byte("foo"))),
+				"name":   []byte(base64.StdEncoding.EncodeToString([]byte("productuion-01"))),
+				"server": []byte("https://production-01.example.com"),
+			},
+			Type: corev1.SecretType("Opaque"),
+		},
+	}
+
+	applicationSetTemplate := argoprojiov1alpha1.ApplicationSetTemplate{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "{{name}}-app",
+			Namespace: "namespace",
+		},
+		Spec: argov1alpha1.ApplicationSpec{
+			Source: argov1alpha1.ApplicationSource{
+				RepoURL:        "RepoURL",
+				Path:           "app/{{metadata.labels.environment}}",
+				TargetRevision: "HEAD",
+			},
+			Destination: argov1alpha1.ApplicationDestination{
+				Server:    "{{server}}",
+				Namespace: "destinationNamespace",
+			},
+			Project: "project",
+		},
+	}
+
+	testCases := []struct {
+		template      argoprojiov1alpha1.ApplicationSetTemplate
+		selector      metav1.LabelSelector
+		expected      []argov1alpha1.Application
+		clientError   bool
+		expectedError error
+	}{
+		{
+			applicationSetTemplate,
+			metav1.LabelSelector{},
+			[]argov1alpha1.Application{
+				*getRenderTemplate("app", "staging-01", "https://staging-01.example.com", "staging"),
+				*getRenderTemplate("app", "production-01", "https://production-01.example.com", "production"),
+			},
+			false,
+			nil,
+		},
+		{
+			applicationSetTemplate,
+			metav1.LabelSelector{
+				MatchLabels: map[string]string{
+					"environment": "production",
+				},
+			},
+			[]argov1alpha1.Application{
+				*getRenderTemplate("app", "production-01", "https://production-01.example.com", "production"),
+			},
+			false,
+			nil,
+		},
+		{
+			applicationSetTemplate,
+			metav1.LabelSelector{},
+			nil,
+			true,
+			errors.New("Could not list Secrets."),
+		},
+	}
+
+	for _, testCase := range testCases {
+		fakeClient := fake.NewFakeClientWithScheme(scheme.Scheme, clusters...)
+		cl := &possiblyErroringFakeCtrlRuntimeClient{
+			fakeClient,
+			testCase.clientError,
+		}
+
+		var clusterGenerator = NewClusterGenerator(cl)
+		applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: "set",
+			},
+			Spec: argoprojiov1alpha1.ApplicationSetSpec{
+				Generators: []argoprojiov1alpha1.ApplicationSetGenerator{{
+					Clusters: &argoprojiov1alpha1.ClusterGenerator{
+						Selector: testCase.selector,
+					},
+				}},
+				Template: testCase.template,
+			},
+		}
+
+		got, err := clusterGenerator.GenerateApplications(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
+
+		if testCase.expectedError != nil {
+			assert.Error(t, testCase.expectedError, err)
+		} else {
+			assert.NoError(t, err)
+			assert.Equal(t, testCase.expected, got)
+		}
+
+	}
+}