github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/base/caller.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package base
     5  
     6  import (
     7  	"io"
     8  	"net/url"
     9  
    10  	"github.com/juju/httprequest"
    11  	"gopkg.in/juju/names.v2"
    12  )
    13  
    14  // APICaller is implemented by the client-facing State object.
    15  // It defines the lowest level of API calls and is used by
    16  // the various API implementations to actually make
    17  // the calls to the API. It should not be used outside
    18  // of tests or the api/* hierarchy.
    19  type APICaller interface {
    20  	// APICall makes a call to the API server with the given object type,
    21  	// id, request and parameters. The response is filled in with the
    22  	// call's result if the call is successful.
    23  	APICall(objType string, version int, id, request string, params, response interface{}) error
    24  
    25  	// BestFacadeVersion returns the newest version of 'objType' that this
    26  	// client can use with the current API server.
    27  	BestFacadeVersion(facade string) int
    28  
    29  	// ModelTag returns the tag of the model the client is connected
    30  	// to if there is one. It returns false for a controller-only connection.
    31  	ModelTag() (names.ModelTag, bool)
    32  
    33  	// HTTPClient returns an httprequest.Client that can be used
    34  	// to make HTTP requests to the API. URLs passed to the client
    35  	// will be made relative to the API host and the current model.
    36  	//
    37  	// Note that the URLs in HTTP requests passed to the Client.Do
    38  	// method should not include a host part.
    39  	HTTPClient() (*httprequest.Client, error)
    40  
    41  	StreamConnector
    42  }
    43  
    44  // StreamConnector is implemented by the client-facing State object.
    45  type StreamConnector interface {
    46  	// ConnectStream connects to the given HTTP websocket
    47  	// endpoint path (interpreted relative to the receiver's
    48  	// model) and returns the resulting connection.
    49  	// The given parameters are used as URL query values
    50  	// when making the initial HTTP request.
    51  	//
    52  	// The path must start with a "/".
    53  	ConnectStream(path string, attrs url.Values) (Stream, error)
    54  }
    55  
    56  // Stream represents a streaming connection to the API.
    57  type Stream interface {
    58  	io.ReadWriteCloser
    59  
    60  	// WriteJSON encodes the given value as JSON
    61  	// and writes it to the connection.
    62  	WriteJSON(v interface{}) error
    63  
    64  	// ReadJSON reads a JSON value from the stream
    65  	// and decodes it into the element pointed to by
    66  	// the given value, which should be a pointer.
    67  	ReadJSON(v interface{}) error
    68  }
    69  
    70  // FacadeCaller is a wrapper for the common paradigm that a given client just
    71  // wants to make calls on a facade using the best known version of the API. And
    72  // without dealing with an id parameter.
    73  type FacadeCaller interface {
    74  	// FacadeCall will place a request against the API using the requested
    75  	// Facade and the best version that the API server supports that is
    76  	// also known to the client.
    77  	FacadeCall(request string, params, response interface{}) error
    78  
    79  	// Name returns the facade name.
    80  	Name() string
    81  
    82  	// BestAPIVersion returns the API version that we were able to
    83  	// determine is supported by both the client and the API Server
    84  	BestAPIVersion() int
    85  
    86  	// RawAPICaller returns the wrapped APICaller. This can be used if you need
    87  	// to switch what Facade you are calling (such as Facades that return
    88  	// Watchers and then need to use the Watcher facade)
    89  	RawAPICaller() APICaller
    90  }
    91  
    92  type facadeCaller struct {
    93  	facadeName  string
    94  	bestVersion int
    95  	caller      APICaller
    96  }
    97  
    98  var _ FacadeCaller = facadeCaller{}
    99  
   100  // FacadeCall will place a request against the API using the requested
   101  // Facade and the best version that the API server supports that is
   102  // also known to the client. (id is always passed as the empty string.)
   103  func (fc facadeCaller) FacadeCall(request string, params, response interface{}) error {
   104  	return fc.caller.APICall(
   105  		fc.facadeName, fc.bestVersion, "",
   106  		request, params, response)
   107  }
   108  
   109  // Name returns the facade name.
   110  func (fc facadeCaller) Name() string {
   111  	return fc.facadeName
   112  }
   113  
   114  // BestAPIVersion returns the version of the Facade that is going to be used
   115  // for calls. It is determined using the algorithm defined in api
   116  // BestFacadeVersion. Callers can use this to determine what methods must be
   117  // used for compatibility.
   118  func (fc facadeCaller) BestAPIVersion() int {
   119  	return fc.bestVersion
   120  }
   121  
   122  // RawAPICaller returns the wrapped APICaller. This can be used if you need to
   123  // switch what Facade you are calling (such as Facades that return Watchers and
   124  // then need to use the Watcher facade)
   125  func (fc facadeCaller) RawAPICaller() APICaller {
   126  	return fc.caller
   127  }
   128  
   129  // NewFacadeCaller wraps an APICaller for a given facade name and the
   130  // best available version.
   131  func NewFacadeCaller(caller APICaller, facadeName string) FacadeCaller {
   132  	return NewFacadeCallerForVersion(caller, facadeName, caller.BestFacadeVersion(facadeName))
   133  }
   134  
   135  // NewFacadeCallerForVersion wraps an APICaller for a given facade
   136  // name and version.
   137  func NewFacadeCallerForVersion(caller APICaller, facadeName string, version int) FacadeCaller {
   138  	return facadeCaller{
   139  		facadeName:  facadeName,
   140  		bestVersion: version,
   141  		caller:      caller,
   142  	}
   143  }