mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Mobx-6 migration (#2718)
* mobx-6 migration -- part 1 Signed-off-by: Roman <ixrock@gmail.com> * mobx-6 migration -- part 2 (npx mobx-undecorate --keepDecorators) Signed-off-by: Roman <ixrock@gmail.com> * mobx-6 migration -- part 3 (more fixes) Signed-off-by: Roman <ixrock@gmail.com> * unwrap possible observables from IPC-messaging Signed-off-by: Roman <ixrock@gmail.com> * mobx-6 migration -- remove @autobind as class-decorator Signed-off-by: Roman <ixrock@gmail.com> * mobx-6: replacing @autobind() as method-decorator to @boundMethod Signed-off-by: Roman <ixrock@gmail.com> * mobx-6: use toJS()-wrapper since monkey-patching require(mobx).toJS doesn't work Signed-off-by: Roman <ixrock@gmail.com> * removed `@observable static` Signed-off-by: Roman <ixrock@gmail.com> * use {useDefineForClassFields: true} in tsconfig.json Signed-off-by: Roman <ixrock@gmail.com> * remove ExtendedObservableMap Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix: removed makeObservable(this) from "terminal-tab.tsx" Signed-off-by: Roman <ixrock@gmail.com> * storage-helper refactoring Signed-off-by: Roman <ixrock@gmail.com> * normalize usages of #observable-value.toJSON() / attempt to catch the wind Signed-off-by: Roman <ixrock@gmail.com> * refactoring, more possible branch fixes + lint Signed-off-by: Roman <ixrock@gmail.com> * debugging cluster-view error -- part 1 Signed-off-by: Roman <ixrock@gmail.com> * fix: refreshing cluster-view on ready Signed-off-by: Roman <ixrock@gmail.com> * fix: various app-crashes related to KubeObject.spec.* access from "undefined" fix: config-map-details crash Signed-off-by: Roman <ixrock@gmail.com> * fix: namespace-store refactoring / saving selected-namespaces to external json-file Signed-off-by: Roman <ixrock@gmail.com> * fix: don't cache mobx.when(() => this.someObservable) cause might not work as expected due later call of makeObservable(this) in constructor Signed-off-by: Roman <ixrock@gmail.com> * fix: app-crash on editing k8s resource Signed-off-by: Roman <ixrock@gmail.com> * fix: restore "all namespaces" on page reload Signed-off-by: Roman <ixrock@gmail.com> * - fix: persist table-sort params and cluster-view's sidebar state to lens-local-storage - new-feature: auto-open main-window's devtools in development-mode (yes/no/ugly?) Signed-off-by: Roman <ixrock@gmail.com> * fix: crd definition details -> crashing with <AceEditor mode="json"> (added missing mode-file in ace-editor.tsx) Signed-off-by: Roman <ixrock@gmail.com> * fix: crd definitions -> groups selector couldn't deselect last selected option Signed-off-by: Roman <ixrock@gmail.com> * refactoring: extensions-api exports clarification for "@k8slens/extensions" Signed-off-by: Roman <ixrock@gmail.com> * fix: various app-crashes related to kube-events (events page, some details page, overview, etc.) Signed-off-by: Roman <ixrock@gmail.com> * Reverted "use {useDefineForClassFields: true} in tsconfig.json" (various app-crash fixes) This flag seems to be not possible to use with class-inheritance in some cases. Example / demo: `KubeObject` class has initial type definitions for the fields like: "metadata", "kind", etc. and constructor() has Object.assign(this, data); Meanwhile child class, e.g. KubeEvent inherited from KubeObject and has it's own extra type definitions for underlying resource, e.g. "involvedObject", "source", etc. So calling super(data) doesn't work as expected for child class as it's own type definitions overwrites data from parent's constructor with `undefined` at later point. Signed-off-by: Roman <ixrock@gmail.com> * master-merge lint-fixes Signed-off-by: Roman <ixrock@gmail.com> * catalog.tsx / catalog-entities.store.ts refactoring & fixes Signed-off-by: Roman <ixrock@gmail.com> * fix: Catalog -> Browse all tab Signed-off-by: Roman <ixrock@gmail.com> * fix: CommandPalette doesn't appear from global menu by click/hotkey Signed-off-by: Roman <ixrock@gmail.com> * - Merging interfaces & classses to avoid overwriting fields from parent's super(data)-call with Object.assign(this, data). Otherwise use "declare" keyword at class field definition. - Revamping {useDefineForClassFields: true} to avoid issues with non-observable class fields in some cases (from previous commit): ``` @observer export class CommandContainer extends React.Component<CommandContainerProps> { // without some defined initial value "commandComponent" is non-observable for some reasons // when tsconfig.ts has {useDefineForClassFields:false} @observable.ref commandComponent: React.ReactNode = null; constructor(props: CommandContainerProps) { super(props); makeObservable(this); } ``` Signed-off-by: Roman <ixrock@gmail.com> * update KubeObject class type definition Signed-off-by: Roman <ixrock@gmail.com> * clean up / responding to comments Signed-off-by: Roman <ixrock@gmail.com> * fix: app-crash when navigating to catalog from active cluster-view, refactoring `catalog-entity-store` Signed-off-by: Roman <ixrock@gmail.com> * catalog-pusher clean up, replaced .observe_() to external observe() helper from "mobx" Signed-off-by: Roman <ixrock@gmail.com> * fix: catalog's items stale/non-observable (after connection to the cluster status still "disconnected"), lint-fixes Signed-off-by: Roman <ixrock@gmail.com> * fix: Catalog is empty after closing main-window and re-opening app from Tray Signed-off-by: Roman <ixrock@gmail.com> * fix: HotBar's icon context menu items non-observable (no "disconnect cluster", etc.) Signed-off-by: Roman <ixrock@gmail.com> * lint-fix/license check Signed-off-by: Roman <ixrock@gmail.com> * fix: redirect to catalog when disconnecting active cluster Signed-off-by: Roman <ixrock@gmail.com> * fix: refresh visibility of active cluster-view on switching from hotbar/catalog Signed-off-by: Roman <ixrock@gmail.com> * updated package.json for built-in extensions to use "*" version for packages served from main app Signed-off-by: Roman <ixrock@gmail.com> * - added missing makeObservable(this) to metrics-settings.tsx - updated package-lock.json for built-in extensions - lint fixes Signed-off-by: Roman <ixrock@gmail.com> * master-merge clean up fix, updated package-lock.json for built-in extensions after `make clean-extensions && make build-extensions` Signed-off-by: Roman <ixrock@gmail.com> * fix unit-tests Signed-off-by: Roman <ixrock@gmail.com> * master-merge fixes Signed-off-by: Roman <ixrock@gmail.com> * make lint happy Signed-off-by: Roman <ixrock@gmail.com> * reverted some changes, removed auto-opening devtools in dev-mode Signed-off-by: Roman <ixrock@gmail.com> * merge fixes Signed-off-by: Roman <ixrock@gmail.com> * master-merge conflict fixes: - proper handling and navigating into catalog's active category via URL-builder Signed-off-by: Roman <ixrock@gmail.com> * reverting splitted params for catalog's page route to "/catalog/:group?/:kind?" Signed-off-by: Roman <ixrock@gmail.com> * clean-up: remove app's injecting dependencies from `extensions/kube-object-event-status/package.json` Signed-off-by: Roman <ixrock@gmail.com> * master-merge fix: added missing makeObservable(this) for extensions.tsx Signed-off-by: Roman <ixrock@gmail.com> * fix: catalog entity context menu stale/unobservable Signed-off-by: Roman <ixrock@gmail.com> Co-authored-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
1 parent
0c45dd807e
commit
2c3b510997
256 files changed
+2359
-1473
No files matched your search
@@ -21,15 +21,19 @@
|
||||
|
||||
import type { KubeObjectStore } from "../kube-object.store";
|
||||
|
||||
import { action, observable } from "mobx";
|
||||
import { autobind } from "../utils";
|
||||
import { action, observable, makeObservable } from "mobx";
|
||||
import { autoBind } from "../utils";
|
||||
import { KubeApi, parseKubeApi } from "./kube-api";
|
||||
|
||||
@autobind()
|
||||
export class ApiManager {
|
||||
private apis = observable.map<string, KubeApi>();
|
||||
private stores = observable.map<string, KubeObjectStore>();
|
||||
|
||||
constructor() {
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getApi(pathOrCallback: string | ((api: KubeApi) => boolean)) {
|
||||
if (typeof pathOrCallback === "string") {
|
||||
return this.apis.get(pathOrCallback) || this.apis.get(parseKubeApi(pathOrCallback).apiBase);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { computed, observable } from "mobx";
|
||||
import { computed, observable, makeObservable } from "mobx";
|
||||
import { subscribeToBroadcast } from "../../common/ipc";
|
||||
import { CatalogCategory, CatalogEntity, CatalogEntityData, catalogCategoryRegistry, CatalogCategoryRegistry, CatalogEntityKindData } from "../../common/catalog";
|
||||
import "../../common/catalog-entities";
|
||||
@@ -29,7 +29,9 @@ export class CatalogEntityRegistry {
|
||||
protected rawItems = observable.array<CatalogEntityData & CatalogEntityKindData>([], { deep: true });
|
||||
@observable protected _activeEntity: CatalogEntity;
|
||||
|
||||
constructor(private categoryRegistry: CatalogCategoryRegistry) {}
|
||||
constructor(private categoryRegistry: CatalogCategoryRegistry) {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
init() {
|
||||
subscribeToBroadcast("catalog:items", (ev, items: (CatalogEntityData & CatalogEntityKindData)[]) => {
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { Role } from "./role.api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
|
||||
@autobind()
|
||||
export class ClusterRole extends Role {
|
||||
static kind = "ClusterRole";
|
||||
static namespaced = false;
|
||||
|
||||
@@ -71,10 +71,7 @@ export interface IClusterMetrics<T = IMetrics> {
|
||||
fsUsage: T;
|
||||
}
|
||||
|
||||
export class Cluster extends KubeObject {
|
||||
static kind = "Cluster";
|
||||
static apiBase = "/apis/cluster.k8s.io/v1alpha1/clusters";
|
||||
|
||||
export interface Cluster {
|
||||
spec: {
|
||||
clusterNetwork?: {
|
||||
serviceDomain?: string;
|
||||
@@ -106,6 +103,11 @@ export class Cluster extends KubeObject {
|
||||
errorMessage?: string;
|
||||
errorReason?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class Cluster extends KubeObject {
|
||||
static kind = "Cluster";
|
||||
static apiBase = "/apis/cluster.k8s.io/v1alpha1/clusters";
|
||||
|
||||
getStatus() {
|
||||
if (this.metadata.deletionTimestamp) return ClusterStatus.REMOVING;
|
||||
|
||||
@@ -28,13 +28,15 @@ export interface IComponentStatusCondition {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface ComponentStatus {
|
||||
conditions: IComponentStatusCondition[];
|
||||
}
|
||||
|
||||
export class ComponentStatus extends KubeObject {
|
||||
static kind = "ComponentStatus";
|
||||
static namespaced = false;
|
||||
static apiBase = "/api/v1/componentstatuses";
|
||||
|
||||
conditions: IComponentStatusCondition[];
|
||||
|
||||
getTruthyConditions() {
|
||||
return this.conditions.filter(c => c.status === "True");
|
||||
}
|
||||
|
||||
@@ -21,10 +21,15 @@
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
import { autobind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import { autoBind } from "../../../common/utils";
|
||||
|
||||
export interface ConfigMap {
|
||||
data: {
|
||||
[param: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class ConfigMap extends KubeObject {
|
||||
static kind = "ConfigMap";
|
||||
static namespaced = true;
|
||||
@@ -32,12 +37,10 @@ export class ConfigMap extends KubeObject {
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
this.data = this.data || {};
|
||||
}
|
||||
autoBind(this);
|
||||
|
||||
data: {
|
||||
[param: string]: string;
|
||||
};
|
||||
this.data ??= {};
|
||||
}
|
||||
|
||||
getKeys(): string[] {
|
||||
return Object.keys(this.data);
|
||||
|
||||
@@ -38,11 +38,7 @@ type AdditionalPrinterColumnsV1Beta = AdditionalPrinterColumnsCommon & {
|
||||
JSONPath: string;
|
||||
};
|
||||
|
||||
export class CustomResourceDefinition extends KubeObject {
|
||||
static kind = "CustomResourceDefinition";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions";
|
||||
|
||||
export interface CustomResourceDefinition {
|
||||
spec: {
|
||||
group: string;
|
||||
version?: string; // deprecated in v1 api
|
||||
@@ -84,6 +80,12 @@ export class CustomResourceDefinition extends KubeObject {
|
||||
};
|
||||
storedVersions: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export class CustomResourceDefinition extends KubeObject {
|
||||
static kind = "CustomResourceDefinition";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions";
|
||||
|
||||
getResourceUrl() {
|
||||
return crdResourcesURL({
|
||||
|
||||
@@ -23,8 +23,9 @@ import moment from "moment";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import type { IPodContainer } from "./pods.api";
|
||||
import { formatDuration } from "../../utils/formatDuration";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class CronJobApi extends KubeApi<CronJob> {
|
||||
suspend(params: { namespace: string; name: string }) {
|
||||
@@ -58,28 +59,7 @@ export class CronJobApi extends KubeApi<CronJob> {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class CronJob extends KubeObject {
|
||||
static kind = "CronJob";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/batch/v1beta1/cronjobs";
|
||||
|
||||
kind: string;
|
||||
apiVersion: string;
|
||||
metadata: {
|
||||
name: string;
|
||||
namespace: string;
|
||||
selfLink: string;
|
||||
uid: string;
|
||||
resourceVersion: string;
|
||||
creationTimestamp: string;
|
||||
labels: {
|
||||
[key: string]: string;
|
||||
};
|
||||
annotations: {
|
||||
[key: string]: string;
|
||||
};
|
||||
};
|
||||
export interface CronJob {
|
||||
spec: {
|
||||
schedule: string;
|
||||
concurrencyPolicy: string;
|
||||
@@ -116,6 +96,17 @@ export class CronJob extends KubeObject {
|
||||
status: {
|
||||
lastScheduleTime?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class CronJob extends KubeObject {
|
||||
static kind = "CronJob";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/batch/v1beta1/cronjobs";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getSuspendFlag() {
|
||||
return this.spec.suspend.toString();
|
||||
|
||||
@@ -22,16 +22,21 @@
|
||||
import get from "lodash/get";
|
||||
import type { IPodContainer } from "./pods.api";
|
||||
import { IAffinity, WorkloadKubeObject } from "../workload-kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
@autobind()
|
||||
export class DaemonSet extends WorkloadKubeObject {
|
||||
static kind = "DaemonSet";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/apps/v1/daemonsets";
|
||||
|
||||
spec: {
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
declare spec: {
|
||||
selector: {
|
||||
matchLabels: {
|
||||
[name: string]: string;
|
||||
@@ -73,7 +78,7 @@ export class DaemonSet extends WorkloadKubeObject {
|
||||
};
|
||||
revisionHistoryLimit: number;
|
||||
};
|
||||
status: {
|
||||
declare status: {
|
||||
currentNumberScheduled: number;
|
||||
numberMisscheduled: number;
|
||||
desiredNumberScheduled: number;
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
import moment from "moment";
|
||||
|
||||
import { IAffinity, WorkloadKubeObject } from "../workload-kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class DeploymentApi extends KubeApi<Deployment> {
|
||||
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||
@@ -87,13 +88,17 @@ interface IContainerProbe {
|
||||
failureThreshold?: number;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class Deployment extends WorkloadKubeObject {
|
||||
static kind = "Deployment";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/apps/v1/deployments";
|
||||
|
||||
spec: {
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
declare spec: {
|
||||
replicas: number;
|
||||
selector: { matchLabels: { [app: string]: string } };
|
||||
template: {
|
||||
@@ -172,7 +177,7 @@ export class Deployment extends WorkloadKubeObject {
|
||||
};
|
||||
};
|
||||
};
|
||||
status: {
|
||||
declare status: {
|
||||
observedGeneration: number;
|
||||
replicas: number;
|
||||
updatedReplicas: number;
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export interface IEndpointPort {
|
||||
name?: string;
|
||||
@@ -121,13 +122,19 @@ export class EndpointSubset implements IEndpointSubset {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export interface Endpoint {
|
||||
subsets: IEndpointSubset[];
|
||||
}
|
||||
|
||||
export class Endpoint extends KubeObject {
|
||||
static kind = "Endpoints";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/endpoints";
|
||||
|
||||
subsets: IEndpointSubset[];
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getEndpointSubsets(): EndpointSubset[] {
|
||||
const subsets = this.subsets || [];
|
||||
|
||||
@@ -22,15 +22,9 @@
|
||||
import moment from "moment";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { formatDuration } from "../../utils/formatDuration";
|
||||
import { autobind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
|
||||
@autobind()
|
||||
export class KubeEvent extends KubeObject {
|
||||
static kind = "Event";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/events";
|
||||
|
||||
export interface KubeEvent {
|
||||
involvedObject: {
|
||||
kind: string;
|
||||
namespace: string;
|
||||
@@ -53,6 +47,12 @@ export class KubeEvent extends KubeObject {
|
||||
eventTime: null;
|
||||
reportingComponent: string;
|
||||
reportingInstance: string;
|
||||
}
|
||||
|
||||
export class KubeEvent extends KubeObject {
|
||||
static kind = "Event";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/events";
|
||||
|
||||
isWarning() {
|
||||
return this.type === "Warning";
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import { compile } from "path-to-regexp";
|
||||
import { apiBase } from "../index";
|
||||
import { stringify } from "querystring";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
|
||||
export type RepoHelmChartList = Record<string, HelmChart[]>;
|
||||
export type HelmChartList = Record<string, RepoHelmChartList>;
|
||||
@@ -83,16 +83,7 @@ export async function getChartValues(repo: string, name: string, version: string
|
||||
return apiBase.get<string>(`/v2/charts/${repo}/${name}/values?${stringify({ version })}`);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class HelmChart {
|
||||
constructor(data: any) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
||||
static create(data: any) {
|
||||
return new HelmChart(data);
|
||||
}
|
||||
|
||||
export interface HelmChart {
|
||||
apiVersion: string;
|
||||
name: string;
|
||||
version: string;
|
||||
@@ -114,6 +105,17 @@ export class HelmChart {
|
||||
appVersion?: string;
|
||||
deprecated?: boolean;
|
||||
tillerVersion?: string;
|
||||
}
|
||||
|
||||
export class HelmChart {
|
||||
constructor(data: HelmChart) {
|
||||
Object.assign(this, data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
static create(data: any) {
|
||||
return new HelmChart(data);
|
||||
}
|
||||
|
||||
getId() {
|
||||
return `${this.repo}:${this.apiVersion}/${this.name}@${this.getAppVersion()}+${this.digest}`;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
import jsYaml from "js-yaml";
|
||||
import { compile } from "path-to-regexp";
|
||||
import { autobind, formatDuration } from "../../utils";
|
||||
import { autoBind, formatDuration } from "../../utils";
|
||||
import capitalize from "lodash/capitalize";
|
||||
import { apiBase } from "../index";
|
||||
import { helmChartStore } from "../../components/+apps-helm-charts/helm-chart.store";
|
||||
@@ -155,16 +155,7 @@ export async function rollbackRelease(name: string, namespace: string, revision:
|
||||
});
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class HelmRelease implements ItemObject {
|
||||
constructor(data: any) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
||||
static create(data: any) {
|
||||
return new HelmRelease(data);
|
||||
}
|
||||
|
||||
export interface HelmRelease {
|
||||
appVersion: string;
|
||||
name: string;
|
||||
namespace: string;
|
||||
@@ -172,6 +163,17 @@ export class HelmRelease implements ItemObject {
|
||||
status: string;
|
||||
updated: string;
|
||||
revision: string;
|
||||
}
|
||||
|
||||
export class HelmRelease implements ItemObject {
|
||||
constructor(data: any) {
|
||||
Object.assign(this, data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
static create(data: any) {
|
||||
return new HelmRelease(data);
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.namespace + this.name;
|
||||
|
||||
@@ -59,11 +59,7 @@ export interface IHpaMetric {
|
||||
}>;
|
||||
}
|
||||
|
||||
export class HorizontalPodAutoscaler extends KubeObject {
|
||||
static kind = "HorizontalPodAutoscaler";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/autoscaling/v2beta1/horizontalpodautoscalers";
|
||||
|
||||
export interface HorizontalPodAutoscaler {
|
||||
spec: {
|
||||
scaleTargetRef: {
|
||||
kind: string;
|
||||
@@ -86,6 +82,12 @@ export class HorizontalPodAutoscaler extends KubeObject {
|
||||
type: string;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
export class HorizontalPodAutoscaler extends KubeObject {
|
||||
static kind = "HorizontalPodAutoscaler";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/autoscaling/v2beta1/horizontalpodautoscalers";
|
||||
|
||||
getMaxPods() {
|
||||
return this.spec.maxReplicas || 0;
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
*/
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { IMetrics, metricsApi } from "./metrics.api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class IngressApi extends KubeApi<Ingress> {
|
||||
getMetrics(ingress: string, namespace: string): Promise<IIngressMetrics> {
|
||||
@@ -82,12 +83,7 @@ export const getBackendServiceNamePort = (backend: IIngressBackend) => {
|
||||
return { serviceName, servicePort };
|
||||
};
|
||||
|
||||
@autobind()
|
||||
export class Ingress extends KubeObject {
|
||||
static kind = "Ingress";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/networking.k8s.io/v1/ingresses";
|
||||
|
||||
export interface Ingress {
|
||||
spec: {
|
||||
tls: {
|
||||
secretName: string;
|
||||
@@ -117,6 +113,17 @@ export class Ingress extends KubeObject {
|
||||
ingress: ILoadBalancerIngress[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export class Ingress extends KubeObject {
|
||||
static kind = "Ingress";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/networking.k8s.io/v1/ingresses";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getRoutes() {
|
||||
const { spec: { tls, rules } } = this;
|
||||
@@ -188,7 +195,7 @@ export class Ingress extends KubeObject {
|
||||
|
||||
getLoadBalancers() {
|
||||
const { status: { loadBalancer = { ingress: [] } } } = this;
|
||||
|
||||
|
||||
return (loadBalancer.ingress ?? []).map(address => (
|
||||
address.hostname || address.ip
|
||||
));
|
||||
|
||||
@@ -20,19 +20,24 @@
|
||||
*/
|
||||
|
||||
import get from "lodash/get";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { IAffinity, WorkloadKubeObject } from "../workload-kube-object";
|
||||
import type { IPodContainer } from "./pods.api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { JsonApiParams } from "../json-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
@autobind()
|
||||
export class Job extends WorkloadKubeObject {
|
||||
static kind = "Job";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/batch/v1/jobs";
|
||||
|
||||
spec: {
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
declare spec: {
|
||||
parallelism?: number;
|
||||
completions?: number;
|
||||
backoffLimit?: number;
|
||||
@@ -78,7 +83,7 @@ export class Job extends WorkloadKubeObject {
|
||||
serviceAccount?: string;
|
||||
schedulerName?: string;
|
||||
};
|
||||
status: {
|
||||
declare status: {
|
||||
conditions: {
|
||||
type: string;
|
||||
status: string;
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export enum LimitType {
|
||||
CONTAINER = "Container",
|
||||
@@ -50,15 +51,21 @@ export interface LimitRangeItem extends LimitRangeParts {
|
||||
type: string
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export interface LimitRange {
|
||||
spec: {
|
||||
limits: LimitRangeItem[];
|
||||
};
|
||||
}
|
||||
|
||||
export class LimitRange extends KubeObject {
|
||||
static kind = "LimitRange";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/limitranges";
|
||||
|
||||
spec: {
|
||||
limits: LimitRangeItem[];
|
||||
};
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getContainerLimits() {
|
||||
return this.spec.limits.filter(limit => limit.type === LimitType.CONTAINER);
|
||||
|
||||
@@ -21,25 +21,32 @@
|
||||
|
||||
import { KubeApi } from "../kube-api";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export enum NamespaceStatus {
|
||||
ACTIVE = "Active",
|
||||
TERMINATING = "Terminating",
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export interface Namespace {
|
||||
status?: {
|
||||
phase: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class Namespace extends KubeObject {
|
||||
static kind = "Namespace";
|
||||
static namespaced = false;
|
||||
static apiBase = "/api/v1/namespaces";
|
||||
|
||||
status?: {
|
||||
phase: string;
|
||||
};
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getStatus() {
|
||||
return this.status ? this.status.phase : "-";
|
||||
return this.status?.phase ?? "-";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export interface IPolicyIpBlock {
|
||||
cidr: string;
|
||||
@@ -56,12 +57,7 @@ export interface IPolicyEgress {
|
||||
}[];
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class NetworkPolicy extends KubeObject {
|
||||
static kind = "NetworkPolicy";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/networking.k8s.io/v1/networkpolicies";
|
||||
|
||||
export interface NetworkPolicy {
|
||||
spec: {
|
||||
podSelector: {
|
||||
matchLabels: {
|
||||
@@ -73,6 +69,17 @@ export class NetworkPolicy extends KubeObject {
|
||||
ingress: IPolicyIngress[];
|
||||
egress: IPolicyEgress[];
|
||||
};
|
||||
}
|
||||
|
||||
export class NetworkPolicy extends KubeObject {
|
||||
static kind = "NetworkPolicy";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/networking.k8s.io/v1/networkpolicies";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getMatchLabels(): string[] {
|
||||
if (!this.spec.podSelector || !this.spec.podSelector.matchLabels) return [];
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
*/
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { autobind, cpuUnitsToNumber, unitsToBytes } from "../../utils";
|
||||
import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../utils";
|
||||
import { IMetrics, metricsApi } from "./metrics.api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class NodesApi extends KubeApi<Node> {
|
||||
getMetrics(): Promise<INodeMetrics> {
|
||||
const opts = { category: "nodes"};
|
||||
const opts = { category: "nodes" };
|
||||
|
||||
return metricsApi.getMetrics({
|
||||
memoryUsage: opts,
|
||||
@@ -49,12 +50,7 @@ export interface INodeMetrics<T = IMetrics> {
|
||||
fsSize: T;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class Node extends KubeObject {
|
||||
static kind = "Node";
|
||||
static namespaced = false;
|
||||
static apiBase = "/api/v1/nodes";
|
||||
|
||||
export interface Node {
|
||||
spec: {
|
||||
podCIDR: string;
|
||||
externalID: string;
|
||||
@@ -105,6 +101,17 @@ export class Node extends KubeObject {
|
||||
sizeBytes: number;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
export class Node extends KubeObject {
|
||||
static kind = "Node";
|
||||
static namespaced = false;
|
||||
static apiBase = "/api/v1/nodes";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getNodeConditionText() {
|
||||
const { conditions } = this.status;
|
||||
|
||||
@@ -20,10 +20,11 @@
|
||||
*/
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { IMetrics, metricsApi } from "./metrics.api";
|
||||
import type { Pod } from "./pods.api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class PersistentVolumeClaimsApi extends KubeApi<PersistentVolumeClaim> {
|
||||
getMetrics(pvcName: string, namespace: string): Promise<IPvcMetrics> {
|
||||
@@ -42,12 +43,7 @@ export interface IPvcMetrics<T = IMetrics> {
|
||||
diskCapacity: T;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class PersistentVolumeClaim extends KubeObject {
|
||||
static kind = "PersistentVolumeClaim";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/persistentvolumeclaims";
|
||||
|
||||
export interface PersistentVolumeClaim {
|
||||
spec: {
|
||||
accessModes: string[];
|
||||
storageClassName: string;
|
||||
@@ -70,6 +66,17 @@ export class PersistentVolumeClaim extends KubeObject {
|
||||
status: {
|
||||
phase: string; // Pending
|
||||
};
|
||||
}
|
||||
|
||||
export class PersistentVolumeClaim extends KubeObject {
|
||||
static kind = "PersistentVolumeClaim";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/persistentvolumeclaims";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getPods(allPods: Pod[]): Pod[] {
|
||||
const pods = allPods.filter(pod => pod.getNs() === this.getNs());
|
||||
|
||||
@@ -21,15 +21,11 @@
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { unitsToBytes } from "../../utils/convertMemory";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
@autobind()
|
||||
export class PersistentVolume extends KubeObject {
|
||||
static kind = "PersistentVolume";
|
||||
static namespaced = false;
|
||||
static apiBase = "/api/v1/persistentvolumes";
|
||||
|
||||
export interface PersistentVolume {
|
||||
spec: {
|
||||
capacity: {
|
||||
storage: string; // 8Gi
|
||||
@@ -65,6 +61,17 @@ export class PersistentVolume extends KubeObject {
|
||||
phase: string;
|
||||
reason?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class PersistentVolume extends KubeObject {
|
||||
static kind = "PersistentVolume";
|
||||
static namespaced = false;
|
||||
static apiBase = "/api/v1/persistentvolumes";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getCapacity(inBytes = false) {
|
||||
const capacity = this.spec.capacity;
|
||||
|
||||
@@ -22,11 +22,7 @@
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
|
||||
export class PodMetrics extends KubeObject {
|
||||
static kind = "PodMetrics";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/metrics.k8s.io/v1beta1/pods";
|
||||
|
||||
export interface PodMetrics {
|
||||
timestamp: string;
|
||||
window: string;
|
||||
containers: {
|
||||
@@ -38,6 +34,12 @@ export class PodMetrics extends KubeObject {
|
||||
}[];
|
||||
}
|
||||
|
||||
export class PodMetrics extends KubeObject {
|
||||
static kind = "PodMetrics";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/metrics.k8s.io/v1beta1/pods";
|
||||
}
|
||||
|
||||
export const podMetricsApi = new KubeApi({
|
||||
objectConstructor: PodMetrics,
|
||||
});
|
||||
@@ -19,16 +19,12 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
@autobind()
|
||||
export class PodDisruptionBudget extends KubeObject {
|
||||
static kind = "PodDisruptionBudget";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/policy/v1beta1/poddisruptionbudgets";
|
||||
|
||||
export interface PodDisruptionBudget {
|
||||
spec: {
|
||||
minAvailable: string;
|
||||
maxUnavailable: string;
|
||||
@@ -40,6 +36,17 @@ export class PodDisruptionBudget extends KubeObject {
|
||||
disruptionsAllowed: number
|
||||
expectedPods: number
|
||||
};
|
||||
}
|
||||
|
||||
export class PodDisruptionBudget extends KubeObject {
|
||||
static kind = "PodDisruptionBudget";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/policy/v1beta1/poddisruptionbudgets";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getSelectors() {
|
||||
const selector = this.spec.selector;
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
*/
|
||||
|
||||
import { IAffinity, WorkloadKubeObject } from "../workload-kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { IMetrics, metricsApi } from "./metrics.api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class PodsApi extends KubeApi<Pod> {
|
||||
async getLogs(params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise<string> {
|
||||
@@ -202,13 +203,17 @@ export interface IPodContainerStatus {
|
||||
started?: boolean;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class Pod extends WorkloadKubeObject {
|
||||
static kind = "Pod";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/pods";
|
||||
|
||||
spec: {
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
declare spec: {
|
||||
volumes?: {
|
||||
name: string;
|
||||
persistentVolumeClaim: {
|
||||
@@ -265,7 +270,7 @@ export class Pod extends WorkloadKubeObject {
|
||||
};
|
||||
affinity?: IAffinity;
|
||||
};
|
||||
status?: {
|
||||
declare status?: {
|
||||
phase: string;
|
||||
conditions: {
|
||||
type: string;
|
||||
|
||||
@@ -19,16 +19,12 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
@autobind()
|
||||
export class PodSecurityPolicy extends KubeObject {
|
||||
static kind = "PodSecurityPolicy";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/policy/v1beta1/podsecuritypolicies";
|
||||
|
||||
export interface PodSecurityPolicy {
|
||||
spec: {
|
||||
allowPrivilegeEscalation?: boolean;
|
||||
allowedCSIDrivers?: {
|
||||
@@ -88,6 +84,17 @@ export class PodSecurityPolicy extends KubeObject {
|
||||
};
|
||||
volumes?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export class PodSecurityPolicy extends KubeObject {
|
||||
static kind = "PodSecurityPolicy";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/policy/v1beta1/podsecuritypolicies";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
isPrivileged() {
|
||||
return !!this.spec.privileged;
|
||||
|
||||
@@ -20,10 +20,11 @@
|
||||
*/
|
||||
|
||||
import get from "lodash/get";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { WorkloadKubeObject } from "../workload-kube-object";
|
||||
import type { IPodContainer, Pod } from "./pods.api";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class ReplicaSetApi extends KubeApi<ReplicaSet> {
|
||||
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||
@@ -48,12 +49,17 @@ export class ReplicaSetApi extends KubeApi<ReplicaSet> {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class ReplicaSet extends WorkloadKubeObject {
|
||||
static kind = "ReplicaSet";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/apps/v1/replicasets";
|
||||
spec: {
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
declare spec: {
|
||||
replicas?: number;
|
||||
selector: { matchLabels: { [app: string]: string } };
|
||||
template?: {
|
||||
@@ -66,7 +72,7 @@ export class ReplicaSet extends WorkloadKubeObject {
|
||||
};
|
||||
minReadySeconds?: number;
|
||||
};
|
||||
status: {
|
||||
declare status: {
|
||||
replicas: number;
|
||||
fullyLabeledReplicas?: number;
|
||||
readyReplicas?: number;
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export interface IResourceQuotaValues {
|
||||
[quota: string]: string;
|
||||
@@ -51,16 +50,7 @@ export interface IResourceQuotaValues {
|
||||
"count/deployments.extensions"?: string;
|
||||
}
|
||||
|
||||
export class ResourceQuota extends KubeObject {
|
||||
static kind = "ResourceQuota";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/resourcequotas";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
this.spec = this.spec || {} as any;
|
||||
}
|
||||
|
||||
export interface ResourceQuota {
|
||||
spec: {
|
||||
hard: IResourceQuotaValues;
|
||||
scopeSelector?: {
|
||||
@@ -76,6 +66,12 @@ export class ResourceQuota extends KubeObject {
|
||||
hard: IResourceQuotaValues;
|
||||
used: IResourceQuotaValues;
|
||||
};
|
||||
}
|
||||
|
||||
export class ResourceQuota extends KubeObject {
|
||||
static kind = "ResourceQuota";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/resourcequotas";
|
||||
|
||||
getScopeSelector() {
|
||||
const { matchExpressions = [] } = this.spec.scopeSelector || {};
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export interface IRoleBindingSubject {
|
||||
kind: string;
|
||||
@@ -30,18 +31,24 @@ export interface IRoleBindingSubject {
|
||||
apiGroup?: string;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class RoleBinding extends KubeObject {
|
||||
static kind = "RoleBinding";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/rbac.authorization.k8s.io/v1/rolebindings";
|
||||
|
||||
export interface RoleBinding {
|
||||
subjects?: IRoleBindingSubject[];
|
||||
roleRef: {
|
||||
kind: string;
|
||||
name: string;
|
||||
apiGroup?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class RoleBinding extends KubeObject {
|
||||
static kind = "RoleBinding";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/rbac.authorization.k8s.io/v1/rolebindings";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getSubjects() {
|
||||
return this.subjects || [];
|
||||
|
||||
@@ -22,17 +22,19 @@
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
|
||||
export class Role extends KubeObject {
|
||||
static kind = "Role";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/rbac.authorization.k8s.io/v1/roles";
|
||||
|
||||
export interface Role {
|
||||
rules: {
|
||||
verbs: string[];
|
||||
apiGroups: string[];
|
||||
resources: string[];
|
||||
resourceNames?: string[];
|
||||
}[];
|
||||
}
|
||||
|
||||
export class Role extends KubeObject {
|
||||
static kind = "Role";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/rbac.authorization.k8s.io/v1/roles";
|
||||
|
||||
getRules() {
|
||||
return this.rules || [];
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
import { KubeObject } from "../kube-object";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
|
||||
export enum SecretType {
|
||||
@@ -40,21 +40,24 @@ export interface ISecretRef {
|
||||
name: string;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class Secret extends KubeObject {
|
||||
static kind = "Secret";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/secrets";
|
||||
|
||||
export interface Secret {
|
||||
type: SecretType;
|
||||
data: {
|
||||
[prop: string]: string;
|
||||
token?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class Secret extends KubeObject {
|
||||
static kind = "Secret";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/secrets";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
this.data = this.data || {};
|
||||
autoBind(this);
|
||||
|
||||
this.data ??= {};
|
||||
}
|
||||
|
||||
getKeys(): string[] {
|
||||
|
||||
@@ -28,8 +28,7 @@ export class SelfSubjectRulesReviewApi extends KubeApi<SelfSubjectRulesReview> {
|
||||
spec: {
|
||||
namespace
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,21 +40,21 @@ export interface ISelfSubjectReviewRule {
|
||||
nonResourceURLs?: string[];
|
||||
}
|
||||
|
||||
export class SelfSubjectRulesReview extends KubeObject {
|
||||
static kind = "SelfSubjectRulesReview";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/authorization.k8s.io/v1/selfsubjectrulesreviews";
|
||||
|
||||
export interface SelfSubjectRulesReview {
|
||||
spec: {
|
||||
// todo: add more types from api docs
|
||||
namespace?: string;
|
||||
};
|
||||
|
||||
status: {
|
||||
resourceRules: ISelfSubjectReviewRule[];
|
||||
nonResourceRules: ISelfSubjectReviewRule[];
|
||||
incomplete: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export class SelfSubjectRulesReview extends KubeObject {
|
||||
static kind = "SelfSubjectRulesReview";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/authorization.k8s.io/v1/selfsubjectrulesreviews";
|
||||
|
||||
getResourceRules() {
|
||||
const rules = this.status && this.status.resourceRules || [];
|
||||
|
||||
@@ -19,22 +19,29 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
@autobind()
|
||||
export class ServiceAccount extends KubeObject {
|
||||
static kind = "ServiceAccount";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/serviceaccounts";
|
||||
|
||||
export interface ServiceAccount {
|
||||
secrets?: {
|
||||
name: string;
|
||||
}[];
|
||||
imagePullSecrets?: {
|
||||
name: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export class ServiceAccount extends KubeObject {
|
||||
static kind = "ServiceAccount";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/serviceaccounts";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getSecrets() {
|
||||
return this.secrets || [];
|
||||
|
||||
@@ -19,25 +19,21 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export interface IServicePort {
|
||||
name?: string;
|
||||
protocol: string;
|
||||
port: number;
|
||||
targetPort: number;
|
||||
}
|
||||
|
||||
export class ServicePort implements IServicePort {
|
||||
export interface ServicePort {
|
||||
name?: string;
|
||||
protocol: string;
|
||||
port: number;
|
||||
targetPort: number;
|
||||
nodePort?: number;
|
||||
}
|
||||
|
||||
constructor(data: IServicePort) {
|
||||
export class ServicePort {
|
||||
constructor(data: ServicePort) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
||||
@@ -50,12 +46,7 @@ export class ServicePort implements IServicePort {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class Service extends KubeObject {
|
||||
static kind = "Service";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/services";
|
||||
|
||||
export interface Service {
|
||||
spec: {
|
||||
type: string;
|
||||
clusterIP: string;
|
||||
@@ -75,6 +66,17 @@ export class Service extends KubeObject {
|
||||
}[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export class Service extends KubeObject {
|
||||
static kind = "Service";
|
||||
static namespaced = true;
|
||||
static apiBase = "/api/v1/services";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getClusterIp() {
|
||||
return this.spec.clusterIP;
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
import get from "lodash/get";
|
||||
import type { IPodContainer } from "./pods.api";
|
||||
import { IAffinity, WorkloadKubeObject } from "../workload-kube-object";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
export class StatefulSetApi extends KubeApi<StatefulSet> {
|
||||
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||
@@ -48,13 +49,17 @@ export class StatefulSetApi extends KubeApi<StatefulSet> {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class StatefulSet extends WorkloadKubeObject {
|
||||
static kind = "StatefulSet";
|
||||
static namespaced = true;
|
||||
static apiBase = "/apis/apps/v1/statefulsets";
|
||||
|
||||
spec: {
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
declare spec: {
|
||||
serviceName: string;
|
||||
replicas: number;
|
||||
selector: {
|
||||
@@ -107,7 +112,7 @@ export class StatefulSet extends WorkloadKubeObject {
|
||||
};
|
||||
}[];
|
||||
};
|
||||
status: {
|
||||
declare status: {
|
||||
observedGeneration: number;
|
||||
replicas: number;
|
||||
currentReplicas: number;
|
||||
|
||||
@@ -19,16 +19,12 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeApi } from "../kube-api";
|
||||
import type { KubeJsonApiData } from "../kube-json-api";
|
||||
|
||||
@autobind()
|
||||
export class StorageClass extends KubeObject {
|
||||
static kind = "StorageClass";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/storage.k8s.io/v1/storageclasses";
|
||||
|
||||
export interface StorageClass {
|
||||
provisioner: string; // e.g. "storage.k8s.io/v1"
|
||||
mountOptions?: string[];
|
||||
volumeBindingMode: string;
|
||||
@@ -36,6 +32,17 @@ export class StorageClass extends KubeObject {
|
||||
parameters: {
|
||||
[param: string]: string; // every provisioner has own set of these parameters
|
||||
};
|
||||
}
|
||||
|
||||
export class StorageClass extends KubeObject {
|
||||
static kind = "StorageClass";
|
||||
static namespaced = false;
|
||||
static apiBase = "/apis/storage.k8s.io/v1/storageclasses";
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
isDefault() {
|
||||
const annotations = this.metadata.annotations || {};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
import moment from "moment";
|
||||
import type { KubeJsonApiData, KubeJsonApiDataList, KubeJsonApiListMetadata, KubeJsonApiMetadata } from "./kube-json-api";
|
||||
import { autobind, formatDuration } from "../utils";
|
||||
import { autoBind, formatDuration } from "../utils";
|
||||
import type { ItemObject } from "../item.store";
|
||||
import { apiKube } from "./index";
|
||||
import type { JsonApiParams } from "./json-api";
|
||||
@@ -87,11 +87,16 @@ export class KubeStatus {
|
||||
|
||||
export type IKubeMetaField = keyof IKubeObjectMetadata;
|
||||
|
||||
@autobind()
|
||||
export class KubeObject implements ItemObject {
|
||||
export class KubeObject<Metadata extends IKubeObjectMetadata = IKubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
||||
static readonly kind: string;
|
||||
static readonly namespaced: boolean;
|
||||
|
||||
apiVersion: string;
|
||||
kind: string;
|
||||
metadata: Metadata;
|
||||
status?: Status;
|
||||
spec?: Spec;
|
||||
|
||||
static create(data: any) {
|
||||
return new KubeObject(data);
|
||||
}
|
||||
@@ -176,13 +181,9 @@ export class KubeObject implements ItemObject {
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
Object.assign(this, data);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
apiVersion: string;
|
||||
kind: string;
|
||||
metadata: IKubeObjectMetadata;
|
||||
status?: any; // todo: type-safety support
|
||||
|
||||
get selfLink() {
|
||||
return this.metadata.selfLink;
|
||||
}
|
||||
@@ -265,7 +266,7 @@ export class KubeObject implements ItemObject {
|
||||
}
|
||||
|
||||
// use unified resource-applier api for updating all k8s objects
|
||||
async update<T extends KubeObject>(data: Partial<T>) {
|
||||
async update<T extends KubeObject>(data: Partial<T>): Promise<T> {
|
||||
return resourceApplierApi.update<T>({
|
||||
...this.toPlainObject(),
|
||||
...data,
|
||||
|
||||
@@ -26,8 +26,8 @@ import type { KubeObjectStore } from "../kube-object.store";
|
||||
import type { ClusterContext } from "../components/context";
|
||||
|
||||
import plimit from "p-limit";
|
||||
import { comparer, IReactionDisposer, observable, reaction, when } from "mobx";
|
||||
import { autobind, noop } from "../utils";
|
||||
import { comparer, IReactionDisposer, observable, reaction, makeObservable } from "mobx";
|
||||
import { autoBind, noop } from "../utils";
|
||||
import type { KubeApi } from "./kube-api";
|
||||
import type { KubeJsonApiData } from "./kube-json-api";
|
||||
import { isDebugging, isProduction } from "../../common/vars";
|
||||
@@ -50,11 +50,13 @@ export interface IKubeWatchLog {
|
||||
cssStyle?: string;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class KubeWatchApi {
|
||||
@observable context: ClusterContext = null;
|
||||
|
||||
contextReady = when(() => Boolean(this.context));
|
||||
constructor() {
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
isAllowedApi(api: KubeApi): boolean {
|
||||
return Boolean(this.context?.cluster.isAllowedResource(api.kind));
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
import { stringify } from "querystring";
|
||||
import { autobind, base64, EventEmitter } from "../utils";
|
||||
import { boundMethod, base64, EventEmitter } from "../utils";
|
||||
import { WebSocketApi } from "./websocket-api";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { isDevelopment } from "../../common/vars";
|
||||
@@ -106,7 +106,7 @@ export class TerminalApi extends WebSocketApi {
|
||||
this.onReady.removeAllListeners();
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
protected _onReady(data: string) {
|
||||
if (!data) return true;
|
||||
this.isReady = true;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { EventEmitter } from "../../common/event-emitter";
|
||||
|
||||
interface IParams {
|
||||
@@ -66,6 +66,7 @@ export class WebSocketApi {
|
||||
};
|
||||
|
||||
constructor(protected params: IParams) {
|
||||
makeObservable(this);
|
||||
this.params = Object.assign({}, WebSocketApi.defaultParams, params);
|
||||
const { autoConnect, pingIntervalSeconds } = this.params;
|
||||
|
||||
|
||||
@@ -68,8 +68,6 @@ export interface IAffinity {
|
||||
}
|
||||
|
||||
export class WorkloadKubeObject extends KubeObject {
|
||||
spec: any; // todo: add proper types
|
||||
|
||||
getSelectors(): string[] {
|
||||
const selector = this.spec.selector;
|
||||
|
||||
|
||||
+25
-10
@@ -26,13 +26,14 @@ import * as Mobx from "mobx";
|
||||
import * as MobxReact from "mobx-react";
|
||||
import * as ReactRouter from "react-router";
|
||||
import * as ReactRouterDom from "react-router-dom";
|
||||
import * as LensExtensionsCoreApi from "../extensions/core-api";
|
||||
import * as LensExtensionsRendererApi from "../extensions/renderer-api";
|
||||
import { render, unmountComponentAtNode } from "react-dom";
|
||||
import { delay } from "../common/utils";
|
||||
import { isMac, isDevelopment } from "../common/vars";
|
||||
import { HotbarStore } from "../common/hotbar-store";
|
||||
import { ClusterStore } from "../common/cluster-store";
|
||||
import { UserStore } from "../common/user-store";
|
||||
import * as LensExtensions from "../extensions/extension-api";
|
||||
import { ExtensionDiscovery } from "../extensions/extension-discovery";
|
||||
import { ExtensionLoader } from "../extensions/extension-loader";
|
||||
import { ExtensionsStore } from "../extensions/extensions-store";
|
||||
@@ -43,6 +44,9 @@ import { ThemeStore } from "./theme.store";
|
||||
import { HelmRepoManager } from "../main/helm/helm-repo-manager";
|
||||
import { ExtensionInstallationStateStore } from "./components/+extensions/extension-install.store";
|
||||
import { DefaultProps } from "./mui-base-theme";
|
||||
import configurePackages from "../common/configure-packages";
|
||||
|
||||
configurePackages();
|
||||
|
||||
/**
|
||||
* If this is a development buid, wait a second to attach
|
||||
@@ -59,15 +63,6 @@ type AppComponent = React.ComponentType & {
|
||||
init?(): Promise<void>;
|
||||
};
|
||||
|
||||
export {
|
||||
React,
|
||||
ReactRouter,
|
||||
ReactRouterDom,
|
||||
Mobx,
|
||||
MobxReact,
|
||||
LensExtensions
|
||||
};
|
||||
|
||||
export async function bootstrap(App: AppComponent) {
|
||||
const rootElem = document.getElementById("app");
|
||||
|
||||
@@ -120,3 +115,23 @@ export async function bootstrap(App: AppComponent) {
|
||||
|
||||
// run
|
||||
bootstrap(process.isMainFrame ? LensApp : App);
|
||||
|
||||
|
||||
/**
|
||||
* Exports for virtual package "@k8slens/extensions" for renderer-process.
|
||||
* All exporting names available in global runtime scope:
|
||||
* e.g. Devtools -> Console -> window.LensExtensions (renderer)
|
||||
*/
|
||||
const LensExtensions = {
|
||||
...LensExtensionsCoreApi,
|
||||
...LensExtensionsRendererApi,
|
||||
};
|
||||
|
||||
export {
|
||||
React,
|
||||
ReactRouter,
|
||||
ReactRouterDom,
|
||||
Mobx,
|
||||
MobxReact,
|
||||
LensExtensions,
|
||||
};
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./add-cluster.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { action, observable, runInAction } from "mobx";
|
||||
import { action, observable, runInAction, makeObservable } from "mobx";
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
import { AceEditor } from "../ace-editor";
|
||||
import { Button } from "../button";
|
||||
@@ -50,6 +50,11 @@ export class AddCluster extends React.Component {
|
||||
|
||||
kubeContexts = observable.map<string, KubeConfig>();
|
||||
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
appEventBus.emit({ name: "cluster-add", action: "start" });
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ import "./helm-chart-details.scss";
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { getChartDetails, HelmChart } from "../../api/endpoints/helm-charts.api";
|
||||
import { observable, autorun } from "mobx";
|
||||
import { observable, autorun, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Drawer, DrawerItem } from "../drawer";
|
||||
import { autobind, stopPropagation } from "../../utils";
|
||||
import { boundMethod, stopPropagation } from "../../utils";
|
||||
import { MarkdownViewer } from "../markdown-viewer";
|
||||
import { Spinner } from "../spinner";
|
||||
import { Button } from "../button";
|
||||
@@ -48,6 +48,11 @@ export class HelmChartDetails extends Component<Props> {
|
||||
|
||||
private abortController?: AbortController;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.abortController?.abort();
|
||||
}
|
||||
@@ -67,7 +72,7 @@ export class HelmChartDetails extends Component<Props> {
|
||||
});
|
||||
});
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
async onVersionChange({ value: version }: SelectOption<string>) {
|
||||
this.selectedChart = this.chartVersions.find(chart => chart.version === version);
|
||||
this.readme = null;
|
||||
@@ -84,7 +89,7 @@ export class HelmChartDetails extends Component<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
install() {
|
||||
createInstallChartTab(this.selectedChart);
|
||||
this.props.hideDetails();
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
import semver from "semver";
|
||||
import { observable } from "mobx";
|
||||
import { autobind } from "../../utils";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { autoBind } from "../../utils";
|
||||
import { getChartDetails, HelmChart, listCharts } from "../../api/endpoints/helm-charts.api";
|
||||
import { ItemStore } from "../../item.store";
|
||||
import flatten from "lodash/flatten";
|
||||
@@ -31,10 +31,16 @@ export interface IChartVersion {
|
||||
version: string;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class HelmChartStore extends ItemStore<HelmChart> {
|
||||
@observable versions = observable.map<string, IChartVersion[]>();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
async loadAll() {
|
||||
try {
|
||||
const res = await this.loadItems(() => listCharts());
|
||||
|
||||
@@ -57,10 +57,10 @@ export class HelmCharts extends Component<Props> {
|
||||
|
||||
showDetails = (chart: HelmChart) => {
|
||||
if (!chart) {
|
||||
navigation.merge(helmChartsURL());
|
||||
navigation.push(helmChartsURL());
|
||||
}
|
||||
else {
|
||||
navigation.merge(helmChartsURL({
|
||||
navigation.push(helmChartsURL({
|
||||
params: {
|
||||
chartName: chart.getName(),
|
||||
repo: chart.getRepository(),
|
||||
|
||||
@@ -24,7 +24,7 @@ import "./release-details.scss";
|
||||
import React, { Component } from "react";
|
||||
import groupBy from "lodash/groupBy";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { observable, reaction } from "mobx";
|
||||
import { observable, reaction, makeObservable } from "mobx";
|
||||
import { Link } from "react-router-dom";
|
||||
import kebabCase from "lodash/kebabCase";
|
||||
import { getRelease, getReleaseValues, HelmRelease, IReleaseDetails } from "../../api/endpoints/helm-releases.api";
|
||||
@@ -72,7 +72,7 @@ export class ReleaseDetails extends Component<Props> {
|
||||
);
|
||||
|
||||
@disposeOnUnmount
|
||||
secretWatcher = reaction(() => secretsStore.items.toJS(), () => {
|
||||
secretWatcher = reaction(() => secretsStore.getItems(), () => {
|
||||
if (!this.props.release) return;
|
||||
const { getReleaseSecret } = releaseStore;
|
||||
const { release } = this.props;
|
||||
@@ -85,6 +85,11 @@ export class ReleaseDetails extends Component<Props> {
|
||||
this.releaseSecret = secret;
|
||||
});
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
async loadDetails() {
|
||||
const { release } = this.props;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
import React from "react";
|
||||
import type { HelmRelease } from "../../api/endpoints/helm-releases.api";
|
||||
import { autobind, cssNames } from "../../utils";
|
||||
import { boundMethod, cssNames } from "../../utils";
|
||||
import { releaseStore } from "./release.store";
|
||||
import { MenuActions, MenuActionsProps } from "../menu/menu-actions";
|
||||
import { MenuItem } from "../menu";
|
||||
@@ -35,12 +35,12 @@ interface Props extends MenuActionsProps {
|
||||
}
|
||||
|
||||
export class HelmReleaseMenu extends React.Component<Props> {
|
||||
@autobind()
|
||||
@boundMethod
|
||||
remove() {
|
||||
return releaseStore.remove(this.props.release);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
upgrade() {
|
||||
const { release, hideDetails } = this.props;
|
||||
|
||||
@@ -48,7 +48,7 @@ export class HelmReleaseMenu extends React.Component<Props> {
|
||||
hideDetails && hideDetails();
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
rollback() {
|
||||
ReleaseRollbackDialog.open(this.props.release);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./release-rollback-dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Dialog, DialogProps } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
@@ -35,26 +35,33 @@ import orderBy from "lodash/orderBy";
|
||||
interface Props extends DialogProps {
|
||||
}
|
||||
|
||||
const dialogState = observable.object({
|
||||
isOpen: false,
|
||||
release: null as HelmRelease,
|
||||
});
|
||||
|
||||
@observer
|
||||
export class ReleaseRollbackDialog extends React.Component<Props> {
|
||||
@observable static isOpen = false;
|
||||
@observable.ref static release: HelmRelease = null;
|
||||
|
||||
@observable isLoading = false;
|
||||
@observable revision: IReleaseRevision;
|
||||
@observable revisions = observable.array<IReleaseRevision>();
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open(release: HelmRelease) {
|
||||
ReleaseRollbackDialog.isOpen = true;
|
||||
ReleaseRollbackDialog.release = release;
|
||||
dialogState.isOpen = true;
|
||||
dialogState.release = release;
|
||||
}
|
||||
|
||||
static close() {
|
||||
ReleaseRollbackDialog.isOpen = false;
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
get release(): HelmRelease {
|
||||
return ReleaseRollbackDialog.release;
|
||||
return dialogState.release;
|
||||
}
|
||||
|
||||
onOpen = async () => {
|
||||
@@ -115,7 +122,7 @@ export class ReleaseRollbackDialog extends React.Component<Props> {
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="ReleaseRollbackDialog"
|
||||
isOpen={ReleaseRollbackDialog.isOpen}
|
||||
isOpen={dialogState.isOpen}
|
||||
onOpen={this.onOpen}
|
||||
close={this.close}
|
||||
>
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { action, observable, reaction, when } from "mobx";
|
||||
import { autobind } from "../../utils";
|
||||
import { action, observable, reaction, when, makeObservable } from "mobx";
|
||||
import { autoBind } from "../../utils";
|
||||
import { createRelease, deleteRelease, HelmRelease, IReleaseCreatePayload, IReleaseUpdatePayload, listReleases, rollbackRelease, updateRelease } from "../../api/endpoints/helm-releases.api";
|
||||
import { ItemStore } from "../../item.store";
|
||||
import type { Secret } from "../../api/endpoints";
|
||||
@@ -29,19 +29,21 @@ import { secretsStore } from "../+config-secrets/secrets.store";
|
||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||
import { Notifications } from "../notifications";
|
||||
|
||||
@autobind()
|
||||
export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
releaseSecrets = observable.map<string, Secret>();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
|
||||
when(() => secretsStore.isLoaded, () => {
|
||||
this.releaseSecrets.replace(this.getReleaseSecrets());
|
||||
});
|
||||
}
|
||||
|
||||
watchAssociatedSecrets(): (() => void) {
|
||||
return reaction(() => secretsStore.items.toJS(), () => {
|
||||
return reaction(() => secretsStore.getItems(), () => {
|
||||
if (this.isLoading) return;
|
||||
const newSecrets = this.getReleaseSecrets();
|
||||
const amountChanged = newSecrets.length !== this.releaseSecrets.size;
|
||||
|
||||
@@ -67,7 +67,7 @@ export class HelmReleases extends Component<Props> {
|
||||
}
|
||||
|
||||
showDetails = (item: HelmRelease) => {
|
||||
navigation.merge(releaseURL({
|
||||
navigation.push(releaseURL({
|
||||
params: {
|
||||
name: item.getName(),
|
||||
namespace: item.getNs()
|
||||
@@ -76,7 +76,7 @@ export class HelmReleases extends Component<Props> {
|
||||
};
|
||||
|
||||
hideDetails = () => {
|
||||
navigation.merge(releaseURL());
|
||||
navigation.push(releaseURL());
|
||||
};
|
||||
|
||||
renderRemoveDialogMessage(selectedItems: HelmRelease[]) {
|
||||
|
||||
@@ -24,12 +24,10 @@ import { observer } from "mobx-react";
|
||||
import { TabLayout, TabLayoutRoute } from "../layout/tab-layout";
|
||||
import { HelmCharts, helmChartsRoute, helmChartsURL } from "../+apps-helm-charts";
|
||||
import { HelmReleases, releaseRoute, releaseURL } from "../+apps-releases";
|
||||
import { namespaceUrlParam } from "../+namespaces/namespace.store";
|
||||
|
||||
@observer
|
||||
export class Apps extends React.Component {
|
||||
static get tabRoutes(): TabLayoutRoute[] {
|
||||
const query = namespaceUrlParam.toObjectParam();
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -41,7 +39,7 @@ export class Apps extends React.Component {
|
||||
{
|
||||
title: "Releases",
|
||||
component: HelmReleases,
|
||||
url: releaseURL({ query }),
|
||||
url: releaseURL(),
|
||||
routePath: releaseRoute.path.toString(),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -24,8 +24,8 @@ import React from "react";
|
||||
import { SpeedDial, SpeedDialAction } from "@material-ui/lab";
|
||||
import { Icon } from "../icon";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { observable, reaction } from "mobx";
|
||||
import { autobind } from "../../../common/utils";
|
||||
import { observable, reaction, makeObservable } from "mobx";
|
||||
import { boundMethod } from "../../../common/utils";
|
||||
import type { CatalogCategory, CatalogEntityAddMenuContext, CatalogEntityAddMenu } from "../../api/catalog-entity";
|
||||
import { EventEmitter } from "events";
|
||||
import { navigate } from "../../navigation";
|
||||
@@ -39,6 +39,11 @@ export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
|
||||
@observable protected isOpen = false;
|
||||
protected menuItems = observable.array<CatalogEntityAddMenu>([]);
|
||||
|
||||
constructor(props: CatalogAddButtonProps) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.category, (category) => {
|
||||
@@ -56,17 +61,17 @@ export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
|
||||
]);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
onOpen() {
|
||||
this.isOpen = true;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
onClose() {
|
||||
this.isOpen = false;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
onButtonClick() {
|
||||
if (this.menuItems.length == 1) {
|
||||
this.menuItems[0].onClick();
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
|
||||
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from "mobx";
|
||||
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
|
||||
import type { CatalogEntity, CatalogEntityActionContext } from "../../api/catalog-entity";
|
||||
import { ItemObject, ItemStore } from "../../item.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { CatalogCategory } from "../../../common/catalog";
|
||||
import { autoBind } from "../../../common/utils";
|
||||
|
||||
export class CatalogEntityItem implements ItemObject {
|
||||
constructor(public entity: CatalogEntity) {}
|
||||
@@ -84,8 +84,13 @@ export class CatalogEntityItem implements ItemObject {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class CatalogEntityStore extends ItemStore<CatalogEntityItem> {
|
||||
constructor() {
|
||||
super();
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
@observable activeCategory?: CatalogCategory;
|
||||
|
||||
@computed get entities() {
|
||||
|
||||
@@ -23,7 +23,7 @@ import "./catalog.scss";
|
||||
import React from "react";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { ItemListLayout } from "../item-object-list";
|
||||
import { action, observable, reaction, when } from "mobx";
|
||||
import { action, makeObservable, observable, reaction, when } from "mobx";
|
||||
import { CatalogEntityItem, CatalogEntityStore } from "./catalog-entity.store";
|
||||
import { navigate } from "../../navigation";
|
||||
import { kebabCase } from "lodash";
|
||||
@@ -32,7 +32,6 @@ import { MenuItem, MenuActions } from "../menu";
|
||||
import { CatalogEntityContextMenu, CatalogEntityContextMenuContext, catalogEntityRunContext } from "../../api/catalog-entity";
|
||||
import { Badge } from "../badge";
|
||||
import { HotbarStore } from "../../../common/hotbar-store";
|
||||
import { autobind } from "../../utils";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { Tab, Tabs } from "../tabs";
|
||||
import { catalogCategoryRegistry } from "../../../common/catalog";
|
||||
@@ -49,12 +48,18 @@ enum sortBy {
|
||||
}
|
||||
|
||||
interface Props extends RouteComponentProps<ICatalogViewRouteParam> {}
|
||||
|
||||
@observer
|
||||
export class Catalog extends React.Component<Props> {
|
||||
@observable private catalogEntityStore?: CatalogEntityStore;
|
||||
@observable.deep private contextMenu: CatalogEntityContextMenuContext;
|
||||
@observable private contextMenu: CatalogEntityContextMenuContext;
|
||||
@observable activeTab?: string;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
get routeActiveTab(): string | undefined {
|
||||
const { group, kind } = this.props.match.params ?? {};
|
||||
|
||||
@@ -155,8 +160,7 @@ export class Catalog extends React.Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
renderItemMenu(item: CatalogEntityItem) {
|
||||
renderItemMenu = (item: CatalogEntityItem) => {
|
||||
const menuItems = this.contextMenu.menuItems.filter((menuItem) => !menuItem.onlyVisibleForSource || menuItem.onlyVisibleForSource === item.entity.metadata.source);
|
||||
|
||||
return (
|
||||
@@ -173,7 +177,7 @@ export class Catalog extends React.Component<Props> {
|
||||
</MenuItem>
|
||||
</MenuActions>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderIcon(item: CatalogEntityItem) {
|
||||
const category = catalogCategoryRegistry.getCategoryForEntity(item.entity);
|
||||
|
||||
@@ -23,13 +23,13 @@ import "./cluster-issues.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { computed } from "mobx";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { Icon } from "../icon";
|
||||
import { SubHeader } from "../layout/sub-header";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { nodesStore } from "../+nodes/nodes.store";
|
||||
import { eventStore } from "../+events/event.store";
|
||||
import { autobind, cssNames, prevDefault } from "../../utils";
|
||||
import { boundMethod, cssNames, prevDefault } from "../../utils";
|
||||
import type { ItemObject } from "../../item.store";
|
||||
import { Spinner } from "../spinner";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
@@ -62,6 +62,11 @@ export class ClusterIssues extends React.Component<Props> {
|
||||
[sortBy.age]: (warning: IWarning) => warning.timeDiffFromNow,
|
||||
};
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@computed get warnings() {
|
||||
const warnings: IWarning[] = [];
|
||||
|
||||
@@ -103,7 +108,7 @@ export class ClusterIssues extends React.Component<Props> {
|
||||
return warnings;
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
getTableRow(uid: string) {
|
||||
const { warnings } = this;
|
||||
const warning = warnings.find(warn => warn.getId() == uid);
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { action, observable, reaction, when } from "mobx";
|
||||
import { action, observable, reaction, when, makeObservable } from "mobx";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { Cluster, clusterApi, IClusterMetrics } from "../../api/endpoints";
|
||||
import { autobind, createStorage } from "../../utils";
|
||||
import { autoBind, createStorage } from "../../utils";
|
||||
import { IMetricsReqParams, normalizeMetrics } from "../../api/endpoints/metrics.api";
|
||||
import { nodesStore } from "../+nodes/nodes.store";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
@@ -42,7 +42,6 @@ export interface ClusterOverviewStorageState {
|
||||
metricNodeRole: MetricNodeRole,
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class ClusterOverviewStore extends KubeObjectStore<Cluster> implements ClusterOverviewStorageState {
|
||||
api = clusterApi;
|
||||
|
||||
@@ -72,6 +71,9 @@ export class ClusterOverviewStore extends KubeObjectStore<Cluster> implements Cl
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { HorizontalPodAutoscaler, hpaApi } from "../../api/endpoints/hpa.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class HPAStore extends KubeObjectStore<HorizontalPodAutoscaler> {
|
||||
api = hpaApi;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../../common/utils/autobind";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { LimitRange, limitRangeApi } from "../../api/endpoints/limit-range.api";
|
||||
|
||||
@autobind()
|
||||
export class LimitRangesStore extends KubeObjectStore<LimitRange> {
|
||||
api = limitRangeApi;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./config-map-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import { autorun, observable } from "mobx";
|
||||
import { autorun, makeObservable, observable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { DrawerTitle } from "../drawer";
|
||||
import { Notifications } from "../notifications";
|
||||
@@ -41,7 +41,12 @@ interface Props extends KubeObjectDetailsProps<ConfigMap> {
|
||||
@observer
|
||||
export class ConfigMapDetails extends React.Component<Props> {
|
||||
@observable isSaving = false;
|
||||
@observable data = observable.map();
|
||||
@observable data = observable.map<string, string>();
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
@@ -60,7 +65,10 @@ export class ConfigMapDetails extends React.Component<Props> {
|
||||
|
||||
try {
|
||||
this.isSaving = true;
|
||||
await configMapsStore.update(configMap, { ...configMap, data: this.data.toJSON() });
|
||||
await configMapsStore.update(configMap, {
|
||||
...configMap,
|
||||
data: Object.fromEntries(this.data),
|
||||
});
|
||||
Notifications.ok(
|
||||
<p>
|
||||
<>ConfigMap <b>{configMap.getName()}</b> successfully updated.</>
|
||||
@@ -75,7 +83,7 @@ export class ConfigMapDetails extends React.Component<Props> {
|
||||
const { object: configMap } = this.props;
|
||||
|
||||
if (!configMap) return null;
|
||||
const data = Object.entries(this.data.toJSON());
|
||||
const data = Array.from(this.data.entries());
|
||||
|
||||
return (
|
||||
<div className="ConfigMapDetails">
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { ConfigMap, configMapApi } from "../../api/endpoints/configmap.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class ConfigMapsStore extends KubeObjectStore<ConfigMap> {
|
||||
api = configMapApi;
|
||||
}
|
||||
|
||||
+1
-3
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { PodDisruptionBudget, pdbApi } from "../../api/endpoints/poddisruptionbudget.api";
|
||||
import { pdbApi, PodDisruptionBudget } from "../../api/endpoints/poddisruptionbudget.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class PodDisruptionBudgetsStore extends KubeObjectStore<PodDisruptionBudget> {
|
||||
api = pdbApi;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./add-quota-dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import { computed, observable } from "mobx";
|
||||
import { computed, observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Dialog, DialogProps } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
@@ -39,10 +39,12 @@ import { SubTitle } from "../layout/sub-title";
|
||||
interface Props extends DialogProps {
|
||||
}
|
||||
|
||||
const dialogState = observable.object({
|
||||
isOpen: false,
|
||||
});
|
||||
|
||||
@observer
|
||||
export class AddQuotaDialog extends React.Component<Props> {
|
||||
@observable static isOpen = false;
|
||||
|
||||
static defaultQuotas: IResourceQuotaValues = {
|
||||
"limits.cpu": "",
|
||||
"limits.memory": "",
|
||||
@@ -72,12 +74,17 @@ export class AddQuotaDialog extends React.Component<Props> {
|
||||
@observable namespace = this.defaultNamespace;
|
||||
@observable quotas = AddQuotaDialog.defaultQuotas;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open() {
|
||||
AddQuotaDialog.isOpen = true;
|
||||
dialogState.isOpen = true;
|
||||
}
|
||||
|
||||
static close() {
|
||||
AddQuotaDialog.isOpen = false;
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
@computed get quotaEntries() {
|
||||
@@ -154,7 +161,7 @@ export class AddQuotaDialog extends React.Component<Props> {
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddQuotaDialog"
|
||||
isOpen={AddQuotaDialog.isOpen}
|
||||
isOpen={dialogState.isOpen}
|
||||
close={this.close}
|
||||
>
|
||||
<Wizard header={header} done={this.close}>
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { ResourceQuota, resourceQuotaApi } from "../../api/endpoints/resource-quota.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class ResourceQuotasStore extends KubeObjectStore<ResourceQuota> {
|
||||
api = resourceQuotaApi;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./add-secret-dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Dialog, DialogProps } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
@@ -57,16 +57,23 @@ interface ISecretTemplate {
|
||||
|
||||
type ISecretField = keyof ISecretTemplate;
|
||||
|
||||
const dialogState = observable.object({
|
||||
isOpen: false,
|
||||
});
|
||||
|
||||
@observer
|
||||
export class AddSecretDialog extends React.Component<Props> {
|
||||
@observable static isOpen = false;
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open() {
|
||||
AddSecretDialog.isOpen = true;
|
||||
dialogState.isOpen = true;
|
||||
}
|
||||
|
||||
static close() {
|
||||
AddSecretDialog.isOpen = false;
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
private secretTemplate: { [p: string]: ISecretTemplate } = {
|
||||
@@ -205,7 +212,7 @@ export class AddSecretDialog extends React.Component<Props> {
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddSecretDialog"
|
||||
isOpen={AddSecretDialog.isOpen}
|
||||
isOpen={dialogState.isOpen}
|
||||
onOpen={this.reset}
|
||||
close={this.close}
|
||||
>
|
||||
|
||||
@@ -23,7 +23,7 @@ import "./secret-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
import { autorun, observable } from "mobx";
|
||||
import { autorun, observable, makeObservable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||
import { Input } from "../input";
|
||||
@@ -46,6 +46,11 @@ export class SecretDetails extends React.Component<Props> {
|
||||
@observable data: { [name: string]: string } = {};
|
||||
@observable revealSecret: { [name: string]: boolean } = {};
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
autorun(() => {
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { Secret, secretsApi } from "../../api/endpoints";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class SecretsStore extends KubeObjectStore<Secret> {
|
||||
api = secretsApi;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import { observer } from "mobx-react";
|
||||
import { TabLayout, TabLayoutRoute } from "../layout/tab-layout";
|
||||
import { ConfigMaps, configMapsRoute, configMapsURL } from "../+config-maps";
|
||||
import { Secrets, secretsRoute, secretsURL } from "../+config-secrets";
|
||||
import { namespaceUrlParam } from "../+namespaces/namespace.store";
|
||||
import { resourceQuotaRoute, ResourceQuotas, resourceQuotaURL } from "../+config-resource-quotas";
|
||||
import { pdbRoute, pdbURL, PodDisruptionBudgets } from "../+config-pod-disruption-budgets";
|
||||
import { HorizontalPodAutoscalers, hpaRoute, hpaURL } from "../+config-autoscalers";
|
||||
@@ -34,14 +33,13 @@ import { LimitRanges, limitRangesRoute, limitRangeURL } from "../+config-limit-r
|
||||
@observer
|
||||
export class Config extends React.Component {
|
||||
static get tabRoutes(): TabLayoutRoute[] {
|
||||
const query = namespaceUrlParam.toObjectParam();
|
||||
const routes: TabLayoutRoute[] = [];
|
||||
|
||||
if (isAllowedResource("configmaps")) {
|
||||
routes.push({
|
||||
title: "ConfigMaps",
|
||||
component: ConfigMaps,
|
||||
url: configMapsURL({ query }),
|
||||
url: configMapsURL(),
|
||||
routePath: configMapsRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -50,7 +48,7 @@ export class Config extends React.Component {
|
||||
routes.push({
|
||||
title: "Secrets",
|
||||
component: Secrets,
|
||||
url: secretsURL({ query }),
|
||||
url: secretsURL(),
|
||||
routePath: secretsRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -59,7 +57,7 @@ export class Config extends React.Component {
|
||||
routes.push({
|
||||
title: "Resource Quotas",
|
||||
component: ResourceQuotas,
|
||||
url: resourceQuotaURL({ query }),
|
||||
url: resourceQuotaURL(),
|
||||
routePath: resourceQuotaRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -68,7 +66,7 @@ export class Config extends React.Component {
|
||||
routes.push({
|
||||
title: "Limit Ranges",
|
||||
component: LimitRanges,
|
||||
url: limitRangeURL({ query }),
|
||||
url: limitRangeURL(),
|
||||
routePath: limitRangesRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -77,7 +75,7 @@ export class Config extends React.Component {
|
||||
routes.push({
|
||||
title: "HPA",
|
||||
component: HorizontalPodAutoscalers,
|
||||
url: hpaURL({ query }),
|
||||
url: hpaURL(),
|
||||
routePath: hpaRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -86,7 +84,7 @@ export class Config extends React.Component {
|
||||
routes.push({
|
||||
title: "Pod Disruption Budgets",
|
||||
component: PodDisruptionBudgets,
|
||||
url: pdbURL({ query }),
|
||||
url: pdbURL(),
|
||||
routePath: pdbRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./crd-list.scss";
|
||||
|
||||
import React from "react";
|
||||
import { computed } from "mobx";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { stopPropagation } from "../../utils";
|
||||
@@ -35,8 +35,6 @@ import { Icon } from "../icon";
|
||||
|
||||
export const crdGroupsUrlParam = createPageParam<string[]>({
|
||||
name: "groups",
|
||||
multiValues: true,
|
||||
isSystem: true,
|
||||
defaultValue: [],
|
||||
});
|
||||
|
||||
@@ -50,6 +48,11 @@ enum columnId {
|
||||
|
||||
@observer
|
||||
export class CrdList extends React.Component {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
get selectedGroups(): string[] {
|
||||
return crdGroupsUrlParam.get();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import "./crd-resource-details.scss";
|
||||
import React from "react";
|
||||
import jsonPath from "jsonpath";
|
||||
import { observer } from "mobx-react";
|
||||
import { computed } from "mobx";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { cssNames } from "../../utils";
|
||||
import { Badge } from "../badge";
|
||||
import { DrawerItem } from "../drawer";
|
||||
@@ -60,6 +60,11 @@ function convertSpecValue(value: any): any {
|
||||
|
||||
@observer
|
||||
export class CrdResourceDetails extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@computed get crd() {
|
||||
return crdStore.getByObject(this.props.object);
|
||||
}
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autobind } from "../../utils";
|
||||
import { KubeApi } from "../../api/kube-api";
|
||||
import type { KubeApi } from "../../api/kube-api";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import type { KubeObject } from "../../api/kube-object";
|
||||
|
||||
@autobind()
|
||||
export class CRDResourceStore<T extends KubeObject = any> extends KubeObjectStore<T> {
|
||||
api: KubeApi;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import type { RouteComponentProps } from "react-router";
|
||||
import { KubeObjectListLayout } from "../kube-object";
|
||||
import type { KubeObject } from "../../api/kube-object";
|
||||
import type { ICRDRouteParams } from "./crd.route";
|
||||
import { autorun, computed } from "mobx";
|
||||
import { autorun, computed, makeObservable } from "mobx";
|
||||
import { crdStore } from "./crd.store";
|
||||
import type { TableSortCallback } from "../table";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
@@ -45,6 +45,11 @@ enum columnId {
|
||||
|
||||
@observer
|
||||
export class CrdResources extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
autorun(() => {
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { computed, reaction } from "mobx";
|
||||
import { computed, reaction, makeObservable } from "mobx";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { crdApi, CustomResourceDefinition } from "../../api/endpoints/crd.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { KubeApi } from "../../api/kube-api";
|
||||
@@ -39,15 +39,17 @@ function initStore(crd: CustomResourceDefinition) {
|
||||
}
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class CRDStore extends KubeObjectStore<CustomResourceDefinition> {
|
||||
api = crdApi;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
|
||||
// auto-init stores for crd-s
|
||||
reaction(() => this.items.toJS(), items => items.forEach(initStore));
|
||||
reaction(() => this.getItems(), items => items.forEach(initStore));
|
||||
}
|
||||
|
||||
protected sortItems(items: CustomResourceDefinition[]) {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./entity-settings.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import type { RouteComponentProps } from "react-router";
|
||||
import { observer } from "mobx-react";
|
||||
import { PageLayout } from "../layout/page-layout";
|
||||
@@ -41,6 +41,11 @@ interface Props extends RouteComponentProps<EntitySettingsRouteParams> {
|
||||
export class EntitySettings extends React.Component<Props> {
|
||||
@observable activeTab: string;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
get entityId() {
|
||||
return this.props.match.params.entityId;
|
||||
}
|
||||
|
||||
@@ -22,19 +22,23 @@
|
||||
import groupBy from "lodash/groupBy";
|
||||
import compact from "lodash/compact";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { eventApi, KubeEvent } from "../../api/endpoints/events.api";
|
||||
import type { KubeObject } from "../../api/kube-object";
|
||||
import { Pod } from "../../api/endpoints/pods.api";
|
||||
import { podsStore } from "../+workloads-pods/pods.store";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class EventStore extends KubeObjectStore<KubeEvent> {
|
||||
api = eventApi;
|
||||
limit = 1000;
|
||||
saveLimit = 50000;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
protected bindWatchEventsUpdater() {
|
||||
return super.bindWatchEventsUpdater(5000);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./events.scss";
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
import { computed, observable } from "mobx";
|
||||
import { computed, observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { orderBy } from "lodash";
|
||||
import { TabLayout } from "../layout/tab-layout";
|
||||
@@ -81,6 +81,11 @@ export class Events extends React.Component<Props> {
|
||||
onSort: params => this.sorting = params,
|
||||
};
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
get store(): EventStore {
|
||||
return eventStore;
|
||||
}
|
||||
|
||||
@@ -24,33 +24,17 @@ import "./extensions.scss";
|
||||
import { remote, shell } from "electron";
|
||||
import fse from "fs-extra";
|
||||
import _ from "lodash";
|
||||
import { observable, reaction, when } from "mobx";
|
||||
import { makeObservable, observable, reaction, when } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import React from "react";
|
||||
import { SemVer } from "semver";
|
||||
import URLParse from "url-parse";
|
||||
|
||||
import {
|
||||
Disposer,
|
||||
disposer,
|
||||
downloadFile,
|
||||
downloadJson,
|
||||
ExtendableDisposer,
|
||||
extractTar,
|
||||
listTarEntries,
|
||||
noop,
|
||||
readFileFromTar,
|
||||
} from "../../../common/utils";
|
||||
import { Disposer, disposer, downloadFile, downloadJson, ExtendableDisposer, extractTar, listTarEntries, noop, readFileFromTar, } from "../../../common/utils";
|
||||
import { ExtensionDiscovery, InstalledExtension, manifestFilename } from "../../../extensions/extension-discovery";
|
||||
import { ExtensionLoader } from "../../../extensions/extension-loader";
|
||||
import {
|
||||
extensionDisplayName,
|
||||
LensExtensionId,
|
||||
LensExtensionManifest,
|
||||
sanitizeExtensionName,
|
||||
} from "../../../extensions/lens-extension";
|
||||
import { extensionDisplayName, LensExtensionId, LensExtensionManifest, sanitizeExtensionName, } from "../../../extensions/lens-extension";
|
||||
import logger from "../../../main/logger";
|
||||
import { Button } from "../button";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
@@ -193,7 +177,7 @@ async function validatePackage(filePath: string): Promise<LensExtensionManifest>
|
||||
// tarball from npm contains single root folder "package/*"
|
||||
const firstFile = tarFiles[0];
|
||||
|
||||
if(!firstFile) {
|
||||
if (!firstFile) {
|
||||
throw new Error(`invalid extension bundle, ${manifestFilename} not found`);
|
||||
}
|
||||
|
||||
@@ -201,7 +185,7 @@ async function validatePackage(filePath: string): Promise<LensExtensionManifest>
|
||||
const packedInRootFolder = tarFiles.every(entry => entry.startsWith(rootFolder));
|
||||
const manifestLocation = packedInRootFolder ? path.join(rootFolder, manifestFilename) : manifestFilename;
|
||||
|
||||
if(!tarFiles.includes(manifestLocation)) {
|
||||
if (!tarFiles.includes(manifestLocation)) {
|
||||
throw new Error(`invalid extension bundle, ${manifestFilename} not found`);
|
||||
}
|
||||
|
||||
@@ -415,7 +399,7 @@ async function attemptInstall(request: InstallRequest, d?: ExtendableDisposer):
|
||||
} else {
|
||||
dispose();
|
||||
}
|
||||
}} />
|
||||
}}/>
|
||||
</div>,
|
||||
{
|
||||
onClose: dispose,
|
||||
@@ -460,7 +444,7 @@ async function installFromInput(input: string) {
|
||||
|
||||
await attemptInstall({ fileName, dataP: readFileNotify(input) });
|
||||
} else if (InputValidators.isExtensionNameInstall.validate(input)) {
|
||||
const [{ groups: { name, version }}] = [...input.matchAll(InputValidators.isExtensionNameInstallRegex)];
|
||||
const [{ groups: { name, version } }] = [...input.matchAll(InputValidators.isExtensionNameInstallRegex)];
|
||||
|
||||
await attemptInstallByInfo({ name, version });
|
||||
}
|
||||
@@ -493,10 +477,18 @@ async function installFromSelectFileDialog() {
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
}
|
||||
|
||||
@observer
|
||||
export class Extensions extends React.Component {
|
||||
export class Extensions extends React.Component<Props> {
|
||||
@observable installPath = "";
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// TODO: change this after upgrading to mobx6 as that versions' reactions have this functionality
|
||||
let prevSize = ExtensionLoader.getInstance().userExtensions.size;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./add-namespace-dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Dialog, DialogProps } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
@@ -37,17 +37,25 @@ interface Props extends DialogProps {
|
||||
onError?(error: any): void;
|
||||
}
|
||||
|
||||
const dialogState = observable.object({
|
||||
isOpen: false,
|
||||
});
|
||||
|
||||
@observer
|
||||
export class AddNamespaceDialog extends React.Component<Props> {
|
||||
@observable static isOpen = false;
|
||||
@observable namespace = "";
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open() {
|
||||
AddNamespaceDialog.isOpen = true;
|
||||
dialogState.isOpen = true;
|
||||
}
|
||||
|
||||
static close() {
|
||||
AddNamespaceDialog.isOpen = false;
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
reset = () => {
|
||||
@@ -78,7 +86,7 @@ export class AddNamespaceDialog extends React.Component<Props> {
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddNamespaceDialog"
|
||||
isOpen={AddNamespaceDialog.isOpen}
|
||||
isOpen={dialogState.isOpen}
|
||||
onOpen={this.reset}
|
||||
close={AddNamespaceDialog.close}
|
||||
>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./namespace-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import { computed } from "mobx";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { DrawerItem } from "../drawer";
|
||||
import { cssNames } from "../../utils";
|
||||
@@ -40,6 +40,11 @@ interface Props extends KubeObjectDetailsProps<Namespace> {
|
||||
|
||||
@observer
|
||||
export class NamespaceDetails extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@computed get quotas() {
|
||||
const namespace = this.props.object.getName();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./namespace-select.scss";
|
||||
|
||||
import React from "react";
|
||||
import { computed } from "mobx";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { Select, SelectOption, SelectProps } from "../select";
|
||||
import { cssNames } from "../../utils";
|
||||
@@ -46,6 +46,11 @@ const defaultProps: Partial<Props> = {
|
||||
export class NamespaceSelect extends React.Component<Props> {
|
||||
static defaultProps = defaultProps as object;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores([namespaceStore], {
|
||||
|
||||
@@ -19,71 +19,39 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { action, comparer, computed, IReactionDisposer, IReactionOptions, observable, reaction } from "mobx";
|
||||
import { autobind, createStorage } from "../../utils";
|
||||
import { action, comparer, computed, IReactionDisposer, IReactionOptions, makeObservable, reaction, } from "mobx";
|
||||
import { autoBind, createStorage } from "../../utils";
|
||||
import { KubeObjectStore, KubeObjectStoreLoadingParams } from "../../kube-object.store";
|
||||
import { Namespace, namespacesApi } from "../../api/endpoints/namespaces.api";
|
||||
import { createPageParam } from "../../navigation";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
const selectedNamespaces = createStorage<string[] | undefined>("selected_namespaces", undefined);
|
||||
|
||||
export const namespaceUrlParam = createPageParam<string[]>({
|
||||
name: "namespaces",
|
||||
isSystem: true,
|
||||
multiValues: true,
|
||||
defaultValue: [],
|
||||
});
|
||||
|
||||
export function getDummyNamespace(name: string) {
|
||||
return new Namespace({
|
||||
kind: Namespace.kind,
|
||||
apiVersion: "v1",
|
||||
metadata: {
|
||||
name,
|
||||
uid: "",
|
||||
resourceVersion: "",
|
||||
selfLink: `/api/v1/namespaces/${name}`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@autobind()
|
||||
export class NamespaceStore extends KubeObjectStore<Namespace> {
|
||||
api = namespacesApi;
|
||||
|
||||
@observable private contextNs = observable.set<string>();
|
||||
private storage = createStorage<string[] | undefined>("selected_namespaces", undefined);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
private async init() {
|
||||
await this.contextReady;
|
||||
await selectedNamespaces.whenReady;
|
||||
await this.storage.whenReady;
|
||||
|
||||
this.setContext(this.initialNamespaces);
|
||||
this.selectNamespaces(this.initialNamespaces);
|
||||
this.autoLoadAllowedNamespaces();
|
||||
this.autoUpdateUrlAndLocalStorage();
|
||||
}
|
||||
|
||||
public onContextChange(callback: (contextNamespaces: string[]) => void, opts: IReactionOptions = {}): IReactionDisposer {
|
||||
return reaction(() => Array.from(this.contextNs), callback, {
|
||||
public onContextChange(callback: (namespaces: string[]) => void, opts: IReactionOptions = {}): IReactionDisposer {
|
||||
return reaction(() => Array.from(this.contextNamespaces), callback, {
|
||||
equals: comparer.shallow,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
|
||||
private autoUpdateUrlAndLocalStorage(): IReactionDisposer {
|
||||
return this.onContextChange(namespaces => {
|
||||
selectedNamespaces.set(namespaces); // save to local-storage
|
||||
namespaceUrlParam.set(namespaces, { replaceHistory: true }); // update url
|
||||
}, {
|
||||
fireImmediately: true,
|
||||
});
|
||||
}
|
||||
|
||||
private autoLoadAllowedNamespaces(): IReactionDisposer {
|
||||
return reaction(() => this.allowedNamespaces, namespaces => this.loadAll({ namespaces }), {
|
||||
fireImmediately: true,
|
||||
@@ -92,24 +60,28 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
||||
}
|
||||
|
||||
private get initialNamespaces(): string[] {
|
||||
const namespaces = new Set(this.allowedNamespaces);
|
||||
const prevSelectedNamespaces = selectedNamespaces.get();
|
||||
const { allowedNamespaces } = this;
|
||||
const selectedNamespaces = this.storage.get(); // raw namespaces, undefined on first load
|
||||
|
||||
// return previously saved namespaces from local-storage (if any)
|
||||
if (prevSelectedNamespaces) {
|
||||
return prevSelectedNamespaces.filter(namespace => namespaces.has(namespace));
|
||||
if (Array.isArray(selectedNamespaces)) {
|
||||
return selectedNamespaces.filter(namespace => allowedNamespaces.includes(namespace));
|
||||
}
|
||||
|
||||
// otherwise select "default" or first allowed namespace
|
||||
if (namespaces.has("default")) {
|
||||
if (allowedNamespaces.includes("default")) {
|
||||
return ["default"];
|
||||
} else if (namespaces.size) {
|
||||
return [Array.from(namespaces)[0]];
|
||||
} else if (allowedNamespaces.length) {
|
||||
return [allowedNamespaces[0]];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
@computed get selectedNamespaces(): string[] {
|
||||
return this.storage.get() ?? [];
|
||||
}
|
||||
|
||||
@computed get allowedNamespaces(): string[] {
|
||||
return Array.from(new Set([
|
||||
...(this.context?.allNamespaces ?? []), // allowed namespaces from cluster (main), updating every 30s
|
||||
@@ -118,13 +90,11 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
||||
}
|
||||
|
||||
@computed get contextNamespaces(): string[] {
|
||||
const namespaces = Array.from(this.contextNs);
|
||||
|
||||
if (!namespaces.length) {
|
||||
if (!this.selectedNamespaces.length) {
|
||||
return this.allowedNamespaces; // show all namespaces when nothing selected
|
||||
}
|
||||
|
||||
return namespaces;
|
||||
return this.selectedNamespaces;
|
||||
}
|
||||
|
||||
getSubscribeApis() {
|
||||
@@ -151,31 +121,40 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
||||
}
|
||||
|
||||
@action
|
||||
setContext(namespace: string | string[]) {
|
||||
const namespaces = [namespace].flat();
|
||||
selectNamespaces(namespace: string | string[]) {
|
||||
const namespaces = Array.from(new Set([namespace].flat()));
|
||||
|
||||
this.contextNs.replace(namespaces);
|
||||
this.storage.set(namespaces);
|
||||
}
|
||||
|
||||
@action
|
||||
resetContext() {
|
||||
this.contextNs.clear();
|
||||
clearSelected(namespaces?: string | string[]) {
|
||||
if (namespaces) {
|
||||
const resettingNamespaces = [namespaces].flat();
|
||||
const newNamespaces = this.storage.get().filter(ns => !resettingNamespaces.includes(ns));
|
||||
|
||||
this.storage.set(newNamespaces);
|
||||
} else {
|
||||
this.storage.reset();
|
||||
}
|
||||
}
|
||||
|
||||
hasContext(namespaces: string | string[]) {
|
||||
return [namespaces].flat().every(namespace => this.contextNs.has(namespace));
|
||||
hasContext(namespaces: string | string[]): boolean {
|
||||
return [namespaces]
|
||||
.flat()
|
||||
.every(namespace => this.selectedNamespaces.includes(namespace));
|
||||
}
|
||||
|
||||
@computed get hasAllContexts(): boolean {
|
||||
return this.contextNs.size === this.allowedNamespaces.length;
|
||||
return this.selectedNamespaces.length === this.allowedNamespaces.length;
|
||||
}
|
||||
|
||||
@action
|
||||
toggleContext(namespace: string) {
|
||||
if (this.hasContext(namespace)) {
|
||||
this.contextNs.delete(namespace);
|
||||
toggleContext(namespaces: string | string[]) {
|
||||
if (this.hasContext(namespaces)) {
|
||||
this.clearSelected(namespaces);
|
||||
} else {
|
||||
this.contextNs.add(namespace);
|
||||
this.selectNamespaces([this.selectedNamespaces, namespaces].flat());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,9 +162,9 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
||||
toggleAll(showAll?: boolean) {
|
||||
if (typeof showAll === "boolean") {
|
||||
if (showAll) {
|
||||
this.setContext(this.allowedNamespaces);
|
||||
this.selectNamespaces(this.allowedNamespaces);
|
||||
} else {
|
||||
this.resetContext(); // empty context considered as "All namespaces"
|
||||
this.selectNamespaces([]); // empty context considered as "All namespaces"
|
||||
}
|
||||
} else {
|
||||
this.toggleAll(!this.hasAllContexts);
|
||||
@@ -195,9 +174,22 @@ export class NamespaceStore extends KubeObjectStore<Namespace> {
|
||||
@action
|
||||
async remove(item: Namespace) {
|
||||
await super.remove(item);
|
||||
this.contextNs.delete(item.getName());
|
||||
this.clearSelected(item.getName());
|
||||
}
|
||||
}
|
||||
|
||||
export const namespaceStore = new NamespaceStore();
|
||||
apiManager.registerStore(namespaceStore);
|
||||
|
||||
export function getDummyNamespace(name: string) {
|
||||
return new Namespace({
|
||||
kind: Namespace.kind,
|
||||
apiVersion: "v1",
|
||||
metadata: {
|
||||
name,
|
||||
uid: "",
|
||||
resourceVersion: "",
|
||||
selfLink: `/api/v1/namespaces/${name}`
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EndpointSubset, Endpoint, EndpointAddress} from "../../api/endpoints";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import { autobind } from "../../utils";
|
||||
import { boundMethod } from "../../utils";
|
||||
import { lookupApiLink } from "../../api/kube-api";
|
||||
import { Link } from "react-router-dom";
|
||||
import { getDetailsUrl } from "../kube-object";
|
||||
@@ -45,7 +45,7 @@ export class EndpointSubsetList extends React.Component<Props> {
|
||||
return this.renderAddressTableRow(address);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
getNotReadyAddressTableRow(ip: string) {
|
||||
const { subset} = this.props;
|
||||
const address = subset.getNotReadyAddresses().find(address => address.getId() == ip);
|
||||
@@ -53,7 +53,7 @@ export class EndpointSubsetList extends React.Component<Props> {
|
||||
return this.renderAddressTableRow(address);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
renderAddressTable(addresses: EndpointAddress[], virtual: boolean) {
|
||||
return (
|
||||
<div>
|
||||
@@ -79,7 +79,7 @@ export class EndpointSubsetList extends React.Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
renderAddressTableRow(address: EndpointAddress) {
|
||||
const { endpoint } = this.props;
|
||||
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { Endpoint, endpointApi } from "../../api/endpoints/endpoint.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class EndpointStore extends KubeObjectStore<Endpoint> {
|
||||
api = endpointApi;
|
||||
}
|
||||
|
||||
@@ -19,17 +19,23 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { IIngressMetrics, Ingress, ingressApi } from "../../api/endpoints";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class IngressStore extends KubeObjectStore<Ingress> {
|
||||
api = ingressApi;
|
||||
@observable metrics: IIngressMetrics = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
async loadMetrics(ingress: Ingress) {
|
||||
this.metrics = await this.api.getMetrics(ingress.getName(), ingress.getNs());
|
||||
}
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { NetworkPolicy, networkPolicyApi } from "../../api/endpoints/network-policy.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class NetworkPolicyStore extends KubeObjectStore<NetworkPolicy> {
|
||||
api = networkPolicyApi;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { Service, ServicePort } from "../../api/endpoints";
|
||||
import { apiBase } from "../../api";
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { cssNames } from "../../utils";
|
||||
import { Notifications } from "../notifications";
|
||||
import { Spinner } from "../spinner";
|
||||
@@ -39,6 +39,11 @@ interface Props {
|
||||
export class ServicePortComponent extends React.Component<Props> {
|
||||
@observable waiting = false;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
async portForward() {
|
||||
const { service, port } = this.props;
|
||||
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { Service, serviceApi } from "../../api/endpoints/service.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class ServiceStore extends KubeObjectStore<Service> {
|
||||
api = serviceApi;
|
||||
}
|
||||
|
||||
@@ -28,20 +28,18 @@ import { Services, servicesRoute, servicesURL } from "../+network-services";
|
||||
import { endpointRoute, Endpoints, endpointURL } from "../+network-endpoints";
|
||||
import { Ingresses, ingressRoute, ingressURL } from "../+network-ingresses";
|
||||
import { NetworkPolicies, networkPoliciesRoute, networkPoliciesURL } from "../+network-policies";
|
||||
import { namespaceUrlParam } from "../+namespaces/namespace.store";
|
||||
import { isAllowedResource } from "../../../common/rbac";
|
||||
|
||||
@observer
|
||||
export class Network extends React.Component {
|
||||
static get tabRoutes(): TabLayoutRoute[] {
|
||||
const query = namespaceUrlParam.toObjectParam();
|
||||
const routes: TabLayoutRoute[] = [];
|
||||
|
||||
if (isAllowedResource("services")) {
|
||||
routes.push({
|
||||
title: "Services",
|
||||
component: Services,
|
||||
url: servicesURL({ query }),
|
||||
url: servicesURL(),
|
||||
routePath: servicesRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -50,7 +48,7 @@ export class Network extends React.Component {
|
||||
routes.push({
|
||||
title: "Endpoints",
|
||||
component: Endpoints,
|
||||
url: endpointURL({ query }),
|
||||
url: endpointURL(),
|
||||
routePath: endpointRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -59,7 +57,7 @@ export class Network extends React.Component {
|
||||
routes.push({
|
||||
title: "Ingresses",
|
||||
component: Ingresses,
|
||||
url: ingressURL({ query }),
|
||||
url: ingressURL(),
|
||||
routePath: ingressRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
@@ -68,7 +66,7 @@ export class Network extends React.Component {
|
||||
routes.push({
|
||||
title: "Network Policies",
|
||||
component: NetworkPolicies,
|
||||
url: networkPoliciesURL({ query }),
|
||||
url: networkPoliciesURL(),
|
||||
routePath: networkPoliciesRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,13 +20,12 @@
|
||||
*/
|
||||
|
||||
import { sum } from "lodash";
|
||||
import { action, computed, observable } from "mobx";
|
||||
import { action, computed, observable, makeObservable } from "mobx";
|
||||
import { clusterApi, IClusterMetrics, INodeMetrics, Node, nodesApi } from "../../api/endpoints";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class NodesStore extends KubeObjectStore<Node> {
|
||||
api = nodesApi;
|
||||
|
||||
@@ -35,6 +34,13 @@ export class NodesStore extends KubeObjectStore<Node> {
|
||||
@observable metricsLoading = false;
|
||||
@observable metricsLoaded = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
@action
|
||||
async loadUsageMetrics() {
|
||||
this.metricsLoading = true;
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
*/
|
||||
|
||||
import { PodSecurityPolicy, pspApi } from "../../api/endpoints";
|
||||
import { autobind } from "../../utils";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class PodSecurityPoliciesStore extends KubeObjectStore<PodSecurityPolicy> {
|
||||
api = pspApi;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import "./add-helm-repo-dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import { remote, FileFilter } from "electron";
|
||||
import { observable } from "mobx";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Dialog, DialogProps } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
@@ -46,6 +46,10 @@ enum FileType {
|
||||
CertFile = "certFile",
|
||||
}
|
||||
|
||||
const dialogState = observable.object({
|
||||
isOpen: false,
|
||||
});
|
||||
|
||||
@observer
|
||||
export class AddHelmRepoDialog extends React.Component<Props> {
|
||||
private emptyRepo = {name: "", url: "", username: "", password: "", insecureSkipTlsVerify: false, caFile:"", keyFile: "", certFile: ""};
|
||||
@@ -53,14 +57,17 @@ export class AddHelmRepoDialog extends React.Component<Props> {
|
||||
private static keyExtensions = ["key", "keystore", "jks", "p12", "pfx", "pem"];
|
||||
private static certExtensions = ["crt", "cer", "ca-bundle", "p7b", "p7c" , "p7s", "p12", "pfx", "pem"];
|
||||
|
||||
@observable static isOpen = false;
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
static open() {
|
||||
AddHelmRepoDialog.isOpen = true;
|
||||
dialogState.isOpen = true;
|
||||
}
|
||||
|
||||
static close() {
|
||||
AddHelmRepoDialog.isOpen = false;
|
||||
dialogState.isOpen = false;
|
||||
}
|
||||
|
||||
@observable helmRepo : HelmRepo = this.emptyRepo;
|
||||
@@ -161,7 +168,7 @@ export class AddHelmRepoDialog extends React.Component<Props> {
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="AddHelmRepoDialog"
|
||||
isOpen={AddHelmRepoDialog.isOpen}
|
||||
isOpen={dialogState.isOpen}
|
||||
close={this.close}
|
||||
>
|
||||
<Wizard header={header} done={this.close}>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import "./helm-charts.scss";
|
||||
|
||||
import React from "react";
|
||||
import { action, computed, observable } from "mobx";
|
||||
import { action, computed, observable, makeObservable } from "mobx";
|
||||
|
||||
import { HelmRepo, HelmRepoManager } from "../../../main/helm/helm-repo-manager";
|
||||
import { Button } from "../button";
|
||||
@@ -38,6 +38,11 @@ export class HelmCharts extends React.Component {
|
||||
@observable repos: HelmRepo[] = [];
|
||||
@observable addedRepos = observable.map<string, HelmRepo>();
|
||||
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@computed get options(): SelectOption<HelmRepo>[] {
|
||||
return this.repos.map(repo => ({
|
||||
label: repo.name,
|
||||
|
||||
@@ -23,7 +23,7 @@ import React from "react";
|
||||
import { remote } from "electron";
|
||||
import { Avatar, IconButton, List, ListItem, ListItemAvatar, ListItemSecondaryAction, ListItemText, Paper } from "@material-ui/core";
|
||||
import { Description, Folder, Delete, HelpOutline } from "@material-ui/icons";
|
||||
import { action, computed, observable, reaction } from "mobx";
|
||||
import { action, computed, observable, reaction, makeObservable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import fse from "fs-extra";
|
||||
import { KubeconfigSyncEntry, KubeconfigSyncValue, UserStore } from "../../../common/user-store";
|
||||
@@ -74,6 +74,11 @@ export class KubeconfigSyncs extends React.Component {
|
||||
syncs = observable.map<string, Value>();
|
||||
@observable loaded = false;
|
||||
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const mapEntries = await Promise.all(
|
||||
iter.map(
|
||||
|
||||
@@ -23,7 +23,7 @@ import "./preferences.scss";
|
||||
|
||||
import React from "react";
|
||||
import moment from "moment-timezone";
|
||||
import { computed, observable, reaction } from "mobx";
|
||||
import { computed, observable, reaction, makeObservable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
|
||||
import { isWindows } from "../../../common/vars";
|
||||
@@ -56,6 +56,11 @@ export class Preferences extends React.Component {
|
||||
@observable shell = UserStore.getInstance().shell || "";
|
||||
@observable activeTab = Pages.Application;
|
||||
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@computed get themeOptions(): SelectOption<string>[] {
|
||||
return ThemeStore.getInstance().themes.map(theme => ({
|
||||
label: theme.name,
|
||||
|
||||
@@ -20,15 +20,19 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { StorageClass, storageClassApi } from "../../api/endpoints/storage-class.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import { volumesStore } from "../+storage-volumes/volumes.store";
|
||||
|
||||
@autobind()
|
||||
export class StorageClassStore extends KubeObjectStore<StorageClass> {
|
||||
api = storageClassApi;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getPersistentVolumes(storageClass: StorageClass) {
|
||||
return volumesStore.getByStorageClass(storageClass);
|
||||
}
|
||||
|
||||
@@ -19,17 +19,23 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { action, observable } from "mobx";
|
||||
import { action, observable, makeObservable } from "mobx";
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { IPvcMetrics, PersistentVolumeClaim, pvcApi } from "../../api/endpoints";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
|
||||
@autobind()
|
||||
export class VolumeClaimStore extends KubeObjectStore<PersistentVolumeClaim> {
|
||||
api = pvcApi;
|
||||
@observable metrics: IPvcMetrics = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
@action
|
||||
async loadMetrics(pvc: PersistentVolumeClaim) {
|
||||
this.metrics = await pvcApi.getMetrics(pvc.getName(), pvc.getNs());
|
||||
|
||||
@@ -24,7 +24,7 @@ import "./volume-details-list.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { PersistentVolume } from "../../api/endpoints/persistent-volume.api";
|
||||
import { autobind } from "../../../common/utils/autobind";
|
||||
import { boundMethod } from "../../../common/utils/autobind";
|
||||
import { TableRow } from "../table/table-row";
|
||||
import { cssNames, prevDefault } from "../../utils";
|
||||
import { showDetails } from "../kube-object/kube-object-details";
|
||||
@@ -54,7 +54,7 @@ export class VolumeDetailsList extends React.Component<Props> {
|
||||
[sortBy.status]: (volume: PersistentVolume) => volume.getStatus(),
|
||||
};
|
||||
|
||||
@autobind()
|
||||
@boundMethod
|
||||
getTableRow(uid: string) {
|
||||
const { persistentVolumes } = this.props;
|
||||
const volume = persistentVolumes.find(volume => volume.getId() === uid);
|
||||
|
||||
@@ -20,15 +20,19 @@
|
||||
*/
|
||||
|
||||
import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { autobind } from "../../utils";
|
||||
import { autoBind } from "../../utils";
|
||||
import { PersistentVolume, persistentVolumeApi } from "../../api/endpoints/persistent-volume.api";
|
||||
import { apiManager } from "../../api/api-manager";
|
||||
import type { StorageClass } from "../../api/endpoints/storage-class.api";
|
||||
|
||||
@autobind()
|
||||
export class PersistentVolumesStore extends KubeObjectStore<PersistentVolume> {
|
||||
api = persistentVolumeApi;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
getByStorageClass(storageClass: StorageClass): PersistentVolume[] {
|
||||
return this.items.filter(volume =>
|
||||
volume.getStorageClassName() === storageClass.getName()
|
||||
|
||||
@@ -27,20 +27,18 @@ import { TabLayout, TabLayoutRoute } from "../layout/tab-layout";
|
||||
import { PersistentVolumes, volumesRoute, volumesURL } from "../+storage-volumes";
|
||||
import { StorageClasses, storageClassesRoute, storageClassesURL } from "../+storage-classes";
|
||||
import { PersistentVolumeClaims, volumeClaimsRoute, volumeClaimsURL } from "../+storage-volume-claims";
|
||||
import { namespaceUrlParam } from "../+namespaces/namespace.store";
|
||||
import { isAllowedResource } from "../../../common/rbac";
|
||||
|
||||
@observer
|
||||
export class Storage extends React.Component {
|
||||
static get tabRoutes() {
|
||||
const tabRoutes: TabLayoutRoute[] = [];
|
||||
const query = namespaceUrlParam.toObjectParam();
|
||||
|
||||
if (isAllowedResource("persistentvolumeclaims")) {
|
||||
tabRoutes.push({
|
||||
title: "Persistent Volume Claims",
|
||||
component: PersistentVolumeClaims,
|
||||
url: volumeClaimsURL({ query }),
|
||||
url: volumeClaimsURL(),
|
||||
routePath: volumeClaimsRoute.path.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
Loaded 100 of 256 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user