package bootstrap import ( "cryptic-net/garage" "fmt" ) // Paths within the bootstrap FS related to garage. const ( garageGlobalBucketKeyYmlPath = "garage/cryptic-net-global-bucket-key.yml" garageRPCSecretPath = "garage/rpc-secret.txt" ) // GaragePeers returns a Peer for each known garage instance in the network. func (b Bootstrap) GaragePeers() []garage.Peer { var peers []garage.Peer for _, host := range b.Hosts { if host.Garage == nil { continue } for _, instance := range host.Garage.Instances { peer := garage.Peer{ IP: host.Nebula.IP, RPCPort: instance.RPCPort, S3APIPort: instance.S3APIPort, } peers = append(peers, peer) } } return peers } // GarageRPCPeerAddrs returns the full RPC peer address for each known garage // instance in the network. func (b Bootstrap) GarageRPCPeerAddrs() []string { var addrs []string for _, peer := range b.GaragePeers() { addrs = append(addrs, peer.RPCPeerAddr()) } return addrs } // ChooseGaragePeer returns a Peer for a garage instance from the network. It // will prefer a garage instance on this particular host, if there is one, but // will otherwise return a random endpoint. func (b Bootstrap) ChooseGaragePeer() garage.Peer { thisHost := b.ThisHost() if thisHost.Garage != nil && len(thisHost.Garage.Instances) > 0 { inst := thisHost.Garage.Instances[0] return garage.Peer{ IP: thisHost.Nebula.IP, RPCPort: inst.RPCPort, S3APIPort: inst.S3APIPort, } } for _, peer := range b.GaragePeers() { return peer } panic("no garage instances configured") } // GlobalBucketS3APIClient returns an S3 client pre-configured with access to // the global bucket. func (b Bootstrap) GlobalBucketS3APIClient() (garage.S3APIClient, error) { addr := b.ChooseGaragePeer().S3APIAddr() creds := b.GarageGlobalBucketS3APICredentials client, err := garage.NewS3APIClient(addr, creds) if err != nil { return nil, fmt.Errorf("connecting to garage S3 API At %q: %w", addr, err) } return client, err }