Skip to content

Commit

Permalink
Merge pull request #91 from kubesphere/cloud
Browse files Browse the repository at this point in the history
Integrate with KubeSphere Cloud
  • Loading branch information
iawia002 committed May 31, 2024
2 parents d1b2cfa + 5000d43 commit 32d302b
Show file tree
Hide file tree
Showing 11 changed files with 575 additions and 38 deletions.
61 changes: 61 additions & 0 deletions cmd/login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"errors"
"fmt"
"strings"

"github.com/manifoldco/promptui"
"github.com/spf13/cobra"

"github.com/kubesphere/ksbuilder/pkg/cloud"
"github.com/kubesphere/ksbuilder/pkg/config"
)

type loginOptions struct {
token string
server string
}

func loginCmd() *cobra.Command {
o := loginOptions{}

cmd := &cobra.Command{
Use: "login",
Short: "Login to KubeSphere Cloud",
Args: cobra.NoArgs,
RunE: o.login,
}
cmd.Flags().StringVarP(&o.token, "token", "t", "", "API access token")
cmd.Flags().StringVar(&o.server, "server", "https://apis.kubesphere.cloud", "API server address")
return cmd
}

func (o *loginOptions) login(_ *cobra.Command, _ []string) error {
if o.token == "" {
prompt := promptui.Prompt{
Label: "Enter API token",
Mask: '*',
Validate: func(input string) error {
if len(strings.TrimSpace(input)) <= 0 {
return errors.New("token can't be empty")
}
return nil
},
}
result, err := prompt.Run()
if err != nil {
return err
}
o.token = result
}

if _, err := cloud.NewClient(cloud.WithToken(o.token), cloud.WithServer(o.server)); err != nil {
return fmt.Errorf("login failed: %v", err)
}
if err := config.Write([]byte(o.token), o.server); err != nil {
return err
}
fmt.Println("Login Succeeded")
return nil
}
31 changes: 31 additions & 0 deletions cmd/logout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"

"github.com/kubesphere/ksbuilder/pkg/config"
)

type logoutOptions struct{}

func logoutCmd() *cobra.Command {
o := logoutOptions{}

cmd := &cobra.Command{
Use: "logout",
Short: "Log out from KubeSphere Cloud",
Args: cobra.NoArgs,
RunE: o.logout,
}
return cmd
}

func (o *logoutOptions) logout(_ *cobra.Command, _ []string) error {
if err := config.Remove(); err != nil {
return err
}
fmt.Println("Logout Succeeded")
return nil
}
136 changes: 136 additions & 0 deletions cmd/push.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package cmd

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"sigs.k8s.io/yaml"

"github.com/kubesphere/ksbuilder/pkg/cloud"
"github.com/kubesphere/ksbuilder/pkg/extension"
)

type pushOptions struct{}

func pushCmd() *cobra.Command {
o := pushOptions{}

cmd := &cobra.Command{
Use: "push",
Short: "Push and submit extensions to KubeSphere Cloud for review",
Long: `NOTE: We will upload static files such as icons and screenshots in the extension to the KubeSphere Cloud separately
and delete the static file directory in the original package to reduce the size of the entire chart`,
Args: cobra.ExactArgs(1),
RunE: o.push,
}
return cmd
}

func (o *pushOptions) push(_ *cobra.Command, args []string) error {
fmt.Printf("push extension %s\n", args[0])

client, err := cloud.NewClient()
if err != nil {
return fmt.Errorf("login failed: %v", err)
}

tempDir, err := os.MkdirTemp("", "chart")
if err != nil {
return err
}
defer os.RemoveAll(tempDir)
if err = extension.WriteFilesToTempDir(args[0], tempDir); err != nil {
return err
}

metadata, err := extension.LoadMetadata(tempDir)
if err != nil {
return err
}
// upload images to cloud
if needUpload(metadata.Icon) {
resp, err := client.UploadFiles(metadata.Name, metadata.Version, tempDir, metadata.Icon)
if err != nil {
return err
}
metadata.Icon = resp.Files[0].URL
}
screenshots := make([]string, 0)
localScreenshots := make([]string, 0)
for _, p := range metadata.Screenshots {
if needUpload(p) {
localScreenshots = append(localScreenshots, p)
} else {
screenshots = append(screenshots, p)
}
}
if len(localScreenshots) > 0 {
resp, err := client.UploadFiles(metadata.Name, metadata.Version, tempDir, localScreenshots...)
if err != nil {
return err
}
for _, f := range resp.Files {
screenshots = append(screenshots, f.URL)
}
metadata.Screenshots = screenshots
}
// delete static directory to reduce chart package size
if metadata.StaticFileDirectory != "" {
if err = os.RemoveAll(filepath.Join(tempDir, metadata.StaticFileDirectory)); err != nil && !os.IsNotExist(err) {
return err
}
}

data, err := yaml.Marshal(metadata)
if err != nil {
return err
}
if err = os.WriteFile(tempDir+"/"+extension.MetadataFilename, data, 0644); err != nil {
return err
}

chartYaml, err := metadata.ToChartYaml()
if err != nil {
return err
}
chartMetadata, err := yaml.Marshal(chartYaml)
if err != nil {
return err
}
if err = os.WriteFile(tempDir+"/Chart.yaml", chartMetadata, 0644); err != nil {
return err
}

ch, err := loader.LoadDir(tempDir)
if err != nil {
return err
}
chartFilename, err := chartutil.Save(ch, tempDir)
if err != nil {
return err
}

uploadExtensionResp, err := client.UploadExtension(metadata.Name, chartFilename)
if err != nil {
return err
}
if err = client.SubmitExtension(uploadExtensionResp.Snapshot.SnapshotID); err != nil {
return err
}
fmt.Println("Pushed to KubeSphere Cloud")
return nil
}

func needUpload(path string) bool {
if strings.HasPrefix(path, "http://") ||
strings.HasPrefix(path, "https://") ||
strings.HasPrefix(path, "data:image") {
return false
}
return true
}
3 changes: 3 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ func NewRootCmd(version string) *cobra.Command {
cmd.AddCommand(validateExtensionCmd())
cmd.AddCommand(lintExtensionCmd())
cmd.AddCommand(templateExtensionCmd())
cmd.AddCommand(loginCmd())
cmd.AddCommand(logoutCmd())
cmd.AddCommand(pushCmd())

return cmd
}
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ module github.com/kubesphere/ksbuilder
go 1.21

require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/Masterminds/sprig/v3 v3.2.3
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/manifoldco/promptui v0.9.0
github.com/mitchellh/go-homedir v1.1.0
github.com/otiai10/copy v1.7.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.7.0
Expand All @@ -28,10 +31,8 @@ require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/Microsoft/hcsshim v0.11.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKju
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
Expand Down
Loading

0 comments on commit 32d302b

Please sign in to comment.