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