Skip to content

Commit

Permalink
Updating Customer CLI (#382)
Browse files Browse the repository at this point in the history
* Updating Customer CLI

* rename to IsKotsInstallEnabled

* rename to IsKotsInstallEnabled

* improving customer list and inspect

* improving customer list and inspect

* Allowing customer license expiration to be specified as duration or in absolute time
  • Loading branch information
jdewinne authored Apr 24, 2024
1 parent fb86acf commit b2fc8f5
Show file tree
Hide file tree
Showing 10 changed files with 368 additions and 78 deletions.
16 changes: 8 additions & 8 deletions cli/cmd/cluster_prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,17 @@ func (r *runners) prepareCluster(_ *cobra.Command, args []string) error {
// create a test customer with the correct entitlement values
email := fmt.Sprintf("%[email protected]", clusterName)
customerOpts := kotsclient.CreateCustomerOpts{
Name: clusterName,
ChannelID: "",
AppID: r.appID,
LicenseType: "test",
Email: email,
EntitlementValues: entitlements,
IsKotInstallEnabled: true,
Name: clusterName,
ChannelID: "",
AppID: r.appID,
LicenseType: "test",
Email: email,
EntitlementValues: entitlements,
IsKotsInstallEnabled: true,
}

if appRelease.IsHelmOnly {
customerOpts.IsKotInstallEnabled = false
customerOpts.IsKotsInstallEnabled = false
}
log.ActionWithSpinner("Creating Customer")
customer, err := r.api.CreateCustomer(r.appType, customerOpts)
Expand Down
36 changes: 24 additions & 12 deletions cli/cmd/customer_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ func (r *runners) InitCustomersCreateCommand(parent *cobra.Command) *cobra.Comma
cmd.Flags().BoolVar(&r.args.customerCreateIsAirgapEnabled, "airgap", false, "If set, the license will allow airgap installs.")
cmd.Flags().BoolVar(&r.args.customerCreateIsGitopsSupported, "gitops", false, "If set, the license will allow the GitOps usage.")
cmd.Flags().BoolVar(&r.args.customerCreateIsSnapshotSupported, "snapshot", false, "If set, the license will allow Snapshots.")
cmd.Flags().BoolVar(&r.args.customerCreateIsKotInstallEnabled, "kots-install", true, "If set, the license will allow KOTS install. Otherwise license will allow Helm CLI installs only.")
cmd.Flags().BoolVar(&r.args.customerCreateIsKotsInstallEnabled, "kots-install", true, "If set, the license will allow KOTS install. Otherwise license will allow Helm CLI installs only.")
cmd.Flags().BoolVar(&r.args.customerCreateIsEmbeddedClusterDownloadEnabled, "embedded-cluster-download", false, "If set, the license will allow embedded cluster downloads.")
cmd.Flags().BoolVar(&r.args.customerCreateIsGeoaxisSupported, "geo-axis", false, "If set, the license will allow Geo Axis usage.")
cmd.Flags().BoolVar(&r.args.customerCreateIsHelmVMDownloadEnabled, "helmvm-cluster-download", false, "If set, the license will allow helmvm cluster downloads.")
cmd.Flags().BoolVar(&r.args.customerCreateIsIdentityServiceSupported, "identity-service", false, "If set, the license will allow Identity Service usage.")
cmd.Flags().BoolVar(&r.args.customerCreateIsInstallerSupportEnabled, "installer-support", false, "If set, the license will allow installer support.")
cmd.Flags().BoolVar(&r.args.customerCreateIsSupportBundleUploadEnabled, "support-bundle-upload", false, "If set, the license will allow uploading support bundles.")
cmd.Flags().StringVar(&r.args.customerCreateEmail, "email", "", "Email address of the customer that is to be created.")
cmd.Flags().StringVar(&r.args.customerCreateType, "type", "dev", "The license type to create. One of: dev|trial|paid|community|test (default: dev)")
cmd.Flags().StringVar(&r.outputFormat, "output", "table", "The output format to use. One of: json|table (default: table)")
Expand Down Expand Up @@ -71,17 +77,23 @@ func (r *runners) createCustomer(cmd *cobra.Command, _ []string) (err error) {
}

opts := kotsclient.CreateCustomerOpts{
Name: r.args.customerCreateName,
CustomID: r.args.customerCreateCustomID,
ChannelID: channelID,
AppID: r.appID,
ExpiresAt: r.args.customerCreateExpiryDuration,
IsAirgapEnabled: r.args.customerCreateIsAirgapEnabled,
IsGitopsSupported: r.args.customerCreateIsGitopsSupported,
IsSnapshotSupported: r.args.customerCreateIsSnapshotSupported,
IsKotInstallEnabled: r.args.customerCreateIsKotInstallEnabled,
LicenseType: r.args.customerCreateType,
Email: r.args.customerCreateEmail,
Name: r.args.customerCreateName,
CustomID: r.args.customerCreateCustomID,
ChannelID: channelID,
AppID: r.appID,
ExpiresAtDuration: r.args.customerCreateExpiryDuration,
IsAirgapEnabled: r.args.customerCreateIsAirgapEnabled,
IsGitopsSupported: r.args.customerCreateIsGitopsSupported,
IsSnapshotSupported: r.args.customerCreateIsSnapshotSupported,
IsKotsInstallEnabled: r.args.customerCreateIsKotsInstallEnabled,
IsEmbeddedClusterDownloadEnabled: r.args.customerCreateIsEmbeddedClusterDownloadEnabled,
IsGeoaxisSupported: r.args.customerCreateIsGeoaxisSupported,
IsHelmVMDownloadEnabled: r.args.customerCreateIsHelmVMDownloadEnabled,
IsIdentityServiceSupported: r.args.customerCreateIsIdentityServiceSupported,
IsInstallerSupportEnabled: r.args.customerCreateIsInstallerSupportEnabled,
IsSupportBundleUploadEnabled: r.args.customerCreateIsSupportBundleUploadEnabled,
LicenseType: r.args.customerCreateType,
Email: r.args.customerCreateEmail,
}

customer, err := r.api.CreateCustomer(r.appType, opts)
Expand Down
113 changes: 113 additions & 0 deletions cli/cmd/customer_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package cmd

import (
"time"

"github.com/pkg/errors"
"github.com/replicatedhq/replicated/cli/print"
"github.com/replicatedhq/replicated/client"
"github.com/replicatedhq/replicated/pkg/kotsclient"
"github.com/spf13/cobra"
)

func (r *runners) InitCustomerUpdateCommand(parent *cobra.Command) *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Short: "update a customer",
Long: `update a customer`,
RunE: r.updateCustomer,
SilenceUsage: false,
SilenceErrors: true, // this command uses custom error printing
}
parent.AddCommand(cmd)
cmd.Flags().StringVar(&r.args.customerUpdateID, "customer", "", "The ID of the customer to update")
_ = cmd.MarkFlagRequired("customer")
cmd.Flags().StringVar(&r.args.customerUpdateName, "name", "", "Name of the customer")
cmd.Flags().StringVar(&r.args.customerUpdateCustomID, "custom-id", "", "Set a custom customer ID to more easily tie this customer record to your external data systems")
cmd.Flags().StringVar(&r.args.customerUpdateChannel, "channel", "", "Release channel to which the customer should be assigned")
cmd.Flags().DurationVar(&r.args.customerUpdateExpiryDuration, "expires-in", 0, "If set, an expiration date will be set on the license. Supports Go durations like '72h' or '3600m'")
cmd.Flags().BoolVar(&r.args.customerUpdateEnsureChannel, "ensure-channel", false, "If set, channel will be created if it does not exist.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsAirgapEnabled, "airgap", false, "If set, the license will allow airgap installs.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsGitopsSupported, "gitops", false, "If set, the license will allow the GitOps usage.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsSnapshotSupported, "snapshot", false, "If set, the license will allow Snapshots.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsKotsInstallEnabled, "kots-install", true, "If set, the license will allow KOTS install. Otherwise license will allow Helm CLI installs only.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsEmbeddedClusterDownloadEnabled, "embedded-cluster-download", false, "If set, the license will allow embedded cluster downloads.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsGeoaxisSupported, "geo-axis", false, "If set, the license will allow Geo Axis usage.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsHelmVMDownloadEnabled, "helmvm-cluster-download", false, "If set, the license will allow helmvm cluster downloads.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsIdentityServiceSupported, "identity-service", false, "If set, the license will allow Identity Service usage.")
cmd.Flags().BoolVar(&r.args.customerUpdateIsSupportBundleUploadEnabled, "support-bundle-upload", false, "If set, the license will allow uploading support bundles.")
cmd.Flags().StringVar(&r.args.customerUpdateEmail, "email", "", "Email address of the customer that is to be updated.")
cmd.Flags().StringVar(&r.args.customerUpdateType, "type", "dev", "The license type to update. One of: dev|trial|paid|community|test (default: dev)")
cmd.Flags().StringVar(&r.outputFormat, "output", "table", "The output format to use. One of: json|table (default: table)")
return cmd
}

func (r *runners) updateCustomer(cmd *cobra.Command, _ []string) (err error) {
defer func() {
printIfError(cmd, err)
}()
if r.args.customerUpdateID == "" {
return errors.Errorf("missing or invalid parameters: customer")
}

// all of the following validation occurs in the API also, but
// we want to fail fast if the user has provided invalid input
if err := validateCustomerType(r.args.customerUpdateType); err != nil {
return errors.Wrap(err, "validate customer type")
}
if r.args.customerUpdateType == "test" && r.args.customerUpdateExpiryDuration > time.Hour*48 {
return errors.New("test licenses cannot be updated with an expiration date greater than 48 hours")
}
if r.args.customerUpdateType == "paid" {
r.args.customerUpdateType = "prod"
}

channelID := ""
if r.args.customerUpdateChannel != "" {
getOrCreateChannelOptions := client.GetOrCreateChannelOptions{
AppID: r.appID,
AppType: r.appType,
NameOrID: r.args.customerUpdateChannel,
Description: "",
CreateIfAbsent: r.args.customerUpdateEnsureChannel,
}

channel, err := r.api.GetOrCreateChannelByName(getOrCreateChannelOptions)
if err != nil {
return errors.Wrap(err, "get channel")
}

channelID = channel.ID
}

opts := kotsclient.UpdateCustomerOpts{
Name: r.args.customerUpdateName,
CustomID: r.args.customerUpdateCustomID,
ChannelID: channelID,
AppID: r.appID,
ExpiresAtDuration: r.args.customerUpdateExpiryDuration,
IsAirgapEnabled: r.args.customerUpdateIsAirgapEnabled,
IsGitopsSupported: r.args.customerUpdateIsGitopsSupported,
IsSnapshotSupported: r.args.customerUpdateIsSnapshotSupported,
IsKotsInstallEnabled: r.args.customerUpdateIsKotsInstallEnabled,
IsEmbeddedClusterDownloadEnabled: r.args.customerUpdateIsEmbeddedClusterDownloadEnabled,
IsGeoaxisSupported: r.args.customerUpdateIsGeoaxisSupported,
IsHelmVMDownloadEnabled: r.args.customerUpdateIsHelmVMDownloadEnabled,
IsIdentityServiceSupported: r.args.customerUpdateIsIdentityServiceSupported,
IsSupportBundleUploadEnabled: r.args.customerUpdateIsSupportBundleUploadEnabled,
LicenseType: r.args.customerUpdateType,
Email: r.args.customerUpdateEmail,
}

customer, err := r.api.UpdateCustomer(r.appType, r.args.customerUpdateID, opts)
if err != nil {
return errors.Wrap(err, "update customer")
}

err = print.Customer(r.outputFormat, r.w, customer)
if err != nil {
return errors.Wrap(err, "print customer")
}

return nil
}
1 change: 1 addition & 0 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ func Execute(rootCmd *cobra.Command, stdin io.Reader, stdout io.Writer, stderr i
runCmds.InitCustomersDownloadLicenseCommand(customersCmd)
runCmds.InitCustomersArchiveCommand(customersCmd)
runCmds.InitCustomersInspectCommand(customersCmd)
runCmds.InitCustomerUpdateCommand(customersCmd)

instanceCmd := runCmds.InitInstanceCommand(runCmds.rootCmd)
runCmds.InitInstanceLSCommand(instanceCmd)
Expand Down
48 changes: 36 additions & 12 deletions cli/cmd/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,42 @@ type runnerArgs struct {

customerLsIncludeTest bool

customerArchiveNameOrId string
customerCreateName string
customerCreateCustomID string
customerCreateChannel string
customerCreateEnsureChannel bool
customerCreateExpiryDuration time.Duration
customerCreateIsAirgapEnabled bool
customerCreateIsGitopsSupported bool
customerCreateIsSnapshotSupported bool
customerCreateIsKotInstallEnabled bool
customerCreateEmail string
customerCreateType string
customerArchiveNameOrId string
customerCreateName string
customerCreateCustomID string
customerCreateChannel string
customerCreateEnsureChannel bool
customerCreateExpiryDuration time.Duration
customerCreateIsAirgapEnabled bool
customerCreateIsGitopsSupported bool
customerCreateIsSnapshotSupported bool
customerCreateIsKotsInstallEnabled bool
customerCreateIsEmbeddedClusterDownloadEnabled bool
customerCreateIsGeoaxisSupported bool
customerCreateIsHelmVMDownloadEnabled bool
customerCreateIsIdentityServiceSupported bool
customerCreateIsInstallerSupportEnabled bool
customerCreateIsSupportBundleUploadEnabled bool
customerCreateEmail string
customerCreateType string

customerUpdateID string
customerUpdateName string
customerUpdateCustomID string
customerUpdateChannel string
customerUpdateEnsureChannel bool
customerUpdateExpiryDuration time.Duration
customerUpdateIsAirgapEnabled bool
customerUpdateIsGitopsSupported bool
customerUpdateIsSnapshotSupported bool
customerUpdateIsKotsInstallEnabled bool
customerUpdateIsEmbeddedClusterDownloadEnabled bool
customerUpdateIsGeoaxisSupported bool
customerUpdateIsHelmVMDownloadEnabled bool
customerUpdateIsIdentityServiceSupported bool
customerUpdateIsSupportBundleUploadEnabled bool
customerUpdateEmail string
customerUpdateType string

instanceInspectCustomer string
instanceInspectInstance string
Expand Down
10 changes: 10 additions & 0 deletions client/customer.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ func (c *Client) CreateCustomer(appType string, opts kotsclient.CreateCustomerOp
return c.KotsClient.CreateCustomer(opts)
}

return nil, errors.Errorf("unknown app type %q", appType)
}

func (c *Client) UpdateCustomer(appType string, customerID string, opts kotsclient.UpdateCustomerOpts) (*types.Customer, error) {
if appType == "platform" {
return nil, errors.New("updating customers is not supported for platform applications")
} else if appType == "kots" {
return c.KotsClient.UpdateCustomer(customerID, opts)
}

return nil, errors.Errorf("unknown app type %q", appType)

}
Expand Down
Loading

0 comments on commit b2fc8f5

Please sign in to comment.