github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/context/context.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package context
    21  
    22  import (
    23  	"github.com/pkg/errors"
    24  	"github.com/spf13/cobra"
    25  	"k8s.io/cli-runtime/pkg/genericiooptions"
    26  	cmdutil "k8s.io/kubectl/pkg/cmd/util"
    27  	"k8s.io/kubectl/pkg/util/templates"
    28  
    29  	"github.com/1aal/kubeblocks/pkg/cli/cmd/organization"
    30  )
    31  
    32  var contextExample = templates.Examples(`
    33  	// Get the context name currently used by the user.
    34  	kbcli context current 
    35  	// List all contexts created by the current user.
    36  	kbcli context list
    37  	// Get the description information of context context1.
    38  	kbcli context describe context1
    39  	// Switch to context context2.
    40  	kbcli context use context2
    41  `)
    42  
    43  const (
    44  	localContext = "local"
    45  )
    46  
    47  type Context interface {
    48  	showContext() error
    49  	showContexts() error
    50  	showCurrentContext() error
    51  	showUseContext() error
    52  	showRemoveContext() error
    53  }
    54  
    55  type ContextOptions struct {
    56  	ContextName  string
    57  	Context      Context
    58  	OutputFormat string
    59  
    60  	genericiooptions.IOStreams
    61  }
    62  
    63  func NewContextCmd(streams genericiooptions.IOStreams) *cobra.Command {
    64  	cmd := &cobra.Command{
    65  		Use: "context",
    66  		Short: "kbcli context allows you to manage cloud context. This command is currently only applicable to cloud," +
    67  			" and currently does not support switching the context of the local k8s cluster.",
    68  		Example: contextExample,
    69  	}
    70  	cmd.AddCommand(
    71  		newContextListCmd(streams),
    72  		newContextUseCmd(streams),
    73  		newContextCurrentCmd(streams),
    74  		newContextDescribeCmd(streams),
    75  	)
    76  	return cmd
    77  }
    78  
    79  func newContextListCmd(streams genericiooptions.IOStreams) *cobra.Command {
    80  	o := &ContextOptions{IOStreams: streams}
    81  
    82  	cmd := &cobra.Command{
    83  		Use:   "list",
    84  		Short: "List all created contexts.",
    85  		Run: func(cmd *cobra.Command, args []string) {
    86  			cmdutil.CheckErr(o.complete(args))
    87  			cmdutil.CheckErr(o.validate(cmd))
    88  			cmdutil.CheckErr(o.runList())
    89  		},
    90  	}
    91  	return cmd
    92  }
    93  
    94  func newContextCurrentCmd(streams genericiooptions.IOStreams) *cobra.Command {
    95  	o := &ContextOptions{IOStreams: streams}
    96  
    97  	cmd := &cobra.Command{
    98  		Use:   "current",
    99  		Short: "Get the currently used context.",
   100  		Run: func(cmd *cobra.Command, args []string) {
   101  			cmdutil.CheckErr(o.complete(args))
   102  			cmdutil.CheckErr(o.validate(cmd))
   103  			cmdutil.CheckErr(o.runCurrent())
   104  		},
   105  	}
   106  	return cmd
   107  }
   108  
   109  func newContextDescribeCmd(streams genericiooptions.IOStreams) *cobra.Command {
   110  	o := &ContextOptions{IOStreams: streams}
   111  
   112  	cmd := &cobra.Command{
   113  		Use:   "describe",
   114  		Short: "Get the description information of a context.",
   115  		Run: func(cmd *cobra.Command, args []string) {
   116  			cmdutil.CheckErr(o.complete(args))
   117  			cmdutil.CheckErr(o.validate(cmd))
   118  			cmdutil.CheckErr(o.runDescribe())
   119  		},
   120  	}
   121  
   122  	cmd.Flags().StringVarP(&o.OutputFormat, "output", "o", "human", "Output format (table|yaml|json)")
   123  
   124  	return cmd
   125  }
   126  
   127  func newContextUseCmd(streams genericiooptions.IOStreams) *cobra.Command {
   128  	o := &ContextOptions{IOStreams: streams}
   129  
   130  	cmd := &cobra.Command{
   131  		Use:   "use",
   132  		Short: "Use another context that you have already created.",
   133  		Run: func(cmd *cobra.Command, args []string) {
   134  			cmdutil.CheckErr(o.complete(args))
   135  			cmdutil.CheckErr(o.validate(cmd))
   136  			cmdutil.CheckErr(o.runUse())
   137  		},
   138  	}
   139  
   140  	return cmd
   141  }
   142  
   143  func (o *ContextOptions) validate(cmd *cobra.Command) error {
   144  	if cmd.Name() == "describe" || cmd.Name() == "use" {
   145  		if o.ContextName == "" {
   146  			return errors.New("context name is required")
   147  		}
   148  	}
   149  
   150  	return nil
   151  }
   152  
   153  func (o *ContextOptions) complete(args []string) error {
   154  	if len(args) > 0 {
   155  		o.ContextName = args[0]
   156  	}
   157  
   158  	currentOrgAndContext, err := organization.GetCurrentOrgAndContext()
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	if o.Context == nil {
   164  		if currentOrgAndContext.CurrentContext != localContext {
   165  			token, err := organization.GetToken()
   166  			if err != nil {
   167  				return err
   168  			}
   169  			o.Context = &CloudContext{
   170  				ContextName:  o.ContextName,
   171  				Token:        token,
   172  				OrgName:      currentOrgAndContext.CurrentOrganization,
   173  				IOStreams:    o.IOStreams,
   174  				APIURL:       organization.APIURL,
   175  				APIPath:      organization.APIPath,
   176  				OutputFormat: o.OutputFormat,
   177  			}
   178  		}
   179  	}
   180  
   181  	return nil
   182  }
   183  
   184  func (o *ContextOptions) runList() error {
   185  	return o.Context.showContexts()
   186  }
   187  
   188  func (o *ContextOptions) runCurrent() error {
   189  	return o.Context.showCurrentContext()
   190  }
   191  
   192  func (o *ContextOptions) runDescribe() error {
   193  	return o.Context.showContext()
   194  }
   195  
   196  func (o *ContextOptions) runUse() error {
   197  	return o.Context.showUseContext()
   198  }