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  }