diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a3c80d1..dac37ed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: restore-keys: ${{ runner.os }}-go- - name: Install staticcheck - run: go get -u golang.org/x/tools/... && go get honnef.co/go/tools/cmd/staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@2020.2.1 - name: Run 'go vet' run: go vet ./... diff --git a/cmd/serverless_cluster.go b/cmd/serverless_cluster.go new file mode 100644 index 0000000..c349ba4 --- /dev/null +++ b/cmd/serverless_cluster.go @@ -0,0 +1,179 @@ +package cmd + +import ( + "context" + "github.com/fatih/color" + "github.com/hazelcast/hazelcast-cloud-cli/internal" + "github.com/hazelcast/hazelcast-cloud-cli/util" + "github.com/hazelcast/hazelcast-cloud-sdk-go/models" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" +) + +func newServerlessClusterCmd() *cobra.Command { + return &cobra.Command{ + Use: "serverless-cluster", + Aliases: []string{"slc"}, + Short: "This command allows you to make actions on your serverless clusters like: create, delete, get, list, stop or resume.", + } +} + +func newServerlessClusterCreateCmd() *cobra.Command { + var createClusterInputParams models.CreateServerlessClusterInput + var devModeEnabled bool + + serverlessClusterCreateCmd := cobra.Command{ + Use: "create", + Short: "This command allows you to create a serverless Hazelcast cluster.", + Example: "hzcloud serverless-cluster create --name=mycluster --region=us-west-2", + RunE: func(cmd *cobra.Command, args []string) error { + if devModeEnabled { + createClusterInputParams.ClusterType = models.Devmode + } else { + createClusterInputParams.ClusterType = models.Serverless + } + client := internal.NewClient() + cluster := internal.Validate(client.ServerlessCluster.Create(context.Background(), &createClusterInputParams)).(*models.Cluster) + color.Green("Cluster %s is creating. You can check the status using hzcloud serverless-cluster list.", cluster.Id) + return nil + }, + } + + serverlessClusterCreateCmd.Flags().StringVar(&createClusterInputParams.Name, "name", "", "name of the cluster (required)") + _ = serverlessClusterCreateCmd.MarkFlagRequired("name") + + serverlessClusterCreateCmd.Flags().StringVar(&createClusterInputParams.Region, "region", "", "name of the region (required)") + _ = serverlessClusterCreateCmd.MarkFlagRequired("region") + + serverlessClusterCreateCmd.Flags().BoolVar(&devModeEnabled, "dev-mode-enabled", false, "development mode") + + return &serverlessClusterCreateCmd +} + +func newServerlessClusterListCmd() *cobra.Command { + return &cobra.Command{ + Use: "list", + Short: "This command allows you to create a serverless Hazelcast cluster.", + Example: "hzcloud serverless-cluster list", + Run: func(cmd *cobra.Command, args []string) { + client := internal.NewClient() + clusters := internal.Validate(client.ServerlessCluster.List(context.Background())).(*[]models.Cluster) + header := table.Row{"Id", "Name", "Type", "State", "Version", "Memory (GiB)", "Cloud Provider", "Region"} + var rows []table.Row + for _, cluster := range *clusters { + rows = append(rows, table.Row{cluster.Id, cluster.Name, cluster.ClusterType.Name, cluster.State, + cluster.HazelcastVersion, cluster.Specs.TotalMemory, cluster.CloudProvider.Name, + cluster.CloudProvider.Region}) + } + util.Print(util.PrintRequest{ + Header: header, + Rows: rows, + Data: clusters, + PrintStyle: util.PrintStyle(outputStyle), + }) + }, + } +} + +func newServerlessClusterGetCmd() *cobra.Command { + var serverlessClusterId string + + serverlessClusterGetCmd := cobra.Command{ + Use: "get", + Short: "This command get detailed configuration of a serverless Hazelcast cluster.", + Example: "hzcloud serverless-cluster get --cluster-id=100", + Run: func(cmd *cobra.Command, args []string) { + client := internal.NewClient() + cluster := internal.Validate(client.ServerlessCluster.Get(context.Background(), &models.GetServerlessClusterInput{ + ClusterId: serverlessClusterId, + })).(*models.Cluster) + util.Print(util.PrintRequest{ + Data: *cluster, + PrintStyle: util.PrintStyle(outputStyle), + }) + }, + } + + serverlessClusterGetCmd.Flags().StringVar(&serverlessClusterId, "cluster-id", "", "id of the cluster") + _ = serverlessClusterGetCmd.MarkFlagRequired("cluster-id") + + return &serverlessClusterGetCmd +} + +func newServerlessClusterDeleteCmd() *cobra.Command { + var serverlessClusterId string + + serverlessClusterDeleteCmd := &cobra.Command{ + Use: "delete", + Short: "This command allows you to delete a serverless Hazelcast cluster.", + Example: "hzcloud serverless-cluster delete --cluster-id=100", + Run: func(cmd *cobra.Command, args []string) { + client := internal.NewClient() + clusterResponse := internal.Validate(client.ServerlessCluster.Delete(context.Background(), &models.ClusterDeleteInput{ + ClusterId: serverlessClusterId, + })).(*models.ClusterId) + color.Blue("Cluster %d deleted.", clusterResponse.ClusterId) + }, + } + + serverlessClusterDeleteCmd.Flags().StringVar(&serverlessClusterId, "cluster-id", "", "id of the cluster") + _ = serverlessClusterDeleteCmd.MarkFlagRequired("cluster-id") + + return serverlessClusterDeleteCmd +} + +func newServerlessClusterStopCmd() *cobra.Command { + var serverlessClusterId string + + serverlessClusterStopCmd := &cobra.Command{ + Use: "stop", + Short: "This command allows you to stop a serverless Hazelcast cluster.", + Example: "hzcloud serverless-cluster stop --cluster-id=100", + Run: func(cmd *cobra.Command, args []string) { + client := internal.NewClient() + clusterResponse := internal.Validate(client.ServerlessCluster.Stop(context.Background(), &models.ClusterStopInput{ + ClusterId: serverlessClusterId, + })).(*models.ClusterId) + color.Blue("Cluster %d stopped.", clusterResponse.ClusterId) + }, + } + + serverlessClusterStopCmd.Flags().StringVar(&serverlessClusterId, "cluster-id", "", "id of the cluster") + _ = serverlessClusterStopCmd.MarkFlagRequired("cluster-id") + + return serverlessClusterStopCmd +} + +func newServerlessClusterResumeCmd() *cobra.Command { + var serverlessClusterId string + + serverlessClusterResumeCmd := &cobra.Command{ + Use: "resume", + Short: "This command allows you to resume a serverless Hazelcast cluster.", + Example: "hzcloud serverless-cluster resume --cluster-id=100", + Run: func(cmd *cobra.Command, args []string) { + client := internal.NewClient() + clusterResponse := internal.Validate(client.ServerlessCluster.Resume(context.Background(), &models.ClusterResumeInput{ + ClusterId: serverlessClusterId, + })).(*models.ClusterId) + color.Blue("Cluster %d resumed.", clusterResponse.ClusterId) + }, + } + + serverlessClusterResumeCmd.Flags().StringVar(&serverlessClusterId, "cluster-id", "", "id of the cluster") + _ = serverlessClusterResumeCmd.MarkFlagRequired("cluster-id") + + return serverlessClusterResumeCmd +} + +func init() { + serverlessClusterCmd := newServerlessClusterCmd() + rootCmd.AddCommand(serverlessClusterCmd) + + serverlessClusterCmd.AddCommand(newServerlessClusterCreateCmd()) + serverlessClusterCmd.AddCommand(newServerlessClusterListCmd()) + serverlessClusterCmd.AddCommand(newServerlessClusterGetCmd()) + serverlessClusterCmd.AddCommand(newServerlessClusterDeleteCmd()) + serverlessClusterCmd.AddCommand(newServerlessClusterStopCmd()) + serverlessClusterCmd.AddCommand(newServerlessClusterResumeCmd()) +} diff --git a/go.mod b/go.mod index c4eb64c..303f8aa 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/golang-jwt/jwt/v4 v4.1.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/uuid v1.3.0 - github.com/hazelcast/hazelcast-cloud-sdk-go v1.2.2 + github.com/hazelcast/hazelcast-cloud-sdk-go v1.3.0 github.com/jedib0t/go-pretty/v6 v6.2.4 github.com/mattn/go-colorable v0.1.11 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect diff --git a/go.sum b/go.sum index 22da3de..c115e87 100644 --- a/go.sum +++ b/go.sum @@ -232,8 +232,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hazelcast/hazelcast-cloud-sdk-go v1.2.2 h1:qeWmMA/oHjwe0cWhFLc+Zu9wlQ2s+GjZLe5n0mOeL/Q= -github.com/hazelcast/hazelcast-cloud-sdk-go v1.2.2/go.mod h1:3Iane/AnU7k1x2+t4C9BrE6CTGU/T/3i79DVFLbJLkg= +github.com/hazelcast/hazelcast-cloud-sdk-go v1.3.0 h1:YKuhdajxufEwY9EJpgBQZSjvPnxyCuBqUdeybPMTdPs= +github.com/hazelcast/hazelcast-cloud-sdk-go v1.3.0/go.mod h1:3Iane/AnU7k1x2+t4C9BrE6CTGU/T/3i79DVFLbJLkg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= diff --git a/util/cluster.go b/util/cluster.go index 9c44e81..8dbd45e 100644 --- a/util/cluster.go +++ b/util/cluster.go @@ -11,7 +11,7 @@ import ( "github.com/jedib0t/go-pretty/v6/list" ) -func AugmentStarterClusterType(starterClusterCreateClusterType string) (models.StarterClusterType, error) { +func AugmentStarterClusterType(starterClusterCreateClusterType string) (models.ClusterType, error) { switch strings.ToUpper(starterClusterCreateClusterType) { case "FREE": return models.Free, nil @@ -72,6 +72,11 @@ func printCluster(cluster models.Cluster, printStyle PrintStyle) { wr.AppendItem(fmt.Sprintf("Free: %t", cluster.ProductType.IsFree)) wr.UnIndent() + wr.AppendItem("Cluster Type") + wr.Indent() + wr.AppendItem(fmt.Sprintf("Name: %s", cluster.ClusterType.Name)) + wr.UnIndent() + wr.AppendItem(fmt.Sprintf("State: %s", cluster.State)) wr.AppendItem(fmt.Sprintf("Created at: %s", cluster.CreatedAt)) wr.AppendItem(fmt.Sprintf("Started at: %s", cluster.StartedAt))