mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix getting allowed resources, don't display workloads overview if no resources are allowed
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
55d3e996cb
commit
439c469ce6
@ -519,20 +519,25 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
return getClusterResources(await this.getProxyKubeconfig());
|
return getClusterResources(await this.getProxyKubeconfig());
|
||||||
}, 60 * 1000); // 1min
|
}, 60 * 1000); // 1min
|
||||||
|
|
||||||
private isAllowedCheckers = new ExtendedObservableMap<string, () => Promise<Map<string, boolean>>>();
|
private isAllowedCheckers = new ExtendedObservableMap<string, () => Promise<Set<string>>>();
|
||||||
|
|
||||||
private async getIsAllowedResourcesInNamespace(namespace: string): Promise<Map<string, boolean>> {
|
private async getIsAllowedResourcesInNamespace(namespace: string): Promise<Set<string>> {
|
||||||
|
console.log("getIsAllowedResourcesInNamespace", Date.now());
|
||||||
const groups = await this.getApiResourceMap();
|
const groups = await this.getApiResourceMap();
|
||||||
const isAllowed = new Map<string, boolean>();
|
const isAllowed = new Set<string>();
|
||||||
|
|
||||||
for (const group of groups.values()) {
|
for (const group of groups.values()) {
|
||||||
for (const versions of group.values()) {
|
for (const versions of group.values()) {
|
||||||
for (const resource of versions.keys()) {
|
for (const resource of versions.keys()) {
|
||||||
isAllowed.set(resource, await this.canI({
|
const canList = await this.canI({
|
||||||
name: resource,
|
resource,
|
||||||
namespace,
|
namespace,
|
||||||
verb: "list",
|
verb: "list",
|
||||||
}));
|
});
|
||||||
|
|
||||||
|
if (canList) {
|
||||||
|
isAllowed.add(resource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -540,7 +545,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
return isAllowed;
|
return isAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getIsAllowedResources(namespace: string): Promise<Map<string, boolean>> {
|
async getIsAllowedResources(namespace: string): Promise<Set<string>> {
|
||||||
return this.isAllowedCheckers.getOrInsert(
|
return this.isAllowedCheckers.getOrInsert(
|
||||||
namespace,
|
namespace,
|
||||||
() => asyncThrottle(
|
() => asyncThrottle(
|
||||||
@ -566,7 +571,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
const accessReview = await this.canIApiLimit(() => authApi.createSelfSubjectAccessReview({
|
const accessReview = await this.canIApiLimit(() => authApi.createSelfSubjectAccessReview({
|
||||||
apiVersion: "authorization.k8s.io/v1",
|
apiVersion: "authorization.k8s.io/v1",
|
||||||
kind: "SelfSubjectAccessReview",
|
kind: "SelfSubjectAccessReview",
|
||||||
spec: { resourceAttributes }
|
spec: { resourceAttributes },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return accessReview.body.status.allowed;
|
return accessReview.body.status.allowed;
|
||||||
|
|||||||
@ -119,19 +119,19 @@ export function initIpcMainHandlers() {
|
|||||||
?.getApiResourceMap();
|
?.getApiResourceMap();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMainHandle(ClusterResourceIsAllowedChannel, async (event, clusterId: ClusterId, namespaces: string[]): Promise<[string, boolean][]> => {
|
ipcMainHandle(ClusterResourceIsAllowedChannel, async (event, clusterId: ClusterId, namespaces: string[]): Promise<string[]> => {
|
||||||
const cluster = ClusterStore.getInstance().getById(clusterId);
|
const cluster = ClusterStore.getInstance().getById(clusterId);
|
||||||
|
|
||||||
if (!cluster) {
|
if (!cluster) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAllowed = new Map<string, boolean>();
|
const isAllowed = new Set<string>();
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
namespaces.map(async namespace => {
|
namespaces.map(async namespace => {
|
||||||
for (const [resource, canList] of await cluster.getIsAllowedResources(namespace)) {
|
for (const resource of await cluster.getIsAllowedResources(namespace)) {
|
||||||
isAllowed.set(resource, Boolean(isAllowed.get(resource)) || canList);
|
isAllowed.add(resource);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { action, makeObservable, observable, ObservableMap, reaction } from "mobx";
|
import { action, makeObservable, observable, reaction } from "mobx";
|
||||||
import type { ClusterId } from "../../common/cluster-store";
|
import type { ClusterId } from "../../common/cluster-store";
|
||||||
import { ClusterResourceIsAllowedChannel, ClusterGetResourcesChannel, requestMain } from "../../common/ipc";
|
import { ClusterResourceIsAllowedChannel, ClusterGetResourcesChannel, requestMain } from "../../common/ipc";
|
||||||
import { Disposer, Singleton } from "../utils";
|
import { Disposer, Singleton } from "../utils";
|
||||||
@ -31,7 +31,7 @@ type NamespaceName = string;
|
|||||||
type ResourceName = string;
|
type ResourceName = string;
|
||||||
|
|
||||||
export class AllowedResources extends Singleton {
|
export class AllowedResources extends Singleton {
|
||||||
protected allowedResourceMap = new ObservableMap<ResourceName, boolean>();
|
protected allowedResources = observable.set<ResourceName>();
|
||||||
@observable public resources: ApiResourceMap;
|
@observable public resources: ApiResourceMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,9 +65,10 @@ export class AllowedResources extends Singleton {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
private async refresh(namespaces: NamespaceName[]) {
|
private async refresh(namespaces: NamespaceName[]) {
|
||||||
try {
|
try {
|
||||||
this.allowedResourceMap.replace(await requestMain(ClusterResourceIsAllowedChannel, this.clusterId, namespaces));
|
this.allowedResources.replace(await requestMain(ClusterResourceIsAllowedChannel, this.clusterId, namespaces));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[ALLOWED-RESOURCES]: failed to refresh", error, { namespaces });
|
console.error("[ALLOWED-RESOURCES]: failed to refresh", error, { namespaces });
|
||||||
Notifications.error("Failed to refresh allowed resources");
|
Notifications.error("Failed to refresh allowed resources");
|
||||||
@ -81,7 +82,7 @@ export class AllowedResources extends Singleton {
|
|||||||
* @returns `true` if the resource exists; is cluster scoped and can be listed, or is namespaced and can be listed in at least one of the namespaces
|
* @returns `true` if the resource exists; is cluster scoped and can be listed, or is namespaced and can be listed in at least one of the namespaces
|
||||||
*/
|
*/
|
||||||
isAllowed(name: ResourceName): boolean {
|
isAllowed(name: ResourceName): boolean {
|
||||||
return this.allowedResourceMap.get(name) ?? false;
|
return this.allowedResources.has(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,14 +39,7 @@ import * as routes from "../../../common/routes";
|
|||||||
@observer
|
@observer
|
||||||
export class Workloads extends React.Component {
|
export class Workloads extends React.Component {
|
||||||
@computed static get tabRoutes(): TabLayoutRoute[] {
|
@computed static get tabRoutes(): TabLayoutRoute[] {
|
||||||
const tabs: TabLayoutRoute[] = [
|
const tabs: TabLayoutRoute[] = [];
|
||||||
{
|
|
||||||
title: "Overview",
|
|
||||||
component: WorkloadsOverview,
|
|
||||||
url: routes.overviewURL(),
|
|
||||||
routePath: routes.overviewRoute.path.toString()
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
if (isAllowedResource("pods")) {
|
if (isAllowedResource("pods")) {
|
||||||
tabs.push({
|
tabs.push({
|
||||||
@ -111,6 +104,15 @@ export class Workloads extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tabs.length > 0) {
|
||||||
|
tabs.unshift({
|
||||||
|
title: "Overview",
|
||||||
|
component: WorkloadsOverview,
|
||||||
|
url: routes.overviewURL(),
|
||||||
|
routePath: routes.overviewRoute.path.toString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return tabs;
|
return tabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user