github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/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 environments, err := environs.ReadEnvirons("") 84 if err != nil { 85 return errors.Errorf("couldn't read the environment") 86 } 87 88 names := set.NewStrings(environments.Names()...) 89 configEnvirons, configSystems, err := getConfigstoreOptions() 90 if err != nil { 91 return err 92 } 93 names = names.Union(configEnvirons) 94 names = names.Union(configSystems) 95 96 if c.List { 97 // List all environments and systems. 98 if c.EnvName != "" { 99 return errors.New("cannot switch and list at the same time") 100 } 101 for _, name := range names.SortedValues() { 102 if configSystems.Contains(name) && !configEnvirons.Contains(name) { 103 name += systemSuffix 104 } 105 fmt.Fprintf(ctx.Stdout, "%s\n", name) 106 } 107 return nil 108 } 109 110 jujuEnv := os.Getenv("JUJU_ENV") 111 if jujuEnv != "" { 112 if c.EnvName == "" { 113 fmt.Fprintf(ctx.Stdout, "%s\n", jujuEnv) 114 return nil 115 } else { 116 return errors.Errorf("cannot switch when JUJU_ENV is overriding the environment (set to %q)", jujuEnv) 117 } 118 } 119 120 current, isSystem, err := envcmd.CurrentConnectionName() 121 if err != nil { 122 return errors.Trace(err) 123 } 124 if current == "" { 125 current = environments.Default 126 } else if isSystem { 127 current += systemSuffix 128 } 129 130 // Handle the different operation modes. 131 switch { 132 case c.EnvName == "" && current == "": 133 // Nothing specified and nothing to switch to. 134 return errors.New("no currently specified environment") 135 case c.EnvName == "": 136 // Simply print the current environment. 137 fmt.Fprintf(ctx.Stdout, "%s\n", current) 138 return nil 139 default: 140 // Switch the environment. 141 if !names.Contains(c.EnvName) { 142 return errors.Errorf("%q is not a name of an existing defined environment or system", c.EnvName) 143 } 144 // If the name is not in the environment set, but is in the system 145 // set, then write the name into the current system file. 146 logger.Debugf("systems: %v", configSystems) 147 logger.Debugf("environs: %v", configEnvirons) 148 newEnv := c.EnvName 149 if configSystems.Contains(newEnv) && !configEnvirons.Contains(newEnv) { 150 return envcmd.SetCurrentSystem(ctx, newEnv) 151 } 152 return envcmd.SetCurrentEnvironment(ctx, newEnv) 153 } 154 }