mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Enforce semicolons in eslint
Signed-off-by: Panu Horsmalahti <phorsmalahti@mirantis.com>
This commit is contained in:
1 parent
0f3f5611ba
commit
1477bb8274
531 files changed
+3979
-3975
No files matched your search
@@ -24,7 +24,7 @@ export class ApiManager {
|
||||
}
|
||||
|
||||
protected resolveApi(api: string | KubeApi): KubeApi {
|
||||
if (typeof api === "string") return this.getApi(api)
|
||||
if (typeof api === "string") return this.getApi(api);
|
||||
return api;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export class ApiManager {
|
||||
registerStore(store: KubeObjectStore, apis: KubeApi[] = [store.api]) {
|
||||
apis.forEach(api => {
|
||||
this.stores.set(api, store);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
getStore(api: string | KubeApi): KubeObjectStore {
|
||||
|
||||
@@ -8,7 +8,7 @@ export class ClusterApi extends KubeApi<Cluster> {
|
||||
|
||||
async getMetrics(nodeNames: string[], params?: IMetricsReqParams): Promise<IClusterMetrics> {
|
||||
const nodes = nodeNames.join("|");
|
||||
const opts = { category: "cluster", nodes: nodes }
|
||||
const opts = { category: "cluster", nodes: nodes };
|
||||
|
||||
return metricsApi.getMetrics({
|
||||
memoryUsage: opts,
|
||||
|
||||
@@ -70,25 +70,25 @@ export class CustomResourceDefinition extends KubeObject {
|
||||
group: this.getGroup(),
|
||||
name: this.getPluralName(),
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
getResourceApiBase() {
|
||||
const { group } = this.spec;
|
||||
return `/apis/${group}/${this.getVersion()}/${this.getPluralName()}`
|
||||
return `/apis/${group}/${this.getVersion()}/${this.getPluralName()}`;
|
||||
}
|
||||
|
||||
getPluralName() {
|
||||
return this.getNames().plural
|
||||
return this.getNames().plural;
|
||||
}
|
||||
|
||||
getResourceKind() {
|
||||
return this.spec.names.kind
|
||||
return this.spec.names.kind;
|
||||
}
|
||||
|
||||
getResourceTitle() {
|
||||
const name = this.getPluralName();
|
||||
return name[0].toUpperCase() + name.substr(1)
|
||||
return name[0].toUpperCase() + name.substr(1);
|
||||
}
|
||||
|
||||
getGroup() {
|
||||
@@ -141,7 +141,7 @@ export class CustomResourceDefinition extends KubeObject {
|
||||
...condition,
|
||||
isReady: status === "True",
|
||||
tooltip: `${message || reason} (${lastTransitionTime})`
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,17 +65,17 @@ export class CronJob extends KubeObject {
|
||||
}
|
||||
|
||||
getSuspendFlag() {
|
||||
return this.spec.suspend.toString()
|
||||
return this.spec.suspend.toString();
|
||||
}
|
||||
|
||||
getLastScheduleTime() {
|
||||
if (!this.status.lastScheduleTime) return "-"
|
||||
const diff = moment().diff(this.status.lastScheduleTime)
|
||||
return formatDuration(diff, true)
|
||||
if (!this.status.lastScheduleTime) return "-";
|
||||
const diff = moment().diff(this.status.lastScheduleTime);
|
||||
return formatDuration(diff, true);
|
||||
}
|
||||
|
||||
getSchedule() {
|
||||
return this.spec.schedule
|
||||
return this.spec.schedule;
|
||||
}
|
||||
|
||||
isNeverRun() {
|
||||
|
||||
@@ -64,9 +64,9 @@ export class DaemonSet extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getImages() {
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", [])
|
||||
const initContainers: IPodContainer[] = get(this, "spec.template.spec.initContainers", [])
|
||||
return [...containers, ...initContainers].map(container => container.image)
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []);
|
||||
const initContainers: IPodContainer[] = get(this, "spec.template.spec.initContainers", []);
|
||||
return [...containers, ...initContainers].map(container => container.image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ import { KubeApi } from "../kube-api";
|
||||
|
||||
export class DeploymentApi extends KubeApi<Deployment> {
|
||||
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||
return this.getUrl(params) + "/scale"
|
||||
return this.getUrl(params) + "/scale";
|
||||
}
|
||||
|
||||
getReplicas(params: { namespace: string; name: string }): Promise<number> {
|
||||
return this.request
|
||||
.get(this.getScaleApiUrl(params))
|
||||
.then(({ status }: any) => status?.replicas)
|
||||
.then(({ status }: any) => status?.replicas);
|
||||
}
|
||||
|
||||
scale(params: { namespace: string; name: string }, replicas: number) {
|
||||
@@ -23,7 +23,7 @@ export class DeploymentApi extends KubeApi<Deployment> {
|
||||
replicas: replicas
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
restart(params: { namespace: string; name: string }) {
|
||||
@@ -42,7 +42,7 @@ export class DeploymentApi extends KubeApi<Deployment> {
|
||||
headers: {
|
||||
'content-type': 'application/strategic-merge-patch+json'
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,16 +170,16 @@ export class Deployment extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getConditions(activeOnly = false) {
|
||||
const { conditions } = this.status
|
||||
if (!conditions) return []
|
||||
const { conditions } = this.status;
|
||||
if (!conditions) return [];
|
||||
if (activeOnly) {
|
||||
return conditions.filter(c => c.status === "True")
|
||||
return conditions.filter(c => c.status === "True");
|
||||
}
|
||||
return conditions
|
||||
return conditions;
|
||||
}
|
||||
|
||||
getConditionsText(activeOnly = true) {
|
||||
return this.getConditions(activeOnly).map(({ type }) => type).join(" ")
|
||||
return this.getConditions(activeOnly).map(({ type }) => type).join(" ");
|
||||
}
|
||||
|
||||
getReplicas() {
|
||||
|
||||
@@ -42,22 +42,22 @@ export class EndpointAddress implements IEndpointAddress {
|
||||
};
|
||||
|
||||
constructor(data: IEndpointAddress) {
|
||||
Object.assign(this, data)
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.ip
|
||||
return this.ip;
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this.hostname
|
||||
return this.hostname;
|
||||
}
|
||||
|
||||
getTargetRef(): ITargetRef {
|
||||
if (this.targetRef) {
|
||||
return Object.assign(this.targetRef, {apiVersion: "v1"})
|
||||
return Object.assign(this.targetRef, {apiVersion: "v1"});
|
||||
} else {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ export class EndpointSubset implements IEndpointSubset {
|
||||
ports: IEndpointPort[];
|
||||
|
||||
constructor(data: IEndpointSubset) {
|
||||
Object.assign(this, data)
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
||||
getAddresses(): EndpointAddress[] {
|
||||
@@ -83,16 +83,16 @@ export class EndpointSubset implements IEndpointSubset {
|
||||
|
||||
toString(): string {
|
||||
if(!this.addresses) {
|
||||
return ""
|
||||
return "";
|
||||
}
|
||||
return this.addresses.map(address => {
|
||||
if (!this.ports) {
|
||||
return address.ip
|
||||
return address.ip;
|
||||
}
|
||||
return this.ports.map(port => {
|
||||
return `${address.ip}:${port.port}`
|
||||
}).join(", ")
|
||||
}).join(", ")
|
||||
return `${address.ip}:${port.port}`;
|
||||
}).join(", ");
|
||||
}).join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +111,9 @@ export class Endpoint extends KubeObject {
|
||||
|
||||
toString(): string {
|
||||
if(this.subsets) {
|
||||
return this.getEndpointSubsets().map(es => es.toString()).join(", ")
|
||||
return this.getEndpointSubsets().map(es => es.toString()).join(", ");
|
||||
} else {
|
||||
return "<none>"
|
||||
return "<none>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,21 +38,21 @@ export class KubeEvent extends KubeObject {
|
||||
}
|
||||
|
||||
getSource() {
|
||||
const { component, host } = this.source
|
||||
return `${component} ${host || ""}`
|
||||
const { component, host } = this.source;
|
||||
return `${component} ${host || ""}`;
|
||||
}
|
||||
|
||||
getFirstSeenTime() {
|
||||
const diff = moment().diff(this.firstTimestamp)
|
||||
return formatDuration(diff, true)
|
||||
const diff = moment().diff(this.firstTimestamp);
|
||||
return formatDuration(diff, true);
|
||||
}
|
||||
|
||||
getLastSeenTime() {
|
||||
const diff = moment().diff(this.lastTimestamp)
|
||||
return formatDuration(diff, true)
|
||||
const diff = moment().diff(this.lastTimestamp);
|
||||
return formatDuration(diff, true);
|
||||
}
|
||||
}
|
||||
|
||||
export const eventApi = new KubeApi({
|
||||
objectConstructor: KubeEvent,
|
||||
})
|
||||
});
|
||||
@@ -41,7 +41,7 @@ export const helmChartsApi = {
|
||||
return {
|
||||
readme,
|
||||
versions,
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ export const helmReleasesApi = {
|
||||
return {
|
||||
...details,
|
||||
resources
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -156,12 +156,12 @@ export class HelmRelease implements ItemObject {
|
||||
}
|
||||
|
||||
getChart(withVersion = false) {
|
||||
let chart = this.chart
|
||||
let chart = this.chart;
|
||||
if(!withVersion && this.getVersion() != "" ) {
|
||||
const search = new RegExp(`-${this.getVersion()}`)
|
||||
const search = new RegExp(`-${this.getVersion()}`);
|
||||
chart = chart.replace(search, "");
|
||||
}
|
||||
return chart
|
||||
return chart;
|
||||
}
|
||||
|
||||
getRevision() {
|
||||
@@ -173,12 +173,12 @@ export class HelmRelease implements ItemObject {
|
||||
}
|
||||
|
||||
getVersion() {
|
||||
const versions = this.chart.match(/(v?\d+)[^-].*$/)
|
||||
const versions = this.chart.match(/(v?\d+)[^-].*$/);
|
||||
if (versions) {
|
||||
return versions[0]
|
||||
return versions[0];
|
||||
}
|
||||
else {
|
||||
return ""
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ export class HorizontalPodAutoscaler extends KubeObject {
|
||||
...condition,
|
||||
isReady: status === "True",
|
||||
tooltip: `${message || reason} (${lastTransitionTime})`
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ export class HorizontalPodAutoscaler extends KubeObject {
|
||||
const { type, resource, pods, object, external } = metric;
|
||||
switch (type) {
|
||||
case HpaMetricType.Resource:
|
||||
return resource.name
|
||||
return resource.name;
|
||||
case HpaMetricType.Pods:
|
||||
return pods.metricName;
|
||||
case HpaMetricType.Object:
|
||||
@@ -128,7 +128,7 @@ export class HorizontalPodAutoscaler extends KubeObject {
|
||||
}
|
||||
if (target) {
|
||||
targetValue = target.targetAverageUtilization || target.targetAverageValue || target.targetValue;
|
||||
if (target.targetAverageUtilization) targetValue += "%"
|
||||
if (target.targetAverageUtilization) targetValue += "%";
|
||||
}
|
||||
return `${currentValue} / ${targetValue}`;
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
// Kubernetes apis
|
||||
// Docs: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/
|
||||
|
||||
export * from "./cluster.api"
|
||||
export * from "./cluster-role.api"
|
||||
export * from "./cluster-role-binding.api"
|
||||
export * from "./configmap.api"
|
||||
export * from "./crd.api"
|
||||
export * from "./cron-job.api"
|
||||
export * from "./daemon-set.api"
|
||||
export * from "./deployment.api"
|
||||
export * from "./endpoint.api"
|
||||
export * from "./events.api"
|
||||
export * from "./hpa.api"
|
||||
export * from "./ingress.api"
|
||||
export * from "./job.api"
|
||||
export * from "./namespaces.api"
|
||||
export * from "./network-policy.api"
|
||||
export * from "./nodes.api"
|
||||
export * from "./persistent-volume.api"
|
||||
export * from "./persistent-volume-claims.api"
|
||||
export * from "./pods.api"
|
||||
export * from "./poddisruptionbudget.api"
|
||||
export * from "./pod-metrics.api"
|
||||
export * from "./podsecuritypolicy.api"
|
||||
export * from "./replica-set.api"
|
||||
export * from "./resource-quota.api"
|
||||
export * from "./role.api"
|
||||
export * from "./role-binding.api"
|
||||
export * from "./secret.api"
|
||||
export * from "./selfsubjectrulesreviews.api"
|
||||
export * from "./service.api"
|
||||
export * from "./service-accounts.api"
|
||||
export * from "./stateful-set.api"
|
||||
export * from "./storage-class.api"
|
||||
export * from "./cluster.api";
|
||||
export * from "./cluster-role.api";
|
||||
export * from "./cluster-role-binding.api";
|
||||
export * from "./configmap.api";
|
||||
export * from "./crd.api";
|
||||
export * from "./cron-job.api";
|
||||
export * from "./daemon-set.api";
|
||||
export * from "./deployment.api";
|
||||
export * from "./endpoint.api";
|
||||
export * from "./events.api";
|
||||
export * from "./hpa.api";
|
||||
export * from "./ingress.api";
|
||||
export * from "./job.api";
|
||||
export * from "./namespaces.api";
|
||||
export * from "./network-policy.api";
|
||||
export * from "./nodes.api";
|
||||
export * from "./persistent-volume.api";
|
||||
export * from "./persistent-volume-claims.api";
|
||||
export * from "./pods.api";
|
||||
export * from "./poddisruptionbudget.api";
|
||||
export * from "./pod-metrics.api";
|
||||
export * from "./podsecuritypolicy.api";
|
||||
export * from "./replica-set.api";
|
||||
export * from "./resource-quota.api";
|
||||
export * from "./role.api";
|
||||
export * from "./role-binding.api";
|
||||
export * from "./secret.api";
|
||||
export * from "./selfsubjectrulesreviews.api";
|
||||
export * from "./service.api";
|
||||
export * from "./service-accounts.api";
|
||||
export * from "./stateful-set.api";
|
||||
export * from "./storage-class.api";
|
||||
@@ -5,7 +5,7 @@ import { KubeApi } from "../kube-api";
|
||||
|
||||
export class IngressApi extends KubeApi<Ingress> {
|
||||
getMetrics(ingress: string, namespace: string): Promise<IIngressMetrics> {
|
||||
const opts = { category: "ingress", ingress }
|
||||
const opts = { category: "ingress", ingress };
|
||||
return metricsApi.getMetrics({
|
||||
bytesSentSuccess: opts,
|
||||
bytesSentFailure: opts,
|
||||
@@ -63,51 +63,51 @@ export class Ingress extends KubeObject {
|
||||
}
|
||||
|
||||
getRoutes() {
|
||||
const { spec: { tls, rules } } = this
|
||||
if (!rules) return []
|
||||
const { spec: { tls, rules } } = this;
|
||||
if (!rules) return [];
|
||||
|
||||
let protocol = "http"
|
||||
const routes: string[] = []
|
||||
let protocol = "http";
|
||||
const routes: string[] = [];
|
||||
if (tls && tls.length > 0) {
|
||||
protocol += "s"
|
||||
protocol += "s";
|
||||
}
|
||||
rules.map(rule => {
|
||||
const host = rule.host ? rule.host : "*"
|
||||
const host = rule.host ? rule.host : "*";
|
||||
if (rule.http && rule.http.paths) {
|
||||
rule.http.paths.forEach(path => {
|
||||
routes.push(protocol + "://" + host + (path.path || "/") + " ⇢ " + path.backend.serviceName + ":" + path.backend.servicePort)
|
||||
})
|
||||
routes.push(protocol + "://" + host + (path.path || "/") + " ⇢ " + path.backend.serviceName + ":" + path.backend.servicePort);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
||||
getHosts() {
|
||||
const { spec: { rules } } = this
|
||||
if (!rules) return []
|
||||
return rules.filter(rule => rule.host).map(rule => rule.host)
|
||||
const { spec: { rules } } = this;
|
||||
if (!rules) return [];
|
||||
return rules.filter(rule => rule.host).map(rule => rule.host);
|
||||
}
|
||||
|
||||
getPorts() {
|
||||
const ports: number[] = []
|
||||
const { spec: { tls, rules, backend } } = this
|
||||
const httpPort = 80
|
||||
const tlsPort = 443
|
||||
const ports: number[] = [];
|
||||
const { spec: { tls, rules, backend } } = this;
|
||||
const httpPort = 80;
|
||||
const tlsPort = 443;
|
||||
if (rules && rules.length > 0) {
|
||||
if (rules.some(rule => rule.hasOwnProperty("http"))) {
|
||||
ports.push(httpPort)
|
||||
ports.push(httpPort);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (backend && backend.servicePort) {
|
||||
ports.push(backend.servicePort)
|
||||
ports.push(backend.servicePort);
|
||||
}
|
||||
}
|
||||
if (tls && tls.length > 0) {
|
||||
ports.push(tlsPort)
|
||||
ports.push(tlsPort);
|
||||
}
|
||||
return ports.join(", ")
|
||||
return ports.join(", ");
|
||||
}
|
||||
|
||||
getLoadBalancers() {
|
||||
@@ -115,7 +115,7 @@ export class Ingress extends KubeObject {
|
||||
|
||||
return (loadBalancer.ingress ?? []).map(address => (
|
||||
address.hostname || address.ip
|
||||
))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,15 +91,15 @@ export class Job extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getImages() {
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", [])
|
||||
return [...containers].map(container => container.image)
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []);
|
||||
return [...containers].map(container => container.image);
|
||||
}
|
||||
|
||||
delete() {
|
||||
const params: JsonApiParams = {
|
||||
query: { propagationPolicy: "Background" }
|
||||
}
|
||||
return super.delete(params)
|
||||
};
|
||||
return super.delete(params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics {
|
||||
} as IMetricsResult],
|
||||
},
|
||||
status: "",
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const { result } = metrics.data;
|
||||
@@ -78,7 +78,7 @@ export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics {
|
||||
if (!res.values || !res.values.length) return;
|
||||
while (res.values.length < frames) {
|
||||
const timestamp = moment.unix(res.values[0][0]).subtract(1, "minute").unix();
|
||||
res.values.unshift([timestamp, "0"])
|
||||
res.values.unshift([timestamp, "0"]);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -103,7 +103,7 @@ export function getItemMetrics(metrics: { [key: string]: IMetrics }, itemName: s
|
||||
const itemMetrics = { ...metrics };
|
||||
for (const metric in metrics) {
|
||||
if (!metrics[metric]?.data?.result) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
const results = metrics[metric].data.result;
|
||||
const result = results.find(res => Object.values(res.metric)[0] == itemName);
|
||||
|
||||
@@ -57,7 +57,7 @@ export class NetworkPolicy extends KubeObject {
|
||||
if (!this.spec.podSelector || !this.spec.podSelector.matchLabels) return [];
|
||||
return Object
|
||||
.entries(this.spec.podSelector.matchLabels)
|
||||
.map(data => data.join(":"))
|
||||
.map(data => data.join(":"));
|
||||
}
|
||||
|
||||
getTypes(): string[] {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { KubeApi } from "../kube-api";
|
||||
|
||||
export class NodesApi extends KubeApi<Node> {
|
||||
getMetrics(): Promise<INodeMetrics> {
|
||||
const opts = { category: "nodes"}
|
||||
const opts = { category: "nodes"};
|
||||
|
||||
return metricsApi.getMetrics({
|
||||
memoryUsage: opts,
|
||||
@@ -86,12 +86,12 @@ export class Node extends KubeObject {
|
||||
}
|
||||
|
||||
getNodeConditionText() {
|
||||
const { conditions } = this.status
|
||||
if (!conditions) return ""
|
||||
const { conditions } = this.status;
|
||||
if (!conditions) return "";
|
||||
return conditions.reduce((types, current) => {
|
||||
if (current.status !== "True") return ""
|
||||
return types += ` ${current.type}`
|
||||
}, "")
|
||||
if (current.status !== "True") return "";
|
||||
return types += ` ${current.type}`;
|
||||
}, "");
|
||||
}
|
||||
|
||||
getTaints() {
|
||||
@@ -101,23 +101,23 @@ export class Node extends KubeObject {
|
||||
getRoleLabels() {
|
||||
const roleLabels = Object.keys(this.metadata.labels).filter(key =>
|
||||
key.includes("node-role.kubernetes.io")
|
||||
).map(key => key.match(/([^/]+$)/)[0]) // all after last slash
|
||||
).map(key => key.match(/([^/]+$)/)[0]); // all after last slash
|
||||
|
||||
if (this.metadata.labels["kubernetes.io/role"] != undefined) {
|
||||
roleLabels.push(this.metadata.labels["kubernetes.io/role"])
|
||||
roleLabels.push(this.metadata.labels["kubernetes.io/role"]);
|
||||
}
|
||||
|
||||
return roleLabels.join(", ")
|
||||
return roleLabels.join(", ");
|
||||
}
|
||||
|
||||
getCpuCapacity() {
|
||||
if (!this.status.capacity || !this.status.capacity.cpu) return 0
|
||||
return cpuUnitsToNumber(this.status.capacity.cpu)
|
||||
if (!this.status.capacity || !this.status.capacity.cpu) return 0;
|
||||
return cpuUnitsToNumber(this.status.capacity.cpu);
|
||||
}
|
||||
|
||||
getMemoryCapacity() {
|
||||
if (!this.status.capacity || !this.status.capacity.memory) return 0
|
||||
return unitsToBytes(this.status.capacity.memory)
|
||||
if (!this.status.capacity || !this.status.capacity.memory) return 0;
|
||||
return unitsToBytes(this.status.capacity.memory);
|
||||
}
|
||||
|
||||
getConditions() {
|
||||
@@ -144,16 +144,16 @@ export class Node extends KubeObject {
|
||||
}
|
||||
|
||||
getOperatingSystem(): string {
|
||||
const label = this.getLabels().find(label => label.startsWith("kubernetes.io/os="))
|
||||
const label = this.getLabels().find(label => label.startsWith("kubernetes.io/os="));
|
||||
if (label) {
|
||||
return label.split("=", 2)[1]
|
||||
return label.split("=", 2)[1];
|
||||
}
|
||||
|
||||
return "linux"
|
||||
return "linux";
|
||||
}
|
||||
|
||||
isUnschedulable() {
|
||||
return this.spec.unschedulable
|
||||
return this.spec.unschedulable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@ export class PersistentVolumeClaim extends KubeObject {
|
||||
}
|
||||
|
||||
getPods(allPods: Pod[]): Pod[] {
|
||||
const pods = allPods.filter(pod => pod.getNs() === this.getNs())
|
||||
const pods = allPods.filter(pod => pod.getNs() === this.getNs());
|
||||
return pods.filter(pod => {
|
||||
return pod.getVolumes().filter(volume =>
|
||||
volume.persistentVolumeClaim &&
|
||||
volume.persistentVolumeClaim.claimName === this.getName()
|
||||
).length > 0
|
||||
})
|
||||
).length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
getStorage(): string {
|
||||
@@ -78,7 +78,7 @@ export class PersistentVolumeClaim extends KubeObject {
|
||||
|
||||
getStatus(): string {
|
||||
if (this.status) return this.status.phase;
|
||||
return "-"
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ export class PersistentVolume extends KubeObject {
|
||||
getCapacity(inBytes = false) {
|
||||
const capacity = this.spec.capacity;
|
||||
if (capacity) {
|
||||
if (inBytes) return unitsToBytes(capacity.storage)
|
||||
if (inBytes) return unitsToBytes(capacity.storage);
|
||||
return capacity.storage;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -11,7 +11,7 @@ export class PodsApi extends KubeApi<Pod> {
|
||||
|
||||
getMetrics(pods: Pod[], namespace: string, selector = "pod, namespace"): Promise<IPodMetrics> {
|
||||
const podSelector = pods.map(pod => pod.getName()).join("|");
|
||||
const opts = { category: "pods", pods: podSelector, namespace, selector }
|
||||
const opts = { category: "pods", pods: podSelector, namespace, selector };
|
||||
|
||||
return metricsApi.getMetrics({
|
||||
cpuUsage: opts,
|
||||
@@ -246,11 +246,11 @@ export class Pod extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getRunningContainers() {
|
||||
const statuses = this.getContainerStatuses()
|
||||
const statuses = this.getContainerStatuses();
|
||||
return this.getAllContainers().filter(container => {
|
||||
return statuses.find(status => status.name === container.name && !!status.state["running"])
|
||||
return statuses.find(status => status.name === container.name && !!status.state["running"]);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getContainerStatuses(includeInitContainers = true) {
|
||||
@@ -323,7 +323,7 @@ export class Pod extends WorkloadKubeObject {
|
||||
const { reason } = state.terminated;
|
||||
message = reason ? reason : "Terminated";
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
if (message) return message;
|
||||
return this.getStatusPhase();
|
||||
@@ -348,32 +348,32 @@ export class Pod extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getNodeSelectors(): string[] {
|
||||
const { nodeSelector } = this.spec
|
||||
if (!nodeSelector) return []
|
||||
return Object.entries(nodeSelector).map(values => values.join(": "))
|
||||
const { nodeSelector } = this.spec;
|
||||
if (!nodeSelector) return [];
|
||||
return Object.entries(nodeSelector).map(values => values.join(": "));
|
||||
}
|
||||
|
||||
getTolerations() {
|
||||
return this.spec.tolerations || []
|
||||
return this.spec.tolerations || [];
|
||||
}
|
||||
|
||||
getAffinity(): IAffinity {
|
||||
return this.spec.affinity
|
||||
return this.spec.affinity;
|
||||
}
|
||||
|
||||
hasIssues() {
|
||||
const notReady = !!this.getConditions().find(condition => {
|
||||
return condition.type == "Ready" && condition.status !== "True"
|
||||
return condition.type == "Ready" && condition.status !== "True";
|
||||
});
|
||||
const crashLoop = !!this.getContainerStatuses().find(condition => {
|
||||
const waiting = condition.state.waiting
|
||||
return (waiting && waiting.reason == "CrashLoopBackOff")
|
||||
})
|
||||
const waiting = condition.state.waiting;
|
||||
return (waiting && waiting.reason == "CrashLoopBackOff");
|
||||
});
|
||||
return (
|
||||
notReady ||
|
||||
crashLoop ||
|
||||
this.getStatusPhase() !== "Running"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getLivenessProbe(container: IPodContainer) {
|
||||
@@ -418,14 +418,14 @@ export class Pod extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getNodeName() {
|
||||
return this.spec?.nodeName
|
||||
return this.spec?.nodeName;
|
||||
}
|
||||
|
||||
getSelectedNodeOs() {
|
||||
if (!this.spec.nodeSelector) return
|
||||
if (!this.spec.nodeSelector["kubernetes.io/os"] && !this.spec.nodeSelector["beta.kubernetes.io/os"]) return
|
||||
if (!this.spec.nodeSelector) return;
|
||||
if (!this.spec.nodeSelector["kubernetes.io/os"] && !this.spec.nodeSelector["beta.kubernetes.io/os"]) return;
|
||||
|
||||
return this.spec.nodeSelector["kubernetes.io/os"] || this.spec.nodeSelector["beta.kubernetes.io/os"]
|
||||
return this.spec.nodeSelector["kubernetes.io/os"] || this.spec.nodeSelector["beta.kubernetes.io/os"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ export class ReplicaSet extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getImages() {
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", [])
|
||||
return [...containers].map(container => container.image)
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []);
|
||||
return [...containers].map(container => container.image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import jsYaml from "js-yaml"
|
||||
import jsYaml from "js-yaml";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeJsonApiData } from "../kube-json-api";
|
||||
import { apiBase } from "../index";
|
||||
@@ -21,7 +21,7 @@ export const resourceApplierApi = {
|
||||
if (api) {
|
||||
return new api.objectConstructor(obj);
|
||||
} else {
|
||||
return new KubeObject(obj)
|
||||
return new KubeObject(obj);
|
||||
}
|
||||
});
|
||||
return items.length === 1 ? items[0] : items;
|
||||
|
||||
@@ -37,7 +37,7 @@ export class ResourceQuota extends KubeObject {
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
super(data);
|
||||
this.spec = this.spec || {} as any
|
||||
this.spec = this.spec || {} as any;
|
||||
}
|
||||
|
||||
spec: {
|
||||
|
||||
@@ -27,7 +27,7 @@ export class RoleBinding extends KubeObject {
|
||||
}
|
||||
|
||||
getSubjectNames(): string {
|
||||
return this.getSubjects().map(subject => subject.name).join(", ")
|
||||
return this.getSubjects().map(subject => subject.name).join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ export class SelfSubjectRulesReview extends KubeObject {
|
||||
const separator = apiGroup == "" ? "" : ".";
|
||||
return resource + separator + apiGroup;
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export class ServicePort implements IServicePort {
|
||||
nodePort?: number;
|
||||
|
||||
constructor(data: IServicePort) {
|
||||
Object.assign(this, data)
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
||||
toString() {
|
||||
@@ -62,7 +62,7 @@ export class Service extends KubeObject {
|
||||
getExternalIps() {
|
||||
const lb = this.getLoadBalancer();
|
||||
if (lb && lb.ingress) {
|
||||
return lb.ingress.map(val => val.ip || val.hostname)
|
||||
return lb.ingress.map(val => val.ip || val.hostname);
|
||||
}
|
||||
return this.spec.externalIPs || [];
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ export class StatefulSet extends WorkloadKubeObject {
|
||||
}
|
||||
|
||||
getImages() {
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", [])
|
||||
return [...containers].map(container => container.image)
|
||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []);
|
||||
return [...containers].map(container => container.image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@ export class StorageClass extends KubeObject {
|
||||
return (
|
||||
annotations["storageclass.kubernetes.io/is-default-class"] === "true" ||
|
||||
annotations["storageclass.beta.kubernetes.io/is-default-class"] === "true"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getVolumeBindingMode() {
|
||||
return this.volumeBindingMode || "-"
|
||||
return this.volumeBindingMode || "-";
|
||||
}
|
||||
|
||||
getReclaimPolicy() {
|
||||
return this.reclaimPolicy || "-"
|
||||
return this.reclaimPolicy || "-";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,23 +110,23 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
||||
} else {
|
||||
const error = new JsonApiErrorParsed(data, this.parseError(data, res));
|
||||
this.onError.emit(error, res);
|
||||
this.writeLog({ ...log, error })
|
||||
this.writeLog({ ...log, error });
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
protected parseError(error: JsonApiError | string, res: Response): string[] {
|
||||
if (typeof error === "string") {
|
||||
return [error]
|
||||
return [error];
|
||||
}
|
||||
else if (Array.isArray(error.errors)) {
|
||||
return error.errors.map(error => error.title)
|
||||
return error.errors.map(error => error.title);
|
||||
}
|
||||
else if (error.message) {
|
||||
return [error.message]
|
||||
return [error.message];
|
||||
}
|
||||
return [res.statusText || "Error!"]
|
||||
return [res.statusText || "Error!"];
|
||||
}
|
||||
|
||||
protected writeLog(log: JsonApiLog) {
|
||||
|
||||
@@ -51,7 +51,7 @@ export function parseKubeApi(path: string): IKubeApiParsed {
|
||||
} else {
|
||||
switch (left.length) {
|
||||
case 4:
|
||||
[apiGroup, apiVersion, resource, name] = left
|
||||
[apiGroup, apiVersion, resource, name] = left;
|
||||
break;
|
||||
case 2:
|
||||
resource = left.pop();
|
||||
@@ -79,11 +79,11 @@ export function parseKubeApi(path: string): IKubeApiParsed {
|
||||
*/
|
||||
if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
|
||||
[apiGroup, apiVersion] = left;
|
||||
resource = left.slice(2).join("/")
|
||||
resource = left.slice(2).join("/");
|
||||
} else {
|
||||
apiGroup = "";
|
||||
apiVersion = left[0];
|
||||
[resource, name] = left.slice(1)
|
||||
[resource, name] = left.slice(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ export function parseKubeApi(path: string): IKubeApiParsed {
|
||||
const apiBase = [apiPrefix, apiGroup, apiVersion, resource].filter(v => v).join("/");
|
||||
|
||||
if (!apiBase) {
|
||||
throw new Error(`invalid apiPath: ${path}`)
|
||||
throw new Error(`invalid apiPath: ${path}`);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -108,11 +108,11 @@ export function createKubeApiURL(ref: IKubeApiLinkRef): string {
|
||||
const { apiPrefix = "/apis", resource, apiVersion, name } = ref;
|
||||
let { namespace } = ref;
|
||||
if (namespace) {
|
||||
namespace = `namespaces/${namespace}`
|
||||
namespace = `namespaces/${namespace}`;
|
||||
}
|
||||
return [apiPrefix, apiVersion, namespace, resource, name]
|
||||
.filter(v => v)
|
||||
.join("/")
|
||||
.join("/");
|
||||
}
|
||||
|
||||
export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string {
|
||||
@@ -124,9 +124,9 @@ export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): st
|
||||
if (!kind) return "";
|
||||
|
||||
// search in registered apis by 'kind' & 'apiVersion'
|
||||
const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion)
|
||||
const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
|
||||
if (api) {
|
||||
return api.getUrl({ namespace, name })
|
||||
return api.getUrl({ namespace, name });
|
||||
}
|
||||
|
||||
// lookup api by generated resource link
|
||||
@@ -142,10 +142,10 @@ export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): st
|
||||
// resolve by kind only (hpa's might use refs to older versions of resources for example)
|
||||
const apiByKind = apiManager.getApi(api => api.kind === kind);
|
||||
if (apiByKind) {
|
||||
return apiByKind.getUrl({ name, namespace })
|
||||
return apiByKind.getUrl({ name, namespace });
|
||||
}
|
||||
|
||||
// otherwise generate link with default prefix
|
||||
// resource still might exists in k8s, but api is not registered in the app
|
||||
return createKubeApiURL({ apiVersion, name, namespace, resource })
|
||||
return createKubeApiURL({ apiVersion, name, namespace, resource });
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Base class for building all kubernetes apis
|
||||
|
||||
import merge from "lodash/merge"
|
||||
import merge from "lodash/merge";
|
||||
import { stringify } from "querystring";
|
||||
import { IKubeObjectConstructor, KubeObject } from "./kube-object";
|
||||
import { KubeJsonApi, KubeJsonApiData, KubeJsonApiDataList } from "./kube-json-api";
|
||||
@@ -51,7 +51,7 @@ export function forCluster<T extends KubeObject>(cluster: IKubeApiCluster, kubeC
|
||||
return new KubeApi({
|
||||
objectConstructor: kubeClass,
|
||||
request: request
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
export class KubeApi<T extends KubeObject = any> {
|
||||
@@ -83,7 +83,7 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
isNamespaced = options.objectConstructor?.namespaced
|
||||
} = options || {};
|
||||
if (!options.apiBase) {
|
||||
options.apiBase = objectConstructor.apiBase
|
||||
options.apiBase = objectConstructor.apiBase;
|
||||
}
|
||||
const { apiBase, apiPrefix, apiGroup, apiVersion, apiVersionWithGroup, resource } = KubeApi.parseApi(options.apiBase);
|
||||
|
||||
@@ -105,7 +105,7 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
get apiVersionWithGroup() {
|
||||
return [this.apiGroup, this.apiVersionPreferred ?? this.apiVersion]
|
||||
.filter(Boolean)
|
||||
.join("/")
|
||||
.join("/");
|
||||
}
|
||||
|
||||
protected async checkPreferredVersion() {
|
||||
@@ -116,7 +116,7 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
});
|
||||
|
||||
if (this.apiVersionPreferred) {
|
||||
Object.defineProperty(this, "apiBase", { value: this.getUrl() })
|
||||
Object.defineProperty(this, "apiBase", { value: this.getUrl() });
|
||||
apiManager.registerApi(this.apiBase, this);
|
||||
}
|
||||
}
|
||||
@@ -147,10 +147,10 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
|
||||
protected normalizeQuery(query: Partial<IKubeApiQueryParams> = {}) {
|
||||
if (query.labelSelector) {
|
||||
query.labelSelector = [query.labelSelector].flat().join(",")
|
||||
query.labelSelector = [query.labelSelector].flat().join(",");
|
||||
}
|
||||
if (query.fieldSelector) {
|
||||
query.fieldSelector = [query.fieldSelector].flat().join(",")
|
||||
query.fieldSelector = [query.fieldSelector].flat().join(",");
|
||||
}
|
||||
return query;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
kind: this.kind,
|
||||
apiVersion: apiVersion,
|
||||
...item,
|
||||
}))
|
||||
}));
|
||||
}
|
||||
|
||||
// custom apis might return array for list response, e.g. users, groups, etc.
|
||||
@@ -218,13 +218,13 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
const apiUrl = this.getUrl({ namespace, name });
|
||||
return this.request
|
||||
.put(apiUrl, { data })
|
||||
.then(this.parseResponse)
|
||||
.then(this.parseResponse);
|
||||
}
|
||||
|
||||
async delete({ name = "", namespace = "default" }) {
|
||||
await this.checkPreferredVersion();
|
||||
const apiUrl = this.getUrl({ namespace, name });
|
||||
return this.request.del(apiUrl)
|
||||
return this.request.del(apiUrl);
|
||||
}
|
||||
|
||||
getWatchUrl(namespace = "", query: IKubeApiQueryParams = {}) {
|
||||
@@ -232,7 +232,7 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
watch: 1,
|
||||
resourceVersion: this.getResourceVersion(namespace),
|
||||
...query,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
watch(): () => void {
|
||||
@@ -240,4 +240,4 @@ export class KubeApi<T extends KubeObject = any> {
|
||||
}
|
||||
}
|
||||
|
||||
export * from "./kube-api-parse"
|
||||
export * from "./kube-api-parse";
|
||||
@@ -1 +1 @@
|
||||
export { kubeObjectDetailRegistry } from "../../extensions/registries/kube-object-detail-registry"
|
||||
export { kubeObjectDetailRegistry } from "../../extensions/registries/kube-object-detail-registry";
|
||||
@@ -65,7 +65,7 @@ export class KubeObject implements ItemObject {
|
||||
|
||||
static stringifyLabels(labels: { [name: string]: string }): string[] {
|
||||
if (!labels) return [];
|
||||
return Object.entries(labels).map(([name, value]) => `${name}=${value}`)
|
||||
return Object.entries(labels).map(([name, value]) => `${name}=${value}`);
|
||||
}
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
@@ -78,7 +78,7 @@ export class KubeObject implements ItemObject {
|
||||
status?: any; // todo: type-safety support
|
||||
|
||||
get selfLink() {
|
||||
return this.metadata.selfLink
|
||||
return this.metadata.selfLink;
|
||||
}
|
||||
|
||||
getId() {
|
||||
@@ -131,18 +131,18 @@ export class KubeObject implements ItemObject {
|
||||
return refs.map(ownerRef => ({
|
||||
...ownerRef,
|
||||
namespace: this.getNs(),
|
||||
}))
|
||||
}));
|
||||
}
|
||||
|
||||
getSearchFields() {
|
||||
const { getName, getId, getNs, getAnnotations, getLabels } = this
|
||||
const { getName, getId, getNs, getAnnotations, getLabels } = this;
|
||||
return [
|
||||
getName(),
|
||||
getNs(),
|
||||
getId(),
|
||||
...getLabels(),
|
||||
...getAnnotations(true),
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
toPlainObject(): object {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Kubernetes watch-api consumer
|
||||
|
||||
import { computed, observable, reaction } from "mobx";
|
||||
import { stringify } from "querystring"
|
||||
import { stringify } from "querystring";
|
||||
import { autobind, EventEmitter } from "../utils";
|
||||
import { KubeJsonApiData } from "./kube-json-api";
|
||||
import type { KubeObjectStore } from "../kube-object.store";
|
||||
@@ -61,13 +61,13 @@ export class KubeWatchApi {
|
||||
}
|
||||
|
||||
protected getQuery(): Partial<IKubeWatchRouteQuery> {
|
||||
const { isAdmin, allowedNamespaces } = getHostedCluster()
|
||||
const { isAdmin, allowedNamespaces } = getHostedCluster();
|
||||
return {
|
||||
api: this.activeApis.map(api => {
|
||||
if (isAdmin) return api.getWatchUrl();
|
||||
return allowedNamespaces.map(namespace => api.getWatchUrl(namespace))
|
||||
return allowedNamespaces.map(namespace => api.getWatchUrl(namespace));
|
||||
}).flat()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// todo: maybe switch to websocket to avoid often reconnects
|
||||
@@ -119,11 +119,11 @@ export class KubeWatchApi {
|
||||
await api.refreshResourceVersion({ namespace });
|
||||
this.reconnect();
|
||||
} catch (error) {
|
||||
console.error("failed to refresh resource version", error)
|
||||
console.error("failed to refresh resource version", error);
|
||||
if (this.subscribers.size > 0) {
|
||||
setTimeout(() => {
|
||||
this.onRouteEvent(event)
|
||||
}, 1000)
|
||||
this.onRouteEvent(event);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { stringify } from "querystring";
|
||||
import { autobind, base64, EventEmitter } from "../utils";
|
||||
import { WebSocketApi } from "./websocket-api";
|
||||
import isEqual from "lodash/isEqual"
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { isDevelopment } from "../../common/vars";
|
||||
|
||||
export enum TerminalChannels {
|
||||
@@ -51,7 +51,7 @@ export class TerminalApi extends WebSocketApi {
|
||||
const wss = `ws${protocol === "https:" ? "s" : ""}://`;
|
||||
const query: TerminalApiQuery = { id };
|
||||
if (port) {
|
||||
port = `:${port}`
|
||||
port = `:${port}`;
|
||||
}
|
||||
if (node) {
|
||||
query.node = node;
|
||||
|
||||
@@ -146,7 +146,7 @@ export class WebSocketApi {
|
||||
}
|
||||
|
||||
protected _onError(evt: Event) {
|
||||
this.writeLog('%cERROR', 'color:red;font-weight:bold;', evt)
|
||||
this.writeLog('%cERROR', 'color:red;font-weight:bold;', evt);
|
||||
}
|
||||
|
||||
protected _onClose(evt: CloseEvent) {
|
||||
|
||||
@@ -65,16 +65,16 @@ export class WorkloadKubeObject extends KubeObject {
|
||||
}
|
||||
|
||||
getTolerations(): IToleration[] {
|
||||
return get(this, "spec.template.spec.tolerations", [])
|
||||
return get(this, "spec.template.spec.tolerations", []);
|
||||
}
|
||||
|
||||
getAffinity(): IAffinity {
|
||||
return get(this, "spec.template.spec.affinity")
|
||||
return get(this, "spec.template.spec.affinity");
|
||||
}
|
||||
|
||||
getAffinityNumber() {
|
||||
const affinity = this.getAffinity()
|
||||
if (!affinity) return 0
|
||||
return Object.keys(affinity).length
|
||||
const affinity = this.getAffinity();
|
||||
if (!affinity) return 0;
|
||||
return Object.keys(affinity).length;
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -1,9 +1,9 @@
|
||||
import "./components/app.scss"
|
||||
import "./components/app.scss";
|
||||
|
||||
import React from "react";
|
||||
import * as Mobx from "mobx"
|
||||
import * as MobxReact from "mobx-react"
|
||||
import * as LensExtensions from "../extensions/extension-api"
|
||||
import * as Mobx from "mobx";
|
||||
import * as MobxReact from "mobx-react";
|
||||
import * as LensExtensions from "../extensions/extension-api";
|
||||
import { App } from "./components/app";
|
||||
import { LensApp } from "./lens-app";
|
||||
import { render, unmountComponentAtNode } from "react-dom";
|
||||
@@ -25,13 +25,13 @@ export {
|
||||
Mobx,
|
||||
MobxReact,
|
||||
LensExtensions
|
||||
}
|
||||
};
|
||||
|
||||
export async function bootstrap(App: AppComponent) {
|
||||
const rootElem = document.getElementById("app")
|
||||
const rootElem = document.getElementById("app");
|
||||
rootElem.classList.toggle("is-mac", isMac);
|
||||
|
||||
extensionLoader.init()
|
||||
extensionLoader.init();
|
||||
|
||||
// preload common stores
|
||||
await Promise.all([
|
||||
@@ -53,13 +53,13 @@ export async function bootstrap(App: AppComponent) {
|
||||
}
|
||||
window.addEventListener("message", (ev: MessageEvent) => {
|
||||
if (ev.data === "teardown") {
|
||||
userStore.unregisterIpcListener()
|
||||
workspaceStore.unregisterIpcListener()
|
||||
clusterStore.unregisterIpcListener()
|
||||
unmountComponentAtNode(rootElem)
|
||||
window.location.href = "about:blank"
|
||||
userStore.unregisterIpcListener();
|
||||
workspaceStore.unregisterIpcListener();
|
||||
clusterStore.unregisterIpcListener();
|
||||
unmountComponentAtNode(rootElem);
|
||||
window.location.href = "about:blank";
|
||||
}
|
||||
})
|
||||
});
|
||||
render(<>
|
||||
{isMac && <div id="draggable-top" />}
|
||||
<App />
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from "./not-found"
|
||||
export * from "./not-found";
|
||||
@@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const addClusterRoute: RouteProps = {
|
||||
path: "/add-cluster"
|
||||
}
|
||||
};
|
||||
|
||||
export const addClusterURL = buildURL(addClusterRoute.path)
|
||||
export const addClusterURL = buildURL(addClusterRoute.path);
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./add-cluster.scss"
|
||||
import "./add-cluster.scss";
|
||||
import os from "os";
|
||||
import React, { Fragment } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
@@ -16,7 +16,7 @@ import { WizardLayout } from "../layout/wizard-layout";
|
||||
import { kubeConfigDefaultPath, loadConfig, splitConfig, validateConfig, validateKubeConfig } from "../../../common/kube-helpers";
|
||||
import { ClusterModel, ClusterStore, clusterStore } from "../../../common/cluster-store";
|
||||
import { workspaceStore } from "../../../common/workspace-store";
|
||||
import { v4 as uuid } from "uuid"
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { navigate } from "../../navigation";
|
||||
import { userStore } from "../../../common/user-store";
|
||||
import { clusterViewURL } from "../cluster-manager/cluster-view.route";
|
||||
@@ -84,7 +84,7 @@ export class AddCluster extends React.Component {
|
||||
break;
|
||||
case KubeConfigSourceTab.TEXT:
|
||||
try {
|
||||
this.error = ""
|
||||
this.error = "";
|
||||
const contexts = this.getContexts(loadConfig(this.customConfig || "{}"));
|
||||
this.kubeContexts.replace(contexts);
|
||||
} catch (err) {
|
||||
@@ -94,7 +94,7 @@ export class AddCluster extends React.Component {
|
||||
}
|
||||
|
||||
if (this.kubeContexts.size === 1) {
|
||||
this.selectedContexts.push(this.kubeContexts.keys().next().value)
|
||||
this.selectedContexts.push(this.kubeContexts.keys().next().value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +102,8 @@ export class AddCluster extends React.Component {
|
||||
const contexts = new Map();
|
||||
splitConfig(config).forEach(config => {
|
||||
contexts.set(config.currentContext, config);
|
||||
})
|
||||
return contexts
|
||||
});
|
||||
return contexts;
|
||||
}
|
||||
|
||||
selectKubeConfigDialog = async () => {
|
||||
@@ -124,11 +124,11 @@ export class AddCluster extends React.Component {
|
||||
let newClusters: ClusterModel[] = [];
|
||||
try {
|
||||
if (!this.selectedContexts.length) {
|
||||
this.error = <Trans>Please select at least one cluster context</Trans>
|
||||
this.error = <Trans>Please select at least one cluster context</Trans>;
|
||||
return;
|
||||
}
|
||||
this.error = ""
|
||||
this.isWaiting = true
|
||||
this.error = "";
|
||||
this.isWaiting = true;
|
||||
|
||||
newClusters = this.selectedContexts.filter(context => {
|
||||
try {
|
||||
@@ -136,7 +136,7 @@ export class AddCluster extends React.Component {
|
||||
validateKubeConfig(kubeConfig);
|
||||
return true;
|
||||
} catch (err) {
|
||||
this.error = String(err.message)
|
||||
this.error = String(err.message);
|
||||
if (err instanceof ExecValidationNotFoundError ) {
|
||||
Notifications.error(<Trans>Error while adding cluster(s): {this.error}</Trans>);
|
||||
return false;
|
||||
@@ -159,8 +159,8 @@ export class AddCluster extends React.Component {
|
||||
clusterName: kubeConfig.currentContext,
|
||||
httpsProxy: this.proxyServer || undefined,
|
||||
},
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
clusterStore.addClusters(...newClusters);
|
||||
@@ -175,7 +175,7 @@ export class AddCluster extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
this.refreshContexts();
|
||||
} catch (err) {
|
||||
this.error = String(err);
|
||||
@@ -218,7 +218,7 @@ export class AddCluster extends React.Component {
|
||||
Lens app might not have all login shell env variables set automatically.
|
||||
</p>
|
||||
</Fragment>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderKubeConfigSource() {
|
||||
@@ -281,7 +281,7 @@ export class AddCluster extends React.Component {
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderContextSelector() {
|
||||
@@ -302,7 +302,7 @@ export class AddCluster extends React.Component {
|
||||
noOptionsMessage={() => _i18n._(t`No contexts available or they have been added already`)}
|
||||
onChange={({ value: ctx }: SelectOption<string>) => {
|
||||
if (this.selectedContexts.includes(ctx)) {
|
||||
this.selectedContexts.remove(ctx)
|
||||
this.selectedContexts.remove(ctx);
|
||||
} else {
|
||||
this.selectedContexts.push(ctx);
|
||||
}
|
||||
@@ -315,7 +315,7 @@ export class AddCluster extends React.Component {
|
||||
</small>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
onKubeConfigInputBlur = (evt: React.FocusEvent<HTMLInputElement>) => {
|
||||
@@ -345,11 +345,11 @@ export class AddCluster extends React.Component {
|
||||
{isNew && <Icon small material="fiber_new" />}
|
||||
{isSelected && <Icon small material="check" className="box right" />}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const addDisabled = this.selectedContexts.length === 0
|
||||
const addDisabled = this.selectedContexts.length === 0;
|
||||
|
||||
return (
|
||||
<WizardLayout
|
||||
@@ -361,12 +361,12 @@ export class AddCluster extends React.Component {
|
||||
onDragLeave: event => this.dropAreaActive = false,
|
||||
onDragOver: event => {
|
||||
event.preventDefault(); // enable onDrop()-callback
|
||||
event.dataTransfer.dropEffect = "move"
|
||||
event.dataTransfer.dropEffect = "move";
|
||||
},
|
||||
onDrop: event => {
|
||||
this.sourceTab = KubeConfigSourceTab.FILE;
|
||||
this.dropAreaActive = false
|
||||
this.setKubeConfig(event.dataTransfer.files[0].path)
|
||||
this.dropAreaActive = false;
|
||||
this.setKubeConfig(event.dataTransfer.files[0].path);
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -407,6 +407,6 @@ export class AddCluster extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
</WizardLayout>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "./add-cluster"
|
||||
export * from "./add-cluster.route"
|
||||
export * from "./add-cluster";
|
||||
export * from "./add-cluster.route";
|
||||
@@ -35,16 +35,16 @@ export class HelmChartDetails extends Component<Props> {
|
||||
}
|
||||
|
||||
chartUpdater = autorun(() => {
|
||||
this.selectedChart = null
|
||||
const { chart: { name, repo, version } } = this.props
|
||||
this.selectedChart = null;
|
||||
const { chart: { name, repo, version } } = this.props;
|
||||
helmChartsApi.get(repo, name, version).then(result => {
|
||||
this.readme = result.readme
|
||||
this.chartVersions = result.versions
|
||||
this.selectedChart = result.versions[0]
|
||||
this.readme = result.readme;
|
||||
this.chartVersions = result.versions;
|
||||
this.selectedChart = result.versions[0];
|
||||
},
|
||||
error => {
|
||||
this.error = error;
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@autobind()
|
||||
@@ -55,7 +55,7 @@ export class HelmChartDetails extends Component<Props> {
|
||||
try {
|
||||
this.chartPromise?.cancel();
|
||||
const { chart: { name, repo } } = this.props;
|
||||
const { readme } = await (this.chartPromise = helmChartsApi.get(repo, name, version))
|
||||
const { readme } = await (this.chartPromise = helmChartsApi.get(repo, name, version));
|
||||
this.readme = readme;
|
||||
} catch (error) {
|
||||
this.error = error;
|
||||
@@ -65,7 +65,7 @@ export class HelmChartDetails extends Component<Props> {
|
||||
@autobind()
|
||||
install() {
|
||||
createInstallChartTab(this.selectedChart);
|
||||
this.props.hideDetails()
|
||||
this.props.hideDetails();
|
||||
}
|
||||
|
||||
renderIntroduction() {
|
||||
@@ -112,14 +112,14 @@ export class HelmChartDetails extends Component<Props> {
|
||||
|
||||
renderReadme() {
|
||||
if (this.readme === null) {
|
||||
return <Spinner center />
|
||||
return <Spinner center />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="chart-description">
|
||||
<MarkdownViewer markdown={this.readme} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
@@ -132,7 +132,7 @@ export class HelmChartDetails extends Component<Props> {
|
||||
<div className="box grow">
|
||||
<p className="error">{this.error}</p>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import semver from "semver"
|
||||
import semver from "semver";
|
||||
import { observable } from "mobx";
|
||||
import { autobind } from "../../utils";
|
||||
import { HelmChart, helmChartsApi } from "../../api/endpoints/helm-charts.api";
|
||||
import { ItemStore } from "../../item.store";
|
||||
import flatten from "lodash/flatten"
|
||||
import flatten from "lodash/flatten";
|
||||
|
||||
export interface IChartVersion {
|
||||
repo: string;
|
||||
@@ -24,7 +24,7 @@ export class HelmChartStore extends ItemStore<HelmChart> {
|
||||
|
||||
protected sortVersions = (versions: IChartVersion[]) => {
|
||||
return versions.sort((first, second) => {
|
||||
return semver.compare(second.version, first.version)
|
||||
return semver.compare(second.version, first.version);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -38,8 +38,8 @@ export class HelmChartStore extends ItemStore<HelmChart> {
|
||||
return versions.map(chart => ({
|
||||
repo: repo,
|
||||
version: chart.getVersion()
|
||||
}))
|
||||
})
|
||||
}));
|
||||
});
|
||||
};
|
||||
if (!this.isLoaded) {
|
||||
await this.loadAll();
|
||||
|
||||
@@ -4,11 +4,11 @@ import { appsRoute } from "../+apps/apps.route";
|
||||
|
||||
export const helmChartsRoute: RouteProps = {
|
||||
path: appsRoute.path + "/charts/:repo?/:chartName?"
|
||||
}
|
||||
};
|
||||
|
||||
export interface IHelmChartsRouteParams {
|
||||
chartName?: string;
|
||||
repo?: string;
|
||||
}
|
||||
|
||||
export const helmChartsURL = buildURL<IHelmChartsRouteParams>(helmChartsRoute.path)
|
||||
export const helmChartsURL = buildURL<IHelmChartsRouteParams>(helmChartsRoute.path);
|
||||
@@ -28,13 +28,13 @@ export class HelmCharts extends Component<Props> {
|
||||
}
|
||||
|
||||
get selectedChart() {
|
||||
const { match: { params: { chartName, repo } } } = this.props
|
||||
const { match: { params: { chartName, repo } } } = this.props;
|
||||
return helmChartStore.getByName(chartName, repo);
|
||||
}
|
||||
|
||||
showDetails = (chart: HelmChart) => {
|
||||
if (!chart) {
|
||||
navigation.merge(helmChartsURL())
|
||||
navigation.merge(helmChartsURL());
|
||||
}
|
||||
else {
|
||||
navigation.merge(helmChartsURL({
|
||||
@@ -42,7 +42,7 @@ export class HelmCharts extends Component<Props> {
|
||||
chartName: chart.getName(),
|
||||
repo: chart.getRepository(),
|
||||
}
|
||||
}))
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ export class ReleaseDetails extends Component<Props> {
|
||||
updateValues = async () => {
|
||||
const { release } = this.props;
|
||||
const name = release.getName();
|
||||
const namespace = release.getNs()
|
||||
const namespace = release.getNs();
|
||||
const data = {
|
||||
chart: release.getChart(),
|
||||
repo: await release.getRepo(),
|
||||
@@ -121,7 +121,7 @@ export class ReleaseDetails extends Component<Props> {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderNotes() {
|
||||
@@ -222,13 +222,13 @@ export class ReleaseDetails extends Component<Props> {
|
||||
<DrawerTitle title={_i18n._(t`Resources`)}/>
|
||||
{this.renderResources()}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { release, hideDetails } = this.props
|
||||
const title = release ? <Trans>Release: {release.getName()}</Trans> : ""
|
||||
const toolbar = <HelmReleaseMenu release={release} toolbar hideDetails={hideDetails}/>
|
||||
const { release, hideDetails } = this.props;
|
||||
const title = release ? <Trans>Release: {release.getName()}</Trans> : "";
|
||||
const toolbar = <HelmReleaseMenu release={release} toolbar hideDetails={hideDetails}/>;
|
||||
return (
|
||||
<Drawer
|
||||
className={cssNames("ReleaseDetails", themeStore.activeTheme.type)}
|
||||
@@ -240,6 +240,6 @@ export class ReleaseDetails extends Component<Props> {
|
||||
>
|
||||
{this.renderContent()}
|
||||
</Drawer>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ export class HelmReleaseMenu extends React.Component<Props> {
|
||||
</MenuItem>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { HelmRelease, helmReleasesApi, IReleaseRevision } from "../../api/endpoi
|
||||
import { releaseStore } from "./release.store";
|
||||
import { Select, SelectOption } from "../select";
|
||||
import { Notifications } from "../notifications";
|
||||
import orderBy from "lodash/orderBy"
|
||||
import orderBy from "lodash/orderBy";
|
||||
|
||||
interface Props extends DialogProps {
|
||||
}
|
||||
@@ -65,7 +65,7 @@ export class ReleaseRollbackDialog extends React.Component<Props> {
|
||||
renderContent() {
|
||||
const { revision, revisions } = this;
|
||||
if (!revision) {
|
||||
return <p><Trans>No revisions to rollback.</Trans></p>
|
||||
return <p><Trans>No revisions to rollback.</Trans></p>;
|
||||
}
|
||||
return (
|
||||
<div className="flex gaps align-center">
|
||||
@@ -78,13 +78,13 @@ export class ReleaseRollbackDialog extends React.Component<Props> {
|
||||
onChange={({ value }: SelectOption<IReleaseRevision>) => this.revision = value}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { ...dialogProps } = this.props;
|
||||
const releaseName = this.release ? this.release.getName() : "";
|
||||
const header = <h5><Trans>Rollback <b>{releaseName}</b></Trans></h5>
|
||||
const header = <h5><Trans>Rollback <b>{releaseName}</b></Trans></h5>;
|
||||
return (
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
@@ -104,6 +104,6 @@ export class ReleaseRollbackDialog extends React.Component<Props> {
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
</Dialog>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { appsRoute } from "../+apps/apps.route";
|
||||
|
||||
export const releaseRoute: RouteProps = {
|
||||
path: appsRoute.path + "/releases/:namespace?/:name?"
|
||||
}
|
||||
};
|
||||
|
||||
export interface IReleaseRouteParams {
|
||||
name?: string;
|
||||
|
||||
@@ -33,7 +33,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
this.loadAll();
|
||||
}
|
||||
this.releaseSecrets = [...secrets];
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
unwatch() {
|
||||
@@ -48,7 +48,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
const labels = {
|
||||
owner: "helm",
|
||||
name: release.getName()
|
||||
}
|
||||
};
|
||||
return secretsStore.getByLabel(labels)
|
||||
.filter(secret => secret.getNs() == release.getNs())[0];
|
||||
}
|
||||
@@ -58,7 +58,7 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
|
||||
this.isLoading = true;
|
||||
let items;
|
||||
try {
|
||||
const { isAdmin, allowedNamespaces } = getHostedCluster()
|
||||
const { isAdmin, allowedNamespaces } = getHostedCluster();
|
||||
items = await this.loadItems(!isAdmin ? allowedNamespaces : null);
|
||||
} finally {
|
||||
if (items) {
|
||||
|
||||
@@ -48,7 +48,7 @@ export class HelmReleases extends Component<Props> {
|
||||
|
||||
showDetails = (item: HelmRelease) => {
|
||||
if (!item) {
|
||||
navigation.merge(releaseURL())
|
||||
navigation.merge(releaseURL());
|
||||
}
|
||||
else {
|
||||
navigation.merge(releaseURL({
|
||||
@@ -56,7 +56,7 @@ export class HelmReleases extends Component<Props> {
|
||||
name: item.getName(),
|
||||
namespace: item.getNs()
|
||||
}
|
||||
}))
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export class HelmReleases extends Component<Props> {
|
||||
<Trans>Note: StatefulSet Volumes won't be deleted automatically</Trans>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -122,7 +122,7 @@ export class HelmReleases extends Component<Props> {
|
||||
release.appVersion,
|
||||
{ title: release.getStatus(), className: kebabCase(release.getStatus()) },
|
||||
release.getUpdated(),
|
||||
]
|
||||
];
|
||||
}}
|
||||
renderItemMenu={(release: HelmRelease) => {
|
||||
return (
|
||||
@@ -130,7 +130,7 @@ export class HelmReleases extends Component<Props> {
|
||||
release={release}
|
||||
removeConfirmationMessage={this.renderRemoveDialogMessage([release])}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}}
|
||||
customizeRemoveDialog={(selectedItems: HelmRelease[]) => ({
|
||||
message: this.renderRemoveDialogMessage(selectedItems)
|
||||
|
||||
@@ -23,12 +23,12 @@ export class Apps extends React.Component {
|
||||
url: releaseURL({ query }),
|
||||
routePath: releaseRoute.path.toString(),
|
||||
},
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TabLayout className="Apps" tabs={Apps.tabRoutes}/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,6 @@ export interface IClusterSettingsRouteParams extends IClusterViewRouteParams {
|
||||
|
||||
export const clusterSettingsRoute: RouteProps = {
|
||||
path: `/cluster/:clusterId/settings`,
|
||||
}
|
||||
};
|
||||
|
||||
export const clusterSettingsURL = buildURL<IClusterSettingsRouteParams>(clusterSettingsRoute.path)
|
||||
export const clusterSettingsURL = buildURL<IClusterSettingsRouteParams>(clusterSettingsRoute.path);
|
||||
@@ -14,7 +14,7 @@ import { IClusterSettingsRouteParams } from "./cluster-settings.route";
|
||||
import { clusterStore } from "../../../common/cluster-store";
|
||||
import { PageLayout } from "../layout/page-layout";
|
||||
import { requestMain } from "../../../common/ipc";
|
||||
import { clusterActivateHandler, clusterRefreshHandler } from "../../../common/cluster-ipc"
|
||||
import { clusterActivateHandler, clusterRefreshHandler } from "../../../common/cluster-ipc";
|
||||
|
||||
interface Props extends RouteComponentProps<IClusterSettingsRouteParams> {
|
||||
}
|
||||
@@ -22,7 +22,7 @@ interface Props extends RouteComponentProps<IClusterSettingsRouteParams> {
|
||||
@observer
|
||||
export class ClusterSettings extends React.Component<Props> {
|
||||
get clusterId() {
|
||||
return this.props.match.params.clusterId
|
||||
return this.props.match.params.clusterId;
|
||||
}
|
||||
|
||||
get cluster(): Cluster {
|
||||
@@ -37,18 +37,18 @@ export class ClusterSettings extends React.Component<Props> {
|
||||
reaction(() => this.clusterId, clusterId => clusterStore.setActive(clusterId), {
|
||||
fireImmediately: true,
|
||||
})
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
refreshCluster = async () => {
|
||||
if (this.cluster) {
|
||||
await requestMain(clusterActivateHandler, this.cluster.id)
|
||||
await requestMain(clusterRefreshHandler, this.cluster.id)
|
||||
await requestMain(clusterActivateHandler, this.cluster.id);
|
||||
await requestMain(clusterRefreshHandler, this.cluster.id);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const cluster = this.cluster
|
||||
const cluster = this.cluster;
|
||||
if (!cluster) return null;
|
||||
const header = (
|
||||
<>
|
||||
|
||||
@@ -35,14 +35,14 @@ export class ClusterIconSetting extends React.Component<Props> {
|
||||
cluster.preferences.icon = undefined;
|
||||
}
|
||||
} catch (e) {
|
||||
this.errorText = e.toString()
|
||||
this.status = GeneralInputStatus.ERROR
|
||||
this.errorText = e.toString();
|
||||
this.status = GeneralInputStatus.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
getClearButton() {
|
||||
if (this.props.cluster.preferences.icon) {
|
||||
return <Button tooltip="Revert back to default icon" accent onClick={() => this.onIconPick([])}>Clear</Button>
|
||||
return <Button tooltip="Revert back to default icon" accent onClick={() => this.onIconPick([])}>Clear</Button>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ export class ClusterPrometheusSetting extends React.Component<Props> {
|
||||
service: parsed[1],
|
||||
port: parseInt(parsed[2]),
|
||||
prefix: apiPrefix
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
onSaveProvider = () => {
|
||||
|
||||
@@ -19,21 +19,21 @@ export class InstallFeature extends React.Component<Props> {
|
||||
@observable message = "";
|
||||
|
||||
componentDidMount() {
|
||||
const feature = this.props.feature
|
||||
const cluster = this.props.cluster
|
||||
const feature = this.props.feature;
|
||||
const cluster = this.props.cluster;
|
||||
const statusUpdate = interval(20, () => {
|
||||
feature.updateStatus(cluster)
|
||||
})
|
||||
statusUpdate.start(true)
|
||||
feature.updateStatus(cluster);
|
||||
});
|
||||
statusUpdate.start(true);
|
||||
|
||||
disposeOnUnmount(this, () => {
|
||||
statusUpdate.stop()
|
||||
})
|
||||
statusUpdate.stop();
|
||||
});
|
||||
|
||||
disposeOnUnmount(this,
|
||||
reaction(() => feature.status.installed, () => {
|
||||
this.loading = false;
|
||||
this.message = ""
|
||||
this.message = "";
|
||||
}, { equals: comparer.structural })
|
||||
);
|
||||
}
|
||||
@@ -60,8 +60,8 @@ export class InstallFeature extends React.Component<Props> {
|
||||
accent
|
||||
disabled={disabled}
|
||||
onClick={this.runAction(async () => {
|
||||
this.message = "Uninstalling feature ..."
|
||||
feature.uninstall(cluster)
|
||||
this.message = "Uninstalling feature ...";
|
||||
feature.uninstall(cluster);
|
||||
})}
|
||||
>
|
||||
Uninstall
|
||||
@@ -72,8 +72,8 @@ export class InstallFeature extends React.Component<Props> {
|
||||
primary
|
||||
disabled={disabled}
|
||||
onClick={this.runAction(async () =>{
|
||||
this.message = "Installing feature ..."
|
||||
feature.install(cluster)
|
||||
this.message = "Installing feature ...";
|
||||
feature.install(cluster);
|
||||
})}
|
||||
>
|
||||
Install
|
||||
|
||||
@@ -23,7 +23,7 @@ export class RemoveClusterButton extends React.Component<Props> {
|
||||
ok: async () => {
|
||||
await clusterStore.removeById(cluster.id);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -22,7 +22,7 @@ export class Features extends React.Component<Props> {
|
||||
<p><f.components.Description /></p>
|
||||
</>
|
||||
</InstallFeature>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "./cluster-settings.route"
|
||||
export * from "./cluster-settings"
|
||||
export * from "./cluster-settings.route";
|
||||
export * from "./cluster-settings";
|
||||
@@ -14,7 +14,7 @@ export class Status extends React.Component<Props> {
|
||||
@autobind()
|
||||
openKubeconfig() {
|
||||
const { cluster } = this.props;
|
||||
shell.showItemInFolder(cluster.kubeConfigPath)
|
||||
shell.showItemInFolder(cluster.kubeConfigPath);
|
||||
}
|
||||
|
||||
renderStatusRows() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./cluster-issues.scss"
|
||||
import "./cluster-issues.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
@@ -43,7 +43,7 @@ export class ClusterIssues extends React.Component<Props> {
|
||||
|
||||
// Node bad conditions
|
||||
nodesStore.items.forEach(node => {
|
||||
const { kind, selfLink, getId, getName } = node
|
||||
const { kind, selfLink, getId, getName } = node;
|
||||
node.getWarningConditions().forEach(({ message }) => {
|
||||
warnings.push({
|
||||
kind,
|
||||
@@ -51,8 +51,8 @@ export class ClusterIssues extends React.Component<Props> {
|
||||
getName,
|
||||
selfLink,
|
||||
message,
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Warning events for Workloads
|
||||
@@ -67,7 +67,7 @@ export class ClusterIssues extends React.Component<Props> {
|
||||
kind,
|
||||
selfLink: lookupApiLink(involvedObject, error),
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ export const ClusterMetrics = observer(() => {
|
||||
return <Spinner center/>;
|
||||
}
|
||||
if (!memoryCapacity || !cpuCapacity) {
|
||||
return <ClusterNoMetrics className="empty"/>
|
||||
return <ClusterNoMetrics className="empty"/>;
|
||||
}
|
||||
return (
|
||||
<BarChart
|
||||
|
||||
@@ -24,7 +24,7 @@ export const ClusterPieCharts = observer(() => {
|
||||
<p><Trans>Specified limits are higher than node capacity!</Trans></p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const renderCharts = () => {
|
||||
const data = getMetricLastPoints(clusterStore.metrics);
|
||||
@@ -168,7 +168,7 @@ export const ClusterPieCharts = observer(() => {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
const { masterNodes, workerNodes } = nodesStore;
|
||||
@@ -194,11 +194,11 @@ export const ClusterPieCharts = observer(() => {
|
||||
return <ClusterNoMetrics className="empty"/>;
|
||||
}
|
||||
return renderCharts();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="ClusterPieCharts flex">
|
||||
{renderContent()}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
});
|
||||
@@ -3,6 +3,6 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const clusterRoute: RouteProps = {
|
||||
path: "/cluster"
|
||||
}
|
||||
};
|
||||
|
||||
export const clusterURL = buildURL(clusterRoute.path)
|
||||
export const clusterURL = buildURL(clusterRoute.path);
|
||||
@@ -35,7 +35,7 @@ export class ClusterStore extends KubeObjectStore<Cluster> {
|
||||
Object.assign(this, storage.get());
|
||||
reaction(() => {
|
||||
const { metricType, metricNodeRole } = this;
|
||||
return { metricType, metricNodeRole }
|
||||
return { metricType, metricNodeRole };
|
||||
},
|
||||
settings => storage.set(settings)
|
||||
);
|
||||
@@ -85,9 +85,9 @@ export class ClusterStore extends KubeObjectStore<Cluster> {
|
||||
getMetricsValues(source: Partial<IClusterMetrics>): [number, string][] {
|
||||
switch (this.metricType) {
|
||||
case MetricType.CPU:
|
||||
return normalizeMetrics(source.cpuUsage).data.result[0].values
|
||||
return normalizeMetrics(source.cpuUsage).data.result[0].values;
|
||||
case MetricType.MEMORY:
|
||||
return normalizeMetrics(source.memoryUsage).data.result[0].values
|
||||
return normalizeMetrics(source.memoryUsage).data.result[0].values;
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./cluster.scss"
|
||||
import "./cluster.scss";
|
||||
|
||||
import React from "react";
|
||||
import { computed, reaction } from "mobx";
|
||||
@@ -21,19 +21,19 @@ export class Cluster extends React.Component {
|
||||
private dependentStores = [nodesStore, podsStore];
|
||||
|
||||
private watchers = [
|
||||
interval(60, () => { getHostedCluster().available && clusterStore.getMetrics()}),
|
||||
interval(20, () => { getHostedCluster().available && eventStore.loadAll()})
|
||||
interval(60, () => { getHostedCluster().available && clusterStore.getMetrics();}),
|
||||
interval(20, () => { getHostedCluster().available && eventStore.loadAll();})
|
||||
];
|
||||
|
||||
@computed get isLoaded() {
|
||||
return nodesStore.isLoaded && podsStore.isLoaded
|
||||
return nodesStore.isLoaded && podsStore.isLoaded;
|
||||
}
|
||||
|
||||
// todo: refactor
|
||||
async componentDidMount() {
|
||||
const { dependentStores } = this;
|
||||
if (!isAllowedResource("nodes")) {
|
||||
dependentStores.splice(dependentStores.indexOf(nodesStore), 1)
|
||||
dependentStores.splice(dependentStores.indexOf(nodesStore), 1);
|
||||
}
|
||||
this.watchers.forEach(watcher => watcher.start(true));
|
||||
|
||||
@@ -49,7 +49,7 @@ export class Cluster extends React.Component {
|
||||
() => clusterStore.metricNodeRole,
|
||||
() => this.watchers.forEach(watcher => watcher.restart())
|
||||
)
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -67,6 +67,6 @@ export class Cluster extends React.Component {
|
||||
)}
|
||||
</div>
|
||||
</TabLayout>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "./cluster.route"
|
||||
export * from "./cluster.route";
|
||||
|
||||
@@ -51,7 +51,7 @@ export class HpaDetails extends React.Component<Props> {
|
||||
</Trans>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Table>
|
||||
@@ -68,7 +68,7 @@ export class HpaDetails extends React.Component<Props> {
|
||||
<TableCell className="name">{name}</TableCell>
|
||||
<TableCell className="metrics">{values}</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
);
|
||||
})
|
||||
}
|
||||
</Table>
|
||||
@@ -113,7 +113,7 @@ export class HpaDetails extends React.Component<Props> {
|
||||
tooltip={tooltip}
|
||||
className={cssNames({ [type.toLowerCase()]: isReady })}
|
||||
/>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</DrawerItem>
|
||||
|
||||
@@ -132,7 +132,7 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <HpaDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
kubeObjectDetailRegistry.add({
|
||||
kind: "HorizontalPodAutoscaler",
|
||||
@@ -141,4 +141,4 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <KubeEventDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const hpaRoute: RouteProps = {
|
||||
path: "/hpa"
|
||||
}
|
||||
};
|
||||
|
||||
export interface IHpaRouteParams {
|
||||
}
|
||||
|
||||
export const hpaURL = buildURL<IHpaRouteParams>(hpaRoute.path)
|
||||
export const hpaURL = buildURL<IHpaRouteParams>(hpaRoute.path);
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./hpa.scss"
|
||||
import "./hpa.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
@@ -78,7 +78,7 @@ export class HorizontalPodAutoscalers extends React.Component<Props> {
|
||||
tooltip={tooltip}
|
||||
className={cssNames(type.toLowerCase())}
|
||||
/>
|
||||
)
|
||||
);
|
||||
})
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from "./hpa"
|
||||
export * from "./hpa-details"
|
||||
export * from "./hpa.route"
|
||||
export * from "./hpa";
|
||||
export * from "./hpa-details";
|
||||
export * from "./hpa.route";
|
||||
@@ -31,7 +31,7 @@ export class ConfigMapDetails extends React.Component<Props> {
|
||||
this.data.replace(configMap.data); // refresh
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
save = async () => {
|
||||
@@ -75,7 +75,7 @@ export class ConfigMapDetails extends React.Component<Props> {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
})
|
||||
}
|
||||
<Button
|
||||
@@ -98,7 +98,7 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <ConfigMapDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
kubeObjectDetailRegistry.add({
|
||||
kind: "ConfigMap",
|
||||
@@ -107,6 +107,6 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <KubeEventDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const configMapsRoute: RouteProps = {
|
||||
path: "/configmaps"
|
||||
}
|
||||
};
|
||||
|
||||
export interface IConfigMapsRouteParams {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./config-maps.scss"
|
||||
import "./config-maps.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from "./config-maps.route"
|
||||
export * from "./config-maps"
|
||||
export * from "./config-map-details"
|
||||
export * from "./config-maps.route";
|
||||
export * from "./config-maps";
|
||||
export * from "./config-map-details";
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from "./pod-disruption-budgets.route"
|
||||
export * from "./pod-disruption-budgets"
|
||||
export * from "./pod-disruption-budgets-details"
|
||||
export * from "./pod-disruption-budgets.route";
|
||||
export * from "./pod-disruption-budgets";
|
||||
export * from "./pod-disruption-budgets-details";
|
||||
+4
-4
@@ -18,8 +18,8 @@ export class PodDisruptionBudgetDetails extends React.Component<Props> {
|
||||
|
||||
render() {
|
||||
const { object: pdb } = this.props;
|
||||
if (!pdb) return null
|
||||
const { status, spec } = pdb
|
||||
if (!pdb) return null;
|
||||
const { status, spec } = pdb;
|
||||
const selectors = pdb.getSelectors();
|
||||
return (
|
||||
<div className="PdbDetails">
|
||||
@@ -50,7 +50,7 @@ export class PodDisruptionBudgetDetails extends React.Component<Props> {
|
||||
</DrawerItem>
|
||||
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +60,4 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <PodDisruptionBudgetDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
+2
-2
@@ -3,9 +3,9 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const pdbRoute: RouteProps = {
|
||||
path: "/poddisruptionbudgets"
|
||||
}
|
||||
};
|
||||
|
||||
export interface IPodDisruptionBudgetsRouteParams {
|
||||
}
|
||||
|
||||
export const pdbURL = buildURL<IPodDisruptionBudgetsRouteParams>(pdbRoute.path)
|
||||
export const pdbURL = buildURL<IPodDisruptionBudgetsRouteParams>(pdbRoute.path);
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./pod-disruption-budgets.scss"
|
||||
import "./pod-disruption-budgets.scss";
|
||||
|
||||
import * as React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
@@ -65,7 +65,7 @@ export class PodDisruptionBudgets extends React.Component<Props> {
|
||||
pdb.getCurrentHealthy(),
|
||||
pdb.getDesiredHealthy(),
|
||||
pdb.getAge(),
|
||||
]
|
||||
];
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -193,12 +193,12 @@ export class AddQuotaDialog extends React.Component<Props> {
|
||||
<div className="value">{value}</div>
|
||||
<Icon material="clear" onClick={() => this.quotas[quota] = ""} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
</Dialog>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from "./resource-quotas.route"
|
||||
export * from "./resource-quotas"
|
||||
export * from "./resource-quota-details"
|
||||
export * from "./resource-quotas.route";
|
||||
export * from "./resource-quotas";
|
||||
export * from "./resource-quota-details";
|
||||
@@ -20,24 +20,24 @@ const onlyNumbers = /$[0-9]*^/g;
|
||||
|
||||
function transformUnit(name: string, value: string): number {
|
||||
if (name.includes("memory") || name.includes("storage")) {
|
||||
return unitsToBytes(value)
|
||||
return unitsToBytes(value);
|
||||
}
|
||||
|
||||
if (name.includes("cpu")) {
|
||||
return cpuUnitsToNumber(value)
|
||||
return cpuUnitsToNumber(value);
|
||||
}
|
||||
|
||||
return metricUnitsToNumber(value);
|
||||
}
|
||||
|
||||
function renderQuotas(quota: ResourceQuota): JSX.Element[] {
|
||||
const { hard = {}, used = {} } = quota.status
|
||||
const { hard = {}, used = {} } = quota.status;
|
||||
|
||||
return Object.entries(hard)
|
||||
.filter(([name]) => used[name])
|
||||
.map(([name, value]) => {
|
||||
const current = transformUnit(name, used[name])
|
||||
const max = transformUnit(name, value)
|
||||
const current = transformUnit(name, used[name]);
|
||||
const max = transformUnit(name, value);
|
||||
const usage = max === 0 ? 100 : Math.ceil(current / max * 100); // special case 0 max as always 100% usage
|
||||
|
||||
return (
|
||||
@@ -52,8 +52,8 @@ function renderQuotas(quota: ResourceQuota): JSX.Element[] {
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -104,4 +104,4 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <ReplicaSetDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const resourceQuotaRoute: RouteProps = {
|
||||
path: "/resourcequotas"
|
||||
}
|
||||
};
|
||||
|
||||
export interface IResourceQuotaRouteParams {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./add-secret-dialog.scss"
|
||||
import "./add-secret-dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observable } from "mobx";
|
||||
@@ -85,7 +85,7 @@ export class AddSecretDialog extends React.Component<Props> {
|
||||
data[key] = processValue ? processValue(value) : value;
|
||||
}
|
||||
return data;
|
||||
}, {})
|
||||
}, {});
|
||||
}
|
||||
|
||||
createSecret = async () => {
|
||||
@@ -100,7 +100,7 @@ export class AddSecretDialog extends React.Component<Props> {
|
||||
annotations: this.getDataFromFields(annotations),
|
||||
labels: this.getDataFromFields(labels),
|
||||
} as IKubeObjectMetadata
|
||||
}
|
||||
};
|
||||
try {
|
||||
const newSecret = await secretsApi.create({ namespace, name }, secret);
|
||||
showDetails(newSecret.selfLink);
|
||||
@@ -163,11 +163,11 @@ export class AddSecretDialog extends React.Component<Props> {
|
||||
onClick={() => this.removeField(field, index)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -216,6 +216,6 @@ export class AddSecretDialog extends React.Component<Props> {
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
</Dialog>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from "./secrets.route"
|
||||
export * from "./secrets"
|
||||
export * from "./secret-details"
|
||||
export * from "./secrets.route";
|
||||
export * from "./secrets";
|
||||
export * from "./secret-details";
|
||||
|
||||
@@ -36,7 +36,7 @@ export class SecretDetails extends React.Component<Props> {
|
||||
this.revealSecret = {};
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
saveSecret = async () => {
|
||||
@@ -97,7 +97,7 @@ export class SecretDetails extends React.Component<Props> {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
})
|
||||
}
|
||||
<Button
|
||||
@@ -119,4 +119,4 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <SecretDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const secretsRoute: RouteProps = {
|
||||
path: "/secrets"
|
||||
}
|
||||
};
|
||||
|
||||
export interface ISecretsRouteParams {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./secrets.scss"
|
||||
import "./secrets.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
@@ -5,8 +5,8 @@ import { configMapsURL } from "../+config-maps/config-maps.route";
|
||||
|
||||
export const configRoute: RouteProps = {
|
||||
get path() {
|
||||
return Config.tabRoutes.map(({ routePath }) => routePath).flat()
|
||||
return Config.tabRoutes.map(({ routePath }) => routePath).flat();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const configURL = (params?: IURLParams) => configMapsURL(params);
|
||||
@@ -8,20 +8,20 @@ import { namespaceStore } 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";
|
||||
import { isAllowedResource } from "../../../common/rbac"
|
||||
import { isAllowedResource } from "../../../common/rbac";
|
||||
|
||||
@observer
|
||||
export class Config extends React.Component {
|
||||
static get tabRoutes(): TabLayoutRoute[] {
|
||||
const query = namespaceStore.getContextParams()
|
||||
const routes: TabLayoutRoute[] = []
|
||||
const query = namespaceStore.getContextParams();
|
||||
const routes: TabLayoutRoute[] = [];
|
||||
if (isAllowedResource("configmaps")) {
|
||||
routes.push({
|
||||
title: <Trans>ConfigMaps</Trans>,
|
||||
component: ConfigMaps,
|
||||
url: configMapsURL({ query }),
|
||||
routePath: configMapsRoute.path.toString(),
|
||||
})
|
||||
});
|
||||
}
|
||||
if (isAllowedResource("secrets")) {
|
||||
routes.push({
|
||||
@@ -29,7 +29,7 @@ export class Config extends React.Component {
|
||||
component: Secrets,
|
||||
url: secretsURL({ query }),
|
||||
routePath: secretsRoute.path.toString(),
|
||||
})
|
||||
});
|
||||
}
|
||||
if (isAllowedResource("resourcequotas")) {
|
||||
routes.push({
|
||||
@@ -37,7 +37,7 @@ export class Config extends React.Component {
|
||||
component: ResourceQuotas,
|
||||
url: resourceQuotaURL({ query }),
|
||||
routePath: resourceQuotaRoute.path.toString(),
|
||||
})
|
||||
});
|
||||
}
|
||||
if (isAllowedResource("horizontalpodautoscalers")) {
|
||||
routes.push({
|
||||
@@ -45,7 +45,7 @@ export class Config extends React.Component {
|
||||
component: HorizontalPodAutoscalers,
|
||||
url: hpaURL({ query }),
|
||||
routePath: hpaRoute.path.toString(),
|
||||
})
|
||||
});
|
||||
}
|
||||
if (isAllowedResource("poddisruptionbudgets")) {
|
||||
routes.push({
|
||||
@@ -53,7 +53,7 @@ export class Config extends React.Component {
|
||||
component: PodDisruptionBudgets,
|
||||
url: pdbURL({ query }),
|
||||
routePath: pdbRoute.path.toString(),
|
||||
})
|
||||
});
|
||||
}
|
||||
return routes;
|
||||
}
|
||||
@@ -61,6 +61,6 @@ export class Config extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<TabLayout className="Config" tabs={Config.tabRoutes}/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from "./config.route"
|
||||
export * from "./config"
|
||||
export * from "./config.route";
|
||||
export * from "./config";
|
||||
@@ -60,7 +60,7 @@ export class CRDDetails extends React.Component<Props> {
|
||||
<DrawerItem name={<Trans>Conditions</Trans>} className="conditions" labelsOnly>
|
||||
{
|
||||
crd.getConditions().map(condition => {
|
||||
const { type, message, lastTransitionTime, status } = condition
|
||||
const { type, message, lastTransitionTime, status } = condition;
|
||||
return (
|
||||
<Badge
|
||||
key={type}
|
||||
@@ -112,7 +112,7 @@ export class CRDDetails extends React.Component<Props> {
|
||||
<Badge label={jsonPath}/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
);
|
||||
})
|
||||
}
|
||||
</Table>
|
||||
@@ -130,7 +130,7 @@ export class CRDDetails extends React.Component<Props> {
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,4 +140,4 @@ kubeObjectDetailRegistry.add({
|
||||
components: {
|
||||
Details: (props) => <CRDDetails {...props} />
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import "./crd-list.scss"
|
||||
import "./crd-list.scss";
|
||||
|
||||
import React from "react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
@@ -24,7 +24,7 @@ enum sortBy {
|
||||
@observer
|
||||
export class CrdList extends React.Component {
|
||||
@computed get groups() {
|
||||
return navigation.searchParams.getAsArray("groups")
|
||||
return navigation.searchParams.getAsArray("groups");
|
||||
}
|
||||
|
||||
onGroupChange(group: string) {
|
||||
@@ -32,7 +32,7 @@ export class CrdList extends React.Component {
|
||||
const index = groups.findIndex(item => item == group);
|
||||
if (index !== -1) groups.splice(index, 1);
|
||||
else groups.push(group);
|
||||
setQueryParams({ groups })
|
||||
setQueryParams({ groups });
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -52,14 +52,14 @@ export class CrdList extends React.Component {
|
||||
searchFilters={Object.values(sortingCallbacks)}
|
||||
filterItems={[
|
||||
(items: CustomResourceDefinition[]) => {
|
||||
return selectedGroups.length ? items.filter(item => selectedGroups.includes(item.getGroup())) : items
|
||||
return selectedGroups.length ? items.filter(item => selectedGroups.includes(item.getGroup())) : items;
|
||||
}
|
||||
]}
|
||||
renderHeaderTitle={<Trans>Custom Resources</Trans>}
|
||||
customizeHeader={() => {
|
||||
let placeholder = <Trans>All groups</Trans>;
|
||||
if (selectedGroups.length == 1) placeholder = <><Trans>Group</Trans>: {selectedGroups[0]}</>
|
||||
if (selectedGroups.length >= 2) placeholder = <><Trans>Groups</Trans>: {selectedGroups.join(", ")}</>
|
||||
if (selectedGroups.length == 1) placeholder = <><Trans>Group</Trans>: {selectedGroups[0]}</>;
|
||||
if (selectedGroups.length >= 2) placeholder = <><Trans>Groups</Trans>: {selectedGroups.join(", ")}</>;
|
||||
return {
|
||||
// todo: move to global filters
|
||||
filters: (
|
||||
@@ -77,11 +77,11 @@ export class CrdList extends React.Component {
|
||||
<span>{group}</span>
|
||||
{isSelected && <Icon small material="check" className="box right"/>}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
};
|
||||
}}
|
||||
renderTableHeader={[
|
||||
{ title: <Trans>Resource</Trans>, className: "kind", sortBy: sortBy.kind },
|
||||
@@ -99,10 +99,10 @@ export class CrdList extends React.Component {
|
||||
crd.getVersion(),
|
||||
crd.getScope(),
|
||||
crd.getAge(),
|
||||
]
|
||||
];
|
||||
}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ interface Props extends KubeObjectDetailsProps<CustomResourceDefinition> {
|
||||
|
||||
function convertSpecValue(value: any): any {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(convertSpecValue)
|
||||
return value.map(convertSpecValue);
|
||||
}
|
||||
|
||||
if (typeof value === "object") {
|
||||
@@ -31,10 +31,10 @@ function convertSpecValue(value: any): any {
|
||||
className="box grow"
|
||||
value={JSON.stringify(value, null, 2)}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return value
|
||||
return value;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -48,13 +48,13 @@ export class CrdResourceDetails extends React.Component<Props> {
|
||||
<DrawerItem key={name} name={name} renderBoolean>
|
||||
{convertSpecValue(jsonPath.value(crd, jp.slice(1)))}
|
||||
</DrawerItem>
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
renderStatus(crd: CustomResourceDefinition, columns: AdditionalPrinterColumnsV1[]) {
|
||||
const showStatus = !columns.find(column => column.name == "Status") && crd.status?.conditions;
|
||||
if (!showStatus) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
const conditions = crd.status.conditions
|
||||
@@ -66,13 +66,13 @@ export class CrdResourceDetails extends React.Component<Props> {
|
||||
className={cssNames({ disabled: status === "False" }, kind.toLowerCase())}
|
||||
tooltip={message}
|
||||
/>
|
||||
))
|
||||
));
|
||||
|
||||
return (
|
||||
<DrawerItem name={<Trans>Status</Trans>} className="status" labelsOnly>
|
||||
{conditions}
|
||||
</DrawerItem>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -90,6 +90,6 @@ export class CrdResourceDetails extends React.Component<Props> {
|
||||
{this.renderAdditionalColumns(object, extraColumns)}
|
||||
{this.renderStatus(object, extraColumns)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export class CrdResources extends React.Component<Props> {
|
||||
store.loadAll();
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
@computed get crd() {
|
||||
@@ -41,7 +41,7 @@ export class CrdResources extends React.Component<Props> {
|
||||
}
|
||||
|
||||
@computed get store() {
|
||||
if (!this.crd) return null
|
||||
if (!this.crd) return null;
|
||||
return apiManager.getStore(this.crd.getResourceApiBase());
|
||||
}
|
||||
|
||||
@@ -54,10 +54,10 @@ export class CrdResources extends React.Component<Props> {
|
||||
[sortBy.name]: (item: KubeObject) => item.getName(),
|
||||
[sortBy.namespace]: (item: KubeObject) => item.getNs(),
|
||||
[sortBy.age]: (item: KubeObject) => item.metadata.creationTimestamp,
|
||||
}
|
||||
};
|
||||
extraColumns.forEach(column => {
|
||||
sortingCallbacks[column.name] = (item: KubeObject) => jsonPath.value(item, column.jsonPath.slice(1))
|
||||
})
|
||||
sortingCallbacks[column.name] = (item: KubeObject) => jsonPath.value(item, column.jsonPath.slice(1));
|
||||
});
|
||||
|
||||
return (
|
||||
<KubeObjectListLayout
|
||||
@@ -78,7 +78,7 @@ export class CrdResources extends React.Component<Props> {
|
||||
title: name,
|
||||
className: name.toLowerCase(),
|
||||
sortBy: name
|
||||
}
|
||||
};
|
||||
}),
|
||||
{ title: <Trans>Age</Trans>, className: "age", sortBy: sortBy.age },
|
||||
]}
|
||||
@@ -92,6 +92,6 @@ export class CrdResources extends React.Component<Props> {
|
||||
crdInstance.getAge(),
|
||||
]}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,15 @@ import { buildURL } from "../../../common/utils/buildUrl";
|
||||
|
||||
export const crdRoute: RouteProps = {
|
||||
path: "/crd"
|
||||
}
|
||||
};
|
||||
|
||||
export const crdDefinitionsRoute: RouteProps = {
|
||||
path: crdRoute.path + "/definitions"
|
||||
}
|
||||
};
|
||||
|
||||
export const crdResourcesRoute: RouteProps = {
|
||||
path: crdRoute.path + "/:group/:name"
|
||||
}
|
||||
};
|
||||
|
||||
export interface ICRDListQuery {
|
||||
groups?: string;
|
||||
|
||||
@@ -26,14 +26,14 @@ export class CRDStore extends KubeObjectStore<CustomResourceDefinition> {
|
||||
super();
|
||||
|
||||
// auto-init stores for crd-s
|
||||
reaction(() => this.items.toJS(), items => items.forEach(initStore))
|
||||
reaction(() => this.items.toJS(), items => items.forEach(initStore));
|
||||
}
|
||||
|
||||
protected sortItems(items: CustomResourceDefinition[]) {
|
||||
return super.sortItems(items, [
|
||||
crd => crd.getGroup(),
|
||||
crd => crd.getName(),
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
@computed get groups() {
|
||||
@@ -43,7 +43,7 @@ export class CRDStore extends KubeObjectStore<CustomResourceDefinition> {
|
||||
if (!groups[group]) groups[group] = [];
|
||||
groups[group].push(crd);
|
||||
return groups;
|
||||
}, groups)
|
||||
}, groups);
|
||||
}
|
||||
|
||||
getByGroup(group: string, pluralName: string) {
|
||||
@@ -53,12 +53,12 @@ export class CRDStore extends KubeObjectStore<CustomResourceDefinition> {
|
||||
}
|
||||
|
||||
getByObject(obj: KubeObject) {
|
||||
if (!obj) return null
|
||||
if (!obj) return null;
|
||||
const { kind, apiVersion } = obj;
|
||||
|
||||
return this.items.find(crd => (
|
||||
kind === crd.getResourceKind() && apiVersion === `${crd.getGroup()}/${crd.getVersion()}`
|
||||
))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export class CustomResources extends React.Component {
|
||||
url: crdURL(),
|
||||
routePath: crdRoute.path.toString(),
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
Loaded 100 of 531 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user