github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/process/provisioning/edp_registration.go (about) 1 package provisioning 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "strings" 7 "time" 8 9 "github.com/kyma-project/kyma-environment-broker/internal" 10 "github.com/kyma-project/kyma-environment-broker/internal/broker" 11 "github.com/kyma-project/kyma-environment-broker/internal/edp" 12 kebError "github.com/kyma-project/kyma-environment-broker/internal/error" 13 "github.com/kyma-project/kyma-environment-broker/internal/process" 14 "github.com/kyma-project/kyma-environment-broker/internal/storage" 15 16 "github.com/sirupsen/logrus" 17 ) 18 19 //go:generate mockery --name=EDPClient --output=automock --outpkg=automock --case=underscore 20 type EDPClient interface { 21 CreateDataTenant(data edp.DataTenantPayload) error 22 CreateMetadataTenant(name, env string, data edp.MetadataTenantPayload) error 23 24 DeleteDataTenant(name, env string) error 25 DeleteMetadataTenant(name, env, key string) error 26 } 27 28 type EDPRegistrationStep struct { 29 operationManager *process.OperationManager 30 client EDPClient 31 config edp.Config 32 } 33 34 func NewEDPRegistrationStep(os storage.Operations, client EDPClient, config edp.Config) *EDPRegistrationStep { 35 return &EDPRegistrationStep{ 36 operationManager: process.NewOperationManager(os), 37 client: client, 38 config: config, 39 } 40 } 41 42 func (s *EDPRegistrationStep) Name() string { 43 return "EDP_Registration" 44 } 45 46 func (s *EDPRegistrationStep) Run(operation internal.Operation, log logrus.FieldLogger) (internal.Operation, time.Duration, error) { 47 if operation.EDPCreated { 48 return operation, 0, nil 49 } 50 subAccountID := strings.ToLower(operation.ProvisioningParameters.ErsContext.SubAccountID) 51 52 log.Infof("Create DataTenant for %s subaccount (env=%s)", subAccountID, s.config.Environment) 53 err := s.client.CreateDataTenant(edp.DataTenantPayload{ 54 Name: subAccountID, 55 Environment: s.config.Environment, 56 Secret: s.generateSecret(subAccountID, s.config.Environment), 57 }) 58 if err != nil { 59 if edp.IsConflictError(err) { 60 log.Warnf("Data Tenant already exists, deleting") 61 return s.handleConflict(operation, log) 62 } 63 return s.handleError(operation, err, log, "cannot create DataTenant") 64 } 65 66 log.Infof("Create DataTenant metadata for %s subaccount", subAccountID) 67 for key, value := range map[string]string{ 68 edp.MaasConsumerEnvironmentKey: s.selectEnvironmentKey(operation.ProvisioningParameters.PlatformRegion, log), 69 edp.MaasConsumerRegionKey: operation.ProvisioningParameters.PlatformRegion, 70 edp.MaasConsumerSubAccountKey: subAccountID, 71 edp.MaasConsumerServicePlan: s.selectServicePlan(operation.ProvisioningParameters.PlanID), 72 } { 73 payload := edp.MetadataTenantPayload{ 74 Key: key, 75 Value: value, 76 } 77 log.Infof("Sending metadata %s: %s", payload.Key, payload.Value) 78 err = s.client.CreateMetadataTenant(subAccountID, s.config.Environment, payload) 79 if err != nil { 80 if edp.IsConflictError(err) { 81 log.Warnf("Metadata already exists, deleting") 82 return s.handleConflict(operation, log) 83 } 84 return s.handleError(operation, err, log, fmt.Sprintf("cannot create DataTenant metadata %s", key)) 85 } 86 } 87 88 newOp, repeat, _ := s.operationManager.UpdateOperation(operation, func(op *internal.Operation) { 89 op.EDPCreated = true 90 }, log) 91 if repeat != 0 { 92 log.Errorf("cannot save operation") 93 return newOp, 5 * time.Second, nil 94 } 95 96 return newOp, 0, nil 97 } 98 99 func (s *EDPRegistrationStep) handleError(operation internal.Operation, err error, log logrus.FieldLogger, msg string) (internal.Operation, time.Duration, error) { 100 log.Errorf("%s: %s", msg, err) 101 102 if kebError.IsTemporaryError(err) { 103 since := time.Since(operation.UpdatedAt) 104 if since < time.Minute*30 { 105 log.Errorf("request to EDP failed: %s. Retry...", err) 106 return operation, 10 * time.Second, nil 107 } 108 } 109 110 if !s.config.Required { 111 log.Errorf("Step %s failed. Step is not required. Skip step.", s.Name()) 112 return operation, 0, nil 113 } 114 115 return s.operationManager.OperationFailed(operation, msg, err, log) 116 } 117 118 func (s *EDPRegistrationStep) selectEnvironmentKey(region string, log logrus.FieldLogger) string { 119 parts := strings.Split(region, "-") 120 switch parts[0] { 121 case "cf": 122 return "CF" 123 case "k8s": 124 return "KUBERNETES" 125 case "neo": 126 return "NEO" 127 default: 128 log.Warnf("region %s does not fit any of the options, default CF is used", region) 129 return "CF" 130 } 131 } 132 133 func (s *EDPRegistrationStep) selectServicePlan(planID string) string { 134 switch planID { 135 case broker.FreemiumPlanID: 136 return "free" 137 case broker.AzureLitePlanID: 138 return "tdd" 139 default: 140 return "standard" 141 } 142 } 143 144 // generateSecret generates secret during dataTenant creation, at this moment the secret is not needed 145 // except required parameter 146 func (s *EDPRegistrationStep) generateSecret(name, env string) string { 147 return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s%s", name, env))) 148 } 149 150 func (s *EDPRegistrationStep) handleConflict(operation internal.Operation, log logrus.FieldLogger) (internal.Operation, time.Duration, error) { 151 for _, key := range []string{ 152 edp.MaasConsumerEnvironmentKey, 153 edp.MaasConsumerRegionKey, 154 edp.MaasConsumerSubAccountKey, 155 edp.MaasConsumerServicePlan, 156 } { 157 log.Infof("Deleting DataTenant metadata %s (%s): %s", operation.SubAccountID, s.config.Environment, key) 158 err := s.client.DeleteMetadataTenant(operation.SubAccountID, s.config.Environment, key) 159 if err != nil { 160 return s.handleError(operation, err, log, fmt.Sprintf("cannot remove DataTenant metadata with key: %s", key)) 161 } 162 } 163 164 log.Infof("Deleting DataTenant %s (%s)", operation.SubAccountID, s.config.Environment) 165 err := s.client.DeleteDataTenant(operation.SubAccountID, s.config.Environment) 166 if err != nil { 167 return s.handleError(operation, err, log, "cannot remove DataTenant") 168 } 169 170 log.Infof("Retrying...") 171 return operation, time.Second, nil 172 }