github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/envcmd/systemcommand.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package envcmd
     5  
     6  import (
     7  	"github.com/juju/cmd"
     8  	"github.com/juju/errors"
     9  	"launchpad.net/gnuflag"
    10  
    11  	"github.com/juju/juju/api"
    12  	"github.com/juju/juju/api/environmentmanager"
    13  	"github.com/juju/juju/api/systemmanager"
    14  	"github.com/juju/juju/api/usermanager"
    15  	"github.com/juju/juju/environs/configstore"
    16  	"github.com/juju/juju/juju"
    17  )
    18  
    19  // ErrNoSystemSpecified is returned by commands that operate on
    20  // a system if there is no current system, no system has been
    21  // explicitly specified, and there is no default system.
    22  var ErrNoSystemSpecified = errors.New("no system specified")
    23  
    24  // SystemCommand is intended to be a base for all commands
    25  // that need to operate on systems as opposed to environments.
    26  type SystemCommand interface {
    27  	cmd.Command
    28  
    29  	// SetSystemName is called prior to the wrapped command's Init method with
    30  	// the active system name. The system name is guaranteed to be non-empty
    31  	// at entry of Init.
    32  	SetSystemName(systemName string)
    33  
    34  	// SystemName returns the name of the system or environment used to
    35  	// determine that API end point.
    36  	SystemName() string
    37  }
    38  
    39  // SysCommandBase is a convenience type for embedding in commands
    40  // that wish to implement SystemCommand.
    41  type SysCommandBase struct {
    42  	cmd.CommandBase
    43  	systemName string
    44  }
    45  
    46  // SetSystemName records the current environment name in the SysCommandBase
    47  func (c *SysCommandBase) SetSystemName(systemName string) {
    48  	c.systemName = systemName
    49  }
    50  
    51  // SystemName returns the name of the system or environment used to determine
    52  // that API end point.
    53  func (c *SysCommandBase) SystemName() string {
    54  	return c.systemName
    55  }
    56  
    57  // NewEnvironmentManagerAPIClient returns an API client for the
    58  // EnvironmentManager on the current system using the current credentials.
    59  func (c *SysCommandBase) NewEnvironmentManagerAPIClient() (*environmentmanager.Client, error) {
    60  	root, err := c.newAPIRoot()
    61  	if err != nil {
    62  		return nil, errors.Trace(err)
    63  	}
    64  	return environmentmanager.NewClient(root), nil
    65  }
    66  
    67  // NewSystemManagerAPIClient returns an API client for the SystemManager on
    68  // the current system using the current credentials.
    69  func (c *SysCommandBase) NewSystemManagerAPIClient() (*systemmanager.Client, error) {
    70  	root, err := c.newAPIRoot()
    71  	if err != nil {
    72  		return nil, errors.Trace(err)
    73  	}
    74  	return systemmanager.NewClient(root), nil
    75  }
    76  
    77  // NewUserManagerAPIClient returns an API client for the UserManager on the
    78  // current system using the current credentials.
    79  func (c *SysCommandBase) NewUserManagerAPIClient() (*usermanager.Client, error) {
    80  	root, err := c.newAPIRoot()
    81  	if err != nil {
    82  		return nil, errors.Trace(err)
    83  	}
    84  	return usermanager.NewClient(root), nil
    85  }
    86  
    87  // newAPIRoot returns a restricted API for the current system using the current
    88  // credentials.  Only the UserManager and EnvironmentManager may be accessed
    89  // through this API connection.
    90  func (c *SysCommandBase) newAPIRoot() (api.Connection, error) {
    91  	if c.systemName == "" {
    92  		return nil, errors.Trace(ErrNoSystemSpecified)
    93  	}
    94  	return juju.NewAPIFromName(c.systemName)
    95  }
    96  
    97  // ConnectionCredentials returns the credentials used to connect to the API for
    98  // the specified system.
    99  func (c *SysCommandBase) ConnectionCredentials() (configstore.APICredentials, error) {
   100  	// TODO: the user may soon be specified through the command line
   101  	// or through an environment setting, so return these when they are ready.
   102  	var emptyCreds configstore.APICredentials
   103  	info, err := c.ConnectionInfo()
   104  	if err != nil {
   105  		return emptyCreds, errors.Trace(err)
   106  	}
   107  	return info.APICredentials(), nil
   108  }
   109  
   110  // ConnectionEndpoint returns the endpoint details used to connect to the API for
   111  // the specified system.
   112  func (c *SysCommandBase) ConnectionEndpoint() (configstore.APIEndpoint, error) {
   113  	// TODO: the user may soon be specified through the command line
   114  	// or through an environment setting, so return these when they are ready.
   115  	var empty configstore.APIEndpoint
   116  	info, err := c.ConnectionInfo()
   117  	if err != nil {
   118  		return empty, errors.Trace(err)
   119  	}
   120  	return info.APIEndpoint(), nil
   121  }
   122  
   123  // ConnectionInfo returns the environ info from the cached config store.
   124  func (c *SysCommandBase) ConnectionInfo() (configstore.EnvironInfo, error) {
   125  	// TODO: the user may soon be specified through the command line
   126  	// or through an environment setting, so return these when they are ready.
   127  	if c.systemName == "" {
   128  		return nil, errors.Trace(ErrNoSystemSpecified)
   129  	}
   130  	info, err := ConnectionInfoForName(c.systemName)
   131  	if err != nil {
   132  		return nil, errors.Trace(err)
   133  	}
   134  	return info, nil
   135  }
   136  
   137  // Wrap wraps the specified SystemCommand, returning a Command
   138  // that proxies to each of the SystemCommand methods.
   139  func WrapSystem(c SystemCommand) cmd.Command {
   140  	return &sysCommandWrapper{SystemCommand: c}
   141  }
   142  
   143  type sysCommandWrapper struct {
   144  	SystemCommand
   145  	systemName string
   146  }
   147  
   148  // SetFlags implements Command.SetFlags, then calls the wrapped command's SetFlags.
   149  func (w *sysCommandWrapper) SetFlags(f *gnuflag.FlagSet) {
   150  	f.StringVar(&w.systemName, "s", "", "juju system to operate in")
   151  	f.StringVar(&w.systemName, "system", "", "")
   152  	w.SystemCommand.SetFlags(f)
   153  }
   154  
   155  func (w *sysCommandWrapper) getDefaultSystemName() (string, error) {
   156  	if currentSystem, err := ReadCurrentSystem(); err != nil {
   157  		return "", errors.Trace(err)
   158  	} else if currentSystem != "" {
   159  		return currentSystem, nil
   160  	}
   161  	if currentEnv, err := ReadCurrentEnvironment(); err != nil {
   162  		return "", errors.Trace(err)
   163  	} else if currentEnv != "" {
   164  		return currentEnv, nil
   165  	}
   166  	return "", errors.Trace(ErrNoSystemSpecified)
   167  }
   168  
   169  // Init implements Command.Init, then calls the wrapped command's Init.
   170  func (w *sysCommandWrapper) Init(args []string) error {
   171  	if w.systemName == "" {
   172  		name, err := w.getDefaultSystemName()
   173  		if err != nil {
   174  			return errors.Trace(err)
   175  		}
   176  		w.systemName = name
   177  	}
   178  	w.SetSystemName(w.systemName)
   179  	return w.SystemCommand.Init(args)
   180  }