package main import ( "log" "m.cluseau.fr/go/watchable" "novit.tech/direktil/pkg/localconfig" ) type PublicState struct { ServerVersion string UIHash string Store struct { New bool Open bool } } var wPublicState = watchable.New[PublicState]() type State struct { HasConfig bool Store struct { DownloadToken string KeyNames []string } Clusters []ClusterState Hosts []HostState Config *localconfig.Config Downloads map[string]DownloadSpec HostTemplates []string } type ClusterState struct { Name string Addons bool Passwords []string Tokens []string CAs []CAState } type HostState struct { Name string Cluster string IPs []string Template string `json:",omitempty"` } type CAState struct { Name string Signed []string } var wState = watchable.New[State]() func init() { wState.Set(State{Downloads: map[string]DownloadSpec{}}) } func updateState() { log.Print("updating state") // store key names keyNames := make([]string, 0, len(secStore.Keys)) for _, key := range secStore.Keys { keyNames = append(keyNames, key.Name) } // config cfg, err := readConfig() if err != nil { wState.Change(func(v *State) { v.HasConfig = false; v.Config = nil; v.Store.KeyNames = keyNames }) return } if secStore.IsNew() || !secStore.Unlocked() { wState.Change(func(v *State) { v.HasConfig = false; v.Config = nil; v.Store.KeyNames = keyNames }) 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, } 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) } clusters = append(clusters, c) } 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)) for _, host := range cfg.Hosts { h := HostState{ Name: host.Name, Cluster: host.ClusterName, IPs: host.IPs, } 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}, Template: hft.Template, } hosts = append(hosts, h) } hostTemplates := make([]string, 0, len(cfg.HostTemplates)) for _, ht := range cfg.HostTemplates { hostTemplates = append(hostTemplates, ht.Name) } // done wState.Change(func(v *State) { v.HasConfig = true v.Store.KeyNames = keyNames v.Clusters = clusters v.Hosts = hosts v.HostTemplates = hostTemplates }) }