diff options
author | Julien Dessaux | 2024-06-12 23:24:52 +0200 |
---|---|---|
committer | Julien Dessaux | 2024-06-12 23:24:52 +0200 |
commit | da6565d5f7620016ccfc91d77f4d14d3cdf7daf5 (patch) | |
tree | 175ab94dcab99ed22647880496478413c4bf8ac1 | |
parent | feat(stdlib): added borg server custom promise (diff) | |
download | gonf-da6565d5f7620016ccfc91d77f4d14d3cdf7daf5.tar.gz gonf-da6565d5f7620016ccfc91d77f4d14d3cdf7daf5.tar.bz2 gonf-da6565d5f7620016ccfc91d77f4d14d3cdf7daf5.zip |
chore(gonf): replace global variables with an env struct
-rw-r--r-- | cmd/gonf/cmd_build.go | 35 | ||||
-rw-r--r-- | cmd/gonf/cmd_deploy.go | 40 | ||||
-rw-r--r-- | cmd/gonf/env.go | 19 | ||||
-rw-r--r-- | cmd/gonf/hostflag.go | 13 | ||||
-rw-r--r-- | cmd/gonf/main.go | 76 | ||||
-rw-r--r-- | cmd/gonf/ssh.go | 34 |
6 files changed, 105 insertions, 112 deletions
diff --git a/cmd/gonf/cmd_build.go b/cmd/gonf/cmd_build.go index 0bc1fa0..92337db 100644 --- a/cmd/gonf/cmd_build.go +++ b/cmd/gonf/cmd_build.go @@ -1,38 +1,31 @@ package main import ( - "context" "flag" "fmt" - "io" "os" "os/exec" ) -func cmdBuild(ctx context.Context, - f *flag.FlagSet, - args []string, - getenv func(string) string, - stdout, stderr io.Writer, -) error { - f.Init(`gonf build [-FLAG] +func (env *Env) cmdBuild() error { + env.flagSet.Init(`gonf build [-FLAG] where FLAG can be one or more of`, flag.ContinueOnError) - hostFlag := addHostFlag(f) - f.SetOutput(stderr) - f.Parse(args) - if helpMode { - f.SetOutput(stdout) - f.Usage() + hostFlag := env.addHostFlag() + env.flagSet.SetOutput(env.stderr) + env.flagSet.Parse(env.args) + if env.helpMode { + env.flagSet.SetOutput(env.stdout) + env.flagSet.Usage() } - hostDir, err := hostFlagToHostDir(hostFlag, getenv) + hostDir, err := env.hostFlagToHostDir(hostFlag) if err != nil { - f.Usage() + env.flagSet.Usage() return err } - return runBuild(ctx, stderr, hostDir) + return env.runBuild(hostDir) } -func runBuild(ctx context.Context, stderr io.Writer, hostDir string) error { +func (env *Env) runBuild(hostDir string) error { wd, err := os.Getwd() if err != nil { return err @@ -41,10 +34,10 @@ func runBuild(ctx context.Context, stderr io.Writer, hostDir string) error { if err = os.Chdir(hostDir); err != nil { return err } - cmd := exec.CommandContext(ctx, "go", "build", "-ldflags", "-s -w -extldflags \"-static\"", hostDir) + cmd := exec.CommandContext(env.ctx, "go", "build", "-ldflags", "-s -w -extldflags \"-static\"", hostDir) cmd.Env = append(cmd.Environ(), "CGO_ENABLED=0") if out, err := cmd.CombinedOutput(); err != nil { - _, _ = fmt.Fprint(stderr, string(out)) + _, _ = fmt.Fprint(env.stderr, string(out)) return err } return nil diff --git a/cmd/gonf/cmd_deploy.go b/cmd/gonf/cmd_deploy.go index 2f0d68f..d956af2 100644 --- a/cmd/gonf/cmd_deploy.go +++ b/cmd/gonf/cmd_deploy.go @@ -1,43 +1,31 @@ package main import ( - "context" "flag" - "io" "log/slog" "path/filepath" ) -func cmdDeploy(ctx context.Context, - f *flag.FlagSet, - args []string, - getenv func(string) string, - stdout, stderr io.Writer, -) error { - f.Init(`gonf deploy [-FLAG] +func (env *Env) cmdDeploy() error { + env.flagSet.Init(`gonf deploy [-FLAG] where FLAG can be one or more of`, flag.ContinueOnError) - hostFlag := addHostFlag(f) - f.SetOutput(stderr) - f.Parse(args) - if helpMode { - f.SetOutput(stdout) - f.Usage() + hostFlag := env.addHostFlag() + env.flagSet.SetOutput(env.stderr) + env.flagSet.Parse(env.args) + if env.helpMode { + env.flagSet.SetOutput(env.stdout) + env.flagSet.Usage() } - hostDir, err := hostFlagToHostDir(hostFlag, getenv) + hostDir, err := env.hostFlagToHostDir(hostFlag) if err != nil { - f.Usage() + env.flagSet.Usage() return err } - return runDeploy(ctx, getenv, stdout, stderr, *hostFlag, hostDir) + return env.runDeploy(*hostFlag, hostDir) } -func runDeploy(ctx context.Context, - getenv func(string) string, - stdout, stderr io.Writer, - hostFlag string, - hostDir string, -) error { - sshc, err := newSSHClient(ctx, getenv, hostFlag+":22") +func (env *Env) runDeploy(hostFlag string, hostDir string) error { + sshc, err := env.newSSHClient(hostFlag + ":22") if err != nil { slog.Error("deploy", "action", "newSshClient", "error", err) return err @@ -48,7 +36,7 @@ func runDeploy(ctx context.Context, } }() - if err = sshc.SendFile(ctx, stdout, stderr, filepath.Join(hostDir, hostFlag)); err != nil { + if err = sshc.SendFile(filepath.Join(hostDir, hostFlag)); err != nil { slog.Error("deploy", "action", "SendFile", "error", err) } diff --git a/cmd/gonf/env.go b/cmd/gonf/env.go new file mode 100644 index 0000000..612fbf7 --- /dev/null +++ b/cmd/gonf/env.go @@ -0,0 +1,19 @@ +package main + +import ( + "context" + "flag" + "io" +) + +type Env struct { + batchMode bool + ctx context.Context + configDir string + flagSet *flag.FlagSet + helpMode bool + args []string + getenv func(string) string + stdout io.Writer + stderr io.Writer +} diff --git a/cmd/gonf/hostflag.go b/cmd/gonf/hostflag.go index e936f45..2bfeeee 100644 --- a/cmd/gonf/hostflag.go +++ b/cmd/gonf/hostflag.go @@ -1,26 +1,23 @@ package main import ( - "flag" "fmt" "os" "path/filepath" ) -func addHostFlag(f *flag.FlagSet) *string { - return f.String("host", "", "(REQUIRED) a valid $GONF_CONFIG/hosts/ subdirectory (overrides the GONF_HOST environment variable)") +func (env *Env) addHostFlag() *string { + return env.flagSet.String("host", "", "(REQUIRED) a valid $GONF_CONFIG/hosts/ subdirectory (overrides the GONF_HOST environment variable)") } -func hostFlagToHostDir(hostFlag *string, - getenv func(string) string, -) (string, error) { +func (env *Env) hostFlagToHostDir(hostFlag *string) (string, error) { if *hostFlag == "" { - *hostFlag = getenv("GONF_HOST") + *hostFlag = env.getenv("GONF_HOST") if *hostFlag == "" { return "", fmt.Errorf("the GONF_HOST environment variable is unset and the -host FLAG is missing. Please use one or the other") } } - hostDir := filepath.Join(configDir, "hosts", *hostFlag) + hostDir := filepath.Join(env.configDir, "hosts", *hostFlag) if info, err := os.Stat(hostDir); err != nil { return "", fmt.Errorf("invalid host name %s: %w", *hostFlag, err) } else if !info.IsDir() { diff --git a/cmd/gonf/main.go b/cmd/gonf/main.go index aefc088..606beb5 100644 --- a/cmd/gonf/main.go +++ b/cmd/gonf/main.go @@ -4,80 +4,72 @@ import ( "context" "flag" "fmt" - "io" "os" "os/signal" ) -var ( - batchMode bool - configDir string - helpMode bool -) - func main() { - if err := run(context.Background(), - os.Args, - os.Getenv, - //os.Getwd, - //os.Stdin, - os.Stdout, - os.Stderr, - ); err != nil { + env := Env{ + batchMode: false, + ctx: context.Background(), + configDir: "", + flagSet: nil, + helpMode: false, + args: os.Args, + getenv: os.Getenv, + stdout: os.Stdout, + stderr: os.Stderr, + } + if err := env.run(); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } } -func run(ctx context.Context, - args []string, - getenv func(string) string, - //getwd func() (string, error), - //stdin io.Reader, - stdout, stderr io.Writer, -) error { - ctx, cancel := signal.NotifyContext(ctx, os.Interrupt) +func (env *Env) run() error { + ctx, cancel := signal.NotifyContext(env.ctx, os.Interrupt) defer cancel() - f := flag.NewFlagSet(`gonf COMMAND [-FLAG] + env.ctx = ctx + env.flagSet = flag.NewFlagSet(`gonf COMMAND [-FLAG] where COMMAND is one of: * build: build configuration for a host * deploy: deploy configuration for a host * help: show contextual help * version: show build version and time where FLAG can be one or more of`, flag.ContinueOnError) - f.BoolVar(&batchMode, "batch", false, "skips all questions and confirmations, using the default (safe) choices each time") - f.BoolVar(&helpMode, "help", false, "show contextual help") - f.StringVar(&configDir, "config", "", "(REQUIRED for most commands) path to a gonf configurations repository (overrides the GONF_CONFIG environment variable)") - f.SetOutput(stderr) - f.Parse(args[1:]) + env.flagSet.BoolVar(&env.batchMode, "batch", false, "skips all questions and confirmations, using the default (safe) choices each time") + env.flagSet.BoolVar(&env.helpMode, "help", false, "show contextual help") + env.flagSet.StringVar(&env.configDir, "config", "", "(REQUIRED for most commands) path to a gonf configurations repository (overrides the GONF_CONFIG environment variable)") + env.flagSet.SetOutput(env.stderr) + env.flagSet.Parse(env.args[1:]) - if f.NArg() < 1 { - f.Usage() + if env.flagSet.NArg() < 1 { + env.flagSet.Usage() return fmt.Errorf("no command given") } - cmd := f.Arg(0) - argsTail := f.Args()[1:] + cmd := env.flagSet.Arg(0) + env.args = env.flagSet.Args()[1:] switch cmd { case "help": - f.SetOutput(stdout) - f.Usage() + env.flagSet.SetOutput(env.stdout) + env.flagSet.Usage() case "version": cmdVersion() default: - if configDir == "" { - configDir = getenv("GONF_CONFIG") - if configDir == "" { - f.Usage() + if env.configDir == "" { + env.configDir = env.getenv("GONF_CONFIG") + if env.configDir == "" { + env.flagSet.Usage() return fmt.Errorf("the GONF_CONFIG environment variable is unset and the -config FLAG is missing. Please use one or the other") } } switch cmd { case "build": - return cmdBuild(ctx, f, argsTail, getenv, stdout, stderr) + return env.cmdBuild() case "deploy": - return cmdDeploy(ctx, f, argsTail, getenv, stdout, stderr) + return env.cmdDeploy() default: - f.Usage() + env.flagSet.Usage() return fmt.Errorf("invalid command: %s", cmd) } } diff --git a/cmd/gonf/ssh.go b/cmd/gonf/ssh.go index e113d9f..99ad07c 100644 --- a/cmd/gonf/ssh.go +++ b/cmd/gonf/ssh.go @@ -18,22 +18,30 @@ import ( type sshClient struct { agentConn net.Conn client *ssh.Client + ctx context.Context + getenv func(string) string + stdout io.Writer + stderr io.Writer } -func newSSHClient(context context.Context, - getenv func(string) string, - destination string, -) (*sshClient, error) { - var sshc sshClient +func (env *Env) newSSHClient(destination string) (*sshClient, error) { + sshc := sshClient{ + agentConn: nil, + client: nil, + ctx: env.ctx, + getenv: env.getenv, + stdout: env.stdout, + stderr: env.stderr, + } var err error - socket := getenv("SSH_AUTH_SOCK") + socket := sshc.getenv("SSH_AUTH_SOCK") if sshc.agentConn, err = net.Dial("unix", socket); err != nil { return nil, fmt.Errorf("failed to open SSH_AUTH_SOCK: %w", err) } agentClient := agent.NewClient(sshc.agentConn) - hostKeyCallback, err := knownhosts.New(filepath.Join(getenv("HOME"), ".ssh/known_hosts")) + hostKeyCallback, err := knownhosts.New(filepath.Join(sshc.getenv("HOME"), ".ssh/known_hosts")) if err != nil { return nil, fmt.Errorf("failed to create hostkeycallback function: %w", err) } @@ -62,11 +70,7 @@ func (sshc *sshClient) Close() error { return nil } -func (sshc *sshClient) SendFile( - ctx context.Context, - stdout, stderr io.Writer, - filename string, -) error { +func (sshc *sshClient) SendFile(filename string) error { session, err := sshc.client.NewSession() if err != nil { return fmt.Errorf("failed to create ssh client session: %w", err) @@ -93,8 +97,8 @@ func (sshc *sshClient) SendFile( wg.Add(2) errCh := make(chan error, 2) - session.Stdout = stdout - session.Stderr = stderr + session.Stdout = sshc.stdout + session.Stderr = sshc.stderr if err := session.Start("scp -t /usr/local/bin/gonf-run"); err != nil { return fmt.Errorf("failed to run scp: %w", err) } @@ -124,7 +128,7 @@ func (sshc *sshClient) SendFile( } }() - ctx, cancel := context.WithTimeout(ctx, 60*time.Second) + ctx, cancel := context.WithTimeout(sshc.ctx, 60*time.Second) defer cancel() // wait for all waitgroup.Done() or the timeout |