UNPKG

@kubernetes/client-node

Version:
469 lines 26.5 kB
import { ApiException, HttpMethod, } from './api.js'; import { ObjectSerializer } from './serializer.js'; import { from, mergeMap, of } from './gen/rxjsStub.js'; import { PatchStrategy } from './patch.js'; /** * Dynamically construct Kubernetes API request URIs so client does not have to know what type of object it is acting * on. */ export class KubernetesObjectApi { /** * Create a KubernetesObjectApi object from the provided KubeConfig. This method should be used rather than * [[KubeConfig.makeApiClient]] so we can properly determine the default namespace if one is provided by the current * context. * * @param kc Valid Kubernetes config * @return Properly instantiated [[KubernetesObjectApi]] object */ static makeApiClient(kc) { const client = kc.makeApiClient(KubernetesObjectApi); client.setDefaultNamespace(kc); return client; } constructor(configuration) { /** Initialize the default namespace. May be overwritten by context. */ this.defaultNamespace = 'default'; /** Cache resource API response. */ this.apiVersionResourceCache = {}; this.configuration = configuration; } /** * Create any Kubernetes resource. * @param spec Kubernetes resource spec. * @param pretty If \&#39;true\&#39;, then the output is pretty printed. * @param dryRun When present, indicates that modifications should not be persisted. An invalid or unrecognized * dryRun directive will result in an error response and no further processing of the request. Valid values * are: - All: all dry run stages will be processed * @param fieldManager fieldManager is a name associated with the actor or entity that is making these changes. The * value must be less than or 128 characters long, and only contain printable characters, as defined by * https://golang.org/pkg/unicode/#IsPrint. * @param options Optional headers to use in the request. * @return Promise containing the request response and [[KubernetesObject]]. */ async create(spec, pretty, dryRun, fieldManager, options) { const _config = options || this.configuration; // verify required parameter 'spec' is not null or undefined if (spec === null || spec === undefined) { throw new Error('Required parameter spec was null or undefined when calling create.'); } const localVarPath = await this.specUriPath(spec, 'create'); const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.POST); requestContext.setHeaderParam('Accept', 'application/json, */*;q=0.8'); if (pretty !== undefined) { requestContext.setQueryParam('pretty', ObjectSerializer.serialize(pretty, 'string')); } if (dryRun !== undefined) { requestContext.setQueryParam('dryRun', ObjectSerializer.serialize(dryRun, 'string')); } if (fieldManager !== undefined) { requestContext.setQueryParam('fieldManager', ObjectSerializer.serialize(fieldManager, 'string')); } // Body Params const contentType = ObjectSerializer.getPreferredMediaType([]); requestContext.setHeaderParam('Content-Type', contentType); const serializedBody = ObjectSerializer.stringify(ObjectSerializer.serialize(spec, 'any'), contentType); requestContext.setBody(serializedBody); return this.requestPromise(requestContext); } /** * Delete any Kubernetes resource. * @param spec Kubernetes resource spec * @param pretty If \&#39;true\&#39;, then the output is pretty printed. * @param dryRun When present, indicates that modifications should not be persisted. An invalid or unrecognized * dryRun directive will result in an error response and no further processing of the request. Valid values * are: - All: all dry run stages will be processed * @param gracePeriodSeconds The duration in seconds before the object should be deleted. Value must be non-negative * integer. The value zero indicates delete immediately. If this value is nil, the default grace period for * the specified type will be used. Defaults to a per object value if not specified. zero means delete * immediately. * @param orphanDependents Deprecated: please use the PropagationPolicy, this field will be deprecated in * 1.7. Should the dependent objects be orphaned. If true/false, the \&quot;orphan\&quot; finalizer will be * added to/removed from the object\&#39;s finalizers list. Either this field or PropagationPolicy may be * set, but not both. * @param propagationPolicy Whether and how garbage collection will be performed. Either this field or * OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in * the metadata.finalizers and the resource-specific default policy. Acceptable values are: * \&#39;Orphan\&#39; - orphan the dependents; \&#39;Background\&#39; - allow the garbage collector to delete * the dependents in the background; \&#39;Foreground\&#39; - a cascading policy that deletes all dependents * in the foreground. * @param body See [[V1DeleteOptions]]. * @param options Optional headers to use in the request. * @return Promise containing the request response and a Kubernetes [[V1Status]]. */ async delete(spec, pretty, dryRun, gracePeriodSeconds, orphanDependents, propagationPolicy, body, options) { const _config = options || this.configuration; // verify required parameter 'spec' is not null or undefined if (spec === null || spec === undefined) { throw new Error('Required parameter spec was null or undefined when calling delete.'); } const localVarPath = await this.specUriPath(spec, 'delete'); const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.DELETE); requestContext.setHeaderParam('Accept', 'application/json, */*;q=0.8'); if (pretty !== undefined) { requestContext.setQueryParam('pretty', ObjectSerializer.serialize(pretty, 'string')); } if (dryRun !== undefined) { requestContext.setQueryParam('dryRun', ObjectSerializer.serialize(dryRun, 'string')); } if (gracePeriodSeconds !== undefined) { requestContext.setQueryParam('gracePeriodSeconds', ObjectSerializer.serialize(gracePeriodSeconds, 'number')); } if (orphanDependents !== undefined) { requestContext.setQueryParam('orphanDependents', ObjectSerializer.serialize(orphanDependents, 'boolean')); } if (propagationPolicy !== undefined) { requestContext.setQueryParam('propagationPolicy', ObjectSerializer.serialize(propagationPolicy, 'string')); } // Body Params if (body) { const contentType = ObjectSerializer.getPreferredMediaType([]); requestContext.setHeaderParam('Content-Type', contentType); const serializedBody = ObjectSerializer.stringify(ObjectSerializer.serialize(body, 'V1DeleteOptions'), contentType); requestContext.setBody(serializedBody); } return this.requestPromise(requestContext, 'V1Status'); } /** * Patch any Kubernetes resource. * @param spec Kubernetes resource spec * @param pretty If \&#39;true\&#39;, then the output is pretty printed. * @param dryRun When present, indicates that modifications should not be persisted. An invalid or unrecognized * dryRun directive will result in an error response and no further processing of the request. Valid values * are: - All: all dry run stages will be processed * @param fieldManager fieldManager is a name associated with the actor or entity that is making these changes. The * value must be less than or 128 characters long, and only contain printable characters, as defined by * https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests * (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, * StrategicMergePatch). * @param force Force is going to \&quot;force\&quot; Apply requests. It means user will re-acquire conflicting * fields owned by other people. Force flag must be unset for non-apply patch requests. * @param patchStrategy Content-Type header used to control how the patch will be performed. See * See https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/ * for details. * @param options Optional headers to use in the request. * @return Promise containing the request response and [[KubernetesObject]]. */ async patch(spec, pretty, dryRun, fieldManager, force, patchStrategy = PatchStrategy.StrategicMergePatch, options) { const _config = options || this.configuration; // verify required parameter 'spec' is not null or undefined if (spec === null || spec === undefined) { throw new Error('Required parameter spec was null or undefined when calling patch.'); } const localVarPath = await this.specUriPath(spec, 'patch'); const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.PATCH); requestContext.setHeaderParam('Accept', 'application/json, */*;q=0.8'); requestContext.setHeaderParam('Content-Type', patchStrategy); if (pretty !== undefined) { requestContext.setQueryParam('pretty', ObjectSerializer.serialize(pretty, 'string')); } if (dryRun !== undefined) { requestContext.setQueryParam('dryRun', ObjectSerializer.serialize(dryRun, 'string')); } if (fieldManager !== undefined) { requestContext.setQueryParam('fieldManager', ObjectSerializer.serialize(fieldManager, 'string')); } if (force !== undefined) { requestContext.setQueryParam('force', ObjectSerializer.serialize(force, 'boolean')); } // Body Params const serializedBody = ObjectSerializer.stringify(ObjectSerializer.serialize(spec, 'any'), // TODO: use the patch content type once ObjectSerializer supports it. 'application/json'); requestContext.setBody(serializedBody); return this.requestPromise(requestContext); } /** * Read any Kubernetes resource. * @param spec Kubernetes resource spec * @param pretty If \&#39;true\&#39;, then the output is pretty printed. * @param exact Should the export be exact. Exact export maintains cluster-specific fields like * \&#39;Namespace\&#39;. Deprecated. Planned for removal in 1.18. * @param exportt Should this value be exported. Export strips fields that a user can not * specify. Deprecated. Planned for removal in 1.18. * @param options Optional headers to use in the request. * @return Promise containing the request response and [[KubernetesObject]]. */ async read(spec, pretty, exact, exportt, options) { const _config = options || this.configuration; // verify required parameter 'spec' is not null or undefined if (spec === null || spec === undefined) { throw new Error('Required parameter spec was null or undefined when calling read.'); } // verify required parameter 'kind' is not null or undefined if (spec.kind === null || spec.kind === undefined) { throw new Error('Required parameter spec.kind was null or undefined when calling read.'); } if (!spec.apiVersion) { throw new Error('Required parameter spec.apiVersion was null or undefined when calling read.'); } const localVarPath = await this.specUriPath(spec, 'read'); const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.GET); requestContext.setHeaderParam('Accept', 'application/json, */*;q=0.8'); if (pretty !== undefined) { requestContext.setQueryParam('pretty', ObjectSerializer.serialize(pretty, 'string')); } if (exact !== undefined) { requestContext.setQueryParam('exact', ObjectSerializer.serialize(exact, 'boolean')); } if (exportt !== undefined) { requestContext.setQueryParam('export', ObjectSerializer.serialize(exportt, 'boolean')); } return this.requestPromise(requestContext); } /** * List any Kubernetes resources. * @param apiVersion api group and version of the form <apiGroup>/<version> * @param kind Kubernetes resource kind * @param namespace list resources in this namespace * @param pretty If \&#39;true\&#39;, then the output is pretty printed. * @param exact Should the export be exact. Exact export maintains cluster-specific fields like * \&#39;Namespace\&#39;. Deprecated. Planned for removal in 1.18. * @param exportt Should this value be exported. Export strips fields that a user can not * specify. Deprecated. Planned for removal in 1.18. * @param fieldSelector A selector to restrict the list of returned objects by their fields. Defaults to everything. * @param labelSelector A selector to restrict the list of returned objects by their labels. Defaults to everything. * @param limit Number of returned resources. * @param options Optional headers to use in the request. * @return Promise containing the request response and [[KubernetesListObject<KubernetesObject>]]. */ async list(apiVersion, kind, namespace, pretty, exact, exportt, fieldSelector, labelSelector, limit, continueToken, options) { const _config = options || this.configuration; // verify required parameters 'apiVersion', 'kind' is not null or undefined if (apiVersion === null || apiVersion === undefined) { throw new Error('Required parameter apiVersion was null or undefined when calling list.'); } if (kind === null || kind === undefined) { throw new Error('Required parameter kind was null or undefined when calling list.'); } const localVarPath = await this.specUriPath({ apiVersion, kind, metadata: { namespace, }, }, 'list'); const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.GET); requestContext.setHeaderParam('Accept', 'application/json, */*;q=0.8'); if (pretty !== undefined) { requestContext.setQueryParam('pretty', ObjectSerializer.serialize(pretty, 'string')); } if (exact !== undefined) { requestContext.setQueryParam('exact', ObjectSerializer.serialize(exact, 'boolean')); } if (exportt !== undefined) { requestContext.setQueryParam('export', ObjectSerializer.serialize(exportt, 'boolean')); } if (fieldSelector !== undefined) { requestContext.setQueryParam('fieldSelector', ObjectSerializer.serialize(fieldSelector, 'string')); } if (labelSelector !== undefined) { requestContext.setQueryParam('labelSelector', ObjectSerializer.serialize(labelSelector, 'string')); } if (limit !== undefined) { requestContext.setQueryParam('limit', ObjectSerializer.serialize(limit, 'number')); } if (continueToken !== undefined) { requestContext.setQueryParam('continue', ObjectSerializer.serialize(continueToken, 'string')); } return this.requestPromise(requestContext); } /** * Replace any Kubernetes resource. * @param spec Kubernetes resource spec * @param pretty If \&#39;true\&#39;, then the output is pretty printed. * @param dryRun When present, indicates that modifications should not be persisted. An invalid or unrecognized * dryRun directive will result in an error response and no further processing of the request. Valid values * are: - All: all dry run stages will be processed * @param fieldManager fieldManager is a name associated with the actor or entity that is making these changes. The * value must be less than or 128 characters long, and only contain printable characters, as defined by * https://golang.org/pkg/unicode/#IsPrint. * @param options Optional headers to use in the request. * @return Promise containing the request response and [[KubernetesObject]]. */ async replace(spec, pretty, dryRun, fieldManager, options) { const _config = options || this.configuration; // verify required parameter 'spec' is not null or undefined if (spec === null || spec === undefined) { throw new Error('Required parameter spec was null or undefined when calling replace.'); } const localVarPath = await this.specUriPath(spec, 'replace'); const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.PUT); requestContext.setHeaderParam('Accept', 'application/json, */*;q=0.8'); if (pretty !== undefined) { requestContext.setQueryParam('pretty', ObjectSerializer.serialize(pretty, 'string')); } if (dryRun !== undefined) { requestContext.setQueryParam('dryRun', ObjectSerializer.serialize(dryRun, 'string')); } if (fieldManager !== undefined) { requestContext.setQueryParam('fieldManager', ObjectSerializer.serialize(fieldManager, 'string')); } // Body Params const contentType = ObjectSerializer.getPreferredMediaType([]); requestContext.setHeaderParam('Content-Type', contentType); const serializedBody = ObjectSerializer.stringify(ObjectSerializer.serialize(spec, 'any'), contentType); requestContext.setBody(serializedBody); return this.requestPromise(requestContext); } /** Set default namespace from current context, if available. */ setDefaultNamespace(kc) { if (kc.currentContext) { const currentContext = kc.getContextObject(kc.currentContext); if (currentContext && currentContext.namespace) { this.defaultNamespace = currentContext.namespace; } } return this.defaultNamespace; } /** * Use spec information to construct resource URI path. If any required information in not provided, an Error is * thrown. If an `apiVersion` is not provided, 'v1' is used. If a `metadata.namespace` is not provided for a * request that requires one, the context default is used, if available, if not, 'default' is used. * * @param spec Kubernetes resource spec which must define kind and apiVersion properties. * @param action API action, see [[K8sApiAction]]. * @return tail of resource-specific URI */ async specUriPath(spec, action) { if (!spec.kind) { throw new Error('Required spec property kind is not set'); } if (!spec.apiVersion) { spec.apiVersion = 'v1'; } if (!spec.metadata) { spec.metadata = {}; } const resource = await this.resource(spec.apiVersion, spec.kind); if (!resource) { throw new Error(`Unrecognized API version and kind: ${spec.apiVersion} ${spec.kind}`); } if (resource.namespaced && !spec.metadata.namespace && action !== 'list') { spec.metadata.namespace = this.defaultNamespace; } const parts = [this.apiVersionPath(spec.apiVersion)]; if (resource.namespaced && spec.metadata.namespace) { parts.push('namespaces', encodeURIComponent(String(spec.metadata.namespace))); } parts.push(resource.name); if (action !== 'create' && action !== 'list') { if (!spec.metadata.name) { throw new Error('Required spec property name is not set'); } parts.push(encodeURIComponent(String(spec.metadata.name))); } return parts.join('/').toLowerCase(); } /** Return root of API path up to API version. */ apiVersionPath(apiVersion) { const api = apiVersion.includes('/') ? 'apis' : 'api'; return '/' + [api, apiVersion].join('/'); } /** * Get metadata from Kubernetes API for resources described by `kind` and `apiVersion`. If it is unable to find the * resource `kind` under the provided `apiVersion`, `undefined` is returned. * * This method caches responses from the Kubernetes API to use for future requests. If the cache for apiVersion * exists but the kind is not found the request is attempted again. * * @param apiVersion Kubernetes API version, e.g., 'v1' or 'apps/v1'. * @param kind Kubernetes resource kind, e.g., 'Pod' or 'Namespace'. * @return Promise of the resource metadata or `undefined` if the resource is not found. */ async resource(apiVersion, kind, options) { const _config = options || this.configuration; // verify required parameter 'apiVersion' is not null or undefined if (apiVersion === null || apiVersion === undefined) { throw new Error('Required parameter apiVersion was null or undefined when calling resource'); } // verify required parameter 'kind' is not null or undefined if (kind === null || kind === undefined) { throw new Error('Required parameter kind was null or undefined when calling resource'); } if (this.apiVersionResourceCache[apiVersion]) { const resource = this.apiVersionResourceCache[apiVersion].resources.find((r) => r.kind === kind); if (resource) { return resource; } } const localVarPath = this.apiVersionPath(apiVersion); const requestContext = _config.baseServer.makeRequestContext(localVarPath, HttpMethod.GET); requestContext.setHeaderParam('Accept', 'application/json, */*;q=0.8'); try { const getApiResponse = await this.requestPromise(requestContext, 'V1APIResourceList'); this.apiVersionResourceCache[apiVersion] = getApiResponse; return this.apiVersionResourceCache[apiVersion].resources.find((r) => r.kind === kind); } catch (e) { if (e instanceof Error) { e.message = `Failed to fetch resource metadata for ${apiVersion}/${kind}: ${e.message}`; } throw e; } } async getSerializationType(apiVersion, kind) { if (apiVersion === undefined || kind === undefined) { return 'KubernetesObject'; } // Types are defined in src/gen/api/models with the format "<Version><Kind>". // Version and Kind are in PascalCase. const gv = this.groupVersion(apiVersion); const version = gv.version.charAt(0).toUpperCase() + gv.version.slice(1); return `${version}${kind}`; } groupVersion(apiVersion) { const v = apiVersion.split('/'); return v.length === 1 ? { group: 'core', version: apiVersion, } : { group: v[0], version: v[1], }; } async requestPromise(requestContext, type, options) { var _a, _b, _c; const _config = options || this.configuration; // Apply auth methods const authMethod = _config.authMethods.BearerToken; if (authMethod === null || authMethod === void 0 ? void 0 : authMethod.applySecurityAuthentication) { await (authMethod === null || authMethod === void 0 ? void 0 : authMethod.applySecurityAuthentication(requestContext)); } const defaultAuth = ((_a = options === null || options === void 0 ? void 0 : options.authMethods) === null || _a === void 0 ? void 0 : _a.default) || ((_c = (_b = this.configuration) === null || _b === void 0 ? void 0 : _b.authMethods) === null || _c === void 0 ? void 0 : _c.default); if (defaultAuth === null || defaultAuth === void 0 ? void 0 : defaultAuth.applySecurityAuthentication) { await (defaultAuth === null || defaultAuth === void 0 ? void 0 : defaultAuth.applySecurityAuthentication(requestContext)); } // build promise chain let middlewarePreObservable = from(Promise.resolve(requestContext)); for (const middleware of this.configuration.middleware) { middlewarePreObservable = middlewarePreObservable.pipe(mergeMap((ctx) => middleware.pre(ctx))); } return middlewarePreObservable .pipe(mergeMap((ctx) => this.configuration.httpApi.send(ctx))) .pipe(mergeMap((response) => { let middlewarePostObservable = of(response); for (const middleware of this.configuration.middleware) { middlewarePostObservable = middlewarePostObservable.pipe(mergeMap((rsp) => middleware.post(rsp))); } return middlewarePostObservable.pipe((rsp) => this.processResponse(rsp, type)); })) .toPromise(); } async processResponse(response, type) { const contentType = ObjectSerializer.normalizeMediaType(response.headers['content-type']); if (response.httpStatusCode >= 200 && response.httpStatusCode <= 299) { const data = ObjectSerializer.parse(await response.body.text(), contentType); if (type === undefined) { type = await this.getSerializationType(data.apiVersion, data.kind); } if (!type) { throw new Error('Unable to determine type of Kubernetes type of response.'); } return ObjectSerializer.deserialize(data, type); } throw new ApiException(response.httpStatusCode, 'Unsuccessful HTTP Request', await response.getBodyAsAny(), response.headers); } } //# sourceMappingURL=object.js.map