mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Replace resource applier with injectables
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
35f3c08279
commit
1809f98046
@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import yaml from "js-yaml";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
import { apiBase } from "../index";
|
||||
import type { Patch } from "rfc6902";
|
||||
|
||||
export const annotations = [
|
||||
"kubectl.kubernetes.io/last-applied-configuration",
|
||||
];
|
||||
|
||||
export async function update(resource: object | string): Promise<KubeJsonApiData> {
|
||||
if (typeof resource === "string") {
|
||||
const parsed = yaml.load(resource);
|
||||
|
||||
if (!parsed || typeof parsed !== "object") {
|
||||
throw new Error("Cannot update resource to string or number");
|
||||
}
|
||||
|
||||
resource = parsed;
|
||||
}
|
||||
|
||||
return apiBase.post<KubeJsonApiData>("/stack", { data: resource });
|
||||
}
|
||||
|
||||
export async function patch(name: string, kind: string, ns: string | undefined, patch: Patch): Promise<KubeJsonApiData> {
|
||||
return apiBase.patch<KubeJsonApiData>("/stack", {
|
||||
data: {
|
||||
name,
|
||||
kind,
|
||||
ns,
|
||||
patch,
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { Patch } from "rfc6902";
|
||||
import { apiBaseInjectionToken } from "../../api-base";
|
||||
import type { KubeJsonApiData } from "../../kube-json-api";
|
||||
|
||||
export type RequestKubeObjectPatch = (name: string, kind: string, ns: string | undefined, patch: Patch) => Promise<KubeJsonApiData>;
|
||||
|
||||
const requestKubeObjectPatchInjectable = getInjectable({
|
||||
id: "request-kube-object-patch",
|
||||
instantiate: (di): RequestKubeObjectPatch => {
|
||||
const apiBase = di.inject(apiBaseInjectionToken);
|
||||
|
||||
return (name, kind, ns, patch) => (
|
||||
apiBase.patch("/stack", {
|
||||
data: {
|
||||
name,
|
||||
kind,
|
||||
ns,
|
||||
patch,
|
||||
},
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export default requestKubeObjectPatchInjectable;
|
||||
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { apiBaseInjectionToken } from "../../api-base";
|
||||
import type { KubeJsonApiData } from "../../kube-json-api";
|
||||
|
||||
export type RequestKubeObjectCreation = (resourceDescriptor: string) => Promise<KubeJsonApiData>;
|
||||
|
||||
const requestKubeObjectCreationInjectable = getInjectable({
|
||||
id: "request-kube-object-creation",
|
||||
instantiate: (di): RequestKubeObjectCreation => {
|
||||
const apiBase = di.inject(apiBaseInjectionToken);
|
||||
|
||||
return (data) => apiBase.post("/stack", { data });
|
||||
},
|
||||
});
|
||||
|
||||
export default requestKubeObjectCreationInjectable;
|
||||
@ -9,11 +9,15 @@ import moment from "moment";
|
||||
import type { KubeJsonApiData, KubeJsonApiDataList, KubeJsonApiListMetadata } from "./kube-json-api";
|
||||
import { autoBind, formatDuration, hasOptionalTypedProperty, hasTypedProperty, isObject, isString, isNumber, bindPredicate, isTypedArray, isRecord, json } from "../utils";
|
||||
import type { ItemObject } from "../item.store";
|
||||
import { apiKube } from "./index";
|
||||
import * as resourceApplierApi from "./endpoints/resource-applier.api";
|
||||
import type { Patch } from "rfc6902";
|
||||
import assert from "assert";
|
||||
import type { JsonObject } from "type-fest";
|
||||
import { asLegacyGlobalFunctionForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
|
||||
import requestKubeObjectPatchInjectable from "./endpoints/resource-applier.api/patch.injectable";
|
||||
import { asLegacyGlobalForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import { apiKubeInjectionToken } from "./api-kube";
|
||||
import requestKubeObjectCreationInjectable from "./endpoints/resource-applier.api/update.injectable";
|
||||
import { dump } from "js-yaml";
|
||||
|
||||
export type KubeJsonApiDataFor<K> = K extends KubeObject<infer Metadata, infer Status, infer Spec>
|
||||
? KubeJsonApiData<Metadata, Status, Spec>
|
||||
@ -375,6 +379,12 @@ export type ScopedNamespace<Namespaced extends KubeObjectScope> = (
|
||||
: string | undefined
|
||||
);
|
||||
|
||||
const resourceApplierAnnotationsForFiltering = [
|
||||
"kubectl.kubernetes.io/last-applied-configuration",
|
||||
];
|
||||
|
||||
const filterOutResourceApplierAnnotations = (label: string) => !resourceApplierAnnotationsForFiltering.some(key => label.startsWith(key));
|
||||
|
||||
export class KubeObject<
|
||||
Metadata extends KubeObjectMetadata<KubeObjectScope> = KubeObjectMetadata<KubeObjectScope>,
|
||||
Status = unknown,
|
||||
@ -588,11 +598,11 @@ export class KubeObject<
|
||||
getAnnotations(filter = false): string[] {
|
||||
const labels = KubeObject.stringifyLabels(this.metadata.annotations);
|
||||
|
||||
return filter ? labels.filter(label => {
|
||||
const skip = resourceApplierApi.annotations.some(key => label.startsWith(key));
|
||||
if (!filter) {
|
||||
return labels;
|
||||
}
|
||||
|
||||
return !skip;
|
||||
}) : labels;
|
||||
return labels.filter(filterOutResourceApplierAnnotations);
|
||||
}
|
||||
|
||||
getOwnerRefs() {
|
||||
@ -634,7 +644,9 @@ export class KubeObject<
|
||||
}
|
||||
}
|
||||
|
||||
return resourceApplierApi.patch(this.getName(), this.kind, this.getNs(), patch);
|
||||
const requestKubeObjectPatch = asLegacyGlobalFunctionForExtensionApi(requestKubeObjectPatchInjectable);
|
||||
|
||||
return requestKubeObjectPatch(this.getName(), this.kind, this.getNs(), patch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -647,11 +659,13 @@ export class KubeObject<
|
||||
* @deprecated use KubeApi.update instead
|
||||
*/
|
||||
async update(data: Partial<this>): Promise<KubeJsonApiData | null> {
|
||||
// use unified resource-applier api for updating all k8s objects
|
||||
return resourceApplierApi.update({
|
||||
const requestKubeObjectCreation = asLegacyGlobalFunctionForExtensionApi(requestKubeObjectCreationInjectable);
|
||||
const descriptor = dump({
|
||||
...this.toPlainObject(),
|
||||
...data,
|
||||
});
|
||||
|
||||
return requestKubeObjectCreation(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -660,6 +674,8 @@ export class KubeObject<
|
||||
delete(params?: object) {
|
||||
assert(this.selfLink, "selfLink must be present to delete self");
|
||||
|
||||
const apiKube = asLegacyGlobalForExtensionApi(apiKubeInjectionToken);
|
||||
|
||||
return apiKube.del(this.selfLink, params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,11 +62,10 @@ export class ResourceApplier {
|
||||
}
|
||||
}
|
||||
|
||||
async apply(resource: KubernetesObject | any): Promise<string> {
|
||||
resource = this.sanitizeObject(resource);
|
||||
async create(resource: string): Promise<string> {
|
||||
appEventBus.emit({ name: "resource", action: "apply" });
|
||||
|
||||
return this.kubectlApply(yaml.dump(resource));
|
||||
return this.kubectlApply(yaml.dump(this.sanitizeObject(resource)));
|
||||
}
|
||||
|
||||
protected async kubectlApply(content: string): Promise<string> {
|
||||
@ -154,11 +153,7 @@ export class ResourceApplier {
|
||||
|
||||
delete res.status;
|
||||
delete res.metadata?.resourceVersion;
|
||||
const annotations = res.metadata?.annotations;
|
||||
|
||||
if (annotations) {
|
||||
delete annotations["kubectl.kubernetes.io/last-applied-configuration"];
|
||||
}
|
||||
delete res.metadata?.annotations["kubectl.kubernetes.io/last-applied-configuration"];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -5,17 +5,19 @@
|
||||
import { getRouteInjectable } from "../../router/router.injectable";
|
||||
import { apiPrefix } from "../../../common/vars";
|
||||
import { ResourceApplier } from "../../resource-applier";
|
||||
import { clusterRoute } from "../../router/route";
|
||||
import { payloadValidatedClusterRoute } from "../../router/route";
|
||||
import Joi from "joi";
|
||||
|
||||
const applyResourceRouteInjectable = getRouteInjectable({
|
||||
const createResourceRouteInjectable = getRouteInjectable({
|
||||
id: "apply-resource-route",
|
||||
|
||||
instantiate: () => clusterRoute({
|
||||
instantiate: () => payloadValidatedClusterRoute({
|
||||
method: "post",
|
||||
path: `${apiPrefix}/stack`,
|
||||
payloadValidator: Joi.string(),
|
||||
})(async ({ cluster, payload }) => ({
|
||||
response: await new ResourceApplier(cluster).apply(payload),
|
||||
response: await new ResourceApplier(cluster).create(payload),
|
||||
})),
|
||||
});
|
||||
|
||||
export default applyResourceRouteInjectable;
|
||||
export default createResourceRouteInjectable;
|
||||
|
||||
@ -6,14 +6,13 @@
|
||||
import React from "react";
|
||||
import type { SelectOption } from "../../select";
|
||||
import { Select } from "../../select";
|
||||
import yaml from "js-yaml";
|
||||
import yaml, { dump } from "js-yaml";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { makeObservable, observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { CreateResourceTabStore } from "./store";
|
||||
import { EditorPanel } from "../editor-panel";
|
||||
import { InfoPanel } from "../info-panel";
|
||||
import * as resourceApplierApi from "../../../../common/k8s-api/endpoints/resource-applier.api";
|
||||
import { Notifications } from "../../notifications";
|
||||
import logger from "../../../../common/logger";
|
||||
import type { ApiManager } from "../../../../common/k8s-api/api-manager";
|
||||
@ -28,6 +27,8 @@ import type { GetDetailsUrl } from "../../kube-detail-params/get-details-url.inj
|
||||
import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import getDetailsUrlInjectable from "../../kube-detail-params/get-details-url.injectable";
|
||||
import navigateInjectable from "../../../navigation/navigate.injectable";
|
||||
import type { RequestKubeObjectCreation } from "../../../../common/k8s-api/endpoints/resource-applier.api/update.injectable";
|
||||
import requestKubeObjectCreationInjectable from "../../../../common/k8s-api/endpoints/resource-applier.api/update.injectable";
|
||||
|
||||
export interface CreateResourceProps {
|
||||
tabId: string;
|
||||
@ -39,6 +40,7 @@ interface Dependencies {
|
||||
apiManager: ApiManager;
|
||||
navigate: Navigate;
|
||||
getDetailsUrl: GetDetailsUrl;
|
||||
requestKubeObjectCreation: RequestKubeObjectCreation;
|
||||
}
|
||||
|
||||
@observer
|
||||
@ -68,7 +70,7 @@ class NonInjectedCreateResource extends React.Component<CreateResourceProps & De
|
||||
};
|
||||
|
||||
create = async (): Promise<void> => {
|
||||
const { apiManager, getDetailsUrl, navigate } = this.props;
|
||||
const { apiManager, getDetailsUrl, navigate, requestKubeObjectCreation } = this.props;
|
||||
|
||||
if (this.error || !this.data?.trim()) {
|
||||
// do not save when field is empty or there is an error
|
||||
@ -84,7 +86,7 @@ class NonInjectedCreateResource extends React.Component<CreateResourceProps & De
|
||||
|
||||
const creatingResources = resources.map(async (resource) => {
|
||||
try {
|
||||
const data = await resourceApplierApi.update(resource);
|
||||
const data = await requestKubeObjectCreation(dump(resource));
|
||||
const { kind, apiVersion, metadata: { name, namespace }} = data;
|
||||
|
||||
const showDetails = () => {
|
||||
@ -168,5 +170,6 @@ export const CreateResource = withInjectables<Dependencies, CreateResourceProps>
|
||||
apiManager: di.inject(apiManagerInjectable),
|
||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||
navigate: di.inject(navigateInjectable),
|
||||
requestKubeObjectCreation: di.inject(requestKubeObjectCreationInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user