Skip to content

Commit

Permalink
Merge branch 'argoproj-labs:master' into Set_execTimeoutRepo_branch
Browse files Browse the repository at this point in the history
  • Loading branch information
sarfarazgit authored Feb 4, 2025
2 parents 283c9c0 + 8210187 commit 5afcc05
Show file tree
Hide file tree
Showing 8 changed files with 507 additions and 93 deletions.
47 changes: 30 additions & 17 deletions controllers/argocd/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -834,43 +834,56 @@ func (r *ReconcileArgoCD) reconcileRedisHAProxyDeployment(cr *argoproj.ArgoCD) e
changed = true
}
updateNodePlacement(existing, deploy, &changed, &explanation)

if !reflect.DeepEqual(deploy.Spec.Template.Spec.Containers[0].Resources, existing.Spec.Template.Spec.Containers[0].Resources) {
existing.Spec.Template.Spec.Containers[0].Resources = deploy.Spec.Template.Spec.Containers[0].Resources
if !reflect.DeepEqual(deploy.Spec.Template.Spec.Volumes, existing.Spec.Template.Spec.Volumes) {
existing.Spec.Template.Spec.Volumes = deploy.Spec.Template.Spec.Volumes
if changed {
explanation += ", "
}
explanation += "container resources"
explanation += "volumes"
changed = true
}

if !reflect.DeepEqual(deploy.Spec.Template.Spec.Containers[0].SecurityContext, existing.Spec.Template.Spec.Containers[0].SecurityContext) {
existing.Spec.Template.Spec.Containers[0].SecurityContext = deploy.Spec.Template.Spec.Containers[0].SecurityContext
if !reflect.DeepEqual(deploy.Spec.Template.Spec.Containers[0].VolumeMounts,
existing.Spec.Template.Spec.Containers[0].VolumeMounts) {
existing.Spec.Template.Spec.Containers[0].VolumeMounts = deploy.Spec.Template.Spec.Containers[0].VolumeMounts
if changed {
explanation += ", "
}
explanation += "container security context"
explanation += "container volume mounts"
changed = true
}

if !reflect.DeepEqual(deploy.Spec.Template.Spec.InitContainers[0].Resources, existing.Spec.Template.Spec.InitContainers[0].Resources) {
existing.Spec.Template.Spec.InitContainers[0].Resources = deploy.Spec.Template.Spec.InitContainers[0].Resources
if !reflect.DeepEqual(deploy.Spec.Template.Spec.InitContainers, existing.Spec.Template.Spec.InitContainers) {
existing.Spec.Template.Spec.InitContainers = deploy.Spec.Template.Spec.InitContainers
if changed {
explanation += ", "
}
explanation += "init container resources"
explanation += "init containers"
changed = true
}

if !reflect.DeepEqual(deploy.Spec.Template.Spec.InitContainers[0].SecurityContext, existing.Spec.Template.Spec.InitContainers[0].SecurityContext) {
existing.Spec.Template.Spec.InitContainers[0].SecurityContext = deploy.Spec.Template.Spec.InitContainers[0].SecurityContext
if !reflect.DeepEqual(deploy.Spec.Template.Spec.Containers[0].Env,
existing.Spec.Template.Spec.Containers[0].Env) {
existing.Spec.Template.Spec.Containers[0].Env = deploy.Spec.Template.Spec.Containers[0].Env
if changed {
explanation += ", "
}
explanation += "init container security context"
explanation += "container env"
changed = true
}
if !reflect.DeepEqual(deploy.Spec.Template.Spec.Containers[0].Resources, existing.Spec.Template.Spec.Containers[0].Resources) {
existing.Spec.Template.Spec.Containers[0].Resources = deploy.Spec.Template.Spec.Containers[0].Resources
if changed {
explanation += ", "
}
explanation += "container resources"
changed = true
}
if !reflect.DeepEqual(deploy.Spec.Template.Spec.Containers[0].SecurityContext, existing.Spec.Template.Spec.Containers[0].SecurityContext) {
existing.Spec.Template.Spec.Containers[0].SecurityContext = deploy.Spec.Template.Spec.Containers[0].SecurityContext
if changed {
explanation += ", "
}
explanation += "container security context"
changed = true
}

if changed {
argoutil.LogResourceUpdate(log, existing, "updating", explanation)
return r.Client.Update(context.TODO(), existing)
Expand Down
112 changes: 112 additions & 0 deletions controllers/argocd/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,118 @@ func TestReconcileArgoCD_reconcileDeployments_HA_proxy_with_resources(t *testing
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Resources, newResources)
assert.Equal(t, deployment.Spec.Template.Spec.InitContainers[0].Resources, newResources)
}
func TestReconcileArgoCD_reconcileRedisHAProxyDeployment_ModifyContainerSpec(t *testing.T) {
logf.SetLogger(ZapLogger(true))

a := makeTestArgoCD(func(a *argoproj.ArgoCD) {
a.Spec.HA.Enabled = true
})

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)

assert.NoError(t, r.reconcileRedisHAProxyDeployment(a))

deployment := &appsv1.Deployment{}
assert.NoError(t, r.Client.Get(
context.TODO(),
types.NamespacedName{
Name: "argocd-redis-ha-haproxy",
Namespace: a.Namespace,
},
deployment))

// Modify the deployment container environment variables
deployment.Spec.Template.Spec.Containers[0].Env = append(deployment.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
Name: "TEST_ENV",
Value: "test",
})

assert.NoError(t, r.Client.Update(context.TODO(), deployment))

// Reconcile again
assert.NoError(t, r.reconcileRedisHAProxyDeployment(a))

// Check if the environment variable changes were reverted
assert.NoError(t, r.Client.Get(
context.TODO(),
types.NamespacedName{
Name: "argocd-redis-ha-haproxy",
Namespace: a.Namespace,
},
deployment))

assert.NotContains(t, deployment.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
Name: "TEST_ENV",
Value: "test",
})

// Modify the deployment initcontainer environment variables
deployment.Spec.Template.Spec.InitContainers[0].Env = append(deployment.Spec.Template.Spec.InitContainers[0].Env, corev1.EnvVar{
Name: "TEST_ENV",
Value: "test",
})

assert.NoError(t, r.Client.Update(context.TODO(), deployment))

// Reconcile again
assert.NoError(t, r.reconcileRedisHAProxyDeployment(a))

// Check if the environment variable changes were reverted
assert.NoError(t, r.Client.Get(
context.TODO(),
types.NamespacedName{
Name: "argocd-redis-ha-haproxy",
Namespace: a.Namespace,
},
deployment))

assert.NotContains(t, deployment.Spec.Template.Spec.InitContainers[0].Env, corev1.EnvVar{
Name: "TEST_ENV",
Value: "test",
})

// Modify the deployment volumes
deployment.Spec.Template.Spec.Volumes = append(deployment.Spec.Template.Spec.Volumes, corev1.Volume{
Name: "test-volume",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
})
deployment.Spec.Template.Spec.Containers[0].VolumeMounts = append(deployment.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
Name: "test-volume",
MountPath: "/test",
})

assert.NoError(t, r.Client.Update(context.TODO(), deployment))

// Reconcile again
assert.NoError(t, r.reconcileRedisHAProxyDeployment(a))

// Check if the volume changes were reverted
assert.NoError(t, r.Client.Get(
context.TODO(),
types.NamespacedName{
Name: "argocd-redis-ha-haproxy",
Namespace: a.Namespace,
},
deployment))

assert.NotContains(t, deployment.Spec.Template.Spec.Volumes, corev1.Volume{
Name: "test-volume",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
})
assert.NotContains(t, deployment.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
Name: "test-volume",
MountPath: "/test",
})
}

func TestReconcileArgoCD_reconcileRepoDeployment_updatesVolumeMounts(t *testing.T) {
logf.SetLogger(ZapLogger(true))
Expand Down
147 changes: 108 additions & 39 deletions controllers/argocd/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,23 +391,14 @@ func (r *ReconcileArgoCD) reconcileGrafanaSecret(cr *argoproj.ArgoCD) error {
return nil
}

// reconcileClusterPermissionsSecret ensures ArgoCD instance is namespace-scoped
func (r *ReconcileArgoCD) reconcileClusterPermissionsSecret(cr *argoproj.ArgoCD) error {
var clusterConfigInstance bool
secret := argoutil.NewSecretWithSuffix(cr, "default-cluster-config")
secret.Labels[common.ArgoCDSecretTypeLabel] = "cluster"
dataBytes, _ := json.Marshal(map[string]interface{}{
"tlsClientConfig": map[string]interface{}{
"insecure": false,
},
})

// generateSortedManagedNamespaceListForArgoCDCR return a list of namespaces with 'managed-by' label that are managed by this 'cr', and including the namespace containing 'cr'
func generateSortedManagedNamespaceListForArgoCDCR(cr *argoproj.ArgoCD, rClient client.Client) ([]string, error) {
namespaceList := corev1.NamespaceList{}
listOption := client.MatchingLabels{
common.ArgoCDManagedByLabel: cr.Namespace,
}
if err := r.Client.List(context.TODO(), &namespaceList, listOption); err != nil {
return err
if err := rClient.List(context.TODO(), &namespaceList, listOption); err != nil {
return nil, err
}

var namespaces []string
Expand All @@ -419,54 +410,132 @@ func (r *ReconcileArgoCD) reconcileClusterPermissionsSecret(cr *argoproj.ArgoCD)
namespaces = append(namespaces, cr.Namespace)
}
sort.Strings(namespaces)
return namespaces, nil
}

secret.Data = map[string][]byte{
"config": dataBytes,
"name": []byte("in-cluster"),
"server": []byte(common.ArgoCDDefaultServer),
"namespaces": []byte(strings.Join(namespaces, ",")),
// combineClusterSecretNamespacesWithManagedNamespaces will combine the contents of clusterSecret's .data.namespaces value, with the list of namespaces in 'managedNamespaceList', sorting them and removing duplicates.
func combineClusterSecretNamespacesWithManagedNamespaces(clusterSecret corev1.Secret, managedNamespaceList []string) string {
namespacesToManageMap := map[string]string{}

for _, managedNamespace := range managedNamespaceList {
namespacesToManageMap[managedNamespace] = managedNamespace
}

clusterSecretNamespaces := strings.Split(string(clusterSecret.Data["namespaces"]), ",")
for _, clusterSecretNS := range clusterSecretNamespaces {
ns := strings.TrimSpace(clusterSecretNS)
namespacesToManageMap[ns] = ns
}

namespacesToManageList := []string{}
for namespaceToManage := range namespacesToManageMap {
namespacesToManageList = append(namespacesToManageList, namespaceToManage)
}
sort.Strings(namespacesToManageList)

namespacesToManageString := strings.Join(namespacesToManageList, ",")

return namespacesToManageString

}

// reconcileClusterPermissionsSecret ensures ArgoCD instance is namespace-scoped
func (r *ReconcileArgoCD) reconcileClusterPermissionsSecret(cr *argoproj.ArgoCD) error {

managedNamespaceList, err := generateSortedManagedNamespaceListForArgoCDCR(cr, r.Client)
if err != nil {
return err
}

// isArgoCDAClusterConfigInstance indicates whether 'cr' is a cluster config instance (mentioned in ARGOCD_CLUSTER_CONFIG_NAMESPACES)
var isArgoCDAClusterConfigInstance bool

if allowedNamespace(cr.Namespace, os.Getenv("ARGOCD_CLUSTER_CONFIG_NAMESPACES")) {
clusterConfigInstance = true
isArgoCDAClusterConfigInstance = true
}

// Get all existing cluster secrets in the namespace
clusterSecrets, err := r.getClusterSecrets(cr)
if err != nil {
return err
}

for _, s := range clusterSecrets.Items {
// Find the cluster secret in the list that points to common.ArgoCDDefaultServer (default server address)
var localClusterSecret *corev1.Secret
for x, clusterSecret := range clusterSecrets.Items {

// check if cluster secret with default server address exists
if string(s.Data["server"]) == common.ArgoCDDefaultServer {
// if the cluster belongs to cluster config namespace,
// remove all namespaces from cluster secret,
// else update the list of namespaces if value differs.
var explanation string
if clusterConfigInstance {
delete(s.Data, "namespaces")
if string(clusterSecret.Data["server"]) == common.ArgoCDDefaultServer {
localClusterSecret = &clusterSecrets.Items[x]
}
}

if localClusterSecret != nil {

// If the default Cluster Secret already exists

secretUpdateRequired := false

// if the cluster belongs to cluster config namespace,
// remove all namespaces from cluster secret,
// else update the list of namespaces if value differs.
var explanation string
if isArgoCDAClusterConfigInstance {

if _, exists := localClusterSecret.Data["namespaces"]; exists {
delete(localClusterSecret.Data, "namespaces")
explanation = "removing namespaces from cluster secret"
} else {
ns := strings.Split(string(s.Data["namespaces"]), ",")
for _, n := range namespaces {
if !containsString(ns, strings.TrimSpace(n)) {
ns = append(ns, strings.TrimSpace(n))
}
}
sort.Strings(ns)
s.Data["namespaces"] = []byte(strings.Join(ns, ","))
secretUpdateRequired = true
}

} else {

namespacesToManageString := combineClusterSecretNamespacesWithManagedNamespaces(*localClusterSecret, managedNamespaceList)

var existingNamespacesValue string
if localClusterSecret.Data["namespaces"] != nil {
existingNamespacesValue = string(localClusterSecret.Data["namespaces"])
}

if existingNamespacesValue != namespacesToManageString {
localClusterSecret.Data["namespaces"] = []byte(namespacesToManageString)
explanation = "updating namespaces in cluster secret"
secretUpdateRequired = true
}
argoutil.LogResourceUpdate(log, &s, explanation)
return r.Client.Update(context.TODO(), &s)
}

if secretUpdateRequired {
// We found the Secret, and the field needs to be updated
argoutil.LogResourceUpdate(log, localClusterSecret, explanation)
return r.Client.Update(context.TODO(), localClusterSecret)
}

// We found the Secret, but the field hasn't changed: no update needed.
return nil
}

if clusterConfigInstance {
// If ArgoCD is configured as a cluster-scoped, no need to create a Namespace containing managed namespaces
if isArgoCDAClusterConfigInstance {
// do nothing
return nil
}

// Create the Secret, since we could not find it above
secret := argoutil.NewSecretWithSuffix(cr, "default-cluster-config")
secret.Labels[common.ArgoCDSecretTypeLabel] = "cluster"
dataBytes, _ := json.Marshal(map[string]interface{}{
"tlsClientConfig": map[string]interface{}{
"insecure": false,
},
})

secret.Data = map[string][]byte{
"config": dataBytes,
"name": []byte("in-cluster"),
"server": []byte(common.ArgoCDDefaultServer),
"namespaces": []byte(strings.Join(managedNamespaceList, ",")),
}

if err := controllerutil.SetControllerReference(cr, secret, r.Scheme); err != nil {
return err
}
Expand Down
Loading

0 comments on commit 5afcc05

Please sign in to comment.