Skip to content

Commit

Permalink
feat: make enterprise flow the primary flow (#1837)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimakis authored Mar 21, 2023
1 parent 94582ea commit 8f15393
Showing 3 changed files with 131 additions and 46 deletions.
169 changes: 123 additions & 46 deletions pkg/cmd/kafka/create/create.go
Original file line number Diff line number Diff line change
@@ -75,7 +75,9 @@ type options struct {
kfmClusterList *kafkamgmtclient.EnterpriseClusterList
selectedCluster *kafkamgmtclient.EnterpriseCluster
clusterMap *map[string]v1.Cluster
useEnterpriseCluster bool
useEnterpriseFlow bool
hasLegacyQuota bool
useLegacyFlow bool
clusterManagementApiUrl string
accessToken string

@@ -501,58 +503,88 @@ func selectEnterpriseOrRHInfraPrompt(opts *options) error {
if err != nil {
return err
}
opts.useEnterpriseCluster = idx != 0
opts.useEnterpriseFlow = idx != 0
opts.useLegacyFlow = idx == 0

return nil
}

func checkForLegacyQuota(opts *options, orgQuotas *accountmgmtutil.OrgQuotas) {
// Check if the user has enterprise quota
for _, quota := range orgQuotas.EnterpriseQuotas {
if quota.Quota > 0 {
opts.useEnterpriseFlow = true
}
}
// to-do may have to deal with trial (developer instances) quota here

// Check if the user has a legacy quota
for _, quota := range orgQuotas.StandardQuotas {
if quota.Quota > 0 {
opts.hasLegacyQuota = true
return
}
}
for _, quota := range orgQuotas.MarketplaceQuotas {
if quota.Quota > 0 {
opts.hasLegacyQuota = true
return
}
}
for _, quota := range orgQuotas.EvalQuotas {
if quota.Quota > 0 {
opts.hasLegacyQuota = true
return
}
}
}

// Show a prompt to allow the user to interactively insert the data for their Kafka
// nolint:funlen
func promptKafkaPayload(opts *options, constants *remote.DynamicServiceConstants) (*kafkamgmtclient.KafkaRequestPayload, error) {
f := opts.f

validator := &kafkacmdutil.Validator{
Localizer: f.Localizer,
Connection: f.Connection,
// getting org quotas
orgQuota, err := accountmgmtutil.GetOrgQuotas(f, &constants.Kafka.Ams)
if err != nil {
return nil, err
}

promptName := &survey.Input{
Message: f.Localizer.MustLocalize("kafka.create.input.name.message"),
Help: f.Localizer.MustLocalize("kafka.create.input.name.help"),
}
// check if org has legacy (non-hybrid) quota
checkForLegacyQuota(opts, orgQuota)

var enterpriseQuota accountmgmtutil.QuotaSpec

answers := &promptAnswers{}

err := survey.AskOne(promptName, &answers.Name, survey.WithValidator(validator.ValidateName), survey.WithValidator(validator.ValidateNameIsAvailable))
// Message the user with a link to get enterprise quota if they don't have any
if !opts.useEnterpriseFlow {
f.Logger.Info(opts.f.Localizer.MustLocalize("kafka.create.info.enterpriseQuota"))
}

answers, err = promptForKafkaName(f, answers)
if err != nil {
return nil, err
}

// Get the list of enterprise clusters in the users organization if there are any, creates a map of cluster ids to names to include names in the prompt
// Get the list of enterprise clusters in the users organization if there are any, creates a map of cluster ids
// to names to include names in the prompt
kfmClusterList, clusterMap, err := setEnterpriseClusterList(opts)
if err != nil {
return nil, err
}

opts.kfmClusterList = kfmClusterList
opts.clusterMap = clusterMap

// If there are enterprise clusters in the user's organization, prompt them to select one using the interactive prompt for enterprise flow
if len(opts.kfmClusterList.Items) > 0 {
err = selectEnterpriseOrRHInfraPrompt(opts)
if err != nil {
return nil, err
}
}

// getting org quotas
orgQuota, err := accountmgmtutil.GetOrgQuotas(f, &constants.Kafka.Ams)
// If there are enterprise clusters in the user's organization, prompt them to select a flow (enterprise or legacy)
// using the interactive prompt. If there are no enterprise clusters, the user must use the legacy flow.
// Default to enterprise flow
err = determineFlowFromQuota(opts)
if err != nil {
return nil, err
}

var enterpriseQuota accountmgmtutil.QuotaSpec
if opts.useEnterpriseCluster {
if opts.useEnterpriseFlow {
if len(orgQuota.EnterpriseQuotas) < 1 {
return nil, opts.f.Localizer.MustLocalizeError("kafka.create.error.noEnterpriseQuota")
}
@@ -582,33 +614,17 @@ func promptKafkaPayload(opts *options, constants *remote.DynamicServiceConstants
}

// If the user is not using an enterprise cluster, prompt them to select a cloud provider
if !opts.useEnterpriseCluster {
if opts.useLegacyFlow {
answers, err = cloudProviderPrompt(f, answers)
if err != nil {
return nil, err
}
}

availableBillingModels := FetchSupportedBillingModels(orgQuota, answers.CloudProvider)

if len(availableBillingModels) == 0 && len(orgQuota.MarketplaceQuotas) > 0 {
return nil, opts.f.Localizer.MustLocalizeError("kafka.create.provider.error.noStandardInstancesAvailable")
}

// prompting for billing model if there are more than one available, otherwise using the only one available
if len(availableBillingModels) > 0 {
if len(availableBillingModels) == 1 {
answers.BillingModel = availableBillingModels[0]
} else {
billingModelPrompt := &survey.Select{
Message: f.Localizer.MustLocalize("kafka.create.input.billingModel.message"),
Options: availableBillingModels,
}
err = survey.AskOne(billingModelPrompt, &answers.BillingModel)
if err != nil {
return nil, err
}
}
// gets the billing model for the kafka, if the user has more than one billing model, a prompt is shown to select one
answers, err = getBillingModel(opts, orgQuota, answers)
if err != nil {
return nil, err
}

// if billing model is marketplace, prompt for marketplace provider and account id
@@ -623,7 +639,7 @@ func promptKafkaPayload(opts *options, constants *remote.DynamicServiceConstants
// nolint:staticcheck
payload := &kafkamgmtclient.KafkaRequestPayload{}

if opts.useEnterpriseCluster {
if opts.useEnterpriseFlow {
/*
if using dedicated cluster option then get the supported sizes for this cluster
based on the sizes it supports the user to select the one they want to use
@@ -757,6 +773,67 @@ func promptKafkaPayload(opts *options, constants *remote.DynamicServiceConstants
return payload, nil
}

func getBillingModel(opts *options, orgQuota *accountmgmtutil.OrgQuotas, answers *promptAnswers) (*promptAnswers, error) {
availableBillingModels := FetchSupportedBillingModels(orgQuota, answers.CloudProvider)

if len(availableBillingModels) == 0 && len(orgQuota.MarketplaceQuotas) > 0 {
return nil, opts.f.Localizer.MustLocalizeError("kafka.create.provider.error.noStandardInstancesAvailable")
}

// prompting for billing model if there are more than one available, otherwise using the only one available
if len(availableBillingModels) > 0 {
if len(availableBillingModels) == 1 {
answers.BillingModel = availableBillingModels[0]
} else {
billingModelPrompt := &survey.Select{
Message: opts.f.Localizer.MustLocalize("kafka.create.input.billingModel.message"),
Options: availableBillingModels,
}
err := survey.AskOne(billingModelPrompt, &answers.BillingModel)
if err != nil {
return nil, err
}
}
}
return answers, nil
}

func determineFlowFromQuota(opts *options) error {
switch {
case len(opts.kfmClusterList.Items) > 0 && opts.hasLegacyQuota:
err := selectEnterpriseOrRHInfraPrompt(opts)
if err != nil {
return err
}
return nil
case opts.hasLegacyQuota:
opts.useLegacyFlow = true
return nil
default:
opts.useEnterpriseFlow = true
return nil
}
}

func promptForKafkaName(f *factory.Factory, answers *promptAnswers) (*promptAnswers, error) {
validator := &kafkacmdutil.Validator{
Localizer: f.Localizer,
Connection: f.Connection,
}

// prompt for kafka name
promptName := &survey.Input{
Message: f.Localizer.MustLocalize("kafka.create.input.name.message"),
Help: f.Localizer.MustLocalize("kafka.create.input.name.help"),
}

err := survey.AskOne(promptName, &answers.Name, survey.WithValidator(validator.ValidateName), survey.WithValidator(validator.ValidateNameIsAvailable))
if err != nil {
return nil, err
}
return answers, nil
}

func marketplaceQuotaPrompt(orgQuota *accountmgmtutil.OrgQuotas, answers *promptAnswers, f *factory.Factory) (*promptAnswers, error) {
validMarketPlaces := FetchValidMarketplaces(orgQuota.MarketplaceQuotas, answers.CloudProvider)
if len(validMarketPlaces) == 1 {
1 change: 1 addition & 0 deletions pkg/core/localize/locales/en/cmd/dedicated.en.toml
Original file line number Diff line number Diff line change
@@ -167,3 +167,4 @@ You can check for when your cluster status is "ready" by running the following c
rhoas dedicated list
'''


7 changes: 7 additions & 0 deletions pkg/core/localize/locales/en/cmd/kafka.en.toml
Original file line number Diff line number Diff line change
@@ -1213,3 +1213,10 @@ one = 'Red Hat Managed OpenShift Cluster for your Kafka Instances'

[kafka.create.input.cluster.help]
one = 'Select the cluster to provision your Kafka instance on.'

[kafka.create.info.enterpriseQuota]
one = '''
You do not have enough quota to create a Kafka instance on your own OpenShift Cluster.
Please visit https://console.redhat.com/application-services/streams/overview to request more quota.
'''

0 comments on commit 8f15393

Please sign in to comment.