diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b33aa37..c15317f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: go version go env - name: Lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: version: v1.54 args: --timeout=10m diff --git a/cmd/get.go b/cmd/get.go new file mode 100644 index 0000000..76966c5 --- /dev/null +++ b/cmd/get.go @@ -0,0 +1,68 @@ +package cmd + +import ( + "fmt" + + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + + "github.com/kubesphere/ksbuilder/pkg/cloud" + "github.com/kubesphere/ksbuilder/pkg/utils" +) + +type getOptions struct{} + +func getCmd() *cobra.Command { + o := getOptions{} + + cmd := &cobra.Command{ + Use: "get", + Short: "Get the summary and snapshots list of the extension on KubeSphere Cloud", + Args: cobra.ExactArgs(1), + RunE: o.get, + } + return cmd +} + +func (o *getOptions) get(_ *cobra.Command, args []string) error { + client, err := cloud.NewClient() + if err != nil { + return fmt.Errorf("login failed: %v", err) + } + + extensionName := args[0] + extension, err := client.GetExtension(extensionName) + if err != nil { + return err + } + snapshots, err := client.ListExtensionSnapshots(extensionName) + if err != nil { + return err + } + + tabWriter := utils.NewTabWriter() + tabWriter.Write([]byte(fmt.Sprintf("Name:\t%s\n", extensionName))) // nolint + tabWriter.Write([]byte(fmt.Sprintf("ID:\t%s\n", extension.ExtensionID))) // nolint + tabWriter.Write([]byte(fmt.Sprintf("Status:\t%s\n", extension.Status))) // nolint + if extension.Status == "ready" { + tabWriter.Write([]byte(fmt.Sprintf("Latest version:\t%s\n", extension.LatestVersion.Version))) // nolint + } + tabWriter.Write([]byte("\n")) // nolint + tabWriter.Flush() // nolint + + rows := make([]table.Row, 0) + for _, snapshot := range snapshots { + rows = append(rows, table.Row{ + snapshot.SnapshotID, + snapshot.Metadata.Version, + snapshot.Status, + snapshot.UpdatedAt.Format("2006-01-02 15:04:05"), + }) + } + + t := utils.NewTableWriter() + t.AppendHeader(table.Row{"Snapshot ID", "Version", "Status", "Update time"}) + t.AppendRows(rows) + t.Render() + return nil +} diff --git a/cmd/push.go b/cmd/push.go index ecb3207..2f17542 100644 --- a/cmd/push.go +++ b/cmd/push.go @@ -122,7 +122,7 @@ func (o *pushOptions) push(_ *cobra.Command, args []string) error { if err = client.SubmitExtension(uploadExtensionResp.Snapshot.SnapshotID); err != nil { return err } - fmt.Println("Pushed to KubeSphere Cloud") + fmt.Println("Extension pushed and submitted to KubeSphere Cloud, waiting for review") return nil } diff --git a/cmd/root.go b/cmd/root.go index 49c479e..80f6606 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -29,6 +29,7 @@ func NewRootCmd(version string) *cobra.Command { cmd.AddCommand(loginCmd()) cmd.AddCommand(logoutCmd()) cmd.AddCommand(pushCmd()) + cmd.AddCommand(getCmd()) return cmd } diff --git a/go.mod b/go.mod index 802856e..0e328bf 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 github.com/go-playground/validator/v10 v10.14.1 github.com/iawia002/lia v0.5.1 + github.com/jedib0t/go-pretty/v6 v6.5.9 github.com/manifoldco/promptui v0.9.0 github.com/mitchellh/go-homedir v1.1.0 github.com/otiai10/copy v1.7.0 @@ -92,7 +93,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect @@ -113,6 +114,7 @@ require ( github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/rubenv/sql-migrate v1.5.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect diff --git a/go.sum b/go.sum index 221e707..5f9254a 100644 --- a/go.sum +++ b/go.sum @@ -310,8 +310,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -365,6 +365,8 @@ github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= +github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -436,8 +438,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= @@ -549,6 +551,8 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= diff --git a/pkg/cloud/cloud.go b/pkg/cloud/cloud.go index 31b3942..28a7267 100644 --- a/pkg/cloud/cloud.go +++ b/pkg/cloud/cloud.go @@ -206,3 +206,31 @@ func (c *Client) SubmitExtension(snapshotID string) error { nil, ) } + +func (c *Client) GetExtension(extensionName string) (*Extension, error) { + data := &Extension{} + if err := c.sendRequest( + http.MethodGet, + fmt.Sprintf("/apis/extension/v1/extensions/%s/summary", extensionName), + nil, + nil, + data, + ); err != nil { + return nil, err + } + return data, nil +} + +func (c *Client) ListExtensionSnapshots(extensionName string) ([]Snapshot, error) { + data := make([]Snapshot, 0) + if err := c.sendRequest( + http.MethodGet, + fmt.Sprintf("/apis/extension/v1/extensions/%s/snapshots", extensionName), + nil, + nil, + &data, + ); err != nil { + return nil, err + } + return data, nil +} diff --git a/pkg/cloud/types.go b/pkg/cloud/types.go index 493957d..492df54 100644 --- a/pkg/cloud/types.go +++ b/pkg/cloud/types.go @@ -1,5 +1,9 @@ package cloud +import ( + "time" +) + type userInfo struct { UserID string `json:"user_id"` } @@ -23,3 +27,20 @@ type UploadExtensionResponse struct { SnapshotID string `json:"snapshot_id"` } `json:"snapshot"` } + +type Snapshot struct { + SnapshotID string `json:"snapshot_id"` + Metadata struct { + Version string `json:"version"` + } `json:"metadata"` + Status string `json:"status"` + UpdatedAt time.Time `json:"updated_at"` +} + +type Extension struct { + ExtensionID string `json:"extension_id"` + Status string `json:"status"` + LatestVersion struct { + Version string `json:"version"` + } `json:"latest_version"` +} diff --git a/pkg/utils/table.go b/pkg/utils/table.go new file mode 100644 index 0000000..90c1524 --- /dev/null +++ b/pkg/utils/table.go @@ -0,0 +1,23 @@ +package utils + +import ( + "os" + "text/tabwriter" + + "github.com/jedib0t/go-pretty/v6/table" +) + +func NewTableWriter() table.Writer { + t := table.NewWriter() + t.SetOutputMirror(os.Stdout) + t.SetStyle(table.StyleDefault) + t.Style().Options = table.Options{} + t.Style().Box = table.BoxStyle{ + PaddingRight: " ", + } + return t +} + +func NewTabWriter() *tabwriter.Writer { + return tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0) +}