github.com/kyma-project/kyma-environment-broker@v0.0.1/cmd/broker/broker_suite_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "io" 9 "net/http" 10 "net/http/httptest" 11 "path" 12 "reflect" 13 "sort" 14 "testing" 15 "time" 16 17 corev1 "k8s.io/api/core/v1" 18 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 19 20 "code.cloudfoundry.org/lager" 21 "github.com/google/uuid" 22 "github.com/gorilla/mux" 23 reconcilerApi "github.com/kyma-incubator/reconciler/pkg/keb" 24 "github.com/kyma-project/control-plane/components/provisioner/pkg/gqlschema" 25 "github.com/kyma-project/kyma-environment-broker/common/director" 26 "github.com/kyma-project/kyma-environment-broker/common/gardener" 27 "github.com/kyma-project/kyma-environment-broker/common/orchestration" 28 "github.com/kyma-project/kyma-environment-broker/internal" 29 "github.com/kyma-project/kyma-environment-broker/internal/avs" 30 "github.com/kyma-project/kyma-environment-broker/internal/broker" 31 kebConfig "github.com/kyma-project/kyma-environment-broker/internal/config" 32 "github.com/kyma-project/kyma-environment-broker/internal/edp" 33 "github.com/kyma-project/kyma-environment-broker/internal/event" 34 "github.com/kyma-project/kyma-environment-broker/internal/fixture" 35 "github.com/kyma-project/kyma-environment-broker/internal/ias" 36 "github.com/kyma-project/kyma-environment-broker/internal/notification" 37 kebOrchestration "github.com/kyma-project/kyma-environment-broker/internal/orchestration" 38 orchestrate "github.com/kyma-project/kyma-environment-broker/internal/orchestration/handlers" 39 "github.com/kyma-project/kyma-environment-broker/internal/process" 40 "github.com/kyma-project/kyma-environment-broker/internal/process/input" 41 "github.com/kyma-project/kyma-environment-broker/internal/process/provisioning" 42 "github.com/kyma-project/kyma-environment-broker/internal/process/update" 43 "github.com/kyma-project/kyma-environment-broker/internal/process/upgrade_cluster" 44 "github.com/kyma-project/kyma-environment-broker/internal/process/upgrade_kyma" 45 "github.com/kyma-project/kyma-environment-broker/internal/provisioner" 46 "github.com/kyma-project/kyma-environment-broker/internal/reconciler" 47 kebRuntime "github.com/kyma-project/kyma-environment-broker/internal/runtime" 48 "github.com/kyma-project/kyma-environment-broker/internal/runtimeoverrides" 49 "github.com/kyma-project/kyma-environment-broker/internal/runtimeversion" 50 "github.com/kyma-project/kyma-environment-broker/internal/storage" 51 "github.com/pivotal-cf/brokerapi/v8/domain" 52 "github.com/pivotal-cf/brokerapi/v8/domain/apiresponses" 53 "github.com/pkg/errors" 54 "github.com/sirupsen/logrus" 55 "github.com/stretchr/testify/assert" 56 "github.com/stretchr/testify/require" 57 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 58 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 59 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 60 "k8s.io/apimachinery/pkg/runtime/schema" 61 "k8s.io/client-go/dynamic" 62 "sigs.k8s.io/controller-runtime/pkg/client" 63 "sigs.k8s.io/controller-runtime/pkg/client/fake" 64 ) 65 66 const fixedGardenerNamespace = "garden-test" 67 68 const ( 69 btpOperatorGroup = "services.cloud.sap.com" 70 btpOperatorApiVer = "v1" 71 btpOperatorServiceInstance = "ServiceInstance" 72 btpOperatorServiceBinding = "ServiceBinding" 73 instanceName = "my-service-instance" 74 bindingName = "my-binding" 75 kymaNamespace = "kyma-system" 76 ) 77 78 var ( 79 serviceBindingGvk = schema.GroupVersionKind{ 80 Group: btpOperatorGroup, 81 Version: btpOperatorApiVer, 82 Kind: btpOperatorServiceBinding, 83 } 84 serviceInstanceGvk = schema.GroupVersionKind{ 85 Group: btpOperatorGroup, 86 Version: btpOperatorApiVer, 87 Kind: btpOperatorServiceInstance, 88 } 89 ) 90 91 // BrokerSuiteTest is a helper which allows to write simple tests of any KEB processes (provisioning, deprovisioning, update). 92 // The starting point of a test could be an HTTP call to Broker API. 93 type BrokerSuiteTest struct { 94 db storage.BrokerStorage 95 provisionerClient *provisioner.FakeClient 96 directorClient *director.FakeClient 97 reconcilerClient *reconciler.FakeClient 98 gardenerClient dynamic.Interface 99 100 httpServer *httptest.Server 101 router *mux.Router 102 103 t *testing.T 104 inputBuilderFactory input.CreatorForPlan 105 106 componentProvider componentProviderDecorated 107 108 k8sKcp client.Client 109 k8sSKR client.Client 110 111 poller broker.Poller 112 } 113 114 type componentProviderDecorated struct { 115 componentProvider input.ComponentListProvider 116 decorator map[string]internal.KymaComponent 117 } 118 119 func (s componentProviderDecorated) AllComponents(kymaVersion internal.RuntimeVersionData, config *internal.ConfigForPlan) ([]internal.KymaComponent, error) { 120 all, err := s.componentProvider.AllComponents(kymaVersion, config) 121 for i, c := range all { 122 if dc, found := s.decorator[c.Name]; found { 123 all[i] = dc 124 } 125 } 126 return all, err 127 } 128 129 func (s *BrokerSuiteTest) TearDown() { 130 s.httpServer.Close() 131 } 132 133 func NewBrokerSuiteTest(t *testing.T, version ...string) *BrokerSuiteTest { 134 ctx := context.Background() 135 sch := internal.NewSchemeForTests() 136 apiextensionsv1.AddToScheme(sch) 137 additionalKymaVersions := []string{"1.19", "1.20", "main", "2.0"} 138 additionalKymaVersions = append(additionalKymaVersions, version...) 139 cli := fake.NewClientBuilder().WithScheme(sch).WithRuntimeObjects(fixK8sResources(defaultKymaVer, additionalKymaVersions)...).Build() 140 cfg := fixConfig() 141 if len(version) == 1 { 142 cfg.KymaVersion = version[0] // overriden to 143 } 144 145 optionalComponentsDisablers := kebRuntime.ComponentsDisablers{} 146 optComponentsSvc := kebRuntime.NewOptionalComponentsService(optionalComponentsDisablers) 147 148 disabledComponentsProvider := kebRuntime.NewDisabledComponentsProvider() 149 150 installerYAML := kebRuntime.ReadYAMLFromFile(t, "kyma-installer-cluster.yaml") 151 componentsYAML := kebRuntime.ReadYAMLFromFile(t, "kyma-components.yaml") 152 fakeHTTPClient := kebRuntime.NewTestClient(t, installerYAML, componentsYAML, http.StatusOK) 153 154 configProvider := kebConfig.NewConfigProvider( 155 kebConfig.NewConfigMapReader(ctx, cli, logrus.New(), defaultKymaVer), 156 kebConfig.NewConfigMapKeysValidator(), 157 kebConfig.NewConfigMapConverter()) 158 159 componentListProvider := kebRuntime.NewComponentsListProvider( 160 path.Join("testdata", "managed-runtime-components.yaml"), 161 path.Join("testdata", "additional-runtime-components.yaml")).WithHTTPClient(fakeHTTPClient) 162 decoratedComponentListProvider := componentProviderDecorated{ 163 componentProvider: componentListProvider, 164 decorator: make(map[string]internal.KymaComponent), 165 } 166 167 inputFactory, err := input.NewInputBuilderFactory(optComponentsSvc, disabledComponentsProvider, decoratedComponentListProvider, 168 configProvider, input.Config{ 169 MachineImageVersion: "253", 170 KubernetesVersion: "1.18", 171 MachineImage: "coreos", 172 URL: "http://localhost", 173 DefaultGardenerShootPurpose: "testing", 174 DefaultTrialProvider: internal.AWS, 175 }, defaultKymaVer, map[string]string{"cf-eu10": "europe", "cf-us10": "us"}, cfg.FreemiumProviders, defaultOIDCValues()) 176 177 db := storage.NewMemoryStorage() 178 179 require.NoError(t, err) 180 181 logs := logrus.New() 182 logs.SetLevel(logrus.DebugLevel) 183 184 gardenerClient := gardener.NewDynamicFakeClient() 185 186 provisionerClient := provisioner.NewFakeClientWithGardener(gardenerClient, "kcp-system") 187 eventBroker := event.NewPubSub(logs) 188 189 runtimeOverrides := runtimeoverrides.NewRuntimeOverrides(ctx, cli) 190 accountVersionMapping := runtimeversion.NewAccountVersionMapping(ctx, cli, cfg.VersionConfig.Namespace, cfg.VersionConfig.Name, logs) 191 runtimeVerConfigurator := runtimeversion.NewRuntimeVersionConfigurator(cfg.KymaVersion, accountVersionMapping, nil) 192 193 directorClient := director.NewFakeClient() 194 avsDel, externalEvalCreator, internalEvalAssistant, externalEvalAssistant := createFakeAvsDelegator(t, db, cfg) 195 196 iasFakeClient := ias.NewFakeClient() 197 reconcilerClient := reconciler.NewFakeClient() 198 bundleBuilder := ias.NewBundleBuilder(iasFakeClient, cfg.IAS) 199 edpClient := edp.NewFakeClient() 200 accountProvider := fixAccountProvider() 201 require.NoError(t, err) 202 203 fakeK8sSKRClient := fake.NewClientBuilder().WithScheme(sch).Build() 204 provisionManager := process.NewStagedManager(db.Operations(), eventBroker, cfg.OperationTimeout, cfg.Provisioning, logs.WithField("provisioning", "manager")) 205 provisioningQueue := NewProvisioningProcessingQueue(context.Background(), provisionManager, workersAmount, cfg, db, provisionerClient, inputFactory, 206 avsDel, internalEvalAssistant, externalEvalCreator, runtimeVerConfigurator, runtimeOverrides, 207 edpClient, accountProvider, reconcilerClient, fakeK8sClientProvider(fakeK8sSKRClient), cli, logs) 208 209 provisioningQueue.SpeedUp(10000) 210 provisionManager.SpeedUp(10000) 211 212 updateManager := process.NewStagedManager(db.Operations(), eventBroker, time.Hour, cfg.Update, logs) 213 rvc := runtimeversion.NewRuntimeVersionConfigurator(cfg.KymaVersion, nil, db.RuntimeStates()) 214 updateQueue := NewUpdateProcessingQueue(context.Background(), updateManager, 1, db, inputFactory, provisionerClient, 215 eventBroker, rvc, db.RuntimeStates(), decoratedComponentListProvider, reconcilerClient, *cfg, fakeK8sClientProvider(fakeK8sSKRClient), cli, logs) 216 updateQueue.SpeedUp(10000) 217 updateManager.SpeedUp(10000) 218 219 deprovisionManager := process.NewStagedManager(db.Operations(), eventBroker, time.Hour, cfg.Deprovisioning, logs.WithField("deprovisioning", "manager")) 220 deprovisioningQueue := NewDeprovisioningProcessingQueue(ctx, workersAmount, deprovisionManager, cfg, db, eventBroker, 221 provisionerClient, avsDel, internalEvalAssistant, externalEvalAssistant, 222 bundleBuilder, edpClient, accountProvider, reconcilerClient, fakeK8sClientProvider(fakeK8sSKRClient), fakeK8sSKRClient, configProvider, logs, 223 ) 224 deprovisionManager.SpeedUp(10000) 225 226 deprovisioningQueue.SpeedUp(10000) 227 228 ts := &BrokerSuiteTest{ 229 db: db, 230 provisionerClient: provisionerClient, 231 directorClient: directorClient, 232 reconcilerClient: reconcilerClient, 233 gardenerClient: gardenerClient, 234 router: mux.NewRouter(), 235 t: t, 236 inputBuilderFactory: inputFactory, 237 componentProvider: decoratedComponentListProvider, 238 k8sKcp: cli, 239 k8sSKR: fakeK8sSKRClient, 240 poller: &broker.DefaultPoller{PollInterval: 3 * time.Millisecond, PollTimeout: 2 * time.Second}, 241 } 242 243 ts.CreateAPI(inputFactory, cfg, db, provisioningQueue, deprovisioningQueue, updateQueue, logs) 244 245 notificationFakeClient := notification.NewFakeClient() 246 notificationBundleBuilder := notification.NewBundleBuilder(notificationFakeClient, cfg.Notification) 247 248 upgradeEvaluationManager := avs.NewEvaluationManager(avsDel, avs.Config{}) 249 runtimeLister := kebOrchestration.NewRuntimeLister(db.Instances(), db.Operations(), kebRuntime.NewConverter(defaultRegion), logs) 250 runtimeResolver := orchestration.NewGardenerRuntimeResolver(gardenerClient, fixedGardenerNamespace, runtimeLister, logs) 251 kymaQueue := NewKymaOrchestrationProcessingQueue(ctx, db, runtimeOverrides, provisionerClient, eventBroker, inputFactory, &upgrade_kyma.TimeSchedule{ 252 Retry: 10 * time.Millisecond, 253 StatusCheck: 100 * time.Millisecond, 254 UpgradeKymaTimeout: 4 * time.Second, 255 }, 250*time.Millisecond, runtimeVerConfigurator, runtimeResolver, upgradeEvaluationManager, cfg, avs.NewInternalEvalAssistant(cfg.Avs), reconcilerClient, notificationBundleBuilder, logs, cli, 1000) 256 257 clusterQueue := NewClusterOrchestrationProcessingQueue(ctx, db, provisionerClient, eventBroker, inputFactory, &upgrade_cluster.TimeSchedule{ 258 Retry: 10 * time.Millisecond, 259 StatusCheck: 100 * time.Millisecond, 260 UpgradeClusterTimeout: 4 * time.Second, 261 }, 250*time.Millisecond, runtimeResolver, upgradeEvaluationManager, notificationBundleBuilder, logs, cli, *cfg, 1000) 262 263 kymaQueue.SpeedUp(1000) 264 clusterQueue.SpeedUp(1000) 265 266 // TODO: in case of cluster upgrade the same Azure Zones must be send to the Provisioner 267 orchestrationHandler := orchestrate.NewOrchestrationHandler(db, kymaQueue, clusterQueue, cfg.MaxPaginationPage, logs) 268 orchestrationHandler.AttachRoutes(ts.router) 269 ts.httpServer = httptest.NewServer(ts.router) 270 return ts 271 } 272 273 func fakeK8sClientProvider(k8sCli client.Client) func(s string) (client.Client, error) { 274 return func(s string) (client.Client, error) { 275 return k8sCli, nil 276 } 277 } 278 279 func defaultOIDCValues() internal.OIDCConfigDTO { 280 return internal.OIDCConfigDTO{ 281 ClientID: "client-id-oidc", 282 GroupsClaim: "groups", 283 IssuerURL: "https://issuer.url", 284 SigningAlgs: []string{"RS256"}, 285 UsernameClaim: "sub", 286 UsernamePrefix: "-", 287 } 288 } 289 290 func defaultOIDCConfig() *gqlschema.OIDCConfigInput { 291 return &gqlschema.OIDCConfigInput{ 292 ClientID: defaultOIDCValues().ClientID, 293 GroupsClaim: defaultOIDCValues().GroupsClaim, 294 IssuerURL: defaultOIDCValues().IssuerURL, 295 SigningAlgs: defaultOIDCValues().SigningAlgs, 296 UsernameClaim: defaultOIDCValues().UsernameClaim, 297 UsernamePrefix: defaultOIDCValues().UsernamePrefix, 298 } 299 } 300 301 func (s *BrokerSuiteTest) ChangeDefaultTrialProvider(provider internal.CloudProvider) { 302 s.inputBuilderFactory.(*input.InputBuilderFactory).SetDefaultTrialProvider(provider) 303 } 304 305 func (s *BrokerSuiteTest) CallAPI(method string, path string, body string) *http.Response { 306 cli := s.httpServer.Client() 307 req, err := http.NewRequest(method, fmt.Sprintf("%s/%s", s.httpServer.URL, path), bytes.NewBuffer([]byte(body))) 308 req.Header.Set("X-Broker-API-Version", "2.15") 309 require.NoError(s.t, err) 310 311 resp, err := cli.Do(req) 312 require.NoError(s.t, err) 313 return resp 314 } 315 316 func (s *BrokerSuiteTest) CreateAPI(inputFactory broker.PlanValidator, cfg *Config, db storage.BrokerStorage, provisioningQueue *process.Queue, deprovisionQueue *process.Queue, updateQueue *process.Queue, logs logrus.FieldLogger) { 317 servicesConfig := map[string]broker.Service{ 318 broker.KymaServiceName: { 319 Description: "", 320 Metadata: broker.ServiceMetadata{ 321 DisplayName: "kyma", 322 SupportUrl: "https://kyma-project.io", 323 }, 324 Plans: map[string]broker.PlanData{ 325 broker.AzurePlanID: { 326 Description: broker.AzurePlanName, 327 Metadata: broker.PlanMetadata{}, 328 }, 329 broker.AWSPlanName: { 330 Description: broker.AWSPlanName, 331 Metadata: broker.PlanMetadata{}, 332 }, 333 }, 334 }, 335 } 336 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 337 return &gqlschema.ClusterConfigInput{}, nil 338 } 339 createAPI(s.router, servicesConfig, inputFactory, cfg, db, provisioningQueue, deprovisionQueue, updateQueue, lager.NewLogger("api"), logs, planDefaults) 340 341 s.httpServer = httptest.NewServer(s.router) 342 } 343 344 func createFakeAvsDelegator(t *testing.T, db storage.BrokerStorage, cfg *Config) (*avs.Delegator, *provisioning.ExternalEvalCreator, *avs.InternalEvalAssistant, *avs.ExternalEvalAssistant) { 345 server := avs.NewMockAvsServer(t) 346 mockServer := avs.FixMockAvsServer(server) 347 avsConfig := avs.Config{ 348 OauthTokenEndpoint: fmt.Sprintf("%s/oauth/token", mockServer.URL), 349 ApiEndpoint: fmt.Sprintf("%s/api/v2/evaluationmetadata", mockServer.URL), 350 } 351 client, err := avs.NewClient(context.TODO(), avsConfig, logrus.New()) 352 assert.NoError(t, err) 353 avsDel := avs.NewDelegator(client, avsConfig, db.Operations()) 354 externalEvalAssistant := avs.NewExternalEvalAssistant(cfg.Avs) 355 internalEvalAssistant := avs.NewInternalEvalAssistant(cfg.Avs) 356 externalEvalCreator := provisioning.NewExternalEvalCreator(avsDel, cfg.Avs.Disabled, externalEvalAssistant) 357 358 return avsDel, externalEvalCreator, internalEvalAssistant, externalEvalAssistant 359 } 360 361 func (s *BrokerSuiteTest) CreateProvisionedRuntime(options RuntimeOptions) string { 362 randomInstanceId := uuid.New().String() 363 364 instance := fixture.FixInstance(randomInstanceId) 365 instance.GlobalAccountID = options.ProvideGlobalAccountID() 366 instance.SubAccountID = options.ProvideSubAccountID() 367 instance.InstanceDetails.SubAccountID = options.ProvideSubAccountID() 368 instance.Parameters.PlatformRegion = options.ProvidePlatformRegion() 369 instance.Parameters.Parameters.Region = options.ProvideRegion() 370 instance.ProviderRegion = *options.ProvideRegion() 371 372 provisioningOperation := fixture.FixProvisioningOperation(operationID, randomInstanceId) 373 374 require.NoError(s.t, s.db.Instances().Insert(instance)) 375 require.NoError(s.t, s.db.Operations().InsertOperation(provisioningOperation)) 376 377 return instance.InstanceID 378 } 379 380 func (s *BrokerSuiteTest) WaitForProvisioningState(operationID string, state domain.LastOperationState) { 381 var op *internal.ProvisioningOperation 382 err := s.poller.Invoke(func() (done bool, err error) { 383 op, err = s.db.Operations().GetProvisioningOperationByID(operationID) 384 if err != nil { 385 return false, nil 386 } 387 return op.State == state, nil 388 }) 389 assert.NoError(s.t, err, "timeout waiting for the operation expected state %s. The existing operation %+v", state, op) 390 } 391 392 func (s *BrokerSuiteTest) WaitForOperationState(operationID string, state domain.LastOperationState) { 393 var op *internal.Operation 394 err := s.poller.Invoke(func() (done bool, err error) { 395 op, err = s.db.Operations().GetOperationByID(operationID) 396 if err != nil { 397 return false, nil 398 } 399 return op.State == state, nil 400 }) 401 assert.NoError(s.t, err, "timeout waiting for the operation expected state %s != %s. The existing operation %+v", state, op.State, op) 402 } 403 404 func (s *BrokerSuiteTest) WaitForLastOperation(iid string, state domain.LastOperationState) string { 405 var op *internal.Operation 406 err := s.poller.Invoke(func() (done bool, err error) { 407 op, _ = s.db.Operations().GetLastOperation(iid) 408 return op.State == state, nil 409 }) 410 assert.NoError(s.t, err, "timeout waiting for the operation expected state %s. The existing operation %+v", state, op) 411 412 return op.ID 413 } 414 415 func (s *BrokerSuiteTest) LastOperation(iid string) *internal.Operation { 416 op, _ := s.db.Operations().GetLastOperation(iid) 417 return op 418 } 419 420 func (s *BrokerSuiteTest) FinishProvisioningOperationByProvisioner(operationID string, operationState gqlschema.OperationState) { 421 var op *internal.ProvisioningOperation 422 err := s.poller.Invoke(func() (done bool, err error) { 423 op, _ = s.db.Operations().GetProvisioningOperationByID(operationID) 424 if op.RuntimeID != "" { 425 return true, nil 426 } 427 return false, nil 428 }) 429 assert.NoError(s.t, err, "timeout waiting for the operation with runtimeID. The existing operation %+v", op) 430 431 s.finishOperationByProvisioner(gqlschema.OperationTypeProvision, operationState, op.RuntimeID) 432 } 433 434 func (s *BrokerSuiteTest) FailProvisioningOperationByProvisioner(operationID string) { 435 var op *internal.ProvisioningOperation 436 err := s.poller.Invoke(func() (done bool, err error) { 437 op, _ = s.db.Operations().GetProvisioningOperationByID(operationID) 438 if op.RuntimeID != "" { 439 return true, nil 440 } 441 return false, nil 442 }) 443 assert.NoError(s.t, err, "timeout waiting for the operation with runtimeID. The existing operation %+v", op) 444 445 s.finishOperationByProvisioner(gqlschema.OperationTypeProvision, gqlschema.OperationStateFailed, op.RuntimeID) 446 } 447 448 func (s *BrokerSuiteTest) FailDeprovisioningOperationByProvisioner(operationID string) { 449 var op *internal.DeprovisioningOperation 450 err := s.poller.Invoke(func() (done bool, err error) { 451 op, _ = s.db.Operations().GetDeprovisioningOperationByID(operationID) 452 if op.RuntimeID != "" { 453 return true, nil 454 } 455 return false, nil 456 }) 457 assert.NoError(s.t, err, "timeout waiting for the operation with runtimeID. The existing operation %+v", op) 458 459 s.finishOperationByProvisioner(gqlschema.OperationTypeDeprovision, gqlschema.OperationStateFailed, op.RuntimeID) 460 } 461 462 func (s *BrokerSuiteTest) FinishDeprovisioningOperationByProvisioner(operationID string) { 463 var op *internal.DeprovisioningOperation 464 err := s.poller.Invoke(func() (done bool, err error) { 465 op, err = s.db.Operations().GetDeprovisioningOperationByID(operationID) 466 if err != nil { 467 return false, nil 468 } 469 if op.RuntimeID != "" { 470 return true, nil 471 } 472 return false, nil 473 }) 474 assert.NoError(s.t, err, "timeout waiting for the operation with runtimeID. The existing operation %+v", op) 475 476 err = s.gardenerClient.Resource(gardener.ShootResource). 477 Namespace(fixedGardenerNamespace). 478 Delete(context.Background(), op.ShootName, v1.DeleteOptions{}) 479 require.NoError(s.t, err) 480 481 s.finishOperationByProvisioner(gqlschema.OperationTypeDeprovision, gqlschema.OperationStateSucceeded, op.RuntimeID) 482 } 483 484 func (s *BrokerSuiteTest) FinishUpdatingOperationByProvisioner(operationID string) { 485 var op *internal.Operation 486 err := s.poller.Invoke(func() (done bool, err error) { 487 op, _ = s.db.Operations().GetOperationByID(operationID) 488 if op.RuntimeID == "" { 489 return false, nil 490 } 491 if op.ProvisionerOperationID == "" { 492 return false, nil 493 } 494 return true, nil 495 }) 496 assert.NoError(s.t, err, "timeout waiting for the operation with runtimeID. The existing operation %+v", op) 497 s.finishOperationByOpIDByProvisioner(gqlschema.OperationTypeUpgradeShoot, gqlschema.OperationStateSucceeded, op.ID) 498 } 499 500 func (s *BrokerSuiteTest) FinishDeprovisioningOperationByProvisionerForGivenOpId(operationID string) { 501 var op *internal.DeprovisioningOperation 502 err := s.poller.Invoke(func() (done bool, err error) { 503 op, err = s.db.Operations().GetDeprovisioningOperationByID(operationID) 504 if err != nil { 505 return false, nil 506 } 507 if op.RuntimeID != "" && op.ProvisionerOperationID != "" { 508 return true, nil 509 } 510 return false, nil 511 }) 512 assert.NoError(s.t, err, "timeout waiting for the operation with runtimeID. The existing operation %+v", op) 513 514 err = s.gardenerClient.Resource(gardener.ShootResource). 515 Namespace(fixedGardenerNamespace). 516 Delete(context.Background(), op.ShootName, v1.DeleteOptions{}) 517 require.NoError(s.t, err) 518 519 s.finishOperationByOpIDByProvisioner(gqlschema.OperationTypeDeprovision, gqlschema.OperationStateSucceeded, op.ID) 520 } 521 522 func (s *BrokerSuiteTest) finishOperationByProvisioner(operationType gqlschema.OperationType, state gqlschema.OperationState, runtimeID string) { 523 err := s.poller.Invoke(func() (bool, error) { 524 status := s.provisionerClient.FindOperationByRuntimeIDAndType(runtimeID, operationType) 525 if status.ID != nil { 526 s.provisionerClient.FinishProvisionerOperation(*status.ID, state) 527 return true, nil 528 } 529 return false, nil 530 }) 531 assert.NoError(s.t, err, "timeout waiting for provisioner operation to exist") 532 } 533 534 func (s *BrokerSuiteTest) finishOperationByOpIDByProvisioner(operationType gqlschema.OperationType, state gqlschema.OperationState, operationID string) { 535 err := s.poller.Invoke(func() (bool, error) { 536 op, err := s.db.Operations().GetOperationByID(operationID) 537 if err != nil { 538 s.Log(fmt.Sprintf("failed to GetOperationsByID: %v", err)) 539 return false, nil 540 } 541 status, err := s.provisionerClient.RuntimeOperationStatus("", op.ProvisionerOperationID) 542 if err != nil { 543 s.Log(fmt.Sprintf("failed to get RuntimeOperationStatus: %v", err)) 544 return false, nil 545 } 546 if status.Operation != operationType { 547 s.Log(fmt.Sprintf("operation types don't match, expected: %s, actual: %s", operationType.String(), status.Operation.String())) 548 return false, nil 549 } 550 if status.ID != nil { 551 s.provisionerClient.FinishProvisionerOperation(*status.ID, state) 552 return true, nil 553 } 554 return false, nil 555 }) 556 assert.NoError(s.t, err, "timeout waiting for provisioner operation to exist") 557 } 558 559 func (s *BrokerSuiteTest) MarkClustertConfigurationDeleted(iid string) { 560 op, _ := s.db.Operations().GetDeprovisioningOperationByInstanceID(iid) 561 s.reconcilerClient.ChangeClusterState(op.RuntimeID, op.ClusterConfigurationVersion, reconcilerApi.StatusDeleted) 562 } 563 564 func (s *BrokerSuiteTest) RemoveFromReconcilerByInstanceID(iid string) { 565 op, _ := s.db.Operations().GetDeprovisioningOperationByInstanceID(iid) 566 s.reconcilerClient.DeleteCluster(op.RuntimeID) 567 } 568 569 func (s *BrokerSuiteTest) FinishProvisioningOperationByReconciler(operationID string) { 570 // wait until ProvisioningOperation reaches CreateRuntime step 571 var provisioningOp *internal.ProvisioningOperation 572 err := s.poller.Invoke(func() (bool, error) { 573 op, err := s.db.Operations().GetProvisioningOperationByID(operationID) 574 if err != nil { 575 return false, nil 576 } 577 if op.ProvisionerOperationID != "" || broker.IsOwnClusterPlan(op.ProvisioningParameters.PlanID) { 578 provisioningOp = op 579 return true, nil 580 } 581 return false, nil 582 }) 583 assert.NoError(s.t, err) 584 585 var state *reconcilerApi.HTTPClusterResponse 586 err = s.poller.Invoke(func() (bool, error) { 587 state, err = s.reconcilerClient.GetCluster(provisioningOp.RuntimeID, provisioningOp.ClusterConfigurationVersion) 588 if err != nil { 589 return false, err 590 } 591 if state.Cluster != "" { 592 s.reconcilerClient.ChangeClusterState(provisioningOp.RuntimeID, provisioningOp.ClusterConfigurationVersion, reconcilerApi.StatusReady) 593 return true, nil 594 } 595 return false, nil 596 }) 597 assert.NoError(s.t, err) 598 } 599 600 func (s *BrokerSuiteTest) FailProvisioningOperationByReconciler(operationID string) { 601 // wait until ProvisioningOperation reaches CreateRuntime step 602 var provisioningOp *internal.ProvisioningOperation 603 err := s.poller.Invoke(func() (bool, error) { 604 op, err := s.db.Operations().GetProvisioningOperationByID(operationID) 605 if err != nil { 606 return false, nil 607 } 608 if op.ProvisionerOperationID != "" || broker.IsOwnClusterPlan(op.ProvisioningParameters.PlanID) { 609 provisioningOp = op 610 return true, nil 611 } 612 return false, nil 613 }) 614 assert.NoError(s.t, err) 615 616 var state *reconcilerApi.HTTPClusterResponse 617 err = s.poller.Invoke(func() (bool, error) { 618 state, err = s.reconcilerClient.GetCluster(provisioningOp.RuntimeID, provisioningOp.ClusterConfigurationVersion) 619 if err != nil { 620 return false, err 621 } 622 if state.Cluster != "" { 623 s.reconcilerClient.ChangeClusterState(provisioningOp.RuntimeID, provisioningOp.ClusterConfigurationVersion, reconcilerApi.StatusError) 624 return true, nil 625 } 626 return false, nil 627 }) 628 assert.NoError(s.t, err) 629 } 630 631 func (s *BrokerSuiteTest) FinishReconciliation(opID string) { 632 var state *reconcilerApi.HTTPClusterResponse 633 err := s.poller.Invoke(func() (bool, error) { 634 provisioningOp, err := s.db.Operations().GetProvisioningOperationByID(opID) 635 if err != nil { 636 return false, nil 637 } 638 state, err = s.reconcilerClient.GetCluster(provisioningOp.RuntimeID, provisioningOp.ClusterConfigurationVersion) 639 if err != nil { 640 return false, nil 641 } 642 if state.Cluster != "" { 643 s.reconcilerClient.ChangeClusterState(provisioningOp.RuntimeID, provisioningOp.ClusterConfigurationVersion, reconcilerApi.StatusReady) 644 return true, nil 645 } 646 return false, nil 647 }) 648 assert.NoError(s.t, err) 649 } 650 651 func (s *BrokerSuiteTest) FinishDeprovisioningByReconciler(opID string) { 652 653 err := s.poller.Invoke(func() (bool, error) { 654 op, err := s.db.Operations().GetDeprovisioningOperationByID(opID) 655 if err != nil { 656 return false, nil 657 } 658 _, err = s.reconcilerClient.GetCluster(op.RuntimeID, op.ClusterConfigurationVersion) 659 if err != nil { 660 return false, err 661 } 662 s.reconcilerClient.ChangeClusterState(op.RuntimeID, op.ClusterConfigurationVersion, reconcilerApi.StatusDeleted) 663 return true, nil 664 }) 665 assert.NoError(s.t, err) 666 } 667 668 func (s *BrokerSuiteTest) FailDeprovisioningByReconciler(opID string) { 669 670 err := s.poller.Invoke(func() (bool, error) { 671 op, err := s.db.Operations().GetDeprovisioningOperationByID(opID) 672 if err != nil { 673 return false, nil 674 } 675 _, err = s.reconcilerClient.GetCluster(op.RuntimeID, op.ClusterConfigurationVersion) 676 if err != nil { 677 return false, err 678 } 679 s.reconcilerClient.ChangeClusterState(op.RuntimeID, op.ClusterConfigurationVersion, reconcilerApi.StatusDeleteError) 680 return true, nil 681 }) 682 assert.NoError(s.t, err) 683 } 684 685 func (s *BrokerSuiteTest) FinishUpdatingOperationByReconciler(operationID string) { 686 op, err := s.db.Operations().GetOperationByID(operationID) 687 assert.NoError(s.t, err) 688 var state *reconcilerApi.HTTPClusterResponse 689 err = s.poller.Invoke(func() (bool, error) { 690 state, err = s.reconcilerClient.GetCluster(op.RuntimeID, op.ClusterConfigurationVersion) 691 if err != nil { 692 return false, err 693 } 694 if state.Cluster != "" { 695 s.reconcilerClient.ChangeClusterState(op.RuntimeID, op.ClusterConfigurationVersion, reconcilerApi.StatusReady) 696 return true, nil 697 } 698 return false, nil 699 }) 700 assert.NoError(s.t, err) 701 } 702 703 func (s *BrokerSuiteTest) AssertProvisionerStartedProvisioning(operationID string) { 704 // wait until ProvisioningOperation reaches CreateRuntime step 705 var provisioningOp *internal.ProvisioningOperation 706 err := s.poller.Invoke(func() (bool, error) { 707 op, err := s.db.Operations().GetProvisioningOperationByID(operationID) 708 if err != nil { 709 return false, nil 710 } 711 if op.ProvisionerOperationID != "" { 712 provisioningOp = op 713 return true, nil 714 } 715 return false, nil 716 }) 717 assert.NoError(s.t, err) 718 719 var status gqlschema.OperationStatus 720 err = s.poller.Invoke(func() (bool, error) { 721 status = s.provisionerClient.FindOperationByRuntimeIDAndType(provisioningOp.RuntimeID, gqlschema.OperationTypeProvision) 722 if status.ID != nil { 723 return true, nil 724 } 725 return false, nil 726 }) 727 assert.NoError(s.t, err) 728 assert.Equal(s.t, gqlschema.OperationStateInProgress, status.State) 729 } 730 731 func (s *BrokerSuiteTest) FinishUpgradeKymaOperationByReconciler(operationID string) { 732 var upgradeOp *internal.UpgradeKymaOperation 733 err := s.poller.Invoke(func() (bool, error) { 734 op, err := s.db.Operations().GetUpgradeKymaOperationByID(operationID) 735 if err != nil { 736 return false, nil 737 } 738 if op.ClusterConfigurationVersion != 0 { 739 upgradeOp = op 740 return true, nil 741 } 742 return false, nil 743 }) 744 assert.NoError(s.t, err) 745 746 var state *reconcilerApi.HTTPClusterResponse 747 err = s.poller.Invoke(func() (bool, error) { 748 state, err = s.reconcilerClient.GetCluster(upgradeOp.InstanceDetails.RuntimeID, upgradeOp.ClusterConfigurationVersion) 749 if err != nil { 750 return false, err 751 } 752 if state.Cluster != "" { 753 s.reconcilerClient.ChangeClusterState(upgradeOp.InstanceDetails.RuntimeID, upgradeOp.ClusterConfigurationVersion, reconcilerApi.StatusReady) 754 return true, nil 755 } 756 return false, nil 757 }) 758 assert.NoError(s.t, err) 759 } 760 761 func (s *BrokerSuiteTest) FinishUpgradeClusterOperationByProvisioner(operationID string) { 762 var upgradeOp *internal.UpgradeClusterOperation 763 err := s.poller.Invoke(func() (bool, error) { 764 op, err := s.db.Operations().GetUpgradeClusterOperationByID(operationID) 765 if err != nil { 766 return false, nil 767 } 768 upgradeOp = op 769 return true, nil 770 }) 771 assert.NoError(s.t, err) 772 773 s.finishOperationByOpIDByProvisioner(gqlschema.OperationTypeUpgradeShoot, gqlschema.OperationStateSucceeded, upgradeOp.Operation.ID) 774 } 775 776 func (s *BrokerSuiteTest) AssertReconcilerStartedReconcilingWhenProvisioning(provisioningOpID string) { 777 var provisioningOp *internal.ProvisioningOperation 778 err := s.poller.Invoke(func() (bool, error) { 779 op, err := s.db.Operations().GetProvisioningOperationByID(provisioningOpID) 780 if err != nil { 781 return false, nil 782 } 783 if op.ProvisionerOperationID != "" || broker.IsOwnClusterPlan(op.ProvisioningParameters.PlanID) { 784 provisioningOp = op 785 return true, nil 786 } 787 return false, nil 788 }) 789 assert.NoError(s.t, err) 790 791 var state *reconcilerApi.HTTPClusterResponse 792 err = s.poller.Invoke(func() (bool, error) { 793 state, err = s.reconcilerClient.GetCluster(provisioningOp.RuntimeID, 1) 794 if state.Cluster != "" { 795 return true, nil 796 } 797 return false, nil 798 }) 799 assert.NoError(s.t, err) 800 assert.Equal(s.t, reconcilerApi.StatusReconcilePending, state.Status) 801 } 802 803 func (s *BrokerSuiteTest) AssertReconcilerStartedReconcilingWhenUpgrading(opID string) { 804 // wait until UpgradeOperation reaches Apply_Cluster_Configuration step 805 var upgradeKymaOp *internal.UpgradeKymaOperation 806 err := s.poller.Invoke(func() (bool, error) { 807 op, err := s.db.Operations().GetUpgradeKymaOperationByID(opID) 808 upgradeKymaOp = op 809 return err == nil && op != nil, nil 810 }) 811 assert.NoError(s.t, err) 812 813 var state *reconcilerApi.HTTPClusterResponse 814 err = s.poller.Invoke(func() (bool, error) { 815 fmt.Println(upgradeKymaOp) 816 state, err := s.reconcilerClient.GetCluster(upgradeKymaOp.InstanceDetails.RuntimeID, upgradeKymaOp.InstanceDetails.ClusterConfigurationVersion) 817 if err != nil { 818 return false, err 819 } 820 if state.Cluster != "" { 821 return true, nil 822 } 823 return false, nil 824 }) 825 assert.NoError(s.t, err) 826 assert.Equal(s.t, reconcilerApi.StatusReconcilePending, state.Status) 827 } 828 829 func (s *BrokerSuiteTest) DecodeErrorResponse(resp *http.Response) apiresponses.ErrorResponse { 830 m, err := io.ReadAll(resp.Body) 831 defer resp.Body.Close() 832 require.NoError(s.t, err) 833 834 r := apiresponses.ErrorResponse{} 835 err = json.Unmarshal(m, &r) 836 require.NoError(s.t, err) 837 838 return r 839 } 840 841 func (s *BrokerSuiteTest) DecodeOperationID(resp *http.Response) string { 842 m, err := io.ReadAll(resp.Body) 843 s.Log(string(m)) 844 require.NoError(s.t, err) 845 var provisioningResp struct { 846 Operation string `json:"operation"` 847 } 848 err = json.Unmarshal(m, &provisioningResp) 849 require.NoError(s.t, err) 850 851 return provisioningResp.Operation 852 } 853 854 func (s *BrokerSuiteTest) DecodeOrchestrationID(resp *http.Response) string { 855 m, err := io.ReadAll(resp.Body) 856 s.Log(string(m)) 857 require.NoError(s.t, err) 858 var upgradeResponse orchestration.UpgradeResponse 859 err = json.Unmarshal(m, &upgradeResponse) 860 require.NoError(s.t, err) 861 862 return upgradeResponse.OrchestrationID 863 } 864 865 func (s *BrokerSuiteTest) DecodeLastUpgradeKymaOperationFromOrchestration(resp *http.Response) (*orchestration.OperationResponse, error) { 866 m, err := io.ReadAll(resp.Body) 867 s.Log(string(m)) 868 require.NoError(s.t, err) 869 var operationsList orchestration.OperationResponseList 870 err = json.Unmarshal(m, &operationsList) 871 require.NoError(s.t, err) 872 873 if operationsList.TotalCount == 0 || len(operationsList.Data) == 0 { 874 return nil, errors.New("no operations found for given orchestration") 875 } 876 877 return &operationsList.Data[len(operationsList.Data)-1], nil 878 } 879 880 func (s *BrokerSuiteTest) DecodeLastUpgradeKymaOperationIDFromOrchestration(resp *http.Response) (string, error) { 881 operation, err := s.DecodeLastUpgradeKymaOperationFromOrchestration(resp) 882 if err == nil { 883 return operation.OperationID, err 884 } else { 885 return "", err 886 } 887 } 888 889 func (s *BrokerSuiteTest) DecodeLastUpgradeClusterOperationIDFromOrchestration(orchestrationID string) (string, error) { 890 var operationsList orchestration.OperationResponseList 891 err := s.poller.Invoke(func() (bool, error) { 892 resp := s.CallAPI("GET", fmt.Sprintf("orchestrations/%s/operations", orchestrationID), "") 893 m, err := io.ReadAll(resp.Body) 894 s.Log(string(m)) 895 if err != nil { 896 return false, fmt.Errorf("failed to read response body: %v", err) 897 } 898 operationsList = orchestration.OperationResponseList{} 899 err = json.Unmarshal(m, &operationsList) 900 if err != nil { 901 return false, fmt.Errorf("failed to marshal: %v", err) 902 } 903 if operationsList.TotalCount == 0 || len(operationsList.Data) == 0 { 904 return false, nil 905 } 906 return true, nil 907 }) 908 require.NoError(s.t, err) 909 if operationsList.TotalCount == 0 || len(operationsList.Data) == 0 { 910 return "", errors.New("no operations found for given orchestration") 911 } 912 913 return operationsList.Data[len(operationsList.Data)-1].OperationID, nil 914 } 915 916 func (s *BrokerSuiteTest) AssertShootUpgrade(operationID string, config gqlschema.UpgradeShootInput) { 917 // wait until the operation reaches the call to a Provisioner (provisioner operation ID is stored) 918 var provisioningOp *internal.Operation 919 err := s.poller.Invoke(func() (bool, error) { 920 op, err := s.db.Operations().GetOperationByID(operationID) 921 assert.NoError(s.t, err) 922 if op.ProvisionerOperationID != "" || broker.IsOwnClusterPlan(op.ProvisioningParameters.PlanID) { 923 provisioningOp = op 924 return true, nil 925 } 926 return false, nil 927 }) 928 require.NoError(s.t, err) 929 930 var shootUpgrade gqlschema.UpgradeShootInput 931 var found bool 932 err = s.poller.Invoke(func() (bool, error) { 933 shootUpgrade, found = s.provisionerClient.LastShootUpgrade(provisioningOp.RuntimeID) 934 if found { 935 return true, nil 936 } 937 return false, nil 938 }) 939 require.NoError(s.t, err) 940 941 assert.Equal(s.t, config, shootUpgrade) 942 } 943 944 func (s *BrokerSuiteTest) AssertInstanceRuntimeAdmins(instanceId string, expectedAdmins []string) { 945 var instance *internal.Instance 946 err := s.poller.Invoke(func() (bool, error) { 947 instance = s.GetInstance(instanceId) 948 if instance != nil { 949 return true, nil 950 } 951 return false, nil 952 }) 953 assert.NoError(s.t, err) 954 assert.Equal(s.t, expectedAdmins, instance.Parameters.Parameters.RuntimeAdministrators) 955 } 956 957 func (s *BrokerSuiteTest) fetchProvisionInput() gqlschema.ProvisionRuntimeInput { 958 input := s.provisionerClient.GetLatestProvisionRuntimeInput() 959 return input 960 } 961 962 func (s *BrokerSuiteTest) AssertProvider(expectedProvider string) { 963 input := s.fetchProvisionInput() 964 assert.Equal(s.t, expectedProvider, input.ClusterConfig.GardenerConfig.Provider) 965 } 966 967 func (s *BrokerSuiteTest) AssertProvisionRuntimeInputWithoutKymaConfig() { 968 input := s.fetchProvisionInput() 969 assert.Nil(s.t, input.KymaConfig) 970 } 971 972 func (s *BrokerSuiteTest) AssertClusterState(operationID string, expectedState reconcilerApi.HTTPClusterResponse) { 973 var provisioningOp *internal.ProvisioningOperation 974 err := s.poller.Invoke(func() (bool, error) { 975 op, err := s.db.Operations().GetProvisioningOperationByID(operationID) 976 assert.NoError(s.t, err) 977 if op.ProvisionerOperationID != "" { 978 provisioningOp = op 979 return true, nil 980 } 981 return false, nil 982 }) 983 assert.NoError(s.t, err) 984 985 var state *reconcilerApi.HTTPClusterResponse 986 err = s.poller.Invoke(func() (bool, error) { 987 state, err = s.reconcilerClient.GetLatestCluster(provisioningOp.RuntimeID) 988 if err == nil { 989 return true, nil 990 } 991 return false, err 992 }) 993 assert.NoError(s.t, err) 994 995 assert.Equal(s.t, expectedState, state) 996 } 997 998 func (s *BrokerSuiteTest) AssertClusterConfig(operationID string, expectedClusterConfig *reconcilerApi.Cluster) { 999 clusterConfig := s.getClusterConfig(operationID) 1000 1001 assert.Equal(s.t, *expectedClusterConfig, clusterConfig) 1002 } 1003 1004 func (s *BrokerSuiteTest) AssertClusterKymaConfig(operationID string, expectedKymaConfig reconcilerApi.KymaConfig) { 1005 clusterConfig := s.getClusterConfig(operationID) 1006 1007 // values in arrays need to be sorted, because globalOverrides are coming from a map and map's elements' order is not deterministic 1008 for _, component := range clusterConfig.KymaConfig.Components { 1009 sort.Slice(component.Configuration, func(i, j int) bool { 1010 return component.Configuration[i].Key < component.Configuration[j].Key 1011 }) 1012 } 1013 for _, component := range expectedKymaConfig.Components { 1014 sort.Slice(component.Configuration, func(i, j int) bool { 1015 return component.Configuration[i].Key < component.Configuration[j].Key 1016 }) 1017 } 1018 1019 assert.Equal(s.t, expectedKymaConfig, clusterConfig.KymaConfig) 1020 } 1021 1022 func (s *BrokerSuiteTest) AssertComponent(a, b reconcilerApi.Component) { 1023 sort.Slice(a.Configuration, func(i, j int) bool { return a.Configuration[i].Key < a.Configuration[j].Key }) 1024 sort.Slice(b.Configuration, func(i, j int) bool { return b.Configuration[i].Key < b.Configuration[j].Key }) 1025 assert.Equal(s.t, a, b) 1026 } 1027 1028 func (s *BrokerSuiteTest) AssertClusterConfigWithKubeconfig(id string) { 1029 clusterConfig := s.getClusterConfig(id) 1030 1031 assert.NotEmpty(s.t, clusterConfig.Kubeconfig) 1032 } 1033 1034 func (s *BrokerSuiteTest) AssertClusterMetadata(id string, metadata reconcilerApi.Metadata) { 1035 clusterConfig := s.getClusterConfig(id) 1036 1037 assert.Equal(s.t, metadata, clusterConfig.Metadata) 1038 } 1039 1040 func (s *BrokerSuiteTest) AssertDisabledNetworkFilterForProvisioning(val *bool) { 1041 var got, exp string 1042 err := s.poller.Invoke(func() (bool, error) { 1043 input := s.provisionerClient.GetLatestProvisionRuntimeInput() 1044 gc := input.ClusterConfig.GardenerConfig 1045 if reflect.DeepEqual(val, gc.ShootNetworkingFilterDisabled) { 1046 return true, nil 1047 } 1048 got = "<nil>" 1049 if gc.ShootNetworkingFilterDisabled != nil { 1050 got = fmt.Sprintf("%v", *gc.ShootNetworkingFilterDisabled) 1051 } 1052 exp = "<nil>" 1053 if val != nil { 1054 exp = fmt.Sprintf("%v", *val) 1055 } 1056 return false, nil 1057 }) 1058 if err != nil { 1059 err = fmt.Errorf("ShootNetworkingFilterDisabled expected %v, got %v", exp, got) 1060 } 1061 require.NoError(s.t, err) 1062 } 1063 1064 func (s *BrokerSuiteTest) AssertDisabledNetworkFilterRuntimeState(runtimeid, op string, val *bool) { 1065 var got, exp string 1066 err := s.poller.Invoke(func() (bool, error) { 1067 states, _ := s.db.RuntimeStates().ListByRuntimeID(runtimeid) 1068 exp = "<nil>" 1069 if val != nil { 1070 exp = fmt.Sprintf("%v", *val) 1071 } 1072 for _, rs := range states { 1073 if rs.OperationID != op { 1074 // skip runtime states for different operations 1075 continue 1076 } 1077 if rs.ClusterSetup != nil { 1078 // skip reconciler runtime states, the test is interested only in provisioner rs 1079 continue 1080 } 1081 if reflect.DeepEqual(val, rs.ClusterConfig.ShootNetworkingFilterDisabled) { 1082 return true, nil 1083 } 1084 got = "<nil>" 1085 if rs.ClusterConfig.ShootNetworkingFilterDisabled != nil { 1086 got = fmt.Sprintf("%v", *rs.ClusterConfig.ShootNetworkingFilterDisabled) 1087 } 1088 return false, nil 1089 } 1090 return false, nil 1091 }) 1092 if err != nil { 1093 err = fmt.Errorf("ShootNetworkingFilterDisabled expected %v, got %v", exp, got) 1094 } 1095 require.NoError(s.t, err) 1096 } 1097 1098 func (s *BrokerSuiteTest) getClusterConfig(operationID string) reconcilerApi.Cluster { 1099 provisioningOp, err := s.db.Operations().GetProvisioningOperationByID(operationID) 1100 assert.NoError(s.t, err) 1101 1102 var clusterConfig *reconcilerApi.Cluster 1103 err = s.poller.Invoke(func() (bool, error) { 1104 clusterConfig, err = s.reconcilerClient.LastClusterConfig(provisioningOp.RuntimeID) 1105 if err != nil { 1106 return false, err 1107 } 1108 if clusterConfig.RuntimeID != "" { 1109 return true, nil 1110 } 1111 return false, nil 1112 }) 1113 require.NoError(s.t, err) 1114 1115 return *clusterConfig 1116 } 1117 1118 func (s *BrokerSuiteTest) LastProvisionInput(iid string) gqlschema.ProvisionRuntimeInput { 1119 // wait until the operation reaches the call to a Provisioner (provisioner operation ID is stored) 1120 err := s.poller.Invoke(func() (bool, error) { 1121 op, err := s.db.Operations().GetProvisioningOperationByInstanceID(iid) 1122 assert.NoError(s.t, err) 1123 if op.ProvisionerOperationID != "" { 1124 return true, nil 1125 } 1126 return false, nil 1127 }) 1128 assert.NoError(s.t, err) 1129 return s.provisionerClient.LastProvisioning() 1130 } 1131 1132 func (s *BrokerSuiteTest) Log(msg string) { 1133 s.t.Log(msg) 1134 } 1135 1136 func (s *BrokerSuiteTest) EnableDumpingProvisionerRequests() { 1137 s.provisionerClient.EnableRequestDumping() 1138 } 1139 1140 func (s *BrokerSuiteTest) GetInstance(iid string) *internal.Instance { 1141 inst, err := s.db.Instances().GetByID(iid) 1142 require.NoError(s.t, err) 1143 return inst 1144 } 1145 1146 func (s *BrokerSuiteTest) processProvisioningByOperationID(opID string) { 1147 s.WaitForProvisioningState(opID, domain.InProgress) 1148 s.AssertProvisionerStartedProvisioning(opID) 1149 1150 s.FinishProvisioningOperationByProvisioner(opID, gqlschema.OperationStateSucceeded) 1151 _, err := s.gardenerClient.Resource(gardener.ShootResource).Namespace(fixedGardenerNamespace).Create(context.Background(), s.fixGardenerShootForOperationID(opID), v1.CreateOptions{}) 1152 require.NoError(s.t, err) 1153 1154 // provisioner finishes the operation 1155 s.WaitForOperationState(opID, domain.Succeeded) 1156 } 1157 1158 func (s *BrokerSuiteTest) processUpdatingByOperationID(opID string) { 1159 s.WaitForProvisioningState(opID, domain.InProgress) 1160 1161 s.FinishUpdatingOperationByProvisioner(opID) 1162 1163 // provisioner finishes the operation 1164 s.WaitForOperationState(opID, domain.Succeeded) 1165 } 1166 1167 func (s *BrokerSuiteTest) failProvisioningByOperationID(opID string) { 1168 s.WaitForProvisioningState(opID, domain.InProgress) 1169 s.AssertProvisionerStartedProvisioning(opID) 1170 1171 s.FinishProvisioningOperationByProvisioner(opID, gqlschema.OperationStateFailed) 1172 1173 // provisioner finishes the operation 1174 s.WaitForOperationState(opID, domain.Failed) 1175 } 1176 1177 func (s *BrokerSuiteTest) fixGardenerShootForOperationID(opID string) *unstructured.Unstructured { 1178 op, err := s.db.Operations().GetProvisioningOperationByID(opID) 1179 require.NoError(s.t, err) 1180 1181 un := unstructured.Unstructured{ 1182 Object: map[string]interface{}{ 1183 "metadata": map[string]interface{}{ 1184 "name": op.ShootName, 1185 "namespace": fixedGardenerNamespace, 1186 "labels": map[string]interface{}{ 1187 globalAccountLabel: op.ProvisioningParameters.ErsContext.GlobalAccountID, 1188 subAccountLabel: op.ProvisioningParameters.ErsContext.SubAccountID, 1189 }, 1190 "annotations": map[string]interface{}{ 1191 runtimeIDAnnotation: op.RuntimeID, 1192 }, 1193 }, 1194 "spec": map[string]interface{}{ 1195 "region": "eu", 1196 "maintenance": map[string]interface{}{ 1197 "timeWindow": map[string]interface{}{ 1198 "begin": "030000+0000", 1199 "end": "040000+0000", 1200 }, 1201 }, 1202 }, 1203 }, 1204 } 1205 un.SetGroupVersionKind(shootGVK) 1206 return &un 1207 } 1208 1209 func (s *BrokerSuiteTest) processProvisioningAndReconcilingByOperationID(opID string) { 1210 // Provisioner part 1211 s.WaitForProvisioningState(opID, domain.InProgress) 1212 s.AssertProvisionerStartedProvisioning(opID) 1213 s.FinishProvisioningOperationByProvisioner(opID, gqlschema.OperationStateSucceeded) 1214 _, err := s.gardenerClient.Resource(gardener.ShootResource).Namespace(fixedGardenerNamespace).Create(context.Background(), s.fixGardenerShootForOperationID(opID), v1.CreateOptions{}) 1215 require.NoError(s.t, err) 1216 1217 // Reconciler part 1218 s.processReconcilingByOperationID(opID) 1219 } 1220 1221 func (s *BrokerSuiteTest) processReconcilingByOperationID(opID string) { 1222 // Reconciler part 1223 s.AssertReconcilerStartedReconcilingWhenProvisioning(opID) 1224 s.FinishProvisioningOperationByReconciler(opID) 1225 1226 s.WaitForOperationState(opID, domain.Succeeded) 1227 } 1228 1229 func (s *BrokerSuiteTest) processProvisioningAndFailReconcilingByOperationID(opID string) { 1230 // Provisioner part 1231 s.WaitForProvisioningState(opID, domain.InProgress) 1232 s.AssertProvisionerStartedProvisioning(opID) 1233 s.FinishProvisioningOperationByProvisioner(opID, gqlschema.OperationStateSucceeded) 1234 _, err := s.gardenerClient.Resource(gardener.ShootResource).Namespace(fixedGardenerNamespace).Create(context.Background(), s.fixGardenerShootForOperationID(opID), v1.CreateOptions{}) 1235 require.NoError(s.t, err) 1236 1237 // Reconciler part 1238 s.failReconcilingByOperationID(opID) 1239 } 1240 1241 func (s *BrokerSuiteTest) failReconcilingByOperationID(opID string) { 1242 s.AssertReconcilerStartedReconcilingWhenProvisioning(opID) 1243 s.FailProvisioningOperationByReconciler(opID) 1244 s.WaitForOperationState(opID, domain.Failed) 1245 } 1246 1247 func (s *BrokerSuiteTest) processProvisioningByInstanceID(iid string) { 1248 opID := s.WaitForLastOperation(iid, domain.InProgress) 1249 1250 s.processProvisioningByOperationID(opID) 1251 } 1252 1253 func (s *BrokerSuiteTest) processProvisioningAndReconciliationByInstanceID(iid string) { 1254 opID := s.WaitForLastOperation(iid, domain.InProgress) 1255 1256 s.processProvisioningAndReconcilingByOperationID(opID) 1257 } 1258 1259 func (s *BrokerSuiteTest) ShootName(id string) string { 1260 op, err := s.db.Operations().GetProvisioningOperationByID(id) 1261 require.NoError(s.t, err) 1262 return op.ShootName 1263 } 1264 1265 func (s *BrokerSuiteTest) AssertAWSRegionAndZone(region string) { 1266 input := s.provisionerClient.GetLatestProvisionRuntimeInput() 1267 assert.Equal(s.t, region, input.ClusterConfig.GardenerConfig.Region) 1268 assert.Contains(s.t, input.ClusterConfig.GardenerConfig.ProviderSpecificConfig.AwsConfig.AwsZones[0].Name, region) 1269 } 1270 1271 func (s *BrokerSuiteTest) AssertAzureRegion(region string) { 1272 input := s.provisionerClient.GetLatestProvisionRuntimeInput() 1273 assert.Equal(s.t, region, input.ClusterConfig.GardenerConfig.Region) 1274 } 1275 1276 // fixExpectedComponentListWithoutSMProxy provides a fixed components list for Service Management without BTP operator credentials provided 1277 func (s *BrokerSuiteTest) fixExpectedComponentListWithoutSMProxy(opID string) []reconcilerApi.Component { 1278 return []reconcilerApi.Component{ 1279 { 1280 URL: "", 1281 Component: "ory", 1282 Namespace: "kyma-system", 1283 Configuration: []reconcilerApi.Configuration{ 1284 { 1285 Key: "global.domainName", 1286 Value: fmt.Sprintf("%s.kyma.sap.com", s.ShootName(opID)), 1287 Secret: false, 1288 }, 1289 { 1290 Key: "foo", 1291 Value: "bar", 1292 Secret: false, 1293 }, 1294 { 1295 Key: "global.booleanOverride.enabled", 1296 Value: false, 1297 Secret: false, 1298 }, 1299 }, 1300 }, 1301 { 1302 URL: "", 1303 Component: "monitoring", 1304 Namespace: "kyma-system", 1305 Configuration: []reconcilerApi.Configuration{ 1306 { 1307 Key: "global.domainName", 1308 Value: fmt.Sprintf("%s.kyma.sap.com", s.ShootName(opID)), 1309 Secret: false, 1310 }, 1311 { 1312 Key: "foo", 1313 Value: "bar", 1314 Secret: false, 1315 }, 1316 { 1317 Key: "global.booleanOverride.enabled", 1318 Value: false, 1319 Secret: false, 1320 }, 1321 }, 1322 }, 1323 } 1324 } 1325 1326 // fixExpectedComponentListWithSMOperator provides a fixed components list for Service Management 2.0 - when `sm_operator_credentials` 1327 // object is provided: btp-opeartor component should be installed 1328 func (s *BrokerSuiteTest) fixExpectedComponentListWithSMOperator(opID, smClusterID string) []reconcilerApi.Component { 1329 return []reconcilerApi.Component{ 1330 { 1331 URL: "", 1332 Component: "ory", 1333 Namespace: "kyma-system", 1334 Configuration: []reconcilerApi.Configuration{ 1335 { 1336 Key: "global.domainName", 1337 Value: fmt.Sprintf("%s.kyma.sap.com", s.ShootName(opID)), 1338 Secret: false, 1339 }, 1340 { 1341 Key: "foo", 1342 Value: "bar", 1343 Secret: false, 1344 }, 1345 { 1346 Key: "global.booleanOverride.enabled", 1347 Value: false, 1348 Secret: false, 1349 }, 1350 }, 1351 }, 1352 { 1353 URL: "", 1354 Component: "monitoring", 1355 Namespace: "kyma-system", 1356 Configuration: []reconcilerApi.Configuration{ 1357 { 1358 Key: "global.domainName", 1359 Value: fmt.Sprintf("%s.kyma.sap.com", s.ShootName(opID)), 1360 Secret: false, 1361 }, 1362 { 1363 Key: "foo", 1364 Value: "bar", 1365 Secret: false, 1366 }, 1367 { 1368 Key: "global.booleanOverride.enabled", 1369 Value: false, 1370 Secret: false, 1371 }, 1372 }, 1373 }, 1374 { 1375 URL: "https://btp-operator", 1376 Component: "btp-operator", 1377 Namespace: "kyma-system", 1378 Configuration: []reconcilerApi.Configuration{ 1379 { 1380 Key: "global.domainName", 1381 Value: fmt.Sprintf("%s.kyma.sap.com", s.ShootName(opID)), 1382 Secret: false, 1383 }, 1384 { 1385 Key: "foo", 1386 Value: "bar", 1387 Secret: false, 1388 }, 1389 { 1390 Key: "global.booleanOverride.enabled", 1391 Value: false, 1392 Secret: false, 1393 }, 1394 { 1395 Key: "manager.secret.clientid", 1396 Value: "testClientID", 1397 Secret: true, 1398 }, 1399 { 1400 Key: "manager.secret.clientsecret", 1401 Value: "testClientSecret", 1402 Secret: true, 1403 }, 1404 { 1405 Key: "manager.secret.url", 1406 Value: "https://service-manager.kyma.com", 1407 Secret: false, 1408 }, 1409 { 1410 Key: "manager.secret.sm_url", 1411 Value: "https://service-manager.kyma.com", 1412 Secret: false, 1413 }, 1414 { 1415 Key: "manager.secret.tokenurl", 1416 Value: "https://test.auth.com", 1417 Secret: false, 1418 }, 1419 { 1420 Key: "cluster.id", 1421 Value: smClusterID, 1422 Secret: false, 1423 }, 1424 { 1425 Key: "manager.priorityClassName", 1426 Value: "kyma-system", 1427 }, 1428 }, 1429 }, 1430 } 1431 } 1432 1433 func (s *BrokerSuiteTest) AssertKymaResourceExists(opId string) { 1434 operation, err := s.db.Operations().GetOperationByID(opId) 1435 assert.NoError(s.t, err) 1436 1437 obj := &unstructured.Unstructured{} 1438 obj.SetName(operation.RuntimeID) 1439 obj.SetNamespace("kyma-system") 1440 obj.SetGroupVersionKind(schema.GroupVersionKind{ 1441 Group: "operator.kyma-project.io", 1442 Version: "v1beta2", 1443 Kind: "Kyma", 1444 }) 1445 1446 err = s.k8sKcp.Get(context.Background(), client.ObjectKeyFromObject(obj), obj) 1447 1448 assert.NoError(s.t, err) 1449 } 1450 1451 func (s *BrokerSuiteTest) AssertKymaAnnotationExists(opId, annotationName string) { 1452 operation, err := s.db.Operations().GetOperationByID(opId) 1453 assert.NoError(s.t, err) 1454 obj := &unstructured.Unstructured{} 1455 obj.SetName(operation.RuntimeID) 1456 obj.SetNamespace("kyma-system") 1457 obj.SetGroupVersionKind(schema.GroupVersionKind{ 1458 Group: "operator.kyma-project.io", 1459 Version: "v1beta2", 1460 Kind: "Kyma", 1461 }) 1462 1463 err = s.k8sKcp.Get(context.Background(), client.ObjectKeyFromObject(obj), obj) 1464 1465 assert.Contains(s.t, obj.GetAnnotations(), annotationName) 1466 } 1467 1468 func (s *BrokerSuiteTest) AssertKymaLabelsExist(opId string, expectedLabels map[string]string) { 1469 operation, err := s.db.Operations().GetOperationByID(opId) 1470 assert.NoError(s.t, err) 1471 obj := &unstructured.Unstructured{} 1472 obj.SetName(operation.RuntimeID) 1473 obj.SetNamespace("kyma-system") 1474 obj.SetGroupVersionKind(schema.GroupVersionKind{ 1475 Group: "operator.kyma-project.io", 1476 Version: "v1beta2", 1477 Kind: "Kyma", 1478 }) 1479 1480 err = s.k8sKcp.Get(context.Background(), client.ObjectKeyFromObject(obj), obj) 1481 1482 assert.Subset(s.t, obj.GetLabels(), expectedLabels) 1483 } 1484 1485 func (s *BrokerSuiteTest) AssertKymaLabelNotExists(opId string, notExpectedLabel string) { 1486 operation, err := s.db.Operations().GetOperationByID(opId) 1487 assert.NoError(s.t, err) 1488 obj := &unstructured.Unstructured{} 1489 obj.SetName(operation.RuntimeID) 1490 obj.SetNamespace("kyma-system") 1491 obj.SetGroupVersionKind(schema.GroupVersionKind{ 1492 Group: "operator.kyma-project.io", 1493 Version: "v1beta2", 1494 Kind: "Kyma", 1495 }) 1496 1497 err = s.k8sKcp.Get(context.Background(), client.ObjectKeyFromObject(obj), obj) 1498 1499 assert.NotContains(s.t, obj.GetLabels(), notExpectedLabel) 1500 } 1501 1502 func (s *BrokerSuiteTest) AssertSecretWithKubeconfigExists(opId string) { 1503 operation, err := s.db.Operations().GetOperationByID(opId) 1504 assert.NoError(s.t, err) 1505 secret := &corev1.Secret{ 1506 ObjectMeta: metav1.ObjectMeta{ 1507 Namespace: "kyma-system", 1508 Name: fmt.Sprintf("kubeconfig-%s", operation.RuntimeID), 1509 }, 1510 StringData: map[string]string{}, 1511 } 1512 err = s.k8sKcp.Get(context.Background(), client.ObjectKeyFromObject(secret), secret) 1513 1514 assert.NoError(s.t, err) 1515 1516 } 1517 1518 func (s *BrokerSuiteTest) fixServiceBindingAndInstances(t *testing.T) { 1519 createResource(t, serviceInstanceGvk, s.k8sSKR, kymaNamespace, instanceName) 1520 createResource(t, serviceBindingGvk, s.k8sSKR, kymaNamespace, bindingName) 1521 } 1522 1523 func (s *BrokerSuiteTest) assertServiceBindingAndInstancesAreRemoved(t *testing.T) { 1524 assertResourcesAreRemoved(t, serviceInstanceGvk, s.k8sSKR) 1525 assertResourcesAreRemoved(t, serviceBindingGvk, s.k8sSKR) 1526 } 1527 1528 func assertResourcesAreRemoved(t *testing.T, gvk schema.GroupVersionKind, k8sClient client.Client) { 1529 list := &unstructured.UnstructuredList{} 1530 list.SetGroupVersionKind(gvk) 1531 err := k8sClient.List(context.TODO(), list) 1532 assert.NoError(t, err) 1533 assert.Zero(t, len(list.Items)) 1534 } 1535 1536 func createResource(t *testing.T, gvk schema.GroupVersionKind, k8sClient client.Client, namespace string, name string) { 1537 object := &unstructured.Unstructured{} 1538 object.SetGroupVersionKind(gvk) 1539 object.SetNamespace(namespace) 1540 object.SetName(name) 1541 err := k8sClient.Create(context.TODO(), object) 1542 assert.NoError(t, err) 1543 } 1544 1545 func mockBTPOperatorClusterID() { 1546 mock := func(string) (string, error) { 1547 return "cluster_id", nil 1548 } 1549 update.ConfigMapGetter = mock 1550 upgrade_kyma.ConfigMapGetter = mock 1551 }