Fetch GarageClientParams from daemon

This commit is contained in:
Brian Picciano 2024-07-12 16:03:37 +02:00
parent 736b23429c
commit 30c8ca332a
7 changed files with 83 additions and 97 deletions

View File

@ -4,6 +4,24 @@ import (
"isle/garage" "isle/garage"
) )
// GarageClientParams contains all the data needed to instantiate garage
// clients.
type GarageClientParams struct {
Peer garage.RemotePeer
GlobalBucketS3APICredentials garage.S3APICredentials
RPCSecret string
}
// GlobalBucketS3APIClient returns an S3 client pre-configured with access to
// the global bucket.
func (p GarageClientParams) GlobalBucketS3APIClient() garage.S3APIClient {
var (
addr = p.Peer.S3APIAddr()
creds = p.GlobalBucketS3APICredentials
)
return garage.NewS3APIClient(addr, creds)
}
// GaragePeers returns a Peer for each known garage instance in the network. // GaragePeers returns a Peer for each known garage instance in the network.
func (b Bootstrap) GaragePeers() []garage.RemotePeer { func (b Bootstrap) GaragePeers() []garage.RemotePeer {
@ -52,10 +70,11 @@ func (b Bootstrap) ChooseGaragePeer() garage.RemotePeer {
panic("no garage instances configured") panic("no garage instances configured")
} }
// GlobalBucketS3APIClient returns an S3 client pre-configured with access to // GarageClientParams returns a GarageClientParams.
// the global bucket. func (b Bootstrap) GarageClientParams() GarageClientParams {
func (b Bootstrap) GlobalBucketS3APIClient() garage.S3APIClient { return GarageClientParams{
addr := b.ChooseGaragePeer().S3APIAddr() Peer: b.ChooseGaragePeer(),
creds := b.Garage.GlobalBucketS3APICredentials GlobalBucketS3APICredentials: b.Garage.GlobalBucketS3APICredentials,
return garage.NewS3APIClient(addr, creds) RPCSecret: b.Garage.RPCSecret,
}
} }

View File

@ -2,14 +2,9 @@ package bootstrap
import ( import (
"context" "context"
"encoding/json"
"fmt"
"isle/garage" "isle/garage"
"isle/nebula"
"path/filepath" "path/filepath"
"dev.mediocregopher.com/mediocre-go-lib.git/mctx"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
"github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7"
) )
@ -38,63 +33,3 @@ func RemoveGarageBootstrapHost(
minio.RemoveObjectOptions{}, minio.RemoveObjectOptions{},
) )
} }
// GetGarageBootstrapHosts loads the <hostname>.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[nebula.HostName]Host, error,
) {
client := b.GlobalBucketS3APIClient()
hosts := map[nebula.HostName]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
}

View File

@ -5,6 +5,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"syscall" "syscall"
"isle/bootstrap"
) )
// minio-client keeps a configuration directory which contains various pieces of // minio-client keeps a configuration directory which contains various pieces of
@ -51,19 +53,22 @@ var subCmdGarageMC = subCmd{
return fmt.Errorf("parsing flags: %w", err) return fmt.Errorf("parsing flags: %w", err)
} }
hostBootstrap, err := loadHostBootstrap() var clientParams bootstrap.GarageClientParams
err := subCmdCtx.daemonRCPClient.Call(
subCmdCtx.ctx, &clientParams, "GetGarageClientParams", nil,
)
if err != nil { if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err) return fmt.Errorf("calling GetGarageClientParams: %w", err)
} }
s3APIAddr := hostBootstrap.ChooseGaragePeer().S3APIAddr() s3APIAddr := clientParams.Peer.S3APIAddr()
if *keyID == "" { if *keyID == "" {
*keyID = hostBootstrap.Garage.GlobalBucketS3APICredentials.ID *keyID = clientParams.GlobalBucketS3APICredentials.ID
} }
if *keySecret == "" { if *keySecret == "" {
*keySecret = hostBootstrap.Garage.GlobalBucketS3APICredentials.Secret *keySecret = clientParams.GlobalBucketS3APICredentials.Secret
} }
args := flags.Args() args := flags.Args()
@ -116,9 +121,12 @@ var subCmdGarageCLI = subCmd{
checkLock: true, checkLock: true,
do: func(subCmdCtx subCmdCtx) error { do: func(subCmdCtx subCmdCtx) error {
hostBootstrap, err := loadHostBootstrap() var clientParams bootstrap.GarageClientParams
err := subCmdCtx.daemonRCPClient.Call(
subCmdCtx.ctx, &clientParams, "GetGarageClientParams", nil,
)
if err != nil { if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err) return fmt.Errorf("calling GetGarageClientParams: %w", err)
} }
var ( var (
@ -126,8 +134,8 @@ var subCmdGarageCLI = subCmd{
args = append([]string{"garage"}, subCmdCtx.args...) args = append([]string{"garage"}, subCmdCtx.args...)
cliEnv = append( cliEnv = append(
os.Environ(), os.Environ(),
"GARAGE_RPC_HOST="+hostBootstrap.ChooseGaragePeer().RPCPeerAddr(), "GARAGE_RPC_HOST="+clientParams.Peer.RPCPeerAddr(),
"GARAGE_RPC_SECRET="+hostBootstrap.Garage.RPCSecret, "GARAGE_RPC_SECRET="+clientParams.RPCSecret,
) )
) )

View File

@ -6,21 +6,9 @@ import (
"isle/bootstrap" "isle/bootstrap"
"isle/jsonutil" "isle/jsonutil"
"os" "os"
"regexp"
"sort" "sort"
) )
var hostNameRegexp = regexp.MustCompile(`^[a-z][a-z0-9\-]*$`)
func validateHostName(name string) error {
if !hostNameRegexp.MatchString(name) {
return errors.New("a host's name must start with a letter and only contain letters, numbers, and dashes")
}
return nil
}
var subCmdHostsList = subCmd{ var subCmdHostsList = subCmd{
name: "list", name: "list",
descr: "Lists all hosts in the network, and their IPs", descr: "Lists all hosts in the network, and their IPs",
@ -78,13 +66,18 @@ var subCmdHostsDelete = subCmd{
return errors.New("--hostname is required") return errors.New("--hostname is required")
} }
hostBootstrap, err := loadHostBootstrap() var clientParams bootstrap.GarageClientParams
err := subCmdCtx.daemonRCPClient.Call(
subCmdCtx.ctx, &clientParams, "GetGarageClientParams", nil,
)
if err != nil { if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err) return fmt.Errorf("calling GetGarageClientParams: %w", err)
} }
client := hostBootstrap.GlobalBucketS3APIClient() client := clientParams.GlobalBucketS3APIClient()
// TODO do this within the daemon, along with first checking if the host
// has any assigned network resources.
return bootstrap.RemoveGarageBootstrapHost(subCmdCtx.ctx, client, *hostName) return bootstrap.RemoveGarageBootstrapHost(subCmdCtx.ctx, client, *hostName)
}, },
} }

View File

@ -56,6 +56,14 @@ type Daemon interface {
map[nebula.HostName]bootstrap.Host, error, map[nebula.HostName]bootstrap.Host, error,
) )
// GetGarageClientParams returns a GarageClientParams based on the current
// network topology.
GetGarageClientParams(
ctx context.Context,
) (
bootstrap.GarageClientParams, error,
)
// Shutdown blocks until all resources held or created by the daemon, // Shutdown blocks until all resources held or created by the daemon,
// including child processes it has started, have been cleaned up. // including child processes it has started, have been cleaned up.
// //
@ -579,6 +587,20 @@ func (d *daemon) GetBootstrapHosts(
}) })
} }
func (d *daemon) GetGarageClientParams(
ctx context.Context,
) (
bootstrap.GarageClientParams, error,
) {
return withCurrBootstrap(d, func(
currBootstrap bootstrap.Bootstrap,
) (
bootstrap.GarageClientParams, error,
) {
return currBootstrap.GarageClientParams(), nil
})
}
func (d *daemon) Shutdown() error { func (d *daemon) Shutdown() error {
d.l.Lock() d.l.Lock()
defer d.l.Unlock() defer d.l.Unlock()

View File

@ -66,7 +66,7 @@ func (d *daemon) putGarageBoostrapHost(ctx context.Context) error {
var ( var (
b = d.currBootstrap b = d.currBootstrap
host = b.ThisHost() host = b.ThisHost()
client = b.GlobalBucketS3APIClient() client = b.GarageClientParams().GlobalBucketS3APIClient()
) )
configured, err := nebula.Sign( configured, err := nebula.Sign(
@ -112,7 +112,7 @@ func getGarageBootstrapHosts(
) { ) {
var ( var (
b = currBootstrap b = currBootstrap
client = b.GlobalBucketS3APIClient() client = b.GarageClientParams().GlobalBucketS3APIClient()
hosts = map[nebula.HostName]bootstrap.Host{} hosts = map[nebula.HostName]bootstrap.Host{}
objInfoCh = client.ListObjects( objInfoCh = client.ListObjects(

View File

@ -85,3 +85,12 @@ func (r *RPC) GetHosts(
return GetHostsResult{hosts}, nil return GetHostsResult{hosts}, nil
} }
// GetGarageClientParams passes through to the Daemon method of the same name.
func (r *RPC) GetGarageClientParams(
ctx context.Context, req struct{},
) (
bootstrap.GarageClientParams, error,
) {
return r.daemon.GetGarageClientParams(ctx)
}