-
Clusters
+
+
{{v.title}}
-
-
-
+
{{view.title}}
+
+
+
-
-
Hosts
-
-
-
-
+
+
-
Admin actions
-
+
Config
-
+
diff --git a/html/ui/js/Cluster.js b/html/ui/js/Cluster.js
index ca8329e..3289cee 100644
--- a/html/ui/js/Cluster.js
+++ b/html/ui/js/Cluster.js
@@ -5,22 +5,43 @@ import GetCopy from './GetCopy.js';
export default {
components: { Downloads, GetCopy },
props: [ 'cluster', 'token', 'state' ],
+ data() {
+ return {
+ sshSignReq: {
+ PubKey: "",
+ Principal: "root",
+ Validity: "+1d",
+ },
+ sshUserCert: null,
+ };
+ },
+ methods: {
+ sshCASign() {
+ event.preventDefault();
+ fetch(`/clusters/${this.cluster.Name}/ssh/user-ca/sign`, {
+ method: 'POST',
+ body: JSON.stringify(this.sshSignReq),
+ headers: { 'Authorization': 'Bearer ' + this.token, 'Content-Type': 'application/json' },
+ }).then((resp) => resp.blob())
+ .then((cert) => { this.sshUserCert = URL.createObjectURL(cert) })
+ .catch((e) => { alert('failed to sign: '+e); })
+ },
+ },
template: `
-
-
Cluster {{ cluster.Name }}
-
Tokens
+
Tokens
-
Passwords
+
+
Passwords
-
Downloads
-
-
CAs
+
+
Downloads
+
+
+
CAs
Name | Certificate | Signed certificates |
{{ ca.Name }} |
@@ -30,6 +51,18 @@ export default {
-
+
+
SSH
+
+
+ Get user SSH certificate
+
`
}
diff --git a/html/ui/js/Downloads.js b/html/ui/js/Downloads.js
index 2e02c44..0fe4993 100644
--- a/html/ui/js/Downloads.js
+++ b/html/ui/js/Downloads.js
@@ -13,15 +13,15 @@ export default {
"initrd",
"bootstrap.tar",
"boot.img.lz4",
- "boot.iso",
- "config",
- "bootstrap-config",
- "boot.tar",
- "boot-efi.tar",
"boot.img.gz",
- "boot.img",
"boot.qcow2",
"boot.vmdk",
+ "boot.img",
+ "boot.iso",
+ "boot.tar",
+ "boot-efi.tar",
+ "config",
+ "bootstrap-config",
"ipxe",
],
}[this.kind]
@@ -56,11 +56,18 @@ export default {
.catch((e) => { alert('failed to create link'); this.createDisabled = false })
},
},
- template: `
-
-
-
-
-
+ template: `
+
Available assets
+
+
+
+ {{" "}}
+
+
+
+
+ Active links
+ {{ d.name }}{{" "}}
+
`
}
diff --git a/html/ui/js/Host.js b/html/ui/js/Host.js
index 22de3ee..2be06e8 100644
--- a/html/ui/js/Host.js
+++ b/html/ui/js/Host.js
@@ -5,18 +5,13 @@ export default {
components: { Downloads },
props: [ 'host', 'token', 'state' ],
template: `
-
-
Host {{ host.Name }}
-
- Cluster: {{ host.Cluster }} ({{ host.Template }})
-
- {{ ip }}
{{" "}}
-
-
-
Downloads
-
-
+
Cluster: {{ host.Cluster }} ({{ host.Template }})
+
IPs:
+
+ {{ ip }}{{" "}}
+
+
+
Downloads
+
`
}
diff --git a/html/ui/js/app.js b/html/ui/js/app.js
index 1994007..cca57ed 100644
--- a/html/ui/js/app.js
+++ b/html/ui/js/app.js
@@ -15,6 +15,8 @@ createApp({
hostFromTemplate: {},
hostFromTemplateDel: "",
},
+ view: "",
+ viewFilter: "",
session: {},
error: null,
publicState: null,
@@ -57,6 +59,27 @@ createApp({
},
computed: {
+ views() {
+ var views = [{type: "actions", name: "admin", title: "Admin actions"}];
+
+ (this.state.Clusters||[]).forEach((c) => views.push({type: "cluster", name: c.Name, title: `Cluster ${c.Name}`}));
+ (this.state.Hosts ||[]).forEach((c) => views.push({type: "host", name: c.Name, title: `Host ${c.Name}`}));
+
+ console.log("views:",views);
+
+ return views.filter((v) => v.name.includes(this.viewFilter));
+ },
+ viewObj() {
+ if (this.view) {
+ if (this.view.type == "cluster") {
+ return this.state.Clusters.find((c) => c.Name == this.view.name);
+ }
+ if (this.view.type == "host") {
+ return this.state.Hosts.find((h) => h.Name == this.view.name);
+ }
+ }
+ return undefined;
+ },
hostsFromTemplate() {
return (this.state.Hosts||[]).filter((h) => h.Template)
},