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 }