From 8eca75bba776b652f338ab5df3ac22b4162d3797 Mon Sep 17 00:00:00 2001 From: 1aal Date: Mon, 13 Nov 2023 20:37:40 +0800 Subject: [PATCH 1/9] feat: support addon index --- pkg/cmd/addon/addon.go | 8 +- pkg/cmd/addon/index.go | 176 ++++++++++++++++++++++++++++++++++++++++ pkg/cmd/cli.go | 1 - pkg/types/types.go | 8 ++ pkg/util/gitutil/git.go | 78 ++++++++++++++++++ pkg/util/util.go | 21 +++++ 6 files changed, 287 insertions(+), 5 deletions(-) create mode 100644 pkg/cmd/addon/index.go create mode 100644 pkg/util/gitutil/git.go diff --git a/pkg/cmd/addon/addon.go b/pkg/cmd/addon/addon.go index bca98c39d..3a5d7e5e2 100644 --- a/pkg/cmd/addon/addon.go +++ b/pkg/cmd/addon/addon.go @@ -100,6 +100,7 @@ func NewAddonCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.C newDescribeCmd(f, streams), newEnableCmd(f, streams), newDisableCmd(f, streams), + newIndexCmd(streams), ) return cmd } @@ -107,10 +108,9 @@ func NewAddonCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.C func newListCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { o := action.NewListOptions(f, streams, types.AddonGVR()) cmd := &cobra.Command{ - Use: "list", - Short: "List addons.", - Aliases: []string{"ls"}, - ValidArgsFunction: util.ResourceNameCompletionFunc(f, o.GVR), + Use: "list", + Short: "List addons.", + Aliases: []string{"ls"}, Run: func(cmd *cobra.Command, args []string) { o.Names = args util.CheckErr(addonListRun(o)) diff --git a/pkg/cmd/addon/index.go b/pkg/cmd/addon/index.go new file mode 100644 index 000000000..eb5ad3290 --- /dev/null +++ b/pkg/cmd/addon/index.go @@ -0,0 +1,176 @@ +package addon + +import ( + "errors" + "fmt" + "io" + "os" + "path" + "regexp" + + "github.com/apecloud/kbcli/pkg/printer" + "github.com/apecloud/kbcli/pkg/types" + "github.com/apecloud/kbcli/pkg/util" + "github.com/apecloud/kbcli/pkg/util/gitutil" + "github.com/spf13/cobra" + "k8s.io/cli-runtime/pkg/genericiooptions" + "k8s.io/klog/v2" +) + +type Index struct { + Name string + URL string +} + +func init() { + addonDir, err := util.GetCliAddonDir() + if err != nil { + klog.V(1).ErrorS(err, "can't get the addon ") + } + + defaultIndexDir := path.Join(addonDir, types.KubeBlocksReleaseName) + if _, err := os.Stat(defaultIndexDir); os.IsNotExist(err) { + err = gitutil.EnsureCloned(types.DefaultAddonIndexURL, defaultIndexDir) + if err != nil { + klog.V(1).ErrorS(err, "can't pull the DefaultAddonIndexURL", types.DefaultAddonIndexURL) + } + } else { + klog.V(1).ErrorS(err, "can't get the kbcli addon index dir") + } +} + +func newIndexListCmd(streams genericiooptions.IOStreams) *cobra.Command { + indexListCmd := &cobra.Command{Use: "list", + Short: "List addon indexes", + Long: `Print a list of addon indexes. + +This command prints a list of addon indexes. It shows the name and the remote URL for +each addon index in table format.`, + Args: cobra.NoArgs, + Run: func(_ *cobra.Command, _ []string) { + util.CheckErr(listIndexes(streams.Out)) + }, + } + return indexListCmd +} + +func newIndexAddCmd() *cobra.Command { + indexAddCmd := &cobra.Command{ + Use: "add", + Short: "Add a new index", + Long: "Configure a new index to install KubeBlocks addon from.", + Example: "kbcli index add KubeBlocks " + types.DefaultAddonIndexURL, + Args: cobra.ExactArgs(2), + Run: func(_ *cobra.Command, args []string) { + util.CheckErr(addAddonIndex(args)) + fmt.Printf("You have added a new index from %q\nThe addons in this index are not audited by ApeCloud.", args[1]) + }, + } + return indexAddCmd +} + +func newIndexDeleteCmd() *cobra.Command { + indexDeleteCmd := &cobra.Command{ + Use: "remove", + Short: "Remove an addon index", + Long: `Remove a configured addon index.`, + + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + util.CheckErr(indexDelete(args[0])) + }, + } + + return indexDeleteCmd +} + +func newIndexCmd(streams genericiooptions.IOStreams) *cobra.Command { + indexCmd := &cobra.Command{ + Use: "index", + Short: "Manage custom plugin indexes", + Long: "Manage which repositories are used to discover and install plugins from.", + Args: cobra.NoArgs, + } + indexCmd.AddCommand( + newIndexAddCmd(), + newIndexDeleteCmd(), + newIndexListCmd(streams), + ) + + return indexCmd +} + +// IsValidIndexName validates if an index name contains invalid characters +func IsValidIndexName(name string) bool { + var validNamePattern = regexp.MustCompile(`^[A-Za-z0-9_-]+$`) + return validNamePattern.MatchString(name) +} + +func addAddonIndex(args []string) error { + name, url := args[0], args[1] + if !IsValidIndexName(name) { + return errors.New("invalid index name") + } + + addonDir, err := util.GetCliAddonDir() + if err != nil { + return err + } + index := path.Join(addonDir, name) + if _, err := os.Stat(index); os.IsNotExist(err) { + return gitutil.EnsureCloned(url, index) + } else if err != nil { + return err + } + return errors.New("index already exists") +} + +func listIndexes(out io.Writer) error { + tbl := printer.NewTablePrinter(out) + tbl.SortBy(1) + tbl.SetHeader("INDEX", "URL") + + dir, err := util.GetCliAddonDir() + if err != nil { + return err + } + entries, err := os.ReadDir(dir) + if err != nil { + return fmt.Errorf("failed to list directory: %s", err.Error()) + } + + for _, e := range entries { + if !e.IsDir() { + continue + } + indexName := e.Name() + remote, err := gitutil.GetRemoteURL(path.Join(dir, indexName)) + if err != nil { + return fmt.Errorf("failed to list the remote URL for index %s due to %s", indexName, err.Error()) + } + tbl.AddRow(indexName, remote) + } + tbl.Print() + return nil +} + +func indexDelete(index string) error { + if IsValidIndexName(index) { + return errors.New("invalid index name") + } + + addonDir, err := util.GetCliAddonDir() + if err != nil { + return err + } + indexDir := path.Join(addonDir, index) + if _, err := os.Stat(indexDir); err == nil { + return os.RemoveAll(indexDir) + } else { + if os.IsNotExist(err) { + return fmt.Errorf("index %s does not exist", index) + } + return fmt.Errorf("error while removing the addon index: %s", err.Error()) + } + +} diff --git a/pkg/cmd/cli.go b/pkg/cmd/cli.go index d7ef0c4a1..d35a3edfa 100644 --- a/pkg/cmd/cli.go +++ b/pkg/cmd/cli.go @@ -251,7 +251,6 @@ func initConfig() { viper.SetDefault(types.CfgKeyClusterDefaultMemory, "1Gi") viper.SetDefault(types.CfgKeyHelmRepoURL, "") - // If a config file is found, read it in. if err := viper.ReadInConfig(); err == nil { fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) diff --git a/pkg/types/types.go b/pkg/types/types.go index 9769ad7e9..41e29b3b0 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -48,6 +48,11 @@ const ( // DefaultLogFilePrefix is the default log file prefix DefaultLogFilePrefix = "kbcli" + // AddonIndexEnv defines kbcli addon index dir + AddonIndexEnv = "KBCLI_ADDON_INDEX_DIR" + // AddonIndexDir is the default addon index dir + AddonIndexDir = "addon_index" + // DefaultNamespace is the namespace where kubeblocks is installed if // no other namespace is specified DefaultNamespace = "kb-system" @@ -222,6 +227,9 @@ var ( // KubeBlocksManagerConfigMapName the kubeblocks manager configMap name KubeBlocksManagerConfigMapName = fmt.Sprintf("%s-manager-config", KubeBlocksChartName) + + // DefaultAddonIndexURL points to the upstream index. + DefaultAddonIndexURL = "https://github.com/apecloud/block-index.git" ) // Playground diff --git a/pkg/util/gitutil/git.go b/pkg/util/gitutil/git.go new file mode 100644 index 000000000..58b772919 --- /dev/null +++ b/pkg/util/gitutil/git.go @@ -0,0 +1,78 @@ +package gitutil + +import ( + "bytes" + "io" + "os" + osexec "os/exec" + "path/filepath" + "strings" + + "github.com/pkg/errors" + "k8s.io/klog/v2" +) + +// EnsureCloned will clone into the destination path, otherwise will return no error. +func EnsureCloned(uri, destinationPath string) error { + if ok, err := IsGitCloned(destinationPath); err != nil { + return err + } else if !ok { + _, err = Exec("", "clone", "-v", uri, destinationPath) + return err + } + return nil +} + +// IsGitCloned will test if the path is a git dir. +func IsGitCloned(gitPath string) (bool, error) { + f, err := os.Stat(filepath.Join(gitPath, ".git")) + if os.IsNotExist(err) { + return false, nil + } + return err == nil && f.IsDir(), err +} + +// update will fetch origin and set HEAD to origin/HEAD +// and also will create a pristine working directory by removing +// untracked files and directories. +func updateAndCleanUntracked(destinationPath string) error { + if _, err := Exec(destinationPath, "fetch", "-v"); err != nil { + return errors.Wrapf(err, "fetch index at %q failed", destinationPath) + } + + if _, err := Exec(destinationPath, "reset", "--hard", "@{upstream}"); err != nil { + return errors.Wrapf(err, "reset index at %q failed", destinationPath) + } + + _, err := Exec(destinationPath, "clean", "-xfd") + return errors.Wrapf(err, "clean index at %q failed", destinationPath) +} + +// EnsureUpdated will ensure the destination path exists and is up to date. +func EnsureUpdated(uri, destinationPath string) error { + if err := EnsureCloned(uri, destinationPath); err != nil { + return err + } + return updateAndCleanUntracked(destinationPath) +} + +// GetRemoteURL returns the url of the remote origin +func GetRemoteURL(dir string) (string, error) { + return Exec(dir, "config", "--get", "remote.origin.url") +} + +func Exec(pwd string, args ...string) (string, error) { + klog.V(4).Infof("Going to run git %s", strings.Join(args, " ")) + cmd := osexec.Command("git", args...) + cmd.Dir = pwd + buf := bytes.Buffer{} + var w io.Writer = &buf + if klog.V(2).Enabled() { + w = io.MultiWriter(w, os.Stderr) + } + cmd.Stdout, cmd.Stderr = w, w + if err := cmd.Run(); err != nil { + return "", errors.Wrapf(err, "command execution failure, output=%q", buf.String()) + } + return strings.TrimSpace(buf.String()), nil +} diff --git a/pkg/util/util.go b/pkg/util/util.go index e2b209b33..661276180 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -106,6 +106,27 @@ func GetCliHomeDir() (string, error) { return cliHome, nil } +func GetCliAddonDir() (string, error) { + var addonIndexDir string + if custom := os.Getenv(types.AddonIndexEnv); custom != "" { + addonIndexDir = custom + } else { + home, err := GetCliHomeDir() + if err != nil { + return "", err + } + addonIndexDir = path.Join(home, types.AddonIndexDir) + } + + if _, err := os.Stat(addonIndexDir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(addonIndexDir, 0750); err != nil { + return "", errors.Wrap(err, "error when create addon index directory") + } + } + + return addonIndexDir, nil +} + // GetKubeconfigDir returns the kubeconfig directory. func GetKubeconfigDir() string { var kubeconfigDir string From 14f90188dd5901c38f06fd1fc7bd9bb1af8f0bca Mon Sep 17 00:00:00 2001 From: 1aal <1aal@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:40:04 +0000 Subject: [PATCH 2/9] chore: auto update cli doc changes --- docs/user_docs/cli/cli.md | 1 + docs/user_docs/cli/kbcli_addon.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/user_docs/cli/cli.md b/docs/user_docs/cli/cli.md index 3dac134e7..e3e5478d8 100644 --- a/docs/user_docs/cli/cli.md +++ b/docs/user_docs/cli/cli.md @@ -11,6 +11,7 @@ Addon command. * [kbcli addon describe](kbcli_addon_describe.md) - Describe an addon specification. * [kbcli addon disable](kbcli_addon_disable.md) - Disable an addon. * [kbcli addon enable](kbcli_addon_enable.md) - Enable an addon. +* [kbcli addon index](kbcli_addon_index.md) - Manage custom plugin indexes * [kbcli addon list](kbcli_addon_list.md) - List addons. diff --git a/docs/user_docs/cli/kbcli_addon.md b/docs/user_docs/cli/kbcli_addon.md index 15723c0e1..95df01197 100644 --- a/docs/user_docs/cli/kbcli_addon.md +++ b/docs/user_docs/cli/kbcli_addon.md @@ -40,6 +40,7 @@ Addon command. * [kbcli addon describe](kbcli_addon_describe.md) - Describe an addon specification. * [kbcli addon disable](kbcli_addon_disable.md) - Disable an addon. * [kbcli addon enable](kbcli_addon_enable.md) - Enable an addon. +* [kbcli addon index](kbcli_addon_index.md) - Manage custom plugin indexes * [kbcli addon list](kbcli_addon_list.md) - List addons. #### Go Back to [CLI Overview](cli.md) Homepage. From 9e74986a9c1533d26c871e1770affa1df3ef1b8f Mon Sep 17 00:00:00 2001 From: 1aal Date: Tue, 14 Nov 2023 21:01:49 +0800 Subject: [PATCH 3/9] chore: add fix-license-header --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index aa04666cb..5391d6bf4 100644 --- a/Makefile +++ b/Makefile @@ -327,4 +327,8 @@ endif KUBECTL=$(shell which kubectl) # NOTE: include must be placed at the end -include docker/docker.mk \ No newline at end of file +include docker/docker.mk + +.PHONY: fix-license-header +fix-license-header: ## Run license header fix. + @./hack/license/header-check.sh fix \ No newline at end of file From cf8ae9fb30955fbdb8748355a4b2e2688a5ed42a Mon Sep 17 00:00:00 2001 From: 1aal Date: Tue, 14 Nov 2023 21:02:25 +0800 Subject: [PATCH 4/9] feat: support index update --- pkg/cmd/addon/addon.go | 7 +- pkg/cmd/addon/index.go | 254 +++++++++++++++++++++++++++++++--------- pkg/types/types.go | 2 +- pkg/util/git.go | 11 ++ pkg/util/gitutil/git.go | 78 ------------ 5 files changed, 216 insertions(+), 136 deletions(-) delete mode 100644 pkg/util/gitutil/git.go diff --git a/pkg/cmd/addon/addon.go b/pkg/cmd/addon/addon.go index 3a5d7e5e2..c2f91fd02 100644 --- a/pkg/cmd/addon/addon.go +++ b/pkg/cmd/addon/addon.go @@ -108,9 +108,10 @@ func NewAddonCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.C func newListCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { o := action.NewListOptions(f, streams, types.AddonGVR()) cmd := &cobra.Command{ - Use: "list", - Short: "List addons.", - Aliases: []string{"ls"}, + Use: "list", + Short: "List addons.", + Aliases: []string{"ls"}, + ValidArgsFunction: util.ResourceNameCompletionFunc(f, o.GVR), Run: func(cmd *cobra.Command, args []string) { o.Names = args util.CheckErr(addonListRun(o)) diff --git a/pkg/cmd/addon/index.go b/pkg/cmd/addon/index.go index eb5ad3290..9301d0327 100644 --- a/pkg/cmd/addon/index.go +++ b/pkg/cmd/addon/index.go @@ -1,3 +1,22 @@ +/* +Copyright (C) 2022-2023 ApeCloud Co., Ltd + +This file is part of KubeBlocks project + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + package addon import ( @@ -7,36 +26,19 @@ import ( "os" "path" "regexp" + "strings" + + "github.com/spf13/cobra" + "k8s.io/cli-runtime/pkg/genericiooptions" "github.com/apecloud/kbcli/pkg/printer" "github.com/apecloud/kbcli/pkg/types" "github.com/apecloud/kbcli/pkg/util" - "github.com/apecloud/kbcli/pkg/util/gitutil" - "github.com/spf13/cobra" - "k8s.io/cli-runtime/pkg/genericiooptions" - "k8s.io/klog/v2" ) -type Index struct { - Name string - URL string -} - -func init() { - addonDir, err := util.GetCliAddonDir() - if err != nil { - klog.V(1).ErrorS(err, "can't get the addon ") - } - - defaultIndexDir := path.Join(addonDir, types.KubeBlocksReleaseName) - if _, err := os.Stat(defaultIndexDir); os.IsNotExist(err) { - err = gitutil.EnsureCloned(types.DefaultAddonIndexURL, defaultIndexDir) - if err != nil { - klog.V(1).ErrorS(err, "can't pull the DefaultAddonIndexURL", types.DefaultAddonIndexURL) - } - } else { - klog.V(1).ErrorS(err, "can't get the kbcli addon index dir") - } +type index struct { + name string + url string } func newIndexListCmd(streams genericiooptions.IOStreams) *cobra.Command { @@ -62,22 +64,35 @@ func newIndexAddCmd() *cobra.Command { Example: "kbcli index add KubeBlocks " + types.DefaultAddonIndexURL, Args: cobra.ExactArgs(2), Run: func(_ *cobra.Command, args []string) { - util.CheckErr(addAddonIndex(args)) - fmt.Printf("You have added a new index from %q\nThe addons in this index are not audited by ApeCloud.", args[1]) + util.CheckErr(addIndex(args)) + fmt.Printf("You have added a new index from %q\n", args[1]) }, } + + defaultIndexCmd := &cobra.Command{ + Use: "default", + Short: "Add the KubeBlocks default addon index: https://github.com/apecloud/block-index.git", + Args: cobra.NoArgs, + Run: func(_ *cobra.Command, args []string) { + util.CheckErr(addDefaultIndex()) + fmt.Printf("Default addon index \"kubeblocks\" has been added.") + }, + } + + indexAddCmd.AddCommand(defaultIndexCmd) return indexAddCmd } func newIndexDeleteCmd() *cobra.Command { indexDeleteCmd := &cobra.Command{ - Use: "remove", - Short: "Remove an addon index", - Long: `Remove a configured addon index.`, - - Args: cobra.ExactArgs(1), + Use: "delete", + Short: "Delete an addon index", + Long: `Delete a configured addon index.`, + ValidArgsFunction: indexCompletion(), + Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { - util.CheckErr(indexDelete(args[0])) + util.CheckErr(deleteIndex(args[0])) + fmt.Printf("Index \"%s\" have been deleted", args[0]) }, } @@ -87,26 +102,108 @@ func newIndexDeleteCmd() *cobra.Command { func newIndexCmd(streams genericiooptions.IOStreams) *cobra.Command { indexCmd := &cobra.Command{ Use: "index", - Short: "Manage custom plugin indexes", - Long: "Manage which repositories are used to discover and install plugins from.", + Short: "Manage custom addon indexes", + Long: "Manage which repositories are used to discover and install addon from.", Args: cobra.NoArgs, } indexCmd.AddCommand( newIndexAddCmd(), newIndexDeleteCmd(), newIndexListCmd(streams), + newIndexUpdateCmd(streams), ) return indexCmd } +type updateOption struct { + names []string + all bool + + genericiooptions.IOStreams +} + +// validate will check the update index whether existed +func (o *updateOption) validate(args []string) error { + indexes, err := getAllIndexes() + if err != nil { + return err + } + + if o.all { + for _, e := range indexes { + o.names = append(o.names, e.name) + } + return nil + } + if len(args) == 0 { + return fmt.Errorf("you must specify one index or use --all flag update all indexes.\nuse `kbcli addon index list` list all available indexes") + } + indexMaps := make(map[string]struct{}) + for _, index := range indexes { + indexMaps[index.name] = struct{}{} + } + for _, name := range args { + if _, ok := indexMaps[name]; !ok { + return fmt.Errorf("index %s don't existed", name) + } + o.names = append(o.names, name) + } + return nil +} + +func (o *updateOption) run() error { + addonDir, err := util.GetCliAddonDir() + if err != nil { + return err + } + // update := []string{} + + for _, name := range o.names { + + if isLatest, err := util.IsRepoLatest(path.Join(addonDir, name)); err == nil && isLatest { + fmt.Fprintf(o.Out, "index \"%s\" is already at the latest and requires no updates.\n", name) + continue + } + + err = util.UpdateAndCleanUntracked(path.Join(addonDir, name)) + if err != nil { + return fmt.Errorf("failed to update index %s due to %s", name, err.Error()) + } + fmt.Fprintf(o.Out, "index \"%s\" has been updated.\n", name) + } + + return nil +} + +func newIndexUpdateCmd(streams genericiooptions.IOStreams) *cobra.Command { + o := &updateOption{ + names: make([]string, 0), + all: false, + IOStreams: streams, + } + indexUpdateCmd := &cobra.Command{ + Use: "update", + Short: "update a existed index", + Long: "Update a existed index repository from index origin URL", + Example: "kbcli index update KubeBlocks", + ValidArgsFunction: indexCompletion(), + Run: func(cmd *cobra.Command, args []string) { + util.CheckErr(o.validate(args)) + util.CheckErr(o.run()) + }, + } + indexUpdateCmd.Flags().BoolVar(&o.all, "all", false, "Upgrade all addon index") + return indexUpdateCmd +} + // IsValidIndexName validates if an index name contains invalid characters func IsValidIndexName(name string) bool { var validNamePattern = regexp.MustCompile(`^[A-Za-z0-9_-]+$`) return validNamePattern.MatchString(name) } -func addAddonIndex(args []string) error { +func addIndex(args []string) error { name, url := args[0], args[1] if !IsValidIndexName(name) { return errors.New("invalid index name") @@ -118,7 +215,7 @@ func addAddonIndex(args []string) error { } index := path.Join(addonDir, name) if _, err := os.Stat(index); os.IsNotExist(err) { - return gitutil.EnsureCloned(url, index) + return util.EnsureCloned(url, index) } else if err != nil { return err } @@ -130,32 +227,19 @@ func listIndexes(out io.Writer) error { tbl.SortBy(1) tbl.SetHeader("INDEX", "URL") - dir, err := util.GetCliAddonDir() + indexes, err := getAllIndexes() if err != nil { return err } - entries, err := os.ReadDir(dir) - if err != nil { - return fmt.Errorf("failed to list directory: %s", err.Error()) - } - - for _, e := range entries { - if !e.IsDir() { - continue - } - indexName := e.Name() - remote, err := gitutil.GetRemoteURL(path.Join(dir, indexName)) - if err != nil { - return fmt.Errorf("failed to list the remote URL for index %s due to %s", indexName, err.Error()) - } - tbl.AddRow(indexName, remote) + for _, e := range indexes { + tbl.AddRow(e.name, e.url) } tbl.Print() return nil } -func indexDelete(index string) error { - if IsValidIndexName(index) { +func deleteIndex(index string) error { + if !IsValidIndexName(index) { return errors.New("invalid index name") } @@ -174,3 +258,65 @@ func indexDelete(index string) error { } } + +func addDefaultIndex() error { + addonDir, err := util.GetCliAddonDir() + if err != nil { + return fmt.Errorf("can't get the index dir : %s", err.Error()) + } + + defaultIndexDir := path.Join(addonDir, types.KubeBlocksReleaseName) + if _, err := os.Stat(defaultIndexDir); err != nil && os.IsNotExist(err) { + return util.EnsureCloned(types.DefaultAddonIndexURL, defaultIndexDir) + } + return fmt.Errorf("default index %s:%s already exists", types.KubeBlocksReleaseName, types.DefaultAddonIndexURL) +} + +func getAllIndexes() ([]index, error) { + addonDir, err := util.GetCliAddonDir() + if err != nil { + return nil, err + } + entries, err := os.ReadDir(addonDir) + if err != nil { + return nil, err + } + res := []index{} + for _, e := range entries { + if !e.IsDir() { + continue + } + indexName := e.Name() + remote, err := util.GitGetRemoteURL(path.Join(addonDir, indexName)) + if err != nil { + return nil, err + } + res = append(res, index{ + name: indexName, + url: remote, + }) + } + return res, nil +} + +func indexCompletion() func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + availableComps := []string{} + indexes, err := getAllIndexes() + if err != nil { + return availableComps, cobra.ShellCompDirectiveNoFileComp + } + seen := make(map[string]struct{}) + for _, input := range args { + seen[input] = struct{}{} + } + + for _, e := range indexes { + if _, ok := seen[e.name]; !ok && strings.HasPrefix(e.name, toComplete) { + availableComps = append(availableComps, e.name) + } + } + + return availableComps, cobra.ShellCompDirectiveNoFileComp + } +} diff --git a/pkg/types/types.go b/pkg/types/types.go index 77188a680..bd8718828 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -54,7 +54,7 @@ const ( // AddonIndexEnv defines kbcli addon index dir AddonIndexEnv = "KBCLI_ADDON_INDEX_DIR" // AddonIndexDir is the default addon index dir - AddonIndexDir = "addon_index" + AddonIndexDir = "index" // DefaultNamespace is the namespace where kubeblocks is installed if // no other namespace is specified diff --git a/pkg/util/git.go b/pkg/util/git.go index bf8ea9adf..ec56b8349 100644 --- a/pkg/util/git.go +++ b/pkg/util/git.go @@ -142,3 +142,14 @@ func ExecGitCommand(pwd string, args ...string) (string, error) { } return strings.TrimSpace(buf.String()), nil } + +func IsRepoLatest(destinationPath string) (bool, error) { + if _, err := ExecGitCommand(destinationPath, "fetch", "-v"); err != nil { + return false, err + } + output, err := ExecGitCommand(destinationPath, "status", "-uno", "--porcelain") + if err != nil { + return false, err + } + return output == "", nil +} diff --git a/pkg/util/gitutil/git.go b/pkg/util/gitutil/git.go deleted file mode 100644 index 58b772919..000000000 --- a/pkg/util/gitutil/git.go +++ /dev/null @@ -1,78 +0,0 @@ -package gitutil - -import ( - "bytes" - "io" - "os" - osexec "os/exec" - "path/filepath" - "strings" - - "github.com/pkg/errors" - "k8s.io/klog/v2" -) - -// EnsureCloned will clone into the destination path, otherwise will return no error. -func EnsureCloned(uri, destinationPath string) error { - if ok, err := IsGitCloned(destinationPath); err != nil { - return err - } else if !ok { - _, err = Exec("", "clone", "-v", uri, destinationPath) - return err - } - return nil -} - -// IsGitCloned will test if the path is a git dir. -func IsGitCloned(gitPath string) (bool, error) { - f, err := os.Stat(filepath.Join(gitPath, ".git")) - if os.IsNotExist(err) { - return false, nil - } - return err == nil && f.IsDir(), err -} - -// update will fetch origin and set HEAD to origin/HEAD -// and also will create a pristine working directory by removing -// untracked files and directories. -func updateAndCleanUntracked(destinationPath string) error { - if _, err := Exec(destinationPath, "fetch", "-v"); err != nil { - return errors.Wrapf(err, "fetch index at %q failed", destinationPath) - } - - if _, err := Exec(destinationPath, "reset", "--hard", "@{upstream}"); err != nil { - return errors.Wrapf(err, "reset index at %q failed", destinationPath) - } - - _, err := Exec(destinationPath, "clean", "-xfd") - return errors.Wrapf(err, "clean index at %q failed", destinationPath) -} - -// EnsureUpdated will ensure the destination path exists and is up to date. -func EnsureUpdated(uri, destinationPath string) error { - if err := EnsureCloned(uri, destinationPath); err != nil { - return err - } - return updateAndCleanUntracked(destinationPath) -} - -// GetRemoteURL returns the url of the remote origin -func GetRemoteURL(dir string) (string, error) { - return Exec(dir, "config", "--get", "remote.origin.url") -} - -func Exec(pwd string, args ...string) (string, error) { - klog.V(4).Infof("Going to run git %s", strings.Join(args, " ")) - cmd := osexec.Command("git", args...) - cmd.Dir = pwd - buf := bytes.Buffer{} - var w io.Writer = &buf - if klog.V(2).Enabled() { - w = io.MultiWriter(w, os.Stderr) - } - cmd.Stdout, cmd.Stderr = w, w - if err := cmd.Run(); err != nil { - return "", errors.Wrapf(err, "command execution failure, output=%q", buf.String()) - } - return strings.TrimSpace(buf.String()), nil -} From 14467e195c2f10d68ada0dc946ac93b2f8d4fb0a Mon Sep 17 00:00:00 2001 From: 1aal <1aal@users.noreply.github.com> Date: Tue, 14 Nov 2023 13:04:38 +0000 Subject: [PATCH 5/9] chore: auto update cli doc changes --- docs/user_docs/cli/cli.md | 2 +- docs/user_docs/cli/kbcli_addon.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user_docs/cli/cli.md b/docs/user_docs/cli/cli.md index e3e5478d8..8277bb097 100644 --- a/docs/user_docs/cli/cli.md +++ b/docs/user_docs/cli/cli.md @@ -11,7 +11,7 @@ Addon command. * [kbcli addon describe](kbcli_addon_describe.md) - Describe an addon specification. * [kbcli addon disable](kbcli_addon_disable.md) - Disable an addon. * [kbcli addon enable](kbcli_addon_enable.md) - Enable an addon. -* [kbcli addon index](kbcli_addon_index.md) - Manage custom plugin indexes +* [kbcli addon index](kbcli_addon_index.md) - Manage custom addon indexes * [kbcli addon list](kbcli_addon_list.md) - List addons. diff --git a/docs/user_docs/cli/kbcli_addon.md b/docs/user_docs/cli/kbcli_addon.md index 95df01197..265b42d78 100644 --- a/docs/user_docs/cli/kbcli_addon.md +++ b/docs/user_docs/cli/kbcli_addon.md @@ -40,7 +40,7 @@ Addon command. * [kbcli addon describe](kbcli_addon_describe.md) - Describe an addon specification. * [kbcli addon disable](kbcli_addon_disable.md) - Disable an addon. * [kbcli addon enable](kbcli_addon_enable.md) - Enable an addon. -* [kbcli addon index](kbcli_addon_index.md) - Manage custom plugin indexes +* [kbcli addon index](kbcli_addon_index.md) - Manage custom addon indexes * [kbcli addon list](kbcli_addon_list.md) - List addons. #### Go Back to [CLI Overview](cli.md) Homepage. From e5695fe4afba5604978939a20293a37e360c4d0d Mon Sep 17 00:00:00 2001 From: 1aal Date: Wed, 15 Nov 2023 09:53:19 +0800 Subject: [PATCH 6/9] fix usage --- pkg/cmd/addon/index.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/addon/index.go b/pkg/cmd/addon/index.go index 9301d0327..f6e1e3db7 100644 --- a/pkg/cmd/addon/index.go +++ b/pkg/cmd/addon/index.go @@ -59,9 +59,9 @@ each addon index in table format.`, func newIndexAddCmd() *cobra.Command { indexAddCmd := &cobra.Command{ Use: "add", - Short: "Add a new index", + Short: "Add a new addon index", Long: "Configure a new index to install KubeBlocks addon from.", - Example: "kbcli index add KubeBlocks " + types.DefaultAddonIndexURL, + Example: "kbcli index add kubeblocks " + types.DefaultAddonIndexURL, Args: cobra.ExactArgs(2), Run: func(_ *cobra.Command, args []string) { util.CheckErr(addIndex(args)) @@ -184,8 +184,8 @@ func newIndexUpdateCmd(streams genericiooptions.IOStreams) *cobra.Command { } indexUpdateCmd := &cobra.Command{ Use: "update", - Short: "update a existed index", - Long: "Update a existed index repository from index origin URL", + Short: "update the specified index(es)", + Long: "Update existed index repository from index origin URL", Example: "kbcli index update KubeBlocks", ValidArgsFunction: indexCompletion(), Run: func(cmd *cobra.Command, args []string) { From 765326f7d885545be9397db1269137f95e3fb59f Mon Sep 17 00:00:00 2001 From: 1aal Date: Wed, 15 Nov 2023 10:57:05 +0800 Subject: [PATCH 7/9] fix index --- Makefile | 8 ++++---- pkg/cmd/addon/index.go | 36 ++++++++++++++++++------------------ pkg/types/types.go | 10 ++++++---- pkg/util/util.go | 2 +- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index 5391d6bf4..2878ea50b 100644 --- a/Makefile +++ b/Makefile @@ -326,9 +326,9 @@ ifeq (, $(shell which kubectl)) endif KUBECTL=$(shell which kubectl) -# NOTE: include must be placed at the end -include docker/docker.mk - .PHONY: fix-license-header fix-license-header: ## Run license header fix. - @./hack/license/header-check.sh fix \ No newline at end of file + @./hack/license/header-check.sh fix + +# NOTE: include must be placed at the end +include docker/docker.mk diff --git a/pkg/cmd/addon/index.go b/pkg/cmd/addon/index.go index f6e1e3db7..eda268745 100644 --- a/pkg/cmd/addon/index.go +++ b/pkg/cmd/addon/index.go @@ -63,23 +63,14 @@ func newIndexAddCmd() *cobra.Command { Long: "Configure a new index to install KubeBlocks addon from.", Example: "kbcli index add kubeblocks " + types.DefaultAddonIndexURL, Args: cobra.ExactArgs(2), - Run: func(_ *cobra.Command, args []string) { - util.CheckErr(addIndex(args)) - fmt.Printf("You have added a new index from %q\n", args[1]) + PersistentPreRun: func(_ *cobra.Command, _ []string) { + util.CheckErr(addDefaultIndex()) }, - } - - defaultIndexCmd := &cobra.Command{ - Use: "default", - Short: "Add the KubeBlocks default addon index: https://github.com/apecloud/block-index.git", - Args: cobra.NoArgs, Run: func(_ *cobra.Command, args []string) { - util.CheckErr(addDefaultIndex()) - fmt.Printf("Default addon index \"kubeblocks\" has been added.") + util.CheckErr(addIndex(args)) }, } - indexAddCmd.AddCommand(defaultIndexCmd) return indexAddCmd } @@ -92,7 +83,6 @@ func newIndexDeleteCmd() *cobra.Command { Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { util.CheckErr(deleteIndex(args[0])) - fmt.Printf("Index \"%s\" have been deleted", args[0]) }, } @@ -157,8 +147,6 @@ func (o *updateOption) run() error { if err != nil { return err } - // update := []string{} - for _, name := range o.names { if isLatest, err := util.IsRepoLatest(path.Join(addonDir, name)); err == nil && isLatest { @@ -215,7 +203,11 @@ func addIndex(args []string) error { } index := path.Join(addonDir, name) if _, err := os.Stat(index); os.IsNotExist(err) { - return util.EnsureCloned(url, index) + if err = util.EnsureCloned(url, index); err != nil { + return err + } + fmt.Printf("You have added a new index from %q\n", args[1]) + return err } else if err != nil { return err } @@ -249,7 +241,11 @@ func deleteIndex(index string) error { } indexDir := path.Join(addonDir, index) if _, err := os.Stat(indexDir); err == nil { - return os.RemoveAll(indexDir) + if err = os.RemoveAll(indexDir); err != nil { + return err + } + fmt.Printf("Index \"%s\" have been deleted", index) + return nil } else { if os.IsNotExist(err) { return fmt.Errorf("index %s does not exist", index) @@ -267,7 +263,11 @@ func addDefaultIndex() error { defaultIndexDir := path.Join(addonDir, types.KubeBlocksReleaseName) if _, err := os.Stat(defaultIndexDir); err != nil && os.IsNotExist(err) { - return util.EnsureCloned(types.DefaultAddonIndexURL, defaultIndexDir) + if err = util.EnsureCloned(types.DefaultAddonIndexURL, defaultIndexDir); err != nil { + return err + } + fmt.Printf("Default addon index \"kubeblocks\" has been added.") + return nil } return fmt.Errorf("default index %s:%s already exists", types.KubeBlocksReleaseName, types.DefaultAddonIndexURL) } diff --git a/pkg/types/types.go b/pkg/types/types.go index bd8718828..7adb4e58e 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -21,6 +21,7 @@ package types import ( "fmt" + "path/filepath" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" @@ -51,10 +52,8 @@ const ( // DefaultLogFilePrefix is the default log file prefix DefaultLogFilePrefix = "kbcli" - // AddonIndexEnv defines kbcli addon index dir - AddonIndexEnv = "KBCLI_ADDON_INDEX_DIR" - // AddonIndexDir is the default addon index dir - AddonIndexDir = "index" + // AddonIndexDirEnv defines kbcli addon index dir + AddonIndexDirEnv = "KBCLI_ADDON_INDEX_DIR" // DefaultNamespace is the namespace where kubeblocks is installed if // no other namespace is specified @@ -233,6 +232,9 @@ var ( // DefaultAddonIndexURL points to the upstream index. DefaultAddonIndexURL = "https://github.com/apecloud/block-index.git" + + // AddonIndexDir is the default addon index dir + AddonIndexDir = filepath.Join("addon", "index") ) // Playground diff --git a/pkg/util/util.go b/pkg/util/util.go index f39d9c30a..726fca9ae 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -124,7 +124,7 @@ func GetCliLogDir() (string, error) { // GetCliAddonDir returns kbcli addon index dir func GetCliAddonDir() (string, error) { var addonIndexDir string - if custom := os.Getenv(types.AddonIndexEnv); custom != "" { + if custom := os.Getenv(types.AddonIndexDirEnv); custom != "" { addonIndexDir = custom } else { home, err := GetCliHomeDir() From ff976645e411995104db3697972040ed307b7e5e Mon Sep 17 00:00:00 2001 From: 1aal Date: Wed, 15 Nov 2023 17:21:36 +0800 Subject: [PATCH 8/9] fix: fix the usage and user_docs --- docs/user_docs/cli/kbcli_addon_index.md | 50 ++++++++++++++++ docs/user_docs/cli/kbcli_addon_index_add.md | 56 ++++++++++++++++++ .../user_docs/cli/kbcli_addon_index_delete.md | 50 ++++++++++++++++ docs/user_docs/cli/kbcli_addon_index_list.md | 53 +++++++++++++++++ .../user_docs/cli/kbcli_addon_index_update.md | 57 +++++++++++++++++++ docs/user_docs/cli/kbcli_cluster_create.md | 2 + pkg/cmd/addon/index.go | 4 +- 7 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 docs/user_docs/cli/kbcli_addon_index.md create mode 100644 docs/user_docs/cli/kbcli_addon_index_add.md create mode 100644 docs/user_docs/cli/kbcli_addon_index_delete.md create mode 100644 docs/user_docs/cli/kbcli_addon_index_list.md create mode 100644 docs/user_docs/cli/kbcli_addon_index_update.md diff --git a/docs/user_docs/cli/kbcli_addon_index.md b/docs/user_docs/cli/kbcli_addon_index.md new file mode 100644 index 000000000..c8a6b459e --- /dev/null +++ b/docs/user_docs/cli/kbcli_addon_index.md @@ -0,0 +1,50 @@ +--- +title: kbcli addon index +--- + +Manage custom addon indexes + +### Synopsis + +Manage which repositories are used to discover and install addon from. + +### Options + +``` + -h, --help help for index +``` + +### Options inherited from parent commands + +``` + --as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace. + --as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --as-uid string UID to impersonate for the operation. + --cache-dir string Default cache directory (default "$HOME/.kube/cache") + --certificate-authority string Path to a cert file for the certificate authority + --client-certificate string Path to a client certificate file for TLS + --client-key string Path to a client key file for TLS + --cluster string The name of the kubeconfig cluster to use + --context string The name of the kubeconfig context to use + --disable-compression If true, opt-out of response compression for all requests to the server + --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + --match-server-version Require server version to match client version + -n, --namespace string If present, the namespace scope for this CLI request + --request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0") + -s, --server string The address and port of the Kubernetes API server + --tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used + --token string Bearer token for authentication to the API server + --user string The name of the kubeconfig user to use +``` + +### SEE ALSO + +* [kbcli addon](kbcli_addon.md) - Addon command. +* [kbcli addon index add](kbcli_addon_index_add.md) - Add a new addon index +* [kbcli addon index delete](kbcli_addon_index_delete.md) - Delete an addon index +* [kbcli addon index list](kbcli_addon_index_list.md) - List addon indexes +* [kbcli addon index update](kbcli_addon_index_update.md) - update the specified index(es) + +#### Go Back to [CLI Overview](cli.md) Homepage. + diff --git a/docs/user_docs/cli/kbcli_addon_index_add.md b/docs/user_docs/cli/kbcli_addon_index_add.md new file mode 100644 index 000000000..50eb3a056 --- /dev/null +++ b/docs/user_docs/cli/kbcli_addon_index_add.md @@ -0,0 +1,56 @@ +--- +title: kbcli addon index add +--- + +Add a new addon index + +### Synopsis + +Configure a new index to install KubeBlocks addon from. + +``` +kbcli addon index add [flags] +``` + +### Examples + +``` +kbcli addon index add kubeblocks https://github.com/apecloud/block-index.git +``` + +### Options + +``` + -h, --help help for add +``` + +### Options inherited from parent commands + +``` + --as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace. + --as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --as-uid string UID to impersonate for the operation. + --cache-dir string Default cache directory (default "$HOME/.kube/cache") + --certificate-authority string Path to a cert file for the certificate authority + --client-certificate string Path to a client certificate file for TLS + --client-key string Path to a client key file for TLS + --cluster string The name of the kubeconfig cluster to use + --context string The name of the kubeconfig context to use + --disable-compression If true, opt-out of response compression for all requests to the server + --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + --match-server-version Require server version to match client version + -n, --namespace string If present, the namespace scope for this CLI request + --request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0") + -s, --server string The address and port of the Kubernetes API server + --tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used + --token string Bearer token for authentication to the API server + --user string The name of the kubeconfig user to use +``` + +### SEE ALSO + +* [kbcli addon index](kbcli_addon_index.md) - Manage custom addon indexes + +#### Go Back to [CLI Overview](cli.md) Homepage. + diff --git a/docs/user_docs/cli/kbcli_addon_index_delete.md b/docs/user_docs/cli/kbcli_addon_index_delete.md new file mode 100644 index 000000000..80e34e0b1 --- /dev/null +++ b/docs/user_docs/cli/kbcli_addon_index_delete.md @@ -0,0 +1,50 @@ +--- +title: kbcli addon index delete +--- + +Delete an addon index + +### Synopsis + +Delete a configured addon index. + +``` +kbcli addon index delete [flags] +``` + +### Options + +``` + -h, --help help for delete +``` + +### Options inherited from parent commands + +``` + --as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace. + --as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --as-uid string UID to impersonate for the operation. + --cache-dir string Default cache directory (default "$HOME/.kube/cache") + --certificate-authority string Path to a cert file for the certificate authority + --client-certificate string Path to a client certificate file for TLS + --client-key string Path to a client key file for TLS + --cluster string The name of the kubeconfig cluster to use + --context string The name of the kubeconfig context to use + --disable-compression If true, opt-out of response compression for all requests to the server + --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + --match-server-version Require server version to match client version + -n, --namespace string If present, the namespace scope for this CLI request + --request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0") + -s, --server string The address and port of the Kubernetes API server + --tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used + --token string Bearer token for authentication to the API server + --user string The name of the kubeconfig user to use +``` + +### SEE ALSO + +* [kbcli addon index](kbcli_addon_index.md) - Manage custom addon indexes + +#### Go Back to [CLI Overview](cli.md) Homepage. + diff --git a/docs/user_docs/cli/kbcli_addon_index_list.md b/docs/user_docs/cli/kbcli_addon_index_list.md new file mode 100644 index 000000000..04ac17ea9 --- /dev/null +++ b/docs/user_docs/cli/kbcli_addon_index_list.md @@ -0,0 +1,53 @@ +--- +title: kbcli addon index list +--- + +List addon indexes + +### Synopsis + +Print a list of addon indexes. + +This command prints a list of addon indexes. It shows the name and the remote URL for +each addon index in table format. + +``` +kbcli addon index list [flags] +``` + +### Options + +``` + -h, --help help for list +``` + +### Options inherited from parent commands + +``` + --as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace. + --as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --as-uid string UID to impersonate for the operation. + --cache-dir string Default cache directory (default "$HOME/.kube/cache") + --certificate-authority string Path to a cert file for the certificate authority + --client-certificate string Path to a client certificate file for TLS + --client-key string Path to a client key file for TLS + --cluster string The name of the kubeconfig cluster to use + --context string The name of the kubeconfig context to use + --disable-compression If true, opt-out of response compression for all requests to the server + --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + --match-server-version Require server version to match client version + -n, --namespace string If present, the namespace scope for this CLI request + --request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0") + -s, --server string The address and port of the Kubernetes API server + --tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used + --token string Bearer token for authentication to the API server + --user string The name of the kubeconfig user to use +``` + +### SEE ALSO + +* [kbcli addon index](kbcli_addon_index.md) - Manage custom addon indexes + +#### Go Back to [CLI Overview](cli.md) Homepage. + diff --git a/docs/user_docs/cli/kbcli_addon_index_update.md b/docs/user_docs/cli/kbcli_addon_index_update.md new file mode 100644 index 000000000..9faf021de --- /dev/null +++ b/docs/user_docs/cli/kbcli_addon_index_update.md @@ -0,0 +1,57 @@ +--- +title: kbcli addon index update +--- + +update the specified index(es) + +### Synopsis + +Update existed index repository from index origin URL + +``` +kbcli addon index update [flags] +``` + +### Examples + +``` +kbcli addon index update KubeBlocks +``` + +### Options + +``` + --all Upgrade all addon index + -h, --help help for update +``` + +### Options inherited from parent commands + +``` + --as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace. + --as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups. + --as-uid string UID to impersonate for the operation. + --cache-dir string Default cache directory (default "$HOME/.kube/cache") + --certificate-authority string Path to a cert file for the certificate authority + --client-certificate string Path to a client certificate file for TLS + --client-key string Path to a client key file for TLS + --cluster string The name of the kubeconfig cluster to use + --context string The name of the kubeconfig context to use + --disable-compression If true, opt-out of response compression for all requests to the server + --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + --match-server-version Require server version to match client version + -n, --namespace string If present, the namespace scope for this CLI request + --request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0") + -s, --server string The address and port of the Kubernetes API server + --tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used + --token string Bearer token for authentication to the API server + --user string The name of the kubeconfig user to use +``` + +### SEE ALSO + +* [kbcli addon index](kbcli_addon_index.md) - Manage custom addon indexes + +#### Go Back to [CLI Overview](cli.md) Homepage. + diff --git a/docs/user_docs/cli/kbcli_cluster_create.md b/docs/user_docs/cli/kbcli_cluster_create.md index f856719be..e8fb3b8df 100644 --- a/docs/user_docs/cli/kbcli_cluster_create.md +++ b/docs/user_docs/cli/kbcli_cluster_create.md @@ -160,7 +160,9 @@ kbcli cluster create [NAME] [flags] * [kbcli cluster create llm](kbcli_cluster_create_llm.md) - Create a llm cluster. * [kbcli cluster create mongodb](kbcli_cluster_create_mongodb.md) - Create a mongodb cluster. * [kbcli cluster create mysql](kbcli_cluster_create_mysql.md) - Create a mysql cluster. +* [kbcli cluster create orioledb](kbcli_cluster_create_orioledb.md) - Create a orioledb cluster. * [kbcli cluster create postgresql](kbcli_cluster_create_postgresql.md) - Create a postgresql cluster. +* [kbcli cluster create qdrant](kbcli_cluster_create_qdrant.md) - Create a qdrant cluster. * [kbcli cluster create redis](kbcli_cluster_create_redis.md) - Create a redis cluster. * [kbcli cluster create xinference](kbcli_cluster_create_xinference.md) - Create a xinference cluster. diff --git a/pkg/cmd/addon/index.go b/pkg/cmd/addon/index.go index eda268745..b179ec830 100644 --- a/pkg/cmd/addon/index.go +++ b/pkg/cmd/addon/index.go @@ -61,7 +61,7 @@ func newIndexAddCmd() *cobra.Command { Use: "add", Short: "Add a new addon index", Long: "Configure a new index to install KubeBlocks addon from.", - Example: "kbcli index add kubeblocks " + types.DefaultAddonIndexURL, + Example: "kbcli addon index add kubeblocks " + types.DefaultAddonIndexURL, Args: cobra.ExactArgs(2), PersistentPreRun: func(_ *cobra.Command, _ []string) { util.CheckErr(addDefaultIndex()) @@ -174,7 +174,7 @@ func newIndexUpdateCmd(streams genericiooptions.IOStreams) *cobra.Command { Use: "update", Short: "update the specified index(es)", Long: "Update existed index repository from index origin URL", - Example: "kbcli index update KubeBlocks", + Example: "kbcli addon index update KubeBlocks", ValidArgsFunction: indexCompletion(), Run: func(cmd *cobra.Command, args []string) { util.CheckErr(o.validate(args)) From f851bfe5db2f23443cc468dfca367587219c56ea Mon Sep 17 00:00:00 2001 From: 1aal <1aal@users.noreply.github.com> Date: Wed, 15 Nov 2023 09:22:55 +0000 Subject: [PATCH 9/9] chore: auto update cli doc changes --- docs/user_docs/cli/kbcli_cluster_create.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/user_docs/cli/kbcli_cluster_create.md b/docs/user_docs/cli/kbcli_cluster_create.md index e8fb3b8df..f856719be 100644 --- a/docs/user_docs/cli/kbcli_cluster_create.md +++ b/docs/user_docs/cli/kbcli_cluster_create.md @@ -160,9 +160,7 @@ kbcli cluster create [NAME] [flags] * [kbcli cluster create llm](kbcli_cluster_create_llm.md) - Create a llm cluster. * [kbcli cluster create mongodb](kbcli_cluster_create_mongodb.md) - Create a mongodb cluster. * [kbcli cluster create mysql](kbcli_cluster_create_mysql.md) - Create a mysql cluster. -* [kbcli cluster create orioledb](kbcli_cluster_create_orioledb.md) - Create a orioledb cluster. * [kbcli cluster create postgresql](kbcli_cluster_create_postgresql.md) - Create a postgresql cluster. -* [kbcli cluster create qdrant](kbcli_cluster_create_qdrant.md) - Create a qdrant cluster. * [kbcli cluster create redis](kbcli_cluster_create_redis.md) - Create a redis cluster. * [kbcli cluster create xinference](kbcli_cluster_create_xinference.md) - Create a xinference cluster.