diff --git a/pkg/cmd/kafka/create/completions.go b/pkg/cmd/kafka/create/completions.go index dbf1b7ba8..dd543dc30 100644 --- a/pkg/cmd/kafka/create/completions.go +++ b/pkg/cmd/kafka/create/completions.go @@ -45,7 +45,7 @@ func GetKafkaSizeCompletionValues(f *factory.Factory, providerID string, regionI return nil, directive } - userInstanceType, _ := accountmgmtutil.SelectQuotaForUser(f, orgQuota, accountmgmtutil.MarketplaceInfo{}) + userInstanceType, _ := accountmgmtutil.SelectQuotaForUser(f, orgQuota, accountmgmtutil.MarketplaceInfo{}, "") // Not including quota in this request as it takes very long time to list quota for all regions in suggestion mode validSizes, _ = FetchValidKafkaSizesLabels(f, providerID, regionId, *userInstanceType) @@ -67,7 +67,7 @@ func GetMarketplaceCompletionValues(f *factory.Factory) (validSizes []string, di return nil, directive } - validMarketPlaces := FetchValidMarketplaces(orgQuota.MarketplaceQuotas) + validMarketPlaces := FetchValidMarketplaces(orgQuota.MarketplaceQuotas, "") return validMarketPlaces, cobra.ShellCompDirectiveNoSpace } @@ -109,7 +109,7 @@ func GetBillingModelCompletionValues(f *factory.Factory) (availableBillingModels return nil, directive } - availableBillingModels = FetchSupportedBillingModels(orgQuota) + availableBillingModels = FetchSupportedBillingModels(orgQuota, "") return availableBillingModels, directive } diff --git a/pkg/cmd/kafka/create/create.go b/pkg/cmd/kafka/create/create.go index 6bdf0c0d9..7d77e1ced 100644 --- a/pkg/cmd/kafka/create/create.go +++ b/pkg/cmd/kafka/create/create.go @@ -257,7 +257,13 @@ func runCreate(opts *options) error { CloudAccountID: opts.marketplaceAcctId, } - userQuota, err = accountmgmtutil.SelectQuotaForUser(f, orgQuotas, marketplaceInfo) + if opts.marketplace != "" && opts.marketplace != accountmgmtutil.RedHatMarketPlace { + if opts.marketplace != opts.provider { + return opts.f.Localizer.MustLocalizeError("kafka.create.provider.error.unsupportedMarketplace") + } + } + + userQuota, err = accountmgmtutil.SelectQuotaForUser(f, orgQuotas, marketplaceInfo, opts.provider) if err != nil { return err } @@ -477,7 +483,11 @@ func promptKafkaPayload(opts *options, constants *remote.DynamicServiceConstants return nil, err } - availableBillingModels := FetchSupportedBillingModels(orgQuota) + availableBillingModels := FetchSupportedBillingModels(orgQuota, answers.CloudProvider) + + if len(availableBillingModels) == 0 && len(orgQuota.MarketplaceQuotas) > 0 { + return nil, opts.f.Localizer.MustLocalizeError("kafka.create.provider.error.noStandardInstancesAvailable") + } if len(availableBillingModels) > 0 { if len(availableBillingModels) == 1 { @@ -495,7 +505,7 @@ func promptKafkaPayload(opts *options, constants *remote.DynamicServiceConstants } if answers.BillingModel == accountmgmtutil.QuotaMarketplaceType { - validMarketPlaces := FetchValidMarketplaces(orgQuota.MarketplaceQuotas) + validMarketPlaces := FetchValidMarketplaces(orgQuota.MarketplaceQuotas, answers.CloudProvider) if len(validMarketPlaces) == 1 { answers.Marketplace = validMarketPlaces[0] } else { @@ -534,7 +544,7 @@ func promptKafkaPayload(opts *options, constants *remote.DynamicServiceConstants CloudAccountID: answers.MarketplaceAcctID, } - userQuota, err := accountmgmtutil.SelectQuotaForUser(f, orgQuota, marketplaceInfo) + userQuota, err := accountmgmtutil.SelectQuotaForUser(f, orgQuota, marketplaceInfo, answers.CloudProvider) if err != nil { return nil, err } diff --git a/pkg/cmd/kafka/create/data.go b/pkg/cmd/kafka/create/data.go index 9a5a74062..9d9a3c47e 100644 --- a/pkg/cmd/kafka/create/data.go +++ b/pkg/cmd/kafka/create/data.go @@ -55,7 +55,7 @@ func FetchValidKafkaSizesLabels(f *factory.Factory, } -func FetchSupportedBillingModels(userQuotas *accountmgmtutil.OrgQuotas) []string { +func FetchSupportedBillingModels(userQuotas *accountmgmtutil.OrgQuotas, provider string) []string { billingModels := []string{} @@ -64,20 +64,37 @@ func FetchSupportedBillingModels(userQuotas *accountmgmtutil.OrgQuotas) []string } if len(userQuotas.MarketplaceQuotas) > 0 { - billingModels = append(billingModels, accountmgmtutil.QuotaMarketplaceType) + if provider != "" { + for _, quota := range userQuotas.MarketplaceQuotas { + for _, cloudAccount := range *quota.CloudAccounts { + if cloudAccount.GetCloudProviderId() == provider || cloudAccount.GetCloudProviderId() == accountmgmtutil.RedHatMarketPlace { + billingModels = append(billingModels, accountmgmtutil.QuotaMarketplaceType) + return billingModels + } + } + } + } else { + billingModels = append(billingModels, accountmgmtutil.QuotaMarketplaceType) + } } return billingModels } -func FetchValidMarketplaces(amsTypes []accountmgmtutil.QuotaSpec) []string { +func FetchValidMarketplaces(amsTypes []accountmgmtutil.QuotaSpec, provider string) []string { validMarketplaces := []string{} for _, quota := range amsTypes { if quota.CloudAccounts != nil { for _, cloudAccount := range *quota.CloudAccounts { - validMarketplaces = append(validMarketplaces, *cloudAccount.CloudProviderId) + if provider != "" { + if *cloudAccount.CloudProviderId == provider || *cloudAccount.CloudProviderId == accountmgmtutil.RedHatMarketPlace { + validMarketplaces = append(validMarketplaces, *cloudAccount.CloudProviderId) + } + } else { + validMarketplaces = append(validMarketplaces, *cloudAccount.CloudProviderId) + } } } } diff --git a/pkg/core/localize/locales/en/cmd/kafka.en.toml b/pkg/core/localize/locales/en/cmd/kafka.en.toml index d369d0449..308021514 100644 --- a/pkg/core/localize/locales/en/cmd/kafka.en.toml +++ b/pkg/core/localize/locales/en/cmd/kafka.en.toml @@ -417,6 +417,15 @@ provided instance size is not valid. Valid sizes: {{.ValidSizes}} [kafka.create.error.noRegionSupported] one = 'all regions in the selected cloud provider are temporarily unavailable' +[kafka.create.provider.error.noStandardInstancesAvailable] +one = 'standard instances are unavailable for the cloud provider, try another provider' + +[kafka.create.provider.error.noMarketplaceQuota] +one = 'no marketplace quota available for given provider' + +[kafka.create.provider.error.unsupportedMarketplace] +one = 'selected marketplace is not supported for the cloud provider' + [kafka.create.error.billing.invalid] one = ''' provided billing account id and provider are invalid {{.Billing}} diff --git a/pkg/shared/accountmgmtutil/ams.go b/pkg/shared/accountmgmtutil/ams.go index 764422c10..5809ef976 100644 --- a/pkg/shared/accountmgmtutil/ams.go +++ b/pkg/shared/accountmgmtutil/ams.go @@ -12,6 +12,10 @@ import ( "github.com/redhat-developer/app-services-cli/pkg/shared/remote" ) +const ( + RedHatMarketPlace = "rhm" +) + func CheckTermsAccepted(ctx context.Context, spec *remote.AmsConfig, conn connection.Connection) (accepted bool, redirectURI string, err error) { termsReview, _, err := conn.API().AccountMgmt(). ApiAuthorizationsV1SelfTermsReviewPost(ctx). @@ -107,7 +111,8 @@ func GetOrgQuotas(f *factory.Factory, spec *remote.AmsConfig) (*OrgQuotas, error return availableOrgQuotas, nil } -func SelectQuotaForUser(f *factory.Factory, orgQuota *OrgQuotas, marketplaceInfo MarketplaceInfo) (*QuotaSpec, error) { +// nolint:funlen +func SelectQuotaForUser(f *factory.Factory, orgQuota *OrgQuotas, marketplaceInfo MarketplaceInfo, provider string) (*QuotaSpec, error) { if len(orgQuota.StandardQuotas) == 0 && len(orgQuota.MarketplaceQuotas) == 0 { if marketplaceInfo.BillingModel != "" || marketplaceInfo.Provider != "" { @@ -131,12 +136,31 @@ func SelectQuotaForUser(f *factory.Factory, orgQuota *OrgQuotas, marketplaceInfo return nil, f.Localizer.MustLocalizeError("kafka.create.quota.error.noStandard") } + var filteredMarketPlaceQuotas []QuotaSpec + + if provider != "" { + for _, quota := range orgQuota.MarketplaceQuotas { + for _, cloudAccount := range *quota.CloudAccounts { + if cloudAccount.GetCloudProviderId() == provider || cloudAccount.GetCloudProviderId() == RedHatMarketPlace { + filteredMarketPlaceQuotas = append(filteredMarketPlaceQuotas, quota) + break + } + } + } + + orgQuota.MarketplaceQuotas = uniqueQuotaSpec(filteredMarketPlaceQuotas) + } + + if len(orgQuota.MarketplaceQuotas) == 0 { + return nil, f.Localizer.MustLocalizeError("kafka.create.provider.error.noMarketplaceQuota") + } + marketplaceQuota, err := getMarketplaceQuota(f, orgQuota.MarketplaceQuotas, marketplaceInfo) if err != nil { return nil, err } - marketplaceQuota.CloudAccounts, err = pickCloudAccount(f, marketplaceQuota.CloudAccounts, marketplaceInfo) + marketplaceQuota.CloudAccounts, err = pickCloudAccount(f, marketplaceQuota.CloudAccounts, marketplaceInfo, provider) if err != nil { return nil, err } @@ -149,12 +173,32 @@ func SelectQuotaForUser(f *factory.Factory, orgQuota *OrgQuotas, marketplaceInfo if marketplaceInfo.BillingModel == QuotaStandardType { return &orgQuota.StandardQuotas[0], nil } else if marketplaceInfo.BillingModel == QuotaMarketplaceType || marketplaceInfo.Provider != "" || marketplaceInfo.CloudAccountID != "" { + + var filteredMarketPlaceQuotas []QuotaSpec + + if provider != "" { + for _, quota := range orgQuota.MarketplaceQuotas { + for _, cloudAccount := range *quota.CloudAccounts { + if cloudAccount.GetCloudProviderId() == provider || cloudAccount.GetCloudProviderId() == RedHatMarketPlace { + filteredMarketPlaceQuotas = append(filteredMarketPlaceQuotas, quota) + break + } + } + } + + orgQuota.MarketplaceQuotas = uniqueQuotaSpec(filteredMarketPlaceQuotas) + } + + if len(orgQuota.MarketplaceQuotas) == 0 { + return nil, f.Localizer.MustLocalizeError("kafka.create.provider.error.noMarketplaceQuota") + } + marketplaceQuota, err := getMarketplaceQuota(f, orgQuota.MarketplaceQuotas, marketplaceInfo) if err != nil { return nil, err } - marketplaceQuota.CloudAccounts, err = pickCloudAccount(f, marketplaceQuota.CloudAccounts, marketplaceInfo) + marketplaceQuota.CloudAccounts, err = pickCloudAccount(f, marketplaceQuota.CloudAccounts, marketplaceInfo, provider) if err != nil { return nil, err } @@ -209,13 +253,26 @@ func pickMarketplaceQuota(f *factory.Factory, marketplaceQuotas []QuotaSpec, mar return &matchedQuotas[0], nil } -func pickCloudAccount(f *factory.Factory, cloudAccounts *[]amsclient.CloudAccount, market MarketplaceInfo) (*[]amsclient.CloudAccount, error) { +func pickCloudAccount(f *factory.Factory, cloudAccounts *[]amsclient.CloudAccount, market MarketplaceInfo, provider string) (*[]amsclient.CloudAccount, error) { + + // filter cloud accounts according to provider + var filteredCloudAccounts []amsclient.CloudAccount + + if provider != "" { + for _, cloudAccount := range *cloudAccounts { + if *cloudAccount.CloudProviderId == provider || *cloudAccount.CloudProviderId == RedHatMarketPlace { + filteredCloudAccounts = append(filteredCloudAccounts, cloudAccount) + } + } + + *cloudAccounts = filteredCloudAccounts + } if len(*cloudAccounts) == 1 { return cloudAccounts, nil } - if len(*cloudAccounts) > 2 && market.Provider == "" && market.CloudAccountID == "" { + if len(*cloudAccounts) > 1 && market.Provider == "" && market.CloudAccountID == "" { return nil, f.Localizer.MustLocalizeError("kafka.create.quota.error.multipleCloudAccounts") } @@ -289,3 +346,16 @@ func unique(s []string) []string { } return result } + +// uniqueQuotaSpec accepts a list of QuotaSpec objects and returns the unique QuotaSpecs +func uniqueQuotaSpec(s []QuotaSpec) []QuotaSpec { + inResult := make(map[QuotaSpec]bool) + var result []QuotaSpec + for _, quota := range s { + if _, ok := inResult[quota]; !ok { + inResult[quota] = true + result = append(result, quota) + } + } + return result +}