Skip to content

Commit

Permalink
[CPG-1925] Only print free remaining credit for free trial orgs & add…
Browse files Browse the repository at this point in the history
… free trial announcement to cloud signup (#1320)
  • Loading branch information
cryoshida authored Jun 23, 2022
1 parent 9ab7c78 commit a4c726b
Show file tree
Hide file tree
Showing 13 changed files with 332 additions and 78 deletions.
50 changes: 49 additions & 1 deletion internal/cmd/cloud-signup/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ import (
"github.com/confluentinc/ccloud-sdk-go-v1"
"github.com/confluentinc/countrycode"

"github.com/confluentinc/cli/internal/cmd/admin"
pauth "github.com/confluentinc/cli/internal/pkg/auth"
pcmd "github.com/confluentinc/cli/internal/pkg/cmd"
v1 "github.com/confluentinc/cli/internal/pkg/config/v1"
"github.com/confluentinc/cli/internal/pkg/errors"
launchdarkly "github.com/confluentinc/cli/internal/pkg/featureflags"
"github.com/confluentinc/cli/internal/pkg/form"
"github.com/confluentinc/cli/internal/pkg/log"
"github.com/confluentinc/cli/internal/pkg/utils"
Expand Down Expand Up @@ -170,7 +173,7 @@ func (c *command) signup(cmd *cobra.Command, prompt form.Prompt, client *ccloud.
return err
}

utils.Println(cmd, "Success! Welcome to Confluent Cloud.")
utils.Print(cmd, errors.CloudSignUpMsg)

authorizedClient := c.clientFactory.JwtHTTPClientFactory(context.Background(), res.Token, client.BaseURL)
credentials := &pauth.Credentials{
Expand All @@ -184,7 +187,52 @@ func (c *command) signup(cmd *cobra.Command, prompt form.Prompt, client *ccloud.
return nil
}

c.printFreeTrialAnnouncement(cmd, authorizedClient, currentOrg)

utils.Printf(cmd, errors.LoggedInAsMsgWithOrg, fEmailName.Responses["email"].(string), currentOrg.ResourceId, currentOrg.Name)
return nil
}
}

func (c *command) printFreeTrialAnnouncement(cmd *cobra.Command, client *ccloud.Client, currentOrg *orgv1.Organization) {
// sanity check that org is not suspended
if c.Config.IsOrgSuspended() {
log.CliLogger.Warn("Failed to print free trial announcement: org is suspended")
return
}

org := &orgv1.Organization{Id: currentOrg.Id}
promoCodes, err := client.Billing.GetClaimedPromoCodes(context.Background(), org, true)
if err != nil {
log.CliLogger.Warnf("Failed to print free trial announcement: %v", err)
return
}

url, _ := c.Flags().GetString("url")

var ldClient v1.LaunchDarklyClient
switch url {
case "https://devel.cpdev.cloud":
ldClient = v1.CcloudDevelLaunchDarklyClient
case "https://stag.cpdev.cloud":
ldClient = v1.CcloudStagLaunchDarklyClient
default:
ldClient = v1.CcloudProdLaunchDarklyClient
}
freeTrialPromoCode := launchdarkly.Manager.StringVariation("billing.service.signup_promo.promo_code", c.Config.Context(), ldClient, false, "")

// try to find free trial promo code
hasFreeTrialCode := false
freeTrialPromoCodeAmount := int64(0)
for _, promoCode := range promoCodes {
if promoCode.Code == freeTrialPromoCode {
hasFreeTrialCode = true
freeTrialPromoCodeAmount = promoCode.Amount
break
}
}

if hasFreeTrialCode {
utils.ErrPrintf(cmd, errors.FreeTrialSignUpMsg, admin.ConvertToUSD(freeTrialPromoCodeAmount))
}
}
26 changes: 17 additions & 9 deletions internal/cmd/login/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,27 +139,35 @@ func (c *command) loginCCloud(cmd *cobra.Command, url string) error {
utils.ErrPrintln(cmd, fmt.Sprintf("Error: %s", endOfFreeTrialErr.Error()))
errors.DisplaySuggestionsMessage(endOfFreeTrialErr.UserFacingError(), os.Stderr)
} else {
c.printRemainingFreeCredit(cmd, client)
c.printRemainingFreeCredit(cmd, client, currentOrg)
}

return c.saveLoginToNetrc(cmd, true, credentials)
}

func (c *command) printRemainingFreeCredit(cmd *cobra.Command, client *ccloud.Client) {
org := &orgv1.Organization{Id: c.Config.Context().State.Auth.Account.OrganizationId}
func (c *command) printRemainingFreeCredit(cmd *cobra.Command, client *ccloud.Client, currentOrg *orgv1.Organization) {
org := &orgv1.Organization{Id: currentOrg.Id}
promoCodes, err := client.Billing.GetClaimedPromoCodes(context.Background(), org, true)
if err != nil {
log.CliLogger.Warnf("Failed to print remaining free credit: %v", err)
return
}

// only print remaining free credit if there is any unexpired promo code
if len(promoCodes) != 0 {
var remainingFreeCredit int64
for _, promoCode := range promoCodes {
remainingFreeCredit += promoCode.Balance
// aggregate remaining free credit
remainingFreeCredit := int64(0)
for _, promoCode := range promoCodes {
remainingFreeCredit += promoCode.Balance
}

// only print remaining free credit if there is any unexpired promo code and there is no payment method yet
if remainingFreeCredit > 0 {
card, err := client.Billing.GetPaymentInfo(context.Background(), org)
if err != nil {
log.CliLogger.Warnf("Failed to print remaining free credit: %v", err)
return
}
if remainingFreeCredit > 0 {

if card == nil {
utils.ErrPrintf(cmd, errors.RemainingFreeCreditMsg, admin.ConvertToUSD(remainingFreeCredit))
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cmd/prerunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func (r *PreRun) Anonymous(command *CLICommand, willAuthenticate bool) func(cmd
}

func checkCliDisable(cmd *CLICommand, config *v1.Config) error {
ldDisableJson := launchdarkly.Manager.JsonVariation("cli.disable", cmd.Config.Context(), nil)
ldDisableJson := launchdarkly.Manager.JsonVariation("cli.disable", cmd.Config.Context(), v1.CliLaunchDarklyClient, true, nil)
ldDisable, ok := ldDisableJson.(map[string]interface{})
if !ok {
return nil
Expand Down
6 changes: 3 additions & 3 deletions internal/pkg/config/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ func (c *Config) CheckIsCloudLogin() error {
return RequireCloudLoginErr
}

if c.isOrgSuspended() {
if c.IsOrgSuspended() {
if c.isLoginBlockedByOrgSuspension() {
return RequireCloudLoginOrgUnsuspendedErr
} else {
Expand Down Expand Up @@ -606,14 +606,14 @@ func (c *Config) isContextStatePresent() bool {
return true
}

func (c *Config) isOrgSuspended() bool {
func (c *Config) IsOrgSuspended() bool {
status := c.Context().GetSuspensionStatus().GetStatus()
return status == orgv1.SuspensionStatusType_SUSPENSION_IN_PROGRESS || status == orgv1.SuspensionStatusType_SUSPENSION_COMPLETED
}

func (c *Config) isLoginBlockedByOrgSuspension() bool {
eventType := c.Context().GetSuspensionStatus().GetEventType()
return c.isOrgSuspended() && eventType != orgv1.SuspensionEventType_SUSPENSION_EVENT_END_OF_FREE_TRIAL
return c.IsOrgSuspended() && eventType != orgv1.SuspensionEventType_SUSPENSION_EVENT_END_OF_FREE_TRIAL
}

func (c *Config) GetLastUsedOrgId() string {
Expand Down
10 changes: 8 additions & 2 deletions internal/pkg/config/v1/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,17 @@ func (c *Context) GetAuthRefreshToken() string {
return ""
}

func (c *Context) GetLDFlags() map[string]interface{} {
func (c *Context) GetLDFlags(client LaunchDarklyClient) map[string]interface{} {
if c.FeatureFlags == nil {
return map[string]interface{}{}
}
return c.FeatureFlags.Values

switch client {
case CcloudDevelLaunchDarklyClient, CcloudStagLaunchDarklyClient, CcloudProdLaunchDarklyClient:
return c.FeatureFlags.CcloudValues
default:
return c.FeatureFlags.Values
}
}

func printApiKeysDictErrorMessage(missingKey, mismatchKey, missingSecret bool, cluster *KafkaClusterConfig, contextName string) {
Expand Down
10 changes: 10 additions & 0 deletions internal/pkg/config/v1/feature_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ package v1

import "gopkg.in/launchdarkly/go-sdk-common.v2/lduser"

type LaunchDarklyClient int

const (
CliLaunchDarklyClient LaunchDarklyClient = iota
CcloudProdLaunchDarklyClient
CcloudStagLaunchDarklyClient
CcloudDevelLaunchDarklyClient
)

type FeatureFlags struct {
Values map[string]interface{} `json:"values" hcl:"values"`
CcloudValues map[string]interface{} `json:"ccloud_values" hcl:"ccloud_values"`
LastUpdateTime int64 `json:"last_update_time" hcl:"last_update_time"`
User lduser.User `json:"user" hcl:"user"`
}
5 changes: 4 additions & 1 deletion internal/pkg/errors/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ const (
FoundNetrcCredMsg = "Found credentials for user \"%s\" from netrc file \"%s\" " +
StopNonInteractiveMsg + ".\n"
FoundOrganizationIdMsg = "Found default organization id for user \"%s\" from environment variable \"%s\".\n"
RemainingFreeCreditMsg = "Free credits: $%.2f USD remaining\n"
RemainingFreeCreditMsg = "Free credits: $%.2f USD remaining\n" +
"You are currently using a free trial version of Confluent Cloud. Add a payment method with \"confluent admin payment update\" to avoid an interruption in service once your trial ends.\n"
CloudSignUpMsg = "Success! Welcome to Confluent Cloud.\n"
FreeTrialSignUpMsg = "Congratulations! You now have $%.2f USD to spend during the first 60 days. No credit card is required.\n"

// confluent cluster command
UnregisteredClusterMsg = "Successfully unregistered the cluster %s from the Cluster Registry.\n"
Expand Down
Loading

0 comments on commit a4c726b

Please sign in to comment.