various code cleanup,
add required tag to select template
This commit is contained in:
@@ -29,15 +29,14 @@ func Run() {
|
|||||||
router.GET("/account", routes.HandleGETAccount)
|
router.GET("/account", routes.HandleGETAccount)
|
||||||
router.GET("/", routes.HandleGETIndex)
|
router.GET("/", routes.HandleGETIndex)
|
||||||
router.GET("/index", routes.HandleGETIndex)
|
router.GET("/index", routes.HandleGETIndex)
|
||||||
router.GET("/config", routes.HandleGETConfig)
|
|
||||||
router.GET("/login", routes.HandleGETLogin)
|
|
||||||
router.GET("/settings", routes.HandleGETSettings)
|
|
||||||
|
|
||||||
router.GET("/index/instances", routes.HandleGETInstancesFragment)
|
router.GET("/index/instances", routes.HandleGETInstancesFragment)
|
||||||
|
router.GET("/config", routes.HandleGETConfig)
|
||||||
router.GET("/config/volumes", routes.HandleGETConfigVolumesFragment)
|
router.GET("/config/volumes", routes.HandleGETConfigVolumesFragment)
|
||||||
router.GET("/config/nets", routes.HandleGETConfigNetsFragment)
|
router.GET("/config/nets", routes.HandleGETConfigNetsFragment)
|
||||||
router.GET("/config/devices", routes.HandleGETConfigDevicesFragment)
|
router.GET("/config/devices", routes.HandleGETConfigDevicesFragment)
|
||||||
router.GET("/config/boot", routes.HandleGETConfigBootFragment)
|
router.GET("/config/boot", routes.HandleGETConfigBootFragment)
|
||||||
|
router.GET("/login", routes.HandleGETLogin)
|
||||||
|
router.GET("/settings", routes.HandleGETSettings)
|
||||||
|
|
||||||
log.Fatal(router.Run(fmt.Sprintf("0.0.0.0:%d", common.Global.Port)))
|
log.Fatal(router.Run(fmt.Sprintf("0.0.0.0:%d", common.Global.Port)))
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,9 @@ type StaticFile struct {
|
|||||||
|
|
||||||
// type used for templated <select>
|
// type used for templated <select>
|
||||||
type Select struct {
|
type Select struct {
|
||||||
ID string
|
ID string
|
||||||
Options []Option
|
Required bool
|
||||||
|
Options []Option
|
||||||
}
|
}
|
||||||
|
|
||||||
// type used for templated <option>
|
// type used for templated <option>
|
||||||
|
@@ -10,6 +10,77 @@ import (
|
|||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func HandleGETAccount(c *gin.Context) {
|
||||||
|
auth, err := common.GetAuth(c)
|
||||||
|
if err == nil {
|
||||||
|
account, err := GetUserAccount(auth)
|
||||||
|
if err != nil {
|
||||||
|
common.HandleNonFatalError(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range account.Resources {
|
||||||
|
switch t := v.(type) {
|
||||||
|
case NumericResource:
|
||||||
|
avail, prefix := FormatNumber(t.Total.Avail*t.Multiplier, t.Base)
|
||||||
|
account.Resources[k] = ResourceChart{
|
||||||
|
Type: t.Type,
|
||||||
|
Display: t.Display,
|
||||||
|
Name: t.Name,
|
||||||
|
Used: t.Total.Used,
|
||||||
|
Max: t.Total.Max,
|
||||||
|
Avail: avail,
|
||||||
|
Prefix: prefix,
|
||||||
|
Unit: t.Unit,
|
||||||
|
}
|
||||||
|
case StorageResource:
|
||||||
|
avail, prefix := FormatNumber(t.Total.Avail*t.Multiplier, t.Base)
|
||||||
|
account.Resources[k] = ResourceChart{
|
||||||
|
Type: t.Type,
|
||||||
|
Display: t.Display,
|
||||||
|
Name: t.Name,
|
||||||
|
Used: t.Total.Used,
|
||||||
|
Max: t.Total.Max,
|
||||||
|
Avail: avail,
|
||||||
|
Prefix: prefix,
|
||||||
|
Unit: t.Unit,
|
||||||
|
}
|
||||||
|
case ListResource:
|
||||||
|
l := struct {
|
||||||
|
Type string
|
||||||
|
Display bool
|
||||||
|
Resources []ResourceChart
|
||||||
|
}{
|
||||||
|
Type: t.Type,
|
||||||
|
Display: t.Display,
|
||||||
|
Resources: []ResourceChart{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range t.Total {
|
||||||
|
l.Resources = append(l.Resources, ResourceChart{
|
||||||
|
Type: t.Type,
|
||||||
|
Display: t.Display,
|
||||||
|
Name: r.Name,
|
||||||
|
Used: r.Used,
|
||||||
|
Max: r.Max,
|
||||||
|
Avail: float64(r.Avail), // usually an int
|
||||||
|
Unit: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
account.Resources[k] = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "html/account.html", gin.H{
|
||||||
|
"global": common.Global,
|
||||||
|
"page": "account",
|
||||||
|
"account": account,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Account struct {
|
type Account struct {
|
||||||
Username string
|
Username string
|
||||||
Pools map[string]bool
|
Pools map[string]bool
|
||||||
@@ -82,77 +153,6 @@ type ResourceChart struct {
|
|||||||
Unit string
|
Unit string
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleGETAccount(c *gin.Context) {
|
|
||||||
auth, err := common.GetAuth(c)
|
|
||||||
if err == nil {
|
|
||||||
account, err := GetUserAccount(auth)
|
|
||||||
if err != nil {
|
|
||||||
common.HandleNonFatalError(c, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range account.Resources {
|
|
||||||
switch t := v.(type) {
|
|
||||||
case NumericResource:
|
|
||||||
avail, prefix := FormatNumber(t.Total.Avail*t.Multiplier, t.Base)
|
|
||||||
account.Resources[k] = ResourceChart{
|
|
||||||
Type: t.Type,
|
|
||||||
Display: t.Display,
|
|
||||||
Name: t.Name,
|
|
||||||
Used: t.Total.Used,
|
|
||||||
Max: t.Total.Max,
|
|
||||||
Avail: avail,
|
|
||||||
Prefix: prefix,
|
|
||||||
Unit: t.Unit,
|
|
||||||
}
|
|
||||||
case StorageResource:
|
|
||||||
avail, prefix := FormatNumber(t.Total.Avail*t.Multiplier, t.Base)
|
|
||||||
account.Resources[k] = ResourceChart{
|
|
||||||
Type: t.Type,
|
|
||||||
Display: t.Display,
|
|
||||||
Name: t.Name,
|
|
||||||
Used: t.Total.Used,
|
|
||||||
Max: t.Total.Max,
|
|
||||||
Avail: avail,
|
|
||||||
Prefix: prefix,
|
|
||||||
Unit: t.Unit,
|
|
||||||
}
|
|
||||||
case ListResource:
|
|
||||||
l := struct {
|
|
||||||
Type string
|
|
||||||
Display bool
|
|
||||||
Resources []ResourceChart
|
|
||||||
}{
|
|
||||||
Type: t.Type,
|
|
||||||
Display: t.Display,
|
|
||||||
Resources: []ResourceChart{},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range t.Total {
|
|
||||||
l.Resources = append(l.Resources, ResourceChart{
|
|
||||||
Type: t.Type,
|
|
||||||
Display: t.Display,
|
|
||||||
Name: r.Name,
|
|
||||||
Used: r.Used,
|
|
||||||
Max: r.Max,
|
|
||||||
Avail: float64(r.Avail), // usually an int
|
|
||||||
Unit: "",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
account.Resources[k] = l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "html/account.html", gin.H{
|
|
||||||
"global": common.Global,
|
|
||||||
"page": "account",
|
|
||||||
"account": account,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserAccount(auth common.Auth) (Account, error) {
|
func GetUserAccount(auth common.Auth) (Account, error) {
|
||||||
account := Account{
|
account := Account{
|
||||||
Resources: map[string]any{},
|
Resources: map[string]any{},
|
||||||
|
@@ -13,42 +13,12 @@ import (
|
|||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VMPath struct {
|
|
||||||
Node string
|
|
||||||
Type string
|
|
||||||
VMID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// imported types from fabric
|
|
||||||
|
|
||||||
type InstanceConfig struct {
|
|
||||||
Type fabric.InstanceType `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Proctype string `json:"cpu"`
|
|
||||||
Cores uint64 `json:"cores"`
|
|
||||||
Memory uint64 `json:"memory"`
|
|
||||||
Swap uint64 `json:"swap"`
|
|
||||||
Volumes map[string]*fabric.Volume `json:"volumes"`
|
|
||||||
Nets map[string]*fabric.Net `json:"nets"`
|
|
||||||
Devices map[string]*fabric.Device `json:"devices"`
|
|
||||||
Boot fabric.BootOrder `json:"boot"`
|
|
||||||
// overrides
|
|
||||||
ProctypeSelect common.Select
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleGETConfig(c *gin.Context) {
|
func HandleGETConfig(c *gin.Context) {
|
||||||
auth, err := common.GetAuth(c)
|
auth, err := common.GetAuth(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
req_node := c.Query("node")
|
vm_path, err := ExtractVMPath(c)
|
||||||
req_type := c.Query("type")
|
if err != nil {
|
||||||
req_vmid := c.Query("vmid")
|
common.HandleNonFatalError(c, err)
|
||||||
if req_node == "" || req_type == "" || req_vmid == "" {
|
|
||||||
common.HandleNonFatalError(c, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid))
|
|
||||||
}
|
|
||||||
vm_path := VMPath{
|
|
||||||
Node: req_node,
|
|
||||||
Type: req_type,
|
|
||||||
VMID: req_vmid,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := GetInstanceConfig(vm_path, auth)
|
config, err := GetInstanceConfig(vm_path, auth)
|
||||||
@@ -56,7 +26,6 @@ func HandleGETConfig(c *gin.Context) {
|
|||||||
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
|
common.HandleNonFatalError(c, fmt.Errorf("error encountered getting instance config: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
config.ProctypeSelect = common.Select{}
|
|
||||||
if config.Type == "VM" { // if VM, fetch CPU types from node
|
if config.Type == "VM" { // if VM, fetch CPU types from node
|
||||||
config.ProctypeSelect, err = GetCPUTypes(vm_path, auth)
|
config.ProctypeSelect, err = GetCPUTypes(vm_path, auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -82,16 +51,9 @@ func HandleGETConfig(c *gin.Context) {
|
|||||||
func HandleGETConfigVolumesFragment(c *gin.Context) {
|
func HandleGETConfigVolumesFragment(c *gin.Context) {
|
||||||
auth, err := common.GetAuth(c)
|
auth, err := common.GetAuth(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
req_node := c.Query("node")
|
vm_path, err := ExtractVMPath(c)
|
||||||
req_type := c.Query("type")
|
if err != nil {
|
||||||
req_vmid := c.Query("vmid")
|
common.HandleNonFatalError(c, err)
|
||||||
if req_node == "" || req_type == "" || req_vmid == "" {
|
|
||||||
common.HandleNonFatalError(c, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid))
|
|
||||||
}
|
|
||||||
vm_path := VMPath{
|
|
||||||
Node: req_node,
|
|
||||||
Type: req_type,
|
|
||||||
VMID: req_vmid,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := GetInstanceConfig(vm_path, auth)
|
config, err := GetInstanceConfig(vm_path, auth)
|
||||||
@@ -112,16 +74,9 @@ func HandleGETConfigVolumesFragment(c *gin.Context) {
|
|||||||
func HandleGETConfigNetsFragment(c *gin.Context) {
|
func HandleGETConfigNetsFragment(c *gin.Context) {
|
||||||
auth, err := common.GetAuth(c)
|
auth, err := common.GetAuth(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
req_node := c.Query("node")
|
vm_path, err := ExtractVMPath(c)
|
||||||
req_type := c.Query("type")
|
if err != nil {
|
||||||
req_vmid := c.Query("vmid")
|
common.HandleNonFatalError(c, err)
|
||||||
if req_node == "" || req_type == "" || req_vmid == "" {
|
|
||||||
common.HandleNonFatalError(c, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid))
|
|
||||||
}
|
|
||||||
vm_path := VMPath{
|
|
||||||
Node: req_node,
|
|
||||||
Type: req_type,
|
|
||||||
VMID: req_vmid,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := GetInstanceConfig(vm_path, auth)
|
config, err := GetInstanceConfig(vm_path, auth)
|
||||||
@@ -142,16 +97,9 @@ func HandleGETConfigNetsFragment(c *gin.Context) {
|
|||||||
func HandleGETConfigDevicesFragment(c *gin.Context) {
|
func HandleGETConfigDevicesFragment(c *gin.Context) {
|
||||||
auth, err := common.GetAuth(c)
|
auth, err := common.GetAuth(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
req_node := c.Query("node")
|
vm_path, err := ExtractVMPath(c)
|
||||||
req_type := c.Query("type")
|
if err != nil {
|
||||||
req_vmid := c.Query("vmid")
|
common.HandleNonFatalError(c, err)
|
||||||
if req_node == "" || req_type == "" || req_vmid == "" {
|
|
||||||
common.HandleNonFatalError(c, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid))
|
|
||||||
}
|
|
||||||
vm_path := VMPath{
|
|
||||||
Node: req_node,
|
|
||||||
Type: req_type,
|
|
||||||
VMID: req_vmid,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := GetInstanceConfig(vm_path, auth)
|
config, err := GetInstanceConfig(vm_path, auth)
|
||||||
@@ -172,16 +120,9 @@ func HandleGETConfigDevicesFragment(c *gin.Context) {
|
|||||||
func HandleGETConfigBootFragment(c *gin.Context) {
|
func HandleGETConfigBootFragment(c *gin.Context) {
|
||||||
auth, err := common.GetAuth(c)
|
auth, err := common.GetAuth(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
req_node := c.Query("node")
|
vm_path, err := ExtractVMPath(c)
|
||||||
req_type := c.Query("type")
|
if err != nil {
|
||||||
req_vmid := c.Query("vmid")
|
common.HandleNonFatalError(c, err)
|
||||||
if req_node == "" || req_type == "" || req_vmid == "" {
|
|
||||||
common.HandleNonFatalError(c, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid))
|
|
||||||
}
|
|
||||||
vm_path := VMPath{
|
|
||||||
Node: req_node,
|
|
||||||
Type: req_type,
|
|
||||||
VMID: req_vmid,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := GetInstanceConfig(vm_path, auth)
|
config, err := GetInstanceConfig(vm_path, auth)
|
||||||
@@ -199,6 +140,44 @@ func HandleGETConfigBootFragment(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExtractVMPath(c *gin.Context) (VMPath, error) {
|
||||||
|
req_node := c.Query("node")
|
||||||
|
req_type := c.Query("type")
|
||||||
|
req_vmid := c.Query("vmid")
|
||||||
|
if req_node == "" || req_type == "" || req_vmid == "" {
|
||||||
|
return VMPath{}, fmt.Errorf("request missing required values: (node: %s, type: %s, vmid: %s)", req_node, req_type, req_vmid)
|
||||||
|
}
|
||||||
|
vm_path := VMPath{
|
||||||
|
Node: req_node,
|
||||||
|
Type: req_type,
|
||||||
|
VMID: req_vmid,
|
||||||
|
}
|
||||||
|
return vm_path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type VMPath struct {
|
||||||
|
Node string
|
||||||
|
Type string
|
||||||
|
VMID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// imported types from fabric
|
||||||
|
|
||||||
|
type InstanceConfig struct {
|
||||||
|
Type fabric.InstanceType `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Proctype string `json:"cpu"`
|
||||||
|
Cores uint64 `json:"cores"`
|
||||||
|
Memory uint64 `json:"memory"`
|
||||||
|
Swap uint64 `json:"swap"`
|
||||||
|
Volumes map[string]*fabric.Volume `json:"volumes"`
|
||||||
|
Nets map[string]*fabric.Net `json:"nets"`
|
||||||
|
Devices map[string]*fabric.Device `json:"devices"`
|
||||||
|
Boot fabric.BootOrder `json:"boot"`
|
||||||
|
// overrides
|
||||||
|
ProctypeSelect common.Select
|
||||||
|
}
|
||||||
|
|
||||||
func GetInstanceConfig(vm VMPath, auth common.Auth) (InstanceConfig, error) {
|
func GetInstanceConfig(vm VMPath, auth common.Auth) (InstanceConfig, error) {
|
||||||
config := InstanceConfig{}
|
config := InstanceConfig{}
|
||||||
path := fmt.Sprintf("/cluster/%s/%s/%s", vm.Node, vm.Type, vm.VMID)
|
path := fmt.Sprintf("/cluster/%s/%s/%s", vm.Node, vm.Type, vm.VMID)
|
||||||
@@ -248,7 +227,8 @@ type CPUConfig struct {
|
|||||||
|
|
||||||
func GetCPUTypes(vm VMPath, auth common.Auth) (common.Select, error) {
|
func GetCPUTypes(vm VMPath, auth common.Auth) (common.Select, error) {
|
||||||
cputypes := common.Select{
|
cputypes := common.Select{
|
||||||
ID: "proctype",
|
ID: "proctype",
|
||||||
|
Required: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// get global resource config
|
// get global resource config
|
||||||
|
@@ -9,6 +9,41 @@ import (
|
|||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func HandleGETIndex(c *gin.Context) {
|
||||||
|
auth, err := common.GetAuth(c)
|
||||||
|
if err == nil { // user should be authed, try to return index with population
|
||||||
|
instances, _, err := GetClusterResources(auth)
|
||||||
|
if err != nil {
|
||||||
|
common.HandleNonFatalError(c, err)
|
||||||
|
}
|
||||||
|
c.HTML(http.StatusOK, "html/index.html", gin.H{
|
||||||
|
"global": common.Global,
|
||||||
|
"page": "index",
|
||||||
|
"instances": instances,
|
||||||
|
})
|
||||||
|
} else { // return index without populating
|
||||||
|
c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleGETInstancesFragment(c *gin.Context) {
|
||||||
|
Auth, err := common.GetAuth(c)
|
||||||
|
if err == nil { // user should be authed, try to return index with population
|
||||||
|
instances, _, err := GetClusterResources(Auth)
|
||||||
|
if err != nil {
|
||||||
|
common.HandleNonFatalError(c, err)
|
||||||
|
}
|
||||||
|
c.Header("Content-Type", "text/plain")
|
||||||
|
common.TMPL.ExecuteTemplate(c.Writer, "html/index-instances.frag", gin.H{
|
||||||
|
"instances": instances,
|
||||||
|
})
|
||||||
|
c.Status(http.StatusOK)
|
||||||
|
} else { // return 401
|
||||||
|
c.Status(http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// used in constructing instance cards in index
|
// used in constructing instance cards in index
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Node string `json:"node"`
|
Node string `json:"node"`
|
||||||
@@ -70,38 +105,3 @@ func GetClusterResources(auth common.Auth) (map[uint]InstanceCard, map[string]No
|
|||||||
}
|
}
|
||||||
return instances, nodes, nil
|
return instances, nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleGETIndex(c *gin.Context) {
|
|
||||||
auth, err := common.GetAuth(c)
|
|
||||||
if err == nil { // user should be authed, try to return index with population
|
|
||||||
instances, _, err := GetClusterResources(auth)
|
|
||||||
if err != nil {
|
|
||||||
common.HandleNonFatalError(c, err)
|
|
||||||
}
|
|
||||||
c.HTML(http.StatusOK, "html/index.html", gin.H{
|
|
||||||
"global": common.Global,
|
|
||||||
"page": "index",
|
|
||||||
"instances": instances,
|
|
||||||
})
|
|
||||||
} else { // return index without populating
|
|
||||||
c.Redirect(http.StatusFound, "/login") // if user is not authed, redirect user to login page
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleGETInstancesFragment(c *gin.Context) {
|
|
||||||
Auth, err := common.GetAuth(c)
|
|
||||||
if err == nil { // user should be authed, try to return index with population
|
|
||||||
instances, _, err := GetClusterResources(Auth)
|
|
||||||
if err != nil {
|
|
||||||
common.HandleNonFatalError(c, err)
|
|
||||||
}
|
|
||||||
c.Header("Content-Type", "text/plain")
|
|
||||||
common.TMPL.ExecuteTemplate(c.Writer, "html/index-instances.frag", gin.H{
|
|
||||||
"instances": instances,
|
|
||||||
})
|
|
||||||
c.Status(http.StatusOK)
|
|
||||||
} else { // return 401
|
|
||||||
c.Status(http.StatusUnauthorized)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@@ -9,18 +9,6 @@ import (
|
|||||||
"github.com/go-viper/mapstructure/v2"
|
"github.com/go-viper/mapstructure/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// used when requesting GET /access/domains
|
|
||||||
type GetRealmsBody struct {
|
|
||||||
Data []Realm `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// stores each realm's data
|
|
||||||
type Realm struct {
|
|
||||||
Default int `json:"default"`
|
|
||||||
Realm string `json:"realm"`
|
|
||||||
Comment string `json:"comment"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetLoginRealms() ([]Realm, error) {
|
func GetLoginRealms() ([]Realm, error) {
|
||||||
realms := []Realm{}
|
realms := []Realm{}
|
||||||
|
|
||||||
@@ -49,6 +37,18 @@ func GetLoginRealms() ([]Realm, error) {
|
|||||||
return realms, nil
|
return realms, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// used when requesting GET /access/domains
|
||||||
|
type GetRealmsBody struct {
|
||||||
|
Data []Realm `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// stores each realm's data
|
||||||
|
type Realm struct {
|
||||||
|
Default int `json:"default"`
|
||||||
|
Realm string `json:"realm"`
|
||||||
|
Comment string `json:"comment"`
|
||||||
|
}
|
||||||
|
|
||||||
func HandleGETLogin(c *gin.Context) {
|
func HandleGETLogin(c *gin.Context) {
|
||||||
realms, err := GetLoginRealms()
|
realms, err := GetLoginRealms()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -56,7 +56,8 @@ func HandleGETLogin(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sel := common.Select{
|
sel := common.Select{
|
||||||
ID: "realm",
|
ID: "realm",
|
||||||
|
Required: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, realm := range realms {
|
for _, realm := range realms {
|
||||||
|
@@ -149,11 +149,6 @@ class InstanceCard extends HTMLElement {
|
|||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
this.actionLock = true;
|
this.actionLock = true;
|
||||||
const targetAction = this.status === "running" ? "stop" : "start";
|
const targetAction = this.status === "running" ? "stop" : "start";
|
||||||
const targetStatus = this.status === "running" ? "stopped" : "running";
|
|
||||||
const prevStatus = this.status;
|
|
||||||
this.status = "loading";
|
|
||||||
|
|
||||||
this.update();
|
|
||||||
|
|
||||||
const result = await requestPVE(`/nodes/${this.node.name}/${this.type}/${this.vmid}/status/${targetAction}`, "POST", { node: this.node.name, vmid: this.vmid });
|
const result = await requestPVE(`/nodes/${this.node.name}/${this.type}/${this.vmid}/status/${targetAction}`, "POST", { node: this.node.name, vmid: this.vmid });
|
||||||
|
|
||||||
@@ -162,22 +157,19 @@ class InstanceCard extends HTMLElement {
|
|||||||
while (true) {
|
while (true) {
|
||||||
const taskStatus = await requestPVE(`/nodes/${this.node.name}/tasks/${result.data}/status`, "GET");
|
const taskStatus = await requestPVE(`/nodes/${this.node.name}/tasks/${result.data}/status`, "GET");
|
||||||
if (taskStatus.data.status === "stopped" && taskStatus.data.exitstatus === "OK") { // task stopped and was successful
|
if (taskStatus.data.status === "stopped" && taskStatus.data.exitstatus === "OK") { // task stopped and was successful
|
||||||
this.status = targetStatus;
|
|
||||||
this.update();
|
|
||||||
this.actionLock = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (taskStatus.data.status === "stopped") { // task stopped but was not successful
|
else if (taskStatus.data.status === "stopped") { // task stopped but was not successful
|
||||||
this.status = prevStatus;
|
|
||||||
alert(`Attempted to ${targetAction} ${this.vmid} but got: ${taskStatus.data.exitstatus}`);
|
alert(`Attempted to ${targetAction} ${this.vmid} but got: ${taskStatus.data.exitstatus}`);
|
||||||
this.update();
|
|
||||||
this.actionLock = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else { // task has not stopped
|
else { // task has not stopped
|
||||||
await waitFor(1000);
|
await waitFor(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.actionLock = false;
|
||||||
|
refreshInstances();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -205,25 +197,18 @@ class InstanceCard extends HTMLElement {
|
|||||||
dialog(header, body, async (result, form) => {
|
dialog(header, body, async (result, form) => {
|
||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
this.actionLock = true;
|
this.actionLock = true;
|
||||||
this.status = "loading";
|
|
||||||
this.update();
|
|
||||||
|
|
||||||
const action = {};
|
const action = {};
|
||||||
action.purge = 1;
|
action.purge = 1;
|
||||||
action["destroy-unreferenced-disks"] = 1;
|
action["destroy-unreferenced-disks"] = 1;
|
||||||
|
|
||||||
const result = await requestAPI(`/cluster/${this.node.name}/${this.type}/${this.vmid}/delete`, "DELETE");
|
const result = await requestAPI(`/cluster/${this.node.name}/${this.type}/${this.vmid}/delete`, "DELETE");
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
if (this.parentElement) {
|
|
||||||
this.parentElement.removeChild(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(`Attempted to delete ${this.vmid} but got: ${result.error}`);
|
alert(`Attempted to delete ${this.vmid} but got: ${result.error}`);
|
||||||
this.status = this.prevStatus;
|
|
||||||
this.update();
|
|
||||||
this.actionLock = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.actionLock = false;
|
||||||
|
refreshInstances();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{{define "select"}}
|
{{define "select"}}
|
||||||
<select class="w3-select w3-border" id="{{.ID}}" name="{{.ID}}">
|
<select class="w3-select w3-border" id="{{.ID}}" name="{{.ID}}" {{if .Required}}required{{end}}>
|
||||||
{{range .Options}}
|
{{range .Options}}
|
||||||
{{if .Selected}}
|
{{if .Selected}}
|
||||||
<option value="{{.Value}}" selected>{{.Display}}</option>
|
<option value="{{.Value}}" selected>{{.Display}}</option>
|
||||||
|
Reference in New Issue
Block a user