Factor out crypticnet.Env completely

This commit is contained in:
Brian Picciano 2022-10-27 00:37:03 +02:00
parent b23a4cafa6
commit 28159608c8
13 changed files with 88 additions and 140 deletions

View File

@ -84,10 +84,8 @@ var subCmdAdminCreateNetwork = subCmd{
return fmt.Errorf("parsing flags: %w", err)
}
env := subCmdCtx.env
if *dumpConfig {
return daemon.CopyDefaultConfig(os.Stdout, env.AppDirPath)
return daemon.CopyDefaultConfig(os.Stdout, envAppDirPath)
}
if *domain == "" || *subnetStr == "" || *hostName == "" {
@ -111,7 +109,7 @@ var subCmdAdminCreateNetwork = subCmd{
}
{
runtimeDirPath := env.RuntimeDirPath
runtimeDirPath := envRuntimeDirPath
fmt.Fprintf(os.Stderr, "will use runtime directory %q for temporary state\n", runtimeDirPath)
@ -129,7 +127,7 @@ var subCmdAdminCreateNetwork = subCmd{
}()
}
daemonConfig, err := daemon.LoadConfig(env.AppDirPath, *daemonConfigPath)
daemonConfig, err := daemon.LoadConfig(envAppDirPath, *daemonConfigPath)
if err != nil {
return fmt.Errorf("loading daemon config: %w", err)
}
@ -165,16 +163,16 @@ var subCmdAdminCreateNetwork = subCmd{
GarageGlobalBucketS3APICredentials: garage.NewS3APICredentials(),
}
if hostBootstrap, err = mergeDaemonConfigIntoBootstrap(env, hostBootstrap, daemonConfig); err != nil {
if hostBootstrap, err = mergeDaemonConfigIntoBootstrap(hostBootstrap, daemonConfig); err != nil {
return fmt.Errorf("merging daemon config into bootstrap data: %w", err)
}
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(env, hostBootstrap, daemonConfig)
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(hostBootstrap, daemonConfig)
if err != nil {
return fmt.Errorf("generating nebula config: %w", err)
}
garagePmuxProcConfigs, err := garagePmuxProcConfigs(env, hostBootstrap, daemonConfig)
garagePmuxProcConfigs, err := garagePmuxProcConfigs(hostBootstrap, daemonConfig)
if err != nil {
return fmt.Errorf("generating garage configs: %w", err)
}
@ -188,7 +186,7 @@ var subCmdAdminCreateNetwork = subCmd{
),
}
ctx, cancel := context.WithCancel(env.Context)
ctx, cancel := context.WithCancel(subCmdCtx.ctx)
pmuxDoneCh := make(chan struct{})
fmt.Fprintln(os.Stderr, "starting child processes")
@ -269,9 +267,7 @@ var subCmdAdminMakeBootstrap = subCmd{
return errors.New("--name and --admin-path are required")
}
env := subCmdCtx.env
hostBootstrap, err := loadHostBootstrap(env.DataDirPath)
hostBootstrap, err := loadHostBootstrap()
if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err)
}
@ -287,7 +283,7 @@ var subCmdAdminMakeBootstrap = subCmd{
// command for this host has been run recently then it might not have
// made it into the bootstrap file yet, and so won't be in
// `hostBootstrap`.
hosts, err := bootstrap.GetGarageBootstrapHosts(env.Context, client)
hosts, err := bootstrap.GetGarageBootstrapHosts(subCmdCtx.ctx, client)
if err != nil {
return fmt.Errorf("retrieving host info from garage: %w", err)
}

View File

@ -9,9 +9,9 @@ import (
"path/filepath"
)
func loadHostBootstrap(dataDirPath string) (bootstrap.Bootstrap, error) {
func loadHostBootstrap() (bootstrap.Bootstrap, error) {
dataDirPath = bootstrap.DataDirPath(dataDirPath)
dataDirPath := bootstrap.DataDirPath(envDataDirPath)
hostBootstrap, err := bootstrap.FromFile(dataDirPath)
if errors.Is(err, fs.ErrNotExist) {
@ -24,9 +24,9 @@ func loadHostBootstrap(dataDirPath string) (bootstrap.Bootstrap, error) {
return hostBootstrap, nil
}
func writeBootstrapToDataDir(dataDirPath string, hostBootstrap bootstrap.Bootstrap) error {
func writeBootstrapToDataDir(hostBootstrap bootstrap.Bootstrap) error {
path := bootstrap.DataDirPath(dataDirPath)
path := bootstrap.DataDirPath(envDataDirPath)
dirPath := filepath.Dir(path)
if err := os.MkdirAll(dirPath, 0700); err != nil {

View File

@ -41,14 +41,14 @@ import (
// the new bootstrap file is different than the existing one, the existing one
// is overwritten and true is returned.
func reloadBootstrap(
env crypticnet.Env,
ctx context.Context,
hostBootstrap bootstrap.Bootstrap,
s3Client garage.S3APIClient,
) (
bootstrap.Bootstrap, bool, error,
) {
newHosts, err := bootstrap.GetGarageBootstrapHosts(env.Context, s3Client)
newHosts, err := bootstrap.GetGarageBootstrapHosts(ctx, s3Client)
if err != nil {
return bootstrap.Bootstrap{}, false, fmt.Errorf("getting hosts from garage: %w", err)
}
@ -69,7 +69,7 @@ func reloadBootstrap(
newHostBootstrap := hostBootstrap.WithHosts(newHosts)
if err := writeBootstrapToDataDir(env.DataDirPath, newHostBootstrap); err != nil {
if err := writeBootstrapToDataDir(newHostBootstrap); err != nil {
return bootstrap.Bootstrap{}, false, fmt.Errorf("writing new bootstrap.tgz to data dir: %w", err)
}
@ -81,7 +81,7 @@ func reloadBootstrap(
// until the spawned pmux has returned, and returns a copy of hostBootstrap with
// updated boostrap info.
func runDaemonPmuxOnce(
env crypticnet.Env,
ctx context.Context,
hostBootstrap bootstrap.Bootstrap,
daemonConfig daemon.Config,
) (
@ -96,17 +96,17 @@ func runDaemonPmuxOnce(
// endpoint.
s3Client := hostBootstrap.GlobalBucketS3APIClient()
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(env, hostBootstrap, daemonConfig)
nebulaPmuxProcConfig, err := nebulaPmuxProcConfig(hostBootstrap, daemonConfig)
if err != nil {
return bootstrap.Bootstrap{}, fmt.Errorf("generating nebula config: %w", err)
}
dnsmasqPmuxProcConfig, err := dnsmasqPmuxProcConfig(env, hostBootstrap, daemonConfig)
dnsmasqPmuxProcConfig, err := dnsmasqPmuxProcConfig(hostBootstrap, daemonConfig)
if err != nil {
return bootstrap.Bootstrap{}, fmt.Errorf("generating dnsmasq config: %w", err)
}
garagePmuxProcConfigs, err := garagePmuxProcConfigs(env, hostBootstrap, daemonConfig)
garagePmuxProcConfigs, err := garagePmuxProcConfigs(hostBootstrap, daemonConfig)
if err != nil {
return bootstrap.Bootstrap{}, fmt.Errorf("generating garage children configs: %w", err)
}
@ -121,12 +121,12 @@ func runDaemonPmuxOnce(
),
}
doneCh := env.Context.Done()
doneCh := ctx.Done()
var wg sync.WaitGroup
defer wg.Wait()
ctx, cancel := context.WithCancel(env.Context)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
wg.Add(1)
@ -184,7 +184,7 @@ func runDaemonPmuxOnce(
select {
case <-doneCh:
return bootstrap.Bootstrap{}, env.Context.Err()
return bootstrap.Bootstrap{}, ctx.Err()
case <-ticker.C:
@ -195,7 +195,7 @@ func runDaemonPmuxOnce(
err error
)
if hostBootstrap, changed, err = reloadBootstrap(env, hostBootstrap, s3Client); err != nil {
if hostBootstrap, changed, err = reloadBootstrap(ctx, hostBootstrap, s3Client); err != nil {
return bootstrap.Bootstrap{}, fmt.Errorf("reloading bootstrap: %w", err)
} else if changed {
@ -232,13 +232,11 @@ var subCmdDaemon = subCmd{
return fmt.Errorf("parsing flags: %w", err)
}
env := subCmdCtx.env
if *dumpConfig {
return daemon.CopyDefaultConfig(os.Stdout, env.AppDirPath)
return daemon.CopyDefaultConfig(os.Stdout, envAppDirPath)
}
runtimeDirPath := env.RuntimeDirPath
runtimeDirPath := envRuntimeDirPath
fmt.Fprintf(os.Stderr, "will use runtime directory %q for temporary state\n", runtimeDirPath)
@ -260,8 +258,8 @@ var subCmdDaemon = subCmd{
}()
var (
bootstrapDataDirPath = bootstrap.DataDirPath(env.DataDirPath)
bootstrapAppDirPath = bootstrap.AppDirPath(env.AppDirPath)
bootstrapDataDirPath = bootstrap.DataDirPath(envDataDirPath)
bootstrapAppDirPath = bootstrap.AppDirPath(envAppDirPath)
hostBootstrapPath string
hostBootstrap bootstrap.Bootstrap
@ -302,12 +300,12 @@ var subCmdDaemon = subCmd{
// If the bootstrap file is not being stored in the data dir, copy
// it there, so it can be loaded from there next time.
if err := writeBootstrapToDataDir(env.DataDirPath, hostBootstrap); err != nil {
if err := writeBootstrapToDataDir(hostBootstrap); err != nil {
return fmt.Errorf("writing bootstrap.tgz to data dir: %w", err)
}
}
daemonConfig, err := daemon.LoadConfig(env.AppDirPath, *daemonConfigPath)
daemonConfig, err := daemon.LoadConfig(envAppDirPath, *daemonConfigPath)
if err != nil {
return fmt.Errorf("loading daemon config: %w", err)
}
@ -317,13 +315,13 @@ var subCmdDaemon = subCmd{
// 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 hostBootstrap, err = mergeDaemonConfigIntoBootstrap(env, hostBootstrap, daemonConfig); err != nil {
if hostBootstrap, err = mergeDaemonConfigIntoBootstrap(hostBootstrap, daemonConfig); err != nil {
return fmt.Errorf("merging daemon config into bootstrap data: %w", err)
}
for {
hostBootstrap, err = runDaemonPmuxOnce(env, hostBootstrap, daemonConfig)
hostBootstrap, err = runDaemonPmuxOnce(subCmdCtx.ctx, hostBootstrap, daemonConfig)
if errors.Is(err, context.Canceled) {
return nil

View File

@ -2,7 +2,6 @@ package main
import (
"context"
crypticnet "cryptic-net"
"cryptic-net/bootstrap"
"cryptic-net/daemon"
"fmt"
@ -10,7 +9,6 @@ import (
)
func mergeDaemonConfigIntoBootstrap(
env crypticnet.Env,
hostBootstrap bootstrap.Bootstrap,
daemonConfig daemon.Config,
) (
@ -36,7 +34,7 @@ func mergeDaemonConfigIntoBootstrap(
hostBootstrap.Hosts[host.Name] = host
if err := writeBootstrapToDataDir(env.DataDirPath, hostBootstrap); err != nil {
if err := writeBootstrapToDataDir(hostBootstrap); err != nil {
return bootstrap.Bootstrap{}, fmt.Errorf("writing bootstrap file: %w", err)
}

View File

@ -1,7 +1,6 @@
package main
import (
crypticnet "cryptic-net"
"cryptic-net/bootstrap"
"cryptic-net/daemon"
"cryptic-net/dnsmasq"
@ -13,14 +12,13 @@ import (
)
func dnsmasqPmuxProcConfig(
env crypticnet.Env,
hostBootstrap bootstrap.Bootstrap,
daemonConfig daemon.Config,
) (
pmuxlib.ProcessConfig, error,
) {
confPath := filepath.Join(env.RuntimeDirPath, "dnsmasq.conf")
confPath := filepath.Join(envRuntimeDirPath, "dnsmasq.conf")
hostsSlice := make([]bootstrap.Host, 0, len(hostBootstrap.Hosts))
for _, host := range hostBootstrap.Hosts {

View File

@ -28,9 +28,7 @@ var subCmdGarageMC = subCmd{
return fmt.Errorf("parsing flags: %w", err)
}
env := subCmdCtx.env
hostBootstrap, err := loadHostBootstrap(env.DataDirPath)
hostBootstrap, err := loadHostBootstrap()
if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err)
}
@ -88,9 +86,7 @@ var subCmdGarageCLI = subCmd{
checkLock: true,
do: func(subCmdCtx subCmdCtx) error {
env := subCmdCtx.env
hostBootstrap, err := loadHostBootstrap(env.DataDirPath)
hostBootstrap, err := loadHostBootstrap()
if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err)
}

View File

@ -2,7 +2,6 @@ package main
import (
"context"
crypticnet "cryptic-net"
"cryptic-net/bootstrap"
"cryptic-net/daemon"
"cryptic-net/garage"
@ -68,7 +67,6 @@ func waitForGarageAndNebula(
}
func garageWriteChildConfig(
env crypticnet.Env,
hostBootstrap bootstrap.Bootstrap,
alloc daemon.ConfigStorageAllocation,
) (
@ -100,7 +98,7 @@ func garageWriteChildConfig(
}
garageTomlPath := filepath.Join(
env.RuntimeDirPath, fmt.Sprintf("garage-%d.toml", alloc.RPCPort),
envRuntimeDirPath, fmt.Sprintf("garage-%d.toml", alloc.RPCPort),
)
err := garage.WriteGarageTomlFile(garageTomlPath, garage.GarageTomlData{
@ -125,7 +123,6 @@ func garageWriteChildConfig(
}
func garagePmuxProcConfigs(
env crypticnet.Env,
hostBootstrap bootstrap.Bootstrap,
daemonConfig daemon.Config,
) (
@ -136,7 +133,7 @@ func garagePmuxProcConfigs(
for _, alloc := range daemonConfig.Storage.Allocations {
childConfigPath, err := garageWriteChildConfig(env, hostBootstrap, alloc)
childConfigPath, err := garageWriteChildConfig(hostBootstrap, alloc)
if err != nil {
return nil, fmt.Errorf("writing child config file for alloc %+v: %w", alloc, err)

View File

@ -59,9 +59,7 @@ var subCmdHostsAdd = subCmd{
// TODO validate that the IP is in the correct CIDR
env := subCmdCtx.env
hostBootstrap, err := loadHostBootstrap(env.DataDirPath)
hostBootstrap, err := loadHostBootstrap()
if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err)
}
@ -75,7 +73,7 @@ var subCmdHostsAdd = subCmd{
},
}
return bootstrap.PutGarageBoostrapHost(env.Context, client, host)
return bootstrap.PutGarageBoostrapHost(subCmdCtx.ctx, client, host)
},
}
@ -85,16 +83,14 @@ var subCmdHostsList = subCmd{
checkLock: true,
do: func(subCmdCtx subCmdCtx) error {
env := subCmdCtx.env
hostBootstrap, err := loadHostBootstrap(env.DataDirPath)
hostBootstrap, err := loadHostBootstrap()
if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err)
}
client := hostBootstrap.GlobalBucketS3APIClient()
hostsMap, err := bootstrap.GetGarageBootstrapHosts(env.Context, client)
hostsMap, err := bootstrap.GetGarageBootstrapHosts(subCmdCtx.ctx, client)
if err != nil {
return fmt.Errorf("retrieving hosts from garage: %w", err)
}
@ -131,16 +127,14 @@ var subCmdHostsDelete = subCmd{
return errors.New("--name is required")
}
env := subCmdCtx.env
hostBootstrap, err := loadHostBootstrap(env.DataDirPath)
hostBootstrap, err := loadHostBootstrap()
if err != nil {
return fmt.Errorf("loading host bootstrap: %w", err)
}
client := hostBootstrap.GlobalBucketS3APIClient()
return bootstrap.RemoveGarageBootstrapHost(env.Context, client, *name)
return bootstrap.RemoveGarageBootstrapHost(subCmdCtx.ctx, client, *name)
},
}

View File

@ -1,9 +1,14 @@
package main
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"syscall"
crypticnet "cryptic-net"
"github.com/adrg/xdg"
)
// The purpose of this binary is to act as the entrypoint of the cryptic-net
@ -11,13 +16,42 @@ import (
// then passes execution along to an appropriate binary housed in AppDir/bin
// (usually a bash script, which is more versatile than a go program).
func getAppDirPath() string {
appDirPath := os.Getenv("APPDIR")
if appDirPath == "" {
appDirPath = "."
}
return appDirPath
}
var (
envAppDirPath = getAppDirPath()
envRuntimeDirPath = filepath.Join(xdg.RuntimeDir, "cryptic-net")
envDataDirPath = filepath.Join(xdg.DataHome, "cryptic-net")
)
func main() {
env := crypticnet.NewEnv()
ctx, cancel := context.WithCancel(context.Background())
signalCh := make(chan os.Signal, 2)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-signalCh
cancel()
fmt.Fprintf(os.Stderr, "got signal %v, will exit gracefully\n", sig)
sig = <-signalCh
fmt.Fprintf(os.Stderr, "second interrupt signal %v received, force quitting, there may be zombie children left behind, good luck!\n", sig)
os.Stderr.Sync()
os.Exit(1)
}()
err := subCmdCtx{
args: os.Args[1:],
env: env,
ctx: ctx,
}.doSubCmd(
subCmdAdmin,
subCmdDaemon,

View File

@ -2,7 +2,6 @@ package main
import (
"context"
crypticnet "cryptic-net"
"cryptic-net/bootstrap"
"cryptic-net/daemon"
"cryptic-net/yamlutil"
@ -36,7 +35,6 @@ func waitForNebula(ctx context.Context, hostBootstrap bootstrap.Bootstrap) error
}
func nebulaPmuxProcConfig(
env crypticnet.Env,
hostBootstrap bootstrap.Bootstrap,
daemonConfig daemon.Config,
) (
@ -105,7 +103,7 @@ func nebulaPmuxProcConfig(
}
}
nebulaYmlPath := filepath.Join(env.RuntimeDirPath, "nebula.yml")
nebulaYmlPath := filepath.Join(envRuntimeDirPath, "nebula.yml")
if err := yamlutil.WriteYamlFile(config, nebulaYmlPath); err != nil {
return pmuxlib.ProcessConfig{}, fmt.Errorf("writing nebula.yml to %q: %w", nebulaYmlPath, err)

View File

@ -1,6 +1,7 @@
package main
import (
"context"
crypticnet "cryptic-net"
"fmt"
"os"
@ -14,7 +15,8 @@ type subCmdCtx struct {
subCmd subCmd // the subCmd itself
args []string // command-line arguments, excluding the subCmd itself.
subCmdNames []string // names of subCmds so far, including this one
env crypticnet.Env
ctx context.Context
}
type subCmd struct {
@ -99,7 +101,7 @@ func (ctx subCmdCtx) doSubCmd(subCmds ...subCmd) error {
if subCmd.checkLock {
err := crypticnet.NewProcLock(ctx.env.RuntimeDirPath).AssertLock()
err := crypticnet.NewProcLock(envRuntimeDirPath).AssertLock()
if err != nil {
return fmt.Errorf("checking lock file: %w", err)
@ -110,7 +112,7 @@ func (ctx subCmdCtx) doSubCmd(subCmds ...subCmd) error {
subCmd: subCmd,
args: args,
subCmdNames: append(ctx.subCmdNames, subCmdName),
env: ctx.env,
ctx: ctx.ctx,
})
if err != nil {

View File

@ -11,7 +11,7 @@ var subCmdVersion = subCmd{
descr: "Dumps version and build info to stdout",
do: func(subCmdCtx subCmdCtx) error {
versionPath := filepath.Join(subCmdCtx.env.AppDirPath, "share/version")
versionPath := filepath.Join(envAppDirPath, "share/version")
version, err := os.ReadFile(versionPath)

View File

@ -1,63 +0,0 @@
package crypticnet
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"syscall"
"github.com/adrg/xdg"
)
// Env contains the values of environment variables, as well as other entities
// which are useful across all processes.
type Env struct {
Context context.Context
AppDirPath string
RuntimeDirPath string
DataDirPath string
}
func getAppDirPath() string {
appDirPath := os.Getenv("APPDIR")
if appDirPath == "" {
appDirPath = "."
}
return appDirPath
}
// NewEnv calculates an Env instance based on the APPDIR and XDG envvars.
func NewEnv() Env {
runtimeDirPath := filepath.Join(xdg.RuntimeDir, "cryptic-net")
appDirPath := getAppDirPath()
env := Env{
AppDirPath: appDirPath,
RuntimeDirPath: runtimeDirPath,
DataDirPath: filepath.Join(xdg.DataHome, "cryptic-net"),
}
var cancel context.CancelFunc
env.Context, cancel = context.WithCancel(context.Background())
signalCh := make(chan os.Signal, 2)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-signalCh
cancel()
fmt.Fprintf(os.Stderr, "got signal %v, will exit gracefully\n", sig)
sig = <-signalCh
fmt.Fprintf(os.Stderr, "second interrupt signal %v received, force quitting, there may be zombie children left behind, good luck!\n", sig)
os.Stderr.Sync()
os.Exit(1)
}()
return env
}