Skip to content

Commit

Permalink
more tests and e2e tests
Browse files Browse the repository at this point in the history
Signed-off-by: Atif Ali <atali@redhat.com>
  • Loading branch information
aali309 committed Jan 15, 2025
1 parent beb0b26 commit dce3dc8
Show file tree
Hide file tree
Showing 10 changed files with 371 additions and 16 deletions.
20 changes: 17 additions & 3 deletions controllers/argocd/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package argocd

import (
"context"
"encoding/json"
"fmt"
"reflect"

Expand Down Expand Up @@ -379,15 +380,28 @@ func (r *ReconcileArgoCD) reconcileCAConfigMap(cr *argoproj.ArgoCD) error {
// reconcileConfiguration will ensure that the main ConfigMap for ArgoCD is present.
func (r *ReconcileArgoCD) reconcileArgoConfigMap(cr *argoproj.ArgoCD) error {
cm := newConfigMapWithName(common.ArgoCDConfigMapName, cr)

cm.Data = make(map[string]string)
cm.Data = setRespectRBAC(cr, cm.Data)
cm.Data[common.ArgoCDKeyApplicationInstanceLabelKey] = getApplicationInstanceLabelKey(cr)

// Set tracking method if specified
if cr.Spec.ResourceTrackingMethod != "" {
cm.Data["resource.tracking.method"] = string(cr.Spec.ResourceTrackingMethod)
}

// Set tracking annotations and handle installationID
if cr.Spec.ApplicationTrackingAnnotations != nil {
for k, v := range cr.Spec.ApplicationTrackingAnnotations {
cm.Data[k] = v
// Set installationID if present
if id, ok := cr.Spec.ApplicationTrackingAnnotations["installationID"]; ok {
cm.Data["installationID"] = id
}

// Set all tracking annotations
trackingAnnotations, err := json.Marshal(cr.Spec.ApplicationTrackingAnnotations)
if err != nil {
return err
}
cm.Data["resource.tracking.annotations"] = string(trackingAnnotations)
}

cm.Data[common.ArgoCDKeyConfigManagementPlugins] = getConfigManagementPlugins(cr)
Expand Down
151 changes: 138 additions & 13 deletions controllers/argocd/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package argocd

import (
"context"
"encoding/json"
"fmt"
"reflect"
"testing"
Expand Down Expand Up @@ -1187,11 +1188,10 @@ func TestReconcileArgoCD_reconcileArgoConfigMap_withApplicationTrackingAnnotatio
assert.NoError(t, err)

// Check initial annotations
for k, v := range initialAnnotations {
if c := cm.Data[k]; c != v {
t.Fatalf("reconcileArgoConfigMap failed got %q, want %q", c, v)
}
}
var actualAnnotations map[string]string
err = json.Unmarshal([]byte(cm.Data["resource.tracking.annotations"]), &actualAnnotations)
assert.NoError(t, err)
assert.Equal(t, initialAnnotations, actualAnnotations)

// Test updating annotations
a.Spec.ApplicationTrackingAnnotations = updatedAnnotations
Expand All @@ -1205,11 +1205,9 @@ func TestReconcileArgoCD_reconcileArgoConfigMap_withApplicationTrackingAnnotatio
assert.NoError(t, err)

// Check updated annotations
for k, v := range updatedAnnotations {
if c := cm.Data[k]; c != v {
t.Fatalf("reconcileArgoConfigMap failed got %q, want %q", c, v)
}
}
err = json.Unmarshal([]byte(cm.Data["resource.tracking.annotations"]), &actualAnnotations)
assert.NoError(t, err)
assert.Equal(t, updatedAnnotations, actualAnnotations)
}

func TestReconcileArgoCD_reconcileArgoConfigMap_withMultipleInstances(t *testing.T) {
Expand Down Expand Up @@ -1250,7 +1248,11 @@ func TestReconcileArgoCD_reconcileArgoConfigMap_withMultipleInstances(t *testing
Namespace: testNamespace,
}, cm1)
assert.NoError(t, err)
assert.Equal(t, "instance-1", cm1.Data["installationID"])

var actualAnnotations1 map[string]string
err = json.Unmarshal([]byte(cm1.Data["resource.tracking.annotations"]), &actualAnnotations1)
assert.NoError(t, err)
assert.Equal(t, "instance-1", actualAnnotations1["installationID"])

// Test second instance
err = r.reconcileArgoConfigMap(argocd2)
Expand All @@ -1262,7 +1264,130 @@ func TestReconcileArgoCD_reconcileArgoConfigMap_withMultipleInstances(t *testing
Namespace: testNamespace,
}, cm2)
assert.NoError(t, err)
assert.Equal(t, "instance-2", cm2.Data["installationID"])

assert.NotEqual(t, cm1.Data["installationID"], cm2.Data["installationID"])
var actualAnnotations2 map[string]string
err = json.Unmarshal([]byte(cm2.Data["resource.tracking.annotations"]), &actualAnnotations2)
assert.NoError(t, err)
assert.Equal(t, "instance-2", actualAnnotations2["installationID"])
}

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

// Test with nil annotations
a := makeTestArgoCD(func(a *argoproj.ArgoCD) {
a.Spec.ApplicationTrackingAnnotations = nil
})

resObjs := []client.Object{a}
subresObjs := []client.Object{a}
runtimeObjs := []runtime.Object{}
sch := makeTestReconcilerScheme(argoproj.AddToScheme)
cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
r := makeTestReconciler(cl, sch)

err := r.reconcileArgoConfigMap(a)
assert.NoError(t, err)

cm := &corev1.ConfigMap{}
err = r.Client.Get(context.TODO(), types.NamespacedName{
Name: common.ArgoCDConfigMapName,
Namespace: testNamespace,
}, cm)
assert.NoError(t, err)

// Verify default behavior without annotations
assert.NotContains(t, cm.Data, "resource.tracking.annotations")
}

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

// Start with annotations
initialAnnotations := map[string]string{
"installationID": "test-id",
"customKey": "value",
}

a := makeTestArgoCD(func(a *argoproj.ArgoCD) {
a.Spec.ApplicationTrackingAnnotations = initialAnnotations
})

resObjs := []client.Object{a}
subresObjs := []client.Object{a}
runtimeObjs := []runtime.Object{}
sch := makeTestReconcilerScheme(argoproj.AddToScheme)
cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
r := makeTestReconciler(cl, sch)

// First create with annotations
err := r.reconcileArgoConfigMap(a)
assert.NoError(t, err)

// Remove annotations
a.Spec.ApplicationTrackingAnnotations = nil
err = r.reconcileArgoConfigMap(a)
assert.NoError(t, err)

cm := &corev1.ConfigMap{}
err = r.Client.Get(context.TODO(), types.NamespacedName{
Name: common.ArgoCDConfigMapName,
Namespace: testNamespace,
}, cm)
assert.NoError(t, err)

// Verify annotations were removed
assert.NotContains(t, cm.Data, "resource.tracking.annotations")
}

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

// Test multiple annotation types
annotations := map[string]string{
"installationID": "test-id",
"environment": "production",
"team": "platform",
"empty": "", // Test empty value
}

// Create single ArgoCD instance
argocd := makeTestArgoCD(func(a *argoproj.ArgoCD) {
a.Name = "argocd"
a.Namespace = testNamespace
a.Spec.ApplicationTrackingAnnotations = annotations
a.Spec.ResourceTrackingMethod = "annotation"
})

resObjs := []client.Object{argocd}
subresObjs := []client.Object{argocd}
runtimeObjs := []runtime.Object{}
sch := makeTestReconcilerScheme(argoproj.AddToScheme)
cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
r := makeTestReconciler(cl, sch)

// When
err := r.reconcileArgoConfigMap(argocd)
assert.NoError(t, err)

// Then
cm := &corev1.ConfigMap{}
err = r.Client.Get(context.TODO(), types.NamespacedName{
Name: common.ArgoCDConfigMapName,
Namespace: testNamespace,
}, cm)
assert.NoError(t, err)

// Verify annotations are set correctly in the ConfigMap
var actualAnnotations map[string]string
err = json.Unmarshal([]byte(cm.Data["resource.tracking.annotations"]), &actualAnnotations)
assert.NoError(t, err)
assert.Equal(t, annotations, actualAnnotations)
assert.Equal(t, "annotation", cm.Data["resource.tracking.method"])

// Verify each annotation individually
for key, expectedValue := range annotations {
assert.Equal(t, expectedValue, actualAnnotations[key],
"Annotation %s should have value %s", key, expectedValue)
}
}
25 changes: 25 additions & 0 deletions controllers/argocd/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package argocd

import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -1361,6 +1362,30 @@ func (r *ReconcileArgoCD) reconcileRepoDeployment(cr *argoproj.ArgoCD, useTLSFor
func (r *ReconcileArgoCD) reconcileServerDeployment(cr *argoproj.ArgoCD, useTLSForRedis bool) error {
deploy := newDeploymentWithSuffix("server", "server", cr)
serverEnv := cr.Spec.Server.Env

// Add tracking method if specified
if cr.Spec.ResourceTrackingMethod != "" {
trackingMethod := argoproj.ParseResourceTrackingMethod(cr.Spec.ResourceTrackingMethod)
if trackingMethod != argoproj.ResourceTrackingMethodInvalid {
serverEnv = append(serverEnv, corev1.EnvVar{
Name: "ARGOCD_RESOURCE_TRACKING_METHOD",
Value: trackingMethod.String(),
})
}
}

// Add tracking annotations if specified
if len(cr.Spec.ApplicationTrackingAnnotations) > 0 {
trackingAnnotations, err := json.Marshal(cr.Spec.ApplicationTrackingAnnotations)
if err != nil {
return fmt.Errorf("failed to marshal tracking annotations: %w", err)
}
serverEnv = append(serverEnv, corev1.EnvVar{
Name: "ARGOCD_RESOURCE_TRACKING_ANNOTATIONS",
Value: string(trackingAnnotations),
})
}

serverEnv = append(serverEnv, corev1.EnvVar{
Name: "REDIS_PASSWORD",
ValueFrom: &corev1.EnvVarSource{
Expand Down
76 changes: 76 additions & 0 deletions tests/k8s/1-046_validate_application_tracking/01-install.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
apiVersion: v1
kind: Namespace
metadata:
name: test-1-046-application-tracking
---
apiVersion: v1
kind: Namespace
metadata:
name: guestbook
labels:
argocd.argoproj.io/managed-by: argocd-1
---
apiVersion: v1
kind: Namespace
metadata:
name: guestbook-second
labels:
argocd.argoproj.io/managed-by: argocd-2
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-application-controller-test
rules:
- apiGroups:
- apps
- ""
- argoproj.io
resources:
- deployments
- services
- namespaces
- applications
- replicasets
- pods
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argocd-application-controller-test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-application-controller-test
subjects:
- kind: ServiceAccount
name: argocd-application-controller
namespace: test-1-046-application-tracking
---
apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
name: argocd-1
namespace: test-1-046-application-tracking
spec:
resourceTrackingMethod: annotation
applicationTrackingAnnotations:
installationID: "instance-1"
---
apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
name: argocd-2
namespace: test-1-046-application-tracking
spec:
resourceTrackingMethod: annotation
applicationTrackingAnnotations:
installationID: "instance-2"
19 changes: 19 additions & 0 deletions tests/k8s/1-046_validate_application_tracking/02-assert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Check first ArgoCD instance configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-1-cm
namespace: test-1-046-application-tracking
data:
resource.tracking.method: "annotation"
resource.tracking.annotations: '{"installationID":"instance-1"}'
---
# Check second ArgoCD instance configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-2-cm
namespace: test-1-046-application-tracking
data:
resource.tracking.method: "annotation"
resource.tracking.annotations: '{"installationID":"instance-2"}'
15 changes: 15 additions & 0 deletions tests/k8s/1-046_validate_application_tracking/02-wait.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
name: argocd-1
namespace: test-1-046-application-tracking
status:
phase: Available
---
apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
name: argocd-2
namespace: test-1-046-application-tracking
status:
phase: Available
18 changes: 18 additions & 0 deletions tests/k8s/1-046_validate_application_tracking/03-install.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Create first application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: same-app-name
namespace: test-1-046-application-tracking
labels:
argocd.argoproj.io/instance: argocd-1
argocd.argoproj.io/managed-by: argocd-1
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps.git
path: guestbook
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: guestbook
Loading

0 comments on commit dce3dc8

Please sign in to comment.