1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix not being able to remove role bindings via the UI (#4394)

This commit is contained in:
Sebastian Malton 2021-11-30 09:06:54 -05:00
parent 9518cbac78
commit d961a9ecbe
3 changed files with 60 additions and 25 deletions

View File

@ -133,7 +133,10 @@ describe("KubeApi", () => {
checkPreferredVersion: true,
});
await kubeApi.get();
await kubeApi.get({
name: "foo",
namespace: "default",
});
expect(kubeApi.apiPrefix).toEqual("/apis");
expect(kubeApi.apiGroup).toEqual("networking.k8s.io");
});
@ -173,7 +176,10 @@ describe("KubeApi", () => {
checkPreferredVersion: true,
});
await kubeApi.get();
await kubeApi.get({
name: "foo",
namespace: "default",
});
expect(kubeApi.apiPrefix).toEqual("/apis");
expect(kubeApi.apiGroup).toEqual("extensions");
});
@ -312,7 +318,7 @@ describe("KubeApi", () => {
(fetch as any).mockResponse(async () => {
return {};
});
api.watch({ namespace: "kube-system" });
expect(spy).toHaveBeenCalledWith("/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=", expect.anything(), expect.anything());
});
@ -323,7 +329,7 @@ describe("KubeApi", () => {
(fetch as any).mockResponse(async () => {
return {};
});
api.watch({ namespace: "kube-system", timeout: 60 });
expect(spy).toHaveBeenCalledWith("/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=", { query: { timeoutSeconds: 60 }}, expect.anything());
});

View File

@ -21,7 +21,6 @@
// Base class for building all kubernetes apis
import merge from "lodash/merge";
import { isFunction } from "lodash";
import { stringify } from "querystring";
import { apiKubePrefix, isDevelopment } from "../../common/vars";
@ -221,6 +220,29 @@ const patchTypeHeaders: Record<KubeApiPatchType, string> = {
"strategic": "application/strategic-merge-patch+json",
};
export interface ResourceDescriptor {
/**
* The name of the kubernetes resource
*/
name: string;
/**
* The namespace that the resource lives in (if the resource is namespaced)
*
* Note: if not provided and the resource kind is namespaced, then this defaults to `"default"`
*/
namespace?: string;
}
export interface DeleteResourceDescriptor extends ResourceDescriptor {
/**
* This determinines how child resources should be handled by kubernetes
*
* @default "Background"
*/
propagationPolicy?: PropagationPolicy;
}
export class KubeApi<T extends KubeObject> {
readonly kind: string;
readonly apiBase: string;
@ -355,12 +377,12 @@ export class KubeApi<T extends KubeObject> {
return this.list(params, { limit: 1 });
}
getUrl({ name = "", namespace = "" } = {}, query?: Partial<IKubeApiQueryParams>) {
getUrl({ name, namespace = "default" }: Partial<ResourceDescriptor> = {}, query?: Partial<IKubeApiQueryParams>) {
const resourcePath = createKubeApiURL({
apiPrefix: this.apiPrefix,
apiVersion: this.apiVersionWithGroup,
resource: this.apiResource,
namespace: this.isNamespaced ? namespace : undefined,
namespace: this.isNamespaced ? namespace ?? "default" : undefined,
name,
});
@ -438,10 +460,10 @@ export class KubeApi<T extends KubeObject> {
throw new Error(`GET multiple request to ${url} returned not an array: ${JSON.stringify(parsed)}`);
}
async get({ name = "", namespace = "default" } = {}, query?: IKubeApiQueryParams): Promise<T | null> {
async get(desc: ResourceDescriptor, query?: IKubeApiQueryParams): Promise<T | null> {
await this.checkPreferredVersion();
const url = this.getUrl({ namespace, name });
const url = this.getUrl(desc);
const res = await this.request.get(url, { query });
const parsed = this.parseResponse(res);
@ -452,19 +474,18 @@ export class KubeApi<T extends KubeObject> {
return parsed;
}
async create({ name = "", namespace = "default" } = {}, data?: Partial<T>): Promise<T | null> {
async create({ name, namespace }: Partial<ResourceDescriptor>, data?: Partial<T>): Promise<T | null> {
await this.checkPreferredVersion();
const apiUrl = this.getUrl({ namespace });
const res = await this.request.post(apiUrl, {
data: merge({
kind: this.kind,
apiVersion: this.apiVersionWithGroup,
data: {
...data,
metadata: {
name,
namespace,
},
}, data),
},
});
const parsed = this.parseResponse(res);
@ -475,11 +496,19 @@ export class KubeApi<T extends KubeObject> {
return parsed;
}
async update({ name = "", namespace = "default" } = {}, data?: Partial<T>): Promise<T | null> {
async update({ name, namespace }: ResourceDescriptor, data: Partial<T>): Promise<T | null> {
await this.checkPreferredVersion();
const apiUrl = this.getUrl({ namespace, name });
const res = await this.request.put(apiUrl, { data });
const res = await this.request.put(apiUrl, {
data: {
...data,
metadata: {
name,
namespace,
},
},
});
const parsed = this.parseResponse(res);
if (Array.isArray(parsed)) {
@ -489,9 +518,9 @@ export class KubeApi<T extends KubeObject> {
return parsed;
}
async patch({ name = "", namespace = "default" } = {}, data?: Partial<T> | Patch, strategy: KubeApiPatchType = "strategic"): Promise<T | null> {
async patch(desc: ResourceDescriptor, data?: Partial<T> | Patch, strategy: KubeApiPatchType = "strategic"): Promise<T | null> {
await this.checkPreferredVersion();
const apiUrl = this.getUrl({ namespace, name });
const apiUrl = this.getUrl(desc);
const res = await this.request.patch(apiUrl, { data }, {
headers: {
@ -507,16 +536,15 @@ export class KubeApi<T extends KubeObject> {
return parsed;
}
async delete({ name = "", namespace = "default", propagationPolicy = "Background" }: { name: string, namespace?: string, propagationPolicy?: PropagationPolicy }) {
async delete({ propagationPolicy = "Background", ...desc }: DeleteResourceDescriptor) {
await this.checkPreferredVersion();
const apiUrl = this.getUrl({ namespace, name });
const reqInit = {
const apiUrl = this.getUrl(desc);
return this.request.del(apiUrl, {
query: {
propagationPolicy,
},
};
return this.request.del(apiUrl, reqInit);
});
}
getWatchUrl(namespace = "", query: IKubeApiQueryParams = {}) {

View File

@ -363,7 +363,8 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
return this.postUpdate(
await this.api.update(
{
name: item.getName(), namespace: item.getNs(),
name: item.getName(),
namespace: item.getNs(),
},
data,
),