merge migrate_to_libvirtxml
completed migration to libvirtxml
This commit is contained in:
parent
48bdc94351
commit
8e62f7e271
@ -1,10 +1,10 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
)
|
||||
|
||||
// ClusterBuilder is used to build a Cluster object, which can then be used
|
||||
@ -42,12 +42,17 @@ func (c *ClusterBuilder) DefaultHostURI(uri *host.URI) *ClusterBuilder {
|
||||
|
||||
func (c *ClusterBuilder) AddHost(h string) *ClusterBuilder {
|
||||
if _, ok := c.cluster.hosts[h]; ok {
|
||||
log.Println("warning: trying to add duplicate host")
|
||||
log.Warn("cluster.AddHost").
|
||||
Str("hostname", h).
|
||||
Msg("won't overwrite existing host")
|
||||
return c
|
||||
}
|
||||
hc, err := host.ConnectHost(c.cluster.defaultURI, h)
|
||||
if err != nil {
|
||||
log.Printf("failed to connect to host: %s, %s", h, err)
|
||||
log.Error("cluster.AddHost").
|
||||
Str("hostname", h).
|
||||
Err(err).
|
||||
Msg("failed to connect to host")
|
||||
return c
|
||||
}
|
||||
c.cluster.hosts[h] = hc
|
||||
@ -56,12 +61,17 @@ func (c *ClusterBuilder) AddHost(h string) *ClusterBuilder {
|
||||
|
||||
func (c *ClusterBuilder) AddHostWithURI(h string, uri *host.URI) *ClusterBuilder {
|
||||
if _, ok := c.cluster.hosts[h]; ok {
|
||||
log.Println("warning: trying to add duplicate host")
|
||||
log.Warn("cluster.AddHostWithURI").
|
||||
Str("hostname", h).
|
||||
Msg("won't overwrite existing host")
|
||||
return c
|
||||
}
|
||||
hc, err := host.ConnectHost(uri, h)
|
||||
if err != nil {
|
||||
log.Printf("failed to connect to host: %s, %s", h, err)
|
||||
log.Error("cluster.AddHostWithURI").
|
||||
Str("hostname", h).
|
||||
Err(err).
|
||||
Msg("failed to connect to host")
|
||||
return c
|
||||
}
|
||||
c.cluster.hosts[h] = hc
|
||||
|
@ -9,6 +9,7 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
||||
@ -24,3 +25,10 @@ type Cluster struct {
|
||||
hosts map[string]*host.Host
|
||||
defaultURI *host.URI
|
||||
}
|
||||
|
||||
func (c *Cluster) GetHost(h string) (*host.Host, error) {
|
||||
if hh, ok := c.hosts[h]; ok {
|
||||
return hh, nil
|
||||
}
|
||||
return nil, fmt.Errorf("%s: %w", h, ErrHostNotFound)
|
||||
}
|
||||
|
8
cluster/errors.go
Normal file
8
cluster/errors.go
Normal file
@ -0,0 +1,8 @@
|
||||
package cluster
|
||||
|
||||
import "errors"
|
||||
|
||||
// Errors that can happen in the cluster
|
||||
var (
|
||||
ErrHostNotFound = errors.New("host not found")
|
||||
)
|
19
cluster/lock/lock.go
Normal file
19
cluster/lock/lock.go
Normal file
@ -0,0 +1,19 @@
|
||||
// Package lock implements a locking mechanism on shared resources to ensure
|
||||
// they don't get used at the same time. There needs to be a lock for the following:
|
||||
// - VM on Host: A VM must only exist on one host at a time
|
||||
// - Storage attached to VM: Block storage can only be attached to one VM at a time
|
||||
package lock
|
||||
|
||||
// Locker interface used to lock and unlock Lockable resources
|
||||
type Locker interface {
|
||||
Lock(Lockable) error
|
||||
Unlock(Lockable) error
|
||||
}
|
||||
|
||||
// Lockable interface must be attached to lockable resources, such as
|
||||
// Virtual Machines, block devices, and host devices that can be attached
|
||||
// to virtual machines.
|
||||
type Lockable interface {
|
||||
Locked() bool
|
||||
HeldBy() Locker
|
||||
}
|
1
cluster/lock/volume.go
Normal file
1
cluster/lock/volume.go
Normal file
@ -0,0 +1 @@
|
||||
package lock
|
335
cluster/stats.go
335
cluster/stats.go
@ -1,128 +1,215 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/storagepool"
|
||||
)
|
||||
|
||||
// ClusterStats is used to gather stats for the entire cluster
|
||||
// Combined with StatsDiff, we can get some basic cluster wide stats tracking
|
||||
type ClusterStats struct {
|
||||
CPU struct {
|
||||
// CPU Statistics including number of CPUs
|
||||
CPU CPUStats
|
||||
// Memory provides information about the amount of memory, including free and
|
||||
// allocated memory
|
||||
Memory MemoryStats
|
||||
// Storage provides information about storage pools, Only get's stats for active
|
||||
// pools, and will not activate pools that are not already active.
|
||||
// Trys to sort out shared file systems from local filesystems using the Type parameter
|
||||
// of Host.StoragePoolInfo
|
||||
Storage StorageStats
|
||||
// Volume provides information on allocated volumes used in the cluster
|
||||
Volume VolumeStats
|
||||
// VM provides VM specific counters for the cluster
|
||||
VM VMStats
|
||||
// Host provides Host information for the cluster
|
||||
Host HostStats
|
||||
// Network provices available networks, and how many are shared between hosts
|
||||
Network NetworkStats
|
||||
// NetIF provides information about Libvirt allocated networks, usable by the
|
||||
// libvirt cluster
|
||||
NetIF NetIFStats
|
||||
|
||||
old *ClusterStats
|
||||
c *Cluster
|
||||
}
|
||||
|
||||
// CPUStats provides information about the number of CPUs, Cores,
|
||||
// Threads, and Speed available to the cluster.
|
||||
type CPUStats struct {
|
||||
Sockets uint32
|
||||
Cores uint32
|
||||
Threads uint32
|
||||
Allocated uint32
|
||||
}
|
||||
Memory struct {
|
||||
MHz uint64
|
||||
}
|
||||
|
||||
// MemoryStats provies information about the amount of memory, including free and
|
||||
// allocated memory. Allocated is the total allocated to Guests
|
||||
type MemoryStats struct {
|
||||
Total uint64
|
||||
Free uint64
|
||||
Buffers uint64
|
||||
Cached uint64
|
||||
Allocated uint64
|
||||
}
|
||||
Storage struct {
|
||||
}
|
||||
|
||||
// StorageStats provides information about the available storage pools in the cluster,
|
||||
// including the amount of space available, allocated, and how many pools are shared
|
||||
// between hosts
|
||||
// All sizes are in Bytes
|
||||
type StorageStats struct {
|
||||
Total uint64
|
||||
Used uint64
|
||||
Free uint64
|
||||
Active uint32
|
||||
Inactive uint32
|
||||
Pools uint32
|
||||
}
|
||||
|
||||
Volumes struct {
|
||||
// VolumeStats provides information about the number of volumes on the cluster.
|
||||
// Counts volumes in shared storage (as detmermined by StorageStats) only once
|
||||
type VolumeStats struct {
|
||||
Total uint32
|
||||
Active uint32
|
||||
Inactive uint32
|
||||
}
|
||||
}
|
||||
VM struct {
|
||||
}
|
||||
|
||||
// VMStats provides information about the defined Virtual Machines on the cluster
|
||||
type VMStats struct {
|
||||
Count uint32
|
||||
Started uint32
|
||||
Stopped uint32
|
||||
}
|
||||
Host struct {
|
||||
Count uint32
|
||||
}
|
||||
|
||||
// HostStats provides informatoin about the number of hosts defined, and how many
|
||||
// are currently available. An unavailable host will not have it's statistics counted
|
||||
type HostStats struct {
|
||||
Available uint32
|
||||
}
|
||||
Network struct {
|
||||
Nodes uint32
|
||||
}
|
||||
|
||||
// NetworkStats provides informatoin about the available Host network connections,
|
||||
// including bridges and ethernet devices.
|
||||
type NetworkStats struct {
|
||||
Count uint32
|
||||
Active uint32
|
||||
Inactive uint32
|
||||
}
|
||||
}
|
||||
|
||||
old *ClusterStats
|
||||
c *Cluster
|
||||
// NetIFStats provides information about Libvirt defined networks
|
||||
type NetIFStats struct {
|
||||
Count uint32
|
||||
Common uint32
|
||||
Active uint32
|
||||
Inactive uint32
|
||||
}
|
||||
|
||||
// DeviceStats provides information about the number of allocatable devices in the
|
||||
// cluster. These are PCI and USB devices.
|
||||
type DeviceStats struct {
|
||||
Count uint32
|
||||
}
|
||||
|
||||
// SecretStats provides the number of secrets defined throughout the cluster.
|
||||
// Shared secrets are only counted once, and are recognized by their UUID
|
||||
type SecretStats struct {
|
||||
Count uint32
|
||||
Shared uint32
|
||||
}
|
||||
|
||||
// ClusterStats is used to gather stats for the entire cluster
|
||||
type StatDiff struct {
|
||||
CPU struct {
|
||||
CPU CPUDiff
|
||||
Memory MemoryDiff
|
||||
Storage StorageDiff
|
||||
Volume VolumeDiff
|
||||
VM VMDiff
|
||||
Host HostDiff
|
||||
Network NetworkDiff
|
||||
}
|
||||
|
||||
type CPUDiff struct {
|
||||
Sockets int
|
||||
Cores int
|
||||
Threads int
|
||||
Allocated int
|
||||
}
|
||||
Memory struct {
|
||||
Total int
|
||||
Free int
|
||||
Buffers int
|
||||
Cached int
|
||||
Allocated int
|
||||
}
|
||||
Storage struct {
|
||||
Total int
|
||||
Used int
|
||||
Free int
|
||||
Active int
|
||||
Inactive int
|
||||
MHz int
|
||||
}
|
||||
type MemoryDiff struct {
|
||||
Total int64
|
||||
Free int64
|
||||
Buffers int64
|
||||
Cached int64
|
||||
Allocated int64
|
||||
}
|
||||
type StorageDiff struct {
|
||||
Total int64
|
||||
Used int64
|
||||
Free int64
|
||||
Active int64
|
||||
Inactive int64
|
||||
Pools int
|
||||
|
||||
Volumes struct {
|
||||
}
|
||||
type VolumeDiff struct {
|
||||
Total int
|
||||
Active int
|
||||
Inactive int
|
||||
}
|
||||
}
|
||||
VM struct {
|
||||
}
|
||||
type VMDiff struct {
|
||||
Count int
|
||||
Started int
|
||||
Stopped int
|
||||
}
|
||||
Host struct {
|
||||
}
|
||||
type HostDiff struct {
|
||||
Count int
|
||||
Available int
|
||||
}
|
||||
Network struct {
|
||||
}
|
||||
type NetworkDiff struct {
|
||||
Count int
|
||||
Active int
|
||||
Inactive int
|
||||
}
|
||||
}
|
||||
|
||||
// InitStats is given a cluster, which it then uses to load the initial statistics
|
||||
// Does not close connections, but uses the host connections available to the
|
||||
// cluster to add statistics together.
|
||||
func InitStats(c *Cluster) *ClusterStats {
|
||||
log.Info("stats.InitStats").Msg("intializing stats")
|
||||
cs := &ClusterStats{
|
||||
c: c,
|
||||
}
|
||||
|
||||
cs.Update()
|
||||
return cs
|
||||
}
|
||||
|
||||
// Update triggers the stats collector to refresh it's statistics
|
||||
func (cs *ClusterStats) Update() {
|
||||
log.Info("ClusterStats.Update").Msg("copying existing stats")
|
||||
cs.old = cs.copy()
|
||||
|
||||
log.Info("ClusterStats.Update").Msg("reseting stats")
|
||||
cs.reset()
|
||||
// Start looping through each host in the cluster, adding to the total
|
||||
for _, h := range cs.c.hosts {
|
||||
cs.Host.Count++
|
||||
log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling stats")
|
||||
cs.Host.Nodes++
|
||||
cs.Host.Available++
|
||||
|
||||
cs.CPU.Sockets += h.HostInfo.Sockets
|
||||
cs.CPU.Cores += h.HostInfo.Cores
|
||||
cs.CPU.Threads += h.HostInfo.Threads
|
||||
log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling host cpu stats")
|
||||
cs.CPU.Sockets += uint32(h.HostInfo.CPU.Topology.Sockets)
|
||||
cs.CPU.Cores += uint32(h.HostInfo.CPU.Topology.Cores)
|
||||
cs.CPU.Threads += uint32(h.HostInfo.CPU.Topology.Threads * h.HostInfo.CPU.Topology.Cores)
|
||||
cs.CPU.MHz += uint64(h.HostInfo.CPU.Counter.Frequency)
|
||||
|
||||
log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling host memmory stats")
|
||||
cs.Memory.Total += h.NodeMemory.Total
|
||||
cs.Memory.Free += h.NodeMemory.Free
|
||||
cs.Memory.Buffers += h.NodeMemory.Buffers
|
||||
cs.Memory.Cached += h.NodeMemory.Cached
|
||||
|
||||
log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling host storage pool stats")
|
||||
// Storage Pool counting
|
||||
cs.Storage.Pools += uint32(len(h.StoragePoolList))
|
||||
countedSharedPools := map[string]struct{}{}
|
||||
@ -132,128 +219,76 @@ func (cs *ClusterStats) Update() {
|
||||
// Already counted this shared pool, move on
|
||||
continue
|
||||
}
|
||||
if sp.HAEnabled {
|
||||
if isNetworkPool(sp.Type) {
|
||||
countedSharedPools[sp.Name] = struct{}{}
|
||||
}
|
||||
if !sp.Active {
|
||||
cs.Storage.Inactive++
|
||||
continue
|
||||
}
|
||||
cs.Storage.Active++
|
||||
cs.Storage.Total += sp.Capacity
|
||||
cs.Storage.Used += sp.Allocation
|
||||
cs.Storage.Free += sp.Capacity - sp.Allocation
|
||||
// Volumes in the pool
|
||||
cs.Storage.Volumes.Total += uint32(len(sp.Volumes))
|
||||
for range sp.Volumes {
|
||||
cs.Storage.Volumes.Active++
|
||||
}
|
||||
cs.Storage.Total += sp.Capacity.Value
|
||||
cs.Storage.Used += sp.Allocation.Value
|
||||
cs.Storage.Free += sp.Capacity.Value - sp.Allocation.Value
|
||||
}
|
||||
log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling volume stats")
|
||||
cs.Volume.Total += uint32(len(h.VolumeList))
|
||||
|
||||
log.Info("ClusterStats.Update").Str("hostname", h.HostName).Msg("filling VM stats")
|
||||
// VM Count
|
||||
cs.VM.Count += uint32(len(h.VMList))
|
||||
for _, vm := range h.VMList {
|
||||
cs.CPU.Allocated += uint32(vm.VCPUs)
|
||||
cs.Memory.Allocated += uint64(vm.Memory)
|
||||
if vm.Active {
|
||||
cs.VM.Started++
|
||||
continue
|
||||
}
|
||||
cs.VM.Stopped++
|
||||
log.Info("ClusterStats.Update").Str("hostname", h.HostName).Str("vmname", vm.Name).Msg("filling vm info")
|
||||
cs.CPU.Allocated += uint32(vm.VCPU.Value)
|
||||
cs.Memory.Allocated += uint64(vm.Memory.Value)
|
||||
}
|
||||
|
||||
// Network count
|
||||
cs.Network.Count += uint32(len(h.NetworkList))
|
||||
for _, ni := range h.NetworkList {
|
||||
if ni.Active {
|
||||
cs.Network.Active++
|
||||
continue
|
||||
}
|
||||
cs.Network.Inactive++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Diff returns a map of all the field and how they changed
|
||||
func (cs *ClusterStats) Diff() StatDiff {
|
||||
return StatDiff{
|
||||
CPU: struct {
|
||||
Sockets int
|
||||
Cores int
|
||||
Threads int
|
||||
Allocated int
|
||||
}{
|
||||
CPU: CPUDiff{
|
||||
Sockets: int(cs.CPU.Sockets) - int(cs.old.CPU.Sockets),
|
||||
Cores: int(cs.CPU.Cores) - int(cs.old.CPU.Cores),
|
||||
Threads: int(cs.CPU.Threads) - int(cs.old.CPU.Threads),
|
||||
Allocated: int(cs.CPU.Allocated) - int(cs.old.CPU.Allocated),
|
||||
MHz: int(cs.CPU.MHz) - int(cs.old.CPU.MHz),
|
||||
},
|
||||
Memory: struct {
|
||||
Total int
|
||||
Free int
|
||||
Buffers int
|
||||
Cached int
|
||||
Allocated int
|
||||
}{
|
||||
Total: int(cs.old.Memory.Total - cs.Memory.Total),
|
||||
Free: int(cs.old.Memory.Free - cs.Memory.Free),
|
||||
Buffers: int(cs.old.Memory.Buffers - cs.Memory.Buffers),
|
||||
Cached: int(cs.old.Memory.Cached - cs.Memory.Cached),
|
||||
Allocated: int(cs.old.Memory.Allocated - cs.Memory.Allocated),
|
||||
Memory: MemoryDiff{
|
||||
Total: int64(cs.old.Memory.Total) - int64(cs.Memory.Total),
|
||||
Free: int64(cs.old.Memory.Free) - int64(cs.Memory.Free),
|
||||
Buffers: int64(cs.old.Memory.Buffers) - int64(cs.Memory.Buffers),
|
||||
Cached: int64(cs.old.Memory.Cached) - int64(cs.Memory.Cached),
|
||||
Allocated: int64(cs.old.Memory.Allocated) - int64(cs.Memory.Allocated),
|
||||
},
|
||||
Storage: struct {
|
||||
Total int
|
||||
Used int
|
||||
Free int
|
||||
Active int
|
||||
Inactive int
|
||||
Pools int
|
||||
Volumes struct {
|
||||
Total int
|
||||
Active int
|
||||
Inactive int
|
||||
}
|
||||
}{
|
||||
Total: int(cs.old.Storage.Total - cs.Storage.Total),
|
||||
Used: int(cs.old.Storage.Used - cs.Storage.Used),
|
||||
Free: int(cs.old.Storage.Free - cs.Storage.Free),
|
||||
Active: int(cs.old.Storage.Active - cs.Storage.Active),
|
||||
Inactive: int(cs.old.Storage.Inactive - cs.Storage.Inactive),
|
||||
Pools: int(cs.old.Storage.Pools - cs.Storage.Pools),
|
||||
Volumes: struct {
|
||||
Total int
|
||||
Active int
|
||||
Inactive int
|
||||
}{
|
||||
Total: int(cs.old.Storage.Volumes.Total - cs.Storage.Volumes.Total),
|
||||
Active: int(cs.old.Storage.Volumes.Active - cs.Storage.Volumes.Active),
|
||||
Inactive: int(cs.old.Storage.Volumes.Inactive - cs.Storage.Volumes.Inactive),
|
||||
Storage: StorageDiff{
|
||||
Total: int64(cs.old.Storage.Total) - int64(cs.Storage.Total),
|
||||
Used: int64(cs.old.Storage.Used) - int64(cs.Storage.Used),
|
||||
Free: int64(cs.old.Storage.Free) - int64(cs.Storage.Free),
|
||||
Active: int64(cs.old.Storage.Active) - int64(cs.Storage.Active),
|
||||
Inactive: int64(cs.old.Storage.Inactive) - int64(cs.Storage.Inactive),
|
||||
Pools: int(cs.old.Storage.Pools) - int(cs.Storage.Pools),
|
||||
},
|
||||
Volume: VolumeDiff{
|
||||
Total: int(cs.old.Volume.Total) - int(cs.Volume.Total),
|
||||
Active: int(cs.old.Volume.Active) - int(cs.Volume.Active),
|
||||
Inactive: int(cs.old.Volume.Inactive) - int(cs.Volume.Inactive),
|
||||
},
|
||||
VM: struct {
|
||||
Count int
|
||||
Started int
|
||||
Stopped int
|
||||
}{
|
||||
Count: int(cs.old.VM.Count - cs.VM.Count),
|
||||
Started: int(cs.old.VM.Started - cs.VM.Started),
|
||||
Stopped: int(cs.old.VM.Stopped - cs.VM.Stopped),
|
||||
|
||||
VM: VMDiff{
|
||||
Count: int(cs.old.VM.Count) - int(cs.VM.Count),
|
||||
Started: int(cs.old.VM.Started) - int(cs.VM.Started),
|
||||
Stopped: int(cs.old.VM.Stopped) - int(cs.VM.Stopped),
|
||||
},
|
||||
Host: struct {
|
||||
Count int
|
||||
Available int
|
||||
}{
|
||||
Count: int(cs.old.Host.Count - cs.Host.Count),
|
||||
Available: int(cs.old.Host.Available - cs.Host.Available),
|
||||
Host: HostDiff{
|
||||
Count: int(cs.old.Host.Nodes) - int(cs.Host.Nodes),
|
||||
Available: int(cs.old.Host.Available) - int(cs.Host.Available),
|
||||
},
|
||||
Network: struct {
|
||||
Count int
|
||||
Active int
|
||||
Inactive int
|
||||
}{
|
||||
Count: int(cs.old.Network.Count - cs.Network.Count),
|
||||
Active: int(cs.old.Network.Active - cs.Network.Active),
|
||||
Inactive: int(cs.old.Network.Inactive - cs.Network.Inactive),
|
||||
Network: NetworkDiff{
|
||||
Count: int(cs.old.Network.Count) - int(cs.Network.Count),
|
||||
Active: int(cs.old.Network.Active) - int(cs.Network.Active),
|
||||
Inactive: int(cs.old.Network.Inactive) - int(cs.Network.Inactive),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -270,11 +305,13 @@ func (cs *ClusterStats) reset() {
|
||||
cs.CPU.Cores = 0
|
||||
cs.CPU.Threads = 0
|
||||
cs.CPU.Allocated = 0
|
||||
cs.CPU.MHz = 0
|
||||
|
||||
cs.Memory.Total = 0
|
||||
cs.Memory.Free = 0
|
||||
cs.Memory.Buffers = 0
|
||||
cs.Memory.Cached = 0
|
||||
cs.Memory.Allocated = 0
|
||||
|
||||
cs.Storage.Total = 0
|
||||
cs.Storage.Used = 0
|
||||
@ -283,14 +320,32 @@ func (cs *ClusterStats) reset() {
|
||||
cs.Storage.Inactive = 0
|
||||
cs.Storage.Pools = 0
|
||||
|
||||
cs.Volume.Total = 0
|
||||
cs.Volume.Active = 0
|
||||
cs.Volume.Inactive = 0
|
||||
|
||||
cs.VM.Count = 0
|
||||
cs.VM.Started = 0
|
||||
cs.VM.Stopped = 0
|
||||
|
||||
cs.Host.Count = 0
|
||||
cs.Host.Available = 0
|
||||
cs.Host.Nodes = 0
|
||||
|
||||
cs.Network.Count = 0
|
||||
cs.Network.Active = 0
|
||||
cs.Network.Inactive = 0
|
||||
|
||||
cs.NetIF.Count = 0
|
||||
cs.NetIF.Common = 0
|
||||
cs.NetIF.Active = 0
|
||||
cs.NetIF.Inactive = 0
|
||||
}
|
||||
|
||||
func isNetworkPool(pooltype string) bool {
|
||||
for _, t := range storagepool.NetTypes {
|
||||
if t == pooltype {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
24
go.mod
24
go.mod
@ -3,16 +3,28 @@ module git.staur.ca/stobbsm/clustvirt
|
||||
go 1.22.1
|
||||
|
||||
require (
|
||||
github.com/a-h/templ v0.2.598
|
||||
github.com/a-h/templ v0.2.646
|
||||
github.com/go-chi/chi/v5 v5.0.12
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.1
|
||||
gopkg.in/ffmt.v1 v1.5.6
|
||||
github.com/jaypipes/pcidb v1.0.0
|
||||
github.com/rs/zerolog v1.32.0
|
||||
libvirt.org/go/libvirt v1.10001.0
|
||||
libvirt.org/go/libvirtxml v1.10001.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/blend/go-sdk v1.20220411.3 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
golang.org/x/image v0.11.0 // indirect
|
||||
github.com/go-chi/cors v1.2.1 // indirect
|
||||
github.com/go-chi/docgen v1.2.0 // indirect
|
||||
github.com/go-chi/jwtauth v1.2.0 // indirect
|
||||
github.com/goccy/go-json v0.3.5 // indirect
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.7 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.0 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.0 // indirect
|
||||
github.com/lestrrat-go/jwx v1.1.0 // indirect
|
||||
github.com/lestrrat-go/option v1.0.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/go-homedir v1.0.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
)
|
||||
|
111
go.sum
111
go.sum
@ -1,50 +1,97 @@
|
||||
github.com/a-h/templ v0.2.598 h1:6jMIHv6wQZvdPxTuv87erW4RqN/FPU0wk7ZHN5wVuuo=
|
||||
github.com/a-h/templ v0.2.598/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8=
|
||||
github.com/blend/go-sdk v1.20220411.3 h1:GFV4/FQX5UzXLPwWV03gP811pj7B8J2sbuq+GJQofXc=
|
||||
github.com/blend/go-sdk v1.20220411.3/go.mod h1:7lnH8fTi6U4i1fArEXRyOIY2E1X4MALg09qsQqY1+ak=
|
||||
github.com/a-h/templ v0.2.646 h1:F4+tGmPavtPMdWF3ofCDkPx/31qtInztsmUdzu6EzVU=
|
||||
github.com/a-h/templ v0.2.646/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k=
|
||||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-chi/docgen v1.2.0 h1:da0Nq2PKU9W9pSOTUfVrKI1vIgTGpauo9cfh4Iwivek=
|
||||
github.com/go-chi/docgen v1.2.0/go.mod h1:G9W0G551cs2BFMSn/cnGwX+JBHEloAgo17MBhyrnhPI=
|
||||
github.com/go-chi/jwtauth v1.2.0 h1:Z116SPpevIABBYsv8ih/AHYBHmd4EufKSKsLUnWdrTM=
|
||||
github.com/go-chi/jwtauth v1.2.0/go.mod h1:NTUpKoTQV6o25UwYE6w/VaLUu83hzrVKYTVo+lE6qDA=
|
||||
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||
github.com/goccy/go-json v0.3.5 h1:HqrLjEWx7hD62JRhBh+mHv+rEEzBANIu6O0kbDlaLzU=
|
||||
github.com/goccy/go-json v0.3.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.1 h1:2u7na789qiD5WzccZsFz4MJWOJP72G+2kUuJoSNqWnE=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.1/go.mod h1:CyCAUt2oqvfhCl6Q5ZvAZwItgpQKZOkCJGb+VGv6l14=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
|
||||
github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.7 h1:i2SeK33aOFJlUNJZzf2IpXRBvqBBnaGXfY5Xaop/GsE=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.7/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||
github.com/lestrrat-go/codegen v1.0.0/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM=
|
||||
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
|
||||
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
|
||||
github.com/lestrrat-go/iter v1.0.0 h1:QD+hHQPDSHC4rCJkZYY/yXChYr/vjfBopKekTc+7l4Q=
|
||||
github.com/lestrrat-go/iter v1.0.0/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||
github.com/lestrrat-go/jwx v1.1.0 h1:gerfaQK3mEIL8X8oJ5MFvsB/JuxXoGryLtTlNmPi3/k=
|
||||
github.com/lestrrat-go/jwx v1.1.0/go.mod h1:vn9FzD6gJtKkgYs7RTKV7CjWtEka8F/voUollhnn4QE=
|
||||
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
|
||||
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
|
||||
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/ffmt.v1 v1.5.6 h1:4Bu3riZp5sAIXW2T/18JM9BkwJLodurXFR0f7PXp+cw=
|
||||
gopkg.in/ffmt.v1 v1.5.6/go.mod h1:LssvGOZFiBGoBcobkTqnyh+uN1VzIRoibW+c0JI/Ha4=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
libvirt.org/go/libvirt v1.10001.0 h1:lEVDNE7xfzmZXiDEGIS8NvJSuaz11OjRXw+ufbQEtPY=
|
||||
libvirt.org/go/libvirt v1.10001.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ=
|
||||
libvirt.org/go/libvirtxml v1.10001.0 h1:r9WBs24r3mxIG3/hAMRRwDMy4ZaPHmhHjw72o/ceXic=
|
||||
|
@ -3,9 +3,9 @@ package guest
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"git.staur.ca/stobbsm/clustvirt/util"
|
||||
"libvirt.org/go/libvirt"
|
||||
)
|
||||
@ -248,7 +248,7 @@ func GetGuest(name string, conn *libvirt.Connect) (*VM, error) {
|
||||
|
||||
// Not errors, but still log the warnings when this happens
|
||||
if g.BackupXML, err = g.dom.BackupGetXMLDesc(0); err != nil {
|
||||
log.Printf("WARNING: While loading backup information: %s", err)
|
||||
log.Warn("guest.GetGuest").Str("guest", g.Name).Err(err).Send()
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -262,7 +262,7 @@ func GetGuest(name string, conn *libvirt.Connect) (*VM, error) {
|
||||
|
||||
// Close closes an open connection
|
||||
func (g *VM) Close() error {
|
||||
log.Println("Closing VM", g.Name)
|
||||
log.Info("guest.Close").Str("guest", g.Name).Msg("closing vm")
|
||||
close(g.close)
|
||||
return <-g.closeErr
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/wcharczuk/go-chart/v2"
|
||||
)
|
||||
|
||||
// This file contains utilities to create charts based on the different data
|
||||
// When a chart is rendered, it can return either an SVG or PNG. SVG is preferrable.
|
||||
|
||||
func (h *Host) ChartMemory() string {
|
||||
h.getNodeInfo()
|
||||
log.Println("Generating Chart")
|
||||
memFree := float64(h.NodeMemory.Free)
|
||||
memCached := float64(h.NodeMemory.Cached)
|
||||
memBuffer := float64(h.NodeMemory.Buffers)
|
||||
memTotal := float64(h.NodeMemory.Total)
|
||||
|
||||
c := chart.PieChart{
|
||||
Title: fmt.Sprintf("Memory Info %s", h.SystemHostName),
|
||||
Width: 256,
|
||||
Height: 256,
|
||||
Values: []chart.Value{
|
||||
{Value: memTotal - memFree, Label: fmt.Sprintf("%.2f%% Free", memFree/memTotal*100)},
|
||||
{Value: memTotal - memCached, Label: fmt.Sprintf("%.2f%% Cached", memCached/memTotal*100)},
|
||||
{Value: memTotal - memBuffer, Label: fmt.Sprintf("%.2f%% Buffers", memBuffer/memTotal*100)},
|
||||
},
|
||||
}
|
||||
sb := new(strings.Builder)
|
||||
log.Println("Rendering chart")
|
||||
if err := c.Render(chart.SVG, sb); err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return sb.String()
|
||||
}
|
12
lib/host/errors.go
Normal file
12
lib/host/errors.go
Normal file
@ -0,0 +1,12 @@
|
||||
package host
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// XML errors
|
||||
ErrGetXML = errors.New("error getting XML")
|
||||
ErrParseXML = errors.New("error parsing XML")
|
||||
|
||||
// Hostinfo errors
|
||||
ErrHostInfo = errors.New("error processing HostInfo")
|
||||
)
|
569
lib/host/lib.go
569
lib/host/lib.go
@ -7,14 +7,10 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/guest"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/secret"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/storagepool"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/storagevol"
|
||||
"git.staur.ca/stobbsm/clustvirt/util"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"libvirt.org/go/libvirt"
|
||||
"libvirt.org/go/libvirtxml"
|
||||
)
|
||||
@ -27,20 +23,8 @@ type Host struct {
|
||||
HostName string
|
||||
// SystemHostName is the hostname as reported by the system itself
|
||||
SystemHostName string
|
||||
// FreeMemory is the available free memory
|
||||
FreeMemory uint64
|
||||
// LibVersion is the version of Libvirt on the host
|
||||
LibVersion uint32
|
||||
// HostInfo provides basic HW information about a host
|
||||
HostInfo NodeInfo
|
||||
// HostSEVInfo provides informatoin about AMD SEV extentions available on the host
|
||||
HostSEVInfo SEVInfo
|
||||
// AvailableCPUTypes are the available types of CPUs that can be used for VM creation
|
||||
AvailableCPUTypes []string
|
||||
// NodeMemory provides basic memory information about the Host
|
||||
NodeMemory NodeMemoryInfo
|
||||
// StorageCapabilities is the XML representation of the hosts storage capabilities
|
||||
StorageCapabilities string
|
||||
// SysInfo is the XML representation of the host system information
|
||||
SysInfo string
|
||||
// Alive indicates if the connection is alive
|
||||
@ -49,18 +33,24 @@ type Host struct {
|
||||
Encrypted bool
|
||||
// Secure indicates if the connection is secure
|
||||
Secure bool
|
||||
// HostInfo provides basic HW information about a host
|
||||
HostInfo *libvirtxml.CapsHost
|
||||
// NodeMemory provides basic memory information about the Host
|
||||
NodeMemory *NodeMemoryInfo
|
||||
// VMList is the list of virtual machines available to the host
|
||||
VMList []VMInfo
|
||||
VMList []*libvirtxml.Domain
|
||||
// NetIfList is the list of network interfaces on the host
|
||||
NetIfFList []NetIfInfo
|
||||
NetIfFList []*libvirtxml.Interface
|
||||
// NetworkList is the list of defined networks on the host
|
||||
NetworkList []NetworkInfo
|
||||
NetworkList []*libvirtxml.Network
|
||||
// DeviceList is the list of devices on the host
|
||||
DeviceList []DeviceInfo
|
||||
DeviceList []*libvirtxml.NodeDevice
|
||||
// SecretList provides a list of secrets available to the host
|
||||
SecretList []SecretInfo
|
||||
SecretList []*libvirtxml.Secret
|
||||
// StoragePoolList provides the list of stoarge ppols available to the host
|
||||
StoragePoolList []StoragePoolInfo
|
||||
StoragePoolList []*libvirtxml.StoragePool
|
||||
// VolumeList is the list of volumes available on the host
|
||||
VolumeList []*libvirtxml.StorageVolume
|
||||
|
||||
uri *URI
|
||||
conn *libvirt.Connect
|
||||
@ -68,108 +58,6 @@ type Host struct {
|
||||
closeErr chan error
|
||||
}
|
||||
|
||||
// DeviceInfo holds basic information for host devices
|
||||
type DeviceInfo struct {
|
||||
Name string
|
||||
Capabilities []string
|
||||
XML string
|
||||
}
|
||||
|
||||
// VMInfo holds basic VM information, like the name and ID
|
||||
type VMInfo struct {
|
||||
Name string
|
||||
ID uint
|
||||
UUID []byte
|
||||
XML string
|
||||
Active bool
|
||||
VCPUs uint
|
||||
Memory uint
|
||||
// States are the current states active on the host
|
||||
States []guest.VMState
|
||||
}
|
||||
|
||||
// SecretInfo doesn't let you see the contents of secrets, but does let you see what secrets have
|
||||
// been defined in a simple format.
|
||||
type SecretInfo struct {
|
||||
UUID string
|
||||
XML string
|
||||
Type string
|
||||
}
|
||||
|
||||
// StoragePoolInfo holds basic information on storage pools
|
||||
type StoragePoolInfo struct {
|
||||
Name string
|
||||
UUID []byte
|
||||
Type string
|
||||
XML string
|
||||
Active bool
|
||||
Persistent bool
|
||||
AutoStart bool
|
||||
State string
|
||||
Capacity uint64
|
||||
Allocation uint64
|
||||
Available uint64
|
||||
IsNet bool
|
||||
// HAEnabled indicates if the storage pool has High Availability
|
||||
HAEnabled bool
|
||||
// Volumes defined in the storage pool
|
||||
Volumes []VolumeInfo
|
||||
}
|
||||
|
||||
// VolumeInfo holds basic information about Volumes available in storage pools
|
||||
type VolumeInfo struct {
|
||||
Name string
|
||||
Key string
|
||||
Path string
|
||||
Type string
|
||||
Capacity uint64
|
||||
Allocation uint64
|
||||
XML string
|
||||
}
|
||||
|
||||
// NetIfInfo holds basic information about available network interfaces (not their connections, the devices themselves)
|
||||
type NetIfInfo struct {
|
||||
Name string
|
||||
MacAddr string
|
||||
XML string
|
||||
}
|
||||
|
||||
// NetworkInfo holds basic information about network connections
|
||||
type NetworkInfo struct {
|
||||
Name string
|
||||
UUID []byte
|
||||
XML string
|
||||
Active bool
|
||||
// NetIf is the network interface this connection is applied to
|
||||
NetIf NetIfInfo
|
||||
}
|
||||
|
||||
// NodeInfo represents the basic HW info for a host node
|
||||
type NodeInfo struct {
|
||||
// livirt.NodeInfo section
|
||||
Model string
|
||||
Memory uint64
|
||||
Cpus uint
|
||||
MHz uint
|
||||
Nodes uint32
|
||||
Sockets uint32
|
||||
Cores uint32
|
||||
Threads uint32
|
||||
}
|
||||
|
||||
// SEVInfo provides information about AMD SEV support
|
||||
type SEVInfo struct {
|
||||
// livirt.NodeSEVParameters section
|
||||
SEVEnabled bool
|
||||
PDH string
|
||||
CertChain string
|
||||
CBitPos uint
|
||||
ReducedPhysBits uint
|
||||
MaxGuests uint
|
||||
MaxEsGuests uint
|
||||
CPU0ID string
|
||||
}
|
||||
|
||||
// NodeMemoryInfo provides statistis about node memory usage from libvirt.NodeMemoryStats
|
||||
type NodeMemoryInfo struct {
|
||||
Total uint64
|
||||
@ -226,7 +114,7 @@ func (h *Host) GetGuestByName(name string) (*guest.VM, error) {
|
||||
|
||||
// Close triggers closing the host connection
|
||||
func (h *Host) Close() error {
|
||||
log.Println("Closing Host", h.HostName)
|
||||
log.Info("Host.Close").Str("hostname", h.HostName).Msg("closing connection")
|
||||
close(h.close)
|
||||
return <-h.closeErr
|
||||
}
|
||||
@ -234,17 +122,18 @@ func (h *Host) Close() error {
|
||||
// private methods that load the different informational parts
|
||||
|
||||
func (h *Host) getInfo() {
|
||||
var wg = new(sync.WaitGroup)
|
||||
wg := new(sync.WaitGroup)
|
||||
|
||||
log.Info("host.getInfo").Str("hostname", h.HostName).Msg("collecting host information")
|
||||
infoFuncs := []func(){
|
||||
h.getDevicesInfo,
|
||||
// h.getDomainInfo,
|
||||
h.getIfaceInfo,
|
||||
h.hostInfo,
|
||||
h.memoryInfo,
|
||||
h.getStoragePools,
|
||||
h.getNetsInfo,
|
||||
h.getNodeInfo,
|
||||
// h.getSEVInfo,
|
||||
// h.getSecretsInfo,
|
||||
// h.getStoragePools,
|
||||
h.getIfaceInfo,
|
||||
h.getDevicesInfo,
|
||||
h.getDomainInfo,
|
||||
h.getSecretsInfo,
|
||||
}
|
||||
|
||||
for _, f := range infoFuncs {
|
||||
@ -258,298 +147,242 @@ func (h *Host) getInfo() {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (h *Host) hostInfo() {
|
||||
log.Info("host.hostInfo").Str("hostname", h.HostName).Msg("collecting hostinfo")
|
||||
var err error
|
||||
|
||||
rawxml, err := h.conn.GetCapabilities()
|
||||
if err != nil {
|
||||
log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
}
|
||||
xmldoc := &libvirtxml.Caps{}
|
||||
if err = xmldoc.Unmarshal(rawxml); err != nil {
|
||||
log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
}
|
||||
h.HostInfo = &xmldoc.Host
|
||||
h.SystemHostName, err = h.conn.GetHostname()
|
||||
if err != nil {
|
||||
log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(err).Msg("unable to set SystemHostName")
|
||||
}
|
||||
if h.SystemHostName == "" {
|
||||
h.SystemHostName = h.HostName
|
||||
}
|
||||
log.Info("Host.hostInfo").Str("hostname", h.HostName).Str("system hostname", h.SystemHostName).Msg("set system hostname")
|
||||
h.LibVersion, err = h.conn.GetLibVersion()
|
||||
if err != nil {
|
||||
log.Error("Host.hostInfo").Str("hostname", h.HostName).Err(err).Msg("unable to get libversion")
|
||||
return
|
||||
}
|
||||
log.Info("Host.hostInfo").Str("hostname", h.HostName).Uint32("libversion", h.LibVersion).Send()
|
||||
}
|
||||
|
||||
func (h *Host) memoryInfo() {
|
||||
mi, err := h.conn.GetMemoryStats(libvirt.NODE_MEMORY_STATS_ALL_CELLS, 0)
|
||||
if err != nil {
|
||||
log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Send()
|
||||
}
|
||||
h.NodeMemory = &NodeMemoryInfo{
|
||||
Total: mi.Total,
|
||||
Free: mi.Free,
|
||||
Buffers: mi.Buffers,
|
||||
Cached: mi.Cached,
|
||||
}
|
||||
|
||||
h.SysInfo, err = h.conn.GetSysinfo(0)
|
||||
if err != nil {
|
||||
log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed to GetSysInfo")
|
||||
}
|
||||
|
||||
h.Alive, err = h.conn.IsAlive()
|
||||
if err != nil {
|
||||
log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed check to IsAlive")
|
||||
}
|
||||
h.Encrypted, err = h.conn.IsEncrypted()
|
||||
if err != nil {
|
||||
log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed to check IsEncrypted")
|
||||
}
|
||||
h.Secure, err = h.conn.IsSecure()
|
||||
if err != nil {
|
||||
log.Error("Host.memoryInfo").Str("hostname", h.HostName).Err(err).Msg("failed to check IsSecure")
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Host) getStoragePools() {
|
||||
log.Info("host.getStoragePools").Str("hostname", h.HostName).Msg("collection storage pool information")
|
||||
// Get list of all storage pools on the host
|
||||
spools, err := h.conn.ListAllStoragePools(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(err).Msg("failed to ListAllStoragePools")
|
||||
}
|
||||
if len(spools) > 0 {
|
||||
h.StoragePoolList = make([]StoragePoolInfo, len(spools))
|
||||
h.StoragePoolList = make([]*libvirtxml.StoragePool, len(spools))
|
||||
for i, s := range spools {
|
||||
if h.StoragePoolList[i].XML, err = s.GetXMLDesc(0); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.StoragePoolList[i].Name, err = s.GetName(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.StoragePoolList[i].UUID, err = s.GetUUID(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.StoragePoolList[i].Active, err = s.IsActive(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.StoragePoolList[i].Persistent, err = s.IsPersistent(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.StoragePoolList[i].AutoStart, err = s.GetAutostart(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
spInfo, err := s.GetInfo()
|
||||
// run in a function to allow defer s.Free()
|
||||
func() {
|
||||
defer s.Free()
|
||||
// Get the XML represenation of each storage pool, parse it with libvirtxml
|
||||
rawxml, err := s.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.StoragePoolList[i].State = storagepool.StoragePoolStateMap[spInfo.State]
|
||||
h.StoragePoolList[i].Capacity = spInfo.Capacity
|
||||
h.StoragePoolList[i].Allocation = spInfo.Allocation
|
||||
h.StoragePoolList[i].Available = spInfo.Available
|
||||
|
||||
spoolXML := &libvirtxml.StoragePool{}
|
||||
if err = spoolXML.Unmarshal(h.StoragePoolList[i].XML); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.StoragePoolList[i].Type = spoolXML.Type
|
||||
for _, t := range storagepool.NetTypes {
|
||||
if h.StoragePoolList[i].Type == t {
|
||||
h.StoragePoolList[i].IsNet = true
|
||||
h.StoragePoolList[i].HAEnabled = true
|
||||
continue
|
||||
}
|
||||
log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
xmldoc := &libvirtxml.StoragePool{}
|
||||
err = xmldoc.Unmarshal(rawxml)
|
||||
if err != nil {
|
||||
log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
h.StoragePoolList[i] = xmldoc
|
||||
|
||||
// Get list of all storage volumes in the current storage pool
|
||||
svols, err := s.ListAllStorageVolumes(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Err(err).Msg("failed to ListAllStorageVolumes")
|
||||
}
|
||||
if len(svols) > 0 {
|
||||
h.StoragePoolList[i].Volumes = make([]VolumeInfo, len(svols))
|
||||
// define temporary variable to hold slice of StorageVolume, that can
|
||||
// either be appended to the existing slice, or used in place of the newly
|
||||
// defined slice
|
||||
tvl := make([]*libvirtxml.StorageVolume, len(svols))
|
||||
for j, sv := range svols {
|
||||
if h.StoragePoolList[i].Volumes[j].Name, err = sv.GetName(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.StoragePoolList[i].Volumes[j].Key, err = sv.GetKey(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.StoragePoolList[i].Volumes[j].Path, err = sv.GetPath(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
svInfo, err := sv.GetInfo() // Type, Capacity, Allocation
|
||||
// run in a function so I can defer the sv.Free() call
|
||||
func() {
|
||||
defer sv.Free()
|
||||
rawxml, err = sv.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
h.StoragePoolList[i].Volumes[j].Type = storagevol.StorageVolTypeMap[svInfo.Type]
|
||||
h.StoragePoolList[i].Volumes[j].Capacity = svInfo.Capacity
|
||||
h.StoragePoolList[i].Volumes[j].Allocation = svInfo.Allocation
|
||||
if h.StoragePoolList[i].Volumes[j].XML, err = sv.GetXMLDesc(0); err != nil {
|
||||
log.Println(err)
|
||||
xmldoc := &libvirtxml.StorageVolume{}
|
||||
err = xmldoc.Unmarshal(rawxml)
|
||||
if err != nil {
|
||||
log.Error("Host.getStoragePools").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
|
||||
sv.Free()
|
||||
tvl[j] = xmldoc
|
||||
log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("added volume", tvl[j].Name).Send()
|
||||
}()
|
||||
}
|
||||
// Append the contents of tvl to h.VolumeList
|
||||
if h.VolumeList == nil {
|
||||
log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Msg("initializing VolumeList")
|
||||
h.VolumeList = []*libvirtxml.StorageVolume{}
|
||||
}
|
||||
// Only append if the temporary storage volume isn't nil
|
||||
log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Int("VolumeList count", len(h.VolumeList)).Msg("before filter")
|
||||
for _, tsv := range tvl {
|
||||
if tsv != nil {
|
||||
h.VolumeList = append(h.VolumeList, tsv)
|
||||
}
|
||||
}
|
||||
|
||||
s.Free()
|
||||
log.Info("Host.getStoragePools").Str("hostname", h.HostName).Str("storagepool", h.StoragePoolList[i].Name).Int("VolumeList count", len(h.VolumeList)).Msg("after filter")
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Host) getSecretsInfo() {
|
||||
log.Info("host.getSecretsInfo").Str("hostname", h.HostName).Msg("collecting secret information")
|
||||
nsecrets, err := h.conn.ListAllSecrets(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getSecretsInfo").Str("hostname", h.HostName).Err(err).Send()
|
||||
}
|
||||
if len(nsecrets) > 0 {
|
||||
h.SecretList = make([]SecretInfo, len(nsecrets))
|
||||
h.SecretList = make([]*libvirtxml.Secret, len(nsecrets))
|
||||
for i, s := range nsecrets {
|
||||
if h.SecretList[i].XML, err = s.GetXMLDesc(0); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
stype, err := s.GetUsageType()
|
||||
func() {
|
||||
defer s.Free()
|
||||
rawxml, err := s.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getSecretsInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
}
|
||||
h.SecretList[i].Type = secret.SecretUsageTypeMap[stype]
|
||||
|
||||
s.Free()
|
||||
xmldoc := &libvirtxml.Secret{}
|
||||
if err = xmldoc.Unmarshal(rawxml); err != nil {
|
||||
log.Error("Host.getSecretsInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
}
|
||||
h.SecretList[i] = xmldoc
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Host) getNodeInfo() {
|
||||
var err error
|
||||
h.AvailableCPUTypes, err = h.conn.GetCPUModelNames("x86_64", 0)
|
||||
if err != nil {
|
||||
log.Println("Error getting cpu model names", err)
|
||||
}
|
||||
|
||||
ni, err := h.conn.GetNodeInfo()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.HostInfo.Model = ni.Model
|
||||
h.HostInfo.Memory = ni.Memory
|
||||
h.HostInfo.Cpus = ni.Cpus
|
||||
h.HostInfo.MHz = ni.MHz
|
||||
h.HostInfo.Nodes = ni.Nodes
|
||||
h.HostInfo.Sockets = ni.Sockets
|
||||
h.HostInfo.Cores = ni.Cores
|
||||
h.HostInfo.Threads = ni.Threads
|
||||
h.SystemHostName, err = h.conn.GetHostname()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.SystemHostName == "" {
|
||||
h.SystemHostName = h.HostName
|
||||
}
|
||||
h.LibVersion, err = h.conn.GetLibVersion()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.FreeMemory, err = h.conn.GetFreeMemory()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
mi, err := h.conn.GetMemoryStats(libvirt.NODE_MEMORY_STATS_ALL_CELLS, 0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.NodeMemory.Total = mi.Total
|
||||
h.NodeMemory.Free = mi.Free
|
||||
h.NodeMemory.Buffers = mi.Buffers
|
||||
h.NodeMemory.Cached = mi.Cached
|
||||
|
||||
h.StorageCapabilities, err = h.conn.GetStoragePoolCapabilities(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
h.SysInfo, err = h.conn.GetSysinfo(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
h.Alive, err = h.conn.IsAlive()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.Encrypted, err = h.conn.IsEncrypted()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.Secure, err = h.conn.IsSecure()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Host) getSEVInfo() {
|
||||
// getSEVInfo
|
||||
h.HostSEVInfo.SEVEnabled = true
|
||||
ns, err := h.conn.GetSEVInfo(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
lverr, ok := err.(libvirt.Error)
|
||||
if ok {
|
||||
switch lverr.Code {
|
||||
case 84:
|
||||
log.Println("SEV functions not supported")
|
||||
h.HostSEVInfo.SEVEnabled = false
|
||||
default:
|
||||
log.Println("Error encountered", lverr.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if h.HostSEVInfo.SEVEnabled {
|
||||
h.HostSEVInfo.PDH = util.SetNotSet(ns.PDH, ns.PDHSet)
|
||||
h.HostSEVInfo.CertChain = util.SetNotSet(ns.CertChain, ns.CertChainSet)
|
||||
h.HostSEVInfo.CBitPos = ns.CBitPos
|
||||
h.HostSEVInfo.ReducedPhysBits = ns.ReducedPhysBits
|
||||
h.HostSEVInfo.MaxGuests = ns.MaxGuests
|
||||
h.HostSEVInfo.MaxEsGuests = ns.MaxEsGuests
|
||||
h.HostSEVInfo.CPU0ID = util.SetNotSet(ns.CPU0ID, ns.CPU0IDSet)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Host) getDomainInfo() {
|
||||
log.Info("host.getDomainInfo").Str("hostname", h.HostName).Msg("collecting domain (vm) information")
|
||||
// getDomainInfo
|
||||
doms, err := h.conn.ListAllDomains(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getDomainInfo").Str("hostname", h.HostName).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if len(doms) > 0 {
|
||||
h.VMList = make([]VMInfo, len(doms))
|
||||
h.VMList = make([]*libvirtxml.Domain, len(doms))
|
||||
for i, d := range doms {
|
||||
// Just going to log errors here, and free the dom after getting what we can
|
||||
if h.VMList[i].Name, err = d.GetName(); err != nil {
|
||||
log.Println(err)
|
||||
func() {
|
||||
defer d.Free()
|
||||
rawxml, err := d.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
log.Error("Host.getDomainInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.VMList[i].UUID, err = d.GetUUID(); err != nil {
|
||||
log.Println(err)
|
||||
h.VMList[i] = &libvirtxml.Domain{}
|
||||
if err = h.VMList[i].Unmarshal(rawxml); err != nil {
|
||||
log.Error("Host.getDomainInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.VMList[i].ID, err = d.GetID(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.VMList[i].XML, err = d.GetXMLDesc(0); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
vmXML := &libvirtxml.Domain{}
|
||||
if err = vmXML.Unmarshal(h.VMList[i].XML); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
h.VMList[i].VCPUs = vmXML.VCPU.Value
|
||||
h.VMList[i].Memory = vmXML.CurrentMemory.Value
|
||||
if h.VMList[i].Active, err = d.IsActive(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
d.Free()
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Host) getIfaceInfo() {
|
||||
// getIfaceInfo
|
||||
ifaces, err := h.conn.ListInterfaces()
|
||||
ifaces, err := h.conn.ListAllInterfaces(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getIfaceInfo").Str("hostname", h.HostName).Err(err).Send()
|
||||
}
|
||||
if len(ifaces) > 0 {
|
||||
h.NetIfFList = make([]NetIfInfo, len(ifaces))
|
||||
h.NetIfFList = make([]*libvirtxml.Interface, len(ifaces))
|
||||
for i, ni := range ifaces {
|
||||
h.NetIfFList[i].Name = ni
|
||||
iface, err := h.conn.LookupInterfaceByName(ni)
|
||||
func() {
|
||||
defer ni.Free()
|
||||
rawxml, err := ni.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getIfaceInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.NetIfFList[i].MacAddr, err = iface.GetMACString(); err != nil {
|
||||
log.Println(err)
|
||||
h.NetIfFList[i] = &libvirtxml.Interface{}
|
||||
if err = h.NetIfFList[i].Unmarshal(rawxml); err != nil {
|
||||
log.Error("Host.getIfaceInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.NetIfFList[i].XML, err = iface.GetXMLDesc(0); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
iface.Free()
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Host) getNetsInfo() {
|
||||
// getNetsInfo
|
||||
nets, err := h.conn.ListNetworks()
|
||||
nets, err := h.conn.ListAllNetworks(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getNetsInfo").Str("hostname", h.HostName).Err(err).Send()
|
||||
}
|
||||
if len(nets) > 0 {
|
||||
h.NetworkList = make([]NetworkInfo, len(nets))
|
||||
for i, netName := range nets {
|
||||
net, err := h.conn.LookupNetworkByName(netName)
|
||||
h.NetworkList = make([]*libvirtxml.Network, len(nets))
|
||||
for i, net := range nets {
|
||||
func() {
|
||||
defer net.Free()
|
||||
rawxml, err := net.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getNetsInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.NetworkList[i].Name, err = net.GetName(); err != nil {
|
||||
log.Println(err)
|
||||
h.NetworkList[i] = &libvirtxml.Network{}
|
||||
if err = h.NetworkList[i].Unmarshal(rawxml); err != nil {
|
||||
log.Error("Host.getNetsInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.NetworkList[i].UUID, err = net.GetUUID(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.NetworkList[i].XML, err = net.GetXMLDesc(0); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if h.NetworkList[i].Active, err = net.IsActive(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
net.Free()
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -557,22 +390,24 @@ func (h *Host) getNetsInfo() {
|
||||
func (h *Host) getDevicesInfo() {
|
||||
ndevs, err := h.conn.ListAllNodeDevices(0)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Error("Host.getDevicesInfo").Str("hostname", h.HostName).Err(err).Send()
|
||||
}
|
||||
if len(ndevs) > 0 {
|
||||
h.DeviceList = make([]DeviceInfo, len(ndevs))
|
||||
h.DeviceList = make([]*libvirtxml.NodeDevice, len(ndevs))
|
||||
for i, dev := range ndevs {
|
||||
if h.DeviceList[i].Name, err = dev.GetName(); err != nil {
|
||||
log.Println(err)
|
||||
func() {
|
||||
defer dev.Free()
|
||||
rawxml, err := dev.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
log.Error("Host.getDevicesInfo").Str("hostname", h.HostName).Err(ErrGetXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.DeviceList[i].Capabilities, err = dev.ListCaps(); err != nil {
|
||||
log.Println(err)
|
||||
h.DeviceList[i] = &libvirtxml.NodeDevice{}
|
||||
if err = h.DeviceList[i].Unmarshal(rawxml); err != nil {
|
||||
log.Error("Host.getDevicesInfo").Str("hostname", h.HostName).Err(ErrParseXML).Err(err).Send()
|
||||
return
|
||||
}
|
||||
if h.DeviceList[i].XML, err = dev.GetXMLDesc(0); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
dev.Free()
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
)
|
||||
|
||||
// URI is a string type, accessed via the pre-defined variables, and represent
|
||||
@ -72,7 +73,12 @@ func (u *URI) ConnectionString(h string) string {
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Printf("Connection URI: %s", sb.String())
|
||||
log.Info("Host.ConnectionString").
|
||||
Str("uri.Driver", u.Driver).
|
||||
Str("uri.Transport", u.Transport).
|
||||
Str("uri.Path", u.Path).
|
||||
Strs("uri.Options", u.Options).
|
||||
Str("builtUri", sb.String()).Send()
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
|
30
lib/log/logs.go
Normal file
30
lib/log/logs.go
Normal file
@ -0,0 +1,30 @@
|
||||
// Package logs provides a central location for ClustVirt logging, wrapping a Zerolog
|
||||
// instance to do the job.
|
||||
// This will standarize logging throughout ClustVirt, and make it easier to debug
|
||||
// issues.
|
||||
// The default is to log to Stderr
|
||||
// TODO: enable logging to syslog through configuration
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var defaultLogger zerolog.Logger
|
||||
|
||||
func init() {
|
||||
defaultLogger = zerolog.New(zerolog.ConsoleWriter{
|
||||
Out: os.Stderr,
|
||||
TimeFormat: zerolog.TimeFormatUnix,
|
||||
})
|
||||
}
|
||||
|
||||
func Trace(method string) *zerolog.Event { return defaultLogger.Trace().Str("method", method) }
|
||||
func Debug(method string) *zerolog.Event { return defaultLogger.Debug().Str("method", method) }
|
||||
func Info(method string) *zerolog.Event { return defaultLogger.Info().Str("method", method) }
|
||||
func Warn(method string) *zerolog.Event { return defaultLogger.Warn().Str("method", method) }
|
||||
func Error(method string) *zerolog.Event { return defaultLogger.Error().Str("method", method) }
|
||||
func Fatal(method string) *zerolog.Event { return defaultLogger.Fatal().Str("method", method) }
|
||||
func Panic(method string) *zerolog.Event { return defaultLogger.Panic().Str("method", method) }
|
74
main.go
74
main.go
@ -1,83 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
||||
"git.staur.ca/stobbsm/clustvirt/view"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/static"
|
||||
"github.com/a-h/templ"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"git.staur.ca/stobbsm/clustvirt/router/server"
|
||||
)
|
||||
|
||||
const DEBUG bool = true
|
||||
|
||||
func main() {
|
||||
log.Println("Starting clustvirt, the libvirt cluster manager")
|
||||
log.Info("main").Msg("Starting clustvirt, the libvirt cluster manager")
|
||||
clst := cluster.New().
|
||||
AddHost("earth.staur.ca").
|
||||
AddHost("venus.staur.ca").
|
||||
AddHost("mars.staur.ca").
|
||||
Build()
|
||||
|
||||
initStats := cluster.InitStats(clst)
|
||||
// Start webserver and serve homepage
|
||||
|
||||
defaultNavBar := []components.NavItem{
|
||||
{Name: "Cluster", Href: "/"},
|
||||
{Name: "Configuration", Href: "/config"},
|
||||
{Name: "About", Href: "/about"},
|
||||
}
|
||||
fs := http.StripPrefix("/static/", http.FileServer(http.Dir("public")))
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.Logger)
|
||||
if DEBUG {
|
||||
r.Use(middleware.NoCache)
|
||||
}
|
||||
r.Get("/static/*", func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
fs.ServeHTTP(w, r)
|
||||
})
|
||||
r.Get("/", templ.Handler(view.HostMain(defaultNavBar)).ServeHTTP)
|
||||
r.Get("/cluster", func(w http.ResponseWriter, r *http.Request) {
|
||||
initStats.Update()
|
||||
log.Println(
|
||||
"Rendering clusterstats",
|
||||
view.ClusterInfo(
|
||||
initStats,
|
||||
initStats.Diff(),
|
||||
defaultNavBar,
|
||||
).Render(context.Background(), w))
|
||||
})
|
||||
r.Get("/about", templ.Handler(static.Home()).ServeHTTP)
|
||||
|
||||
r.Route("/htmx", func(r chi.Router) {
|
||||
r.Get("/host/{hostname}", func(w http.ResponseWriter, r *http.Request) {
|
||||
rhost, err := host.ConnectHost(host.URI_QEMU_SSH_SYSTEM, chi.URLParam(r, "hostname"))
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("error while getting host: %s", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rhost.Close()
|
||||
log.Println("Rendering HostInfo", view.HostInfo(rhost).Render(context.Background(), w))
|
||||
})
|
||||
r.Get("/host/{hostname}/stats", func(w http.ResponseWriter, r *http.Request) {
|
||||
rhost, err := host.ConnectHost(host.URI_QEMU_SSH_SYSTEM, chi.URLParam(r, "hostname"))
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("error while getting host: %s", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rhost.Close()
|
||||
log.Println("Rendering stats", view.SysInfo(rhost).Render(context.Background(), w))
|
||||
})
|
||||
})
|
||||
|
||||
log.Println(http.ListenAndServe(":3000", r))
|
||||
log.Info("main").Msg("starting web server")
|
||||
r := server.New("127.0.0.1", 3000, clst)
|
||||
r.Start()
|
||||
}
|
||||
|
@ -962,6 +962,10 @@ span>a:visited {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.items-end {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
@ -138643,6 +138647,10 @@ span>a:visited {
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text-2xl {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
@ -220221,6 +220229,10 @@ span>a:visited {
|
||||
--tw-ring-offset-color: rgb(51 51 30 / 0.95);
|
||||
}
|
||||
|
||||
.filter {
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
}
|
||||
|
||||
.hover\:border-uipurple-400:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(227 116 229 / var(--tw-border-opacity));
|
||||
|
3
router/api/api.go
Normal file
3
router/api/api.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package api defines the routes for the REST API
|
||||
package api
|
||||
|
6
router/errors.go
Normal file
6
router/errors.go
Normal file
@ -0,0 +1,6 @@
|
||||
package router
|
||||
|
||||
import "errors"
|
||||
|
||||
// Errors uses by the router module and it's sub modules
|
||||
var ErrMethodNotExist = errors.New("http method doesn't exist")
|
54
router/htmx/htmx.go
Normal file
54
router/htmx/htmx.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Package htmx contains the routes for the WebUI HTMX
|
||||
package htmx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"git.staur.ca/stobbsm/clustvirt/router"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type htmx struct {
|
||||
router chi.Router
|
||||
routes []router.Route
|
||||
}
|
||||
|
||||
func (h *htmx) MountTo(c *cluster.Cluster, rr chi.Router) error {
|
||||
var errs []error
|
||||
for _, r := range h.routes {
|
||||
switch r.Method {
|
||||
case http.MethodTrace:
|
||||
h.router.Trace(r.Path, r.Handler(c))
|
||||
case http.MethodOptions:
|
||||
h.router.Options(r.Path, r.Handler(c))
|
||||
case http.MethodConnect:
|
||||
h.router.Connect(r.Path, r.Handler(c))
|
||||
case http.MethodHead:
|
||||
h.router.Head(r.Path, r.Handler(c))
|
||||
case http.MethodGet:
|
||||
h.router.Get(r.Path, r.Handler(c))
|
||||
case http.MethodPost:
|
||||
h.router.Post(r.Path, r.Handler(c))
|
||||
case http.MethodPut:
|
||||
h.router.Put(r.Path, r.Handler(c))
|
||||
case http.MethodPatch:
|
||||
h.router.Patch(r.Path, r.Handler(c))
|
||||
case http.MethodDelete:
|
||||
h.router.Delete(r.Path, r.Handler(c))
|
||||
default:
|
||||
err := fmt.Errorf("method: %s: %w", r.Method, router.ErrMethodNotExist)
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
log.Info("htmx.MoutnTo").
|
||||
Str("Route.Path", r.Path).
|
||||
Str("Route.Method", r.Method).
|
||||
Msg("route registered")
|
||||
}
|
||||
rr.Mount("/htmx", h.router)
|
||||
return errors.Join(errs...)
|
||||
}
|
83
router/htmx/routes.go
Normal file
83
router/htmx/routes.go
Normal file
@ -0,0 +1,83 @@
|
||||
package htmx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"git.staur.ca/stobbsm/clustvirt/router"
|
||||
"git.staur.ca/stobbsm/clustvirt/view"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
var Htmx = &htmx{
|
||||
router: chi.NewRouter(),
|
||||
routes: []router.Route{
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/cluster",
|
||||
Handler: func(c *cluster.Cluster) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := view.ClusterInfo(c).Render(context.Background(), w); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
log.Error("htmx.Handler").
|
||||
Str("uri", r.RequestURI).
|
||||
Err(err).
|
||||
Int("statusCode", http.StatusBadRequest).Send()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/host/{hostname}",
|
||||
Handler: func(c *cluster.Cluster) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
host, err := c.GetHost(chi.URLParam(r, "hostname"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
log.Error("htmx.Handler").
|
||||
Str("uri", r.RequestURI).
|
||||
Err(err).
|
||||
Int("statusCode", http.StatusBadRequest).
|
||||
Send()
|
||||
}
|
||||
if err = view.HostInfo(host).Render(context.Background(), w); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
log.Error("htmx.Handler").
|
||||
Str("uri", r.RequestURI).
|
||||
Err(err).
|
||||
Int("statusCode", http.StatusInternalServerError).
|
||||
Send()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/host/{hostname}/stats",
|
||||
Handler: func(c *cluster.Cluster) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
host, err := c.GetHost(chi.URLParam(r, "hostname"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
log.Error("htmx.Handler").
|
||||
Str("uri", r.RequestURI).
|
||||
Err(err).
|
||||
Int("statusCode", http.StatusBadRequest).
|
||||
Send()
|
||||
}
|
||||
if err = view.HostStats(host).Render(context.Background(), w); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
log.Error("htmx.Handler").
|
||||
Str("uri", r.RequestURI).
|
||||
Err(err).
|
||||
Int("statusCode", http.StatusInternalServerError).
|
||||
Send()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
22
router/middleware/fromchi.go
Normal file
22
router/middleware/fromchi.go
Normal file
@ -0,0 +1,22 @@
|
||||
package middleware
|
||||
|
||||
import "github.com/go-chi/chi/v5/middleware"
|
||||
|
||||
// These middlewares are cloned from chi/middleware
|
||||
var (
|
||||
AllowContentEncoding = middleware.AllowContentEncoding
|
||||
AllowContentType = middleware.AllowContentType
|
||||
BasicAuth = middleware.BasicAuth
|
||||
Compress = middleware.Compress
|
||||
Heartbeat = middleware.Heartbeat
|
||||
NoCache = middleware.NoCache
|
||||
Profiler = middleware.Profiler
|
||||
RealIP = middleware.RealIP
|
||||
Recoverer = middleware.Recoverer
|
||||
RequestID = middleware.RequestID
|
||||
SetHeader = middleware.SetHeader
|
||||
Sunset = middleware.Sunset
|
||||
Throttle = middleware.Throttle
|
||||
Timeout = middleware.Timeout
|
||||
URLFormat = middleware.URLFormat
|
||||
)
|
29
router/middleware/logger.go
Normal file
29
router/middleware/logger.go
Normal file
@ -0,0 +1,29 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
)
|
||||
|
||||
// Logger uses the in package log module to handle route logging
|
||||
func Logger(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Info("router.middleware.Logger").
|
||||
Str("httpMethod", r.Method).
|
||||
Str("host", r.Host).
|
||||
Str("uri", r.URL.RequestURI()).
|
||||
Str("user_agent", r.UserAgent()).
|
||||
Str("referer", r.Referer()).
|
||||
Strs("transfer-encoding", r.TransferEncoding).
|
||||
Int64("length", r.ContentLength).
|
||||
Dur("elasped_ms", time.Since(start)).
|
||||
Msg("incoming connection")
|
||||
}()
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
28
router/router.go
Normal file
28
router/router.go
Normal file
@ -0,0 +1,28 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
// Types that are shared among routers
|
||||
|
||||
// SubRouter defines an interface to be able to add a subrouter to a
|
||||
// chi router
|
||||
type SubRouter interface {
|
||||
MountTo(*cluster.Cluster, chi.Router) error
|
||||
}
|
||||
|
||||
// Route defines a route that should be added to a chi router or
|
||||
// subrouter
|
||||
type Route struct {
|
||||
Method string
|
||||
Path string
|
||||
Handler RouteHandler
|
||||
}
|
||||
|
||||
// RouteHandler gets the active cluster for the server to inject into
|
||||
// the http.HandlerFunc that is then returned
|
||||
type RouteHandler func(*cluster.Cluster) http.HandlerFunc
|
21
router/server/root.go
Normal file
21
router/server/root.go
Normal file
@ -0,0 +1,21 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/static"
|
||||
"github.com/a-h/templ"
|
||||
)
|
||||
|
||||
// Root based routes for ClustVirt
|
||||
|
||||
func (s *Server) baseRoutes() {
|
||||
// fileserver for static content
|
||||
fs := http.StripPrefix("/static", http.FileServer(http.Dir("public")))
|
||||
s.r.Get("/static/*", fs.ServeHTTP)
|
||||
|
||||
// Root defaults to the cluster view
|
||||
s.r.Get("/", templ.Handler(layouts.Manager("ClustVirt", "libvirt made simple")).ServeHTTP)
|
||||
s.r.Get("/about", templ.Handler(static.About()).ServeHTTP)
|
||||
}
|
80
router/server/server.go
Normal file
80
router/server/server.go
Normal file
@ -0,0 +1,80 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"git.staur.ca/stobbsm/clustvirt/router"
|
||||
"git.staur.ca/stobbsm/clustvirt/router/htmx"
|
||||
"git.staur.ca/stobbsm/clustvirt/router/middleware"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
// Server represents an HTTP server that uses chi for routes
|
||||
type Server struct {
|
||||
bindAddr string
|
||||
ssl bool
|
||||
c *cluster.Cluster
|
||||
r chi.Router
|
||||
}
|
||||
|
||||
// New creates a new HTTP Server instance.
|
||||
// Requires the IP and port number to bind to
|
||||
func New(listen string, port int, cluster *cluster.Cluster) *Server {
|
||||
s := &Server{bindAddr: fmt.Sprintf("%s:%d", listen, port), c: cluster}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Start starts the server and initializes the router and common middleware
|
||||
func (s *Server) Start() {
|
||||
tstart := time.Now()
|
||||
defer func() {
|
||||
log.Info("router.Server.Start").
|
||||
Dur("upTime", time.Since(tstart)).
|
||||
Msg("http server stopped")
|
||||
}()
|
||||
s.r = chi.NewRouter()
|
||||
|
||||
indev, _ := os.LookupEnv("CLUSTVIRT_DEV")
|
||||
indev = strings.ToLower(indev)
|
||||
switch indev {
|
||||
case "true":
|
||||
fallthrough
|
||||
case "1":
|
||||
fallthrough
|
||||
case "yes":
|
||||
fallthrough
|
||||
case "on":
|
||||
s.AddMiddleware(middleware.NoCache)
|
||||
s.r.Get("/_/debug", middleware.Profiler().ServeHTTP)
|
||||
}
|
||||
// Add routes
|
||||
s.baseRoutes()
|
||||
if err := s.AddSubRouter(htmx.Htmx); err != nil {
|
||||
log.Error("server.Start").
|
||||
Str("subroute", "htmx").
|
||||
Err(err).Send()
|
||||
}
|
||||
// Start the server
|
||||
if err := http.ListenAndServe(s.bindAddr, s.r); err != nil {
|
||||
log.Error("router.Server.Start").
|
||||
Str("bindaddr", s.bindAddr).
|
||||
Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
// AddMiddleware appends middleware to the chi router
|
||||
func (s *Server) AddMiddleware(m ...func(h http.Handler) http.Handler) {
|
||||
s.r.Use(m...)
|
||||
}
|
||||
|
||||
// AddSubRouter attachs a SubRouter using it's MountTo method
|
||||
func (s *Server) AddSubRouter(sr router.SubRouter) error {
|
||||
return sr.MountTo(s.c, s.r)
|
||||
}
|
46
util/pcidb.go
Normal file
46
util/pcidb.go
Normal file
@ -0,0 +1,46 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/log"
|
||||
"github.com/jaypipes/pcidb"
|
||||
)
|
||||
|
||||
var (
|
||||
pcidbInitDone = false
|
||||
db *pcidb.PCIDB
|
||||
)
|
||||
|
||||
const (
|
||||
pcidbNOTFOUND string = `NOTFOUND`
|
||||
pcidbNODB string = `NODBFOUND`
|
||||
)
|
||||
|
||||
func initPCIDB() {
|
||||
var err error
|
||||
|
||||
// Attempt to use local sources first, fallback to network if
|
||||
// local sources aren't found
|
||||
db, err = pcidb.New()
|
||||
if err != nil {
|
||||
log.Warn("util.initPCIDB").Err(err).Msg("fallback to downloading pcidb")
|
||||
db, err = pcidb.New(pcidb.WithEnableNetworkFetch())
|
||||
if err != nil {
|
||||
log.Error("util.initPCIDB").Err(err).Msg("no more fallbacks available")
|
||||
}
|
||||
}
|
||||
pcidbInitDone = true
|
||||
}
|
||||
|
||||
func GetPCIClass(id string) string {
|
||||
if !pcidbInitDone {
|
||||
initPCIDB()
|
||||
}
|
||||
if pcidbInitDone && db == nil {
|
||||
log.Warn("util.GetPCIClass").Msg("no pcidb to do lookup")
|
||||
return pcidbNODB
|
||||
}
|
||||
if class, ok := db.Classes[id]; ok {
|
||||
return class.Name
|
||||
}
|
||||
return pcidbNOTFOUND
|
||||
}
|
@ -3,55 +3,49 @@ package view
|
||||
import (
|
||||
"fmt"
|
||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||
)
|
||||
|
||||
templ ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []components.NavItem) {
|
||||
@layouts.Manager("ClustVirt", "Cluster Manager", navbar) {
|
||||
templ ClusterInfo(c *cluster.Cluster) {
|
||||
<h3>Cluster Stats</h3>
|
||||
<table class={ "table-auto", "w-full" }>
|
||||
@ClusterStats(cluster.InitStats(c))
|
||||
}
|
||||
|
||||
templ ClusterStats(cs *cluster.ClusterStats) {
|
||||
@CPUStats(cs.CPU, cs.Diff().CPU)
|
||||
}
|
||||
|
||||
templ CPUStats(stats cluster.CPUStats, diff cluster.CPUDiff) {
|
||||
<table class={ "table-auto", "w-full", "text-right" }>
|
||||
<caption class={ "caption-top" }>
|
||||
CPU stats
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Sockets</th>
|
||||
<th>Cores</th>
|
||||
<th>Threads</th>
|
||||
<th>Allocated</th>
|
||||
<th>MHz</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
{ fmt.Sprint(cs.CPU.Sockets) }
|
||||
</td>
|
||||
<td>
|
||||
{ fmt.Sprint(cs.CPU.Cores) }
|
||||
</td>
|
||||
<td>
|
||||
{ fmt.Sprint(cs.CPU.Threads) }
|
||||
</td>
|
||||
<td>
|
||||
{ fmt.Sprint(cs.CPU.Allocated) }
|
||||
</td>
|
||||
<td>Latest</td>
|
||||
<td>{ fmt.Sprint(stats.Sockets) }</td>
|
||||
<td>{ fmt.Sprint(stats.Cores) }</td>
|
||||
<td>{ fmt.Sprint(stats.Threads) }</td>
|
||||
<td>{ fmt.Sprint(stats.Allocated) }</td>
|
||||
<td>{ fmt.Sprint(stats.MHz) }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{ fmt.Sprint(diff.CPU.Sockets) }
|
||||
</td>
|
||||
<td>
|
||||
{ fmt.Sprint(diff.CPU.Cores) }
|
||||
</td>
|
||||
<td>
|
||||
{ fmt.Sprint(diff.CPU.Threads) }
|
||||
</td>
|
||||
<td>
|
||||
{ fmt.Sprint(diff.CPU.Allocated) }
|
||||
</td>
|
||||
<td>Change</td>
|
||||
<td>{ fmt.Sprint(diff.Sockets) }</td>
|
||||
<td>{ fmt.Sprint(diff.Cores) }</td>
|
||||
<td>{ fmt.Sprint(diff.Threads) }</td>
|
||||
<td>{ fmt.Sprint(diff.Allocated) }</td>
|
||||
<td>{ fmt.Sprint(diff.MHz) }</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package view
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -13,11 +13,9 @@ import "bytes"
|
||||
import (
|
||||
"fmt"
|
||||
"git.staur.ca/stobbsm/clustvirt/cluster"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||
)
|
||||
|
||||
func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []components.NavItem) templ.Component {
|
||||
func ClusterInfo(c *cluster.Cluster) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
@ -30,18 +28,60 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h3>Cluster Stats</h3>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = ClusterStats(cluster.InitStats(c)).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func ClusterStats(cs *cluster.ClusterStats) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h3>Cluster Stats</h3>")
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = CPUStats(cs.CPU, cs.Diff().CPU).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 = []any{"table-auto", "w-full"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func CPUStats(stats cluster.CPUStats, diff cluster.CPUDiff) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var4 = []any{"table-auto", "w-full", "text-right"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -49,7 +89,12 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String()))
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -57,8 +102,8 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 = []any{"caption-top"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
||||
var templ_7745c5c3_Var6 = []any{"caption-top"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -66,70 +111,36 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">CPU stats</caption> <thead><tr><th>Sockets</th><th>Cores</th><th>Threads</th><th>Allocated</th></tr></thead> <tbody><tr><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Sockets))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 27, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Cores))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 30, Col: 33}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Threads))
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 33, Col: 35}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">CPU stats</caption> <thead><tr><th></th><th>Sockets</th><th>Cores</th><th>Threads</th><th>Allocated</th><th>MHz</th></tr></thead> <tbody><tr><td>Latest</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(cs.CPU.Allocated))
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Sockets))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 36, Col: 37}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 35, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr><tr><td>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Sockets))
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Cores))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 41, Col: 42}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 36, Col: 33}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -140,9 +151,9 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Cores))
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Threads))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 44, Col: 40}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 37, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -153,9 +164,9 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Threads))
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.Allocated))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 47, Col: 42}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 38, Col: 37}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -166,24 +177,80 @@ func ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []compo
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.CPU.Allocated))
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(stats.MHz))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 50, Col: 44}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 39, Col: 31}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr></tbody></table>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr><tr><td>Change</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Sockets))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 43, Col: 34}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layouts.Manager("ClustVirt", "Cluster Manager", navbar).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Cores))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 44, Col: 32}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Threads))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 45, Col: 34}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.Allocated))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 46, Col: 36}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(diff.MHz))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/cluster.templ`, Line: 47, Col: 30}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr></tbody></table>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -39,7 +39,7 @@ func A(href string, text string) templ.Component {
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 4, Col: 10}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 5, Col: 10}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -85,7 +85,7 @@ func ANewTab(href string, text string) templ.Component {
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 10, Col: 10}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 11, Col: 10}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -36,7 +36,12 @@ func List(listImage string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/contentlist.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -67,16 +72,16 @@ func ListItem() templ.Component {
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var4 == nil {
|
||||
templ_7745c5c3_Var4 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var3.Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var4.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
7
view/components/defaults.go
Normal file
7
view/components/defaults.go
Normal file
@ -0,0 +1,7 @@
|
||||
package components
|
||||
|
||||
var DefaultNavBar = []NavItem{
|
||||
{Name: "Cluster", Href: "/"},
|
||||
{Name: "Configuration", Href: "/config"},
|
||||
{Name: "About", Href: "/about"},
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -36,7 +36,12 @@ func FlexRow(wrap bool) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/flexrow.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
46
view/components/hostbutton.templ
Normal file
46
view/components/hostbutton.templ
Normal file
@ -0,0 +1,46 @@
|
||||
package components
|
||||
|
||||
templ HostButton(hostname string, path string) {
|
||||
<button
|
||||
hx-target="#sysContent"
|
||||
hx-get={ path }
|
||||
class={ "rounded",
|
||||
"border",
|
||||
"border-solid",
|
||||
"border-uiblue-700",
|
||||
"text-uigrey-200",
|
||||
"bg-uiblue-800",
|
||||
"hover:border-uipurple-400",
|
||||
"hover:text-ui-grey-800",
|
||||
"hover:bg-uipurple-600",
|
||||
"gap-2",
|
||||
"p-1",
|
||||
"my-1",
|
||||
"w-full",
|
||||
"flex",
|
||||
"flex-row",
|
||||
"justify-between" }
|
||||
>
|
||||
<span class={ "px-2" }>{ hostname }</span>
|
||||
<img class={ "htmx-indicator" , "inline-block" , "h-6" , "px-2" } src="/static/images/bars.svg"/>
|
||||
</button>
|
||||
}
|
||||
|
||||
templ HostNav() {
|
||||
<div id="sysNavBar" class={ "w-1/6" , "border-uigrey-600" , "border" , "rounded" , "border-dotted" , "p-2" }>
|
||||
<ul>
|
||||
<li>
|
||||
@HostButton("Cluster View", "/htmx/cluster")
|
||||
</li>
|
||||
<li>
|
||||
@HostButton("venus.staur.ca", "/htmx/host/venus.staur.ca")
|
||||
</li>
|
||||
<li>
|
||||
@HostButton("earth.staur.ca", "/htmx/host/earth.staur.ca")
|
||||
</li>
|
||||
<li>
|
||||
@HostButton("mars.staur.ca", "/htmx/host/mars.staur.ca")
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
212
view/components/hostbutton_templ.go
Normal file
212
view/components/hostbutton_templ.go
Normal file
@ -0,0 +1,212 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import "context"
|
||||
import "io"
|
||||
import "bytes"
|
||||
|
||||
func HostButton(hostname string, path string) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var2 = []any{"rounded",
|
||||
"border",
|
||||
"border-solid",
|
||||
"border-uiblue-700",
|
||||
"text-uigrey-200",
|
||||
"bg-uiblue-800",
|
||||
"hover:border-uipurple-400",
|
||||
"hover:text-ui-grey-800",
|
||||
"hover:bg-uipurple-600",
|
||||
"gap-2",
|
||||
"p-1",
|
||||
"my-1",
|
||||
"w-full",
|
||||
"flex",
|
||||
"flex-row",
|
||||
"justify-between"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button hx-target=\"#sysContent\" hx-get=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(path)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/hostbutton.templ`, Line: 6, Col: 15}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/hostbutton.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 = []any{"px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var5).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/hostbutton.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(hostname)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/hostbutton.templ`, Line: 24, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 = []any{"htmx-indicator", "inline-block", "h-6", "px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<img class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/hostbutton.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" src=\"/static/images/bars.svg\"></button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func HostNav() templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var10 == nil {
|
||||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var11 = []any{"w-1/6", "border-uigrey-600", "border", "rounded", "border-dotted", "p-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"sysNavBar\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var11).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/hostbutton.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><ul><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = HostButton("Cluster View", "/htmx/cluster").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = HostButton("venus.staur.ca", "/htmx/host/venus.staur.ca").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = HostButton("earth.staur.ca", "/htmx/host/earth.staur.ca").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = HostButton("mars.staur.ca", "/htmx/host/mars.staur.ca").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li></ul></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -48,7 +48,12 @@ func InfoBox(title string, colour string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/infobox.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -56,12 +61,12 @@ func InfoBox(title string, colour string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/infobox.templ`, Line: 20, Col: 43}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/infobox.templ`, Line: 21, Col: 43}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -38,7 +38,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -46,7 +51,7 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 = []any{"md:h-16",
|
||||
var templ_7745c5c3_Var4 = []any{"md:h-16",
|
||||
"h-28",
|
||||
"mx-auto",
|
||||
"md:px-4",
|
||||
@ -56,7 +61,7 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
"justify-between",
|
||||
"flex-wrap",
|
||||
"md:flex-nowrap"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -64,7 +69,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String()))
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -80,8 +90,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 = []any{"text-uigrey-200", "font-semibold", "md:w-auto", "md:order-2", "order-3"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
||||
var templ_7745c5c3_Var6 = []any{"text-uigrey-200", "font-semibold", "md:w-auto", "md:order-2", "order-3"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -89,7 +99,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String()))
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -97,8 +112,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 = []any{"flex", "justify-between", "sm:w-full", "md:w-auto"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||
var templ_7745c5c3_Var8 = []any{"flex", "justify-between", "sm:w-full", "md:w-auto"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -106,7 +121,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String()))
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -115,8 +135,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, ni := range navItems {
|
||||
var templ_7745c5c3_Var6 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
|
||||
var templ_7745c5c3_Var10 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -124,7 +144,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var6).String()))
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var10).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -132,8 +157,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 templ.SafeURL = templ.URL(ni.Href)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
|
||||
var templ_7745c5c3_Var12 templ.SafeURL = templ.URL(ni.Href)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -141,12 +166,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(ni.Name)
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(ni.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 31, Col: 47}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 32, Col: 47}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -159,8 +184,8 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 = []any{"order-2", "md:order-3"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
|
||||
var templ_7745c5c3_Var14 = []any{"order-2", "md:order-3"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -168,7 +193,12 @@ func NavBar(hero templ.Component, navItems []NavItem) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var9).String()))
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var14).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/navbar.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -3,8 +3,6 @@ package view
|
||||
import (
|
||||
"fmt"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||
)
|
||||
|
||||
script memchart(used uint64, free uint64, buf uint64, cache uint64) {
|
||||
@ -56,58 +54,8 @@ templ MemChart(h *host.Host) {
|
||||
h.NodeMemory.Buffers, h.NodeMemory.Cached)
|
||||
}
|
||||
|
||||
templ hostButton(hostname string) {
|
||||
<button
|
||||
hx-target="#sysContent"
|
||||
hx-get={ fmt.Sprintf("/htmx/host/%s", hostname) }
|
||||
class={ "rounded",
|
||||
"border",
|
||||
"border-solid",
|
||||
"border-uiblue-700",
|
||||
"text-uigrey-200",
|
||||
"bg-uiblue-800",
|
||||
"hover:border-uipurple-400",
|
||||
"hover:text-ui-grey-800",
|
||||
"hover:bg-uipurple-600",
|
||||
"gap-2",
|
||||
"p-1",
|
||||
"my-1",
|
||||
"w-full",
|
||||
"flex",
|
||||
"flex-row",
|
||||
"justify-between" }
|
||||
>
|
||||
<span class={ "px-2" }>{ hostname }</span>
|
||||
<img class={ "htmx-indicator" , "inline-block" , "h-6" , "px-2" } src="/static/images/bars.svg"/>
|
||||
</button>
|
||||
}
|
||||
|
||||
// HostConnect is the page that allows us to select a host to get information from
|
||||
templ HostMain(navBarItems []components.NavItem) {
|
||||
@layouts.Manager("ClustVirt", "Cluster Manager", navBarItems) {
|
||||
<div class={ "flex" , "flex-row" , "h-full" , "mt-2" }>
|
||||
<div id="sysNavBar" class={ "w-1/6" , "border-uigrey-600" , "border" , "rounded" , "border-dotted" , "p-2" }>
|
||||
<ul>
|
||||
<li>
|
||||
@hostButton("venus.staur.ca")
|
||||
</li>
|
||||
<li>
|
||||
@hostButton("earth.staur.ca")
|
||||
</li>
|
||||
<li>
|
||||
@hostButton("mars.staur.ca")
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="sysContent" class={ "w-3/4" , "px-2" }>
|
||||
<p>This is where you can see a system overview of all available hosts</p>
|
||||
<p>
|
||||
For now, there is just this simple box to choose a host to connect to
|
||||
and push the button to load the system information via HTMX
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
templ HostMain() {
|
||||
}
|
||||
|
||||
// HostInfo is meant to be an HTMX response
|
||||
@ -123,11 +71,11 @@ templ HostInfo(h *host.Host) {
|
||||
<img class={ "h-6" , "px-2" , "htmx-indicator" , "inline-block" } src="/static/images/grid.svg"/>
|
||||
</div>
|
||||
<div class={ "flex" , "flex-row" , "flex-wrap" } id="sysInfo">
|
||||
@SysInfo(h)
|
||||
@HostStats(h)
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ SysInfo(h *host.Host) {
|
||||
templ HostStats(h *host.Host) {
|
||||
@MemChart(h)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package view
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -13,8 +13,6 @@ import "bytes"
|
||||
import (
|
||||
"fmt"
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/host"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||
)
|
||||
|
||||
func memchart(used uint64, free uint64, buf uint64, cache uint64) templ.ComponentScript {
|
||||
@ -78,24 +76,12 @@ func MemChart(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 = []any{"size-40", "md:size-80"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String()))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -108,11 +94,38 @@ func MemChart(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 = []any{"size-40", "md:size-80"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<canvas id=\"memchart\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String()))
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -120,12 +133,12 @@ func MemChart(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Free/1024/1024))
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Free/1024/1024))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 48, Col: 83}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 47, Col: 83}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -133,12 +146,12 @@ func MemChart(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Cached/1024/1024))
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Cached/1024/1024))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 49, Col: 87}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 48, Col: 87}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -146,12 +159,12 @@ func MemChart(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Buffers/1024/1024))
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Buffers/1024/1024))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 50, Col: 88}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 49, Col: 88}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -159,12 +172,12 @@ func MemChart(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Total/1024/1024))
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d Gi", h.NodeMemory.Total/1024/1024))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 51, Col: 84}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 50, Col: 84}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -184,115 +197,8 @@ func MemChart(h *host.Host) templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func hostButton(hostname string) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var9 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var9 == nil {
|
||||
templ_7745c5c3_Var9 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var10 = []any{"rounded",
|
||||
"border",
|
||||
"border-solid",
|
||||
"border-uiblue-700",
|
||||
"text-uigrey-200",
|
||||
"bg-uiblue-800",
|
||||
"hover:border-uipurple-400",
|
||||
"hover:text-ui-grey-800",
|
||||
"hover:bg-uipurple-600",
|
||||
"gap-2",
|
||||
"p-1",
|
||||
"my-1",
|
||||
"w-full",
|
||||
"flex",
|
||||
"flex-row",
|
||||
"justify-between"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button hx-target=\"#sysContent\" hx-get=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(fmt.Sprintf("/htmx/host/%s", hostname)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var10).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 = []any{"px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var11).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(hostname)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 79, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 = []any{"htmx-indicator", "inline-block", "h-6", "px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var13...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<img class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var13).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" src=\"/static/images/bars.svg\"></button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
// HostConnect is the page that allows us to select a host to get information from
|
||||
func HostMain(navBarItems []components.NavItem) templ.Component {
|
||||
func HostMain() templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
@ -300,101 +206,11 @@ func HostMain(navBarItems []components.NavItem) templ.Component {
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var14 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var14 == nil {
|
||||
templ_7745c5c3_Var14 = templ.NopComponent
|
||||
templ_7745c5c3_Var12 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var12 == nil {
|
||||
templ_7745c5c3_Var12 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var15 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
var templ_7745c5c3_Var16 = []any{"flex", "flex-row", "h-full", "mt-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var16).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var17 = []any{"w-1/6", "border-uigrey-600", "border", "rounded", "border-dotted", "p-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var17...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"sysNavBar\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var17).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><ul><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = hostButton("venus.staur.ca").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = hostButton("earth.staur.ca").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = hostButton("mars.staur.ca").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li></ul></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var18 = []any{"w-3/4", "px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var18...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"sysContent\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var18).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><p>This is where you can see a system overview of all available hosts</p><p>For now, there is just this simple box to choose a host to connect to and push the button to load the system information via HTMX</p></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layouts.Manager("ClustVirt", "Cluster Manager", navBarItems).Render(templ.WithChildren(ctx, templ_7745c5c3_Var15), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
@ -411,13 +227,13 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var19 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var19 == nil {
|
||||
templ_7745c5c3_Var19 = templ.NopComponent
|
||||
templ_7745c5c3_Var13 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var13 == nil {
|
||||
templ_7745c5c3_Var13 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var20 = []any{"flex", "flex-col"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var20...)
|
||||
var templ_7745c5c3_Var14 = []any{"flex", "flex-col"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -425,7 +241,12 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var20).String()))
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var14).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -433,8 +254,8 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var21 = []any{"flex", "flex-row", "justify-start", "px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var21...)
|
||||
var templ_7745c5c3_Var16 = []any{"flex", "flex-row", "justify-start", "px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -442,7 +263,12 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var21).String()))
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var16).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -450,7 +276,12 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(fmt.Sprintf("/htmx/host/%s/stats", h.HostName)))
|
||||
var templ_7745c5c3_Var18 string
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/htmx/host/%s/stats", h.HostName))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 67, Col: 58}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -458,12 +289,12 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var22 string
|
||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(h.HostName)
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(h.HostName)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 121, Col: 19}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 70, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -471,8 +302,8 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var23 = []any{"h-6", "px-2", "htmx-indicator", "inline-block"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var23...)
|
||||
var templ_7745c5c3_Var20 = []any{"h-6", "px-2", "htmx-indicator", "inline-block"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var20...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -480,7 +311,12 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var23).String()))
|
||||
var templ_7745c5c3_Var21 string
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var20).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -488,8 +324,8 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var24 = []any{"flex", "flex-row", "flex-wrap"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var24...)
|
||||
var templ_7745c5c3_Var22 = []any{"flex", "flex-row", "flex-wrap"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var22...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -497,7 +333,12 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var24).String()))
|
||||
var templ_7745c5c3_Var23 string
|
||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var22).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/hostinfo.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -505,7 +346,7 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = SysInfo(h).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = HostStats(h).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -520,7 +361,7 @@ func HostInfo(h *host.Host) templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func SysInfo(h *host.Host) templ.Component {
|
||||
func HostStats(h *host.Host) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
@ -528,9 +369,9 @@ func SysInfo(h *host.Host) templ.Component {
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var25 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var25 == nil {
|
||||
templ_7745c5c3_Var25 = templ.NopComponent
|
||||
templ_7745c5c3_Var24 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var24 == nil {
|
||||
templ_7745c5c3_Var24 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = MemChart(h).Render(ctx, templ_7745c5c3_Buffer)
|
||||
|
@ -2,20 +2,25 @@ package layouts
|
||||
|
||||
import "git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
|
||||
templ Manager(title string, subtitle string, navBarItem []components.NavItem) {
|
||||
templ Manager(title string, subtitle string) {
|
||||
<!DOCTYPE html>
|
||||
<html class={ "text-slate-50" , "bg-slate-900" }>
|
||||
<head>
|
||||
<title>ClustVirt</title>
|
||||
<title>{ title } - { subtitle }</title>
|
||||
<link href="/static/css/style.css" type="text/css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class={ "flex" , "flex-col" , "h-screen" }>
|
||||
<header class={ "px-4" }>
|
||||
@header(title, subtitle, navBarItem)
|
||||
@header(title, subtitle, components.DefaultNavBar)
|
||||
</header>
|
||||
<main class={ "px-4" , "h-full" }>
|
||||
{ children... }
|
||||
<div class={ "flex", "flex-row", "h-full", "mt-2" }>
|
||||
@components.HostNav()
|
||||
<div id="sysContent" class={ "w-3/4" , "px-2" } >
|
||||
<img class={ "inline-block"} hx-trigger="load delay:1s" hx-target="#sysContent" hx-get="/htmx/cluster" src="/static/images/bars.svg"/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class={ "px-4" , "bottom-0", "w-full" , "justify-self-end" }>
|
||||
@footer()
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package layouts
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -12,7 +12,7 @@ import "bytes"
|
||||
|
||||
import "git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
|
||||
func Manager(title string, subtitle string, navBarItem []components.NavItem) templ.Component {
|
||||
func Manager(title string, subtitle string) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
@ -38,16 +38,47 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><head><title>ClustVirt</title><link href=\"/static/css/style.css\" type=\"text/css\" rel=\"stylesheet\"></head><body>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><head><title>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 = []any{"flex", "flex-col", "h-screen"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 9, Col: 17}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" - ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 9, Col: 32}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title><link href=\"/static/css/style.css\" type=\"text/css\" rel=\"stylesheet\"></head><body>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 = []any{"flex", "flex-col", "h-screen"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -55,7 +86,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String()))
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var6).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -63,8 +99,8 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 = []any{"px-4"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
||||
var templ_7745c5c3_Var8 = []any{"px-4"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -72,7 +108,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String()))
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -80,7 +121,7 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = header(title, subtitle, navBarItem).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = header(title, subtitle, components.DefaultNavBar).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -88,8 +129,8 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 = []any{"px-4", "h-full"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||
var templ_7745c5c3_Var10 = []any{"px-4", "h-full"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -97,7 +138,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String()))
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var10).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -105,16 +151,78 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||
var templ_7745c5c3_Var12 = []any{"flex", "flex-row", "h-full", "mt-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</main>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 = []any{"px-4", "bottom-0", "w-full", "justify-self-end"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var6...)
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var12).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = components.HostNav().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var14 = []any{"w-3/4", "px-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"sysContent\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var14).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var16 = []any{"inline-block"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<img class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var16).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-trigger=\"load delay:1s\" hx-target=\"#sysContent\" hx-get=\"/htmx/cluster\" src=\"/static/images/bars.svg\"></div></div></main>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var18 = []any{"px-4", "bottom-0", "w-full", "justify-self-end"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var18...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -122,7 +230,12 @@ func Manager(title string, subtitle string, navBarItem []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var6).String()))
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var18).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/manager.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
// templ: version: v0.2.646
|
||||
package layouts
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
@ -38,7 +38,12 @@ func StaticPage(title string, subtitle string, navBarItems []components.NavItem)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -54,8 +59,8 @@ func StaticPage(title string, subtitle string, navBarItems []components.NavItem)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 = []any{"flex", "flex-col", "gap-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||
var templ_7745c5c3_Var4 = []any{"flex", "flex-col", "gap-2"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -63,7 +68,12 @@ func StaticPage(title string, subtitle string, navBarItems []components.NavItem)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).String()))
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -102,13 +112,13 @@ func hero(title string) templ.Component {
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var4 == nil {
|
||||
templ_7745c5c3_Var4 = templ.NopComponent
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var5 = []any{"text-2xl", "font-bold", "text-uiblue-200", "md:order-1"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||
var templ_7745c5c3_Var7 = []any{"text-2xl", "font-bold", "text-uiblue-200", "md:order-1"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -116,7 +126,12 @@ func hero(title string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String()))
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var7).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -124,12 +139,12 @@ func hero(title string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 26, Col: 80}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 27, Col: 80}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -152,13 +167,13 @@ func header(title string, subtitle string, navBarItems []components.NavItem) tem
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var10 == nil {
|
||||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var8 = []any{"text-lg", "font-semibold", "italic", "h-6"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
|
||||
var templ_7745c5c3_Var11 = []any{"text-lg", "font-semibold", "italic", "h-6"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -166,7 +181,12 @@ func header(title string, subtitle string, navBarItems []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var8).String()))
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var11).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -174,12 +194,12 @@ func header(title string, subtitle string, navBarItems []components.NavItem) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 30, Col: 72}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 31, Col: 72}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -206,9 +226,9 @@ func footer() templ.Component {
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var10 == nil {
|
||||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
templ_7745c5c3_Var14 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var14 == nil {
|
||||
templ_7745c5c3_Var14 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex gap-4 md:gap-6 sm:gap-8 divide divide-solid\"><div id=\"footer_left\" class=\"flex-auto basis-1/4 md:basis-1/3 p-2\">Left</div><div id=\"footer_middle\" class=\"flex-auto basis-1/2 md:basis-1/3 p-2\">Middle</div><div id=\"footer_right\" class=\"flex-auto basis-1/4 md:basis-1/3 p-2\">Right</div></div>")
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
)
|
||||
|
||||
templ Home() {
|
||||
templ About() {
|
||||
@layouts.StaticPage("ClustVirt", "Libvirt, clustered and managed", []components.NavItem{
|
||||
{Name: "What", Href: "#"},
|
||||
{Name: "Why", Href: "#"},
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user