github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/api/interface.go (about)

     1  // Copyright 2012-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package api
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  	"github.com/juju/version"
    12  	"gopkg.in/macaroon-bakery.v1/httpbakery"
    13  	"gopkg.in/macaroon.v1"
    14  
    15  	"github.com/juju/juju/api/addresser"
    16  	"github.com/juju/juju/api/base"
    17  	"github.com/juju/juju/api/charmrevisionupdater"
    18  	"github.com/juju/juju/api/cleaner"
    19  	"github.com/juju/juju/api/discoverspaces"
    20  	"github.com/juju/juju/api/firewaller"
    21  	"github.com/juju/juju/api/imagemetadata"
    22  	"github.com/juju/juju/api/instancepoller"
    23  	"github.com/juju/juju/api/provisioner"
    24  	"github.com/juju/juju/api/reboot"
    25  	"github.com/juju/juju/api/unitassigner"
    26  	"github.com/juju/juju/api/uniter"
    27  	"github.com/juju/juju/api/upgrader"
    28  	"github.com/juju/juju/network"
    29  	"github.com/juju/juju/rpc"
    30  )
    31  
    32  // Info encapsulates information about a server holding juju state and
    33  // can be used to make a connection to it.
    34  type Info struct {
    35  
    36  	// This block of fields is sufficient to connect:
    37  
    38  	// Addrs holds the addresses of the controllers.
    39  	Addrs []string
    40  
    41  	// CACert holds the CA certificate that will be used
    42  	// to validate the controller's certificate, in PEM format.
    43  	CACert string
    44  
    45  	// ModelTag holds the model tag for the model we are
    46  	// trying to connect to.
    47  	ModelTag names.ModelTag
    48  
    49  	// ...but this block of fields is all about the authentication mechanism
    50  	// to use after connecting -- if any -- and should probably be extracted.
    51  
    52  	// SkipLogin, if true, skips the Login call on connection. It is an
    53  	// error to set Tag, Password, or Macaroons if SkipLogin is true.
    54  	SkipLogin bool `yaml:"-"`
    55  
    56  	// Tag holds the name of the entity that is connecting.
    57  	// If this is nil, and the password is empty, no login attempt will be made.
    58  	// (this is to allow tests to access the API to check that operations
    59  	// fail when not logged in).
    60  	Tag names.Tag
    61  
    62  	// Password holds the password for the administrator or connecting entity.
    63  	Password string
    64  
    65  	// Macaroons holds a slice of macaroon.Slice that may be used to
    66  	// authenticate with the API server.
    67  	Macaroons []macaroon.Slice `yaml:",omitempty"`
    68  
    69  	// Nonce holds the nonce used when provisioning the machine. Used
    70  	// only by the machine agent.
    71  	Nonce string `yaml:",omitempty"`
    72  }
    73  
    74  // Validate validates the API info.
    75  func (info *Info) Validate() error {
    76  	if len(info.Addrs) == 0 {
    77  		return errors.NotValidf("missing addresses")
    78  	}
    79  	if info.CACert == "" {
    80  		return errors.NotValidf("missing CA certificate")
    81  	}
    82  	if info.SkipLogin {
    83  		if info.Tag != nil {
    84  			return errors.NotValidf("specifying Tag and SkipLogin")
    85  		}
    86  		if info.Password != "" {
    87  			return errors.NotValidf("specifying Password and SkipLogin")
    88  		}
    89  		if len(info.Macaroons) > 0 {
    90  			return errors.NotValidf("specifying Macaroons and SkipLogin")
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  // DialOpts holds configuration parameters that control the
    97  // Dialing behavior when connecting to a controller.
    98  type DialOpts struct {
    99  	// DialAddressInterval is the amount of time to wait
   100  	// before starting to dial another address.
   101  	DialAddressInterval time.Duration
   102  
   103  	// Timeout is the amount of time to wait contacting
   104  	// a controller.
   105  	Timeout time.Duration
   106  
   107  	// RetryDelay is the amount of time to wait between
   108  	// unsucssful connection attempts.
   109  	RetryDelay time.Duration
   110  
   111  	// BakeryClient is the httpbakery Client, which
   112  	// is used to do the macaroon-based authorization.
   113  	// This and the *http.Client inside it are copied
   114  	// by Open, and any RoundTripper field
   115  	// the HTTP client is ignored.
   116  	BakeryClient *httpbakery.Client
   117  
   118  	// InsecureSkipVerify skips TLS certificate verification
   119  	// when connecting to the controller. This should only
   120  	// be used in tests, or when verification cannot be
   121  	// performed and the communication need not be secure.
   122  	InsecureSkipVerify bool
   123  }
   124  
   125  // DefaultDialOpts returns a DialOpts representing the default
   126  // parameters for contacting a controller.
   127  func DefaultDialOpts() DialOpts {
   128  	return DialOpts{
   129  		DialAddressInterval: 50 * time.Millisecond,
   130  		Timeout:             10 * time.Minute,
   131  		RetryDelay:          2 * time.Second,
   132  	}
   133  }
   134  
   135  // OpenFunc is the usual form of a function that opens an API connection.
   136  type OpenFunc func(*Info, DialOpts) (Connection, error)
   137  
   138  // Connection exists purely to make api-opening funcs mockable. It's just a
   139  // dumb copy of all the methods on api.Connection; we can and should be extracting
   140  // smaller and more relevant interfaces (and dropping some of them too).
   141  
   142  // Connection represents a connection to a Juju API server.
   143  type Connection interface {
   144  
   145  	// This first block of methods is pretty close to a sane Connection interface.
   146  	Close() error
   147  	Broken() <-chan struct{}
   148  	Addr() string
   149  	APIHostPorts() [][]network.HostPort
   150  
   151  	// These are a bit off -- ServerVersion is apparently not known until after
   152  	// Login()? Maybe evidence of need for a separate AuthenticatedConnection..?
   153  	Login(name names.Tag, password, nonce string, ms []macaroon.Slice) error
   154  	ServerVersion() (version.Number, bool)
   155  
   156  	// APICaller provides the facility to make API calls directly.
   157  	// This should not be used outside the api/* packages or tests.
   158  	base.APICaller
   159  
   160  	// ControllerTag returns the model tag of the controller
   161  	// (as opposed to the model tag of the currently connected
   162  	// model inside that controller).
   163  	// This could be defined on base.APICaller.
   164  	ControllerTag() (names.ModelTag, error)
   165  
   166  	// All the rest are strange and questionable and deserve extra attention
   167  	// and/or discussion.
   168  
   169  	// Something-or-other expects Ping to exist, and *maybe* the heartbeat
   170  	// *should* be handled outside the State type, but it's also handled
   171  	// inside it as well. We should figure this out sometime -- we should
   172  	// either expose Ping() or Broken() but not both.
   173  	Ping() error
   174  
   175  	// RPCClient is apparently exported for testing purposes only, but this
   176  	// seems to indicate *some* sort of layering confusion.
   177  	RPCClient() *rpc.Conn
   178  
   179  	// I think this is actually dead code. It's tested, at least, so I'm
   180  	// keeping it for now, but it's not apparently used anywhere else.
   181  	AllFacadeVersions() map[string][]int
   182  
   183  	// These methods expose a bunch of worker-specific facades, and basically
   184  	// just should not exist; but removing them is too noisy for a single CL.
   185  	// Client in particular is intimately coupled with State -- and the others
   186  	// will be easy to remove, but until we're using them via manifolds it's
   187  	// prohibitively ugly to do so.
   188  	Client() *Client
   189  	Provisioner() *provisioner.State
   190  	Uniter() (*uniter.State, error)
   191  	Firewaller() *firewaller.State
   192  	Upgrader() *upgrader.State
   193  	Reboot() (reboot.State, error)
   194  	Addresser() *addresser.API
   195  	DiscoverSpaces() *discoverspaces.API
   196  	InstancePoller() *instancepoller.API
   197  	CharmRevisionUpdater() *charmrevisionupdater.State
   198  	Cleaner() *cleaner.API
   199  	MetadataUpdater() *imagemetadata.Client
   200  	UnitAssigner() unitassigner.API
   201  }