github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/environment.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
     7  	"github.com/pkg/errors"
     8  
     9  	"github.com/spf13/cobra"
    10  
    11  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    12  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    13  	"github.com/olli-ai/jx/v2/pkg/kube"
    14  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"k8s.io/client-go/tools/clientcmd"
    16  
    17  	"github.com/olli-ai/jx/v2/pkg/util"
    18  	"gopkg.in/AlecAivazis/survey.v1"
    19  	"k8s.io/client-go/kubernetes"
    20  )
    21  
    22  type EnvironmentOptions struct {
    23  	*opts.CommonOptions
    24  }
    25  
    26  var (
    27  	environment_long = templates.LongDesc(`
    28  		Displays or changes the current environment.
    29  
    30  		For more documentation on Environments see: [https://jenkins-x.io/about/features/#environments](https://jenkins-x.io/about/features/#environments)
    31  
    32  `)
    33  	environment_example = templates.Examples(`
    34  		# view the current environment
    35  		jx env -b
    36  
    37  		# pick which environment to switch to
    38  		jx env
    39  
    40  		# Change the current environment to 'staging'
    41  		jx env staging
    42  `)
    43  )
    44  
    45  func NewCmdEnvironment(commonOpts *opts.CommonOptions) *cobra.Command {
    46  	options := &EnvironmentOptions{
    47  		CommonOptions: commonOpts,
    48  	}
    49  	cmd := &cobra.Command{
    50  		Use:     "environment",
    51  		Aliases: []string{"env"},
    52  		Short:   "View or change the current environment in the current Kubernetes cluster",
    53  		Long:    environment_long,
    54  		Example: environment_example,
    55  		Run: func(cmd *cobra.Command, args []string) {
    56  			options.Cmd = cmd
    57  			options.Args = args
    58  			err := options.Run()
    59  			helper.CheckErr(err)
    60  		},
    61  	}
    62  	return cmd
    63  }
    64  
    65  func (o *EnvironmentOptions) Run() error {
    66  	kubeClient, currentNs, err := o.KubeClientAndNamespace()
    67  	if err != nil {
    68  		return err
    69  	}
    70  	jxClient, _, err := o.JXClient()
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	devNs, currentEnv, err := kube.GetDevNamespace(kubeClient, currentNs)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	envNames, err := kube.GetEnvironmentNames(jxClient, devNs)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	config, po, err := o.Kube().LoadConfig()
    85  	if err != nil {
    86  		return err
    87  	}
    88  	env := ""
    89  	args := o.Args
    90  	if len(args) > 0 {
    91  		env = args[0]
    92  	}
    93  	if env == "" && !o.BatchMode {
    94  		pick, err := kube.PickEnvironment(envNames, currentEnv, o.GetIOFileHandles())
    95  		if err != nil {
    96  			return err
    97  		}
    98  		env = pick
    99  	}
   100  	info := util.ColorInfo
   101  	if env != "" && env != currentEnv {
   102  		envResource, err := jxClient.JenkinsV1().Environments(devNs).Get(env, meta_v1.GetOptions{})
   103  		if err != nil {
   104  			return util.InvalidArg(env, envNames)
   105  		}
   106  		ns := envResource.Spec.Namespace
   107  		if ns == "" {
   108  			return fmt.Errorf("Cannot change to environment %s as it has no namespace!", env)
   109  		}
   110  
   111  		newConfig := *config
   112  		ctx := kube.CurrentContext(config)
   113  		if ctx == nil {
   114  			return errors.New("there is no context defined in your Kubernetes configuration")
   115  		}
   116  		if ctx.Namespace == ns {
   117  			return nil
   118  		}
   119  		ctx.Namespace = ns
   120  		err = clientcmd.ModifyConfig(po, newConfig, false)
   121  		if err != nil {
   122  			return fmt.Errorf("Failed to update the kube config %s", err)
   123  		}
   124  		fmt.Fprintf(o.Out, "Now using environment '%s' in team '%s' on cluster '%s'.\n",
   125  			info(env), info(devNs), info(kube.Cluster(config)))
   126  	} else {
   127  		ns := kube.CurrentNamespace(config)
   128  		cluster := kube.Cluster(config)
   129  		if env == "" {
   130  			env = currentEnv
   131  		}
   132  		if env == "" {
   133  			fmt.Fprintf(o.Out, "Using namespace '%s' from context named '%s' on cluster '%s'.\n", info(ns), info(config.CurrentContext), info(cluster))
   134  		} else {
   135  			fmt.Fprintf(o.Out, "Using environment '%s' in team '%s' on cluster '%s'.\n", info(env), info(devNs), info(cluster))
   136  		}
   137  	}
   138  	return nil
   139  }
   140  
   141  func (o *EnvironmentOptions) PickNamespace(client kubernetes.Interface, defaultNamespace string) (string, error) {
   142  	list, err := client.CoreV1().Namespaces().List(meta_v1.ListOptions{})
   143  	if err != nil {
   144  		return "", fmt.Errorf("Failed to load current namespaces %s", err)
   145  	}
   146  	names := []string{}
   147  	for _, n := range list.Items {
   148  		names = append(names, n.Name)
   149  	}
   150  	var qs = []*survey.Question{
   151  		{
   152  			Name: "namespace",
   153  			Prompt: &survey.Select{
   154  				Message: "Change namespace: ",
   155  				Options: names,
   156  				Default: defaultNamespace,
   157  			},
   158  		},
   159  	}
   160  	answers := struct {
   161  		Namespace string
   162  	}{}
   163  	err = survey.Ask(qs, &answers)
   164  	if err != nil {
   165  		return "", err
   166  	}
   167  	return answers.Namespace, nil
   168  }