github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/juju/commands/switch.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package commands 5 6 import ( 7 "fmt" 8 "os" 9 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 "github.com/juju/utils/set" 13 "launchpad.net/gnuflag" 14 15 "github.com/juju/juju/cmd/envcmd" 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/environs/configstore" 18 ) 19 20 type SwitchCommand struct { 21 cmd.CommandBase 22 EnvName string 23 List bool 24 } 25 26 var switchDoc = ` 27 Show or change the default juju environment or system name. 28 29 If no command line parameters are passed, switch will output the current 30 environment as defined by the file $JUJU_HOME/current-environment. 31 32 If a command line parameter is passed in, that value will is stored in the 33 current environment file if it represents a valid environment name as 34 specified in the environments.yaml file. 35 ` 36 37 const systemSuffix = " (system)" 38 39 func (c *SwitchCommand) Info() *cmd.Info { 40 return &cmd.Info{ 41 Name: "switch", 42 Args: "[environment name]", 43 Purpose: "show or change the default juju environment or system name", 44 Doc: switchDoc, 45 Aliases: []string{"env"}, 46 } 47 } 48 49 func (c *SwitchCommand) SetFlags(f *gnuflag.FlagSet) { 50 f.BoolVar(&c.List, "l", false, "list the environment names") 51 f.BoolVar(&c.List, "list", false, "") 52 } 53 54 func (c *SwitchCommand) Init(args []string) (err error) { 55 c.EnvName, err = cmd.ZeroOrOneArgs(args) 56 return 57 } 58 59 func getConfigstoreOptions() (set.Strings, set.Strings, error) { 60 store, err := configstore.Default() 61 if err != nil { 62 return nil, nil, errors.Annotate(err, "failed to get config store") 63 } 64 environmentNames, err := store.List() 65 if err != nil { 66 return nil, nil, errors.Annotate(err, "failed to list environments in config store") 67 } 68 systemNames, err := store.ListSystems() 69 if err != nil { 70 return nil, nil, errors.Annotate(err, "failed to list systems in config store") 71 } 72 // Also include the systems. 73 return set.NewStrings(environmentNames...), set.NewStrings(systemNames...), nil 74 } 75 76 func (c *SwitchCommand) Run(ctx *cmd.Context) error { 77 // Switch is an alternative way of dealing with environments than using 78 // the JUJU_ENV environment setting, and as such, doesn't play too well. 79 // If JUJU_ENV is set we should report that as the current environment, 80 // and not allow switching when it is set. 81 82 // Passing through the empty string reads the default environments.yaml file. 83 // If the environments.yaml file doesn't exist, just list environments in 84 // the configstore. 85 envFileExists := true 86 names := set.NewStrings() 87 environments, err := environs.ReadEnvirons("") 88 if err != nil { 89 if !environs.IsNoEnv(err) { 90 return errors.Annotate(err, "couldn't read the environment") 91 } 92 envFileExists = false 93 } else { 94 for _, name := range environments.Names() { 95 names.Add(name) 96 } 97 } 98 99 configEnvirons, configSystems, err := getConfigstoreOptions() 100 if err != nil { 101 return err 102 } 103 names = names.Union(configEnvirons) 104 names = names.Union(configSystems) 105 106 if c.List { 107 // List all environments and systems. 108 if c.EnvName != "" { 109 return errors.New("cannot switch and list at the same time") 110 } 111 for _, name := range names.SortedValues() { 112 if configSystems.Contains(name) && !configEnvirons.Contains(name) { 113 name += systemSuffix 114 } 115 fmt.Fprintf(ctx.Stdout, "%s\n", name) 116 } 117 return nil 118 } 119 120 jujuEnv := os.Getenv("JUJU_ENV") 121 if jujuEnv != "" { 122 if c.EnvName == "" { 123 fmt.Fprintf(ctx.Stdout, "%s\n", jujuEnv) 124 return nil 125 } else { 126 return errors.Errorf("cannot switch when JUJU_ENV is overriding the environment (set to %q)", jujuEnv) 127 } 128 } 129 130 current, isSystem, err := envcmd.CurrentConnectionName() 131 if err != nil { 132 return errors.Trace(err) 133 } 134 if current == "" { 135 if envFileExists { 136 current = environments.Default 137 } 138 } else if isSystem { 139 current += systemSuffix 140 } 141 142 // Handle the different operation modes. 143 switch { 144 case c.EnvName == "" && current == "": 145 // Nothing specified and nothing to switch to. 146 return errors.New("no currently specified environment") 147 case c.EnvName == "": 148 // Simply print the current environment. 149 fmt.Fprintf(ctx.Stdout, "%s\n", current) 150 return nil 151 default: 152 // Switch the environment. 153 if !names.Contains(c.EnvName) { 154 return errors.Errorf("%q is not a name of an existing defined environment or system", c.EnvName) 155 } 156 // If the name is not in the environment set, but is in the system 157 // set, then write the name into the current system file. 158 logger.Debugf("systems: %v", configSystems) 159 logger.Debugf("environs: %v", configEnvirons) 160 newEnv := c.EnvName 161 if configSystems.Contains(newEnv) && !configEnvirons.Contains(newEnv) { 162 return envcmd.SetCurrentSystem(ctx, newEnv) 163 } 164 return envcmd.SetCurrentEnvironment(ctx, newEnv) 165 } 166 }