mirror of https://github.com/kubevela/kubevela.git
				
				
				
			
		
			
				
	
	
		
			632 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			632 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
| Copyright 2022 The KubeVela Authors.
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
| 	http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package cli
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/spf13/cobra"
 | |
| 	"helm.sh/helm/v3/pkg/strvals"
 | |
| 	"k8s.io/kubectl/pkg/util/i18n"
 | |
| 	"k8s.io/kubectl/pkg/util/templates"
 | |
| 	"sigs.k8s.io/yaml"
 | |
| 
 | |
| 	workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
 | |
| 
 | |
| 	"github.com/oam-dev/kubevela/apis/types"
 | |
| 	velacmd "github.com/oam-dev/kubevela/pkg/cmd"
 | |
| 	"github.com/oam-dev/kubevela/pkg/config"
 | |
| 	pkgUtils "github.com/oam-dev/kubevela/pkg/utils"
 | |
| 	"github.com/oam-dev/kubevela/pkg/utils/util"
 | |
| 	"github.com/oam-dev/kubevela/references/docgen"
 | |
| )
 | |
| 
 | |
| // ConfigCommandGroup commands for the config
 | |
| func ConfigCommandGroup(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:   "config",
 | |
| 		Short: i18n.T("Manage the configs."),
 | |
| 		Long:  i18n.T("Manage the configs, such as the terraform provider, image registry, helm repository, etc."),
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeCD,
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.AddCommand(NewListConfigCommand(f, streams))
 | |
| 	cmd.AddCommand(NewCreateConfigCommand(f, streams))
 | |
| 	cmd.AddCommand(NewDistributeConfigCommand(f, streams))
 | |
| 	cmd.AddCommand(NewDeleteConfigCommand(f, streams))
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // TemplateCommandGroup commands for the template of the config
 | |
| func TemplateCommandGroup(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:     "config-template",
 | |
| 		Aliases: []string{"ct"},
 | |
| 		Short:   i18n.T("Manage the template of config."),
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeExtension,
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.AddCommand(NewTemplateApplyCommand(f, streams))
 | |
| 	cmd.AddCommand(NewTemplateListCommand(f, streams))
 | |
| 	cmd.AddCommand(NewTemplateDeleteCommand(f, streams))
 | |
| 	cmd.AddCommand(NewTemplateShowCommand(f, streams))
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // TemplateApplyCommandOptions the options of the command that apply the config template.
 | |
| type TemplateApplyCommandOptions struct {
 | |
| 	File      string
 | |
| 	Namespace string
 | |
| 	Name      string
 | |
| }
 | |
| 
 | |
| // TemplateCommandOptions the options of the command that delete or show the config template.
 | |
| type TemplateCommandOptions struct {
 | |
| 	Namespace string
 | |
| 	Name      string
 | |
| }
 | |
| 
 | |
| // TemplateListCommandOptions the options of the command that list the config templates.
 | |
| type TemplateListCommandOptions struct {
 | |
| 	Namespace    string
 | |
| 	AllNamespace bool
 | |
| }
 | |
| 
 | |
| // NewTemplateApplyCommand command for creating and updating the config template
 | |
| func NewTemplateApplyCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options TemplateApplyCommandOptions
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:   "apply",
 | |
| 		Short: i18n.T("Apply a config template."),
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeExtension,
 | |
| 		},
 | |
| 		Args: cobra.ExactArgs(0),
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			body, err := pkgUtils.ReadRemoteOrLocalPath(options.File, false)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			template, err := inf.ParseTemplate(options.Name, body)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			if err := inf.CreateOrUpdateConfigTemplate(context.Background(), options.Namespace, template); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			streams.Infof("the config template %s applied successfully\n", template.Name)
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringVarP(&options.File, "file", "f", "", "specify the template file name")
 | |
| 	cmd.Flags().StringVarP(&options.Name, "name", "", "", "specify the config template name")
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the template")
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // NewTemplateListCommand command for listing the config templates
 | |
| func NewTemplateListCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options TemplateListCommandOptions
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:     "list",
 | |
| 		Short:   i18n.T("List the config templates."),
 | |
| 		Example: "vela config template list [-A]",
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeExtension,
 | |
| 		},
 | |
| 		Args: cobra.ExactArgs(0),
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			if options.AllNamespace {
 | |
| 				options.Namespace = ""
 | |
| 			}
 | |
| 			templates, err := inf.ListTemplates(context.Background(), options.Namespace, "")
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			table := newUITable()
 | |
| 			header := []interface{}{"NAME", "ALIAS", "SCOPE", "SENSITIVE", "CREATED-TIME"}
 | |
| 			if options.AllNamespace {
 | |
| 				header = append([]interface{}{"NAMESPACE"}, header...)
 | |
| 			}
 | |
| 			table.AddRow(header...)
 | |
| 			for _, t := range templates {
 | |
| 				row := []interface{}{t.Name, t.Alias, t.Scope, t.Sensitive, t.CreateTime}
 | |
| 				if options.AllNamespace {
 | |
| 					row = append([]interface{}{t.Namespace}, row...)
 | |
| 				}
 | |
| 				table.AddRow(row...)
 | |
| 			}
 | |
| 			if _, err := streams.Out.Write(table.Bytes()); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			if _, err := streams.Out.Write([]byte("\n")); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the template")
 | |
| 	cmd.Flags().BoolVarP(&options.AllNamespace, "all-namespaces", "A", false, "If true, check the specified action in all namespaces.")
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // NewTemplateShowCommand command for show the properties document
 | |
| func NewTemplateShowCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options TemplateCommandOptions
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:     "show",
 | |
| 		Short:   i18n.T("Show the documents of the template properties"),
 | |
| 		Example: "vela config-template show <name> [-n]",
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeExtension,
 | |
| 		},
 | |
| 		Args: cobra.ExactArgs(1),
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			options.Name = args[0]
 | |
| 			if options.Name == "" {
 | |
| 				return fmt.Errorf("can not show the properties without the template")
 | |
| 			}
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			template, err := inf.LoadTemplate(context.Background(), options.Name, options.Namespace)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			doc, err := docgen.GenerateConsoleDocument(template.Schema.Title, template.Schema)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			if _, err := streams.Out.Write([]byte(doc)); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the template")
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // NewTemplateDeleteCommand command for deleting the config template
 | |
| func NewTemplateDeleteCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options TemplateCommandOptions
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:     "delete",
 | |
| 		Short:   i18n.T("Delete a config template."),
 | |
| 		Example: fmt.Sprintf("vela config template delete <name> [-n %s]", types.DefaultKubeVelaNS),
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeCD,
 | |
| 		},
 | |
| 		Args: cobra.ExactArgs(1),
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			if len(args) == 0 {
 | |
| 				return fmt.Errorf("please must provides the template name")
 | |
| 			}
 | |
| 			options.Name = args[0]
 | |
| 			userInput := &UserInput{
 | |
| 				Writer: streams.Out,
 | |
| 				Reader: bufio.NewReader(streams.In),
 | |
| 			}
 | |
| 			if !assumeYes {
 | |
| 				userConfirmation := userInput.AskBool("Do you want to delete this template", &UserInputOptions{assumeYes})
 | |
| 				if !userConfirmation {
 | |
| 					return fmt.Errorf("stopping deleting")
 | |
| 				}
 | |
| 			}
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			if err := inf.DeleteTemplate(context.Background(), options.Namespace, options.Name); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			streams.Infof("the config template %s deleted successfully\n", options.Name)
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the template")
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // DistributeConfigCommandOptions the options of the command that distribute the config.
 | |
| type DistributeConfigCommandOptions struct {
 | |
| 	Targets   []string
 | |
| 	Config    string
 | |
| 	Namespace string
 | |
| 	Recalled  bool
 | |
| }
 | |
| 
 | |
| // CreateConfigCommandOptions the options of the command that create the config.
 | |
| type CreateConfigCommandOptions struct {
 | |
| 	Template    string
 | |
| 	Namespace   string
 | |
| 	Name        string
 | |
| 	File        string
 | |
| 	Properties  map[string]interface{}
 | |
| 	DryRun      bool
 | |
| 	Targets     []string
 | |
| 	Description string
 | |
| 	Alias       string
 | |
| }
 | |
| 
 | |
| // Validate validate the options
 | |
| func (i CreateConfigCommandOptions) Validate() error {
 | |
| 	if i.Name == "" {
 | |
| 		return fmt.Errorf("the config name must be specified")
 | |
| 	}
 | |
| 	if len(i.Targets) > 0 && i.DryRun {
 | |
| 		return fmt.Errorf("can not set the distribution in dry-run mode")
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (i *CreateConfigCommandOptions) parseProperties(args []string) error {
 | |
| 	if i.File != "" {
 | |
| 		body, err := pkgUtils.ReadRemoteOrLocalPath(i.File, false)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		var properties = map[string]interface{}{}
 | |
| 		if err := yaml.Unmarshal(body, &properties); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		i.Properties = properties
 | |
| 		return nil
 | |
| 	}
 | |
| 	res := map[string]interface{}{}
 | |
| 	for _, arg := range args {
 | |
| 		if err := strvals.ParseInto(arg, res); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	i.Properties = res
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // ConfigListCommandOptions the options of the command that list configs.
 | |
| type ConfigListCommandOptions struct {
 | |
| 	Namespace    string
 | |
| 	Template     string
 | |
| 	AllNamespace bool
 | |
| }
 | |
| 
 | |
| // NewListConfigCommand command for listing the config secrets
 | |
| func NewListConfigCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options ConfigListCommandOptions
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:   "list",
 | |
| 		Short: i18n.T("List the configs."),
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeCD,
 | |
| 		},
 | |
| 		Args: cobra.ExactArgs(0),
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			name := options.Template
 | |
| 			if strings.Contains(options.Template, "/") {
 | |
| 				namespacedName := strings.SplitN(options.Template, "/", 2)
 | |
| 				name = namespacedName[1]
 | |
| 			}
 | |
| 			if options.AllNamespace {
 | |
| 				options.Namespace = ""
 | |
| 			}
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			configs, err := inf.ListConfigs(context.Background(), options.Namespace, name, "", true)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			table := newUITable()
 | |
| 			header := []interface{}{"NAME", "ALIAS", "DISTRIBUTION", "TEMPLATE", "CREATED-TIME", "DESCRIPTION"}
 | |
| 			if options.AllNamespace {
 | |
| 				header = append([]interface{}{"NAMESPACE"}, header...)
 | |
| 			}
 | |
| 			table.AddRow(header...)
 | |
| 			for _, t := range configs {
 | |
| 				var targetShow = ""
 | |
| 				for _, target := range t.Targets {
 | |
| 					if targetShow != "" {
 | |
| 						targetShow += " "
 | |
| 					}
 | |
| 					switch target.Status {
 | |
| 					case string(workflowv1alpha1.WorkflowStepPhaseSucceeded):
 | |
| 						targetShow += green.Sprintf("%s/%s", target.ClusterName, target.Namespace)
 | |
| 					case string(workflowv1alpha1.WorkflowStepPhaseFailed):
 | |
| 						targetShow += red.Sprintf("%s/%s", target.ClusterName, target.Namespace)
 | |
| 					default:
 | |
| 						targetShow += yellow.Sprintf("%s/%s", target.ClusterName, target.Namespace)
 | |
| 					}
 | |
| 				}
 | |
| 				row := []interface{}{t.Name, t.Alias, targetShow, fmt.Sprintf("%s/%s", t.Template.Namespace, t.Template.Name), t.CreateTime, t.Description}
 | |
| 				if options.AllNamespace {
 | |
| 					row = append([]interface{}{t.Namespace}, row...)
 | |
| 				}
 | |
| 				table.AddRow(row...)
 | |
| 			}
 | |
| 			if _, err := streams.Out.Write(table.Bytes()); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			if _, err := streams.Out.Write([]byte("\n")); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the config")
 | |
| 	cmd.Flags().StringVarP(&options.Template, "template", "t", "", "specify the template of the config")
 | |
| 	cmd.Flags().BoolVarP(&options.AllNamespace, "all-namespaces", "A", false, "If true, check the specified action in all namespaces.")
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // NewCreateConfigCommand command for creating the config
 | |
| func NewCreateConfigCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options CreateConfigCommandOptions
 | |
| 	createConfigExample := templates.Examples(i18n.T(`
 | |
| 		# Generate a config with the args
 | |
| 		vela config create test-registry --template=image-registry registry=index.docker.io auth.username=test auth.password=test
 | |
| 		
 | |
| 		# Generate a config with the file
 | |
| 		vela config create test-config --template=image-registry  -f config.yaml
 | |
| 
 | |
| 		# Generate a config without the template
 | |
| 		vela config create test-vela -f config.yaml
 | |
| 		`))
 | |
| 
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:     "create",
 | |
| 		Aliases: []string{"c"},
 | |
| 		Short:   i18n.T("Create a config."),
 | |
| 		Example: createConfigExample,
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeCD,
 | |
| 		},
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			options.Name = args[0]
 | |
| 			if err := options.Validate(); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			name := options.Template
 | |
| 			namespace := types.DefaultKubeVelaNS
 | |
| 			if strings.Contains(options.Template, "/") {
 | |
| 				namespacedName := strings.SplitN(options.Template, "/", 2)
 | |
| 				namespace = namespacedName[0]
 | |
| 				name = namespacedName[1]
 | |
| 			}
 | |
| 			if err := options.parseProperties(args[1:]); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			configItem, err := inf.ParseConfig(context.Background(), config.NamespacedName{
 | |
| 				Name:      name,
 | |
| 				Namespace: namespace,
 | |
| 			}, config.Metadata{
 | |
| 				NamespacedName: config.NamespacedName{
 | |
| 					Name:      options.Name,
 | |
| 					Namespace: options.Namespace,
 | |
| 				},
 | |
| 				Properties:  options.Properties,
 | |
| 				Alias:       options.Alias,
 | |
| 				Description: options.Description,
 | |
| 			})
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			if options.DryRun {
 | |
| 				var outBuilder = bytes.NewBuffer(nil)
 | |
| 				out, err := yaml.Marshal(configItem.Secret)
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				_, err = outBuilder.Write(out)
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				if configItem.OutputObjects != nil {
 | |
| 					for k, object := range configItem.OutputObjects {
 | |
| 						_, err = outBuilder.WriteString("# Object: \n ---" + k)
 | |
| 						if err != nil {
 | |
| 							return err
 | |
| 						}
 | |
| 						out, err := yaml.Marshal(object)
 | |
| 						if err != nil {
 | |
| 							return err
 | |
| 						}
 | |
| 						if _, err := outBuilder.Write(out); err != nil {
 | |
| 							return err
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 				_, err = streams.Out.Write(outBuilder.Bytes())
 | |
| 				return err
 | |
| 			}
 | |
| 			if err := inf.CreateOrUpdateConfig(context.Background(), configItem, options.Namespace); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			if len(options.Targets) > 0 {
 | |
| 				ads := &config.CreateDistributionSpec{
 | |
| 					Targets: []*config.ClusterTarget{},
 | |
| 					Configs: []*config.NamespacedName{
 | |
| 						&configItem.NamespacedName,
 | |
| 					},
 | |
| 				}
 | |
| 				for _, t := range options.Targets {
 | |
| 					ti := strings.Split(t, "/")
 | |
| 					if len(ti) == 2 {
 | |
| 						ads.Targets = append(ads.Targets, &config.ClusterTarget{
 | |
| 							ClusterName: ti[0],
 | |
| 							Namespace:   ti[1],
 | |
| 						})
 | |
| 					} else {
 | |
| 						ads.Targets = append(ads.Targets, &config.ClusterTarget{
 | |
| 							ClusterName: types.ClusterLocalName,
 | |
| 							Namespace:   ti[0],
 | |
| 						})
 | |
| 					}
 | |
| 				}
 | |
| 				name := config.DefaultDistributionName(options.Name)
 | |
| 				if err := inf.CreateOrUpdateDistribution(context.Background(), options.Namespace, name, ads); err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 			}
 | |
| 			streams.Infof("the config %s applied successfully\n", options.Name)
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringVarP(&options.Template, "template", "t", "", "specify the config template name and namespace")
 | |
| 	cmd.Flags().StringVarP(&options.File, "file", "f", "", "specify the file name of the config properties")
 | |
| 	cmd.Flags().StringArrayVarP(&options.Targets, "target", "", []string{}, "this config will be distributed if this flag is set")
 | |
| 	cmd.Flags().BoolVarP(&options.DryRun, "dry-run", "", false, "Dry run to apply the config")
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the config")
 | |
| 	cmd.Flags().StringVarP(&options.Description, "description", "", "", "specify the description of the config")
 | |
| 	cmd.Flags().StringVarP(&options.Alias, "alias", "", "", "specify the alias of the config")
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // NewDistributeConfigCommand command for distributing the config
 | |
| func NewDistributeConfigCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options DistributeConfigCommandOptions
 | |
| 
 | |
| 	distributionExample := templates.Examples(i18n.T(`
 | |
| 		# distribute the config(test-registry) from the vela-system namespace to the default namespace in the local cluster.
 | |
| 		vela config d test-registry -t default
 | |
| 
 | |
| 		# distribute the config(test-registry) from the vela-system namespace to the other clusters.
 | |
| 		vela config d test-registry -t cluster1/default -t cluster2/default
 | |
| 
 | |
| 		# recall the config
 | |
| 		vela config d test-registry --recall
 | |
| 		`))
 | |
| 
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:     "distribute",
 | |
| 		Aliases: []string{"d"},
 | |
| 		Short:   i18n.T("Distribute a config"),
 | |
| 		Example: distributionExample,
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeCD,
 | |
| 		},
 | |
| 		Args: cobra.ExactArgs(1),
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			options.Config = args[0]
 | |
| 			name := config.DefaultDistributionName(options.Config)
 | |
| 			if options.Recalled {
 | |
| 				userInput := &UserInput{
 | |
| 					Writer: streams.Out,
 | |
| 					Reader: bufio.NewReader(streams.In),
 | |
| 				}
 | |
| 				if !assumeYes {
 | |
| 					userConfirmation := userInput.AskBool("Do you want to recall this config", &UserInputOptions{assumeYes})
 | |
| 					if !userConfirmation {
 | |
| 						return fmt.Errorf("recalling stopped")
 | |
| 					}
 | |
| 				}
 | |
| 				if err := inf.DeleteDistribution(context.Background(), options.Namespace, name); err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				streams.Infof("the distribution %s deleted successfully\n", name)
 | |
| 				return nil
 | |
| 			}
 | |
| 
 | |
| 			ads := &config.CreateDistributionSpec{
 | |
| 				Targets: []*config.ClusterTarget{},
 | |
| 				Configs: []*config.NamespacedName{
 | |
| 					{
 | |
| 						Name:      options.Config,
 | |
| 						Namespace: options.Namespace,
 | |
| 					},
 | |
| 				},
 | |
| 			}
 | |
| 			for _, t := range options.Targets {
 | |
| 				ti := strings.Split(t, "/")
 | |
| 				if len(ti) == 2 {
 | |
| 					ads.Targets = append(ads.Targets, &config.ClusterTarget{
 | |
| 						ClusterName: ti[0],
 | |
| 						Namespace:   ti[1],
 | |
| 					})
 | |
| 				} else {
 | |
| 					ads.Targets = append(ads.Targets, &config.ClusterTarget{
 | |
| 						ClusterName: types.ClusterLocalName,
 | |
| 						Namespace:   ti[0],
 | |
| 					})
 | |
| 				}
 | |
| 			}
 | |
| 			if err := inf.CreateOrUpdateDistribution(context.Background(), options.Namespace, name, ads); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			streams.Infof("the distribution %s applied successfully\n", name)
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringArrayVarP(&options.Targets, "target", "t", []string{}, "specify the targets that want to distribute,the format is: <clusterName>/<namespace>")
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the distribution")
 | |
| 	cmd.Flags().BoolVarP(&options.Recalled, "recall", "r", false, "this field means recalling the configs from all targets.")
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| // ConfigDeleteCommandOptions the options of the command that delete the config.
 | |
| type ConfigDeleteCommandOptions struct {
 | |
| 	Namespace string
 | |
| 	Name      string
 | |
| 	NotRecall bool
 | |
| }
 | |
| 
 | |
| // NewDeleteConfigCommand command for deleting the config secret
 | |
| func NewDeleteConfigCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
 | |
| 	var options ConfigDeleteCommandOptions
 | |
| 	cmd := &cobra.Command{
 | |
| 		Use:   "delete",
 | |
| 		Short: i18n.T("Delete a config."),
 | |
| 		Annotations: map[string]string{
 | |
| 			types.TagCommandType: types.TypeCD,
 | |
| 		},
 | |
| 		Args: cobra.ExactArgs(1),
 | |
| 		RunE: func(cmd *cobra.Command, args []string) error {
 | |
| 			options.Name = args[0]
 | |
| 			inf := config.NewConfigFactory(f.Client())
 | |
| 			userInput := &UserInput{
 | |
| 				Writer: streams.Out,
 | |
| 				Reader: bufio.NewReader(streams.In),
 | |
| 			}
 | |
| 			if !assumeYes {
 | |
| 				userConfirmation := userInput.AskBool("Do you want to delete this config", &UserInputOptions{assumeYes})
 | |
| 				if !userConfirmation {
 | |
| 					return fmt.Errorf("deleting stopped")
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if !options.NotRecall {
 | |
| 				if err := inf.DeleteDistribution(context.Background(), options.Namespace, config.DefaultDistributionName(options.Name)); err != nil && !errors.Is(err, config.ErrNotFoundDistribution) {
 | |
| 					return err
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if err := inf.DeleteConfig(context.Background(), options.Namespace, options.Name); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 
 | |
| 			streams.Infof("the config %s deleted successfully\n", options.Name)
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| 	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", types.DefaultKubeVelaNS, "specify the namespace of the config")
 | |
| 	cmd.Flags().BoolVarP(&options.NotRecall, "not-recall", "", false, "means only deleting the config from the local and do not recall from targets.")
 | |
| 	return cmd
 | |
| }
 |