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

Fix core resources not showing up

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-11-28 11:13:25 -05:00
parent 00a8b81df4
commit 5f58196529
25 changed files with 58 additions and 39 deletions

View File

@ -175,15 +175,6 @@ export class Cluster implements ClusterModel {
private readonly knownResources = observable.array<KubeApiResource>(); private readonly knownResources = observable.array<KubeApiResource>();
private readonly knownNamespacedResources = computed(() => (
this.knownResources
.filter(r => r.namespaced === true)
));
private readonly knownClusterscopedResources = computed(() => (
this.knownResources
.filter(r => r.namespaced === false)
));
// The formatting of this is `group.name` or `name` (if in core) // The formatting of this is `group.name` or `name` (if in core)
private readonly allowedResources = observable.set<string>(); private readonly allowedResources = observable.set<string>();
@ -677,21 +668,14 @@ export class Cluster implements ClusterModel {
} }
try { try {
const canListClusterScopedResource = await requestNamespaceListPermissions("");
const apiLimit = plimit(5); // 5 concurrent api requests const apiLimit = plimit(5); // 5 concurrent api requests
const canListNamespacedResourceCheckers = await Promise.all(( const canListResourceCheckers = await Promise.all((
this.allowedNamespaces.map(namespace => apiLimit(() => requestNamespaceListPermissions(namespace))) this.allowedNamespaces.map(namespace => apiLimit(() => requestNamespaceListPermissions(namespace)))
)); ));
const canListNamespacedResource: CanListResource = (resource) => canListNamespacedResourceCheckers.some(fn => fn(resource)); const canListNamespacedResource: CanListResource = (resource) => canListResourceCheckers.some(fn => fn(resource));
const allowedClusterScopedResources = this.knownClusterscopedResources return this.knownResources
.get() .filter(canListNamespacedResource)
.filter(canListClusterScopedResource);
const allowedNamespaceScopedResources = this.knownNamespacedResources
.get()
.filter(canListNamespacedResource);
return [...allowedClusterScopedResources, ...allowedNamespaceScopedResources]
.map(formatKubeApiResource); .map(formatKubeApiResource);
} catch (error) { } catch (error) {
return []; return [];

View File

@ -47,11 +47,14 @@ const requestNamespaceListPermissionsForInjectable = getInjectable({
const { resourceRules } = status; const { resourceRules } = status;
return (resource) => { return (resource) => {
const resourceRule = resourceRules.find(rule => { const resourceRule = resourceRules.find(({
console.log(rule); apiGroups = [],
void resource; resources = [],
}) => {
const isAboutRelevantApiGroup = apiGroups.includes("*") || apiGroups.includes(resource.group);
const isAboutResource = resources.includes("*") || resources.includes(resource.apiName);
return true; return isAboutRelevantApiGroup && isAboutResource;
}); });
if (!resourceRule) { if (!resourceRule) {
@ -63,7 +66,7 @@ const requestNamespaceListPermissionsForInjectable = getInjectable({
return verbs.includes("*") || verbs.includes("list"); return verbs.includes("*") || verbs.includes("list");
}; };
} catch (error) { } catch (error) {
logger.error(`[AUTHORIZATION-NAMESPACE-REVIEW]: failed to create subject rules review: ${error}`, { namespace }); logger.error(`[AUTHORIZATION-NAMESPACE-REVIEW]: failed to create subject rules review`, { namespace, error });
return () => true; return () => true;
} }

View File

@ -3,7 +3,7 @@
* 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 { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import shouldShowResourceInjectable from "../../../../../../renderer/cluster-frame-context/should-show-resource.injectable"; import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token"; import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const configMapsRouteInjectable = getInjectable({ const configMapsRouteInjectable = getInjectable({
@ -11,8 +11,9 @@ const configMapsRouteInjectable = getInjectable({
instantiate: (di) => ({ instantiate: (di) => ({
path: "/configmaps", path: "/configmaps",
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectable, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "configmaps", apiName: "configmaps",
group: "v1",
}), }),
}), }),
injectionToken: frontEndRouteInjectionToken, injectionToken: frontEndRouteInjectionToken,

View File

@ -3,7 +3,7 @@
* 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 { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import shouldShowResourceInjectable from "../../../../../../renderer/cluster-frame-context/should-show-resource.injectable"; import { shouldShowResourceInjectionToken } from "../../../../../cluster-store/allowed-resources-injection-token";
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token"; import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
const horizontalPodAutoscalersRouteInjectable = getInjectable({ const horizontalPodAutoscalersRouteInjectable = getInjectable({
@ -12,7 +12,7 @@ const horizontalPodAutoscalersRouteInjectable = getInjectable({
instantiate: (di) => ({ instantiate: (di) => ({
path: "/hpa", path: "/hpa",
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectable, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "horizontalpodautoscalers", apiName: "horizontalpodautoscalers",
group: "autoscaling", group: "autoscaling",
}), }),

View File

@ -14,6 +14,7 @@ const leasesRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "leases", apiName: "leases",
group: "coordination.k8s.io",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const limitRangesRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "limitranges", apiName: "limitranges",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const resourceQuotasRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "resourcequotas", apiName: "resourcequotas",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const secretsRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "secrets", apiName: "secrets",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const eventsRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "events", apiName: "events",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const namespacesRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "namespaces", apiName: "namespaces",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const endpointsRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "endpoints", apiName: "endpoints",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const servicesRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "services", apiName: "services",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const nodesRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "nodes", apiName: "nodes",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const clusterOverviewRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "nodes", apiName: "nodes",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const persistentVolumeClaimsRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "persistentvolumeclaims", apiName: "persistentvolumeclaims",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const persistentVolumesRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "persistentvolumes", apiName: "persistentvolumes",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const serviceAccountsRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "serviceaccounts", apiName: "serviceaccounts",
group: "v1",
}), }),
}), }),

View File

@ -14,6 +14,7 @@ const podsRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "pods", apiName: "pods",
group: "v1",
}), }),
}), }),

View File

@ -13,25 +13,21 @@ export type KubeResource =
export interface KubeApiResource { export interface KubeApiResource {
kind: string; kind: string;
group?: string; group: string;
apiName: string; apiName: string;
namespaced: boolean; namespaced: boolean;
} }
export interface KubeApiResourceDescriptor { export interface KubeApiResourceDescriptor {
apiName: string; apiName: string;
group?: string; group: string;
} }
export const formatKubeApiResource = (res: KubeApiResourceDescriptor) => ( export const formatKubeApiResource = (res: KubeApiResourceDescriptor) => `${res.group}/${res.apiName}`;
res.group
? `${res.group}/${res.apiName}`
: res.apiName
);
export interface KubeApiResourceData { export interface KubeApiResourceData {
kind: string; // resource type (e.g. "Namespace") kind: string; // resource type (e.g. "Namespace")
group?: string; // api-group, if empty then "core" group: string; // api-group, if empty then "core"
namespaced: boolean; namespaced: boolean;
} }
@ -48,6 +44,7 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
}, },
configmaps: { configmaps: {
kind: "ConfigMap", kind: "ConfigMap",
group: "v1",
namespaced: true, namespaced: true,
}, },
cronjobs: { cronjobs: {
@ -72,10 +69,12 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
}, },
endpoints: { endpoints: {
kind: "Endpoint", kind: "Endpoint",
group: "v1",
namespaced: true, namespaced: true,
}, },
events: { events: {
kind: "Event", kind: "Event",
group: "v1",
namespaced: true, namespaced: true,
}, },
horizontalpodautoscalers: { horizontalpodautoscalers: {
@ -95,14 +94,17 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
}, },
namespaces: { namespaces: {
kind: "Namespace", kind: "Namespace",
group: "v1",
namespaced: false, namespaced: false,
}, },
limitranges: { limitranges: {
kind: "LimitRange", kind: "LimitRange",
group: "v1",
namespaced: true, namespaced: true,
}, },
leases: { leases: {
kind: "Lease", kind: "Lease",
group: "v1",
namespaced: true, namespaced: true,
}, },
networkpolicies: { networkpolicies: {
@ -112,18 +114,22 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
}, },
nodes: { nodes: {
kind: "Node", kind: "Node",
group: "v1",
namespaced: false, namespaced: false,
}, },
persistentvolumes: { persistentvolumes: {
kind: "PersistentVolume", kind: "PersistentVolume",
group: "v1",
namespaced: false, namespaced: false,
}, },
persistentvolumeclaims: { persistentvolumeclaims: {
kind: "PersistentVolumeClaim", kind: "PersistentVolumeClaim",
group: "v1",
namespaced: true, namespaced: true,
}, },
pods: { pods: {
kind: "Pod", kind: "Pod",
group: "v1",
namespaced: true, namespaced: true,
}, },
poddisruptionbudgets: { poddisruptionbudgets: {
@ -148,6 +154,7 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
}, },
resourcequotas: { resourcequotas: {
kind: "ResourceQuota", kind: "ResourceQuota",
group: "v1",
namespaced: true, namespaced: true,
}, },
replicasets: { replicasets: {
@ -167,14 +174,17 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
}, },
secrets: { secrets: {
kind: "Secret", kind: "Secret",
group: "v1",
namespaced: true, namespaced: true,
}, },
serviceaccounts: { serviceaccounts: {
kind: "ServiceAccount", kind: "ServiceAccount",
group: "v1",
namespaced: true, namespaced: true,
}, },
services: { services: {
kind: "Service", kind: "Service",
group: "v1",
namespaced: true, namespaced: true,
}, },
statefulsets: { statefulsets: {

View File

@ -100,6 +100,7 @@ describe("cluster/namespaces - edit namespace from new tab", () => {
builder.allowKubeResource({ builder.allowKubeResource({
apiName: "namespaces", apiName: "namespaces",
group: "v1",
}); });
}); });

View File

@ -44,6 +44,7 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () =
builder.allowKubeResource({ builder.allowKubeResource({
apiName: "namespaces", apiName: "namespaces",
group: "v1",
}); });
}); });

View File

@ -52,6 +52,7 @@ describe("cluster - visibility of sidebar items", () => {
beforeEach(() => { beforeEach(() => {
builder.allowKubeResource({ builder.allowKubeResource({
apiName: "namespaces", apiName: "namespaces",
group: "v1",
}); });
}); });
@ -76,6 +77,7 @@ const testRouteInjectable = getInjectable({
clusterFrame: true, clusterFrame: true,
isEnabled: di.inject(shouldShowResourceInjectionToken, { isEnabled: di.inject(shouldShowResourceInjectionToken, {
apiName: "namespaces", apiName: "namespaces",
group: "v1",
}), }),
}), }),

View File

@ -15,6 +15,7 @@ describe("workload overview", () => {
applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame(); applicationBuilder = getApplicationBuilder().setEnvironmentToClusterFrame();
applicationBuilder.allowKubeResource({ applicationBuilder.allowKubeResource({
apiName: "pods", apiName: "pods",
group: "v1",
}); });
rendered = await applicationBuilder.render(); rendered = await applicationBuilder.render();
}); });

View File

@ -21,6 +21,7 @@ const podsWorkloadInjectable = getInjectable({
return { return {
resource: { resource: {
apiName: "pods", apiName: "pods",
group: "v1",
}, },
open: navigate, open: navigate,

View File

@ -7,7 +7,7 @@ import { withInjectables } from "@ogre-tools/injectable-react";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import React from "react"; import React from "react";
import shouldShowResourceInjectable from "../cluster-frame-context/should-show-resource.injectable"; import { shouldShowResourceInjectionToken } from "../../common/cluster-store/allowed-resources-injection-token";
import { Events } from "../components/+events/events"; import { Events } from "../components/+events/events";
export interface WorkloadEventsProps {} export interface WorkloadEventsProps {}
@ -32,8 +32,9 @@ const NonInjectedWorkloadEvents = observer(({ workloadEventsAreAllowed }: Depend
export const WorkloadEvents = withInjectables<Dependencies, WorkloadEventsProps>(NonInjectedWorkloadEvents, { export const WorkloadEvents = withInjectables<Dependencies, WorkloadEventsProps>(NonInjectedWorkloadEvents, {
getProps: (di, props) => ({ getProps: (di, props) => ({
workloadEventsAreAllowed: di.inject(shouldShowResourceInjectable, { workloadEventsAreAllowed: di.inject(shouldShowResourceInjectionToken, {
apiName: "events", apiName: "events",
group: "v1",
}), }),
...props, ...props,
}), }),