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  }