From b2f8089c8759a61a38c68c8de1dc835aa0dbb91e Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Mon, 26 Aug 2019 17:58:10 +0800 Subject: [PATCH 01/10] Add cluster commands `get` --- go.mod | 3 +++ go.sum | 8 +++++++ pkg/ctl/cluster/cluster.go | 1 + pkg/ctl/cluster/create.go | 2 ++ pkg/ctl/cluster/get.go | 44 +++++++++++++++++++++++++++++++++++++ pkg/ctl/cluster/get_test.go | 41 ++++++++++++++++++++++++++++++++++ pkg/ctl/cluster/test.go | 37 +++++++++++++++++++++++++++++++ 7 files changed, 136 insertions(+) create mode 100644 pkg/ctl/cluster/get.go create mode 100644 pkg/ctl/cluster/get_test.go create mode 100644 pkg/ctl/cluster/test.go diff --git a/go.mod b/go.mod index 2bd7af3d..462249d1 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,14 @@ go 1.12 require ( github.com/fatih/color v1.7.0 // indirect + github.com/google/go-cmp v0.3.1 // indirect github.com/kris-nova/logger v0.0.0-20181127235838-fd0d87064b06 github.com/kris-nova/lolgopher v0.0.0-20180921204813-313b3abb0d9b // indirect github.com/mattn/go-colorable v0.1.2 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect github.com/olekukonko/tablewriter v0.0.1 + github.com/pkg/errors v0.8.1 // indirect github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.3 + gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index a025d289..c1a289a0 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/kris-nova/logger v0.0.0-20181127235838-fd0d87064b06 h1:vN4d3jSss3ExzUn2cE0WctxztfOgiKvMKnDrydBsg00= github.com/kris-nova/logger v0.0.0-20181127235838-fd0d87064b06/go.mod h1:++9BgZujZd4v0ZTZCb5iPsaomXdZWyxotIAh1IiDm44= @@ -26,6 +29,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -41,7 +46,10 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/pkg/ctl/cluster/cluster.go b/pkg/ctl/cluster/cluster.go index d5f831e7..6e007dd0 100644 --- a/pkg/ctl/cluster/cluster.go +++ b/pkg/ctl/cluster/cluster.go @@ -14,6 +14,7 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { cmdutils.AddVerbCmd(flagGrouping, resourceCmd, createClusterCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, listClustersCmd) + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getClusterConfiguration) return resourceCmd } diff --git a/pkg/ctl/cluster/create.go b/pkg/ctl/cluster/create.go index 5ad5675e..4152d1d7 100644 --- a/pkg/ctl/cluster/create.go +++ b/pkg/ctl/cluster/create.go @@ -1,6 +1,7 @@ package cluster import ( + "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/streamnative/pulsarctl/pkg/cmdutils" "github.com/streamnative/pulsarctl/pkg/pulsar" @@ -54,6 +55,7 @@ func createClusterCmd(vc *cmdutils.VerbCmd) { "p", []string{""}, "Cluster to be registered as a peer-cluster of this cluster.") + cobra.MarkFlagRequired(flagSet, "broker-url") }) } diff --git a/pkg/ctl/cluster/get.go b/pkg/ctl/cluster/get.go new file mode 100644 index 00000000..ea5c32a9 --- /dev/null +++ b/pkg/ctl/cluster/get.go @@ -0,0 +1,44 @@ +package cluster + +import ( + "encoding/json" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/streamnative/pulsarctl/pkg/cmdutils" +) + +func getClusterConfiguration(vc *cmdutils.VerbCmd) { + vc.SetDescription( + "get", + "Get the configuration data for the specified cluster", + "This command is used for getting the configuration data of the specified cluster.", + "get") + + var clusterName string + + vc.SetRunFuncWithNameArg(func() error { + return doGetClusterConfiguration(vc, clusterName) + }) + + vc.FlagSetGroup.InFlagSet("ClusterName", func(flagSet *pflag.FlagSet) { + flagSet.StringVar(&clusterName, "cluster-name", "", "Pulsar cluster name, e.g. pulsar-cluster") + cobra.MarkFlagRequired(flagSet, "cluster-name") + }) + +} + +func doGetClusterConfiguration(vc *cmdutils.VerbCmd, clusterName string) error { + admin := cmdutils.NewPulsarClient() + clusterData, err := admin.Clusters().Get(clusterName) + if err != nil { + cmdutils.PrintError(vc.Command.OutOrStderr(), err) + } else { + s, err := json.MarshalIndent(clusterData, "", " ") + if err != nil { + return err + } + vc.Command.Println(string(s)) + } + + return err +} diff --git a/pkg/ctl/cluster/get_test.go b/pkg/ctl/cluster/get_test.go new file mode 100644 index 00000000..640c288c --- /dev/null +++ b/pkg/ctl/cluster/get_test.go @@ -0,0 +1,41 @@ +package cluster + +import ( + "encoding/json" + "fmt" + "github.com/streamnative/pulsarctl/pkg/pulsar" + "gotest.tools/assert" + "regexp" + "testing" +) + + +func TestGetClusterConfiguration(t *testing.T) { + args := []string{"get","--cluster-name", "standalone"} + out, err := TestCommands(getClusterConfiguration, args) + if err != nil { + t.Error(err) + } + c := pulsar.ClusterData{} + err = json.Unmarshal(out.Bytes(), &c) + if err != nil { + fmt.Println(err) + } + + pulsarUrl, err := regexp.Compile("^pulsar://[a-z-A-Z]*:6650$") + if err != nil { + t.Error(err) + } + + res := pulsarUrl.MatchString(c.BrokerServiceURL) + assert.Equal(t, res, true) + + httpUrl, err := regexp.Compile("^http://[a-z-A-Z]*:8080$") + if err != nil { + t.Error(err) + } + + res = httpUrl.MatchString(c.ServiceURL) + assert.Equal(t, res, true) +} + diff --git a/pkg/ctl/cluster/test.go b/pkg/ctl/cluster/test.go new file mode 100644 index 00000000..e2bddead --- /dev/null +++ b/pkg/ctl/cluster/test.go @@ -0,0 +1,37 @@ +package cluster + +import ( + "bytes" + "github.com/kris-nova/logger" + "github.com/spf13/cobra" + "github.com/streamnative/pulsarctl/pkg/cmdutils" +) + +func TestCommands(newVerb func(cmd *cmdutils.VerbCmd), args []string) (out *bytes.Buffer, err error) { + var rootCmd = &cobra.Command { + Use: "pulsarctl [command]", + Short: "a CLI for Apache Pulsar", + Run: func(cmd *cobra.Command, _ []string) { + if err := cmd.Help(); err != nil { + logger.Debug("ignoring error %q", err.Error()) + } + }, + } + + buf := new(bytes.Buffer) + rootCmd.SetOut(buf) + rootCmd.SetArgs(append([]string{"clusters"}, args...)) + + + resourceCmd := cmdutils.NewResourceCmd( + "clusters", + "Operations about cluster(s)", + "", + "cluster") + flagGrouping := cmdutils.NewGrouping() + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, newVerb) + rootCmd.AddCommand(resourceCmd) + err = rootCmd.Execute() + + return buf, err +} \ No newline at end of file From c5a5be7298c71427bdc0d2377fe303caaea68827 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Mon, 26 Aug 2019 18:15:33 +0800 Subject: [PATCH 02/10] Add ci --- .github/workflow/ci.yml | 17 +++++++++++++++++ go.mod | 2 ++ go.sum | 9 +++++++++ pkg/ctl/cluster/get_test.go | 6 +++--- 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 .github/workflow/ci.yml diff --git a/.github/workflow/ci.yml b/.github/workflow/ci.yml new file mode 100644 index 00000000..a9f4ced7 --- /dev/null +++ b/.github/workflow/ci.yml @@ -0,0 +1,17 @@ +name: CI + + on: [pull-request] + + jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Run a one-line script + run: echo Hello, world! + - name: Run a multi-line script + run: | + echo Add other actions to build, + echo test, and deploy your project. diff --git a/go.mod b/go.mod index 462249d1..5d13712b 100644 --- a/go.mod +++ b/go.mod @@ -13,5 +13,7 @@ require ( github.com/pkg/errors v0.8.1 // indirect github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.3 + github.com/stretchr/objx v0.2.0 // indirect + github.com/stretchr/testify v1.3.0 gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index c1a289a0..3020e58f 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -31,6 +33,7 @@ github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXW github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -41,7 +44,13 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/pkg/ctl/cluster/get_test.go b/pkg/ctl/cluster/get_test.go index 640c288c..b0ed840e 100644 --- a/pkg/ctl/cluster/get_test.go +++ b/pkg/ctl/cluster/get_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" "github.com/streamnative/pulsarctl/pkg/pulsar" - "gotest.tools/assert" + "github.com/stretchr/testify/assert" "regexp" "testing" ) @@ -28,7 +28,7 @@ func TestGetClusterConfiguration(t *testing.T) { } res := pulsarUrl.MatchString(c.BrokerServiceURL) - assert.Equal(t, res, true) + assert.True(t, res) httpUrl, err := regexp.Compile("^http://[a-z-A-Z]*:8080$") if err != nil { @@ -36,6 +36,6 @@ func TestGetClusterConfiguration(t *testing.T) { } res = httpUrl.MatchString(c.ServiceURL) - assert.Equal(t, res, true) + assert.True(t, res) } From 7858d113eb657fc2657a70673127c97514d13a85 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Mon, 26 Aug 2019 20:23:16 +0800 Subject: [PATCH 03/10] Remove unused dependencies --- go.mod | 1 - pkg/ctl/cluster/get_test.go | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5d13712b..f7dc8ce7 100644 --- a/go.mod +++ b/go.mod @@ -15,5 +15,4 @@ require ( github.com/spf13/pflag v1.0.3 github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.3.0 - gotest.tools v2.2.0+incompatible ) diff --git a/pkg/ctl/cluster/get_test.go b/pkg/ctl/cluster/get_test.go index b0ed840e..b98b456c 100644 --- a/pkg/ctl/cluster/get_test.go +++ b/pkg/ctl/cluster/get_test.go @@ -22,7 +22,7 @@ func TestGetClusterConfiguration(t *testing.T) { fmt.Println(err) } - pulsarUrl, err := regexp.Compile("^pulsar://[a-z-A-Z]*:6650$") + pulsarUrl, err := regexp.Compile("^pulsar://[a-z-A-Z0-9]*:6650$") if err != nil { t.Error(err) } @@ -30,7 +30,7 @@ func TestGetClusterConfiguration(t *testing.T) { res := pulsarUrl.MatchString(c.BrokerServiceURL) assert.True(t, res) - httpUrl, err := regexp.Compile("^http://[a-z-A-Z]*:8080$") + httpUrl, err := regexp.Compile("^http://[a-z-A-Z0-9]*:8080$") if err != nil { t.Error(err) } From a214a8473b0735fa121b32403f49f5ebc2a4de5c Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Mon, 26 Aug 2019 20:25:09 +0800 Subject: [PATCH 04/10] Remove .github --- .github/workflow/ci.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .github/workflow/ci.yml diff --git a/.github/workflow/ci.yml b/.github/workflow/ci.yml deleted file mode 100644 index a9f4ced7..00000000 --- a/.github/workflow/ci.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: CI - - on: [pull-request] - - jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Run a one-line script - run: echo Hello, world! - - name: Run a multi-line script - run: | - echo Add other actions to build, - echo test, and deploy your project. From 9b95d266f80a54aeba17f834696511047d55d447 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 27 Aug 2019 15:14:33 +0800 Subject: [PATCH 05/10] Address most comments --- pkg/cmdutils/cmdutils.go | 2 +- pkg/ctl/cluster/cluster.go | 2 +- pkg/ctl/cluster/create.go | 2 -- pkg/ctl/cluster/get.go | 32 ++++++++++++++++++-------------- pkg/ctl/cluster/get_test.go | 6 +++--- pkg/ctl/cluster/test.go | 2 +- 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/pkg/cmdutils/cmdutils.go b/pkg/cmdutils/cmdutils.go index 572449ca..7d7757ce 100644 --- a/pkg/cmdutils/cmdutils.go +++ b/pkg/cmdutils/cmdutils.go @@ -30,7 +30,7 @@ func NewResourceCmd(use, short, long string, aliases ...string) *cobra.Command { // GetNameArg tests to ensure there is only 1 name argument func GetNameArg(args []string) string { - if len(args) > 1 { + if len(args) > 1 || len(args) == 0 { logger.Critical("only one argument is allowed to be used as a name") os.Exit(1) } diff --git a/pkg/ctl/cluster/cluster.go b/pkg/ctl/cluster/cluster.go index 6e007dd0..6d5bbf92 100644 --- a/pkg/ctl/cluster/cluster.go +++ b/pkg/ctl/cluster/cluster.go @@ -14,7 +14,7 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { cmdutils.AddVerbCmd(flagGrouping, resourceCmd, createClusterCmd) cmdutils.AddVerbCmd(flagGrouping, resourceCmd, listClustersCmd) - cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getClusterConfiguration) + cmdutils.AddVerbCmd(flagGrouping, resourceCmd, getClusterDataCmd) return resourceCmd } diff --git a/pkg/ctl/cluster/create.go b/pkg/ctl/cluster/create.go index 4152d1d7..5ad5675e 100644 --- a/pkg/ctl/cluster/create.go +++ b/pkg/ctl/cluster/create.go @@ -1,7 +1,6 @@ package cluster import ( - "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/streamnative/pulsarctl/pkg/cmdutils" "github.com/streamnative/pulsarctl/pkg/pulsar" @@ -55,7 +54,6 @@ func createClusterCmd(vc *cmdutils.VerbCmd) { "p", []string{""}, "Cluster to be registered as a peer-cluster of this cluster.") - cobra.MarkFlagRequired(flagSet, "broker-url") }) } diff --git a/pkg/ctl/cluster/get.go b/pkg/ctl/cluster/get.go index ea5c32a9..4c41a45b 100644 --- a/pkg/ctl/cluster/get.go +++ b/pkg/ctl/cluster/get.go @@ -2,32 +2,36 @@ package cluster import ( "encoding/json" - "github.com/spf13/cobra" - "github.com/spf13/pflag" + "errors" "github.com/streamnative/pulsarctl/pkg/cmdutils" ) -func getClusterConfiguration(vc *cmdutils.VerbCmd) { +func getClusterDataCmd(vc *cmdutils.VerbCmd) { vc.SetDescription( "get", "Get the configuration data for the specified cluster", - "This command is used for getting the configuration data of the specified cluster.", + "This command is used for getting the cluster data of the specified cluster.\n" + + "The output like this: \n" + + " { \n" + + " serviceUrl : http://localhost:8080, \n" + + " serviceUrlTls : https://localhost:8080, \n" + + " brokerServiceUrl: pulsar://localhost:6650, \n" + + " brokerServiceUrlTls: pulsar://localhost:6650, \n" + + " peerClusterNames: \"\" \n" + + " } \n", "get") - var clusterName string - vc.SetRunFuncWithNameArg(func() error { - return doGetClusterConfiguration(vc, clusterName) - }) - - vc.FlagSetGroup.InFlagSet("ClusterName", func(flagSet *pflag.FlagSet) { - flagSet.StringVar(&clusterName, "cluster-name", "", "Pulsar cluster name, e.g. pulsar-cluster") - cobra.MarkFlagRequired(flagSet, "cluster-name") + return doGetClusterData(vc) }) - } -func doGetClusterConfiguration(vc *cmdutils.VerbCmd, clusterName string) error { +func doGetClusterData(vc *cmdutils.VerbCmd) error { + clusterName := vc.NameArg + if clusterName == "" { + return errors.New("Should specified a cluster name") + } + admin := cmdutils.NewPulsarClient() clusterData, err := admin.Clusters().Get(clusterName) if err != nil { diff --git a/pkg/ctl/cluster/get_test.go b/pkg/ctl/cluster/get_test.go index b98b456c..26f72167 100644 --- a/pkg/ctl/cluster/get_test.go +++ b/pkg/ctl/cluster/get_test.go @@ -10,9 +10,9 @@ import ( ) -func TestGetClusterConfiguration(t *testing.T) { - args := []string{"get","--cluster-name", "standalone"} - out, err := TestCommands(getClusterConfiguration, args) +func TestGetClusterData(t *testing.T) { + args := []string{"get", "standalone"} + out, err := TestClusterCommands(getClusterDataCmd, args) if err != nil { t.Error(err) } diff --git a/pkg/ctl/cluster/test.go b/pkg/ctl/cluster/test.go index e2bddead..d8dcf90c 100644 --- a/pkg/ctl/cluster/test.go +++ b/pkg/ctl/cluster/test.go @@ -7,7 +7,7 @@ import ( "github.com/streamnative/pulsarctl/pkg/cmdutils" ) -func TestCommands(newVerb func(cmd *cmdutils.VerbCmd), args []string) (out *bytes.Buffer, err error) { +func TestClusterCommands(newVerb func(cmd *cmdutils.VerbCmd), args []string) (out *bytes.Buffer, err error) { var rootCmd = &cobra.Command { Use: "pulsarctl [command]", Short: "a CLI for Apache Pulsar", From e619bba3636747a08de5d41e5ebc64d865a342c7 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 27 Aug 2019 16:18:58 +0800 Subject: [PATCH 06/10] Add command description --- pkg/ctl/cluster/get.go | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/pkg/ctl/cluster/get.go b/pkg/ctl/cluster/get.go index 4c41a45b..e2515eab 100644 --- a/pkg/ctl/cluster/get.go +++ b/pkg/ctl/cluster/get.go @@ -6,19 +6,23 @@ import ( "github.com/streamnative/pulsarctl/pkg/cmdutils" ) + +var commandUsedFor = "This command is used for getting the cluster data of the specified cluster." +var commandExample = + "{\n" + + " serviceUrl : http://localhost:8080, \n" + + " serviceUrlTls : https://localhost:8080, \n" + + " brokerServiceUrl: pulsar://localhost:6650, \n" + + " brokerServiceUrlTls: pulsar+ssl://localhost:6650, \n" + + " peerClusterNames: \"\" \n" + + "}\n" +var commandPermission = "This command only admin can use." + func getClusterDataCmd(vc *cmdutils.VerbCmd) { vc.SetDescription( "get", "Get the configuration data for the specified cluster", - "This command is used for getting the cluster data of the specified cluster.\n" + - "The output like this: \n" + - " { \n" + - " serviceUrl : http://localhost:8080, \n" + - " serviceUrlTls : https://localhost:8080, \n" + - " brokerServiceUrl: pulsar://localhost:6650, \n" + - " brokerServiceUrlTls: pulsar://localhost:6650, \n" + - " peerClusterNames: \"\" \n" + - " } \n", + concat("\n"), "get") vc.SetRunFuncWithNameArg(func() error { @@ -46,3 +50,9 @@ func doGetClusterData(vc *cmdutils.VerbCmd) error { return err } + +func concat(join string) string { + return "USED FOR:" + join + "\t" + commandUsedFor + join + + "PERMISSION:" + join + "\t" + commandPermission + join + + "EXAMPLE:" + join + commandExample +} From c183bb9bee55cbc64ed9b83898134765cf6e85d2 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Wed, 28 Aug 2019 13:20:20 +0800 Subject: [PATCH 07/10] Add a simple long description of the command get --- pkg/ctl/cluster/get.go | 33 ++++++++++------------- pkg/pulsar/descriptions.go | 39 ++++++++++++++++++++++++++++ pkg/pulsar/descriptions_test.go | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 pkg/pulsar/descriptions.go create mode 100644 pkg/pulsar/descriptions_test.go diff --git a/pkg/ctl/cluster/get.go b/pkg/ctl/cluster/get.go index e2515eab..0f295c8d 100644 --- a/pkg/ctl/cluster/get.go +++ b/pkg/ctl/cluster/get.go @@ -4,25 +4,26 @@ import ( "encoding/json" "errors" "github.com/streamnative/pulsarctl/pkg/cmdutils" + "github.com/streamnative/pulsarctl/pkg/pulsar" ) - -var commandUsedFor = "This command is used for getting the cluster data of the specified cluster." -var commandExample = - "{\n" + - " serviceUrl : http://localhost:8080, \n" + - " serviceUrlTls : https://localhost:8080, \n" + - " brokerServiceUrl: pulsar://localhost:6650, \n" + - " brokerServiceUrlTls: pulsar+ssl://localhost:6650, \n" + - " peerClusterNames: \"\" \n" + - "}\n" -var commandPermission = "This command only admin can use." - func getClusterDataCmd(vc *cmdutils.VerbCmd) { + desc := pulsar.LongDescription{} + desc.CommandUsedFor = "This command is used for getting the cluster data of the specified cluster." + desc.CommandPermission = "This command requires super-user permissions." + + var examples []pulsar.Example + get := pulsar.Example{ + Desc: "getting the data.", + Command: "pulsarctl clusters get ", + } + examples = append(examples, get) + + desc.CommandExamples = examples vc.SetDescription( "get", "Get the configuration data for the specified cluster", - concat("\n"), + desc.ToString(), "get") vc.SetRunFuncWithNameArg(func() error { @@ -50,9 +51,3 @@ func doGetClusterData(vc *cmdutils.VerbCmd) error { return err } - -func concat(join string) string { - return "USED FOR:" + join + "\t" + commandUsedFor + join + - "PERMISSION:" + join + "\t" + commandPermission + join + - "EXAMPLE:" + join + commandExample -} diff --git a/pkg/pulsar/descriptions.go b/pkg/pulsar/descriptions.go new file mode 100644 index 00000000..aafb2067 --- /dev/null +++ b/pkg/pulsar/descriptions.go @@ -0,0 +1,39 @@ +package pulsar + +var SPACES = " " +var USED_FOR = "USED FOR:" +var PERMISSION = "REQUIRED PERMISSION:" +var EXAMPLES = "EXAMPLES:" +var OUTPUT = "OUTPUT:" + +type LongDescription struct { + CommandUsedFor string + CommandPermission string + CommandExamples []Example + CommandOutput string +} + +type Example struct { + Desc string + Command string +} + +func (desc *LongDescription) ToString() string { + return USED_FOR + "\n" + + SPACES + desc.CommandUsedFor + "\n" + + PERMISSION + "\n" + + SPACES + desc.CommandPermission + "\n" + + EXAMPLES + "\n" + + desc.exampleToString(SPACES) + + OUTPUT + "\n" + + SPACES + desc.CommandOutput + "\n" +} + +func (desc *LongDescription) exampleToString(space string) string { + var result string + for _, v := range desc.CommandExamples { + result += space + "#" + v.Desc + "\n" + + space + v.Command + "\n" + } + return result +} diff --git a/pkg/pulsar/descriptions_test.go b/pkg/pulsar/descriptions_test.go new file mode 100644 index 00000000..d644b1fa --- /dev/null +++ b/pkg/pulsar/descriptions_test.go @@ -0,0 +1,46 @@ +package pulsar + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestLongDescription_exampleToString(t *testing.T) { + desc := LongDescription{} + example := Example{ + Desc: "command description", + Command: "command", + } + desc.CommandExamples = []Example{example} + res := desc.exampleToString(" ") + + expect := " #command description\n" + + " command\n" + + assert.Equal(t, expect, res) +} + +func TestLongDescription_ToString(t *testing.T) { + desc := LongDescription{} + desc.CommandUsedFor = "command used for" + desc.CommandPermission = "command permission" + example := Example{} + example.Desc = "command description" + example.Command = "command" + desc.CommandExamples = []Example{example} + desc.CommandOutput = "out" + + expect := "USED FOR:\n" + + " " + desc.CommandUsedFor + "\n" + + "REQUIRED PERMISSION:\n" + + " " + desc.CommandPermission + "\n" + + "EXAMPLES:\n" + + " " + "#" + example.Desc + "\n" + + " " + example.Command + "\n" + + "OUTPUT:\n" + + " " + desc.CommandOutput + "\n" + + result := desc.ToString() + + assert.Equal(t, expect, result) +} \ No newline at end of file From 9cebaf4f59e537e6774a0e917281350f5cd4ab6e Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Wed, 28 Aug 2019 15:10:35 +0800 Subject: [PATCH 08/10] Update the description of the command get --- pkg/ctl/cluster/get.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/ctl/cluster/get.go b/pkg/ctl/cluster/get.go index 0f295c8d..73bbda7d 100644 --- a/pkg/ctl/cluster/get.go +++ b/pkg/ctl/cluster/get.go @@ -14,12 +14,14 @@ func getClusterDataCmd(vc *cmdutils.VerbCmd) { var examples []pulsar.Example get := pulsar.Example{ - Desc: "getting the data.", + Desc: "getting the data", Command: "pulsarctl clusters get ", } examples = append(examples, get) desc.CommandExamples = examples + desc.CommandOutput = "The configuration data of the specified cluster" + vc.SetDescription( "get", "Get the configuration data for the specified cluster", From 1d2d660c6aa6e967727a3d4cd5472b3b94b843ff Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Wed, 28 Aug 2019 15:35:51 +0800 Subject: [PATCH 09/10] Update the long description --- pkg/ctl/cluster/get.go | 34 ++++++++++++++++----- pkg/pulsar/descriptions.go | 53 +++++++++++++++++++++++---------- pkg/pulsar/descriptions_test.go | 26 +++++++++------- 3 files changed, 80 insertions(+), 33 deletions(-) diff --git a/pkg/ctl/cluster/get.go b/pkg/ctl/cluster/get.go index 73bbda7d..0f0f2e27 100644 --- a/pkg/ctl/cluster/get.go +++ b/pkg/ctl/cluster/get.go @@ -7,20 +7,40 @@ import ( "github.com/streamnative/pulsarctl/pkg/pulsar" ) -func getClusterDataCmd(vc *cmdutils.VerbCmd) { +func getClusterDataCmd(vc *cmdutils.VerbCmd) { desc := pulsar.LongDescription{} desc.CommandUsedFor = "This command is used for getting the cluster data of the specified cluster." desc.CommandPermission = "This command requires super-user permissions." var examples []pulsar.Example get := pulsar.Example{ - Desc: "getting the data", + Desc: "getting the data", Command: "pulsarctl clusters get ", } examples = append(examples, get) desc.CommandExamples = examples - desc.CommandOutput = "The configuration data of the specified cluster" + + var out []pulsar.Output + successOut := pulsar.Output{ + Desc: "normal output", + Out: "{\n " + + "\"serviceUrl\": \"http://f73710b9da2a:8080\",\n " + + "\"serviceUrlTls\": \"\",\n " + + "\"brokerServiceUrl\": \"pulsar://f73710b9da2a:6650\",\n " + + "\"brokerServiceUrlTls\": \"\",\n " + + "\"peerClusterNames\": null\n" + + "}", + } + out = append(out, successOut) + + failOut := pulsar.Output{ + Desc: "output of doesn't specified a cluster name", + Out: "only one argument is allowed to be used as a name", + } + out = append(out, failOut) + + desc.CommandOutput = out vc.SetDescription( "get", @@ -36,15 +56,13 @@ func getClusterDataCmd(vc *cmdutils.VerbCmd) { func doGetClusterData(vc *cmdutils.VerbCmd) error { clusterName := vc.NameArg if clusterName == "" { - return errors.New("Should specified a cluster name") + return errors.New("should specified a cluster name") } admin := cmdutils.NewPulsarClient() clusterData, err := admin.Clusters().Get(clusterName) - if err != nil { - cmdutils.PrintError(vc.Command.OutOrStderr(), err) - } else { - s, err := json.MarshalIndent(clusterData, "", " ") + if err == nil { + s, err := json.MarshalIndent(clusterData, "", " ") if err != nil { return err } diff --git a/pkg/pulsar/descriptions.go b/pkg/pulsar/descriptions.go index aafb2067..22094f78 100644 --- a/pkg/pulsar/descriptions.go +++ b/pkg/pulsar/descriptions.go @@ -1,39 +1,62 @@ package pulsar +import "strings" + var SPACES = " " -var USED_FOR = "USED FOR:" +var USED_FOR = "USED FOR:" var PERMISSION = "REQUIRED PERMISSION:" var EXAMPLES = "EXAMPLES:" var OUTPUT = "OUTPUT:" type LongDescription struct { - CommandUsedFor string + CommandUsedFor string CommandPermission string - CommandExamples []Example - CommandOutput string + CommandExamples []Example + CommandOutput []Output } type Example struct { - Desc string + Desc string Command string } +type Output struct { + Desc string + Out string +} + func (desc *LongDescription) ToString() string { return USED_FOR + "\n" + - SPACES + desc.CommandUsedFor + "\n" + - PERMISSION + "\n" + - SPACES + desc.CommandPermission + "\n" + - EXAMPLES + "\n" + - desc.exampleToString(SPACES) + - OUTPUT + "\n" + - SPACES + desc.CommandOutput + "\n" + SPACES + desc.CommandUsedFor + "\n\n" + + PERMISSION + "\n" + + SPACES + desc.CommandPermission + "\n\n" + + EXAMPLES + "\n" + + desc.exampleToString() + "\n" + + OUTPUT + "\n" + + desc.outputToString() } -func (desc *LongDescription) exampleToString(space string) string { +func (desc *LongDescription) exampleToString() string { var result string for _, v := range desc.CommandExamples { - result += space + "#" + v.Desc + "\n" + - space + v.Command + "\n" + result += SPACES + "#" + v.Desc + "\n" + SPACES + v.Command + "\n" } return result } + +func (desc *LongDescription) outputToString() string { + var result string + for _, v := range desc.CommandOutput { + result += SPACES + "#" + v.Desc + "\n" + makeSpace(v.Out) + "\n" + } + return result +} + +func makeSpace(s string) string { + var res string + lines := strings.Split(s, "\n") + for _, l := range lines { + res += SPACES + l + "\n" + } + return res +} diff --git a/pkg/pulsar/descriptions_test.go b/pkg/pulsar/descriptions_test.go index d644b1fa..99a5abaf 100644 --- a/pkg/pulsar/descriptions_test.go +++ b/pkg/pulsar/descriptions_test.go @@ -5,17 +5,17 @@ import ( "testing" ) -func TestLongDescription_exampleToString(t *testing.T) { +func TestLongDescription_exampleToString(t *testing.T) { desc := LongDescription{} example := Example{ - Desc: "command description", + Desc: "command description", Command: "command", } desc.CommandExamples = []Example{example} - res := desc.exampleToString(" ") + res := desc.exampleToString() expect := " #command description\n" + - " command\n" + " command\n" assert.Equal(t, expect, res) } @@ -28,19 +28,25 @@ func TestLongDescription_ToString(t *testing.T) { example.Desc = "command description" example.Command = "command" desc.CommandExamples = []Example{example} - desc.CommandOutput = "out" + out := Output{ + Desc: "Output", + Out: "Out line 1\nOut line 2", + } + desc.CommandOutput = []Output{out} expect := "USED FOR:\n" + - " " + desc.CommandUsedFor + "\n" + + " " + desc.CommandUsedFor + "\n\n" + "REQUIRED PERMISSION:\n" + - " " + desc.CommandPermission + "\n" + + " " + desc.CommandPermission + "\n\n" + "EXAMPLES:\n" + " " + "#" + example.Desc + "\n" + - " " + example.Command + "\n" + + " " + example.Command + "\n\n" + "OUTPUT:\n" + - " " + desc.CommandOutput + "\n" + " " + "#" + out.Desc + "\n" + + " " + "Out line 1" + "\n" + + " " + "Out line 2" + "\n\n" result := desc.ToString() assert.Equal(t, expect, result) -} \ No newline at end of file +} From 74c7a6cbf8ba2ed85f2bcc7ef80eef543e9c5b42 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Wed, 28 Aug 2019 15:38:14 +0800 Subject: [PATCH 10/10] Update description --- pkg/ctl/cluster/get.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/ctl/cluster/get.go b/pkg/ctl/cluster/get.go index 0f0f2e27..0a4fb6f7 100644 --- a/pkg/ctl/cluster/get.go +++ b/pkg/ctl/cluster/get.go @@ -25,9 +25,9 @@ func getClusterDataCmd(vc *cmdutils.VerbCmd) { successOut := pulsar.Output{ Desc: "normal output", Out: "{\n " + - "\"serviceUrl\": \"http://f73710b9da2a:8080\",\n " + + "\"serviceUrl\": \"http://localhost:8080\",\n " + "\"serviceUrlTls\": \"\",\n " + - "\"brokerServiceUrl\": \"pulsar://f73710b9da2a:6650\",\n " + + "\"brokerServiceUrl\": \"pulsar://localhost:6650\",\n " + "\"brokerServiceUrlTls\": \"\",\n " + "\"peerClusterNames\": null\n" + "}",