Move daemon.yml types and functionality out of entrypoint and Env
This commit is contained in:
parent
03618ba72c
commit
08f47bd514
@ -5,6 +5,7 @@ import (
|
||||
crypticnet "cryptic-net"
|
||||
"cryptic-net/admin"
|
||||
"cryptic-net/bootstrap"
|
||||
"cryptic-net/daemon"
|
||||
"cryptic-net/garage"
|
||||
"cryptic-net/nebula"
|
||||
"crypto/rand"
|
||||
@ -54,7 +55,7 @@ var subCmdAdminCreateNetwork = subCmd{
|
||||
|
||||
flags := subCmdCtx.flagSet(false)
|
||||
|
||||
daemonYmlPath := flags.StringP(
|
||||
daemonConfigPath := flags.StringP(
|
||||
"config-path", "c", "",
|
||||
"Optional path to a daemon.yml file to load configuration from.",
|
||||
)
|
||||
@ -86,7 +87,7 @@ var subCmdAdminCreateNetwork = subCmd{
|
||||
env := subCmdCtx.env
|
||||
|
||||
if *dumpConfig {
|
||||
return writeBuiltinDaemonYml(env, os.Stdout)
|
||||
return daemon.CopyDefaultConfig(os.Stdout, env.AppDirPath)
|
||||
}
|
||||
|
||||
if *domain == "" || *subnetStr == "" || *hostName == "" {
|
||||
@ -128,14 +129,13 @@ var subCmdAdminCreateNetwork = subCmd{
|
||||
}()
|
||||
}
|
||||
|
||||
if err := writeMergedDaemonYml(env, *daemonYmlPath); err != nil {
|
||||
return fmt.Errorf("merging and writing daemon.yml file: %w", err)
|
||||
daemonConfig, err := daemon.LoadConfig(env.AppDirPath, *daemonConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading daemon config: %w", err)
|
||||
}
|
||||
|
||||
daemon := env.ThisDaemon()
|
||||
|
||||
if len(daemon.Storage.Allocations) < 3 {
|
||||
return fmt.Errorf("daemon.yml with at least 3 allocations was not provided")
|
||||
if len(daemonConfig.Storage.Allocations) < 3 {
|
||||
return fmt.Errorf("daemon config with at least 3 allocations was not provided")
|
||||
}
|
||||
|
||||
nebulaCACert, err := nebula.NewCACert(*domain, subnet)
|
||||
@ -165,16 +165,16 @@ var subCmdAdminCreateNetwork = subCmd{
|
||||
GarageGlobalBucketS3APICredentials: garage.NewS3APICredentials(),
|
||||
}
|
||||
|
||||
if env, err = mergeDaemonIntoBootstrap(env); err != nil {
|
||||
return fmt.Errorf("merging daemon.yml into bootstrap data: %w", err)
|
||||
if env, err = mergeDaemonConfigIntoBootstrap(env, daemonConfig); err != nil {
|
||||
return fmt.Errorf("merging daemon config into bootstrap data: %w", err)
|
||||
}
|
||||
|
||||
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(env)
|
||||
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(env, daemonConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating nebula config: %w", err)
|
||||
}
|
||||
|
||||
garagePmuxProcConfigs, err := garagePmuxProcConfigs(env)
|
||||
garagePmuxProcConfigs, err := garagePmuxProcConfigs(env, daemonConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generating garage configs: %w", err)
|
||||
}
|
||||
@ -206,17 +206,17 @@ var subCmdAdminCreateNetwork = subCmd{
|
||||
}()
|
||||
|
||||
fmt.Fprintln(os.Stderr, "waiting for garage instances to come online")
|
||||
if err := waitForGarageAndNebula(ctx, env); err != nil {
|
||||
if err := waitForGarageAndNebula(ctx, env, daemonConfig); err != nil {
|
||||
return fmt.Errorf("waiting for garage to start up: %w", err)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "applying initial garage layout")
|
||||
if err := garageApplyLayout(ctx, env); err != nil {
|
||||
if err := garageApplyLayout(ctx, env, daemonConfig); err != nil {
|
||||
return fmt.Errorf("applying initial garage layout: %w", err)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "initializing garage shared global bucket")
|
||||
err = garageInitializeGlobalBucket(ctx, env)
|
||||
err = garageInitializeGlobalBucket(ctx, env, daemonConfig)
|
||||
|
||||
if cErr := (garage.AdminClientError{}); errors.As(err, &cErr) && cErr.StatusCode == 409 {
|
||||
return fmt.Errorf("shared global bucket has already been created, are the storage allocations from a previously initialized cryptic-net being used?")
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
|
||||
crypticnet "cryptic-net"
|
||||
"cryptic-net/bootstrap"
|
||||
"cryptic-net/daemon"
|
||||
"cryptic-net/garage"
|
||||
|
||||
"code.betamike.com/cryptic-io/pmux/pmuxlib"
|
||||
@ -25,11 +26,8 @@ import (
|
||||
// * Creates the data directory and copies the appdir bootstrap file into there,
|
||||
// if it's not already there.
|
||||
//
|
||||
// * Merges the user-provided daemon.yml file with the default, and writes the
|
||||
// result to the runtime dir.
|
||||
//
|
||||
// * Merges daemon.yml configuration into the bootstrap configuration, and
|
||||
// rewrites the bootstrap file.
|
||||
// * Merges daemon configuration into the bootstrap configuration, and rewrites
|
||||
// the bootstrap file.
|
||||
//
|
||||
// * Sets up environment variables that all other sub-processes then use, based
|
||||
// on the runtime dir.
|
||||
@ -78,10 +76,13 @@ func reloadBootstrap(env crypticnet.Env, s3Client garage.S3APIClient) (crypticne
|
||||
// been canceled or bootstrap info has been changed. This will always block
|
||||
// until the spawned pmux has returned, and returns a copy of Env with updated
|
||||
// boostrap info.
|
||||
func runDaemonPmuxOnce(env crypticnet.Env) (crypticnet.Env, error) {
|
||||
func runDaemonPmuxOnce(
|
||||
env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) (
|
||||
crypticnet.Env, error,
|
||||
) {
|
||||
|
||||
thisHost := env.Bootstrap.ThisHost()
|
||||
thisDaemon := env.ThisDaemon()
|
||||
fmt.Fprintf(os.Stderr, "host name is %q, ip is %q\n", thisHost.Name, thisHost.Nebula.IP)
|
||||
|
||||
// create s3Client anew on every loop, in case the topology has
|
||||
@ -89,33 +90,31 @@ func runDaemonPmuxOnce(env crypticnet.Env) (crypticnet.Env, error) {
|
||||
// endpoint.
|
||||
s3Client := env.Bootstrap.GlobalBucketS3APIClient()
|
||||
|
||||
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(env)
|
||||
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(env, daemonConfig)
|
||||
if err != nil {
|
||||
return crypticnet.Env{}, fmt.Errorf("generating nebula config: %w", err)
|
||||
}
|
||||
|
||||
dnsmasqPmuxProcConfig, err := dnsmasqPmuxProcConfig(env)
|
||||
dnsmasqPmuxProcConfig, err := dnsmasqPmuxProcConfig(env, daemonConfig)
|
||||
if err != nil {
|
||||
return crypticnet.Env{}, fmt.Errorf("generating dnsmasq config: %w", err)
|
||||
}
|
||||
|
||||
pmuxProcConfigs := []pmuxlib.ProcessConfig{
|
||||
nebulaPmuxProcConfig,
|
||||
dnsmasqPmuxProcConfig,
|
||||
garagePmuxProcConfigs, err := garagePmuxProcConfigs(env, daemonConfig)
|
||||
if err != nil {
|
||||
return crypticnet.Env{}, fmt.Errorf("generating garage children configs: %w", err)
|
||||
}
|
||||
|
||||
if len(thisDaemon.Storage.Allocations) > 0 {
|
||||
|
||||
garagePmuxProcConfigs, err := garagePmuxProcConfigs(env)
|
||||
if err != nil {
|
||||
return crypticnet.Env{}, fmt.Errorf("generating garage children configs: %w", err)
|
||||
}
|
||||
|
||||
pmuxProcConfigs = append(pmuxProcConfigs, garagePmuxProcConfigs...)
|
||||
pmuxConfig := pmuxlib.Config{
|
||||
Processes: append(
|
||||
[]pmuxlib.ProcessConfig{
|
||||
nebulaPmuxProcConfig,
|
||||
dnsmasqPmuxProcConfig,
|
||||
},
|
||||
garagePmuxProcConfigs...,
|
||||
),
|
||||
}
|
||||
|
||||
pmuxConfig := pmuxlib.Config{Processes: pmuxProcConfigs}
|
||||
|
||||
doneCh := env.Context.Done()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
@ -134,7 +133,7 @@ func runDaemonPmuxOnce(env crypticnet.Env) (crypticnet.Env, error) {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := waitForGarageAndNebula(ctx, env); err != nil {
|
||||
if err := waitForGarageAndNebula(ctx, env, daemonConfig); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "aborted waiting for garage instances to be accessible: %v\n", err)
|
||||
return
|
||||
}
|
||||
@ -151,19 +150,19 @@ func runDaemonPmuxOnce(env crypticnet.Env) (crypticnet.Env, error) {
|
||||
}
|
||||
}()
|
||||
|
||||
if len(thisDaemon.Storage.Allocations) > 0 {
|
||||
if len(daemonConfig.Storage.Allocations) > 0 {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := waitForGarageAndNebula(ctx, env); err != nil {
|
||||
if err := waitForGarageAndNebula(ctx, env, daemonConfig); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "aborted waiting for garage instances to be accessible: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
err := doOnce(ctx, func(ctx context.Context) error {
|
||||
fmt.Fprintln(os.Stderr, "applying garage layout")
|
||||
return garageApplyLayout(ctx, env)
|
||||
return garageApplyLayout(ctx, env, daemonConfig)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
@ -208,7 +207,7 @@ var subCmdDaemon = subCmd{
|
||||
|
||||
flags := subCmdCtx.flagSet(false)
|
||||
|
||||
daemonYmlPath := flags.StringP(
|
||||
daemonConfigPath := flags.StringP(
|
||||
"config-path", "c", "",
|
||||
"Optional path to a daemon.yml file to load configuration from.",
|
||||
)
|
||||
@ -230,7 +229,7 @@ var subCmdDaemon = subCmd{
|
||||
env := subCmdCtx.env
|
||||
|
||||
if *dumpConfig {
|
||||
return writeBuiltinDaemonYml(env, os.Stdout)
|
||||
return daemon.CopyDefaultConfig(os.Stdout, env.AppDirPath)
|
||||
}
|
||||
|
||||
runtimeDirPath := env.RuntimeDirPath
|
||||
@ -285,24 +284,25 @@ var subCmdDaemon = subCmd{
|
||||
}
|
||||
}
|
||||
|
||||
if err := writeMergedDaemonYml(env, *daemonYmlPath); err != nil {
|
||||
return fmt.Errorf("merging and writing daemon.yml file: %w", err)
|
||||
daemonConfig, err := daemon.LoadConfig(env.AppDirPath, *daemonConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading daemon config: %w", err)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
// we update this Host's data using whatever configuration has been
|
||||
// provided by daemon.yml. This way the daemon has the most
|
||||
// up-to-date possible bootstrap. This updated bootstrap will later
|
||||
// get updated in garage using update-global-bucket, so other hosts
|
||||
// will see it as well.
|
||||
if env, err = mergeDaemonIntoBootstrap(env); err != nil {
|
||||
return fmt.Errorf("merging daemon.yml into bootstrap data: %w", err)
|
||||
// provided by the daemon config. This way the daemon has the most
|
||||
// up-to-date possible bootstrap. This updated bootstrap will later get
|
||||
// updated in garage using bootstrap.PutGarageBoostrapHost, so other
|
||||
// hosts will see it as well.
|
||||
if env, err = mergeDaemonConfigIntoBootstrap(env, daemonConfig); err != nil {
|
||||
return fmt.Errorf("merging daemon config into bootstrap data: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
if env, err = runDaemonPmuxOnce(env); errors.Is(err, context.Canceled) {
|
||||
env, err = runDaemonPmuxOnce(env, daemonConfig)
|
||||
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return nil
|
||||
|
||||
} else if err != nil {
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
crypticnet "cryptic-net"
|
||||
"cryptic-net/bootstrap"
|
||||
"cryptic-net/daemon"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -36,15 +37,18 @@ func copyBootstrapToDataDirAndReload(env crypticnet.Env, r io.Reader) (crypticne
|
||||
return env.LoadBootstrap(path)
|
||||
}
|
||||
|
||||
func mergeDaemonIntoBootstrap(env crypticnet.Env) (crypticnet.Env, error) {
|
||||
daemon := env.ThisDaemon()
|
||||
func mergeDaemonConfigIntoBootstrap(
|
||||
env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) (
|
||||
crypticnet.Env, error,
|
||||
) {
|
||||
host := env.Bootstrap.ThisHost()
|
||||
|
||||
host.Nebula.PublicAddr = daemon.VPN.PublicAddr
|
||||
host.Nebula.PublicAddr = daemonConfig.VPN.PublicAddr
|
||||
|
||||
host.Garage = nil
|
||||
|
||||
if allocs := daemon.Storage.Allocations; len(allocs) > 0 {
|
||||
if allocs := daemonConfig.Storage.Allocations; len(allocs) > 0 {
|
||||
|
||||
host.Garage = new(bootstrap.GarageHost)
|
||||
|
||||
|
@ -1,72 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
crypticnet "cryptic-net"
|
||||
"cryptic-net/yamlutil"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/imdario/mergo"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func builtinDaemonYmlPath(env crypticnet.Env) string {
|
||||
return filepath.Join(env.AppDirPath, "etc", "daemon.yml")
|
||||
}
|
||||
|
||||
func writeBuiltinDaemonYml(env crypticnet.Env, w io.Writer) error {
|
||||
|
||||
builtinDaemonYmlPath := builtinDaemonYmlPath(env)
|
||||
|
||||
builtinDaemonYml, err := os.ReadFile(builtinDaemonYmlPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading default daemon.yml at %q: %w", builtinDaemonYmlPath, err)
|
||||
}
|
||||
|
||||
if _, err := w.Write(builtinDaemonYml); err != nil {
|
||||
return fmt.Errorf("writing default daemon.yml: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeMergedDaemonYml(env crypticnet.Env, userDaemonYmlPath string) error {
|
||||
|
||||
builtinDaemonYmlPath := builtinDaemonYmlPath(env)
|
||||
|
||||
var fullDaemonYml map[string]interface{}
|
||||
|
||||
if err := yamlutil.LoadYamlFile(&fullDaemonYml, builtinDaemonYmlPath); err != nil {
|
||||
return fmt.Errorf("parsing builtin daemon.yml file: %w", err)
|
||||
}
|
||||
|
||||
if userDaemonYmlPath != "" {
|
||||
|
||||
var daemonYml map[string]interface{}
|
||||
if err := yamlutil.LoadYamlFile(&daemonYml, userDaemonYmlPath); err != nil {
|
||||
return fmt.Errorf("parsing %q: %w", userDaemonYmlPath, err)
|
||||
}
|
||||
|
||||
err := mergo.Merge(&fullDaemonYml, daemonYml, mergo.WithOverride)
|
||||
if err != nil {
|
||||
return fmt.Errorf("merging contents of file %q: %w", userDaemonYmlPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
fullDaemonYmlB, err := yaml.Marshal(fullDaemonYml)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("yaml marshaling daemon config: %w", err)
|
||||
}
|
||||
|
||||
daemonYmlPath := filepath.Join(env.RuntimeDirPath, "daemon.yml")
|
||||
|
||||
if err := ioutil.WriteFile(daemonYmlPath, fullDaemonYmlB, 0400); err != nil {
|
||||
return fmt.Errorf("writing daemon.yml file to %q: %w", daemonYmlPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
crypticnet "cryptic-net"
|
||||
"cryptic-net/bootstrap"
|
||||
"cryptic-net/daemon"
|
||||
"cryptic-net/dnsmasq"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
@ -11,9 +12,11 @@ import (
|
||||
"code.betamike.com/cryptic-io/pmux/pmuxlib"
|
||||
)
|
||||
|
||||
func dnsmasqPmuxProcConfig(env crypticnet.Env) (pmuxlib.ProcessConfig, error) {
|
||||
|
||||
thisDaemon := env.ThisDaemon()
|
||||
func dnsmasqPmuxProcConfig(
|
||||
env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) (
|
||||
pmuxlib.ProcessConfig, error,
|
||||
) {
|
||||
|
||||
confPath := filepath.Join(env.RuntimeDirPath, "dnsmasq.conf")
|
||||
|
||||
@ -27,7 +30,7 @@ func dnsmasqPmuxProcConfig(env crypticnet.Env) (pmuxlib.ProcessConfig, error) {
|
||||
})
|
||||
|
||||
confData := dnsmasq.ConfData{
|
||||
Resolvers: thisDaemon.DNS.Resolvers,
|
||||
Resolvers: daemonConfig.DNS.Resolvers,
|
||||
Domain: env.Bootstrap.AdminCreationParams.Domain,
|
||||
IP: env.Bootstrap.ThisHost().Nebula.IP,
|
||||
Hosts: hostsSlice,
|
||||
|
@ -52,7 +52,7 @@ var subCmdGarageMC = subCmd{
|
||||
args = append([]string{"mc"}, args...)
|
||||
|
||||
var (
|
||||
binPath = env.BinPath("mc")
|
||||
binPath = "mc"
|
||||
cliEnv = append(
|
||||
os.Environ(),
|
||||
fmt.Sprintf(
|
||||
@ -86,7 +86,7 @@ var subCmdGarageCLI = subCmd{
|
||||
env := subCmdCtx.env
|
||||
|
||||
var (
|
||||
binPath = env.BinPath("garage")
|
||||
binPath = "garage"
|
||||
args = append([]string{"garage"}, subCmdCtx.args...)
|
||||
cliEnv = append(
|
||||
os.Environ(),
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
crypticnet "cryptic-net"
|
||||
"cryptic-net/daemon"
|
||||
"cryptic-net/garage"
|
||||
"fmt"
|
||||
"net"
|
||||
@ -13,9 +14,28 @@ import (
|
||||
"code.betamike.com/cryptic-io/pmux/pmuxlib"
|
||||
)
|
||||
|
||||
func waitForGarageAndNebula(ctx context.Context, env crypticnet.Env) error {
|
||||
// newGarageAdminClient will return an AdminClient for a local garage instance,
|
||||
// or it will _panic_ if there is no local instance configured.
|
||||
func newGarageAdminClient(
|
||||
env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) *garage.AdminClient {
|
||||
|
||||
allocs := env.ThisDaemon().Storage.Allocations
|
||||
thisHost := env.Bootstrap.ThisHost()
|
||||
|
||||
return garage.NewAdminClient(
|
||||
net.JoinHostPort(
|
||||
thisHost.Nebula.IP,
|
||||
strconv.Itoa(daemonConfig.Storage.Allocations[0].AdminPort),
|
||||
),
|
||||
env.Bootstrap.GarageAdminToken,
|
||||
)
|
||||
}
|
||||
|
||||
func waitForGarageAndNebula(
|
||||
ctx context.Context, env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) error {
|
||||
|
||||
allocs := daemonConfig.Storage.Allocations
|
||||
|
||||
// if this host doesn't have any allocations specified then fall back to
|
||||
// waiting for nebula
|
||||
@ -44,9 +64,9 @@ func waitForGarageAndNebula(ctx context.Context, env crypticnet.Env) error {
|
||||
|
||||
}
|
||||
|
||||
func garageWriteChildConf(
|
||||
func garageWriteChildConfig(
|
||||
env crypticnet.Env,
|
||||
alloc crypticnet.DaemonYmlStorageAllocation,
|
||||
alloc daemon.ConfigStorageAllocation,
|
||||
) (
|
||||
string, error,
|
||||
) {
|
||||
@ -100,13 +120,17 @@ func garageWriteChildConf(
|
||||
return garageTomlPath, nil
|
||||
}
|
||||
|
||||
func garagePmuxProcConfigs(env crypticnet.Env) ([]pmuxlib.ProcessConfig, error) {
|
||||
func garagePmuxProcConfigs(
|
||||
env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) (
|
||||
[]pmuxlib.ProcessConfig, error,
|
||||
) {
|
||||
|
||||
var pmuxProcConfigs []pmuxlib.ProcessConfig
|
||||
|
||||
for _, alloc := range env.ThisDaemon().Storage.Allocations {
|
||||
for _, alloc := range daemonConfig.Storage.Allocations {
|
||||
|
||||
childConfPath, err := garageWriteChildConf(env, alloc)
|
||||
childConfigPath, err := garageWriteChildConfig(env, alloc)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("writing child config file for alloc %+v: %w", alloc, err)
|
||||
@ -115,7 +139,7 @@ func garagePmuxProcConfigs(env crypticnet.Env) ([]pmuxlib.ProcessConfig, error)
|
||||
pmuxProcConfigs = append(pmuxProcConfigs, pmuxlib.ProcessConfig{
|
||||
Name: fmt.Sprintf("garage-%d", alloc.RPCPort),
|
||||
Cmd: "garage",
|
||||
Args: []string{"-c", childConfPath, "server"},
|
||||
Args: []string{"-c", childConfigPath, "server"},
|
||||
StartAfterFunc: func(ctx context.Context) error {
|
||||
return waitForNebula(ctx, env)
|
||||
},
|
||||
@ -125,10 +149,12 @@ func garagePmuxProcConfigs(env crypticnet.Env) ([]pmuxlib.ProcessConfig, error)
|
||||
return pmuxProcConfigs, nil
|
||||
}
|
||||
|
||||
func garageInitializeGlobalBucket(ctx context.Context, env crypticnet.Env) error {
|
||||
func garageInitializeGlobalBucket(
|
||||
ctx context.Context, env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) error {
|
||||
|
||||
var (
|
||||
adminClient = env.GarageAdminClient()
|
||||
adminClient = newGarageAdminClient(env, daemonConfig)
|
||||
globalBucketCreds = env.Bootstrap.GarageGlobalBucketS3APICredentials
|
||||
)
|
||||
|
||||
@ -183,14 +209,16 @@ func garageInitializeGlobalBucket(ctx context.Context, env crypticnet.Env) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func garageApplyLayout(ctx context.Context, env crypticnet.Env) error {
|
||||
func garageApplyLayout(
|
||||
ctx context.Context, env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) error {
|
||||
|
||||
var (
|
||||
adminClient = env.GarageAdminClient()
|
||||
adminClient = newGarageAdminClient(env, daemonConfig)
|
||||
thisHost = env.Bootstrap.ThisHost()
|
||||
hostName = thisHost.Name
|
||||
ip = thisHost.Nebula.IP
|
||||
allocs = env.ThisDaemon().Storage.Allocations
|
||||
allocs = daemonConfig.Storage.Allocations
|
||||
)
|
||||
|
||||
type peerLayout struct {
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
crypticnet "cryptic-net"
|
||||
"cryptic-net/daemon"
|
||||
"cryptic-net/yamlutil"
|
||||
"fmt"
|
||||
"net"
|
||||
@ -33,9 +34,11 @@ func waitForNebula(ctx context.Context, env crypticnet.Env) error {
|
||||
})
|
||||
}
|
||||
|
||||
func nebulaPmuxProcConfig(env crypticnet.Env) (pmuxlib.ProcessConfig, error) {
|
||||
|
||||
thisDaemon := env.ThisDaemon()
|
||||
func nebulaPmuxProcConfig(
|
||||
env crypticnet.Env, daemonConfig daemon.Config,
|
||||
) (
|
||||
pmuxlib.ProcessConfig, error,
|
||||
) {
|
||||
|
||||
var (
|
||||
lighthouseHostIPs []string
|
||||
@ -66,10 +69,10 @@ func nebulaPmuxProcConfig(env crypticnet.Env) (pmuxlib.ProcessConfig, error) {
|
||||
"tun": map[string]interface{}{
|
||||
"dev": "cryptic-net-nebula",
|
||||
},
|
||||
"firewall": thisDaemon.VPN.Firewall,
|
||||
"firewall": daemonConfig.VPN.Firewall,
|
||||
}
|
||||
|
||||
if publicAddr := env.ThisDaemon().VPN.PublicAddr; publicAddr == "" {
|
||||
if publicAddr := daemonConfig.VPN.PublicAddr; publicAddr == "" {
|
||||
|
||||
config["listen"] = map[string]string{
|
||||
"host": "0.0.0.0",
|
||||
|
@ -1,4 +1,4 @@
|
||||
package crypticnet
|
||||
package daemon
|
||||
|
||||
import "strconv"
|
||||
|
||||
@ -27,9 +27,9 @@ type ConfigFirewallRule struct {
|
||||
CAName string `yaml:"ca_name,omitempty"`
|
||||
}
|
||||
|
||||
// DaemonYmlStorageAllocation describes the structure of each storage allocation
|
||||
// within the daemon.yml file.
|
||||
type DaemonYmlStorageAllocation struct {
|
||||
// ConfigStorageAllocation describes the structure of each storage allocation
|
||||
// within the daemon config file.
|
||||
type ConfigStorageAllocation struct {
|
||||
DataPath string `yaml:"data_path"`
|
||||
MetaPath string `yaml:"meta_path"`
|
||||
Capacity int `yaml:"capacity"`
|
||||
@ -38,8 +38,8 @@ type DaemonYmlStorageAllocation struct {
|
||||
AdminPort int `yaml:"admin_port"`
|
||||
}
|
||||
|
||||
// DaemonYml describes the structure of the daemon.yml file.
|
||||
type DaemonYml struct {
|
||||
// Config describes the structure of the daemon config file.
|
||||
type Config struct {
|
||||
DNS struct {
|
||||
Resolvers []string `yaml:"resolvers"`
|
||||
} `yaml:"dns"`
|
||||
@ -48,30 +48,29 @@ type DaemonYml struct {
|
||||
Firewall ConfigFirewall `yaml:"firewall"`
|
||||
} `yaml:"vpn"`
|
||||
Storage struct {
|
||||
Allocations []DaemonYmlStorageAllocation
|
||||
Allocations []ConfigStorageAllocation
|
||||
} `yaml:"storage"`
|
||||
}
|
||||
|
||||
// FillDefaults fills in default values in the DaemonYml.
|
||||
func (d *DaemonYml) FillDefaults() {
|
||||
func (c *Config) fillDefaults() {
|
||||
|
||||
var firewallGarageInbound []ConfigFirewallRule
|
||||
|
||||
for i := range d.Storage.Allocations {
|
||||
for i := range c.Storage.Allocations {
|
||||
|
||||
if d.Storage.Allocations[i].RPCPort == 0 {
|
||||
d.Storage.Allocations[i].RPCPort = 3900 + (i * 10)
|
||||
if c.Storage.Allocations[i].RPCPort == 0 {
|
||||
c.Storage.Allocations[i].RPCPort = 3900 + (i * 10)
|
||||
}
|
||||
|
||||
if d.Storage.Allocations[i].S3APIPort == 0 {
|
||||
d.Storage.Allocations[i].S3APIPort = 3901 + (i * 10)
|
||||
if c.Storage.Allocations[i].S3APIPort == 0 {
|
||||
c.Storage.Allocations[i].S3APIPort = 3901 + (i * 10)
|
||||
}
|
||||
|
||||
if d.Storage.Allocations[i].AdminPort == 0 {
|
||||
d.Storage.Allocations[i].AdminPort = 3902 + (i * 10)
|
||||
if c.Storage.Allocations[i].AdminPort == 0 {
|
||||
c.Storage.Allocations[i].AdminPort = 3902 + (i * 10)
|
||||
}
|
||||
|
||||
alloc := d.Storage.Allocations[i]
|
||||
alloc := c.Storage.Allocations[i]
|
||||
|
||||
firewallGarageInbound = append(
|
||||
firewallGarageInbound,
|
||||
@ -88,8 +87,8 @@ func (d *DaemonYml) FillDefaults() {
|
||||
)
|
||||
}
|
||||
|
||||
d.VPN.Firewall.Inbound = append(
|
||||
d.VPN.Firewall.Inbound,
|
||||
c.VPN.Firewall.Inbound = append(
|
||||
c.VPN.Firewall.Inbound,
|
||||
firewallGarageInbound...,
|
||||
)
|
||||
}
|
85
entrypoint/src/daemon/daemon.go
Normal file
85
entrypoint/src/daemon/daemon.go
Normal file
@ -0,0 +1,85 @@
|
||||
// Package daemon contains types and functions related specifically to the
|
||||
// cryptic-net daemon.
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"cryptic-net/yamlutil"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/imdario/mergo"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func defaultConfigPath(appDirPath string) string {
|
||||
return filepath.Join(appDirPath, "etc", "daemon.yml")
|
||||
}
|
||||
|
||||
// CopyDefaultConfig copies the daemon config file embedded in the AppDir into
|
||||
// the given io.Writer.
|
||||
func CopyDefaultConfig(into io.Writer, appDirPath string) error {
|
||||
|
||||
defaultConfigPath := defaultConfigPath(appDirPath)
|
||||
|
||||
f, err := os.Open(defaultConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("opening daemon config at %q: %w", defaultConfigPath, err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
if _, err := io.Copy(into, f); err != nil {
|
||||
return fmt.Errorf("copying daemon config from %q: %w", defaultConfigPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadConfig loads the daemon config from userConfigPath, merges it with
|
||||
// the default found in the appDirPath, and returns the result.
|
||||
//
|
||||
// If userConfigPath is not given then the default is loaded and returned.
|
||||
func LoadConfig(
|
||||
appDirPath, userConfigPath string,
|
||||
) (
|
||||
Config, error,
|
||||
) {
|
||||
|
||||
defaultConfigPath := defaultConfigPath(appDirPath)
|
||||
|
||||
var fullDaemon map[string]interface{}
|
||||
|
||||
if err := yamlutil.LoadYamlFile(&fullDaemon, defaultConfigPath); err != nil {
|
||||
return Config{}, fmt.Errorf("parsing default daemon config file: %w", err)
|
||||
}
|
||||
|
||||
if userConfigPath != "" {
|
||||
|
||||
var daemonConfig map[string]interface{}
|
||||
if err := yamlutil.LoadYamlFile(&daemonConfig, userConfigPath); err != nil {
|
||||
return Config{}, fmt.Errorf("parsing %q: %w", userConfigPath, err)
|
||||
}
|
||||
|
||||
err := mergo.Merge(&fullDaemon, daemonConfig, mergo.WithOverride)
|
||||
if err != nil {
|
||||
return Config{}, fmt.Errorf("merging contents of file %q: %w", userConfigPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
fullDaemonB, err := yaml.Marshal(fullDaemon)
|
||||
|
||||
if err != nil {
|
||||
return Config{}, fmt.Errorf("yaml marshaling: %w", err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
if err := yaml.Unmarshal(fullDaemonB, &config); err != nil {
|
||||
return Config{}, fmt.Errorf("yaml unmarshaling back into Config struct: %w", err)
|
||||
}
|
||||
|
||||
config.fillDefaults()
|
||||
|
||||
return config, nil
|
||||
}
|
@ -3,17 +3,12 @@ package crypticnet
|
||||
import (
|
||||
"context"
|
||||
"cryptic-net/bootstrap"
|
||||
"cryptic-net/garage"
|
||||
"cryptic-net/yamlutil"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
@ -25,7 +20,6 @@ type Env struct {
|
||||
Context context.Context
|
||||
|
||||
AppDirPath string
|
||||
DaemonYmlPath string
|
||||
RuntimeDirPath string
|
||||
DataDirPath string
|
||||
|
||||
@ -33,9 +27,6 @@ type Env struct {
|
||||
// found, then these fields will not be set.
|
||||
BootstrapPath string
|
||||
Bootstrap bootstrap.Bootstrap
|
||||
|
||||
thisDaemon DaemonYml
|
||||
thisDaemonOnce sync.Once
|
||||
}
|
||||
|
||||
func getAppDirPath() string {
|
||||
@ -58,7 +49,6 @@ func NewEnv(bootstrapOptional bool) (Env, error) {
|
||||
|
||||
env := Env{
|
||||
AppDirPath: appDirPath,
|
||||
DaemonYmlPath: filepath.Join(runtimeDirPath, "daemon.yml"),
|
||||
RuntimeDirPath: runtimeDirPath,
|
||||
DataDirPath: filepath.Join(xdg.DataHome, "cryptic-net"),
|
||||
}
|
||||
@ -154,37 +144,3 @@ func (e Env) init(bootstrapOptional bool) (Env, error) {
|
||||
|
||||
return e.initBootstrap(bootstrapOptional)
|
||||
}
|
||||
|
||||
// ThisDaemon returns the DaemonYml (loaded from DaemonYmlPath) for the
|
||||
// currently running process.
|
||||
func (e Env) ThisDaemon() DaemonYml {
|
||||
e.thisDaemonOnce.Do(func() {
|
||||
if err := yamlutil.LoadYamlFile(&e.thisDaemon, e.DaemonYmlPath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
e.thisDaemon.FillDefaults()
|
||||
})
|
||||
return e.thisDaemon
|
||||
}
|
||||
|
||||
// BinPath returns the absolute path to a binary in the AppDir.
|
||||
func (e Env) BinPath(name string) string {
|
||||
return filepath.Join(e.AppDirPath, "bin", name)
|
||||
}
|
||||
|
||||
// GarageAdminClient will return an AdminClient for a local garage instance, or
|
||||
// it will _panic_ if there is no local instance configured.
|
||||
func (e Env) GarageAdminClient() *garage.AdminClient {
|
||||
|
||||
thisHost := e.Bootstrap.ThisHost()
|
||||
thisDaemon := e.ThisDaemon()
|
||||
|
||||
return garage.NewAdminClient(
|
||||
net.JoinHostPort(
|
||||
thisHost.Nebula.IP,
|
||||
strconv.Itoa(thisDaemon.Storage.Allocations[0].AdminPort),
|
||||
),
|
||||
e.Bootstrap.GarageAdminToken,
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user