github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/system/environments.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package system
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"text/tabwriter"
    10  	"time"
    11  
    12  	"github.com/juju/cmd"
    13  	"github.com/juju/errors"
    14  	"launchpad.net/gnuflag"
    15  
    16  	"github.com/juju/juju/api/base"
    17  	"github.com/juju/juju/cmd/envcmd"
    18  	"github.com/juju/juju/cmd/juju/user"
    19  	"github.com/juju/juju/environs/configstore"
    20  )
    21  
    22  // EnvironmentsCommand returns the list of all the environments the
    23  // current user can access on the current system.
    24  type EnvironmentsCommand struct {
    25  	envcmd.SysCommandBase
    26  	out       cmd.Output
    27  	all       bool
    28  	user      string
    29  	listUUID  bool
    30  	exactTime bool
    31  	envAPI    EnvironmentsEnvAPI
    32  	sysAPI    EnvironmentsSysAPI
    33  	userCreds *configstore.APICredentials
    34  }
    35  
    36  var envsDoc = `
    37  List all the environments the user can access on the current system.
    38  
    39  The environments listed here are either environments you have created
    40  yourself, or environments which have been shared with you.
    41  
    42  See Also:
    43      juju help juju-systems
    44      juju help systems
    45      juju help environment users
    46      juju help environment share
    47      juju help environment unshare
    48  `
    49  
    50  // EnvironmentsEnvAPI defines the methods on the environment manager API that
    51  // the environments command calls.
    52  type EnvironmentsEnvAPI interface {
    53  	Close() error
    54  	ListEnvironments(user string) ([]base.UserEnvironment, error)
    55  }
    56  
    57  // EnvironmentsSysAPI defines the methods on the system manager API that the
    58  // environments command calls.
    59  type EnvironmentsSysAPI interface {
    60  	Close() error
    61  	AllEnvironments() ([]base.UserEnvironment, error)
    62  }
    63  
    64  // Info implements Command.Info
    65  func (c *EnvironmentsCommand) Info() *cmd.Info {
    66  	return &cmd.Info{
    67  		Name:    "environments",
    68  		Purpose: "list all environments the user can access on the current system",
    69  		Doc:     envsDoc,
    70  	}
    71  }
    72  
    73  func (c *EnvironmentsCommand) getEnvAPI() (EnvironmentsEnvAPI, error) {
    74  	if c.envAPI != nil {
    75  		return c.envAPI, nil
    76  	}
    77  	return c.NewEnvironmentManagerAPIClient()
    78  }
    79  
    80  func (c *EnvironmentsCommand) getSysAPI() (EnvironmentsSysAPI, error) {
    81  	if c.sysAPI != nil {
    82  		return c.sysAPI, nil
    83  	}
    84  	return c.NewSystemManagerAPIClient()
    85  }
    86  
    87  func (c *EnvironmentsCommand) getConnectionCredentials() (configstore.APICredentials, error) {
    88  	if c.userCreds != nil {
    89  		return *c.userCreds, nil
    90  	}
    91  	return c.ConnectionCredentials()
    92  }
    93  
    94  // SetFlags implements Command.SetFlags.
    95  func (c *EnvironmentsCommand) SetFlags(f *gnuflag.FlagSet) {
    96  	f.StringVar(&c.user, "user", "", "the user to list environments for (administrative users only)")
    97  	f.BoolVar(&c.all, "all", false, "show all environments  (administrative users only)")
    98  	f.BoolVar(&c.listUUID, "uuid", false, "display UUID for environments")
    99  	f.BoolVar(&c.exactTime, "exact-time", false, "use full timestamp precision")
   100  	c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{
   101  		"yaml":    cmd.FormatYaml,
   102  		"json":    cmd.FormatJson,
   103  		"tabular": c.formatTabular,
   104  	})
   105  }
   106  
   107  // Local structure that controls the output structure.
   108  type UserEnvironment struct {
   109  	Name           string `json:"name"`
   110  	UUID           string `json:"env-uuid" yaml:"env-uuid"`
   111  	Owner          string `json:"owner"`
   112  	LastConnection string `json:"last-connection" yaml:"last-connection"`
   113  }
   114  
   115  // Run implements Command.Run
   116  func (c *EnvironmentsCommand) Run(ctx *cmd.Context) error {
   117  	if c.user == "" {
   118  		creds, err := c.getConnectionCredentials()
   119  		if err != nil {
   120  			return errors.Trace(err)
   121  		}
   122  		c.user = creds.User
   123  	}
   124  
   125  	var envs []base.UserEnvironment
   126  	var err error
   127  	if c.all {
   128  		envs, err = c.getAllEnvironments()
   129  	} else {
   130  		envs, err = c.getUserEnvironments()
   131  	}
   132  	if err != nil {
   133  		return errors.Annotate(err, "cannot list environments")
   134  	}
   135  
   136  	output := make([]UserEnvironment, len(envs))
   137  	now := time.Now()
   138  	for i, env := range envs {
   139  		output[i] = UserEnvironment{
   140  			Name:           env.Name,
   141  			UUID:           env.UUID,
   142  			Owner:          env.Owner,
   143  			LastConnection: user.LastConnection(env.LastConnection, now, c.exactTime),
   144  		}
   145  	}
   146  
   147  	return c.out.Write(ctx, output)
   148  }
   149  
   150  func (c *EnvironmentsCommand) getAllEnvironments() ([]base.UserEnvironment, error) {
   151  	client, err := c.getSysAPI()
   152  	if err != nil {
   153  		return nil, errors.Trace(err)
   154  	}
   155  	defer client.Close()
   156  	return client.AllEnvironments()
   157  }
   158  
   159  func (c *EnvironmentsCommand) getUserEnvironments() ([]base.UserEnvironment, error) {
   160  	client, err := c.getEnvAPI()
   161  	if err != nil {
   162  		return nil, errors.Trace(err)
   163  	}
   164  	defer client.Close()
   165  	return client.ListEnvironments(c.user)
   166  }
   167  
   168  // formatTabular takes an interface{} to adhere to the cmd.Formatter interface
   169  func (c *EnvironmentsCommand) formatTabular(value interface{}) ([]byte, error) {
   170  	envs, ok := value.([]UserEnvironment)
   171  	if !ok {
   172  		return nil, errors.Errorf("expected value of type %T, got %T", envs, value)
   173  	}
   174  	var out bytes.Buffer
   175  	const (
   176  		// To format things into columns.
   177  		minwidth = 0
   178  		tabwidth = 1
   179  		padding  = 2
   180  		padchar  = ' '
   181  		flags    = 0
   182  	)
   183  	tw := tabwriter.NewWriter(&out, minwidth, tabwidth, padding, padchar, flags)
   184  	fmt.Fprintf(tw, "NAME")
   185  	if c.listUUID {
   186  		fmt.Fprintf(tw, "\tENVIRONMENT UUID")
   187  	}
   188  	fmt.Fprintf(tw, "\tOWNER\tLAST CONNECTION\n")
   189  	for _, env := range envs {
   190  		fmt.Fprintf(tw, "%s", env.Name)
   191  		if c.listUUID {
   192  			fmt.Fprintf(tw, "\t%s", env.UUID)
   193  		}
   194  		fmt.Fprintf(tw, "\t%s\t%s\n", env.Owner, env.LastConnection)
   195  	}
   196  	tw.Flush()
   197  	return out.Bytes(), nil
   198  }