github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/tenantfetchersvc/provisioner.go (about) 1 package tenantfetchersvc 2 3 import ( 4 "context" 5 6 "github.com/kyma-incubator/compass/components/director/pkg/graphql" 7 8 "github.com/kyma-incubator/compass/components/director/internal/model" 9 tenantEntity "github.com/kyma-incubator/compass/components/director/pkg/tenant" 10 ) 11 12 const autogeneratedTenantProvider = "autogenerated" 13 14 // DirectorGraphQLClient expects graphql implementation 15 // 16 //go:generate mockery --name=DirectorGraphQLClient --output=automock --outpkg=automock --case=underscore --disable-version-string 17 type DirectorGraphQLClient interface { 18 WriteTenants(context.Context, []graphql.BusinessTenantMappingInput) error 19 DeleteTenants(ctx context.Context, tenants []graphql.BusinessTenantMappingInput) error 20 UpdateTenant(ctx context.Context, id string, tenant graphql.BusinessTenantMappingInput) error 21 SubscribeTenant(ctx context.Context, providerID, subaccountID, providerSubaccountID, consumerTenantID, region, subscriptionProviderAppName, subscriptionPayload string) error 22 UnsubscribeTenant(ctx context.Context, providerID, subaccountID, providerSubaccountID, consumerTenantID, region string) error 23 } 24 25 // TenantConverter expects tenant converter implementation 26 // 27 //go:generate mockery --name=TenantConverter --output=automock --outpkg=automock --case=underscore --disable-version-string 28 type TenantConverter interface { 29 MultipleInputToGraphQLInput([]model.BusinessTenantMappingInput) []graphql.BusinessTenantMappingInput 30 ToGraphQLInput(model.BusinessTenantMappingInput) graphql.BusinessTenantMappingInput 31 } 32 33 // TenantSubscriptionRequest represents the information provided during tenant provisioning request in Compass, which includes tenant IDs, subdomain, and region of the tenant. 34 // The tenant which triggered the provisioning request is only one, and one of the tenant IDs in the request is its external ID, where the other tenant IDs are external IDs from its parents hierarchy. 35 type TenantSubscriptionRequest struct { 36 AccountTenantID string 37 SubaccountTenantID string 38 CustomerTenantID string 39 Subdomain string 40 Region string 41 SubscriptionProviderID string 42 SubscriptionLcenseType string 43 ProviderSubaccountID string 44 ConsumerTenantID string 45 SubscriptionProviderAppName string 46 SubscriptionPayload string 47 } 48 49 // MainTenantID is used to determine the external tenant ID of the tenant for which the provisioning request was triggered. 50 func (r *TenantSubscriptionRequest) MainTenantID() string { 51 if len(r.SubaccountTenantID) > 0 { 52 return r.SubaccountTenantID 53 } 54 55 return r.AccountTenantID 56 } 57 58 type provisioner struct { 59 gqlClient DirectorGraphQLClient 60 converter TenantConverter 61 tenantProvider string 62 } 63 64 // NewTenantProvisioner returns a TenantProvisioner initialized with the provided TenantService, and tenant provider. 65 // All tenants, created by the provisioner, besides the Customer ones, will have the value of tenantProvider as a provider. 66 func NewTenantProvisioner(directorClient DirectorGraphQLClient, tenantConverter TenantConverter, tenantProvider string) *provisioner { 67 return &provisioner{ 68 gqlClient: directorClient, 69 converter: tenantConverter, 70 tenantProvider: tenantProvider, 71 } 72 } 73 74 // ProvisionTenants provisions tenants according to their type 75 func (p *provisioner) ProvisionTenants(ctx context.Context, request *TenantSubscriptionRequest) error { 76 tenantsToCreateGQL := p.converter.MultipleInputToGraphQLInput(p.tenantsFromRequest(*request)) 77 return p.gqlClient.WriteTenants(ctx, tenantsToCreateGQL) 78 } 79 80 func (p *provisioner) tenantsFromRequest(request TenantSubscriptionRequest) []model.BusinessTenantMappingInput { 81 tenants := make([]model.BusinessTenantMappingInput, 0, 3) 82 customerID := request.CustomerTenantID 83 accountID := request.AccountTenantID 84 var licenseType *string 85 86 if len(request.SubscriptionLcenseType) > 0 { 87 licenseType = &request.SubscriptionLcenseType 88 } 89 90 if len(request.CustomerTenantID) > 0 { 91 tenants = append(tenants, p.newCustomerTenant(request.CustomerTenantID, licenseType)) 92 } 93 94 accountTenant := p.newAccountTenant(request.AccountTenantID, customerID, request.Subdomain, request.Region, licenseType) 95 if len(request.SubaccountTenantID) > 0 { // This means that the request is for Subaccount provisioning, therefore the subdomain and the region are for the subaccount and not for the GA 96 accountTenant.Subdomain = "" 97 accountTenant.Region = "" 98 } 99 tenants = append(tenants, accountTenant) 100 101 if len(request.SubaccountTenantID) > 0 { 102 tenants = append(tenants, p.newSubaccountTenant(request.SubaccountTenantID, accountID, request.Subdomain, request.Region, licenseType)) 103 } 104 return tenants 105 } 106 107 func (p *provisioner) newCustomerTenant(tenantID string, licenseType *string) model.BusinessTenantMappingInput { 108 return p.newTenant(tenantID, "", "", "", autogeneratedTenantProvider, licenseType, tenantEntity.Customer) 109 } 110 111 func (p *provisioner) newAccountTenant(tenantID, parent, subdomain, region string, licenseType *string) model.BusinessTenantMappingInput { 112 return p.newTenant(tenantID, parent, subdomain, region, p.tenantProvider, licenseType, tenantEntity.Account) 113 } 114 115 func (p *provisioner) newSubaccountTenant(tenantID, parent, subdomain, region string, licenseType *string) model.BusinessTenantMappingInput { 116 return p.newTenant(tenantID, parent, subdomain, region, p.tenantProvider, licenseType, tenantEntity.Subaccount) 117 } 118 119 func (p *provisioner) newTenant(tenantID, parent, subdomain, region, provider string, licenseType *string, tenantType tenantEntity.Type) model.BusinessTenantMappingInput { 120 return model.BusinessTenantMappingInput{ 121 Name: tenantID, 122 ExternalTenant: tenantID, 123 Parent: parent, 124 Subdomain: subdomain, 125 Region: region, 126 Type: tenantEntity.TypeToStr(tenantType), 127 Provider: provider, 128 LicenseType: licenseType, 129 } 130 }