From 7c9334233d0a7788c9ccf3df4719d77fe7738f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Cluseau?= Date: Mon, 15 Apr 2024 16:35:53 +0200 Subject: [PATCH] host from template ui --- .../ws-hosts-from-templates.go | 9 ++++ cmd/dkl-local-server/ws.go | 2 + html/ui/index.html | 23 ++++++++++ html/ui/js/Host.js | 2 +- html/ui/js/app.js | 43 ++++++++++++++++++- 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/cmd/dkl-local-server/ws-hosts-from-templates.go b/cmd/dkl-local-server/ws-hosts-from-templates.go index 04ad5a6..e808e0a 100644 --- a/cmd/dkl-local-server/ws-hosts-from-templates.go +++ b/cmd/dkl-local-server/ws-hosts-from-templates.go @@ -2,6 +2,7 @@ package main import ( "log" + "net/netip" "github.com/emicklei/go-restful" @@ -55,6 +56,10 @@ func hostOrTemplate(cfg *localconfig.Config, name string) (host *localconfig.Hos return } +func wsHostsFromTemplateList(req *restful.Request, resp *restful.Response) { + hostsFromTemplate.WsList(resp, "") +} + func wsHostsFromTemplateSet(req *restful.Request, resp *restful.Response) { name := req.PathParameter("name") @@ -78,6 +83,10 @@ func wsHostsFromTemplateSet(req *restful.Request, resp *restful.Response) { wsBadRequest(resp, "ip is required") return } + if _, err := netip.ParseAddr(v.IP); err != nil { + wsBadRequest(resp, "bad IP: "+err.Error()) + return + } found := false for _, ht := range cfg.HostTemplates { diff --git a/cmd/dkl-local-server/ws.go b/cmd/dkl-local-server/ws.go index 81c2d4c..aed5f4e 100644 --- a/cmd/dkl-local-server/ws.go +++ b/cmd/dkl-local-server/ws.go @@ -76,6 +76,8 @@ func registerWS(rest *restful.Container) { ws.Route(ws.GET("/clusters").To(wsListClusters). Doc("List clusters")) + ws.Route(ws.GET("/hosts-from-template").To(wsHostsFromTemplateList). + Doc("List host template instances")) ws.Route(ws.POST("/hosts-from-template/{name}").To(wsHostsFromTemplateSet). Reads(HostFromTemplate{}). Doc("Create or update a host template instance")) diff --git a/html/ui/index.html b/html/ui/index.html index e4ae229..97e3c86 100644 --- a/html/ui/index.html +++ b/html/ui/index.html @@ -87,11 +87,13 @@

Admin actions

+

Config

+

Store

Download

@@ -109,6 +111,27 @@

Available names: .

+ + + diff --git a/html/ui/js/Host.js b/html/ui/js/Host.js index 9f606ab..f811dad 100644 --- a/html/ui/js/Host.js +++ b/html/ui/js/Host.js @@ -10,7 +10,7 @@ export default {
Cluster: {{ host.Cluster }}
Downloads
diff --git a/html/ui/js/app.js b/html/ui/js/app.js index 8f78bdc..1994007 100644 --- a/html/ui/js/app.js +++ b/html/ui/js/app.js @@ -12,6 +12,8 @@ createApp({ store: {}, storeUpload: {}, delKey: {}, + hostFromTemplate: {}, + hostFromTemplateDel: "", }, session: {}, error: null, @@ -54,6 +56,12 @@ createApp({ } }, + computed: { + hostsFromTemplate() { + return (this.state.Hosts||[]).filter((h) => h.Template) + }, + }, + methods: { copyText(text) { event.preventDefault() @@ -104,9 +112,21 @@ createApp({ }) }, uploadConfig() { - event.preventDefault() this.apiPost('/configs', this.$refs.configUpload.files[0], (v) => {}, "text/vnd.yaml") }, + hostFromTemplateAdd() { + let v = this.forms.hostFromTemplate; + this.apiPost('/hosts-from-template/'+v.name, v, (v) => { this.forms.hostFromTemplate = {} }); + }, + hostFromTemplateDel() { + event.preventDefault() + + let v = this.forms.hostFromTemplateDel; + if (!confirm("delete host template instance "+v+"?")) { + return + } + this.apiDelete('/hosts-from-template/'+v, (v) => { this.forms.hostFromTemplateDel = "" }); + }, apiPost(action, data, onload, contentType = 'application/json') { event.preventDefault() @@ -155,6 +175,27 @@ createApp({ xhr.send(data) } }, + apiDelete(action, data, onload) { + event.preventDefault() + + var xhr = new XMLHttpRequest() + xhr.onload = (r) => { + if (xhr.status != 200) { + this.error = xhr.response + return + } + this.error = null + if (onload) { + onload(xhr.response) + } + } + xhr.open("DELETE", action) + xhr.setRequestHeader('Accept', 'application/json') + if (this.session.token) { + xhr.setRequestHeader('Authorization', 'Bearer '+this.session.token) + } + xhr.send() + }, download(url) { event.target.target = '_blank' event.target.href = this.downloadLink(url)