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  }