Migrating Vue components to React and stores refactoring (#585)

Signed-off-by: Roman <ixrock@gmail.com>

Co-authored-by: Sebastian Malton <sebastian@malton.name>
Co-authored-by: Sebastian Malton <smalton@mirantis.com>
Co-authored-by: Lauri Nevala <lauri.nevala@gmail.com>
Co-authored-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
authored and GitHub committed 2020-08-20 08:53:07 +03:00
1 parent 905bbe9d3f
commit 5670312c47
297 files changed
+8186 -9103

No files matched your search

-109
View File
@@ -1,109 +0,0 @@
import { app } from "electron"
import { CoreV1Api } from "@kubernetes/client-node"
import { LensApiRequest } from "../router"
import { LensApi } from "../lens-api"
import { userStore } from "../../common/user-store"
import { Cluster } from "../cluster"
export interface IConfigRoutePayload {
kubeVersion?: string;
clusterName?: string;
lensVersion?: string;
lensTheme?: string;
username?: string;
token?: string;
allowedNamespaces?: string[];
allowedResources?: string[];
isClusterAdmin?: boolean;
chartsEnabled: boolean;
kubectlAccess?: boolean; // User accessed via kubectl-lens plugin
}
// TODO: auto-populate all resources dynamically
const apiResources = [
{ resource: "configmaps" },
{ resource: "cronjobs", group: "batch" },
{ resource: "customresourcedefinitions", group: "apiextensions.k8s.io" },
{ resource: "daemonsets", group: "apps" },
{ resource: "deployments", group: "apps" },
{ resource: "endpoints" },
{ resource: "events" },
{ resource: "horizontalpodautoscalers" },
{ resource: "ingresses", group: "networking.k8s.io" },
{ resource: "jobs", group: "batch" },
{ resource: "namespaces" },
{ resource: "networkpolicies", group: "networking.k8s.io" },
{ resource: "nodes" },
{ resource: "persistentvolumes" },
{ resource: "pods" },
{ resource: "podsecuritypolicies" },
{ resource: "resourcequotas" },
{ resource: "secrets" },
{ resource: "services" },
{ resource: "statefulsets", group: "apps" },
{ resource: "storageclasses", group: "storage.k8s.io" },
]
async function getAllowedNamespaces(cluster: Cluster) {
const api = cluster.proxyKubeconfig().makeApiClient(CoreV1Api)
try {
const namespaceList = await api.listNamespace()
const nsAccessStatuses = await Promise.all(
namespaceList.body.items.map(ns => cluster.canI({
namespace: ns.metadata.name,
resource: "pods",
verb: "list",
}))
)
return namespaceList.body.items
.filter((ns, i) => nsAccessStatuses[i])
.map(ns => ns.metadata.name)
} catch(error) {
const ctx = cluster.proxyKubeconfig().getContextObject(cluster.contextName)
if (ctx.namespace) {
return [ctx.namespace]
}
else {
return []
}
}
}
async function getAllowedResources(cluster: Cluster, namespaces: string[]) {
try {
const resourceAccessStatuses = await Promise.all(
apiResources.map(apiResource => cluster.canI({
resource: apiResource.resource,
group: apiResource.group,
verb: "list",
namespace: namespaces[0]
}))
)
return apiResources
.filter((resource, i) => resourceAccessStatuses[i]).map(apiResource => apiResource.resource)
} catch (error) {
return []
}
}
class ConfigRoute extends LensApi {
public async routeConfig(request: LensApiRequest) {
const { params, response, cluster } = request
const namespaces = await getAllowedNamespaces(cluster)
const data: IConfigRoutePayload = {
clusterName: cluster.contextName,
lensVersion: app.getVersion(),
lensTheme: `kontena-${userStore.getPreferences().colorTheme}`,
kubeVersion: cluster.version,
chartsEnabled: true,
isClusterAdmin: cluster.isAdmin,
allowedResources: await getAllowedResources(cluster, namespaces),
allowedNamespaces: namespaces
};
this.respondJson(response, data)
}
}
export const configRoute = new ConfigRoute()
+114
View File
@@ -0,0 +1,114 @@
import { LensApiRequest } from "../router"
import { helmService } from "../helm/helm-service"
import { LensApi } from "../lens-api"
import logger from "../logger"
class HelmApiRoute extends LensApi {
public async listCharts(request: LensApiRequest) {
const { response } = request
const charts = await helmService.listCharts()
this.respondJson(response, charts)
}
public async getChart(request: LensApiRequest) {
const { params, query, response } = request
const chart = await helmService.getChart(params.repo, params.chart, query.get("version"))
this.respondJson(response, chart)
}
public async getChartValues(request: LensApiRequest) {
const { params, query, response } = request
const values = await helmService.getChartValues(params.repo, params.chart, query.get("version"))
this.respondJson(response, values)
}
public async installChart(request: LensApiRequest) {
const { payload, cluster, response } = request
try {
const result = await helmService.installChart(cluster, payload)
this.respondJson(response, result, 201)
} catch (error) {
logger.debug(error)
this.respondText(response, error, 422)
}
}
public async updateRelease(request: LensApiRequest) {
const { cluster, params, payload, response } = request
try {
const result = await helmService.updateRelease(cluster, params.release, params.namespace, payload )
this.respondJson(response, result)
} catch (error) {
logger.debug(error)
this.respondText(response, error, 422)
}
}
public async rollbackRelease(request: LensApiRequest) {
const { cluster, params, payload, response } = request
try {
const result = await helmService.rollback(cluster, params.release, params.namespace, payload.revision)
this.respondJson(response, result)
} catch (error) {
logger.debug(error)
this.respondText(response, error)
}
}
public async listReleases(request: LensApiRequest) {
const { cluster, params, response } = request
try {
const result = await helmService.listReleases(cluster, params.namespace)
this.respondJson(response, result)
} catch(error) {
logger.debug(error)
this.respondText(response, error)
}
}
public async getRelease(request: LensApiRequest) {
const { cluster, params, response } = request
try {
const result = await helmService.getRelease(cluster, params.release, params.namespace)
this.respondJson(response, result)
} catch (error) {
logger.debug(error)
this.respondText(response, error, 422)
}
}
public async getReleaseValues(request: LensApiRequest) {
const { cluster, params, response } = request
try {
const result = await helmService.getReleaseValues(cluster, params.release, params.namespace)
this.respondText(response, result)
} catch (error) {
logger.debug(error)
this.respondText(response, error, 422)
}
}
public async getReleaseHistory(request: LensApiRequest) {
const { cluster, params, response } = request
try {
const result = await helmService.getReleaseHistory(cluster, params.release, params.namespace)
this.respondJson(response, result)
} catch (error) {
logger.debug(error)
this.respondText(response, error, 422)
}
}
public async deleteRelease(request: LensApiRequest) {
const { cluster, params, response } = request
try {
const result = await helmService.deleteRelease(cluster, params.release, params.namespace)
this.respondJson(response, result)
} catch (error) {
logger.debug(error)
this.respondText(response, error, 422)
}
}
}
export const helmRoute = new HelmApiRoute()
+6
View File
@@ -0,0 +1,6 @@
export * from "./kubeconfig-route"
export * from "./metrics-route"
export * from "./port-forward-route"
export * from "./watch-route"
export * from "./helm-route"
export * from "./resource-applier-route"
@@ -4,7 +4,7 @@ import { Cluster } from "../cluster"
import { CoreV1Api, V1Secret } from "@kubernetes/client-node"
function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster) {
const tokenData = new Buffer(secret.data["token"], "base64")
const tokenData = Buffer.from(secret.data["token"], "base64")
return {
'apiVersion': 'v1',
'kind': 'Config',
@@ -44,7 +44,7 @@ class KubeconfigRoute extends LensApi {
public async routeServiceAccountRoute(request: LensApiRequest) {
const { params, response, cluster} = request
const client = cluster.proxyKubeconfig().makeApiClient(CoreV1Api);
const client = cluster.getProxyKubeconfig().makeApiClient(CoreV1Api);
const secretList = await client.listNamespacedSecret(params.namespace)
const secret = secretList.body.items.find(secret => {
const { annotations } = secret.metadata;
@@ -1,34 +1,25 @@
import { LensApiRequest } from "../router"
import { LensApi } from "../lens-api"
import requestPromise from "request-promise-native"
import { PrometheusProviderRegistry, PrometheusProvider, PrometheusNodeQuery, PrometheusClusterQuery, PrometheusPodQuery, PrometheusPvcQuery, PrometheusIngressQuery, PrometheusQueryOpts} from "../prometheus/provider-registry"
import { apiPrefix } from "../../common/vars";
import { PrometheusClusterQuery, PrometheusIngressQuery, PrometheusNodeQuery, PrometheusPodQuery, PrometheusProvider, PrometheusPvcQuery, PrometheusQueryOpts } from "../prometheus/provider-registry"
export type IMetricsQuery = string | string[] | {
[metricName: string]: string;
}
class MetricsRoute extends LensApi {
public async routeMetrics(request: LensApiRequest) {
const { response, cluster} = request
const query: IMetricsQuery = request.payload;
const serverUrl = `http://127.0.0.1:${cluster.port}${apiPrefix.KUBE_BASE}`
const headers = {
"Host": `${cluster.id}.localhost:${cluster.port}`,
"Content-type": "application/json",
}
async routeMetrics(request: LensApiRequest) {
const { response, cluster, payload } = request
const queryParams: IMetricsQuery = {}
request.query.forEach((value: string, key: string) => {
queryParams[key] = value
})
let metricsUrl: string
let prometheusPath: string
let prometheusProvider: PrometheusProvider
try {
const prometheusPath = await cluster.contextHandler.getPrometheusPath()
metricsUrl = `${serverUrl}/api/v1/namespaces/${prometheusPath}/proxy${cluster.getPrometheusApiPrefix()}/api/v1/query_range`
prometheusProvider = await cluster.contextHandler.getPrometheusProvider()
[prometheusPath, prometheusProvider] = await Promise.all([
cluster.contextHandler.getPrometheusPath(),
cluster.contextHandler.getPrometheusProvider()
])
} catch {
this.respondJson(response, {})
return
@@ -36,18 +27,10 @@ class MetricsRoute extends LensApi {
// prometheus metrics loader
const attempts: { [query: string]: number } = {};
const maxAttempts = 5;
const loadMetrics = (orgQuery: string): Promise<any> => {
const query = orgQuery.trim()
const loadMetrics = (promQuery: string): Promise<any> => {
const query = promQuery.trim()
const attempt = attempts[query] = (attempts[query] || 0) + 1;
return requestPromise(metricsUrl, {
resolveWithFullResponse: false,
headers: headers,
json: true,
qs: {
query: query,
...queryParams
}
}).catch(async (error) => {
return cluster.getMetrics(prometheusPath, { query, ...queryParams }).catch(async error => {
if (attempt < maxAttempts && (error.statusCode && error.statusCode != 404)) {
await new Promise(resolve => setTimeout(resolve, attempt * 1000)); // add delay before repeating request
return loadMetrics(query);
@@ -63,16 +46,14 @@ class MetricsRoute extends LensApi {
// return data in same structure as query
let data: any;
if (typeof query === "string") {
data = await loadMetrics(query)
}
else if (Array.isArray(query)) {
data = await Promise.all(query.map(loadMetrics));
}
else {
if (typeof payload === "string") {
data = await loadMetrics(payload)
} else if (Array.isArray(payload)) {
data = await Promise.all(payload.map(loadMetrics));
} else {
data = {};
const result = await Promise.all(
Object.entries(query).map((queryEntry: any) => {
Object.entries(payload).map((queryEntry: any) => {
const queryName: string = queryEntry[0]
const queryOpts: PrometheusQueryOpts = queryEntry[1]
const queries = prometheusProvider.getQueries(queryOpts)
@@ -80,7 +61,7 @@ class MetricsRoute extends LensApi {
return loadMetrics(q)
})
);
Object.keys(query).forEach((metricName, index) => {
Object.keys(payload).forEach((metricName, index) => {
data[metricName] = result[index];
});
}
@@ -37,7 +37,7 @@ class PortForward {
public async start() {
this.localPort = await getFreePort()
const kubectlBin = await bundledKubectl.kubectlPath()
const kubectlBin = await bundledKubectl.getPath()
const args = [
"--kubeconfig", this.kubeConfig,
"port-forward",
@@ -88,7 +88,7 @@ class PortForwardRoute extends LensApi {
namespace: namespace,
name: resourceName,
port: port,
kubeConfig: cluster.proxyKubeconfigPath()
kubeConfig: cluster.getProxyKubeconfigPath()
})
const started = await portForward.start()
if (!started) {
+17
View File
@@ -0,0 +1,17 @@
import { LensApiRequest } from "../router"
import { LensApi } from "../lens-api"
import { ResourceApplier } from "../resource-applier"
class ResourceApplierApiRoute extends LensApi {
public async applyResource(request: LensApiRequest) {
const { response, cluster, payload } = request
try {
const resource = await new ResourceApplier(cluster).apply(payload);
this.respondJson(response, [resource], 200)
} catch (error) {
this.respondText(response, error, 422)
}
}
}
export const resourceApplierRoute = new ResourceApplierApiRoute()
@@ -87,10 +87,10 @@ class WatchRoute extends LensApi {
response.setHeader("Content-Type", "text/event-stream")
response.setHeader("Cache-Control", "no-cache")
response.setHeader("Connection", "keep-alive")
logger.debug("watch using kubeconfig:" + JSON.stringify(cluster.proxyKubeconfig(), null, 2))
logger.debug("watch using kubeconfig:" + JSON.stringify(cluster.getProxyKubeconfig(), null, 2))
apis.forEach(apiUrl => {
const watcher = new ApiWatcher(apiUrl, cluster.proxyKubeconfig(), response)
const watcher = new ApiWatcher(apiUrl, cluster.getProxyKubeconfig(), response)
watcher.start()
watchers.push(watcher)
})