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  }