github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/btpmanager/credentials/manager_test.go (about) 1 package btpmgrcreds 2 3 import ( 4 "context" 5 "math" 6 "math/rand" 7 "os" 8 "os/exec" 9 "strings" 10 "sync" 11 "testing" 12 "time" 13 14 "k8s.io/apimachinery/pkg/api/errors" 15 16 uuid2 "github.com/google/uuid" 17 "github.com/kyma-project/kyma-environment-broker/internal" 18 "github.com/kyma-project/kyma-environment-broker/internal/provisioner" 19 "github.com/kyma-project/kyma-environment-broker/internal/storage" 20 "github.com/kyma-project/kyma-environment-broker/internal/storage/dbmodel" 21 kymaevent "github.com/kyma-project/runtime-watcher/listener/pkg/event" 22 "github.com/kyma-project/runtime-watcher/listener/pkg/types" 23 "github.com/sirupsen/logrus" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 apicorev1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 29 "k8s.io/client-go/rest" 30 "k8s.io/client-go/tools/clientcmd" 31 "k8s.io/client-go/tools/clientcmd/api" 32 "sigs.k8s.io/controller-runtime/pkg/client" 33 "sigs.k8s.io/controller-runtime/pkg/envtest" 34 "sigs.k8s.io/controller-runtime/pkg/event" 35 ) 36 37 const ( 38 expectedTakenInstancesCount = 3 39 expectedRejectedInstancesCount = 1 40 expectedAllInstancesCount = expectedTakenInstancesCount + expectedRejectedInstancesCount 41 credentialsLen = 16 42 jobReconciliationDelay = time.Second * 0 43 ) 44 45 var ( 46 changedInstancesCount = int(math.Ceil(expectedTakenInstancesCount / 2)) 47 testDataIndexes = []int{0, 2} 48 random = rand.New(rand.NewSource(1)) 49 ) 50 51 const ( 52 envTestAssets = "KUBEBUILDER_ASSETS" 53 ) 54 55 type Environment struct { 56 ctx context.Context 57 skrs []*envtest.Environment 58 skrRuntimeId map[string]string 59 kcp client.Client 60 kebDb storage.BrokerStorage 61 logs *logrus.Logger 62 manager *Manager 63 watcher *Watcher 64 job *Job 65 t *testing.T 66 } 67 68 func InitEnvironment(ctx context.Context, t *testing.T) *Environment { 69 logs := logrus.New() 70 logs.SetFormatter(&logrus.JSONFormatter{}) 71 newEnvironment := &Environment{ 72 skrs: make([]*envtest.Environment, 0), 73 kebDb: storage.NewMemoryStorage(), 74 logs: logs, 75 ctx: ctx, 76 t: t, 77 } 78 79 newEnvironment.createTestData() 80 newEnvironment.manager = NewManager(ctx, newEnvironment.kcp, newEnvironment.kebDb.Instances(), logs, false, provisioner.NewFakeClient()) 81 newEnvironment.watcher = NewWatcher(ctx, "3333", "btp-manager-secret-watcher", newEnvironment.manager, logs) 82 newEnvironment.job = NewJob(newEnvironment.manager, logs) 83 newEnvironment.assertThatCorrectNumberOfInstancesExists() 84 return newEnvironment 85 } 86 87 func TestBtpManagerReconciler(t *testing.T) { 88 if os.Getenv(envTestAssets) == "" { 89 out, err := exec.Command("/bin/sh", "../../../setup-envtest.sh").Output() 90 require.NoError(t, err) 91 path := strings.Replace(string(out), "\n", "", -1) 92 os.Setenv(envTestAssets, path) 93 } 94 95 t.Run("btp manager credentials tests", func(t *testing.T) { 96 ctx, cancel := context.WithCancel(context.Background()) 97 environment := InitEnvironment(ctx, t) 98 99 t.Run("reconcile, when all secrets are not set", func(t *testing.T) { 100 environment.assertAllSecretsNotExists() 101 takenInstancesCount, updateDone, updateNotDoneDueError, updateNotDoneDueOkState, err := environment.manager.ReconcileAll(jobReconciliationDelay) 102 assert.NoError(t, err) 103 assert.Equal(t, expectedTakenInstancesCount, takenInstancesCount) 104 assert.Equal(t, expectedTakenInstancesCount, updateDone) 105 assert.Equal(t, 0, updateNotDoneDueError+updateNotDoneDueOkState) 106 environment.assertAllSecretDataAreSet() 107 environment.assureConsistency() 108 }) 109 110 t.Run("reconcile, when all secrets are correct", func(t *testing.T) { 111 environment.assertAllSecretDataAreSet() 112 takenInstancesCount, updateDone, updateNotDoneDueError, updateNotDoneDueOkState, err := environment.manager.ReconcileAll(jobReconciliationDelay) 113 assert.NoError(t, err) 114 environment.assertThatCorrectNumberOfInstancesExists() 115 assert.Equal(t, expectedTakenInstancesCount, takenInstancesCount) 116 assert.Equal(t, updateDone, 0) 117 assert.Equal(t, updateNotDoneDueError+updateNotDoneDueOkState, expectedTakenInstancesCount) 118 environment.assertAllSecretDataAreSet() 119 environment.assureConsistency() 120 }) 121 122 t.Run("reconcile, when some secrets are incorrect (dynamic selected)", func(t *testing.T) { 123 skrs := environment.getSkrsForSimulateChange([]int{}) 124 environment.simulateSecretChangeOnSkr(skrs) 125 environment.assertAllSecretDataAreSet() 126 takenInstancesCount, updateDone, updateNotDoneDueError, updateNotDoneDueOkState, err := environment.manager.ReconcileAll(jobReconciliationDelay) 127 assert.NoError(t, err) 128 environment.assertThatCorrectNumberOfInstancesExists() 129 assert.Equal(t, expectedTakenInstancesCount, takenInstancesCount) 130 assert.Equal(t, updateDone, len(skrs)) 131 assert.Equal(t, updateNotDoneDueError+updateNotDoneDueOkState, expectedTakenInstancesCount-len(skrs)) 132 environment.assertAllSecretDataAreSet() 133 environment.assureConsistency() 134 }) 135 136 t.Run("reconcile, when some secrets are incorrect (static selected)", func(t *testing.T) { 137 max := max(testDataIndexes) 138 assert.GreaterOrEqual(t, expectedTakenInstancesCount-1, max) 139 skrs := environment.getSkrsForSimulateChange(testDataIndexes) 140 environment.simulateSecretChangeOnSkr(skrs) 141 environment.assertAllSecretDataAreSet() 142 takenInstancesCount, updateDone, updateNotDoneDueError, updateNotDoneDueOkState, err := environment.manager.ReconcileAll(jobReconciliationDelay) 143 assert.NoError(t, err) 144 environment.assertThatCorrectNumberOfInstancesExists() 145 assert.Equal(t, expectedTakenInstancesCount, takenInstancesCount) 146 assert.Equal(t, updateDone, len(testDataIndexes)) 147 assert.Equal(t, updateNotDoneDueError+updateNotDoneDueOkState, expectedTakenInstancesCount-len(testDataIndexes)) 148 environment.assertAllSecretDataAreSet() 149 environment.assureConsistency() 150 }) 151 152 t.Run("change one instance", func(t *testing.T) { 153 skrs := environment.getSkrsForSimulateChange([]int{0}) 154 environment.simulateSecretChangeOnSkr(skrs) 155 kymaName := environment.findRuntimeIdForSkr(skrs[0].Config.Host) 156 inconsistentClusters := environment.assureThatClusterIsInIncorrectState() 157 assert.Equal(t, 1, inconsistentClusters) 158 go environment.watcher.ReactOnSkrEvent() 159 time.Sleep(time.Millisecond * 100) 160 environment.watcher.listener.ReceivedEvents <- event.GenericEvent{Object: kymaevent.GenericEvent(&types.WatchEvent{ 161 Owner: client.ObjectKey{ 162 Name: kymaName, 163 }, 164 })} 165 time.Sleep(time.Millisecond * 100) 166 environment.assureConsistency() 167 }) 168 169 t.Run("change many instances", func(t *testing.T) { 170 assert.GreaterOrEqual(t, expectedTakenInstancesCount, 1) 171 skrs := environment.getSkrsForSimulateChange([]int{1, expectedTakenInstancesCount - 1}) 172 environment.simulateSecretChangeOnSkr(skrs) 173 assert.GreaterOrEqual(t, len(skrs), 2) 174 kymaName := environment.findRuntimeIdForSkr(skrs[0].Config.Host) 175 kymaName2 := environment.findRuntimeIdForSkr(skrs[1].Config.Host) 176 inconsistentClusters := environment.assureThatClusterIsInIncorrectState() 177 assert.Equal(t, 2, inconsistentClusters) 178 go environment.watcher.ReactOnSkrEvent() 179 time.Sleep(time.Millisecond * 100) 180 wg := &sync.WaitGroup{} 181 wg.Add(1) 182 go func() { 183 defer wg.Done() 184 environment.watcher.listener.ReceivedEvents <- event.GenericEvent{Object: kymaevent.GenericEvent(&types.WatchEvent{ 185 Owner: client.ObjectKey{ 186 Name: kymaName, 187 }, 188 })} 189 }() 190 191 wg.Add(1) 192 go func() { 193 defer wg.Done() 194 environment.watcher.listener.ReceivedEvents <- event.GenericEvent{Object: kymaevent.GenericEvent(&types.WatchEvent{ 195 Owner: client.ObjectKey{ 196 Name: kymaName2, 197 }, 198 })} 199 }() 200 defer wg.Wait() 201 time.Sleep(time.Millisecond * 100) 202 environment.assureConsistency() 203 }) 204 205 t.Cleanup(func() { 206 cancel() 207 }) 208 }) 209 } 210 211 func TestManager(t *testing.T) { 212 manager := Manager{ 213 logger: logrus.New(), 214 } 215 t.Run("compare secrets with all different data", func(t *testing.T) { 216 current, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 217 ClientID: "a", 218 ClientSecret: "a", 219 ServiceManagerURL: "a", 220 URL: "a", 221 XSAppName: "a", 222 }, "a") 223 assert.NoError(t, err) 224 225 expected, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 226 ClientID: "b", 227 ClientSecret: "b", 228 ServiceManagerURL: "b", 229 URL: "b", 230 XSAppName: "b", 231 }, "b") 232 assert.NoError(t, err) 233 234 notMatchingKeys, err := manager.compareSecrets(current, expected) 235 assert.NoError(t, err) 236 assert.NotNil(t, notMatchingKeys) 237 assert.Greater(t, len(notMatchingKeys), 0) 238 assert.Equal(t, notMatchingKeys, []string{secretClientSecret, secretClientId, secretSmUrl, secretTokenUrl, secretClusterId}) 239 }) 240 241 t.Run("compare secrets with partially different data", func(t *testing.T) { 242 current, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 243 ClientID: "a", 244 ClientSecret: "a", 245 ServiceManagerURL: "a", 246 URL: "a", 247 XSAppName: "a", 248 }, "a") 249 assert.NoError(t, err) 250 251 expected, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 252 ClientID: "b", 253 ClientSecret: "b", 254 ServiceManagerURL: "a", 255 URL: "a", 256 XSAppName: "a", 257 }, "a") 258 assert.NoError(t, err) 259 260 notMatchingKeys, err := manager.compareSecrets(current, expected) 261 assert.NoError(t, err) 262 assert.NotNil(t, notMatchingKeys) 263 assert.Greater(t, len(notMatchingKeys), 0) 264 assert.Equal(t, notMatchingKeys, []string{secretClientSecret, secretClientId}) 265 }) 266 267 t.Run("compare secrets with the same data", func(t *testing.T) { 268 current, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 269 ClientID: "a1", 270 ClientSecret: "a2", 271 ServiceManagerURL: "a3", 272 URL: "a4", 273 XSAppName: "a5", 274 }, "a6") 275 assert.NoError(t, err) 276 277 expected, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 278 ClientID: "a1", 279 ClientSecret: "a2", 280 ServiceManagerURL: "a3", 281 URL: "a4", 282 XSAppName: "a5", 283 }, "a6") 284 assert.NoError(t, err) 285 286 notMatchingKeys, err := manager.compareSecrets(current, expected) 287 assert.NoError(t, err) 288 assert.NotNil(t, notMatchingKeys) 289 assert.Equal(t, len(notMatchingKeys), 0) 290 }) 291 292 t.Run("compare secrets where some of data is missing and data is same", func(t *testing.T) { 293 current, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 294 ClientID: "a", 295 ClientSecret: "a", 296 ServiceManagerURL: "a", 297 URL: "a", 298 XSAppName: "a", 299 }, "a") 300 assert.NoError(t, err) 301 delete(current.Data, secretClientSecret) 302 303 expected, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 304 ClientID: "a", 305 ClientSecret: "a", 306 ServiceManagerURL: "a", 307 URL: "a", 308 XSAppName: "a", 309 }, "a") 310 311 notMatchingKeys, err := manager.compareSecrets(current, expected) 312 assert.Nil(t, notMatchingKeys) 313 assert.Error(t, err) 314 }) 315 316 t.Run("compare secrets where some of data is missing and data are different", func(t *testing.T) { 317 current, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 318 ClientID: "a", 319 ClientSecret: "a", 320 ServiceManagerURL: "a", 321 URL: "a", 322 XSAppName: "a", 323 }, "a") 324 assert.NoError(t, err) 325 delete(current.Data, secretClientSecret) 326 327 expected, err := PrepareSecret(&internal.ServiceManagerOperatorCredentials{ 328 ClientID: "b", 329 ClientSecret: "b", 330 ServiceManagerURL: "b", 331 URL: "b", 332 XSAppName: "b", 333 }, "b") 334 assert.NoError(t, err) 335 336 notMatchingKeys, err := manager.compareSecrets(current, expected) 337 assert.Nil(t, notMatchingKeys) 338 assert.Error(t, err) 339 }) 340 } 341 342 func (e *Environment) createTestData() { 343 e.createClusters(expectedTakenInstancesCount) 344 e.skrRuntimeId = make(map[string]string, 0) 345 for i := 0; i < expectedTakenInstancesCount; i++ { 346 cfg := *e.skrs[i].Config 347 clusterId := cfg.Host 348 kubeConfig := restConfigToString(cfg) 349 require.NotEmpty(e.t, kubeConfig) 350 instanceId, runtimeId := e.createInstance(kubeConfig, generateServiceManagerCredentials(), clusterId) 351 e.createKyma(runtimeId, instanceId) 352 e.skrRuntimeId[clusterId] = runtimeId 353 } 354 355 for i := 0; i < expectedRejectedInstancesCount; i++ { 356 e.createInstance("", generateServiceManagerCredentials(), "") 357 } 358 } 359 360 func (e *Environment) createClusters(count int) { 361 tempSkrs := make([]*envtest.Environment, 0) 362 wg := &sync.WaitGroup{} 363 for i := 0; i <= count; i++ { 364 wg.Add(1) 365 func(i int) { 366 defer wg.Done() 367 if i == count { 368 //KCP 369 testEnv := &envtest.Environment{ 370 CRDDirectoryPaths: []string{"testdata/crds/kyma.yaml"}, 371 } 372 cfg, err := testEnv.Start() 373 if err != nil { 374 e.logs.Errorf("%e", err) 375 return 376 } 377 k8sClient, err := client.New(cfg, client.Options{}) 378 if err != nil { 379 e.logs.Errorf("%e", err) 380 return 381 } 382 e.kcp = k8sClient 383 384 namespace := &apicorev1.Namespace{} 385 namespace.ObjectMeta = metav1.ObjectMeta{Name: kcpNamespace} 386 err = e.kcp.Create(context.Background(), namespace) 387 if err != nil { 388 e.logs.Errorf("%e", err) 389 return 390 } 391 } else { 392 //SKR 393 testEnv := &envtest.Environment{} 394 _, err := testEnv.Start() 395 if err != nil { 396 e.logs.Errorf("%e", err) 397 return 398 } 399 tempSkrs = append(tempSkrs, testEnv) 400 } 401 }(i) 402 } 403 wg.Wait() 404 e.skrs = append(e.skrs, tempSkrs...) 405 require.Equal(e.t, len(e.skrs), count) 406 require.NotNil(e.t, e.kcp) 407 } 408 409 func (e *Environment) createInstance(kubeConfig string, credentials *internal.ServiceManagerOperatorCredentials, clusterId string) (string, string) { 410 instanceId, err := uuid2.NewUUID() 411 require.NoError(e.t, err) 412 413 runtimeId := "" 414 reconcilable := false 415 if kubeConfig != "" && clusterId != "" { 416 runtimeUUID, err := uuid2.NewUUID() 417 require.NoError(e.t, err) 418 runtimeId = runtimeUUID.String() 419 e.createKubeConfigSecret(kubeConfig, runtimeId) 420 reconcilable = true 421 } 422 423 instance := &internal.Instance{ 424 InstanceID: instanceId.String(), 425 RuntimeID: runtimeId, 426 InstanceDetails: internal.InstanceDetails{ 427 ServiceManagerClusterID: clusterId, 428 }, 429 Parameters: internal.ProvisioningParameters{ 430 ErsContext: internal.ERSContext{ 431 SMOperatorCredentials: credentials, 432 }, 433 Parameters: internal.ProvisioningParametersDTO{ 434 Kubeconfig: kubeConfig, 435 }, 436 }, 437 } 438 instance.Reconcilable = reconcilable 439 440 err = e.kebDb.Instances().Insert(*instance) 441 require.NoError(e.t, err) 442 return instanceId.String(), runtimeId 443 } 444 445 func (e *Environment) createKyma(runtimeId, instanceId string) { 446 u := &unstructured.Unstructured{} 447 u.SetGroupVersionKind(KymaGvk) 448 u.SetNamespace(kcpNamespace) 449 u.SetName(runtimeId) 450 labels := make(map[string]string, 1) 451 labels[instanceIdLabel] = instanceId 452 u.SetLabels(labels) 453 err := e.kcp.Create(e.ctx, u) 454 require.NoError(e.t, err) 455 } 456 457 func (e *Environment) createKubeConfigSecret(cfg, runtimeId string) { 458 secret := &apicorev1.Secret{ 459 TypeMeta: metav1.TypeMeta{Kind: "Secret"}, 460 ObjectMeta: metav1.ObjectMeta{ 461 Name: getKubeConfigSecretName(runtimeId), 462 Namespace: kcpNamespace, 463 }, 464 Data: map[string][]byte{ 465 "config": []byte(cfg), 466 }, 467 Type: apicorev1.SecretTypeOpaque, 468 } 469 err := e.kcp.Create(e.ctx, secret) 470 require.NoError(e.t, err) 471 } 472 473 func (e *Environment) changeSecret(restCfg *rest.Config) { 474 skrSecret := e.getSecretFromSkr(restCfg) 475 newCredentials := generateServiceManagerCredentials() 476 skrSecret.Data[secretClientSecret] = []byte(newCredentials.ClientSecret) 477 skrSecret.Data[secretSmUrl] = []byte(newCredentials.ServiceManagerURL) 478 skrSecret.Data[secretTokenUrl] = []byte(newCredentials.URL) 479 skrSecret.Data[secretClusterId] = []byte(generateRandomText(credentialsLen)) 480 skrSecret.Data[secretClientId] = []byte(newCredentials.ClientID) 481 e.updateSecretToSkr(restCfg, skrSecret) 482 } 483 484 func (e *Environment) getSecretFromSkr(restCfg *rest.Config) *apicorev1.Secret { 485 skrClient, err := client.New(restCfg, client.Options{}) 486 require.NoError(e.t, err) 487 skrSecret := &apicorev1.Secret{} 488 err = skrClient.Get(context.Background(), client.ObjectKey{Name: BtpManagerSecretName, Namespace: BtpManagerSecretNamespace}, skrSecret) 489 if err != nil && errors.IsNotFound(err) { 490 return nil 491 } 492 require.NoError(e.t, err) 493 return skrSecret 494 } 495 496 func (e *Environment) updateSecretToSkr(restCfg *rest.Config, secret *apicorev1.Secret) { 497 skrClient, err := client.New(restCfg, client.Options{}) 498 require.NoError(e.t, err) 499 err = skrClient.Update(context.Background(), secret) 500 require.NoError(e.t, err) 501 } 502 503 func (e *Environment) getSkrsForSimulateChange(skrIndexes []int) []*envtest.Environment { 504 var result []*envtest.Environment 505 if skrIndexes == nil || len(skrIndexes) == 0 { 506 indexSet := map[int]struct{}{} 507 for { 508 if len(indexSet) == changedInstancesCount { 509 break 510 } 511 random := rand.Intn(expectedTakenInstancesCount) 512 _, ok := indexSet[random] 513 if !ok { 514 indexSet[random] = struct{}{} 515 } 516 } 517 518 for index, _ := range indexSet { 519 testEnv := e.skrs[index] 520 result = append(result, testEnv) 521 } 522 } else { 523 for _, index := range skrIndexes { 524 testEnv := e.skrs[index] 525 result = append(result, testEnv) 526 } 527 } 528 return result 529 } 530 531 func (e *Environment) simulateSecretChangeOnSkr(skrs []*envtest.Environment) { 532 for _, skr := range skrs { 533 e.changeSecret(skr.Config) 534 } 535 } 536 537 func (e *Environment) findRuntimeIdForSkr(host string) string { 538 value, ok := e.skrRuntimeId[host] 539 require.True(e.t, ok) 540 return value 541 } 542 543 func (e *Environment) assertAllSecretsNotExists() { 544 for _, skr := range e.skrs { 545 skrSecret := e.getSecretFromSkr(skr.Config) 546 require.Nil(e.t, skrSecret) 547 } 548 } 549 550 func (e *Environment) assertAllSecretsExists() { 551 for _, skr := range e.skrs { 552 skrSecret := e.getSecretFromSkr(skr.Config) 553 require.NotNil(e.t, skrSecret) 554 } 555 } 556 557 func (e *Environment) assertAllSecretDataAreSet() { 558 for _, skr := range e.skrs { 559 skrSecret := e.getSecretFromSkr(skr.Config) 560 require.NotNil(e.t, skrSecret) 561 562 require.NotEmpty(e.t, getString(skrSecret.Data, secretClientId)) 563 require.NotEmpty(e.t, getString(skrSecret.Data, secretClientSecret)) 564 require.NotEmpty(e.t, getString(skrSecret.Data, secretSmUrl)) 565 require.NotEmpty(e.t, getString(skrSecret.Data, secretTokenUrl)) 566 require.NotEmpty(e.t, getString(skrSecret.Data, secretClusterId)) 567 568 } 569 } 570 571 func (e *Environment) assureConsistency() { 572 takenInstances, err := e.manager.GetReconcileCandidates() 573 require.NoError(e.t, err) 574 require.Equal(e.t, expectedTakenInstancesCount, len(takenInstances)) 575 576 for _, instance := range takenInstances { 577 skrK8sCfg, credentials := []byte(instance.Parameters.Parameters.Kubeconfig), instance.Parameters.ErsContext.SMOperatorCredentials 578 restCfg, err := clientcmd.RESTConfigFromKubeConfig(skrK8sCfg) 579 require.NoError(e.t, err) 580 skrSecret := e.getSecretFromSkr(restCfg) 581 require.NotNil(e.t, skrSecret) 582 583 require.Equal(e.t, getString(skrSecret.Data, secretClientId), credentials.ClientID) 584 require.Equal(e.t, getString(skrSecret.Data, secretClientSecret), credentials.ClientSecret) 585 require.Equal(e.t, getString(skrSecret.Data, secretSmUrl), credentials.ServiceManagerURL) 586 require.Equal(e.t, getString(skrSecret.Data, secretTokenUrl), credentials.URL) 587 require.Equal(e.t, getString(skrSecret.Data, secretClusterId), instance.InstanceDetails.ServiceManagerClusterID) 588 } 589 } 590 591 func (e *Environment) assureThatClusterIsInIncorrectState() int { 592 takenInstances, err := e.manager.GetReconcileCandidates() 593 require.NoError(e.t, err) 594 require.Equal(e.t, expectedTakenInstancesCount, len(takenInstances)) 595 596 incorrectClusters := 0 597 for _, instance := range takenInstances { 598 require.NoError(e.t, err) 599 skrK8sCfg, credentials := []byte(instance.Parameters.Parameters.Kubeconfig), instance.Parameters.ErsContext.SMOperatorCredentials 600 restCfg, err := clientcmd.RESTConfigFromKubeConfig(skrK8sCfg) 601 require.NoError(e.t, err) 602 skrSecret := e.getSecretFromSkr(restCfg) 603 require.NotNil(e.t, skrSecret) 604 605 if getString(skrSecret.Data, secretClientSecret) != credentials.ClientSecret { 606 incorrectClusters++ 607 continue 608 } 609 if getString(skrSecret.Data, secretClientId) != credentials.ClientID { 610 incorrectClusters++ 611 continue 612 } 613 if getString(skrSecret.Data, secretTokenUrl) != credentials.URL { 614 incorrectClusters++ 615 continue 616 } 617 if getString(skrSecret.Data, secretClusterId) != instance.InstanceDetails.ServiceManagerClusterID { 618 incorrectClusters++ 619 continue 620 } 621 } 622 623 return incorrectClusters 624 } 625 626 func (e *Environment) assertThatCorrectNumberOfInstancesExists() { 627 instances, _, _, err := e.kebDb.Instances().List(dbmodel.InstanceFilter{}) 628 require.NoError(e.t, err) 629 require.Equal(e.t, expectedAllInstancesCount, len(instances)) 630 } 631 632 func restConfigToString(restConfig rest.Config) string { 633 bytes, err := clientcmd.Write(api.Config{ 634 Clusters: map[string]*api.Cluster{ 635 "default": { 636 Server: restConfig.Host, 637 InsecureSkipTLSVerify: restConfig.Insecure, 638 CertificateAuthorityData: restConfig.CAData, 639 }, 640 }, 641 Contexts: map[string]*api.Context{ 642 "default": { 643 Cluster: "default", 644 AuthInfo: "default", 645 }, 646 }, 647 AuthInfos: map[string]*api.AuthInfo{ 648 "default": { 649 ClientCertificateData: restConfig.CertData, 650 ClientKeyData: restConfig.KeyData, 651 Token: restConfig.BearerToken, 652 Username: restConfig.Username, 653 Password: restConfig.Password, 654 }, 655 }, 656 CurrentContext: "default", 657 }) 658 if err != nil { 659 return "" 660 } else { 661 return string(bytes) 662 } 663 } 664 665 func generateServiceManagerCredentials() *internal.ServiceManagerOperatorCredentials { 666 return &internal.ServiceManagerOperatorCredentials{ 667 ClientID: generateRandomText(credentialsLen), 668 ClientSecret: generateRandomText(credentialsLen), 669 ServiceManagerURL: generateRandomText(credentialsLen), 670 URL: generateRandomText(credentialsLen), 671 XSAppName: generateRandomText(credentialsLen), 672 } 673 } 674 675 func generateRandomText(count int) string { 676 letterRunes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 677 runes := make([]rune, count) 678 for i := range runes { 679 runes[i] = letterRunes[random.Intn(len(letterRunes))] 680 } 681 return string(runes) 682 } 683 684 func max(slice []int) int { 685 max := 0 686 for _, v := range slice { 687 if v > max { 688 max = v 689 } 690 } 691 return max 692 } 693 694 func getString(m map[string][]byte, key string) string { 695 value, ok := m[key] 696 if !ok { 697 return "" 698 } 699 return string(value) 700 }