summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorJulien Dessaux2024-06-12 23:24:52 +0200
committerJulien Dessaux2024-06-12 23:24:52 +0200
commitda6565d5f7620016ccfc91d77f4d14d3cdf7daf5 (patch)
tree175ab94dcab99ed22647880496478413c4bf8ac1 /cmd
parentfeat(stdlib): added borg server custom promise (diff)
downloadgonf-da6565d5f7620016ccfc91d77f4d14d3cdf7daf5.tar.gz
gonf-da6565d5f7620016ccfc91d77f4d14d3cdf7daf5.tar.bz2
gonf-da6565d5f7620016ccfc91d77f4d14d3cdf7daf5.zip
chore(gonf): replace global variables with an env struct
Diffstat (limited to 'cmd')
-rw-r--r--cmd/gonf/cmd_build.go35
-rw-r--r--cmd/gonf/cmd_deploy.go40
-rw-r--r--cmd/gonf/env.go19
-rw-r--r--cmd/gonf/hostflag.go13
-rw-r--r--cmd/gonf/main.go76
-rw-r--r--cmd/gonf/ssh.go34
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