github.com/argoproj/argo-cd@v1.8.7/util/db/db_test.go (about)

     1  package db
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"google.golang.org/grpc/codes"
    11  	"google.golang.org/grpc/status"
    12  	v1 "k8s.io/api/core/v1"
    13  	"k8s.io/apimachinery/pkg/api/errors"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"k8s.io/apimachinery/pkg/runtime"
    16  	"k8s.io/client-go/kubernetes/fake"
    17  
    18  	"github.com/argoproj/argo-cd/common"
    19  	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
    20  	"github.com/argoproj/argo-cd/util/settings"
    21  )
    22  
    23  const (
    24  	testNamespace = "default"
    25  )
    26  
    27  func getClientset(config map[string]string, objects ...runtime.Object) *fake.Clientset {
    28  	secret := v1.Secret{
    29  		ObjectMeta: metav1.ObjectMeta{
    30  			Name:      "argocd-secret",
    31  			Namespace: testNamespace,
    32  		},
    33  		Data: map[string][]byte{
    34  			"admin.password":   []byte("test"),
    35  			"server.secretkey": []byte("test"),
    36  		},
    37  	}
    38  	cm := v1.ConfigMap{
    39  		ObjectMeta: metav1.ObjectMeta{
    40  			Name:      "argocd-cm",
    41  			Namespace: testNamespace,
    42  			Labels: map[string]string{
    43  				"app.kubernetes.io/part-of": "argocd",
    44  			},
    45  		},
    46  		Data: config,
    47  	}
    48  	return fake.NewSimpleClientset(append(objects, &cm, &secret)...)
    49  }
    50  
    51  func TestCreateRepository(t *testing.T) {
    52  	clientset := getClientset(nil)
    53  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
    54  
    55  	repo, err := db.CreateRepository(context.Background(), &v1alpha1.Repository{
    56  		Repo:     "https://github.com/argoproj/argocd-example-apps",
    57  		Username: "test-username",
    58  		Password: "test-password",
    59  	})
    60  	assert.Nil(t, err)
    61  	assert.Equal(t, "https://github.com/argoproj/argocd-example-apps", repo.Repo)
    62  
    63  	secret, err := clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), repoURLToSecretName(repoSecretPrefix, repo.Repo), metav1.GetOptions{})
    64  	assert.Nil(t, err)
    65  
    66  	assert.Equal(t, common.AnnotationValueManagedByArgoCD, secret.Annotations[common.AnnotationKeyManagedBy])
    67  	assert.Equal(t, string(secret.Data[username]), "test-username")
    68  	assert.Equal(t, string(secret.Data[password]), "test-password")
    69  	assert.Nil(t, secret.Data[sshPrivateKey])
    70  }
    71  
    72  func TestCreateRepoCredentials(t *testing.T) {
    73  	clientset := getClientset(nil)
    74  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
    75  
    76  	creds, err := db.CreateRepositoryCredentials(context.Background(), &v1alpha1.RepoCreds{
    77  		URL:      "https://github.com/argoproj/",
    78  		Username: "test-username",
    79  		Password: "test-password",
    80  	})
    81  	assert.Nil(t, err)
    82  	assert.Equal(t, "https://github.com/argoproj/", creds.URL)
    83  
    84  	secret, err := clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), repoURLToSecretName(credSecretPrefix, creds.URL), metav1.GetOptions{})
    85  	assert.Nil(t, err)
    86  
    87  	assert.Equal(t, common.AnnotationValueManagedByArgoCD, secret.Annotations[common.AnnotationKeyManagedBy])
    88  	assert.Equal(t, string(secret.Data[username]), "test-username")
    89  	assert.Equal(t, string(secret.Data[password]), "test-password")
    90  	assert.Nil(t, secret.Data[sshPrivateKey])
    91  
    92  	created, err := db.CreateRepository(context.Background(), &v1alpha1.Repository{
    93  		Repo: "https://github.com/argoproj/argo-cd",
    94  	})
    95  	assert.Nil(t, err)
    96  	assert.Equal(t, "https://github.com/argoproj/argo-cd", created.Repo)
    97  
    98  	// There seems to be a race or some other hiccup in the fake K8s clientset used for this test.
    99  	// Just give it a little time to settle.
   100  	time.Sleep(1 * time.Second)
   101  
   102  	repo, err := db.GetRepository(context.Background(), created.Repo)
   103  	assert.NoError(t, err)
   104  	assert.Equal(t, "test-username", repo.Username)
   105  	assert.Equal(t, "test-password", repo.Password)
   106  }
   107  
   108  func TestCreateExistingRepository(t *testing.T) {
   109  	clientset := getClientset(map[string]string{
   110  		"repositories": `- url: https://github.com/argoproj/argocd-example-apps`,
   111  	})
   112  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   113  
   114  	_, err := db.CreateRepository(context.Background(), &v1alpha1.Repository{
   115  		Repo:     "https://github.com/argoproj/argocd-example-apps",
   116  		Username: "test-username",
   117  		Password: "test-password",
   118  	})
   119  	assert.NotNil(t, err)
   120  	assert.Equal(t, codes.AlreadyExists, status.Convert(err).Code())
   121  }
   122  
   123  func TestGetRepository(t *testing.T) {
   124  	config := map[string]string{
   125  		"repositories": `
   126  - url: https://known/repo
   127  - url: https://secured/repo
   128  `,
   129  		"repository.credentials": `
   130  - url: https://secured
   131    usernameSecret:
   132      name: managed-secret
   133      key: username
   134    passwordSecret:
   135      name: managed-secret
   136      key: password
   137  `}
   138  	clientset := getClientset(config, newManagedSecret())
   139  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   140  
   141  	tests := []struct {
   142  		name    string
   143  		repoURL string
   144  		want    *v1alpha1.Repository
   145  	}{
   146  		{
   147  			name:    "TestUnknownRepo",
   148  			repoURL: "https://unknown/repo",
   149  			want:    &v1alpha1.Repository{Repo: "https://unknown/repo"},
   150  		},
   151  		{
   152  			name:    "TestKnownRepo",
   153  			repoURL: "https://known/repo",
   154  			want:    &v1alpha1.Repository{Repo: "https://known/repo"},
   155  		},
   156  		{
   157  			name:    "TestSecuredRepo",
   158  			repoURL: "https://secured/repo",
   159  			want:    &v1alpha1.Repository{Repo: "https://secured/repo", Username: "test-username", Password: "test-password", InheritedCreds: true},
   160  		},
   161  	}
   162  	for _, tt := range tests {
   163  		t.Run(tt.name, func(t *testing.T) {
   164  			got, err := db.GetRepository(context.TODO(), tt.repoURL)
   165  			assert.NoError(t, err)
   166  			assert.Equal(t, tt.want, got)
   167  		})
   168  	}
   169  }
   170  
   171  func newManagedSecret() *v1.Secret {
   172  	return &v1.Secret{
   173  		ObjectMeta: metav1.ObjectMeta{
   174  			Name:      "managed-secret",
   175  			Namespace: testNamespace,
   176  			Annotations: map[string]string{
   177  				common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD,
   178  			},
   179  		},
   180  		Data: map[string][]byte{
   181  			username: []byte("test-username"),
   182  			password: []byte("test-password"),
   183  		},
   184  	}
   185  }
   186  
   187  func TestDeleteRepositoryManagedSecrets(t *testing.T) {
   188  	config := map[string]string{
   189  		"repositories": `
   190  - url: https://github.com/argoproj/argocd-example-apps
   191    usernameSecret:
   192      name: managed-secret
   193      key: username
   194    passwordSecret:
   195      name: managed-secret
   196      key: password
   197  `}
   198  	clientset := getClientset(config, newManagedSecret())
   199  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   200  
   201  	err := db.DeleteRepository(context.Background(), "https://github.com/argoproj/argocd-example-apps")
   202  	assert.Nil(t, err)
   203  
   204  	_, err = clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), "managed-secret", metav1.GetOptions{})
   205  	assert.NotNil(t, err)
   206  	assert.True(t, errors.IsNotFound(err))
   207  
   208  	cm, err := clientset.CoreV1().ConfigMaps(testNamespace).Get(context.Background(), "argocd-cm", metav1.GetOptions{})
   209  	assert.Nil(t, err)
   210  	assert.Equal(t, "", cm.Data["repositories"])
   211  }
   212  
   213  func TestDeleteRepositoryUnmanagedSecrets(t *testing.T) {
   214  	config := map[string]string{
   215  		"repositories": `
   216  - url: https://github.com/argoproj/argocd-example-apps
   217    usernameSecret:
   218      name: unmanaged-secret
   219      key: username
   220    passwordSecret:
   221      name: unmanaged-secret
   222      key: password
   223  `}
   224  	clientset := getClientset(config, &v1.Secret{
   225  		ObjectMeta: metav1.ObjectMeta{
   226  			Name:      "unmanaged-secret",
   227  			Namespace: testNamespace,
   228  		},
   229  		Data: map[string][]byte{
   230  			username: []byte("test-username"),
   231  			password: []byte("test-password"),
   232  		},
   233  	})
   234  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   235  
   236  	err := db.DeleteRepository(context.Background(), "https://github.com/argoproj/argocd-example-apps")
   237  	assert.Nil(t, err)
   238  
   239  	s, err := clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), "unmanaged-secret", metav1.GetOptions{})
   240  	assert.Nil(t, err)
   241  	assert.Equal(t, "test-username", string(s.Data[username]))
   242  	assert.Equal(t, "test-password", string(s.Data[password]))
   243  
   244  	cm, err := clientset.CoreV1().ConfigMaps(testNamespace).Get(context.Background(), "argocd-cm", metav1.GetOptions{})
   245  	assert.Nil(t, err)
   246  	assert.Equal(t, "", cm.Data["repositories"])
   247  }
   248  
   249  func TestUpdateRepositoryWithManagedSecrets(t *testing.T) {
   250  	config := map[string]string{
   251  		"repositories": `
   252  - url: https://github.com/argoproj/argocd-example-apps
   253    usernameSecret:
   254      name: managed-secret
   255      key: username
   256    passwordSecret:
   257      name: managed-secret
   258      key: password
   259    sshPrivateKeySecret:
   260      name: managed-secret
   261      key: sshPrivateKey
   262  `}
   263  	clientset := getClientset(config, &v1.Secret{
   264  		ObjectMeta: metav1.ObjectMeta{
   265  			Name:      "managed-secret",
   266  			Namespace: testNamespace,
   267  			Annotations: map[string]string{
   268  				common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD,
   269  			},
   270  		},
   271  		Data: map[string][]byte{
   272  			username:      []byte("test-username"),
   273  			password:      []byte("test-password"),
   274  			sshPrivateKey: []byte("test-ssh-private-key"),
   275  		},
   276  	})
   277  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   278  
   279  	repo, err := db.GetRepository(context.Background(), "https://github.com/argoproj/argocd-example-apps")
   280  	assert.Nil(t, err)
   281  	assert.Equal(t, "test-username", repo.Username)
   282  	assert.Equal(t, "test-password", repo.Password)
   283  	assert.Equal(t, "test-ssh-private-key", repo.SSHPrivateKey)
   284  
   285  	_, err = db.UpdateRepository(context.Background(), &v1alpha1.Repository{
   286  		Repo: "https://github.com/argoproj/argocd-example-apps", Password: "", Username: "", SSHPrivateKey: ""})
   287  	assert.Nil(t, err)
   288  
   289  	_, err = clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), "managed-secret", metav1.GetOptions{})
   290  	assert.NotNil(t, err)
   291  	assert.True(t, errors.IsNotFound(err))
   292  
   293  	cm, err := clientset.CoreV1().ConfigMaps(testNamespace).Get(context.Background(), "argocd-cm", metav1.GetOptions{})
   294  	assert.Nil(t, err)
   295  	assert.Equal(t, "- url: https://github.com/argoproj/argocd-example-apps", strings.Trim(cm.Data["repositories"], "\n"))
   296  }
   297  
   298  func TestGetClusterSuccessful(t *testing.T) {
   299  	server := "my-cluster"
   300  	name := "my-name"
   301  	clientset := getClientset(nil, &v1.Secret{
   302  		ObjectMeta: metav1.ObjectMeta{
   303  			Namespace: testNamespace,
   304  			Labels: map[string]string{
   305  				common.LabelKeySecretType: common.LabelValueSecretTypeCluster,
   306  			},
   307  		},
   308  		Data: map[string][]byte{
   309  			"server": []byte(server),
   310  			"name":   []byte(name),
   311  			"config": []byte("{}"),
   312  		},
   313  	})
   314  
   315  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   316  	cluster, err := db.GetCluster(context.Background(), server)
   317  	assert.NoError(t, err)
   318  	assert.Equal(t, server, cluster.Server)
   319  	assert.Equal(t, name, cluster.Name)
   320  }
   321  
   322  func TestGetNonExistingCluster(t *testing.T) {
   323  	server := "https://mycluster"
   324  	clientset := getClientset(nil)
   325  
   326  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   327  	_, err := db.GetCluster(context.Background(), server)
   328  	assert.NotNil(t, err)
   329  	status, ok := status.FromError(err)
   330  	assert.True(t, ok)
   331  	assert.Equal(t, codes.NotFound, status.Code())
   332  }
   333  
   334  func TestCreateClusterSuccessful(t *testing.T) {
   335  	server := "https://mycluster"
   336  	clientset := getClientset(nil)
   337  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   338  
   339  	_, err := db.CreateCluster(context.Background(), &v1alpha1.Cluster{
   340  		Server: server,
   341  	})
   342  	assert.Nil(t, err)
   343  
   344  	secret, err := clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), "cluster-mycluster-3274446258", metav1.GetOptions{})
   345  	assert.Nil(t, err)
   346  
   347  	assert.Equal(t, server, string(secret.Data["server"]))
   348  	assert.Equal(t, common.AnnotationValueManagedByArgoCD, secret.Annotations[common.AnnotationKeyManagedBy])
   349  }
   350  
   351  func TestDeleteClusterWithManagedSecret(t *testing.T) {
   352  	clusterURL := "https://mycluster"
   353  	clusterName := "cluster-mycluster-3274446258"
   354  
   355  	clientset := getClientset(nil, &v1.Secret{
   356  		ObjectMeta: metav1.ObjectMeta{
   357  			Name:      clusterName,
   358  			Namespace: testNamespace,
   359  			Labels: map[string]string{
   360  				common.LabelKeySecretType: common.LabelValueSecretTypeCluster,
   361  			},
   362  			Annotations: map[string]string{
   363  				common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD,
   364  			},
   365  		},
   366  		Data: map[string][]byte{
   367  			"server": []byte(clusterURL),
   368  			"config": []byte("{}"),
   369  		},
   370  	})
   371  
   372  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   373  	err := db.DeleteCluster(context.Background(), clusterURL)
   374  	assert.Nil(t, err)
   375  
   376  	_, err = clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), clusterName, metav1.GetOptions{})
   377  	assert.NotNil(t, err)
   378  
   379  	assert.True(t, errors.IsNotFound(err))
   380  }
   381  
   382  func TestDeleteClusterWithUnmanagedSecret(t *testing.T) {
   383  	clusterURL := "https://mycluster"
   384  	clusterName := "mycluster-443"
   385  
   386  	clientset := getClientset(nil, &v1.Secret{
   387  		ObjectMeta: metav1.ObjectMeta{
   388  			Name:      clusterName,
   389  			Namespace: testNamespace,
   390  			Labels: map[string]string{
   391  				common.LabelKeySecretType: common.LabelValueSecretTypeCluster,
   392  			},
   393  		},
   394  		Data: map[string][]byte{
   395  			"server": []byte(clusterURL),
   396  			"config": []byte("{}"),
   397  		},
   398  	})
   399  
   400  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   401  	err := db.DeleteCluster(context.Background(), clusterURL)
   402  	assert.Nil(t, err)
   403  
   404  	secret, err := clientset.CoreV1().Secrets(testNamespace).Get(context.Background(), clusterName, metav1.GetOptions{})
   405  	assert.Nil(t, err)
   406  
   407  	assert.Equal(t, 0, len(secret.Labels))
   408  }
   409  
   410  func TestFuzzyEquivalence(t *testing.T) {
   411  	clientset := getClientset(nil)
   412  	ctx := context.Background()
   413  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   414  
   415  	repo, err := db.CreateRepository(ctx, &v1alpha1.Repository{
   416  		Repo: "https://github.com/argoproj/argocd-example-apps",
   417  	})
   418  	assert.Nil(t, err)
   419  	assert.Equal(t, "https://github.com/argoproj/argocd-example-apps", repo.Repo)
   420  
   421  	repo, err = db.CreateRepository(ctx, &v1alpha1.Repository{
   422  		Repo: "https://github.com/argoproj/argocd-example-apps.git",
   423  	})
   424  	assert.Contains(t, err.Error(), "already exists")
   425  	assert.Nil(t, repo)
   426  
   427  	repo, err = db.CreateRepository(ctx, &v1alpha1.Repository{
   428  		Repo: "https://github.com/argoproj/argocd-example-APPS",
   429  	})
   430  	assert.Contains(t, err.Error(), "already exists")
   431  	assert.Nil(t, repo)
   432  
   433  	repo, err = db.GetRepository(ctx, "https://github.com/argoproj/argocd-example-APPS")
   434  	assert.Nil(t, err)
   435  	assert.Equal(t, "https://github.com/argoproj/argocd-example-apps", repo.Repo)
   436  }
   437  
   438  func TestListHelmRepositories(t *testing.T) {
   439  	config := map[string]string{
   440  		"repositories": `
   441  - url: https://argoproj.github.io/argo-helm
   442    name: argo
   443    type: helm
   444    usernameSecret:
   445      name: test-secret
   446      key: username
   447    passwordSecret:
   448      name: test-secret
   449      key: password
   450    tlsClientCertDataSecret:
   451      name: test-secret
   452      key: cert
   453    tlsClientCertKeySecret:
   454      name: test-secret
   455      key: key
   456  `}
   457  	clientset := getClientset(config, &v1.Secret{
   458  		ObjectMeta: metav1.ObjectMeta{
   459  			Name:      "test-secret",
   460  			Namespace: testNamespace,
   461  		},
   462  		Data: map[string][]byte{
   463  			"username": []byte("test-username"),
   464  			"password": []byte("test-password"),
   465  			"ca":       []byte("test-ca"),
   466  			"cert":     []byte("test-cert"),
   467  			"key":      []byte("test-key"),
   468  		},
   469  	})
   470  	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
   471  
   472  	repos, err := db.ListRepositories(context.Background())
   473  	assert.Nil(t, err)
   474  	assert.Len(t, repos, 1)
   475  	repo := repos[0]
   476  	assert.Equal(t, "https://argoproj.github.io/argo-helm", repo.Repo)
   477  	assert.Equal(t, "helm", repo.Type)
   478  	assert.Equal(t, "argo", repo.Name)
   479  	assert.Equal(t, "test-username", repo.Username)
   480  	assert.Equal(t, "test-password", repo.Password)
   481  	assert.Equal(t, "test-cert", repo.TLSClientCertData)
   482  	assert.Equal(t, "test-key", repo.TLSClientCertKey)
   483  }