package bootstrap import ( "errors" "fmt" "io/fs" "path/filepath" "strings" "gopkg.in/yaml.v3" ) // NebulaHost describes the contents of a `./nebula/hosts/.yml` file. type NebulaHost struct { Name string `yaml:"name"` IP string `yaml:"ip"` PublicAddr string `yaml:"public_addr,omitempty"` } // GarageHostInstance describes a single garage instance running on a host. type GarageHostInstance struct { RPCPort int `yaml:"rpc_port"` S3APIPort int `yaml:"s3_api_port"` WebPort int `yaml:"web_port"` } // GarageHost describes the contents of a `./garage/hosts/.yml` file. type GarageHost struct { Instances []GarageHostInstance `yaml:"instances"` } // Host consolidates all information about a single host from the bootstrap // file. type Host struct { Name string Nebula NebulaHost Garage *GarageHost } func loadHosts(bootstrapFS fs.FS) (map[string]Host, error) { hosts := map[string]Host{} readAsYaml := func(into interface{}, path string) error { b, err := fs.ReadFile(bootstrapFS, path) if err != nil { return fmt.Errorf("reading file from fs: %w", err) } return yaml.Unmarshal(b, into) } { globPath := filepath.Join(NebulaHostsDirPath, "*.yml") nebulaHostFiles, err := fs.Glob(bootstrapFS, globPath) if err != nil { return nil, fmt.Errorf("listing nebula host files at %q in fs: %w", globPath, err) } for _, nebulaHostPath := range nebulaHostFiles { hostName := filepath.Base(nebulaHostPath) hostName = strings.TrimSuffix(hostName, filepath.Ext(hostName)) var nebulaHost NebulaHost if err := readAsYaml(&nebulaHost, nebulaHostPath); err != nil { return nil, fmt.Errorf("reading %q as yaml: %w", nebulaHostPath, err) } hosts[hostName] = Host{ Name: hostName, Nebula: nebulaHost, } } } for hostName, host := range hosts { garageHostPath := filepath.Join(GarageHostsDirPath, hostName+".yml") var garageHost GarageHost if err := readAsYaml(&garageHost, garageHostPath); errors.Is(err, fs.ErrNotExist) { continue } else if err != nil { return nil, fmt.Errorf("reading %q as yaml: %w", garageHostPath, err) } host.Garage = &garageHost hosts[hostName] = host } return hosts, nil }