mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
refactoring: get rid of config.store.ts (renderer), moved allowNamespaces/allowedResources to cluster.ts apis
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
1 parent
407c4fb4d0
commit
3aef3700de
19 files changed
+158
-281
No files matched your search
@@ -6,9 +6,9 @@ import { autobind, EventEmitter } from "../utils";
|
||||
import { KubeJsonApiData } from "./kube-json-api";
|
||||
import type { KubeObjectStore } from "../kube-object.store";
|
||||
import { KubeApi } from "./kube-api";
|
||||
import { configStore } from "../config.store";
|
||||
import { apiManager } from "./api-manager";
|
||||
import { apiPrefix, isDevelopment } from "../../common/vars";
|
||||
import { clusterStore } from "../../common/cluster-store";
|
||||
|
||||
export interface IKubeWatchEvent<T = any> {
|
||||
type: "ADDED" | "MODIFIED" | "DELETED";
|
||||
@@ -61,10 +61,10 @@ export class KubeWatchApi {
|
||||
}
|
||||
|
||||
protected getQuery(): Partial<IKubeWatchRouteQuery> {
|
||||
const { isClusterAdmin, allowedNamespaces } = configStore;
|
||||
const { isAdmin, allowedNamespaces } = clusterStore.activeCluster;
|
||||
return {
|
||||
api: this.activeApis.map(api => {
|
||||
if (isClusterAdmin) return api.getWatchUrl();
|
||||
if (isAdmin) return api.getWatchUrl();
|
||||
return allowedNamespaces.map(namespace => api.getWatchUrl(namespace))
|
||||
}).flat()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { configStore } from "../config.store";
|
||||
import { clusterStore } from "../../common/cluster-store";
|
||||
|
||||
// todo: refactor / move to cluster-store.ts?
|
||||
|
||||
export function isAllowedResource(resources: string | string[]) {
|
||||
if (!Array.isArray(resources)) {
|
||||
resources = [resources];
|
||||
}
|
||||
const { allowedResources } = configStore;
|
||||
const allowedResources = clusterStore.activeCluster?.allowedResources || [];
|
||||
for (const resource of resources) {
|
||||
if (!allowedResources.includes(resource)) {
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { stringify } from "querystring";
|
||||
import { autobind, base64, EventEmitter, interval } from "../utils";
|
||||
import { autobind, base64, EventEmitter } from "../utils";
|
||||
import { WebSocketApi } from "./websocket-api";
|
||||
import { configStore } from "../config.store";
|
||||
import isEqual from "lodash/isEqual"
|
||||
import { isDevelopment } from "../../common/vars";
|
||||
|
||||
@@ -25,21 +24,19 @@ enum TerminalColor {
|
||||
NO_COLOR = "\u001b[0m",
|
||||
}
|
||||
|
||||
export interface ITerminalApiOptions {
|
||||
export type TerminalApiQuery = Record<string, string> & {
|
||||
id: string;
|
||||
node?: string;
|
||||
colorTheme?: "light" | "dark";
|
||||
type?: string | "node";
|
||||
}
|
||||
|
||||
export class TerminalApi extends WebSocketApi {
|
||||
protected size: { Width: number; Height: number };
|
||||
protected currentToken: string;
|
||||
protected tokenInterval = interval(60, this.sendNewToken); // refresh every minute
|
||||
|
||||
public onReady = new EventEmitter<[]>();
|
||||
public isReady = false;
|
||||
|
||||
constructor(protected options: ITerminalApiOptions) {
|
||||
constructor(protected options: TerminalApiQuery) {
|
||||
super({
|
||||
logging: isDevelopment,
|
||||
flushOnOpen: false,
|
||||
@@ -47,50 +44,33 @@ export class TerminalApi extends WebSocketApi {
|
||||
});
|
||||
}
|
||||
|
||||
async getUrl(token: string) {
|
||||
const { hostname, protocol } = location;
|
||||
async getUrl() {
|
||||
let { port } = location;
|
||||
const { hostname, protocol } = location;
|
||||
const { id, node } = this.options;
|
||||
const wss = `ws${protocol === "https:" ? "s" : ""}://`;
|
||||
const queryParams = { token, id };
|
||||
const query: TerminalApiQuery = { id };
|
||||
if (port) {
|
||||
port = `:${port}`
|
||||
}
|
||||
if (node) {
|
||||
Object.assign(queryParams, {
|
||||
node: node,
|
||||
type: "node"
|
||||
});
|
||||
query.node = node;
|
||||
query.type = "node";
|
||||
}
|
||||
return `${wss}${hostname}${port}/api?${stringify(queryParams)}`;
|
||||
return `${wss}${hostname}${port}/api?${stringify(query)}`;
|
||||
}
|
||||
|
||||
async connect() {
|
||||
const token = await configStore.getToken();
|
||||
const apiUrl = await this.getUrl(token);
|
||||
const { colorTheme } = this.options;
|
||||
this.emitStatus("Connecting ...", {
|
||||
color: colorTheme == "light" ? TerminalColor.GRAY : TerminalColor.LIGHT_GRAY
|
||||
});
|
||||
const apiUrl = await this.getUrl();
|
||||
this.emitStatus("Connecting ...");
|
||||
this.onData.addListener(this._onReady, { prepend: true });
|
||||
this.currentToken = token;
|
||||
this.tokenInterval.start();
|
||||
return super.connect(apiUrl);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
async sendNewToken() {
|
||||
const token = await configStore.getToken();
|
||||
if (!this.isReady || token == this.currentToken) return;
|
||||
this.sendCommand(token, TerminalChannels.TOKEN);
|
||||
this.currentToken = token;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (!this.socket) return;
|
||||
const exitCode = String.fromCharCode(4); // ctrl+d
|
||||
this.sendCommand(exitCode);
|
||||
this.tokenInterval.stop();
|
||||
setTimeout(() => super.destroy(), 2000);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { action, observable, when, IReactionDisposer, reaction } from "mobx";
|
||||
import { action, IReactionDisposer, observable, reaction, when } from "mobx";
|
||||
import { autobind } from "../../utils";
|
||||
import { HelmRelease, helmReleasesApi, IReleaseCreatePayload, IReleaseUpdatePayload } from "../../api/endpoints/helm-releases.api";
|
||||
import { ItemStore } from "../../item.store";
|
||||
import { configStore } from "../../config.store";
|
||||
import { secretsStore } from "../+config-secrets/secrets.store";
|
||||
import { Secret } from "../../api/endpoints";
|
||||
import { secretsStore } from "../+config-secrets/secrets.store";
|
||||
import { clusterStore } from "../../../common/cluster-store";
|
||||
|
||||
@autobind()
|
||||
export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
@@ -58,8 +58,8 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
this.isLoading = true;
|
||||
let items;
|
||||
try {
|
||||
const { isClusterAdmin, allowedNamespaces } = configStore;
|
||||
items = await this.loadItems(!isClusterAdmin ? allowedNamespaces : null);
|
||||
const { isAdmin, allowedNamespaces } = clusterStore.activeCluster;
|
||||
items = await this.loadItems(!isAdmin ? allowedNamespaces : null);
|
||||
} finally {
|
||||
if (items) {
|
||||
items = this.sortItems(items);
|
||||
@@ -73,8 +73,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
async loadItems(namespaces?: string[]) {
|
||||
if (!namespaces) {
|
||||
return helmReleasesApi.list();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return Promise
|
||||
.all(namespaces.map(namespace => helmReleasesApi.list(namespace)))
|
||||
.then(items => items.flat());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import "./cluster.scss"
|
||||
|
||||
import React from "react";
|
||||
import { computed, reaction, when } from "mobx";
|
||||
import { computed, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { MainLayout } from "../layout/main-layout";
|
||||
import { ClusterIssues } from "./cluster-issues";
|
||||
@@ -13,22 +13,23 @@ import { nodesStore } from "../+nodes/nodes.store";
|
||||
import { podsStore } from "../+workloads-pods/pods.store";
|
||||
import { clusterStore } from "./cluster.store";
|
||||
import { eventStore } from "../+events/event.store";
|
||||
import { configStore } from "../../config.store";
|
||||
import { isAllowedResource } from "../../api/rbac";
|
||||
|
||||
@observer
|
||||
export class Cluster extends React.Component {
|
||||
private dependentStores = [nodesStore, podsStore];
|
||||
|
||||
private watchers = [
|
||||
interval(60, () => clusterStore.getMetrics()),
|
||||
interval(20, () => eventStore.loadAll())
|
||||
];
|
||||
|
||||
private dependentStores = [nodesStore, podsStore];
|
||||
@computed get isLoaded() {
|
||||
return nodesStore.isLoaded && podsStore.isLoaded
|
||||
}
|
||||
|
||||
// todo: refactor
|
||||
async componentDidMount() {
|
||||
await when(() => configStore.isLoaded);
|
||||
|
||||
const { dependentStores } = this;
|
||||
if (!isAllowedResource("nodes")) {
|
||||
dependentStores.splice(dependentStores.indexOf(nodesStore), 1)
|
||||
@@ -50,13 +51,6 @@ export class Cluster extends React.Component {
|
||||
])
|
||||
}
|
||||
|
||||
@computed get isLoaded() {
|
||||
return (
|
||||
nodesStore.isLoaded &&
|
||||
podsStore.isLoaded
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isLoaded } = this;
|
||||
return (
|
||||
|
||||
@@ -82,10 +82,6 @@ export class Preferences extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onThemeChange = ({ value }: SelectOption<string>) => {
|
||||
userStore.preferences.colorTheme = value;
|
||||
}
|
||||
|
||||
onRepoSelect = async ({ value: repo }: SelectOption<HelmRepo>) => {
|
||||
const isAdded = this.helmAddedRepos.has(repo.name);
|
||||
if (isAdded) {
|
||||
|
||||
@@ -9,9 +9,9 @@ import { MainLayout, TabRoute } from "../layout/main-layout";
|
||||
import { PersistentVolumes, volumesRoute, volumesURL } from "../+storage-volumes";
|
||||
import { StorageClasses, storageClassesRoute, storageClassesURL } from "../+storage-classes";
|
||||
import { PersistentVolumeClaims, volumeClaimsRoute, volumeClaimsURL } from "../+storage-volume-claims";
|
||||
import { configStore } from "../../config.store";
|
||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||
import { storageURL } from "./storage.route";
|
||||
import { isAllowedResource } from "../../api/rbac";
|
||||
|
||||
interface Props extends RouteComponentProps<{}> {
|
||||
}
|
||||
@@ -20,7 +20,6 @@ interface Props extends RouteComponentProps<{}> {
|
||||
export class Storage extends React.Component<Props> {
|
||||
static get tabRoutes() {
|
||||
const tabRoutes: TabRoute[] = [];
|
||||
const { allowedResources } = configStore;
|
||||
const query = namespaceStore.getContextParams()
|
||||
|
||||
tabRoutes.push({
|
||||
@@ -30,7 +29,7 @@ export class Storage extends React.Component<Props> {
|
||||
path: volumeClaimsRoute.path,
|
||||
})
|
||||
|
||||
if (allowedResources.includes('persistentvolumes')) {
|
||||
if (isAllowedResource('persistentvolumes')) {
|
||||
tabRoutes.push({
|
||||
title: <Trans>Persistent Volumes</Trans>,
|
||||
component: PersistentVolumes,
|
||||
@@ -39,7 +38,7 @@ export class Storage extends React.Component<Props> {
|
||||
});
|
||||
}
|
||||
|
||||
if (allowedResources.includes('storageclasses')) {
|
||||
if (isAllowedResource('storageclasses')) {
|
||||
tabRoutes.push({
|
||||
title: <Trans>Storage Classes</Trans>,
|
||||
component: StorageClasses,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import "./user-management.scss"
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Redirect, Route, Switch } from "react-router";
|
||||
@@ -11,8 +10,8 @@ import { RoleBindings } from "../+user-management-roles-bindings";
|
||||
import { ServiceAccounts } from "../+user-management-service-accounts";
|
||||
import { roleBindingsRoute, roleBindingsURL, rolesRoute, rolesURL, serviceAccountsRoute, serviceAccountsURL, usersManagementURL } from "./user-management.routes";
|
||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||
import { configStore } from "../../config.store";
|
||||
import { PodSecurityPolicies, podSecurityPoliciesRoute, podSecurityPoliciesURL } from "../+pod-security-policies";
|
||||
import { isAllowedResource } from "../../api/rbac";
|
||||
|
||||
interface Props extends RouteComponentProps<{}> {
|
||||
}
|
||||
@@ -21,7 +20,6 @@ interface Props extends RouteComponentProps<{}> {
|
||||
export class UserManagement extends React.Component<Props> {
|
||||
static get tabRoutes() {
|
||||
const tabRoutes: TabRoute[] = [];
|
||||
const { allowedResources } = configStore;
|
||||
const query = namespaceStore.getContextParams()
|
||||
tabRoutes.push(
|
||||
{
|
||||
@@ -43,7 +41,7 @@ export class UserManagement extends React.Component<Props> {
|
||||
path: rolesRoute.path,
|
||||
},
|
||||
)
|
||||
if (allowedResources.includes("podsecuritypolicies")) {
|
||||
if (isAllowedResource("podsecuritypolicies")) {
|
||||
tabRoutes.push({
|
||||
title: <Trans>Pod Security Policies</Trans>,
|
||||
component: PodSecurityPolicies,
|
||||
|
||||
@@ -15,13 +15,11 @@ import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
|
||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||
import { PageFiltersList } from "../item-object-list/page-filters-list";
|
||||
import { NamespaceSelectFilter } from "../+namespaces/namespace-select";
|
||||
import { configStore } from "../../config.store";
|
||||
import { isAllowedResource } from "../../api/rbac";
|
||||
|
||||
@observer
|
||||
export class OverviewStatuses extends React.Component {
|
||||
render() {
|
||||
const { allowedResources } = configStore;
|
||||
const { contextNs } = namespaceStore;
|
||||
const pods = isAllowedResource("pods") ? podsStore.getAllByNs(contextNs) : [];
|
||||
const deployments = isAllowedResource("deployments") ? deploymentStore.getAllByNs(contextNs) : [];
|
||||
@@ -37,37 +35,37 @@ export class OverviewStatuses extends React.Component {
|
||||
</div>
|
||||
<PageFiltersList/>
|
||||
<div className="workloads">
|
||||
{ isAllowedResource("pods") &&
|
||||
{isAllowedResource("pods") &&
|
||||
<div className="workload">
|
||||
<div className="title"><Link to={podsURL()}><Trans>Pods</Trans> ({pods.length})</Link></div>
|
||||
<OverviewWorkloadStatus status={podsStore.getStatuses(pods)}/>
|
||||
</div>
|
||||
}
|
||||
{ isAllowedResource("deployments") &&
|
||||
{isAllowedResource("deployments") &&
|
||||
<div className="workload">
|
||||
<div className="title"><Link to={deploymentsURL()}><Trans>Deployments</Trans> ({deployments.length})</Link></div>
|
||||
<OverviewWorkloadStatus status={deploymentStore.getStatuses(deployments)}/>
|
||||
</div>
|
||||
}
|
||||
{ isAllowedResource("statefulsets") &&
|
||||
{isAllowedResource("statefulsets") &&
|
||||
<div className="workload">
|
||||
<div className="title"><Link to={statefulSetsURL()}><Trans>StatefulSets</Trans> ({statefulSets.length})</Link></div>
|
||||
<OverviewWorkloadStatus status={statefulSetStore.getStatuses(statefulSets)}/>
|
||||
</div>
|
||||
}
|
||||
{ isAllowedResource("daemonsets") &&
|
||||
{isAllowedResource("daemonsets") &&
|
||||
<div className="workload">
|
||||
<div className="title"><Link to={daemonSetsURL()}><Trans>DaemonSets</Trans> ({daemonSets.length})</Link></div>
|
||||
<OverviewWorkloadStatus status={daemonSetStore.getStatuses(daemonSets)}/>
|
||||
</div>
|
||||
}
|
||||
{ isAllowedResource("jobs") &&
|
||||
{isAllowedResource("jobs") &&
|
||||
<div className="workload">
|
||||
<div className="title"><Link to={jobsURL()}><Trans>Jobs</Trans> ({jobs.length})</Link></div>
|
||||
<OverviewWorkloadStatus status={jobStore.getStatuses(jobs)}/>
|
||||
</div>
|
||||
}
|
||||
{ isAllowedResource("cronjobs") &&
|
||||
{isAllowedResource("cronjobs") &&
|
||||
<div className="workload">
|
||||
<div className="title"><Link to={cronJobsURL()}><Trans>CronJobs</Trans> ({cronJobs.length})</Link></div>
|
||||
<OverviewWorkloadStatus status={cronJobStore.getStatuses(cronJobs)}/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import "./app.scss";
|
||||
import React from "react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { computed, observable, reaction } from "mobx";
|
||||
import { Redirect, Route, Switch } from "react-router";
|
||||
import { Notifications } from "./notifications";
|
||||
import { NotFound } from "./+404";
|
||||
@@ -31,14 +32,12 @@ import { LandingPage, landingRoute, landingURL } from "./+landing-page";
|
||||
import { ClusterSettings, clusterSettingsRoute } from "./+cluster-settings";
|
||||
import { Workspaces, workspacesRoute } from "./+workspaces";
|
||||
import { ErrorBoundary } from "./error-boundary";
|
||||
import { computed, observable, reaction } from "mobx";
|
||||
import { configStore } from "../config.store";
|
||||
import { navigation } from "../navigation";
|
||||
import { clusterIpc } from "../../common/cluster-ipc";
|
||||
import { clusterStore } from "../../common/cluster-store";
|
||||
import { ClusterStatus } from "./cluster-manager/cluster-status";
|
||||
import { clusterStatusRoute, clusterStatusURL } from "./cluster-manager/cluster-status.route";
|
||||
import { Preferences, preferencesRoute } from "./+preferences";
|
||||
import { navigation } from "../navigation";
|
||||
import { ClusterStatus } from "./cluster-manager/cluster-status";
|
||||
import { CubeSpinner } from "./spinner";
|
||||
|
||||
@observer
|
||||
@@ -52,7 +51,6 @@ export class App extends React.Component {
|
||||
|
||||
async componentDidMount() {
|
||||
await clusterIpc.activate.invokeFromRenderer();
|
||||
await configStore.init();
|
||||
this.appReady = true;
|
||||
|
||||
disposeOnUnmount(this, [
|
||||
|
||||
@@ -6,7 +6,6 @@ import { TerminalApi } from "../../api/terminal-api";
|
||||
import { dockStore, IDockTab, TabId, TabKind } from "./dock.store";
|
||||
import { WebSocketApiState } from "../../api/websocket-api";
|
||||
import { _i18n } from "../../i18n";
|
||||
import { themeStore } from "../../theme.store";
|
||||
|
||||
export interface ITerminalTab extends IDockTab {
|
||||
node?: string; // activate node shell mode
|
||||
@@ -16,7 +15,6 @@ export function isTerminalTab(tab: IDockTab) {
|
||||
return tab && tab.kind === TabKind.TERMINAL;
|
||||
}
|
||||
|
||||
|
||||
export function createTerminalTab(tabParams: Partial<ITerminalTab> = {}) {
|
||||
return dockStore.createTab({
|
||||
kind: TabKind.TERMINAL,
|
||||
@@ -56,7 +54,6 @@ export class TerminalStore {
|
||||
const api = new TerminalApi({
|
||||
id: tabId,
|
||||
node: tab.node,
|
||||
colorTheme: themeStore.activeTheme.type
|
||||
});
|
||||
const terminal = new Terminal(tabId, api);
|
||||
this.connections.set(tabId, api);
|
||||
|
||||
@@ -19,7 +19,6 @@ import { PageFiltersList } from "./page-filters-list";
|
||||
import { PageFiltersSelect } from "./page-filters-select";
|
||||
import { NamespaceSelectFilter } from "../+namespaces/namespace-select";
|
||||
import { themeStore } from "../../theme.store";
|
||||
import { configStore } from "../../config.store";
|
||||
|
||||
// todo: refactor, split to small re-usable components
|
||||
|
||||
@@ -116,7 +115,6 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
const stores = [store, ...dependentStores];
|
||||
if (!isClusterScoped) stores.push(namespaceStore);
|
||||
try {
|
||||
await when(() => configStore.isLoaded); // todo: remove
|
||||
await Promise.all(stores.map(store => store.loadAll()));
|
||||
const subscriptions = stores.map(store => store.subscribe());
|
||||
await when(() => this.isUnmounting);
|
||||
|
||||
@@ -7,11 +7,11 @@ import { matchPath, RouteProps } from "react-router-dom";
|
||||
import { createStorage, cssNames } from "../../utils";
|
||||
import { Tab, Tabs } from "../tabs";
|
||||
import { Sidebar } from "./sidebar";
|
||||
import { configStore } from "../../config.store";
|
||||
import { ErrorBoundary } from "../error-boundary";
|
||||
import { Dock } from "../dock";
|
||||
import { navigate, navigation } from "../../navigation";
|
||||
import { themeStore } from "../../theme.store";
|
||||
import { clusterStore } from "../../../common/cluster-store";
|
||||
|
||||
export interface TabRoute extends RouteProps {
|
||||
title: React.ReactNode;
|
||||
@@ -47,14 +47,12 @@ export class MainLayout extends React.Component<Props> {
|
||||
|
||||
render() {
|
||||
const { className, contentClass, headerClass, tabs, footer, footerClass, children } = this.props;
|
||||
const { clusterName } = configStore.config;
|
||||
const { pathname } = navigation.location;
|
||||
const clusterName = clusterStore.activeCluster?.contextName;
|
||||
const routePath = navigation.location.pathname;
|
||||
return (
|
||||
<div className={cssNames("MainLayout", className, themeStore.activeTheme.type)}>
|
||||
<header className={cssNames("flex gaps align-center", headerClass)}>
|
||||
<div className="box grow flex align-center">
|
||||
{clusterName && <span>{clusterName}</span>}
|
||||
</div>
|
||||
<span className="cluster">{clusterName}</span>
|
||||
</header>
|
||||
|
||||
<aside className={cssNames("flex column", { pinned: this.isPinned, accessible: this.isAccessible })}>
|
||||
@@ -68,7 +66,7 @@ export class MainLayout extends React.Component<Props> {
|
||||
{tabs && (
|
||||
<Tabs center onChange={url => navigate(url)}>
|
||||
{tabs.map(({ title, path, url, ...routeProps }) => {
|
||||
const isActive = !!matchPath(pathname, { path, ...routeProps });
|
||||
const isActive = !!matchPath(routePath, { path, ...routeProps });
|
||||
return <Tab key={url} label={title} value={url} active={isActive}/>
|
||||
})}
|
||||
</Tabs>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import type { IConfigRoutePayload } from "../main/routes/config-route";
|
||||
import { observable, when } from "mobx";
|
||||
import { autobind, interval } from "./utils";
|
||||
import { apiBase } from "./api";
|
||||
|
||||
@autobind()
|
||||
export class ConfigStore {
|
||||
protected updater = interval(60, this.load);
|
||||
|
||||
@observable config: Partial<IConfigRoutePayload> = {};
|
||||
@observable isLoaded = false;
|
||||
|
||||
async init() {
|
||||
await this.load();
|
||||
this.updater.start();
|
||||
}
|
||||
|
||||
load() {
|
||||
if (location.hostname === "no-clusters.localhost") {
|
||||
return;
|
||||
}
|
||||
return apiBase.get("/config").then((config: IConfigRoutePayload) => {
|
||||
this.config = config;
|
||||
this.isLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
async getToken() {
|
||||
await when(() => this.isLoaded);
|
||||
return this.config.token;
|
||||
}
|
||||
|
||||
get allowedNamespaces() {
|
||||
return this.config.allowedNamespaces || [];
|
||||
}
|
||||
|
||||
get allowedResources() {
|
||||
return this.config.allowedResources || [];
|
||||
}
|
||||
|
||||
get isClusterAdmin() {
|
||||
return this.config.isClusterAdmin;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.isLoaded = false;
|
||||
this.config = {};
|
||||
}
|
||||
}
|
||||
|
||||
export const configStore = new ConfigStore();
|
||||
@@ -3,10 +3,10 @@ import { autobind } from "./utils";
|
||||
import { KubeObject } from "./api/kube-object";
|
||||
import { IKubeWatchEvent, kubeWatchApi } from "./api/kube-watch-api";
|
||||
import { ItemStore } from "./item.store";
|
||||
import { configStore } from "./config.store";
|
||||
import { apiManager } from "./api/api-manager";
|
||||
import { IKubeApiQueryParams, KubeApi } from "./api/kube-api";
|
||||
import { KubeJsonApiData } from "./api/kube-json-api";
|
||||
import { clusterStore } from "../common/cluster-store";
|
||||
|
||||
@autobind()
|
||||
export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemStore<T> {
|
||||
@@ -23,8 +23,7 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
const namespaces: string[] = [].concat(namespace);
|
||||
if (namespaces.length) {
|
||||
return this.items.filter(item => namespaces.includes(item.getNs()));
|
||||
}
|
||||
else if (!strict) {
|
||||
} else if (!strict) {
|
||||
return this.items;
|
||||
}
|
||||
}
|
||||
@@ -47,8 +46,7 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
const itemLabels = item.getLabels();
|
||||
return labels.every(label => itemLabels.includes(label));
|
||||
})
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return this.items.filter((item: T) => {
|
||||
const itemLabels = item.metadata.labels || {};
|
||||
return Object.entries(labels)
|
||||
@@ -62,8 +60,7 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
const { limit } = this;
|
||||
const query: IKubeApiQueryParams = limit ? { limit } : {};
|
||||
return this.api.list({}, query);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return Promise
|
||||
.all(allowedNamespaces.map(namespace => this.api.list({ namespace })))
|
||||
.then(items => items.flat())
|
||||
@@ -79,8 +76,8 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
this.isLoading = true;
|
||||
let items: T[];
|
||||
try {
|
||||
const { isClusterAdmin, allowedNamespaces } = configStore;
|
||||
items = await this.loadItems(!isClusterAdmin ? allowedNamespaces : null);
|
||||
const { isAdmin, allowedNamespaces } = clusterStore.activeCluster;
|
||||
items = await this.loadItems(!isAdmin ? allowedNamespaces : null);
|
||||
items = this.filterItemsOnLoad(items);
|
||||
} finally {
|
||||
if (items) {
|
||||
@@ -180,8 +177,7 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
const newItem = new api.objectConstructor(object);
|
||||
if (!item) {
|
||||
items.push(newItem);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
items.splice(index, 1, newItem);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in new issue
Block a user