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