github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/commands/apiinfo.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package commands 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 "launchpad.net/gnuflag" 13 14 "github.com/juju/juju/cmd/envcmd" 15 "github.com/juju/juju/environs/configstore" 16 ) 17 18 // APIInfoCommand returns the fields used to connect to an API server. 19 type APIInfoCommand struct { 20 envcmd.EnvCommandBase 21 out cmd.Output 22 refresh bool 23 user bool 24 password bool 25 cacert bool 26 servers bool 27 envuuid bool 28 srvuuid bool 29 fields []string 30 } 31 32 const apiInfoDoc = ` 33 Print the field values used to connect to the environment's API servers" 34 35 The exact fields to output can be specified on the command line. The 36 available fields are: 37 user 38 password 39 environ-uuid 40 state-servers 41 ca-cert 42 43 If "password" is included as a field, or the --password option is given, the 44 password value will be shown. 45 46 47 Examples: 48 $ juju api-info 49 user: admin 50 environ-uuid: 373b309b-4a86-4f13-88e2-c213d97075b8 51 state-servers: 52 - localhost:17070 53 - 10.0.3.1:17070 54 - 192.168.2.21:17070 55 ca-cert: '-----BEGIN CERTIFICATE----- 56 ... 57 -----END CERTIFICATE----- 58 ' 59 60 $ juju api-info user 61 admin 62 63 $ juju api-info user password 64 user: admin 65 password: sekrit 66 67 68 ` 69 70 func (c *APIInfoCommand) Info() *cmd.Info { 71 return &cmd.Info{ 72 Name: "api-info", 73 Args: "[field ...]", 74 Purpose: "print the field values used to connect to the environment's API servers", 75 Doc: apiInfoDoc, 76 } 77 } 78 79 func (c *APIInfoCommand) Init(args []string) error { 80 c.fields = args 81 if len(args) == 0 { 82 c.user = true 83 c.envuuid = true 84 c.srvuuid = true 85 c.servers = true 86 c.cacert = true 87 return nil 88 } 89 90 var unknown []string 91 for _, name := range args { 92 switch name { 93 case "user": 94 c.user = true 95 case "password": 96 c.password = true 97 case "environ-uuid": 98 c.envuuid = true 99 case "state-servers": 100 c.servers = true 101 case "ca-cert": 102 c.cacert = true 103 case "server-uuid": 104 c.srvuuid = true 105 default: 106 unknown = append(unknown, fmt.Sprintf("%q", name)) 107 } 108 } 109 if len(unknown) > 0 { 110 return errors.Errorf("unknown fields: %s", strings.Join(unknown, ", ")) 111 } 112 113 return nil 114 } 115 116 func (c *APIInfoCommand) SetFlags(f *gnuflag.FlagSet) { 117 c.out.AddFlags(f, "default", map[string]cmd.Formatter{ 118 "default": c.format, 119 "yaml": cmd.FormatYaml, 120 "json": cmd.FormatJson, 121 }) 122 f.BoolVar(&c.refresh, "refresh", false, "connect to the API to ensure an up-to-date endpoint location") 123 f.BoolVar(&c.password, "password", false, "include the password in the output fields") 124 } 125 126 func connectionEndpoint(c envcmd.EnvCommandBase, refresh bool) (configstore.APIEndpoint, error) { 127 return c.ConnectionEndpoint(refresh) 128 } 129 130 func connectionCredentials(c envcmd.EnvCommandBase) (configstore.APICredentials, error) { 131 return c.ConnectionCredentials() 132 } 133 134 var ( 135 endpoint = connectionEndpoint 136 creds = connectionCredentials 137 ) 138 139 // Print out the addresses of the API server endpoints. 140 func (c *APIInfoCommand) Run(ctx *cmd.Context) error { 141 apiendpoint, err := endpoint(c.EnvCommandBase, c.refresh) 142 if err != nil { 143 return err 144 } 145 credentials, err := creds(c.EnvCommandBase) 146 if err != nil { 147 return err 148 } 149 150 var result InfoData 151 if c.user { 152 result.User = credentials.User 153 } 154 if c.password { 155 result.Password = credentials.Password 156 } 157 if c.envuuid { 158 result.EnvironUUID = apiendpoint.EnvironUUID 159 } 160 if c.servers { 161 result.StateServers = apiendpoint.Addresses 162 } 163 if c.cacert { 164 result.CACert = apiendpoint.CACert 165 } 166 if c.srvuuid { 167 result.ServerUUID = apiendpoint.ServerUUID 168 } 169 170 return c.out.Write(ctx, result) 171 } 172 173 func (c *APIInfoCommand) format(value interface{}) ([]byte, error) { 174 if len(c.fields) == 1 { 175 data := value.(InfoData) 176 field, err := data.field(c.fields[0]) 177 if err != nil { 178 return nil, err 179 } 180 switch value := field.(type) { 181 case []string: 182 return []byte(strings.Join(value, "\n")), nil 183 case string: 184 return []byte(value), nil 185 default: 186 return nil, errors.Errorf("Unsupported type %T", field) 187 } 188 } 189 190 return cmd.FormatYaml(value) 191 } 192 193 type InfoData struct { 194 User string `json:"user,omitempty" yaml:",omitempty"` 195 Password string `json:"password,omitempty" yaml:",omitempty"` 196 EnvironUUID string `json:"environ-uuid,omitempty" yaml:"environ-uuid,omitempty"` 197 ServerUUID string `json:"server-uuid,omitempty" yaml:"server-uuid,omitempty"` 198 StateServers []string `json:"state-servers,omitempty" yaml:"state-servers,omitempty"` 199 CACert string `json:"ca-cert,omitempty" yaml:"ca-cert,omitempty"` 200 } 201 202 func (i *InfoData) field(name string) (interface{}, error) { 203 switch name { 204 case "user": 205 return i.User, nil 206 case "password": 207 return i.Password, nil 208 case "environ-uuid": 209 return i.EnvironUUID, nil 210 case "state-servers": 211 return i.StateServers, nil 212 case "ca-cert": 213 return i.CACert, nil 214 case "server-uuid": 215 return i.ServerUUID, nil 216 default: 217 return "", errors.Errorf("unknown field %q", name) 218 } 219 }