Matthias Andreas Benkard | 832a54e | 2019-01-29 09:27:38 +0100 | [diff] [blame^] | 1 | /* |
| 2 | Copyright 2014 The Kubernetes Authors. |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package rest |
| 18 | |
| 19 | import ( |
| 20 | "context" |
| 21 | "io" |
| 22 | "net/http" |
| 23 | "net/url" |
| 24 | |
| 25 | metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" |
| 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 27 | metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" |
| 28 | "k8s.io/apimachinery/pkg/runtime" |
| 29 | "k8s.io/apimachinery/pkg/runtime/schema" |
| 30 | "k8s.io/apimachinery/pkg/watch" |
| 31 | ) |
| 32 | |
| 33 | //TODO: |
| 34 | // Storage interfaces need to be separated into two groups; those that operate |
| 35 | // on collections and those that operate on individually named items. |
| 36 | // Collection interfaces: |
| 37 | // (Method: Current -> Proposed) |
| 38 | // GET: Lister -> CollectionGetter |
| 39 | // WATCH: Watcher -> CollectionWatcher |
| 40 | // CREATE: Creater -> CollectionCreater |
| 41 | // DELETE: (n/a) -> CollectionDeleter |
| 42 | // UPDATE: (n/a) -> CollectionUpdater |
| 43 | // |
| 44 | // Single item interfaces: |
| 45 | // (Method: Current -> Proposed) |
| 46 | // GET: Getter -> NamedGetter |
| 47 | // WATCH: (n/a) -> NamedWatcher |
| 48 | // CREATE: (n/a) -> NamedCreater |
| 49 | // DELETE: Deleter -> NamedDeleter |
| 50 | // UPDATE: Update -> NamedUpdater |
| 51 | |
| 52 | // Storage is a generic interface for RESTful storage services. |
| 53 | // Resources which are exported to the RESTful API of apiserver need to implement this interface. It is expected |
| 54 | // that objects may implement any of the below interfaces. |
| 55 | type Storage interface { |
| 56 | // New returns an empty object that can be used with Create and Update after request data has been put into it. |
| 57 | // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) |
| 58 | New() runtime.Object |
| 59 | } |
| 60 | |
| 61 | // Scoper indicates what scope the resource is at. It must be specified. |
| 62 | // It is usually provided automatically based on your strategy. |
| 63 | type Scoper interface { |
| 64 | // NamespaceScoped returns true if the storage is namespaced |
| 65 | NamespaceScoped() bool |
| 66 | } |
| 67 | |
| 68 | // KindProvider specifies a different kind for its API than for its internal storage. This is necessary for external |
| 69 | // objects that are not compiled into the api server. For such objects, there is no in-memory representation for |
| 70 | // the object, so they must be represented as generic objects (e.g. runtime.Unknown), but when we present the object as part of |
| 71 | // API discovery we want to present the specific kind, not the generic internal representation. |
| 72 | type KindProvider interface { |
| 73 | Kind() string |
| 74 | } |
| 75 | |
| 76 | // ShortNamesProvider is an interface for RESTful storage services. Delivers a list of short names for a resource. The list is used by kubectl to have short names representation of resources. |
| 77 | type ShortNamesProvider interface { |
| 78 | ShortNames() []string |
| 79 | } |
| 80 | |
| 81 | // CategoriesProvider allows a resource to specify which groups of resources (categories) it's part of. Categories can |
| 82 | // be used by API clients to refer to a batch of resources by using a single name (e.g. "all" could translate to "pod,rc,svc,..."). |
| 83 | type CategoriesProvider interface { |
| 84 | Categories() []string |
| 85 | } |
| 86 | |
| 87 | // GroupVersionKindProvider is used to specify a particular GroupVersionKind to discovery. This is used for polymorphic endpoints |
| 88 | // which generally point to foreign versions. Scale refers to Scale.v1beta1.extensions for instance. |
| 89 | // This trumps KindProvider since it is capable of providing the information required. |
| 90 | // TODO KindProvider (only used by federation) should be removed and replaced with this, but that presents greater risk late in 1.8. |
| 91 | type GroupVersionKindProvider interface { |
| 92 | GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind |
| 93 | } |
| 94 | |
| 95 | // Lister is an object that can retrieve resources that match the provided field and label criteria. |
| 96 | type Lister interface { |
| 97 | // NewList returns an empty object that can be used with the List call. |
| 98 | // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) |
| 99 | NewList() runtime.Object |
| 100 | // List selects resources in the storage which match to the selector. 'options' can be nil. |
| 101 | List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) |
| 102 | } |
| 103 | |
| 104 | // Exporter is an object that knows how to strip a RESTful resource for export. A store should implement this interface |
| 105 | // if export is generally supported for that type. Errors can still be returned during the actual Export when certain |
| 106 | // instances of the type are not exportable. |
| 107 | type Exporter interface { |
| 108 | // Export an object. Fields that are not user specified (e.g. Status, ObjectMeta.ResourceVersion) are stripped out |
| 109 | // Returns the stripped object. If 'exact' is true, fields that are specific to the cluster (e.g. namespace) are |
| 110 | // retained, otherwise they are stripped also. |
| 111 | Export(ctx context.Context, name string, opts metav1.ExportOptions) (runtime.Object, error) |
| 112 | } |
| 113 | |
| 114 | // Getter is an object that can retrieve a named RESTful resource. |
| 115 | type Getter interface { |
| 116 | // Get finds a resource in the storage by name and returns it. |
| 117 | // Although it can return an arbitrary error value, IsNotFound(err) is true for the |
| 118 | // returned error value err when the specified resource is not found. |
| 119 | Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) |
| 120 | } |
| 121 | |
| 122 | // GetterWithOptions is an object that retrieve a named RESTful resource and takes |
| 123 | // additional options on the get request. It allows a caller to also receive the |
| 124 | // subpath of the GET request. |
| 125 | type GetterWithOptions interface { |
| 126 | // Get finds a resource in the storage by name and returns it. |
| 127 | // Although it can return an arbitrary error value, IsNotFound(err) is true for the |
| 128 | // returned error value err when the specified resource is not found. |
| 129 | // The options object passed to it is of the same type returned by the NewGetOptions |
| 130 | // method. |
| 131 | // TODO: Pass metav1.GetOptions. |
| 132 | Get(ctx context.Context, name string, options runtime.Object) (runtime.Object, error) |
| 133 | |
| 134 | // NewGetOptions returns an empty options object that will be used to pass |
| 135 | // options to the Get method. It may return a bool and a string, if true, the |
| 136 | // value of the request path below the object will be included as the named |
| 137 | // string in the serialization of the runtime object. E.g., returning "path" |
| 138 | // will convert the trailing request scheme value to "path" in the map[string][]string |
| 139 | // passed to the converter. |
| 140 | NewGetOptions() (runtime.Object, bool, string) |
| 141 | } |
| 142 | |
| 143 | type TableConvertor interface { |
| 144 | ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) |
| 145 | } |
| 146 | |
| 147 | // GracefulDeleter knows how to pass deletion options to allow delayed deletion of a |
| 148 | // RESTful object. |
| 149 | type GracefulDeleter interface { |
| 150 | // Delete finds a resource in the storage and deletes it. |
| 151 | // If options are provided, the resource will attempt to honor them or return an invalid |
| 152 | // request error. |
| 153 | // Although it can return an arbitrary error value, IsNotFound(err) is true for the |
| 154 | // returned error value err when the specified resource is not found. |
| 155 | // Delete *may* return the object that was deleted, or a status object indicating additional |
| 156 | // information about deletion. |
| 157 | // It also returns a boolean which is set to true if the resource was instantly |
| 158 | // deleted or false if it will be deleted asynchronously. |
| 159 | Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) |
| 160 | } |
| 161 | |
| 162 | // CollectionDeleter is an object that can delete a collection |
| 163 | // of RESTful resources. |
| 164 | type CollectionDeleter interface { |
| 165 | // DeleteCollection selects all resources in the storage matching given 'listOptions' |
| 166 | // and deletes them. If 'options' are provided, the resource will attempt to honor |
| 167 | // them or return an invalid request error. |
| 168 | // DeleteCollection may not be atomic - i.e. it may delete some objects and still |
| 169 | // return an error after it. On success, returns a list of deleted objects. |
| 170 | DeleteCollection(ctx context.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) |
| 171 | } |
| 172 | |
| 173 | // Creater is an object that can create an instance of a RESTful object. |
| 174 | type Creater interface { |
| 175 | // New returns an empty object that can be used with Create after request data has been put into it. |
| 176 | // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) |
| 177 | New() runtime.Object |
| 178 | |
| 179 | // Create creates a new version of a resource. If includeUninitialized is set, the object may be returned |
| 180 | // without completing initialization. |
| 181 | Create(ctx context.Context, obj runtime.Object, createValidation ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) |
| 182 | } |
| 183 | |
| 184 | // NamedCreater is an object that can create an instance of a RESTful object using a name parameter. |
| 185 | type NamedCreater interface { |
| 186 | // New returns an empty object that can be used with Create after request data has been put into it. |
| 187 | // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) |
| 188 | New() runtime.Object |
| 189 | |
| 190 | // Create creates a new version of a resource. It expects a name parameter from the path. |
| 191 | // This is needed for create operations on subresources which include the name of the parent |
| 192 | // resource in the path. If includeUninitialized is set, the object may be returned without |
| 193 | // completing initialization. |
| 194 | Create(ctx context.Context, name string, obj runtime.Object, createValidation ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) |
| 195 | } |
| 196 | |
| 197 | // UpdatedObjectInfo provides information about an updated object to an Updater. |
| 198 | // It requires access to the old object in order to return the newly updated object. |
| 199 | type UpdatedObjectInfo interface { |
| 200 | // Returns preconditions built from the updated object, if applicable. |
| 201 | // May return nil, or a preconditions object containing nil fields, |
| 202 | // if no preconditions can be determined from the updated object. |
| 203 | Preconditions() *metav1.Preconditions |
| 204 | |
| 205 | // UpdatedObject returns the updated object, given a context and old object. |
| 206 | // The only time an empty oldObj should be passed in is if a "create on update" is occurring (there is no oldObj). |
| 207 | UpdatedObject(ctx context.Context, oldObj runtime.Object) (newObj runtime.Object, err error) |
| 208 | } |
| 209 | |
| 210 | // ValidateObjectFunc is a function to act on a given object. An error may be returned |
| 211 | // if the hook cannot be completed. An ObjectFunc may NOT transform the provided |
| 212 | // object. |
| 213 | type ValidateObjectFunc func(obj runtime.Object) error |
| 214 | |
| 215 | // ValidateAllObjectFunc is a "admit everything" instance of ValidateObjectFunc. |
| 216 | func ValidateAllObjectFunc(obj runtime.Object) error { |
| 217 | return nil |
| 218 | } |
| 219 | |
| 220 | // ValidateObjectUpdateFunc is a function to act on a given object and its predecessor. |
| 221 | // An error may be returned if the hook cannot be completed. An UpdateObjectFunc |
| 222 | // may NOT transform the provided object. |
| 223 | type ValidateObjectUpdateFunc func(obj, old runtime.Object) error |
| 224 | |
| 225 | // ValidateAllObjectUpdateFunc is a "admit everything" instance of ValidateObjectUpdateFunc. |
| 226 | func ValidateAllObjectUpdateFunc(obj, old runtime.Object) error { |
| 227 | return nil |
| 228 | } |
| 229 | |
| 230 | // Updater is an object that can update an instance of a RESTful object. |
| 231 | type Updater interface { |
| 232 | // New returns an empty object that can be used with Update after request data has been put into it. |
| 233 | // This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object) |
| 234 | New() runtime.Object |
| 235 | |
| 236 | // Update finds a resource in the storage and updates it. Some implementations |
| 237 | // may allow updates creates the object - they should set the created boolean |
| 238 | // to true. |
| 239 | Update(ctx context.Context, name string, objInfo UpdatedObjectInfo, createValidation ValidateObjectFunc, updateValidation ValidateObjectUpdateFunc) (runtime.Object, bool, error) |
| 240 | } |
| 241 | |
| 242 | // CreaterUpdater is a storage object that must support both create and update. |
| 243 | // Go prevents embedded interfaces that implement the same method. |
| 244 | type CreaterUpdater interface { |
| 245 | Creater |
| 246 | Update(ctx context.Context, name string, objInfo UpdatedObjectInfo, createValidation ValidateObjectFunc, updateValidation ValidateObjectUpdateFunc) (runtime.Object, bool, error) |
| 247 | } |
| 248 | |
| 249 | // CreaterUpdater must satisfy the Updater interface. |
| 250 | var _ Updater = CreaterUpdater(nil) |
| 251 | |
| 252 | // Patcher is a storage object that supports both get and update. |
| 253 | type Patcher interface { |
| 254 | Getter |
| 255 | Updater |
| 256 | } |
| 257 | |
| 258 | // Watcher should be implemented by all Storage objects that |
| 259 | // want to offer the ability to watch for changes through the watch api. |
| 260 | type Watcher interface { |
| 261 | // 'label' selects on labels; 'field' selects on the object's fields. Not all fields |
| 262 | // are supported; an error should be returned if 'field' tries to select on a field that |
| 263 | // isn't supported. 'resourceVersion' allows for continuing/starting a watch at a |
| 264 | // particular version. |
| 265 | Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) |
| 266 | } |
| 267 | |
| 268 | // StandardStorage is an interface covering the common verbs. Provided for testing whether a |
| 269 | // resource satisfies the normal storage methods. Use Storage when passing opaque storage objects. |
| 270 | type StandardStorage interface { |
| 271 | Getter |
| 272 | Lister |
| 273 | CreaterUpdater |
| 274 | GracefulDeleter |
| 275 | CollectionDeleter |
| 276 | Watcher |
| 277 | } |
| 278 | |
| 279 | // Redirector know how to return a remote resource's location. |
| 280 | type Redirector interface { |
| 281 | // ResourceLocation should return the remote location of the given resource, and an optional transport to use to request it, or an error. |
| 282 | ResourceLocation(ctx context.Context, id string) (remoteLocation *url.URL, transport http.RoundTripper, err error) |
| 283 | } |
| 284 | |
| 285 | // Responder abstracts the normal response behavior for a REST method and is passed to callers that |
| 286 | // may wish to handle the response directly in some cases, but delegate to the normal error or object |
| 287 | // behavior in other cases. |
| 288 | type Responder interface { |
| 289 | // Object writes the provided object to the response. Invoking this method multiple times is undefined. |
| 290 | Object(statusCode int, obj runtime.Object) |
| 291 | // Error writes the provided error to the response. This method may only be invoked once. |
| 292 | Error(err error) |
| 293 | } |
| 294 | |
| 295 | // Connecter is a storage object that responds to a connection request. |
| 296 | type Connecter interface { |
| 297 | // Connect returns an http.Handler that will handle the request/response for a given API invocation. |
| 298 | // The provided responder may be used for common API responses. The responder will write both status |
| 299 | // code and body, so the ServeHTTP method should exit after invoking the responder. The Handler will |
| 300 | // be used for a single API request and then discarded. The Responder is guaranteed to write to the |
| 301 | // same http.ResponseWriter passed to ServeHTTP. |
| 302 | Connect(ctx context.Context, id string, options runtime.Object, r Responder) (http.Handler, error) |
| 303 | |
| 304 | // NewConnectOptions returns an empty options object that will be used to pass |
| 305 | // options to the Connect method. If nil, then a nil options object is passed to |
| 306 | // Connect. It may return a bool and a string. If true, the value of the request |
| 307 | // path below the object will be included as the named string in the serialization |
| 308 | // of the runtime object. |
| 309 | NewConnectOptions() (runtime.Object, bool, string) |
| 310 | |
| 311 | // ConnectMethods returns the list of HTTP methods handled by Connect |
| 312 | ConnectMethods() []string |
| 313 | } |
| 314 | |
| 315 | // ResourceStreamer is an interface implemented by objects that prefer to be streamed from the server |
| 316 | // instead of decoded directly. |
| 317 | type ResourceStreamer interface { |
| 318 | // InputStream should return an io.ReadCloser if the provided object supports streaming. The desired |
| 319 | // api version and an accept header (may be empty) are passed to the call. If no error occurs, |
| 320 | // the caller may return a flag indicating whether the result should be flushed as writes occur |
| 321 | // and a content type string that indicates the type of the stream. |
| 322 | // If a null stream is returned, a StatusNoContent response wil be generated. |
| 323 | InputStream(apiVersion, acceptHeader string) (stream io.ReadCloser, flush bool, mimeType string, err error) |
| 324 | } |
| 325 | |
| 326 | // StorageMetadata is an optional interface that callers can implement to provide additional |
| 327 | // information about their Storage objects. |
| 328 | type StorageMetadata interface { |
| 329 | // ProducesMIMETypes returns a list of the MIME types the specified HTTP verb (GET, POST, DELETE, |
| 330 | // PATCH) can respond with. |
| 331 | ProducesMIMETypes(verb string) []string |
| 332 | |
| 333 | // ProducesObject returns an object the specified HTTP verb respond with. It will overwrite storage object if |
| 334 | // it is not nil. Only the type of the return object matters, the value will be ignored. |
| 335 | ProducesObject(verb string) interface{} |
| 336 | } |
| 337 | |
| 338 | // +k8s:deepcopy-gen=true |
| 339 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object |
| 340 | // ConnectRequest is an object passed to admission control for Connect operations |
| 341 | type ConnectRequest struct { |
| 342 | // Name is the name of the object on which the connect request was made |
| 343 | Name string |
| 344 | |
| 345 | // Options is the options object passed to the connect request. See the NewConnectOptions method on Connecter |
| 346 | Options runtime.Object |
| 347 | |
| 348 | // ResourcePath is the path for the resource in the REST server (ie. "pods/proxy") |
| 349 | ResourcePath string |
| 350 | } |
| 351 | |
| 352 | func (obj *ConnectRequest) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind } |