Move lookupApi into apiManager (#3540)

This commit is contained in:
Sebastian Malton authored and GitHub committed 2021-08-04 11:36:13 -04:00
1 parent 574aea40b4
commit ee158e33df
16 files changed
+70 -90

No files matched your search

+41 -1
View File
@@ -23,8 +23,9 @@ import type { KubeObjectStore } from "../kube-object.store";
import { action, observable, makeObservable } from "mobx";
import { autoBind, iter } from "../utils";
import { KubeApi, parseKubeApi } from "./kube-api";
import type { KubeApi } from "./kube-api";
import type { KubeObject } from "./kube-object";
import { IKubeObjectRef, parseKubeApi, createKubeApiURL } from "./kube-api-parse";
export class ApiManager {
private apis = observable.map<string, KubeApi<KubeObject>>();
@@ -91,6 +92,45 @@ export class ApiManager {
getStore<S extends KubeObjectStore<KubeObject>>(api: string | KubeApi<KubeObject>): S | undefined {
return this.stores.get(this.resolveApi(api)?.apiBase) as S;
}
lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string {
const {
kind, apiVersion, name,
namespace = parentObject.getNs()
} = ref;
if (!kind) return "";
// search in registered apis by 'kind' & 'apiVersion'
const api = this.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
if (api) {
return api.getUrl({ namespace, name });
}
// lookup api by generated resource link
const apiPrefixes = ["/apis", "/api"];
const resource = kind.endsWith("s") ? `${kind.toLowerCase()}es` : `${kind.toLowerCase()}s`;
for (const apiPrefix of apiPrefixes) {
const apiLink = createKubeApiURL({ apiPrefix, apiVersion, name, namespace, resource });
if (this.getApi(apiLink)) {
return apiLink;
}
}
// resolve by kind only (hpa's might use refs to older versions of resources for example)
const apiByKind = this.getApi(api => api.kind === kind);
if (apiByKind) {
return apiByKind.getUrl({ name, namespace });
}
// otherwise generate link with default prefix
// resource still might exists in k8s, but api is not registered in the app
return createKubeApiURL({ apiVersion, name, namespace, resource });
}
}
export const apiManager = new ApiManager();
@@ -20,35 +20,21 @@
*/
import jsYaml from "js-yaml";
import { KubeObject } from "../kube-object";
import type { KubeJsonApiData } from "../kube-json-api";
import { apiBase } from "../index";
import { apiManager } from "../api-manager";
export const resourceApplierApi = {
annotations: [
"kubectl.kubernetes.io/last-applied-configuration"
],
async update<K extends KubeObject>(resource: object | string): Promise<K | null> {
async update(resource: object | string): Promise<KubeJsonApiData | null> {
if (typeof resource === "string") {
resource = jsYaml.safeLoad(resource);
}
return apiBase
.post<KubeJsonApiData[]>("/stack", { data: resource })
.then(data => {
const items = data.map(obj => {
const api = apiManager.getApiByKind(obj.kind, obj.apiVersion);
const [data = null] = await apiBase.post<KubeJsonApiData[]>("/stack", { data: resource });
if (api) {
return new api.objectConstructor(obj);
} else {
return new KubeObject(obj);
}
});
return items[0] as K ?? null;
});
return data;
}
};
-41
View File
@@ -21,9 +21,7 @@
// Parse kube-api path and get api-version, group, etc.
import type { KubeObject } from "./kube-object";
import { splitArray } from "../../common/utils";
import { apiManager } from "./api-manager";
import { isDebugging } from "../../common/vars";
import logger from "../../main/logger";
import { inspect } from "util";
@@ -159,42 +157,3 @@ export function createKubeApiURL(ref: IKubeApiLinkRef): string {
.filter(v => v)
.join("/");
}
export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string {
const {
kind, apiVersion, name,
namespace = parentObject.getNs()
} = ref;
if (!kind) return "";
// search in registered apis by 'kind' & 'apiVersion'
const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
if (api) {
return api.getUrl({ namespace, name });
}
// lookup api by generated resource link
const apiPrefixes = ["/apis", "/api"];
const resource = kind.endsWith("s") ? `${kind.toLowerCase()}es` : `${kind.toLowerCase()}s`;
for (const apiPrefix of apiPrefixes) {
const apiLink = createKubeApiURL({ apiPrefix, apiVersion, name, namespace, resource });
if (apiManager.getApi(apiLink)) {
return apiLink;
}
}
// resolve by kind only (hpa's might use refs to older versions of resources for example)
const apiByKind = apiManager.getApi(api => api.kind === kind);
if (apiByKind) {
return apiByKind.getUrl({ name, namespace });
}
// otherwise generate link with default prefix
// resource still might exists in k8s, but api is not registered in the app
return createKubeApiURL({ apiVersion, name, namespace, resource });
}
-7
View File
@@ -56,11 +56,6 @@ export interface IKubeApiOptions<T extends KubeObject> {
checkPreferredVersion?: boolean;
}
export interface KubeApiListOptions {
namespace?: string;
reqInit?: RequestInit;
}
export interface IKubeApiQueryParams {
watch?: boolean | number;
resourceVersion?: string;
@@ -506,5 +501,3 @@ export class KubeApi<T extends KubeObject> {
}
}
}
export * from "./kube-api-parse";
+2 -2
View File
@@ -287,14 +287,14 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
}
// use unified resource-applier api for updating all k8s objects
async update<K extends KubeObject>(data: Partial<K>): Promise<K> {
async update(data: Partial<this>): Promise<KubeJsonApiData | null> {
for (const field of KubeObject.nonEditableFields) {
if (!_.isEqual(_.get(this, field), _.get(data, field))) {
throw new Error(`Failed to update Kube Object: ${field} has been modified`);
}
}
return resourceApplierApi.update<K>({
return resourceApplierApi.update({
...this.toPlainObject(),
...data,
});