chore: Upgrade to @kubernetes/client-node@1.0.0-rc2

- Finally removes dependency on 'request'

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton committed 2023-06-01 14:34:12 -04:00
1 parent f602ce8f46
commit 2970fb12e8
13 files changed
+319 -558

No files matched your search

+1 -1
View File
@@ -238,7 +238,7 @@
"@k8slens/startable-stoppable": "^1.0.0-alpha.1",
"@k8slens/tooltip": "^1.0.0-alpha.5",
"@k8slens/utilities": "^1.0.0-alpha.1",
"@kubernetes/client-node": "^0.18.1",
"@kubernetes/client-node": "^1.0.0-rc2",
"@material-ui/core": "^4.12.3",
"@material-ui/lab": "^4.0.0-alpha.60",
"@ogre-tools/fp": "^17.2.0",
@@ -23,13 +23,15 @@ const createCanIInjectable = getInjectable({
return (api) => async (resourceAttributes: V1ResourceAttributes): Promise<boolean> => {
try {
const { body } = await api.createSelfSubjectAccessReview({
apiVersion: "authorization.k8s.io/v1",
kind: "SelfSubjectAccessReview",
spec: { resourceAttributes },
const review = await api.createSelfSubjectAccessReview({
body: {
apiVersion: "authorization.k8s.io/v1",
kind: "SelfSubjectAccessReview",
spec: { resourceAttributes },
},
});
return body.status?.allowed ?? false;
return review.status?.allowed ?? false;
} catch (error) {
logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${error}`, { resourceAttributes });
@@ -25,10 +25,12 @@ const createRequestNamespaceListPermissionsInjectable = getInjectable({
return (api) => async (namespace) => {
try {
const { body: { status }} = await api.createSelfSubjectRulesReview({
apiVersion: "authorization.k8s.io/v1",
kind: "SelfSubjectRulesReview",
spec: { namespace },
const { status } = await api.createSelfSubjectRulesReview({
body: {
apiVersion: "authorization.k8s.io/v1",
kind: "SelfSubjectRulesReview",
spec: { namespace },
},
});
if (!status || status.incomplete) {
@@ -12,7 +12,7 @@ export type CreateListNamespaces = (api: CoreV1Api) => ListNamespaces;
const createListNamespacesInjectable = getInjectable({
id: "create-list-namespaces",
instantiate: (): CreateListNamespaces => (api) => async () => {
const { body: { items }} = await api.listNamespace();
const { items } = await api.listNamespace();
return items
.map(ns => ns.metadata?.name)
@@ -7,7 +7,6 @@ import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { AuthorizationV1Api, V1SubjectRulesReviewStatus } from "@kubernetes/client-node";
import type { DiContainer } from "@ogre-tools/injectable";
import type { IncomingMessage } from "http";
import { anyObject } from "jest-mock-extended";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import { cast } from "../../test-utils/cast";
@@ -46,11 +45,13 @@ describe("requestNamespaceListPermissions", () => {
});
it("should request the creation of a SelfSubjectRulesReview", () => {
expect(createSelfSubjectRulesReviewMock).toBeCalledWith(anyObject({
spec: {
namespace: "irrelevant-namespace",
},
}));
expect(createSelfSubjectRulesReviewMock).toBeCalledWith({
body: anyObject({
spec: {
namespace: "irrelevant-namespace",
},
}),
});
});
([
@@ -189,11 +190,8 @@ describe("requestNamespaceListPermissions", () => {
describe(`when api returns ${description}`, () => {
beforeEach(async () => {
await createSelfSubjectRulesReviewMock.resolve({
body: {
status,
spec: {},
},
response: null as unknown as IncomingMessage,
status,
spec: {},
});
});
@@ -5,7 +5,7 @@
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { AuthorizationV1Api, CoreV1Api, V1APIGroupList, V1APIVersions, V1NamespaceList, V1SelfSubjectAccessReview, V1SelfSubjectRulesReview } from "@kubernetes/client-node";
import type { AuthorizationV1Api, CoreV1Api, V1APIGroupList, V1APIVersions, V1SelfSubjectAccessReview, V1SelfSubjectRulesReview } from "@kubernetes/client-node";
import type { Cluster } from "../../common/cluster/cluster";
import createAuthorizationApiInjectable from "../../common/cluster/create-authorization-api.injectable";
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
@@ -477,20 +477,18 @@ const nonCoreApiResponse = {
} as V1APIGroupList;
const listNamespaceResponse = {
body: {
items: [
{
metadata: {
name: "default",
},
items: [
{
metadata: {
name: "default",
},
{
metadata: {
name: "my-namespace",
},
},
{
metadata: {
name: "my-namespace",
},
],
} as PartialDeep<V1NamespaceList>,
},
],
} as Awaited<ReturnType<CoreV1Api["listNamespace"]>>;
const coreApiKindsResponse = {
@@ -585,51 +583,44 @@ const discoveryK8sIoKindsResponse = {
],
};
type CreateSelfSubjectRulesReviewRes = Awaited<ReturnType<AuthorizationV1Api["createSelfSubjectRulesReview"]>>;
const defaultIncompletePermissions = {
body: {
status: {
incomplete: true,
},
} as PartialDeep<V1SelfSubjectRulesReview>,
} as CreateSelfSubjectRulesReviewRes;
status: {
incomplete: true,
},
} as V1SelfSubjectRulesReview;
const emptyPermissions = {
body: {
status: {
resourceRules: [],
},
} as PartialDeep<V1SelfSubjectRulesReview>,
} as CreateSelfSubjectRulesReviewRes;
status: {
resourceRules: [],
incomplete: false,
nonResourceRules: [],
},
spec: {},
} as V1SelfSubjectRulesReview;
const defaultSingleListPermissions = {
body: {
status: {
resourceRules: [{
status: {
resourceRules: [{
apiGroups: [""],
resources: ["pods"],
verbs: ["list"],
}],
},
} as V1SelfSubjectRulesReview;
const defaultMultipleListPermissions = {
status: {
resourceRules: [
{
apiGroups: [""],
resources: ["pods"],
verbs: ["get"],
},
{
apiGroups: [""],
resources: ["pods"],
verbs: ["list"],
}],
},
} as PartialDeep<V1SelfSubjectRulesReview>,
} as CreateSelfSubjectRulesReviewRes;
const defaultMultipleListPermissions = {
body: {
status: {
resourceRules: [
{
apiGroups: [""],
resources: ["pods"],
verbs: ["get"],
},
{
apiGroups: [""],
resources: ["pods"],
verbs: ["list"],
},
],
},
} as PartialDeep<V1SelfSubjectRulesReview>,
} as CreateSelfSubjectRulesReviewRes;
},
],
},
} as V1SelfSubjectRulesReview;
@@ -3,7 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { type KubeConfig, HttpError } from "@kubernetes/client-node";
import type { KubeConfig } from "@kubernetes/client-node";
import { ApiException } from "@kubernetes/client-node";
import { reaction, comparer, runInAction } from "mobx";
import { ClusterStatus } from "../../common/cluster-types";
import type { CreateListNamespaces } from "../../common/cluster/list-namespaces.injectable";
@@ -375,10 +376,8 @@ class ClusterConnection {
const ctx = proxyConfig.getContextObject(this.cluster.contextName.get());
const namespaceList = [ctx?.namespace].filter(isDefined);
if (namespaceList.length === 0 && error instanceof HttpError && error.statusCode === 403) {
const { response } = error as HttpError & { response: Response };
this.dependencies.logger.info("[CLUSTER]: listing namespaces is forbidden, broadcasting", { clusterId: this.cluster.id, error: response.body });
if (namespaceList.length === 0 && error instanceof ApiException && error.code === 403) {
this.dependencies.logger.info("[CLUSTER]: listing namespaces is forbidden, broadcasting", { clusterId: this.cluster.id, error: error.body || error.message });
this.dependencies.broadcastMessage(clusterListNamespaceForbiddenChannel, this.cluster.id);
}
@@ -18,12 +18,13 @@ const getServiceAccountRouteInjectable = getRouteInjectable({
method: "get",
path: `${apiPrefix}/kubeconfig/service-account/{namespace}/{account}`,
})(async ({ params, cluster }) => {
const { namespace, account } = params;
const loadProxyKubeconfig = di.inject(loadProxyKubeconfigInjectable, cluster);
const proxyKubeconfig = await loadProxyKubeconfig();
const client = proxyKubeconfig.makeApiClient(CoreV1Api);
const secretList = await client.listNamespacedSecret(params.namespace);
const { items } = await client.listNamespacedSecret({ namespace });
const secret = secretList.body.items.find(secret => {
const secret = items.find(secret => {
const { annotations = {}} = secret.metadata ?? {};
return annotations["kubernetes.io/service-account.name"] === params.account;
@@ -63,7 +64,7 @@ const getServiceAccountRouteInjectable = getRouteInjectable({
],
contexts: [
{
name: `${contextName}-${params.account}`,
name: `${contextName}-${account}`,
context: {
user: params.account,
cluster: contextName,
@@ -45,7 +45,10 @@ export class NodeShellSession extends ShellSession {
const cleanup = once(() => {
coreApi
.deleteNamespacedPod(this.podName, "kube-system")
.deleteNamespacedPod({
name: this.podName,
namespace: "kube-system",
})
.catch(error => this.dependencies.logger.warn(`[NODE-SHELL]: failed to remove pod shell`, error));
});
@@ -111,32 +114,35 @@ export class NodeShellSession extends ShellSession {
: undefined;
return coreApi
.createNamespacedPod("kube-system", {
metadata: {
name: this.podName,
namespace: "kube-system",
},
spec: {
nodeName: this.nodeName,
restartPolicy: "Never",
terminationGracePeriodSeconds: 0,
hostPID: true,
hostIPC: true,
hostNetwork: true,
tolerations: [{
operator: "Exists",
}],
priorityClassName: "system-node-critical",
containers: [{
name: "shell",
image: nodeShellImage || initialNodeShellImage,
securityContext: {
privileged: true,
},
command: ["nsenter"],
args: ["-t", "1", "-m", "-u", "-i", "-n", "sleep", "14000"],
}],
imagePullSecrets,
.createNamespacedPod({
namespace: "kube-system",
body: {
metadata: {
name: this.podName,
namespace: "kube-system",
},
spec: {
nodeName: this.nodeName,
restartPolicy: "Never",
terminationGracePeriodSeconds: 0,
hostPID: true,
hostIPC: true,
hostNetwork: true,
tolerations: [{
operator: "Exists",
}],
priorityClassName: "system-node-critical",
containers: [{
name: "shell",
image: nodeShellImage || initialNodeShellImage,
securityContext: {
privileged: true,
},
command: ["nsenter"],
args: ["-t", "1", "-m", "-u", "-i", "-n", "sleep", "14000"],
}],
imagePullSecrets,
},
},
});
}
@@ -35,7 +35,7 @@
"@k8slens/application": "^6.5.0-alpha.2",
"@k8slens/feature-core": "^6.5.0-alpha.0",
"@k8slens/utilities": "^1.0.0-alpha.7",
"@kubernetes/client-node": "^0.18.1",
"@kubernetes/client-node": "^1.0.0-rc2",
"@ogre-tools/fp": "^17.2.0",
"@ogre-tools/injectable": "^17.2.0",
"@ogre-tools/injectable-extension-for-auto-registration": "^17.2.0",
@@ -59,10 +59,10 @@ export async function findFirstNamespacedService(
try {
for (const selector of selectors) {
const {
body: {
items: [service],
},
} = await client.listServiceForAllNamespaces(undefined, undefined, undefined, selector);
items: [service],
} = await client.listServiceForAllNamespaces({
labelSelector: selector,
});
if (service?.metadata?.namespace && service.metadata.name && service.spec?.ports) {
return {
@@ -87,7 +87,7 @@ export async function findNamespacedService(
namespace: string,
): Promise<PrometheusServiceInfo> {
try {
const { body: service } = await client.readNamespacedService(name, namespace);
const service = await client.readNamespacedService({ name, namespace });
if (!service.metadata?.namespace || !service.metadata.name || !service.spec?.ports) {
throw new Error(`Service found in namespace="${namespace}" did not have required information`);