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 }