From ec9c47752f652aeca89e77ffe5836e3e4513f780 Mon Sep 17 00:00:00 2001 From: pashevskii <53330707+pashevskii@users.noreply.github.com> Date: Thu, 15 Apr 2021 16:19:54 +0400 Subject: [PATCH] YAML Templates in Create Resource dock tab (#2327) Co-authored-by: Pavel Ashevskiy --- package.json | 1 + .../components/dock/create-resource.scss | 2 +- .../components/dock/create-resource.store.ts | 48 +++++ .../components/dock/create-resource.tsx | 49 +++++ templates/create-resource/ClusterRole.yaml | 198 ++++++++++++++++++ .../create-resource/ClusterRoleBinding.yaml | 12 ++ templates/create-resource/ConfigMap.yaml | 17 ++ templates/create-resource/CronJob.yaml | 19 ++ templates/create-resource/DeamonSet.yaml | 44 ++++ templates/create-resource/Deployment.yaml | 21 ++ templates/create-resource/Ingress.yaml | 17 ++ templates/create-resource/Job.yaml | 13 ++ templates/create-resource/NetworkPolicy.yaml | 34 +++ .../create-resource/PersistentVolume.yaml | 18 ++ .../PersistentVolumeClaim.yaml | 17 ++ templates/create-resource/ReplicaSet.yaml | 21 ++ .../ReplicationController.yaml | 19 ++ templates/create-resource/Role.yaml | 9 + templates/create-resource/RoleBinding.yaml | 17 ++ templates/create-resource/Secret.yaml | 8 + templates/create-resource/Service.yaml | 11 + templates/create-resource/StatefulSet.yaml | 34 +++ yarn.lock | 47 ++++- 23 files changed, 673 insertions(+), 3 deletions(-) create mode 100644 templates/create-resource/ClusterRole.yaml create mode 100644 templates/create-resource/ClusterRoleBinding.yaml create mode 100644 templates/create-resource/ConfigMap.yaml create mode 100644 templates/create-resource/CronJob.yaml create mode 100644 templates/create-resource/DeamonSet.yaml create mode 100644 templates/create-resource/Deployment.yaml create mode 100644 templates/create-resource/Ingress.yaml create mode 100644 templates/create-resource/Job.yaml create mode 100644 templates/create-resource/NetworkPolicy.yaml create mode 100644 templates/create-resource/PersistentVolume.yaml create mode 100644 templates/create-resource/PersistentVolumeClaim.yaml create mode 100644 templates/create-resource/ReplicaSet.yaml create mode 100644 templates/create-resource/ReplicationController.yaml create mode 100644 templates/create-resource/Role.yaml create mode 100644 templates/create-resource/RoleBinding.yaml create mode 100644 templates/create-resource/Secret.yaml create mode 100644 templates/create-resource/Service.yaml create mode 100644 templates/create-resource/StatefulSet.yaml diff --git a/package.json b/package.json index bb82612ea2..e80f47352d 100644 --- a/package.json +++ b/package.json @@ -206,6 +206,7 @@ "electron-devtools-installer": "^3.1.1", "electron-updater": "^4.3.1", "electron-window-state": "^5.0.3", + "filehound": "^1.17.4", "filenamify": "^4.1.0", "fs-extra": "^9.0.1", "handlebars": "^4.7.6", diff --git a/src/renderer/components/dock/create-resource.scss b/src/renderer/components/dock/create-resource.scss index 027b37763d..48231378c9 100644 --- a/src/renderer/components/dock/create-resource.scss +++ b/src/renderer/components/dock/create-resource.scss @@ -1,2 +1,2 @@ .CreateResource { -} \ No newline at end of file +} diff --git a/src/renderer/components/dock/create-resource.store.ts b/src/renderer/components/dock/create-resource.store.ts index 8933ddf4d0..bdc1f4c139 100644 --- a/src/renderer/components/dock/create-resource.store.ts +++ b/src/renderer/components/dock/create-resource.store.ts @@ -1,13 +1,61 @@ +import fs from "fs-extra"; +import path from "path"; +import os from "os"; +import groupBy from "lodash/groupBy"; +import filehound from "filehound"; +import { watch } from "chokidar"; import { autobind } from "../../utils"; import { DockTabStore } from "./dock-tab.store"; import { dockStore, IDockTab, TabKind } from "./dock.store"; @autobind() export class CreateResourceStore extends DockTabStore { + constructor() { super({ storageKey: "create_resource" }); + fs.ensureDirSync(this.userTemplatesFolder); + } + + get lensTemplatesFolder():string { + return path.resolve(__static, "../templates/create-resource"); + } + + get userTemplatesFolder():string { + return path.join(os.homedir(), ".k8slens", "templates"); + } + + async getTemplates(templatesPath: string, defaultGroup: string) { + const templates = await filehound.create().path(templatesPath).ext(["yaml", "json"]).depth(1).find(); + + return templates ? this.groupTemplates(templates, templatesPath, defaultGroup) : {}; + } + + groupTemplates(templates: string[], templatesPath: string, defaultGroup: string) { + return groupBy(templates,(v:string) => + path.relative(templatesPath,v).split(path.sep).length>1 + ? path.parse(path.relative(templatesPath,v)).dir + : defaultGroup); + } + + async getMergedTemplates() { + const userTemplates = await this.getTemplates(this.userTemplatesFolder, "ungrouped"); + const lensTemplates = await this.getTemplates(this.lensTemplatesFolder, "lens"); + + return {...userTemplates,...lensTemplates}; + } + + async watchUserTemplates(callback: ()=> void){ + watch(this.userTemplatesFolder, { + depth: 1, + ignoreInitial: true, + awaitWriteFinish: { + stabilityThreshold: 500 + } + }).on("all", () => { + callback(); + }); } } diff --git a/src/renderer/components/dock/create-resource.tsx b/src/renderer/components/dock/create-resource.tsx index 01e6002309..29e2bf60e7 100644 --- a/src/renderer/components/dock/create-resource.tsx +++ b/src/renderer/components/dock/create-resource.tsx @@ -1,6 +1,9 @@ import "./create-resource.scss"; import React from "react"; +import path from "path"; +import fs from "fs-extra"; +import {Select, GroupSelectOption, SelectOption} from "../select"; import jsYaml from "js-yaml"; import { observable } from "mobx"; import { observer } from "mobx-react"; @@ -20,7 +23,25 @@ interface Props { @observer export class CreateResource extends React.Component { + @observable currentTemplates:Map = new Map(); @observable error = ""; + @observable templates:GroupSelectOption[] = []; + + componentDidMount() { + createResourceStore.getMergedTemplates().then(v => this.updateGroupSelectOptions(v)); + createResourceStore.watchUserTemplates(() => createResourceStore.getMergedTemplates().then(v => this.updateGroupSelectOptions(v))); + } + + updateGroupSelectOptions(templates :Record) { + this.templates = Object.entries(templates) + .map(([name, grouping]) => this.convertToGroup(name, grouping)); + } + + convertToGroup(group:string, items:string[]):GroupSelectOption { + const options = items.map(v => ({label: path.parse(v).name, value: v})); + + return {label: group, options}; + } get tabId() { return this.props.tab.id; @@ -30,11 +51,20 @@ export class CreateResource extends React.Component { return createResourceStore.getData(this.tabId); } + get currentTemplate() { + return this.currentTemplates.get(this.tabId) ?? null; + } + onChange = (value: string, error?: string) => { createResourceStore.setData(this.tabId, value); this.error = error; }; + onSelectTemplate = (item: SelectOption) => { + this.currentTemplates.set(this.tabId, item); + fs.readFile(item.value,"utf8").then(v => createResourceStore.setData(this.tabId,v)); + }; + create = async () => { if (this.error) return; if (!this.data.trim()) return; // do not save when field is empty @@ -67,6 +97,24 @@ export class CreateResource extends React.Component { return successMessage; }; + renderControls(){ + return ( +
+