Fetch GarageClientParams from daemon
This commit is contained in:
parent
736b23429c
commit
30c8ca332a
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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(
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user