2023-02-07 20:29:19 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
|
|
|
|
"m.cluseau.fr/go/watchable"
|
|
|
|
"novit.tech/direktil/pkg/localconfig"
|
|
|
|
)
|
|
|
|
|
|
|
|
type PublicState struct {
|
2023-11-04 12:53:00 +00:00
|
|
|
ServerVersion string
|
|
|
|
UIHash string
|
|
|
|
Store struct {
|
2023-02-07 20:29:19 +00:00
|
|
|
New bool
|
|
|
|
Open bool
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var wPublicState = watchable.New[PublicState]()
|
|
|
|
|
|
|
|
type State struct {
|
|
|
|
HasConfig bool
|
|
|
|
|
2023-02-13 12:03:42 +00:00
|
|
|
Store struct {
|
|
|
|
DownloadToken string
|
2023-09-10 14:47:54 +00:00
|
|
|
KeyNames []string
|
2023-02-13 12:03:42 +00:00
|
|
|
}
|
|
|
|
|
2023-02-07 20:29:19 +00:00
|
|
|
Clusters []ClusterState
|
|
|
|
Hosts []HostState
|
|
|
|
Config *localconfig.Config
|
|
|
|
|
|
|
|
Downloads map[string]DownloadSpec
|
2024-04-15 13:32:43 +00:00
|
|
|
|
|
|
|
HostTemplates []string
|
2023-02-07 20:29:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ClusterState struct {
|
2023-02-12 10:58:26 +00:00
|
|
|
Name string
|
|
|
|
Addons bool
|
|
|
|
Passwords []string
|
|
|
|
Tokens []string
|
|
|
|
CAs []CAState
|
2023-02-07 20:29:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type HostState struct {
|
|
|
|
Name string
|
|
|
|
Cluster string
|
|
|
|
IPs []string
|
2024-04-15 13:32:43 +00:00
|
|
|
|
|
|
|
Template string `json:",omitempty"`
|
2023-02-07 20:29:19 +00:00
|
|
|
}
|
|
|
|
|
2023-02-12 10:58:26 +00:00
|
|
|
type CAState struct {
|
|
|
|
Name string
|
|
|
|
Signed []string
|
|
|
|
}
|
|
|
|
|
2023-02-07 20:29:19 +00:00
|
|
|
var wState = watchable.New[State]()
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
wState.Set(State{Downloads: map[string]DownloadSpec{}})
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateState() {
|
|
|
|
log.Print("updating state")
|
|
|
|
|
2023-09-10 14:47:54 +00:00
|
|
|
// store key names
|
|
|
|
keyNames := make([]string, 0, len(secStore.Keys))
|
|
|
|
for _, key := range secStore.Keys {
|
|
|
|
keyNames = append(keyNames, key.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// config
|
2023-02-07 20:29:19 +00:00
|
|
|
cfg, err := readConfig()
|
|
|
|
if err != nil {
|
2023-09-10 14:47:54 +00:00
|
|
|
wState.Change(func(v *State) { v.HasConfig = false; v.Config = nil; v.Store.KeyNames = keyNames })
|
2023-02-07 20:29:19 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if secStore.IsNew() || !secStore.Unlocked() {
|
2023-09-10 14:47:54 +00:00
|
|
|
wState.Change(func(v *State) { v.HasConfig = false; v.Config = nil; v.Store.KeyNames = keyNames })
|
2023-02-07 20:29:19 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove heavy data
|
|
|
|
clusters := make([]ClusterState, 0, len(cfg.Clusters))
|
|
|
|
for _, cluster := range cfg.Clusters {
|
|
|
|
c := ClusterState{
|
|
|
|
Name: cluster.Name,
|
|
|
|
Addons: len(cluster.Addons) != 0,
|
|
|
|
}
|
2023-02-12 10:58:26 +00:00
|
|
|
|
|
|
|
c.Passwords, err = clusterPasswords.Keys(c.Name + "/")
|
|
|
|
if err != nil {
|
|
|
|
log.Print("failed to read cluster passwords: ", err)
|
|
|
|
}
|
|
|
|
c.Tokens, err = clusterTokens.Keys(c.Name + "/")
|
|
|
|
if err != nil {
|
|
|
|
log.Print("failed to read cluster tokens: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
caNames, err := clusterCAs.Keys(c.Name + "/")
|
|
|
|
if err != nil {
|
|
|
|
log.Print("failed to read cluster CAs: ", err)
|
|
|
|
}
|
|
|
|
for _, caName := range caNames {
|
|
|
|
ca := CAState{Name: caName}
|
|
|
|
|
|
|
|
signedNames, err := clusterCASignedKeys.Keys(c.Name + "/" + caName + "/")
|
|
|
|
if err != nil {
|
|
|
|
log.Print("failed to read cluster CA signed keys: ", err)
|
|
|
|
}
|
|
|
|
for _, signedName := range signedNames {
|
|
|
|
ca.Signed = append(ca.Signed, signedName)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.CAs = append(c.CAs, ca)
|
|
|
|
}
|
|
|
|
|
2023-02-07 20:29:19 +00:00
|
|
|
clusters = append(clusters, c)
|
|
|
|
}
|
|
|
|
|
2024-04-15 13:32:43 +00:00
|
|
|
hfts, err := hostsFromTemplate.List("")
|
|
|
|
if err != nil {
|
|
|
|
log.Print("failed to read hosts from template: ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
hosts := make([]HostState, 0, len(cfg.Hosts)+len(hfts))
|
2023-02-07 20:29:19 +00:00
|
|
|
for _, host := range cfg.Hosts {
|
|
|
|
h := HostState{
|
|
|
|
Name: host.Name,
|
|
|
|
Cluster: host.ClusterName,
|
|
|
|
IPs: host.IPs,
|
|
|
|
}
|
2024-04-15 13:32:43 +00:00
|
|
|
hosts = append(hosts, h)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, kv := range hfts {
|
|
|
|
name, hft := kv.K, kv.V
|
|
|
|
h := HostState{
|
|
|
|
Name: name,
|
|
|
|
Cluster: hft.ClusterName(cfg),
|
|
|
|
IPs: []string{hft.IP},
|
2023-02-07 20:29:19 +00:00
|
|
|
|
2024-04-15 13:32:43 +00:00
|
|
|
Template: hft.Template,
|
|
|
|
}
|
2023-02-07 20:29:19 +00:00
|
|
|
hosts = append(hosts, h)
|
|
|
|
}
|
|
|
|
|
2024-08-17 17:13:06 +00:00
|
|
|
hostTemplates := make([]string, len(cfg.HostTemplates))
|
|
|
|
for i, ht := range cfg.HostTemplates {
|
|
|
|
hostTemplates[i] = ht.Name
|
2024-04-15 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-07 20:29:19 +00:00
|
|
|
// done
|
|
|
|
wState.Change(func(v *State) {
|
|
|
|
v.HasConfig = true
|
2023-09-10 14:47:54 +00:00
|
|
|
v.Store.KeyNames = keyNames
|
2023-02-07 20:29:19 +00:00
|
|
|
v.Clusters = clusters
|
|
|
|
v.Hosts = hosts
|
2024-04-15 13:32:43 +00:00
|
|
|
v.HostTemplates = hostTemplates
|
2023-02-07 20:29:19 +00:00
|
|
|
})
|
|
|
|
}
|