Skip to content

Commit

Permalink
Add behavioural tests for Cluster Menu K8s Resources in Sidebar menu …
Browse files Browse the repository at this point in the history
…not being shown (#7280)

* Add behavioural tests to cover bug fix

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove previous fix to fix last test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* More consistent impl of flushPromises

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fixup tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove ContextHandler test (dead code)

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix PrometheusHandler describe text

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add useful case test-utils helper

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Rename file to match token

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Cleanup tests to fix type errors and use tables

Signed-off-by: Sebastian Malton <sebastian@malton.name>

---------

Signed-off-by: Sebastian Malton <sebastian@malton.name>
  • Loading branch information
Nokel81 authored Mar 22, 2023
1 parent 5409324 commit 8a80607
Show file tree
Hide file tree
Showing 32 changed files with 1,096 additions and 766 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { AuthorizationV1Api } from "@kubernetes/client-node";
import type { KubeConfig } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";

export type CreateAuthorizationApi = (config: KubeConfig) => AuthorizationV1Api;

const createAuthorizationApiInjectable = getInjectable({
id: "create-authorization-api",
instantiate: (): CreateAuthorizationApi => (config) => config.makeApiClient(AuthorizationV1Api),
});

export default createAuthorizationApiInjectable;
42 changes: 42 additions & 0 deletions packages/core/src/common/cluster/create-can-i.injectable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/

import type { AuthorizationV1Api, V1ResourceAttributes } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";
import loggerInjectable from "../logger.injectable";

/**
* Requests the permissions for actions on the kube cluster
* @param resourceAttributes The descriptor of the action that is desired to be known if it is allowed
* @returns `true` if the actions described are allowed
*/
export type CanI = (resourceAttributes: V1ResourceAttributes) => Promise<boolean>;

export type CreateCanI = (api: AuthorizationV1Api) => CanI;

const createCanIInjectable = getInjectable({
id: "create-can-i",
instantiate: (di): CreateCanI => {
const logger = di.inject(loggerInjectable);

return (api) => async (resourceAttributes: V1ResourceAttributes): Promise<boolean> => {
try {
const { body } = await api.createSelfSubjectAccessReview({
apiVersion: "authorization.k8s.io/v1",
kind: "SelfSubjectAccessReview",
spec: { resourceAttributes },
});

return body.status?.allowed ?? false;
} catch (error) {
logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${error}`, { resourceAttributes });

return false;
}
};
},
});

export default createCanIInjectable;
16 changes: 16 additions & 0 deletions packages/core/src/common/cluster/create-core-api.injectable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { KubeConfig } from "@kubernetes/client-node";
import { CoreV1Api } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";

export type CreateCoreApi = (config: KubeConfig) => CoreV1Api;

const createCoreApiInjectable = getInjectable({
id: "create-core-api",
instantiate: (): CreateCoreApi => config => config.makeApiClient(CoreV1Api),
});

export default createCoreApiInjectable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/

import type { AuthorizationV1Api } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";
import loggerInjectable from "../logger.injectable";
import type { KubeApiResource } from "../rbac";

export type CanListResource = (resource: KubeApiResource) => boolean;

/**
* Requests the permissions for actions on the kube cluster
* @param namespace The namespace of the resources
*/
export type RequestNamespaceListPermissions = (namespace: string) => Promise<CanListResource>;

export type CreateRequestNamespaceListPermissions = (api: AuthorizationV1Api) => RequestNamespaceListPermissions;

const createRequestNamespaceListPermissionsInjectable = getInjectable({
id: "create-request-namespace-list-permissions",
instantiate: (di): CreateRequestNamespaceListPermissions => {
const logger = di.inject(loggerInjectable);

return (api) => async (namespace) => {
try {
const { body: { status }} = await api.createSelfSubjectRulesReview({
apiVersion: "authorization.k8s.io/v1",
kind: "SelfSubjectRulesReview",
spec: { namespace },
});

if (!status || status.incomplete) {
logger.warn(`[AUTHORIZATION-NAMESPACE-REVIEW]: allowing all resources in namespace="${namespace}" due to incomplete SelfSubjectRulesReview: ${status?.evaluationError}`);

return () => true;
}

const { resourceRules } = status;

return (resource) => (
resourceRules
.filter(({ apiGroups = ["*"] }) => apiGroups.includes("*") || apiGroups.includes(resource.group))
.filter(({ resources = ["*"] }) => resources.includes("*") || resources.includes(resource.apiName))
.some(({ verbs }) => verbs.includes("*") || verbs.includes("list"))
);
} catch (error) {
logger.error(`[AUTHORIZATION-NAMESPACE-REVIEW]: failed to create subject rules review`, { namespace, error });

return () => true;
}
};
},
});

export default createRequestNamespaceListPermissionsInjectable;
20 changes: 7 additions & 13 deletions packages/core/src/common/cluster/list-namespaces.injectable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,21 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { KubeConfig } from "@kubernetes/client-node";
import { CoreV1Api } from "@kubernetes/client-node";
import type { CoreV1Api } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable";
import { isDefined } from "@k8slens/utilities";

export type ListNamespaces = () => Promise<string[]>;

export type CreateListNamespaces = (config: KubeConfig) => ListNamespaces;
export type CreateListNamespaces = (api: CoreV1Api) => ListNamespaces;

const createListNamespacesInjectable = getInjectable({
id: "create-list-namespaces",
instantiate: (): CreateListNamespaces => (config) => {
const coreApi = config.makeApiClient(CoreV1Api);

return async () => {
const { body: { items }} = await coreApi.listNamespace();
instantiate: (): CreateListNamespaces => (api) => async () => {
const { body: { items }} = await api.listNamespace();

return items
.map(ns => ns.metadata?.name)
.filter(isDefined);
};
return items
.map(ns => ns.metadata?.name)
.filter(isDefined);
},
});

Expand Down

This file was deleted.

Loading

0 comments on commit 8a80607

Please sign in to comment.