112 lines
2.4 KiB
Go
112 lines
2.4 KiB
Go
|
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 <hostname>.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 <hostname>.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 <hostname>.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
|
||
|
}
|