134 lines
3.7 KiB
Go
134 lines
3.7 KiB
Go
package plan
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
|
|
"metis/pkg/config"
|
|
"metis/pkg/secrets"
|
|
)
|
|
|
|
func fetchSecrets(hostname string) *secrets.NodeSecrets {
|
|
envSecrets := nodeSecretsFromEnv()
|
|
if os.Getenv("VAULT_ADDR") == "" {
|
|
return envSecrets
|
|
}
|
|
cli := secrets.NewFromEnv()
|
|
sec, err := cli.FetchNode(context.Background(), hostname)
|
|
if err != nil {
|
|
return envSecrets
|
|
}
|
|
return mergeNodeSecrets(sec, envSecrets)
|
|
}
|
|
|
|
func nodeSecretsFromEnv() *secrets.NodeSecrets {
|
|
sec := &secrets.NodeSecrets{
|
|
SSHPassword: strings.TrimSpace(os.Getenv("METIS_NODE_SSH_PASSWORD")),
|
|
SSHPasswordHash: strings.TrimSpace(os.Getenv("METIS_NODE_SSH_PASSWORD_HASH")),
|
|
AtlasPassword: strings.TrimSpace(os.Getenv("METIS_NODE_ATLAS_PASSWORD")),
|
|
AtlasPasswordHash: strings.TrimSpace(os.Getenv("METIS_NODE_ATLAS_PASSWORD_HASH")),
|
|
RootPassword: strings.TrimSpace(os.Getenv("METIS_NODE_ROOT_PASSWORD")),
|
|
RootPasswordHash: strings.TrimSpace(os.Getenv("METIS_NODE_ROOT_PASSWORD_HASH")),
|
|
}
|
|
if sec.SSHPassword == "" && sec.SSHPasswordHash == "" && sec.AtlasPassword == "" && sec.AtlasPasswordHash == "" && sec.RootPassword == "" && sec.RootPasswordHash == "" {
|
|
return nil
|
|
}
|
|
return sec
|
|
}
|
|
|
|
func mergeNodeSecrets(base, override *secrets.NodeSecrets) *secrets.NodeSecrets {
|
|
if base == nil {
|
|
return override
|
|
}
|
|
if override == nil {
|
|
return base
|
|
}
|
|
merged := *base
|
|
merged.SSHPassword = firstNonEmptyString(override.SSHPassword, base.SSHPassword)
|
|
merged.SSHPasswordHash = firstNonEmptyString(override.SSHPasswordHash, base.SSHPasswordHash)
|
|
merged.AtlasPassword = firstNonEmptyString(override.AtlasPassword, base.AtlasPassword)
|
|
merged.AtlasPasswordHash = firstNonEmptyString(override.AtlasPasswordHash, base.AtlasPasswordHash)
|
|
merged.RootPassword = firstNonEmptyString(override.RootPassword, base.RootPassword)
|
|
merged.RootPasswordHash = firstNonEmptyString(override.RootPasswordHash, base.RootPasswordHash)
|
|
merged.K3sToken = firstNonEmptyString(override.K3sToken, base.K3sToken)
|
|
merged.CloudInit = firstNonEmptyString(override.CloudInit, base.CloudInit)
|
|
if len(base.Extra) > 0 || len(override.Extra) > 0 {
|
|
merged.Extra = map[string]string{}
|
|
for key, value := range base.Extra {
|
|
merged.Extra[key] = value
|
|
}
|
|
for key, value := range override.Extra {
|
|
merged.Extra[key] = value
|
|
}
|
|
}
|
|
return &merged
|
|
}
|
|
|
|
func applyNodeMetadataEnv(cfg *config.NodeConfig) {
|
|
if cfg == nil {
|
|
return
|
|
}
|
|
if labels := parseEnvJSONMap(os.Getenv("METIS_NODE_LABELS_JSON")); len(labels) > 0 {
|
|
if cfg.Labels == nil {
|
|
cfg.Labels = map[string]string{}
|
|
}
|
|
for key, value := range labels {
|
|
cfg.Labels[key] = value
|
|
}
|
|
cfg.K3s.Labels = cfg.Labels
|
|
}
|
|
if taints := parseEnvJSONList(os.Getenv("METIS_NODE_TAINTS_JSON")); len(taints) > 0 {
|
|
cfg.Taints = uniqueStrings(append(cfg.Taints, taints...))
|
|
cfg.K3s.Taints = append([]string{}, cfg.Taints...)
|
|
}
|
|
}
|
|
|
|
func parseEnvJSONMap(raw string) map[string]string {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
var values map[string]string
|
|
if err := json.Unmarshal([]byte(raw), &values); err != nil {
|
|
return nil
|
|
}
|
|
return values
|
|
}
|
|
|
|
func parseEnvJSONList(raw string) []string {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
var values []string
|
|
if err := json.Unmarshal([]byte(raw), &values); err != nil {
|
|
return nil
|
|
}
|
|
return values
|
|
}
|
|
|
|
func uniqueStrings(values []string) []string {
|
|
seen := map[string]struct{}{}
|
|
out := make([]string, 0, len(values))
|
|
for _, value := range values {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
continue
|
|
}
|
|
if _, ok := seen[value]; ok {
|
|
continue
|
|
}
|
|
seen[value] = struct{}{}
|
|
out = append(out, value)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
func jsonMarshalIndent(value any) ([]byte, error) {
|
|
return json.MarshalIndent(value, "", " ")
|
|
}
|