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 }