github.com/kyma-project/kyma-environment-broker@v0.0.1/cmd/broker/deprovisioning_suite_test.go (about) 1 package main 2 3 import ( 4 "context" 5 "encoding/base64" 6 "fmt" 7 "testing" 8 "time" 9 10 kebConfig "github.com/kyma-project/kyma-environment-broker/internal/config" 11 12 "github.com/kyma-project/kyma-environment-broker/internal/reconciler" 13 "github.com/kyma-project/kyma-environment-broker/internal/storage/dberr" 14 corev1 "k8s.io/api/core/v1" 15 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 16 "k8s.io/apimachinery/pkg/runtime" 17 "sigs.k8s.io/controller-runtime/pkg/client/fake" 18 19 "github.com/google/uuid" 20 "github.com/kyma-project/control-plane/components/provisioner/pkg/gqlschema" 21 "github.com/kyma-project/kyma-environment-broker/internal" 22 "github.com/kyma-project/kyma-environment-broker/internal/avs" 23 "github.com/kyma-project/kyma-environment-broker/internal/edp" 24 "github.com/kyma-project/kyma-environment-broker/internal/event" 25 "github.com/kyma-project/kyma-environment-broker/internal/fixture" 26 "github.com/kyma-project/kyma-environment-broker/internal/ias" 27 "github.com/kyma-project/kyma-environment-broker/internal/process" 28 "github.com/kyma-project/kyma-environment-broker/internal/provisioner" 29 "github.com/kyma-project/kyma-environment-broker/internal/storage" 30 "github.com/pivotal-cf/brokerapi/v8/domain" 31 "github.com/sirupsen/logrus" 32 "github.com/stretchr/testify/assert" 33 "github.com/stretchr/testify/require" 34 "k8s.io/apimachinery/pkg/util/wait" 35 ) 36 37 const ( 38 subAccountID = "fake-subaccount-id" 39 badSubAccountID = "bad-fake-subaccount-id" 40 edpEnvironment = "test" 41 ) 42 43 type DeprovisioningSuite struct { 44 provisionerClient *provisioner.FakeClient 45 deprovisioningQueue *process.Queue 46 storage storage.BrokerStorage 47 48 t *testing.T 49 } 50 51 func NewDeprovisioningSuite(t *testing.T) *DeprovisioningSuite { 52 ctx, _ := context.WithTimeout(context.Background(), 20*time.Minute) 53 54 logs := logrus.New() 55 logs.Formatter.(*logrus.TextFormatter).TimestampFormat = "15:04:05.000" 56 57 cfg := fixConfig() 58 cfg.EDP.Environment = edpEnvironment 59 60 db := storage.NewMemoryStorage() 61 eventBroker := event.NewPubSub(logs) 62 provisionerClient := provisioner.NewFakeClient() 63 64 server := avs.NewMockAvsServer(t) 65 mockServer := avs.FixMockAvsServer(server) 66 avsConfig := avs.Config{ 67 OauthTokenEndpoint: fmt.Sprintf("%s/oauth/token", mockServer.URL), 68 ApiEndpoint: fmt.Sprintf("%s/api/v2/evaluationmetadata", mockServer.URL), 69 } 70 client, err := avs.NewClient(context.TODO(), avsConfig, logrus.New()) 71 assert.NoError(t, err) 72 _, err = client.CreateEvaluation(&avs.BasicEvaluationCreateRequest{ 73 Name: "fake-evaluation", 74 }) 75 assert.NoError(t, err) 76 avsDel := avs.NewDelegator(client, avsConfig, db.Operations()) 77 externalEvalAssistant := avs.NewExternalEvalAssistant(cfg.Avs) 78 internalEvalAssistant := avs.NewInternalEvalAssistant(cfg.Avs) 79 80 iasFakeClient := ias.NewFakeClient() 81 bundleBuilder := ias.NewBundleBuilder(iasFakeClient, cfg.IAS) 82 83 edpClient := fixEDPClient() 84 reconcilerClient := reconciler.NewFakeClient() 85 86 accountProvider := fixAccountProvider() 87 88 deprovisionManager := process.NewStagedManager(db.Operations(), eventBroker, time.Minute, cfg.Deprovisioning, logs.WithField("deprovisioning", "manager")) 89 deprovisionManager.SpeedUp(1000) 90 scheme := runtime.NewScheme() 91 apiextensionsv1.AddToScheme(scheme) 92 corev1.AddToScheme(scheme) 93 fakeK8sSKRClient := fake.NewClientBuilder().WithScheme(scheme).Build() 94 95 sch := internal.NewSchemeForTests() 96 cli := fake.NewClientBuilder().WithScheme(sch).WithRuntimeObjects(fixK8sResources(defaultKymaVer, []string{})...).Build() 97 98 configProvider := kebConfig.NewConfigProvider( 99 kebConfig.NewConfigMapReader(ctx, cli, logrus.New(), defaultKymaVer), 100 kebConfig.NewConfigMapKeysValidator(), 101 kebConfig.NewConfigMapConverter()) 102 103 deprovisioningQueue := NewDeprovisioningProcessingQueue(ctx, workersAmount, deprovisionManager, cfg, db, eventBroker, 104 provisionerClient, avsDel, internalEvalAssistant, externalEvalAssistant, 105 bundleBuilder, edpClient, accountProvider, reconcilerClient, fakeK8sClientProvider(fakeK8sSKRClient), fakeK8sSKRClient, configProvider, logs, 106 ) 107 108 deprovisioningQueue.SpeedUp(10000) 109 110 return &DeprovisioningSuite{ 111 provisionerClient: provisionerClient, 112 deprovisioningQueue: deprovisioningQueue, 113 storage: db, 114 115 t: t, 116 } 117 } 118 119 func (s *DeprovisioningSuite) CreateProvisionedRuntime(options RuntimeOptions) string { 120 randomInstanceId := uuid.New().String() 121 122 instance := fixture.FixInstance(randomInstanceId) 123 instance.GlobalAccountID = options.ProvideGlobalAccountID() 124 instance.SubAccountID = options.ProvideSubAccountID() 125 instance.InstanceDetails.SubAccountID = options.ProvideSubAccountID() 126 instance.Parameters.PlatformRegion = options.ProvidePlatformRegion() 127 instance.Parameters.Parameters.Region = options.ProvideRegion() 128 instance.ProviderRegion = *options.ProvideRegion() 129 130 provisioningOperation := fixture.FixProvisioningOperation(operationID, randomInstanceId) 131 provisioningOperation.SubAccountID = options.ProvideSubAccountID() 132 133 require.NoError(s.t, s.storage.Instances().Insert(instance)) 134 require.NoError(s.t, s.storage.Operations().InsertOperation(provisioningOperation)) 135 136 state, err := s.provisionerClient.ProvisionRuntime(options.ProvideGlobalAccountID(), options.ProvideSubAccountID(), gqlschema.ProvisionRuntimeInput{}) 137 require.NoError(s.t, err) 138 139 s.finishProvisioningOperationByProvisioner(gqlschema.OperationTypeProvision, *state.RuntimeID) 140 141 return instance.InstanceID 142 } 143 144 func (s *DeprovisioningSuite) finishProvisioningOperationByProvisioner(operationType gqlschema.OperationType, runtimeID string) { 145 err := wait.Poll(pollingInterval, 2*time.Second, func() (bool, error) { 146 status := s.provisionerClient.FindOperationByRuntimeIDAndType(runtimeID, operationType) 147 if status.ID != nil { 148 s.provisionerClient.FinishProvisionerOperation(*status.ID, gqlschema.OperationStateSucceeded) 149 return true, nil 150 } 151 return false, nil 152 }) 153 assert.NoError(s.t, err, "timeout waiting for provisioner operation to exist") 154 } 155 156 func (s *DeprovisioningSuite) CreateDeprovisioning(operationID, instanceId string) string { 157 instance, err := s.storage.Instances().GetByID(instanceId) 158 require.NoError(s.t, err) 159 160 operation, err := internal.NewDeprovisioningOperationWithID(operationID, instance) 161 require.NoError(s.t, err) 162 163 operation.ProvisioningParameters.ErsContext.SubAccountID = subAccountID 164 165 err = s.storage.Operations().InsertDeprovisioningOperation(operation) 166 require.NoError(s.t, err) 167 168 s.deprovisioningQueue.Add(operation.ID) 169 170 return operation.ID 171 } 172 173 func (s *DeprovisioningSuite) WaitForDeprovisioningState(operationID string, state domain.LastOperationState) { 174 var op *internal.Operation 175 err := wait.PollImmediate(pollingInterval, 2*time.Second, func() (done bool, err error) { 176 op, _ = s.storage.Operations().GetOperationByID(operationID) 177 return op.State == state, nil 178 }) 179 assert.NoError(s.t, err, "timeout waiting for the operation expected state %s. %v The existing operation %+v", state, op.State, op) 180 } 181 182 func (s *DeprovisioningSuite) AssertProvisionerStartedDeprovisioning(operationID string) { 183 var provisionerOperationID string 184 err := wait.Poll(pollingInterval, 2*time.Second, func() (bool, error) { 185 op, err := s.storage.Operations().GetOperationByID(operationID) 186 assert.NoError(s.t, err) 187 if op.ProvisionerOperationID != "" { 188 provisionerOperationID = op.ProvisionerOperationID 189 return true, nil 190 } 191 return false, nil 192 }) 193 require.NoError(s.t, err) 194 195 var status gqlschema.OperationStatus 196 err = wait.Poll(pollingInterval, 2*time.Second, func() (bool, error) { 197 status = s.provisionerClient.FindOperationByProvisionerOperationID(provisionerOperationID) 198 if status.ID != nil { 199 return true, nil 200 } 201 return false, nil 202 }) 203 assert.NoError(s.t, err) 204 assert.Equal(s.t, gqlschema.OperationStateInProgress, status.State) 205 } 206 207 func (s *DeprovisioningSuite) FinishDeprovisioningOperationByProvisioner(operationID string) { 208 var op *internal.DeprovisioningOperation 209 err := wait.PollImmediate(pollingInterval, 2*time.Second, func() (done bool, err error) { 210 op, _ = s.storage.Operations().GetDeprovisioningOperationByID(operationID) 211 if op.RuntimeID != "" { 212 return true, nil 213 } 214 return false, nil 215 }) 216 assert.NoError(s.t, err, "timeout waiting for the operation with runtimeID. The existing operation %+v", op) 217 218 s.finishOperationByProvisioner(op.ProvisionerOperationID) 219 } 220 221 func (s *DeprovisioningSuite) finishOperationByProvisioner(provisionerOperationID string) { 222 err := wait.Poll(pollingInterval, 2*time.Second, func() (bool, error) { 223 status := s.provisionerClient.FindOperationByProvisionerOperationID(provisionerOperationID) 224 if status.ID != nil { 225 s.provisionerClient.FinishProvisionerOperation(*status.ID, gqlschema.OperationStateSucceeded) 226 return true, nil 227 } 228 return false, nil 229 }) 230 assert.NoError(s.t, err, "timeout waiting for provisioner operation to exist") 231 } 232 233 func (s *DeprovisioningSuite) updateSubAccountIDForDeprovisioningOperation(options RuntimeOptions, instanceId string) { 234 op, err := s.storage.Operations().GetDeprovisioningOperationByInstanceID(instanceId) 235 assert.NoError(s.t, err, "failed to GetDeprovisioningOperationByInstanceID: %v", instanceId) 236 op.SubAccountID = options.ProvideSubAccountID() 237 _, err = s.storage.Operations().UpdateDeprovisioningOperation(*op) 238 assert.NoError(s.t, err, "failed to UpdateDeprovisioningOperation: %v", op) 239 } 240 241 func (s *DeprovisioningSuite) AssertInstanceRemoved(instanceId string) { 242 instance, err := s.storage.Instances().GetByID(instanceId) 243 assert.Error(s.t, err) 244 if dberr.IsNotFound(err) { 245 assert.Nil(s.t, instance) 246 } else { 247 assert.Fail(s.t, "failed to get instance", err) 248 } 249 } 250 251 func (s *DeprovisioningSuite) AssertInstanceNotRemoved(instanceId string) { 252 instance, err := s.storage.Instances().GetByID(instanceId) 253 assert.NoError(s.t, err) 254 assert.NotNil(s.t, instance) 255 } 256 257 func fixEDPClient() *edp.FakeClient { 258 client := edp.NewFakeClient() 259 client.CreateDataTenant(edp.DataTenantPayload{ 260 Name: subAccountID, 261 Environment: edpEnvironment, 262 Secret: base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s%s", subAccountID, edpEnvironment))), 263 }) 264 265 metadataTenantKeys := []string{ 266 edp.MaasConsumerEnvironmentKey, 267 edp.MaasConsumerRegionKey, 268 edp.MaasConsumerSubAccountKey, 269 edp.MaasConsumerServicePlan, 270 } 271 272 for _, key := range metadataTenantKeys { 273 client.CreateMetadataTenant(subAccountID, edpEnvironment, edp.MetadataTenantPayload{ 274 Key: key, 275 Value: "-", 276 }) 277 } 278 279 return client 280 }