Use a real private key for garage instances
This commit is contained in:
parent
b26f4bdd6a
commit
711d568036
@ -12,9 +12,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 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.Peer {
|
func (b Bootstrap) GaragePeers() []garage.RemotePeer {
|
||||||
|
|
||||||
var peers []garage.Peer
|
var peers []garage.RemotePeer
|
||||||
|
|
||||||
for _, host := range b.Hosts {
|
for _, host := range b.Hosts {
|
||||||
|
|
||||||
@ -24,7 +24,8 @@ func (b Bootstrap) GaragePeers() []garage.Peer {
|
|||||||
|
|
||||||
for _, instance := range host.Garage.Instances {
|
for _, instance := range host.Garage.Instances {
|
||||||
|
|
||||||
peer := garage.Peer{
|
peer := garage.RemotePeer{
|
||||||
|
ID: instance.ID,
|
||||||
IP: host.Nebula.IP,
|
IP: host.Nebula.IP,
|
||||||
RPCPort: instance.RPCPort,
|
RPCPort: instance.RPCPort,
|
||||||
S3APIPort: instance.S3APIPort,
|
S3APIPort: instance.S3APIPort,
|
||||||
@ -50,13 +51,14 @@ func (b Bootstrap) GarageRPCPeerAddrs() []string {
|
|||||||
// ChooseGaragePeer returns a Peer for a garage instance from the network. It
|
// 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 prefer a garage instance on this particular host, if there is one, but
|
||||||
// will otherwise return a random endpoint.
|
// will otherwise return a random endpoint.
|
||||||
func (b Bootstrap) ChooseGaragePeer() garage.Peer {
|
func (b Bootstrap) ChooseGaragePeer() garage.RemotePeer {
|
||||||
|
|
||||||
thisHost := b.ThisHost()
|
thisHost := b.ThisHost()
|
||||||
|
|
||||||
if thisHost.Garage != nil && len(thisHost.Garage.Instances) > 0 {
|
if thisHost.Garage != nil && len(thisHost.Garage.Instances) > 0 {
|
||||||
inst := thisHost.Garage.Instances[0]
|
inst := thisHost.Garage.Instances[0]
|
||||||
return garage.Peer{
|
return garage.RemotePeer{
|
||||||
|
ID: inst.ID,
|
||||||
IP: thisHost.Nebula.IP,
|
IP: thisHost.Nebula.IP,
|
||||||
RPCPort: inst.RPCPort,
|
RPCPort: inst.RPCPort,
|
||||||
S3APIPort: inst.S3APIPort,
|
S3APIPort: inst.S3APIPort,
|
||||||
|
@ -22,8 +22,9 @@ type NebulaHost struct {
|
|||||||
|
|
||||||
// GarageHost describes a single garage instance in the GarageHost.
|
// GarageHost describes a single garage instance in the GarageHost.
|
||||||
type GarageHostInstance struct {
|
type GarageHostInstance struct {
|
||||||
RPCPort int `yaml:"rpc_port"`
|
ID string `yaml:"id"`
|
||||||
S3APIPort int `yaml:"s3_api_port"`
|
RPCPort int `yaml:"rpc_port"`
|
||||||
|
S3APIPort int `yaml:"s3_api_port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GarageHost describes the garage configuration of a Host which is relevant for
|
// GarageHost describes the garage configuration of a Host which is relevant for
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"cryptic-net/bootstrap"
|
"cryptic-net/bootstrap"
|
||||||
"cryptic-net/daemon"
|
"cryptic-net/daemon"
|
||||||
|
"cryptic-net/garage"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -25,7 +26,14 @@ func mergeDaemonConfigIntoBootstrap(
|
|||||||
host.Garage = new(bootstrap.GarageHost)
|
host.Garage = new(bootstrap.GarageHost)
|
||||||
|
|
||||||
for _, alloc := range allocs {
|
for _, alloc := range allocs {
|
||||||
|
|
||||||
|
id, err := garage.InitAlloc(alloc.MetaPath)
|
||||||
|
if err != nil {
|
||||||
|
return bootstrap.Bootstrap{}, fmt.Errorf("initializing alloc at %q: %w", alloc.MetaPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
host.Garage.Instances = append(host.Garage.Instances, bootstrap.GarageHostInstance{
|
host.Garage.Instances = append(host.Garage.Instances, bootstrap.GarageHostInstance{
|
||||||
|
ID: id,
|
||||||
RPCPort: alloc.RPCPort,
|
RPCPort: alloc.RPCPort,
|
||||||
S3APIPort: alloc.S3APIPort,
|
S3APIPort: alloc.S3APIPort,
|
||||||
})
|
})
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"cryptic-net/garage"
|
"cryptic-net/garage"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -66,6 +65,25 @@ func waitForGarageAndNebula(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bootstrapGarageHostForAlloc returns the bootstrap.GarageHostInstance which
|
||||||
|
// corresponds with the given alloc from the daemon config. This will panic if
|
||||||
|
// no associated instance can be found.
|
||||||
|
//
|
||||||
|
// This assumes that mergeDaemonConfigIntoBootstrap has already been called.
|
||||||
|
func bootstrapGarageHostForAlloc(
|
||||||
|
host bootstrap.Host,
|
||||||
|
alloc daemon.ConfigStorageAllocation,
|
||||||
|
) bootstrap.GarageHostInstance {
|
||||||
|
|
||||||
|
for _, inst := range host.Garage.Instances {
|
||||||
|
if inst.RPCPort == alloc.RPCPort {
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("could not find alloc %+v in the bootstrap data", alloc))
|
||||||
|
}
|
||||||
|
|
||||||
func garageWriteChildConfig(
|
func garageWriteChildConfig(
|
||||||
hostBootstrap bootstrap.Bootstrap,
|
hostBootstrap bootstrap.Bootstrap,
|
||||||
alloc daemon.ConfigStorageAllocation,
|
alloc daemon.ConfigStorageAllocation,
|
||||||
@ -73,28 +91,17 @@ func garageWriteChildConfig(
|
|||||||
string, error,
|
string, error,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if err := os.MkdirAll(alloc.MetaPath, 0750); err != nil {
|
|
||||||
return "", fmt.Errorf("making directory %q: %w", alloc.MetaPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
thisHost := hostBootstrap.ThisHost()
|
thisHost := hostBootstrap.ThisHost()
|
||||||
|
id := bootstrapGarageHostForAlloc(thisHost, alloc).ID
|
||||||
|
|
||||||
peer := garage.Peer{
|
peer := garage.LocalPeer{
|
||||||
IP: thisHost.Nebula.IP,
|
RemotePeer: garage.RemotePeer{
|
||||||
RPCPort: alloc.RPCPort,
|
ID: id,
|
||||||
S3APIPort: alloc.S3APIPort,
|
IP: thisHost.Nebula.IP,
|
||||||
}
|
RPCPort: alloc.RPCPort,
|
||||||
|
S3APIPort: alloc.S3APIPort,
|
||||||
pubKey, privKey := peer.RPCPeerKey()
|
},
|
||||||
|
AdminPort: alloc.AdminPort,
|
||||||
nodeKeyPath := filepath.Join(alloc.MetaPath, "node_key")
|
|
||||||
nodeKeyPubPath := filepath.Join(alloc.MetaPath, "node_keypub")
|
|
||||||
|
|
||||||
if err := os.WriteFile(nodeKeyPath, privKey, 0400); err != nil {
|
|
||||||
return "", fmt.Errorf("writing private key to %q: %w", nodeKeyPath, err)
|
|
||||||
|
|
||||||
} else if err := os.WriteFile(nodeKeyPubPath, pubKey, 0440); err != nil {
|
|
||||||
return "", fmt.Errorf("writing public key to %q: %w", nodeKeyPubPath, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
garageTomlPath := filepath.Join(
|
garageTomlPath := filepath.Join(
|
||||||
@ -108,9 +115,9 @@ func garageWriteChildConfig(
|
|||||||
RPCSecret: hostBootstrap.GarageRPCSecret,
|
RPCSecret: hostBootstrap.GarageRPCSecret,
|
||||||
AdminToken: hostBootstrap.GarageAdminToken,
|
AdminToken: hostBootstrap.GarageAdminToken,
|
||||||
|
|
||||||
RPCAddr: net.JoinHostPort(thisHost.Nebula.IP, strconv.Itoa(alloc.RPCPort)),
|
RPCAddr: peer.RPCAddr(),
|
||||||
APIAddr: net.JoinHostPort(thisHost.Nebula.IP, strconv.Itoa(alloc.S3APIPort)),
|
S3APIAddr: peer.S3APIAddr(),
|
||||||
AdminAddr: net.JoinHostPort(thisHost.Nebula.IP, strconv.Itoa(alloc.AdminPort)),
|
AdminAddr: peer.AdminAddr(),
|
||||||
|
|
||||||
BootstrapPeers: hostBootstrap.GarageRPCPeerAddrs(),
|
BootstrapPeers: hostBootstrap.GarageRPCPeerAddrs(),
|
||||||
})
|
})
|
||||||
@ -224,7 +231,6 @@ func garageApplyLayout(
|
|||||||
adminClient = newGarageAdminClient(hostBootstrap, daemonConfig)
|
adminClient = newGarageAdminClient(hostBootstrap, daemonConfig)
|
||||||
thisHost = hostBootstrap.ThisHost()
|
thisHost = hostBootstrap.ThisHost()
|
||||||
hostName = thisHost.Name
|
hostName = thisHost.Name
|
||||||
ip = thisHost.Nebula.IP
|
|
||||||
allocs = daemonConfig.Storage.Allocations
|
allocs = daemonConfig.Storage.Allocations
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -239,13 +245,9 @@ func garageApplyLayout(
|
|||||||
|
|
||||||
for _, alloc := range allocs {
|
for _, alloc := range allocs {
|
||||||
|
|
||||||
peer := garage.Peer{
|
id := bootstrapGarageHostForAlloc(thisHost, alloc).ID
|
||||||
IP: ip,
|
|
||||||
RPCPort: alloc.RPCPort,
|
|
||||||
S3APIPort: alloc.S3APIPort,
|
|
||||||
}
|
|
||||||
|
|
||||||
clusterLayout[peer.RPCPeerID()] = peerLayout{
|
clusterLayout[id] = peerLayout{
|
||||||
Capacity: alloc.Capacity / 100,
|
Capacity: alloc.Capacity / 100,
|
||||||
Zone: hostName,
|
Zone: hostName,
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
|
@ -2,6 +2,15 @@
|
|||||||
// setting up garage configs, processes, and deployments.
|
// setting up garage configs, processes, and deployments.
|
||||||
package garage
|
package garage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
||||||
// Region is the region which garage is configured with.
|
// Region is the region which garage is configured with.
|
||||||
@ -15,3 +24,81 @@ const (
|
|||||||
// cluster. We currently only support a factor of 3.
|
// cluster. We currently only support a factor of 3.
|
||||||
ReplicationFactor = 3
|
ReplicationFactor = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func nodeKeyPath(metaDirPath string) string {
|
||||||
|
return filepath.Join(metaDirPath, "node_key")
|
||||||
|
}
|
||||||
|
|
||||||
|
func nodeKeyPubPath(metaDirPath string) string {
|
||||||
|
return filepath.Join(metaDirPath, "node_key.pub")
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAllocID returns the peer ID (ie the public key) of the node at the given
|
||||||
|
// meta directory.
|
||||||
|
func LoadAllocID(metaDirPath string) (string, error) {
|
||||||
|
nodeKeyPubPath := nodeKeyPubPath(metaDirPath)
|
||||||
|
|
||||||
|
pubKey, err := os.ReadFile(nodeKeyPubPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("reading %q: %w", nodeKeyPubPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex.EncodeToString(pubKey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitAlloc initializes the meta directory and keys for a particular
|
||||||
|
// allocation, if it hasn't been done so already. It returns the peer ID (ie the
|
||||||
|
// public key) in any case.
|
||||||
|
func InitAlloc(metaDirPath string) (string, error) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
exists := func(path string) bool {
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
|
||||||
|
} else if _, err = os.Stat(path); errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return false
|
||||||
|
|
||||||
|
} else if err != nil {
|
||||||
|
err = fmt.Errorf("checking if %q exists: %w", path, err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeKeyPath := nodeKeyPath(metaDirPath)
|
||||||
|
nodeKeyPubPath := nodeKeyPubPath(metaDirPath)
|
||||||
|
|
||||||
|
nodeKeyPathExists := exists(nodeKeyPath)
|
||||||
|
nodeKeyPubPathExists := exists(nodeKeyPubPath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
|
||||||
|
} else if nodeKeyPubPathExists != nodeKeyPathExists {
|
||||||
|
return "", fmt.Errorf("%q or %q exist without the other existing", nodeKeyPath, nodeKeyPubPath)
|
||||||
|
|
||||||
|
} else if nodeKeyPathExists {
|
||||||
|
return LoadAllocID(metaDirPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// node key hasn't been written, write it
|
||||||
|
|
||||||
|
if err := os.MkdirAll(metaDirPath, 0750); err != nil {
|
||||||
|
return "", fmt.Errorf("making directory %q: %w", metaDirPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKey, privKey := GeneratePeerKey()
|
||||||
|
|
||||||
|
if err := os.WriteFile(nodeKeyPath, privKey, 0400); err != nil {
|
||||||
|
return "", fmt.Errorf("writing private key to %q: %w", nodeKeyPath, err)
|
||||||
|
|
||||||
|
} else if err := os.WriteFile(nodeKeyPubPath, pubKey, 0440); err != nil {
|
||||||
|
return "", fmt.Errorf("writing public key to %q: %w", nodeKeyPubPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
package garage
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
type infiniteReader struct {
|
|
||||||
b []byte
|
|
||||||
i int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewInfiniteReader returns a reader which will produce the given bytes in
|
|
||||||
// repetition. len(b) must be greater than 0.
|
|
||||||
func NewInfiniteReader(b []byte) io.Reader {
|
|
||||||
|
|
||||||
if len(b) == 0 {
|
|
||||||
panic("len(b) must be greater than 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &infiniteReader{b: b}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *infiniteReader) Read(b []byte) (int, error) {
|
|
||||||
|
|
||||||
// here, have a puzzle
|
|
||||||
|
|
||||||
var n int
|
|
||||||
|
|
||||||
for {
|
|
||||||
|
|
||||||
n += copy(b[n:], r.b[r.i:])
|
|
||||||
|
|
||||||
if r.i > 0 {
|
|
||||||
n += copy(b[n:], r.b[:r.i])
|
|
||||||
}
|
|
||||||
|
|
||||||
r.i = (r.i + n) % len(r.b)
|
|
||||||
|
|
||||||
if n >= len(b) {
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
package garage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestInfiniteReader(t *testing.T) {
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
in []byte
|
|
||||||
size int
|
|
||||||
exp []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
in: []byte("a"),
|
|
||||||
size: 1,
|
|
||||||
exp: []string{"a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("ab"),
|
|
||||||
size: 1,
|
|
||||||
exp: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("ab"),
|
|
||||||
size: 2,
|
|
||||||
exp: []string{"ab"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("ab"),
|
|
||||||
size: 3,
|
|
||||||
exp: []string{"aba", "bab"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("ab"),
|
|
||||||
size: 4,
|
|
||||||
exp: []string{"abab"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("ab"),
|
|
||||||
size: 5,
|
|
||||||
exp: []string{"ababa", "babab"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("abc"),
|
|
||||||
size: 1,
|
|
||||||
exp: []string{"a", "b", "c"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("abc"),
|
|
||||||
size: 2,
|
|
||||||
exp: []string{"ab", "ca", "bc"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("abc"),
|
|
||||||
size: 3,
|
|
||||||
exp: []string{"abc"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("abc"),
|
|
||||||
size: 4,
|
|
||||||
exp: []string{"abca", "bcab", "cabc"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []byte("abc"),
|
|
||||||
size: 5,
|
|
||||||
exp: []string{"abcab", "cabca", "bcabc"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
|
||||||
|
|
||||||
r := NewInfiniteReader(test.in)
|
|
||||||
buf := make([]byte, test.size)
|
|
||||||
|
|
||||||
assertRead := func(expBuf []byte) {
|
|
||||||
|
|
||||||
n, err := r.Read(buf)
|
|
||||||
|
|
||||||
if !bytes.Equal(buf, expBuf) {
|
|
||||||
t.Fatalf("expected bytes %q, got %q", expBuf, buf)
|
|
||||||
|
|
||||||
} else if n != len(buf) {
|
|
||||||
t.Fatalf("expected n %d, got %d", len(buf), n)
|
|
||||||
|
|
||||||
} else if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
for _, expStr := range test.exp {
|
|
||||||
assertRead([]byte(expStr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,35 +2,32 @@ package garage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"encoding/hex"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Peer describes all information necessary to connect to a given garage node.
|
// RemotePeer describes all information necessary to connect to a given garage
|
||||||
type Peer struct {
|
// node.
|
||||||
|
type RemotePeer struct {
|
||||||
|
ID string
|
||||||
IP string
|
IP string
|
||||||
RPCPort int
|
RPCPort int
|
||||||
S3APIPort int
|
S3APIPort int
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCPeerKey deterministically generates a public/private keys which can
|
// LocalPeer describes the configuration of a local garage instance.
|
||||||
// be used as a garage node key.
|
type LocalPeer struct {
|
||||||
//
|
RemotePeer
|
||||||
// DANGER: This function will deterministically produce public/private keys
|
|
||||||
// given some arbitrary input. This is NEVER what you want. It's only being used
|
|
||||||
// in cryptic-net for a very specific purpose for which I think it's ok and is
|
|
||||||
// very necessary, and people are probably _still_ going to yell at me.
|
|
||||||
//
|
|
||||||
func (p Peer) RPCPeerKey() (pubKey, privKey []byte) {
|
|
||||||
input := []byte(net.JoinHostPort(p.IP, strconv.Itoa(p.RPCPort)))
|
|
||||||
|
|
||||||
// Append the length of the input to the input, so that the input "foo"
|
AdminPort int
|
||||||
// doesn't generate the same key as the input "foofoo".
|
}
|
||||||
input = strconv.AppendInt(input, int64(len(input)), 10)
|
|
||||||
|
|
||||||
pubKey, privKey, err := ed25519.GenerateKey(NewInfiniteReader(input))
|
// GeneratePeerKey generates and returns a public/private key pair for a garage
|
||||||
|
// instance.
|
||||||
|
func GeneratePeerKey() (pubKey, privKey []byte) {
|
||||||
|
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -38,29 +35,23 @@ func (p Peer) RPCPeerKey() (pubKey, privKey []byte) {
|
|||||||
return pubKey, privKey
|
return pubKey, privKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCPeerID returns the peer ID of the garage node for use in communicating
|
|
||||||
// over RPC.
|
|
||||||
//
|
|
||||||
// DANGER: See warning on RPCPeerKey.
|
|
||||||
func (p Peer) RPCPeerID() string {
|
|
||||||
pubKey, _ := p.RPCPeerKey()
|
|
||||||
return hex.EncodeToString(pubKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RPCAddr returns the address of the peer's RPC port.
|
// RPCAddr returns the address of the peer's RPC port.
|
||||||
func (p Peer) RPCAddr() string {
|
func (p RemotePeer) RPCAddr() string {
|
||||||
return net.JoinHostPort(p.IP, strconv.Itoa(p.RPCPort))
|
return net.JoinHostPort(p.IP, strconv.Itoa(p.RPCPort))
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCPeerAddr returns the full peer address (e.g. "id@ip:port") of the garage
|
// RPCPeerAddr returns the full peer address (e.g. "id@ip:port") of the garage
|
||||||
// node for use in communicating over RPC.
|
// node for use in communicating over RPC.
|
||||||
//
|
func (p RemotePeer) RPCPeerAddr() string {
|
||||||
// DANGER: See warning on RPCPeerKey.
|
return fmt.Sprintf("%s@%s", p.ID, p.RPCAddr())
|
||||||
func (p Peer) RPCPeerAddr() string {
|
|
||||||
return fmt.Sprintf("%s@%s", p.RPCPeerID(), p.RPCAddr())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// S3APIAddr returns the address of the peer's S3 API port.
|
// S3APIAddr returns the address of the peer's S3 API port.
|
||||||
func (p Peer) S3APIAddr() string {
|
func (p RemotePeer) S3APIAddr() string {
|
||||||
return net.JoinHostPort(p.IP, strconv.Itoa(p.S3APIPort))
|
return net.JoinHostPort(p.IP, strconv.Itoa(p.S3APIPort))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdminAddr returns the address of the peer's S3 API port.
|
||||||
|
func (p LocalPeer) AdminAddr() string {
|
||||||
|
return net.JoinHostPort(p.IP, strconv.Itoa(p.AdminPort))
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@ type GarageTomlData struct {
|
|||||||
AdminToken string
|
AdminToken string
|
||||||
|
|
||||||
RPCAddr string
|
RPCAddr string
|
||||||
APIAddr string
|
S3APIAddr string
|
||||||
AdminAddr string
|
AdminAddr string
|
||||||
|
|
||||||
BootstrapPeers []string
|
BootstrapPeers []string
|
||||||
@ -39,7 +39,7 @@ bootstrap_peers = [{{- range .BootstrapPeers }}
|
|||||||
{{ end -}}]
|
{{ end -}}]
|
||||||
|
|
||||||
[s3_api]
|
[s3_api]
|
||||||
api_bind_addr = "{{ .APIAddr }}"
|
api_bind_addr = "{{ .S3APIAddr }}"
|
||||||
s3_region = "garage"
|
s3_region = "garage"
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
|
Loading…
Reference in New Issue
Block a user