mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
chore: Change refactoring of implementation to maintain behaviour
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
8395c262ad
commit
dcc5495312
@ -9,33 +9,35 @@ import apiKubeInjectable from "../../../renderer/k8s/api-kube.injectable";
|
|||||||
import type { StatefulSetApi } from "../endpoints";
|
import type { StatefulSetApi } from "../endpoints";
|
||||||
import statefulSetApiInjectable from "../endpoints/stateful-set.api.injectable";
|
import statefulSetApiInjectable from "../endpoints/stateful-set.api.injectable";
|
||||||
import type { KubeJsonApi } from "../kube-json-api";
|
import type { KubeJsonApi } from "../kube-json-api";
|
||||||
|
import type { AsyncFnMock } from "@async-fn/jest";
|
||||||
|
import asyncFn from "@async-fn/jest";
|
||||||
|
import { flushPromises } from "@k8slens/test-utils";
|
||||||
|
|
||||||
describe("StatefulSetApi", () => {
|
describe("StatefulSetApi", () => {
|
||||||
let statefulSetApi: StatefulSetApi;
|
let statefulSetApi: StatefulSetApi;
|
||||||
let kubeJsonApi: jest.Mocked<KubeJsonApi>;
|
let kubeJsonApiPatchMock: AsyncFnMock<KubeJsonApi["patch"]>;
|
||||||
|
let kubeJsonApiGetMock: AsyncFnMock<KubeJsonApi["get"]>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const di = getDiForUnitTesting();
|
const di = getDiForUnitTesting();
|
||||||
|
|
||||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||||
kubeJsonApi = {
|
kubeJsonApiPatchMock = asyncFn();
|
||||||
getResponse: jest.fn(),
|
kubeJsonApiGetMock = asyncFn();
|
||||||
get: jest.fn(),
|
di.override(apiKubeInjectable, () => ({
|
||||||
post: jest.fn(),
|
get: kubeJsonApiGetMock,
|
||||||
put: jest.fn(),
|
patch: kubeJsonApiPatchMock,
|
||||||
patch: jest.fn(),
|
} as Partial<KubeJsonApi> as KubeJsonApi));
|
||||||
del: jest.fn(),
|
|
||||||
} as never;
|
|
||||||
di.override(apiKubeInjectable, () => kubeJsonApi);
|
|
||||||
|
|
||||||
statefulSetApi = di.inject(statefulSetApiInjectable);
|
statefulSetApi = di.inject(statefulSetApiInjectable);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("scale", () => {
|
describe("scale", () => {
|
||||||
it("requests Kubernetes API with PATCH verb and correct amount of replicas", () => {
|
it("requests Kubernetes API with PATCH verb and correct amount of replicas", async () => {
|
||||||
statefulSetApi.scale({ namespace: "default", name: "statefulset-1" }, 5);
|
const req = statefulSetApi.scale({ namespace: "default", name: "statefulset-1" }, 5);
|
||||||
|
|
||||||
expect(kubeJsonApi.patch).toHaveBeenCalledWith("/apis/apps/v1/namespaces/default/statefulsets/statefulset-1/scale", {
|
await flushPromises();
|
||||||
|
expect(kubeJsonApiPatchMock).toHaveBeenCalledWith("/apis/apps/v1/namespaces/default/statefulsets/statefulset-1/scale", {
|
||||||
data: {
|
data: {
|
||||||
spec: {
|
spec: {
|
||||||
replicas: 5,
|
replicas: 5,
|
||||||
@ -47,6 +49,19 @@ describe("StatefulSetApi", () => {
|
|||||||
"content-type": "application/merge-patch+json",
|
"content-type": "application/merge-patch+json",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await kubeJsonApiPatchMock.resolve({});
|
||||||
|
await req;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("requests Kubernetes API with GET verb and correct sub-resource", async () => {
|
||||||
|
const req = statefulSetApi.getReplicas({ namespace: "default", name: "statefulset-1" });
|
||||||
|
|
||||||
|
await flushPromises();
|
||||||
|
expect(kubeJsonApiGetMock).toHaveBeenCalledWith("/apis/apps/v1/namespaces/default/statefulsets/statefulset-1/scale");
|
||||||
|
await kubeJsonApiGetMock.resolve({ status: { replicas: 10 }});
|
||||||
|
|
||||||
|
expect(await req).toBe(10);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import moment from "moment";
|
|||||||
import type { DerivedKubeApiOptions, KubeApiDependencies, NamespacedResourceDescriptor } from "../kube-api";
|
import type { DerivedKubeApiOptions, KubeApiDependencies, NamespacedResourceDescriptor } from "../kube-api";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { Deployment } from "@k8slens/kube-object";
|
import { Deployment } from "@k8slens/kube-object";
|
||||||
import { hasTypedProperty, isNumber, isObject } from "@k8slens/utilities";
|
|
||||||
|
|
||||||
export class DeploymentApi extends KubeApi<Deployment> {
|
export class DeploymentApi extends KubeApi<Deployment> {
|
||||||
constructor(deps: KubeApiDependencies, opts?: DerivedKubeApiOptions) {
|
constructor(deps: KubeApiDependencies, opts?: DerivedKubeApiOptions) {
|
||||||
@ -18,33 +17,14 @@ export class DeploymentApi extends KubeApi<Deployment> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getScaleApiUrl(params: NamespacedResourceDescriptor) {
|
|
||||||
return `${this.formatUrlForNotListing(params)}/scale`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getReplicas(params: NamespacedResourceDescriptor): Promise<number> {
|
async getReplicas(params: NamespacedResourceDescriptor): Promise<number> {
|
||||||
const { status } = await this.request.get(this.getScaleApiUrl(params));
|
const { status } = await this.getResourceScale(params);
|
||||||
|
|
||||||
if (isObject(status) && hasTypedProperty(status, "replicas", isNumber)) {
|
|
||||||
return status.replicas;
|
return status.replicas;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
scale(params: NamespacedResourceDescriptor, replicas: number) {
|
scale(params: NamespacedResourceDescriptor, replicas: number) {
|
||||||
return this.request.patch(this.getScaleApiUrl(params), {
|
return this.scaleResource(params, { spec: { replicas }});
|
||||||
data: {
|
|
||||||
spec: {
|
|
||||||
replicas,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"content-type": "application/merge-patch+json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
restart(params: NamespacedResourceDescriptor) {
|
restart(params: NamespacedResourceDescriptor) {
|
||||||
|
|||||||
@ -15,24 +15,13 @@ export class ReplicaSetApi extends KubeApi<ReplicaSet> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getScaleApiUrl(params: NamespacedResourceDescriptor) {
|
|
||||||
return `${this.formatUrlForNotListing(params)}/scale`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getReplicas(params: NamespacedResourceDescriptor): Promise<number> {
|
async getReplicas(params: NamespacedResourceDescriptor): Promise<number> {
|
||||||
const { status } = await this.request.get(this.getScaleApiUrl(params));
|
const { status } = await this.getResourceScale(params);
|
||||||
|
|
||||||
return (status as { replicas: number })?.replicas;
|
return status.replicas;
|
||||||
}
|
}
|
||||||
|
|
||||||
scale(params: NamespacedResourceDescriptor, replicas: number) {
|
scale(params: NamespacedResourceDescriptor, replicas: number) {
|
||||||
return this.request.put(this.getScaleApiUrl(params), {
|
return this.scaleResource(params, { spec: { replicas }});
|
||||||
data: {
|
|
||||||
metadata: params,
|
|
||||||
spec: {
|
|
||||||
replicas,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,17 +25,6 @@ export class ReplicationControllerApi extends KubeApi<ReplicationController> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scale(params: NamespacedResourceDescriptor, replicas: number): Promise<Scale> {
|
scale(params: NamespacedResourceDescriptor, replicas: number): Promise<Scale> {
|
||||||
return this.request.patch(this.getScaleApiUrl(params), {
|
return this.scaleResource(params, { spec: { replicas }});
|
||||||
data: {
|
|
||||||
metadata: params,
|
|
||||||
spec: {
|
|
||||||
replicas,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
headers: {
|
|
||||||
"content-type": "application/strategic-merge-patch+json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,23 +17,14 @@ export class StatefulSetApi extends KubeApi<StatefulSet> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getScaleApiUrl(params: NamespacedResourceDescriptor) {
|
|
||||||
return `${this.formatUrlForNotListing(params)}/scale`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getReplicas(params: NamespacedResourceDescriptor): Promise<number> {
|
async getReplicas(params: NamespacedResourceDescriptor): Promise<number> {
|
||||||
const apiUrl = this.getScaleApiUrl(params);
|
const { status } = await this.getResourceScale(params);
|
||||||
const { status = 0 } = await this.request.get(apiUrl) as { status?: number };
|
|
||||||
|
|
||||||
return status;
|
return status.replicas;
|
||||||
}
|
}
|
||||||
|
|
||||||
scale(params: NamespacedResourceDescriptor, replicas: number) {
|
scale(params: NamespacedResourceDescriptor, replicas: number) {
|
||||||
return this.patch(params, {
|
return this.scaleResource(params, { spec: { replicas }});
|
||||||
spec: {
|
|
||||||
replicas,
|
|
||||||
},
|
|
||||||
}, "merge");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
restart(params: NamespacedResourceDescriptor) {
|
restart(params: NamespacedResourceDescriptor) {
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
import { merge } from "lodash";
|
import { merge } from "lodash";
|
||||||
import { stringify } from "querystring";
|
import { stringify } from "querystring";
|
||||||
import { createKubeApiURL, parseKubeApi } from "./kube-api-parse";
|
import { createKubeApiURL, parseKubeApi } from "./kube-api-parse";
|
||||||
import type { KubeObjectConstructor, KubeJsonApiDataFor, KubeObjectMetadata, KubeJsonApiData, KubeObject, KubeObjectScope } from "@k8slens/kube-object";
|
import type { KubeObjectConstructor, KubeJsonApiDataFor, KubeObjectMetadata, KubeJsonApiData, KubeObject, KubeObjectScope, Scale } from "@k8slens/kube-object";
|
||||||
import { isJsonApiData, isJsonApiDataList, isPartialJsonApiData, KubeStatus, isKubeStatusData } from "@k8slens/kube-object";
|
import { isJsonApiData, isJsonApiDataList, isPartialJsonApiData, KubeStatus, isKubeStatusData } from "@k8slens/kube-object";
|
||||||
import byline from "byline";
|
import byline from "byline";
|
||||||
import type { IKubeWatchEvent } from "./kube-watch-event";
|
import type { IKubeWatchEvent } from "./kube-watch-event";
|
||||||
@ -22,6 +22,7 @@ import type { PartialDeep } from "type-fest";
|
|||||||
import type { Logger } from "../logger";
|
import type { Logger } from "../logger";
|
||||||
import { matches } from "lodash/fp";
|
import { matches } from "lodash/fp";
|
||||||
import { makeObservable, observable } from "mobx";
|
import { makeObservable, observable } from "mobx";
|
||||||
|
import type { ScaleCreateOptions } from "@k8slens/kube-object/src/types/scale";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The options used for creating a `KubeApi`
|
* The options used for creating a `KubeApi`
|
||||||
@ -213,6 +214,10 @@ export interface ResourceDescriptor {
|
|||||||
namespace?: string;
|
namespace?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SubResourceDescriptor {
|
||||||
|
subResource: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type SpecificResourceDescriptor<Scope extends KubeObjectScope> = {
|
export type SpecificResourceDescriptor<Scope extends KubeObjectScope> = {
|
||||||
/**
|
/**
|
||||||
* The name of the kubernetes resource
|
* The name of the kubernetes resource
|
||||||
@ -592,6 +597,37 @@ export class KubeApi<
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal method for requesting the `/scale` sub-resource if it exists
|
||||||
|
*/
|
||||||
|
protected async getResourceScale(desc: ResourceDescriptor): Promise<Scale> {
|
||||||
|
await this.checkPreferredVersion();
|
||||||
|
const apiUrl = this.formatUrlForNotListing(desc);
|
||||||
|
|
||||||
|
const res = await this.request.get(`${apiUrl}/scale`);
|
||||||
|
|
||||||
|
return res as Scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal method for requesting the `/scale` sub-resource if it exists
|
||||||
|
*/
|
||||||
|
protected async scaleResource(desc: ResourceDescriptor, data: ScaleCreateOptions): Promise<Scale> {
|
||||||
|
await this.checkPreferredVersion();
|
||||||
|
const apiUrl = this.formatUrlForNotListing(desc);
|
||||||
|
|
||||||
|
const res = await this.request.patch(`${apiUrl}/scale`, {
|
||||||
|
data: { ...data },
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
"content-type": patchTypeHeaders.merge,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return res as Scale;
|
||||||
|
}
|
||||||
|
|
||||||
async patch(desc: ResourceDescriptor, data: PartialDeep<Object>): Promise<Object | null>;
|
async patch(desc: ResourceDescriptor, data: PartialDeep<Object>): Promise<Object | null>;
|
||||||
async patch(desc: ResourceDescriptor, data: PartialDeep<Object>, strategy: "strategic" | "merge"): Promise<Object | null>;
|
async patch(desc: ResourceDescriptor, data: PartialDeep<Object>, strategy: "strategic" | "merge"): Promise<Object | null>;
|
||||||
async patch(desc: ResourceDescriptor, data: Patch, strategy: "json"): Promise<Object | null>;
|
async patch(desc: ResourceDescriptor, data: Patch, strategy: "json"): Promise<Object | null>;
|
||||||
|
|||||||
@ -3,28 +3,10 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {
|
import type { KubeObjectStatus, NamespaceScopedMetadata, BaseKubeObjectCondition } from "../api-types";
|
||||||
KubeObjectMetadata,
|
|
||||||
KubeObjectStatus,
|
|
||||||
NamespaceScopedMetadata,
|
|
||||||
BaseKubeObjectCondition,
|
|
||||||
} from "../api-types";
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import type { PodTemplateSpec } from "../types/pod-template-spec";
|
import type { PodTemplateSpec } from "../types/pod-template-spec";
|
||||||
|
|
||||||
export interface Scale {
|
|
||||||
apiVersion: "autoscaling/v1";
|
|
||||||
kind: "Scale";
|
|
||||||
metadata: KubeObjectMetadata;
|
|
||||||
spec: {
|
|
||||||
replicas: number;
|
|
||||||
};
|
|
||||||
status: {
|
|
||||||
replicas: number;
|
|
||||||
selector: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ReplicationControllerSpec {
|
export interface ReplicationControllerSpec {
|
||||||
/**
|
/**
|
||||||
* Minimum number of seconds for which a newly created pod should be ready without any of its container crashing,
|
* Minimum number of seconds for which a newly created pod should be ready without any of its container crashing,
|
||||||
|
|||||||
27
packages/kube-object/src/types/scale.ts
Normal file
27
packages/kube-object/src/types/scale.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { KubeObjectMetadata } from "../api-types";
|
||||||
|
|
||||||
|
export interface Scale {
|
||||||
|
apiVersion: "autoscaling/v1";
|
||||||
|
kind: "Scale";
|
||||||
|
metadata: KubeObjectMetadata;
|
||||||
|
spec: {
|
||||||
|
replicas: number;
|
||||||
|
};
|
||||||
|
status: {
|
||||||
|
replicas: number;
|
||||||
|
selector: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScaleCreateOptions {
|
||||||
|
apiVersion?: "autoscaling/v1";
|
||||||
|
kind?: "Scale";
|
||||||
|
spec: {
|
||||||
|
replicas: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user