package bootstrap import ( "context" "encoding/json" "fmt" "isle/garage" "path/filepath" "github.com/mediocregopher/mediocre-go-lib/v2/mctx" "github.com/mediocregopher/mediocre-go-lib/v2/mlog" "github.com/minio/minio-go/v7" ) // Paths within garage's global bucket. // // TODO this is getting moved into daemon package. const ( garageGlobalBucketBootstrapHostsDirPath = "bootstrap/hosts" ) // RemoveGarageBootstrapHost removes the .json.signed 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+".json.signed", ) return client.RemoveObject( ctx, garage.GlobalBucket, filePath, minio.RemoveObjectOptions{}, ) } // GetGarageBootstrapHosts loads the .json.signed file for all hosts // stored in garage. // // Deprecated: should use the method off Daemon instead. func (b Bootstrap) GetGarageBootstrapHosts( ctx context.Context, logger *mlog.Logger, ) ( map[string]Host, error, ) { client := b.GlobalBucketS3APIClient() hosts := map[string]Host{} objInfoCh := client.ListObjects( ctx, garage.GlobalBucket, minio.ListObjectsOptions{ Prefix: garageGlobalBucketBootstrapHostsDirPath, Recursive: true, }, ) for objInfo := range objInfoCh { ctx := mctx.Annotate(ctx, "objectKey", objInfo.Key) 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 authedHost AuthenticatedHost err = json.NewDecoder(obj).Decode(&authedHost) obj.Close() if err != nil { logger.Warn(ctx, "object contains invalid json", err) continue } host, err := authedHost.Unwrap(b.CAPublicCredentials) if err != nil { logger.Warn(ctx, "host could not be authenticated", err) } hosts[host.Name] = host } return hosts, nil }