diff --git a/applicationset/controllers/applicationset_controller_test.go b/applicationset/controllers/applicationset_controller_test.go index 480222b8dd1f2..8d057bcc0e3c9 100644 --- a/applicationset/controllers/applicationset_controller_test.go +++ b/applicationset/controllers/applicationset_controller_test.go @@ -41,6 +41,39 @@ import ( "github.com/argoproj/argo-cd/v2/util/settings" ) +// getDefaultTestClientSet creates a Clientset with the default argo objects +// To add new objects, use kubeclientset.Tracker().Add(obj) +func getDefaultTestClientSet() *kubefake.Clientset { + argoCDSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: argocommon.ArgoCDSecretName, + Namespace: "argocd", + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string][]byte{ + "admin.password": nil, + "server.secretkey": nil, + }, + } + + emptyArgoCDConfigMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: argocommon.ArgoCDConfigMapName, + Namespace: "argocd", + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string]string{}, + } + + objects := append([]runtime.Object{}, emptyArgoCDConfigMap, argoCDSecret) + kubeclientset := kubefake.NewSimpleClientset(objects...) + return kubeclientset +} + func TestCreateOrUpdateInCluster(t *testing.T) { scheme := runtime.NewScheme() err := v1alpha1.AddToScheme(scheme) @@ -1320,8 +1353,10 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) { }, } - objects := append([]runtime.Object{}, secret) - kubeclientset := kubefake.NewSimpleClientset(objects...) + kubeclientset := getDefaultTestClientSet() + err := kubeclientset.Tracker().Add(secret) + require.NoError(t, err) + metrics := appsetmetrics.NewFakeAppsetMetrics(client) argodb := db.NewDB("argocd", settings.NewSettingsManager(context.TODO(), kubeclientset, "argocd"), kubeclientset) @@ -2057,8 +2092,9 @@ func TestValidateGeneratedApplications(t *testing.T) { }, } - objects := append([]runtime.Object{}, secret) - kubeclientset := kubefake.NewSimpleClientset(objects...) + kubeclientset := getDefaultTestClientSet() + err := kubeclientset.Tracker().Add(secret) + require.NoError(t, err) argodb := db.NewDB("argocd", settings.NewSettingsManager(context.TODO(), kubeclientset, "argocd"), kubeclientset) @@ -2120,7 +2156,7 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) { }, } - kubeclientset := kubefake.NewSimpleClientset() + kubeclientset := getDefaultTestClientSet() client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &project).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) @@ -2407,8 +2443,9 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp }, } - objects := append([]runtime.Object{}, secret) - kubeclientset := kubefake.NewSimpleClientset(objects...) + kubeclientset := getDefaultTestClientSet() + err = kubeclientset.Tracker().Add(secret) + require.NoError(t, err) client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) @@ -2583,8 +2620,9 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp }, } - objects := append([]runtime.Object{}, secret) - kubeclientset := kubefake.NewSimpleClientset(objects...) + kubeclientset := getDefaultTestClientSet() + err = kubeclientset.Tracker().Add(secret) + require.NoError(t, err) client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build() metrics := appsetmetrics.NewFakeAppsetMetrics(client) @@ -2703,7 +2741,7 @@ func TestPolicies(t *testing.T) { Spec: v1alpha1.AppProjectSpec{SourceRepos: []string{"*"}, Destinations: []v1alpha1.ApplicationDestination{{Namespace: "*", Server: "https://kubernetes.default.svc"}}}, } - kubeclientset := kubefake.NewSimpleClientset() + kubeclientset := getDefaultTestClientSet() for _, c := range []struct { name string diff --git a/test/e2e/app_management_test.go b/test/e2e/app_management_test.go index 31137af8d54a1..7722bacefab7a 100644 --- a/test/e2e/app_management_test.go +++ b/test/e2e/app_management_test.go @@ -703,6 +703,28 @@ func TestComparisonFailsIfClusterNotAdded(t *testing.T) { Expect(DoesNotExist()) } +func TestComparisonFailsIfInClusterDisabled(t *testing.T) { + Given(t). + Path(guestbookPath). + DestServer(KubernetesInternalAPIServerAddr). + When(). + CreateApp(). + Refresh(RefreshTypeNormal). + Sync(). + Then(). + Expect(Success("")). + Expect(HealthIs(health.HealthStatusHealthy)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + When(). + SetParamInSettingConfigMap("cluster.inClusterEnabled", "false"). + Refresh(RefreshTypeNormal). + Then(). + Expect(Success("")). + Expect(HealthIs(health.HealthStatusUnknown)). + Expect(SyncStatusIs(SyncStatusCodeUnknown)). + Expect(Condition(ApplicationConditionInvalidSpecError, fmt.Sprintf("cluster %q is disabled", KubernetesInternalAPIServerAddr))) +} + func TestCannotSetInvalidPath(t *testing.T) { Given(t). Path(guestbookPath). @@ -1117,15 +1139,15 @@ definitions: end return _copy(object) end - + job = {} job.apiVersion = "batch/v1" job.kind = "Job" - + job.metadata = {} job.metadata.name = obj.metadata.name .. "-123" job.metadata.namespace = obj.metadata.namespace - + ownerRef = {} ownerRef.apiVersion = obj.apiVersion ownerRef.kind = obj.kind @@ -1133,18 +1155,18 @@ definitions: ownerRef.uid = obj.metadata.uid job.metadata.ownerReferences = {} job.metadata.ownerReferences[1] = ownerRef - + job.spec = {} job.spec.suspend = false job.spec.template = {} job.spec.template.spec = deepCopy(obj.spec.jobTemplate.spec.template.spec) - + impactedResource = {} impactedResource.operation = "create" impactedResource.resource = job result = {} result[1] = impactedResource - + return result` func TestNewStyleResourceActionPermitted(t *testing.T) { @@ -1221,15 +1243,15 @@ definitions: end return _copy(object) end - + job = {} job.apiVersion = "batch/v1" job.kind = "Job" - + job.metadata = {} job.metadata.name = obj.metadata.name .. "-123" job.metadata.namespace = obj.metadata.namespace - + ownerRef = {} ownerRef.apiVersion = obj.apiVersion ownerRef.kind = obj.kind @@ -1237,12 +1259,12 @@ definitions: ownerRef.uid = obj.metadata.uid job.metadata.ownerReferences = {} job.metadata.ownerReferences[1] = ownerRef - + job.spec = {} job.spec.suspend = false job.spec.template = {} job.spec.template.spec = deepCopy(obj.spec.jobTemplate.spec.template.spec) - + impactedResource1 = {} impactedResource1.operation = "create" impactedResource1.resource = job @@ -1255,7 +1277,7 @@ definitions: impactedResource2.resource = obj result[2] = impactedResource2 - + return result` func TestNewStyleResourceActionMixedOk(t *testing.T) { @@ -2160,6 +2182,19 @@ func TestCreateAppWithNoNameSpaceWhenRequired2(t *testing.T) { }) } +func TestCreateAppWithInClusterDisabled(t *testing.T) { + Given(t). + Path(guestbookPath). + DestServer(KubernetesInternalAPIServerAddr). + When(). + SetParamInSettingConfigMap("cluster.inClusterEnabled", "false"). + IgnoreErrors(). + CreateApp(). + Then(). + // RPC error messages are quoted: time="2024-12-18T04:13:58Z" level=fatal msg="" + Expect(Error("", fmt.Sprintf(`cluster \"%s\" is disabled`, KubernetesInternalAPIServerAddr))) +} + func TestListResource(t *testing.T) { SkipOnEnv(t, "OPENSHIFT") Given(t). diff --git a/test/e2e/fixture/app/expectation.go b/test/e2e/fixture/app/expectation.go index 9e66f2d6b711b..5b46cca5c2b1e 100644 --- a/test/e2e/fixture/app/expectation.go +++ b/test/e2e/fixture/app/expectation.go @@ -372,7 +372,7 @@ func Error(message, err string, matchers ...func(string, string) bool) Expectati return failed, fmt.Sprintf("output does not contain '%s'", message) } if !match(c.actions.lastError.Error(), err) { - return failed, fmt.Sprintf("error does not contain '%s'", message) + return failed, fmt.Sprintf("error does not contain '%s'", err) } return succeeded, fmt.Sprintf("error '%s'", message) } diff --git a/util/db/cluster.go b/util/db/cluster.go index a76432ad1707a..5254cf2413d14 100644 --- a/util/db/cluster.go +++ b/util/db/cluster.go @@ -142,11 +142,19 @@ func (db *db) WatchClusters(ctx context.Context, handleModEvent func(oldCluster *appv1.Cluster, newCluster *appv1.Cluster), handleDeleteEvent func(clusterServer string), ) error { - localCls, err := db.GetCluster(ctx, appv1.KubernetesInternalAPIServerAddr) + argoSettings, err := db.settingsMgr.GetSettings() if err != nil { return err } - handleAddEvent(localCls) + + localCls := db.getLocalCluster() + if argoSettings.InClusterEnabled { + localCls, err = db.GetCluster(ctx, appv1.KubernetesInternalAPIServerAddr) + if err != nil { + return err + } + handleAddEvent(localCls) + } db.watchSecrets( ctx, @@ -159,9 +167,11 @@ func (db *db) WatchClusters(ctx context.Context, return } if cluster.Server == appv1.KubernetesInternalAPIServerAddr { - // change local cluster event to modified or deleted, since it cannot be re-added or deleted - handleModEvent(localCls, cluster) - localCls = cluster + if argoSettings.InClusterEnabled { + // change local cluster event to modified, since it cannot be added at runtime + handleModEvent(localCls, cluster) + localCls = cluster + } return } handleAddEvent(cluster) @@ -185,10 +195,11 @@ func (db *db) WatchClusters(ctx context.Context, }, func(secret *corev1.Secret) { - if string(secret.Data["server"]) == appv1.KubernetesInternalAPIServerAddr { - // change local cluster event to modified or deleted, since it cannot be re-added or deleted - handleModEvent(localCls, db.getLocalCluster()) - localCls = db.getLocalCluster() + if string(secret.Data["server"]) == appv1.KubernetesInternalAPIServerAddr && argoSettings.InClusterEnabled { + // change local cluster event to modified, since it cannot be deleted at runtime, unless disabled. + newLocalCls := db.getLocalCluster() + handleModEvent(localCls, newLocalCls) + localCls = newLocalCls } else { handleDeleteEvent(string(secret.Data["server"])) } @@ -214,6 +225,14 @@ func (db *db) getClusterSecret(server string) (*corev1.Secret, error) { // GetCluster returns a cluster from a query func (db *db) GetCluster(_ context.Context, server string) (*appv1.Cluster, error) { + argoSettings, err := db.settingsMgr.GetSettings() + if err != nil { + return nil, err + } + if server == appv1.KubernetesInternalAPIServerAddr && !argoSettings.InClusterEnabled { + return nil, status.Errorf(codes.NotFound, "cluster %q is disabled", server) + } + informer, err := db.settingsMgr.GetSecretsInformer() if err != nil { return nil, err @@ -222,6 +241,7 @@ func (db *db) GetCluster(_ context.Context, server string) (*appv1.Cluster, erro if err != nil { return nil, err } + if len(res) > 0 { return SecretToCluster(res[0].(*corev1.Secret)) } @@ -254,6 +274,10 @@ func (db *db) GetProjectClusters(ctx context.Context, project string) ([]*appv1. } func (db *db) GetClusterServersByName(ctx context.Context, name string) ([]string, error) { + argoSettings, err := db.settingsMgr.GetSettings() + if err != nil { + return nil, err + } informer, err := db.settingsMgr.GetSecretsInformer() if err != nil { return nil, err @@ -265,7 +289,7 @@ func (db *db) GetClusterServersByName(ctx context.Context, name string) ([]strin return nil, err } - if len(localClusterSecrets) == 0 && db.getLocalCluster().Name == name { + if len(localClusterSecrets) == 0 && db.getLocalCluster().Name == name && argoSettings.InClusterEnabled { return []string{appv1.KubernetesInternalAPIServerAddr}, nil } @@ -276,7 +300,11 @@ func (db *db) GetClusterServersByName(ctx context.Context, name string) ([]strin var res []string for i := range secrets { s := secrets[i].(*corev1.Secret) - res = append(res, strings.TrimRight(string(s.Data["server"]), "/")) + server := strings.TrimRight(string(s.Data["server"]), "/") + if !argoSettings.InClusterEnabled && server == appv1.KubernetesInternalAPIServerAddr { + continue + } + res = append(res, server) } return res, nil } diff --git a/util/db/cluster_norace_test.go b/util/db/cluster_norace_test.go index 23b5beecef079..3a2fa69f6f638 100644 --- a/util/db/cluster_norace_test.go +++ b/util/db/cluster_norace_test.go @@ -49,7 +49,7 @@ func TestWatchClusters_CreateRemoveCluster(t *testing.T) { kubeclientset := fake.NewClientset(emptyArgoCDConfigMap, argoCDSecret) settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) db := NewDB(fakeNamespace, settingsManager, kubeclientset) - runWatchTest(t, db, []func(old *v1alpha1.Cluster, new *v1alpha1.Cluster){ + completed := runWatchTest(t, db, []func(old *v1alpha1.Cluster, new *v1alpha1.Cluster){ func(old *v1alpha1.Cluster, new *v1alpha1.Cluster) { assert.Nil(t, old) assert.Equal(t, v1alpha1.KubernetesInternalAPIServerAddr, new.Server) @@ -72,6 +72,7 @@ func TestWatchClusters_CreateRemoveCluster(t *testing.T) { assert.Equal(t, "https://minikube", old.Server) }, }) + assert.True(t, completed, "Failed due to timeout") } func TestWatchClusters_LocalClusterModifications(t *testing.T) { @@ -104,7 +105,7 @@ func TestWatchClusters_LocalClusterModifications(t *testing.T) { kubeclientset := fake.NewClientset(emptyArgoCDConfigMap, argoCDSecret) settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) db := NewDB(fakeNamespace, settingsManager, kubeclientset) - runWatchTest(t, db, []func(old *v1alpha1.Cluster, new *v1alpha1.Cluster){ + completed := runWatchTest(t, db, []func(old *v1alpha1.Cluster, new *v1alpha1.Cluster){ func(old *v1alpha1.Cluster, new *v1alpha1.Cluster) { assert.Nil(t, old) assert.Equal(t, v1alpha1.KubernetesInternalAPIServerAddr, new.Server) @@ -127,4 +128,43 @@ func TestWatchClusters_LocalClusterModifications(t *testing.T) { assert.Equal(t, "in-cluster", new.Name) }, }) + assert.True(t, completed, "Failed due to timeout") +} + +func TestWatchClusters_LocalClusterModificationsWhenDisabled(t *testing.T) { + // !race: + // Intermittent failure when running TestWatchClusters_LocalClusterModifications with -race, likely due to race condition + // https://github.com/argoproj/argo-cd/issues/4755 + argoCDConfigMapWithInClusterServerAddressDisabled := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDConfigMapName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string]string{"cluster.inClusterEnabled": "false"}, + } + argoCDSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDSecretName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string][]byte{ + "admin.password": nil, + "server.secretkey": nil, + }, + } + kubeclientset := fake.NewClientset(argoCDConfigMapWithInClusterServerAddressDisabled, argoCDSecret) + settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) + db := NewDB(fakeNamespace, settingsManager, kubeclientset) + completed := runWatchTest(t, db, []func(old *v1alpha1.Cluster, new *v1alpha1.Cluster){ + func(old *v1alpha1.Cluster, new *v1alpha1.Cluster) { + assert.Fail(t, "The in-cluster should not be added when disabled") + }, + }) + assert.False(t, completed, "Expecting the method to never complete because no cluster is ever added") } diff --git a/util/db/cluster_test.go b/util/db/cluster_test.go index b1eabfcc6f074..90703d4d10c5f 100644 --- a/util/db/cluster_test.go +++ b/util/db/cluster_test.go @@ -254,7 +254,7 @@ func TestRejectCreationForInClusterWhenDisabled(t *testing.T) { require.Error(t, err) } -func runWatchTest(t *testing.T, db ArgoDB, actions []func(old *v1alpha1.Cluster, new *v1alpha1.Cluster)) { +func runWatchTest(t *testing.T, db ArgoDB, actions []func(old *v1alpha1.Cluster, new *v1alpha1.Cluster)) (completed bool) { t.Helper() ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -291,11 +291,144 @@ func runWatchTest(t *testing.T, db ArgoDB, actions []func(old *v1alpha1.Cluster, select { case <-allDone: + return true case <-time.After(timeout): - assert.Fail(t, "Failed due to timeout") + return false } } +func TestGetCluster(t *testing.T) { + emptyArgoCDConfigMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDConfigMapName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string]string{}, + } + argoCDConfigMapWithInClusterServerAddressDisabled := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDConfigMapName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string]string{"cluster.inClusterEnabled": "false"}, + } + argoCDSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDSecretName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string][]byte{ + "admin.password": nil, + "server.secretkey": nil, + }, + } + secretForServerWithInClusterAddr := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster1", + Namespace: fakeNamespace, + Labels: map[string]string{ + common.LabelKeySecretType: common.LabelValueSecretTypeCluster, + }, + }, + Data: map[string][]byte{ + "server": []byte(appv1.KubernetesInternalAPIServerAddr), + "name": []byte("in-cluster-renamed"), + }, + } + + secretForServerWithExternalClusterAddr := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster2", + Namespace: fakeNamespace, + Labels: map[string]string{ + common.LabelKeySecretType: common.LabelValueSecretTypeCluster, + }, + }, + Data: map[string][]byte{ + "server": []byte("http://mycluster2"), + "name": []byte("mycluster2"), + }, + } + + t.Run("Valid external cluster", func(t *testing.T) { + kubeclientset := fake.NewClientset(secretForServerWithExternalClusterAddr, emptyArgoCDConfigMap, argoCDSecret) + settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) + db := NewDB(fakeNamespace, settingsManager, kubeclientset) + + cluster, err := db.GetCluster(context.TODO(), string(secretForServerWithExternalClusterAddr.Data["server"])) + require.NoError(t, err) + assert.Equal(t, string(secretForServerWithExternalClusterAddr.Data["server"]), cluster.Server) + assert.Equal(t, string(secretForServerWithExternalClusterAddr.Data["name"]), cluster.Name) + }) + + t.Run("invalid cluster", func(t *testing.T) { + kubeclientset := fake.NewClientset(emptyArgoCDConfigMap, argoCDSecret) + settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) + db := NewDB(fakeNamespace, settingsManager, kubeclientset) + + _, err := db.GetCluster(context.TODO(), "https://mycluster-does-not-exist") + require.Error(t, err) + status, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.NotFound, status.Code()) + }) + + t.Run("in-cluster not configured", func(t *testing.T) { + kubeclientset := fake.NewClientset(emptyArgoCDConfigMap, argoCDSecret) + settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) + db := NewDB(fakeNamespace, settingsManager, kubeclientset) + + cluster, err := db.GetCluster(context.TODO(), appv1.KubernetesInternalAPIServerAddr) + require.NoError(t, err) + assert.Equal(t, appv1.KubernetesInternalAPIServerAddr, cluster.Server) + assert.Equal(t, "in-cluster", cluster.Name) + }) + + t.Run("in-cluster disabled", func(t *testing.T) { + kubeclientset := fake.NewClientset(argoCDConfigMapWithInClusterServerAddressDisabled, argoCDSecret) + settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) + db := NewDB(fakeNamespace, settingsManager, kubeclientset) + + _, err := db.GetCluster(context.TODO(), appv1.KubernetesInternalAPIServerAddr) + require.Error(t, err) + status, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.NotFound, status.Code()) + }) + + t.Run("in-cluster configured", func(t *testing.T) { + kubeclientset := fake.NewClientset(secretForServerWithInClusterAddr, emptyArgoCDConfigMap, argoCDSecret) + settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) + db := NewDB(fakeNamespace, settingsManager, kubeclientset) + + cluster, err := db.GetCluster(context.TODO(), appv1.KubernetesInternalAPIServerAddr) + require.NoError(t, err) + assert.Equal(t, appv1.KubernetesInternalAPIServerAddr, cluster.Server) + assert.Equal(t, "in-cluster-renamed", cluster.Name) + }) + + t.Run("in-cluster configured and disabled", func(t *testing.T) { + kubeclientset := fake.NewClientset(secretForServerWithInClusterAddr, argoCDConfigMapWithInClusterServerAddressDisabled, argoCDSecret) + settingsManager := settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace) + db := NewDB(fakeNamespace, settingsManager, kubeclientset) + + _, err := db.GetCluster(context.TODO(), appv1.KubernetesInternalAPIServerAddr) + require.Error(t, err) + status, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.NotFound, status.Code()) + }) +} + func TestListClusters(t *testing.T) { emptyArgoCDConfigMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -422,6 +555,113 @@ func TestListClusters(t *testing.T) { }) } +func TestGetClusterServersByName(t *testing.T) { + emptyArgoCDConfigMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDConfigMapName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string]string{}, + } + argoCDSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDSecretName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string][]byte{ + "admin.password": nil, + "server.secretkey": nil, + }, + } + argoCDConfigMapWithInClusterServerAddressDisabled := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDConfigMapName, + Namespace: fakeNamespace, + Labels: map[string]string{ + "app.kubernetes.io/part-of": "argocd", + }, + }, + Data: map[string]string{"cluster.inClusterEnabled": "false"}, + } + argoCDSecretInClusterConfigured := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-cluster-secret", + Namespace: fakeNamespace, + Labels: map[string]string{ + common.LabelKeySecretType: common.LabelValueSecretTypeCluster, + }, + Annotations: map[string]string{ + common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD, + }, + }, + Data: map[string][]byte{ + "name": []byte("in-cluster-renamed"), + "server": []byte(v1alpha1.KubernetesInternalAPIServerAddr), + "config": []byte("{}"), + }, + } + + t.Run("returns the server name", func(t *testing.T) { + argoCDClusterSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-cluster-secret", + Namespace: fakeNamespace, + Labels: map[string]string{ + common.LabelKeySecretType: common.LabelValueSecretTypeCluster, + }, + Annotations: map[string]string{ + common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD, + }, + }, + Data: map[string][]byte{ + "name": []byte("my-cluster-name"), + "server": []byte("https://my-cluster-server"), + "config": []byte("{}"), + }, + } + + kubeclientset := fake.NewClientset(emptyArgoCDConfigMap, argoCDClusterSecret, argoCDSecret) + db := NewDB(fakeNamespace, settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace), kubeclientset) + servers, err := db.GetClusterServersByName(context.Background(), "my-cluster-name") + require.NoError(t, err) + assert.ElementsMatch(t, []string{"https://my-cluster-server"}, servers) + }) + t.Run("returns in-cluster", func(t *testing.T) { + kubeclientset := fake.NewClientset(emptyArgoCDConfigMap, argoCDSecret) + db := NewDB(fakeNamespace, settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace), kubeclientset) + servers, err := db.GetClusterServersByName(context.Background(), "in-cluster") + require.NoError(t, err) + assert.ElementsMatch(t, []string{v1alpha1.KubernetesInternalAPIServerAddr}, servers) + }) + t.Run("does not return in-cluster when disabled", func(t *testing.T) { + kubeclientset := fake.NewClientset(argoCDConfigMapWithInClusterServerAddressDisabled, argoCDSecret) + db := NewDB(fakeNamespace, settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace), kubeclientset) + servers, err := db.GetClusterServersByName(context.Background(), "in-cluster") + require.NoError(t, err) + assert.Empty(t, servers) + }) + t.Run("returns in-cluster when configured", func(t *testing.T) { + kubeclientset := fake.NewClientset(emptyArgoCDConfigMap, argoCDSecretInClusterConfigured, argoCDSecret) + db := NewDB(fakeNamespace, settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace), kubeclientset) + servers, err := db.GetClusterServersByName(context.Background(), "in-cluster-renamed") + require.NoError(t, err) + assert.ElementsMatch(t, []string{v1alpha1.KubernetesInternalAPIServerAddr}, servers) + }) + t.Run("does not return in-cluster when configured and disabled", func(t *testing.T) { + kubeclientset := fake.NewClientset(argoCDConfigMapWithInClusterServerAddressDisabled, argoCDSecretInClusterConfigured, argoCDSecret) + db := NewDB(fakeNamespace, settings.NewSettingsManager(context.Background(), kubeclientset, fakeNamespace), kubeclientset) + servers, err := db.GetClusterServersByName(context.Background(), "in-cluster-renamed") + require.NoError(t, err) + assert.Empty(t, servers) + }) +} + // TestClusterRaceConditionClusterSecrets reproduces a race condition // on the cluster secrets. The test isn't asserting anything because // before the fix it would cause a panic from concurrent map iteration and map write diff --git a/util/db/db_test.go b/util/db/db_test.go index 2ab263955dbbc..05b3d61b0ca62 100644 --- a/util/db/db_test.go +++ b/util/db/db_test.go @@ -502,42 +502,6 @@ func TestRepositorySecretsTrim(t *testing.T) { } } -func TestGetClusterSuccessful(t *testing.T) { - server := "my-cluster" - name := "my-name" - clientset := getClientset(nil, &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: testNamespace, - Labels: map[string]string{ - common.LabelKeySecretType: common.LabelValueSecretTypeCluster, - }, - }, - Data: map[string][]byte{ - "server": []byte(server), - "name": []byte(name), - "config": []byte("{}"), - }, - }) - - db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset) - cluster, err := db.GetCluster(context.Background(), server) - require.NoError(t, err) - assert.Equal(t, server, cluster.Server) - assert.Equal(t, name, cluster.Name) -} - -func TestGetNonExistingCluster(t *testing.T) { - server := "https://mycluster" - clientset := getClientset(nil) - - db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset) - _, err := db.GetCluster(context.Background(), server) - require.Error(t, err) - status, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.NotFound, status.Code()) -} - func TestCreateClusterSuccessful(t *testing.T) { server := "https://mycluster" clientset := getClientset(nil) @@ -752,62 +716,6 @@ func TestHelmRepositorySecretsTrim(t *testing.T) { } } -func TestGetClusterServersByName(t *testing.T) { - clientset := getClientset(nil, &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-cluster-secret", - Namespace: testNamespace, - Labels: map[string]string{ - common.LabelKeySecretType: common.LabelValueSecretTypeCluster, - }, - Annotations: map[string]string{ - common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD, - }, - }, - Data: map[string][]byte{ - "name": []byte("my-cluster-name"), - "server": []byte("https://my-cluster-server"), - "config": []byte("{}"), - }, - }) - db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset) - servers, err := db.GetClusterServersByName(context.Background(), "my-cluster-name") - require.NoError(t, err) - assert.ElementsMatch(t, []string{"https://my-cluster-server"}, servers) -} - -func TestGetClusterServersByName_InClusterNotConfigured(t *testing.T) { - clientset := getClientset(nil) - db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset) - servers, err := db.GetClusterServersByName(context.Background(), "in-cluster") - require.NoError(t, err) - assert.ElementsMatch(t, []string{v1alpha1.KubernetesInternalAPIServerAddr}, servers) -} - -func TestGetClusterServersByName_InClusterConfigured(t *testing.T) { - clientset := getClientset(nil, &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-cluster-secret", - Namespace: testNamespace, - Labels: map[string]string{ - common.LabelKeySecretType: common.LabelValueSecretTypeCluster, - }, - Annotations: map[string]string{ - common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD, - }, - }, - Data: map[string][]byte{ - "name": []byte("in-cluster-renamed"), - "server": []byte(v1alpha1.KubernetesInternalAPIServerAddr), - "config": []byte("{}"), - }, - }) - db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset) - servers, err := db.GetClusterServersByName(context.Background(), "in-cluster-renamed") - require.NoError(t, err) - assert.ElementsMatch(t, []string{v1alpha1.KubernetesInternalAPIServerAddr}, servers) -} - func TestGetApplicationControllerReplicas(t *testing.T) { clientset := getClientset(nil) expectedReplicas := int32(2)