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 }