package bootstrap import ( "bytes" "context" "cryptic-net/garage" "fmt" "log" "path/filepath" "github.com/minio/minio-go/v7" "gopkg.in/yaml.v3" ) // Paths within garage's global bucket const ( garageGlobalBucketBootstrapHostsDirPath = "bootstrap/hosts" ) // PutGarageBoostrapHost places the .yml file for the given host into // garage so that other hosts are able to see relevant configuration for it. // // The given client should be for the global bucket. func PutGarageBoostrapHost( ctx context.Context, client garage.S3APIClient, host Host, ) error { buf := new(bytes.Buffer) if err := yaml.NewEncoder(buf).Encode(host); err != nil { log.Fatalf("yaml encoding host data: %v", err) } filePath := filepath.Join(garageGlobalBucketBootstrapHostsDirPath, host.Name+".yml") _, err := client.PutObject( ctx, garage.GlobalBucket, filePath, buf, int64(buf.Len()), minio.PutObjectOptions{}, ) if err != nil { return fmt.Errorf("writing to %q in global bucket: %w", filePath, err) } return nil } // RemoveGarageBootstrapHost removes the .yml for the given host from // garage. // // The given client should be for the global bucket. func RemoveGarageBootstrapHost( ctx context.Context, client garage.S3APIClient, hostName string, ) error { filePath := filepath.Join(garageGlobalBucketBootstrapHostsDirPath, hostName+".yml") return client.RemoveObject( ctx, garage.GlobalBucket, filePath, minio.RemoveObjectOptions{}, ) } // GetGarageBootstrapHosts loads the .yml file for all hosts stored in // garage. // // The given client should be for the global bucket. func GetGarageBootstrapHosts( ctx context.Context, client garage.S3APIClient, ) ( map[string]Host, error, ) { hosts := map[string]Host{} objInfoCh := client.ListObjects( ctx, garage.GlobalBucket, minio.ListObjectsOptions{ Prefix: garageGlobalBucketBootstrapHostsDirPath, Recursive: true, }, ) for objInfo := range objInfoCh { if objInfo.Err != nil { return nil, fmt.Errorf("listing objects: %w", objInfo.Err) } obj, err := client.GetObject( ctx, garage.GlobalBucket, objInfo.Key, minio.GetObjectOptions{}, ) if err != nil { return nil, fmt.Errorf("retrieving object %q: %w", objInfo.Key, err) } var host Host err = yaml.NewDecoder(obj).Decode(&host) obj.Close() if err != nil { return nil, fmt.Errorf("yaml decoding object %q: %w", objInfo.Key, err) } hosts[host.Name] = host } return hosts, nil }