From 6ccb75f4fa254410d57356179818d62f01c8b759 Mon Sep 17 00:00:00 2001 From: Andrew Woodlee Date: Sun, 6 Aug 2023 22:27:51 -0500 Subject: [PATCH] added scriptEnvFile to command.commandName object --- .woodpecker/go-lint.yml | 5 +++ docs/content/config/commands.md | 23 +++++++++---- go.mod | 2 +- pkg/backy/backy.go | 58 ++++++++++++++++++++++++++++++--- pkg/backy/config.go | 3 +- pkg/backy/types.go | 2 ++ 6 files changed, 80 insertions(+), 13 deletions(-) diff --git a/.woodpecker/go-lint.yml b/.woodpecker/go-lint.yml index d296bd1..42d37b7 100644 --- a/.woodpecker/go-lint.yml +++ b/.woodpecker/go-lint.yml @@ -1,4 +1,9 @@ steps: + build: + image: golang + commands: + - go build + - go test release: image: golangci/golangci-lint:v1.53.3 commands: diff --git a/docs/content/config/commands.md b/docs/content/config/commands.md index 2963184..5e20359 100644 --- a/docs/content/config/commands.md +++ b/docs/content/config/commands.md @@ -7,6 +7,8 @@ The yaml top-level map can be any string. The top-level name must be unique. +### Example Config + ```yaml commands: stop-docker-container: @@ -29,14 +31,15 @@ commands: Values available for this section: -| name | description | type | required +| name | notes | type | required | --- | --- | --- | --- | | `cmd` | Defines the command to execute | `string` | yes | | `args` | Defines the arguments to the command | `[]string` | no | | `environment` | Defines evironment variables for the command | `[]string` | no | -| `type` | May be `scriptFile` or `script`. Runs script from local machine on remote | `string` | no | +| `type` | May be `scriptFile` or `script`. Runs script from local machine on remote. Only applicable when `host` is defined. | `string` | no | | `getOutput` | Command(s) output is in the notification(s) | `bool` | no | | `host` | If not specified, the command will execute locally. | `string` | no | +| `scriptEnvFile` | When type is `scriptFile`, the script is appended to this file. | `string` | no | | `shell` | Only applicable when host is not specified | `string` | no | #### cmd @@ -86,13 +89,21 @@ If I assign a value to host as `host: web-prod` and don't specify this value in If shell is defined and host is NOT defined, the command will run in the specified shell. Make sure to escape any shell input. +### scriptEnvFile + +Path to a file. + +When type is `scriptFile`, the script is appended to this file. + +This is useful for specifiing environment variables or other things so they don't have to be included in the script. + ### type -May be `scriptFile` or `script`. Runs script from local machine on remote host. +May be `scriptFile` or `script`. Runs script from local machine on remote host passed to the SSH session as standard input. -If `script` is specified, `cmd` is used as the script. +If `type` is `script`, `cmd` is used as the script. -Script file is input as stdin to SSH. +If `type` is `scriptFile`, cmd must be a file path. ### environment @@ -100,7 +111,7 @@ The environment variables support expansion: - using escaped values `$VAR` or `${VAR}` -For now the variables have to be defined in an `.env` file in the same directory as the config file. +For now, the variables have to be defined in an `.env` file in the same directory as the config file. If using it with host specified, the SSH server has to be configured to accept those env variables. diff --git a/go.mod b/go.mod index 8cb0525..77ba0cc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.andrewnw.xyz/CyberShell/backy -go 1.20 +go 1.26 require ( github.com/go-co-op/gocron v1.30.1 diff --git a/pkg/backy/backy.go b/pkg/backy/backy.go index 491f786..cecd44a 100644 --- a/pkg/backy/backy.go +++ b/pkg/backy/backy.go @@ -95,6 +95,13 @@ func (command *Command) RunCmd(log zerolog.Logger, backyConf *ConfigFile, opts * commandSession.Stderr = cmdOutWriters if command.Type != "" { + // did the program panic while writing to the buffer? + defer func() { + if err := recover(); err != nil { + log.Info().Msg(fmt.Sprintf("panic occured writing to buffer: %x", err)) + } + }() + if command.Type == "script" { script := bytes.NewBufferString(cmd + "\n") @@ -130,8 +137,31 @@ func (command *Command) RunCmd(log zerolog.Logger, backyConf *ConfigFile, opts * return outputArr, nil } if command.Type == "scriptFile" { - var buffer bytes.Buffer - var dirErr error + var ( + buffer bytes.Buffer + scriptEnvFileBuffer bytes.Buffer + scriptFileBuffer bytes.Buffer + dirErr error + scriptEnvFilePresent bool + ) + + if command.ScriptEnvFile != "" { + command.ScriptEnvFile, dirErr = resolveDir(command.ScriptEnvFile) + if dirErr != nil { + return nil, dirErr + } + file, err := os.Open(command.ScriptEnvFile) + if err != nil { + return nil, err + } + defer file.Close() + _, err = io.Copy(&scriptEnvFileBuffer, file) + if err != nil { + return nil, err + } + scriptEnvFilePresent = true + } + command.Cmd, dirErr = resolveDir(command.Cmd) if dirErr != nil { return nil, dirErr @@ -140,12 +170,32 @@ func (command *Command) RunCmd(log zerolog.Logger, backyConf *ConfigFile, opts * if err != nil { return nil, err } - defer file.Close() - _, err = io.Copy(&buffer, file) + _, err = io.Copy(&scriptFileBuffer, file) if err != nil { return nil, err } + defer file.Close() + + if scriptEnvFilePresent { + _, err := buffer.WriteString(scriptEnvFileBuffer.String()) + if err != nil { + return nil, err + } + // write newline + buffer.WriteByte(0x0A) + + _, err = buffer.WriteString(scriptFileBuffer.String()) + if err != nil { + return nil, err + } + } else { + _, err = io.Copy(&buffer, file) + if err != nil { + return nil, err + } + } + script := &buffer commandSession.Stdin = script diff --git a/pkg/backy/config.go b/pkg/backy/config.go index 6c2400b..56f0af1 100644 --- a/pkg/backy/config.go +++ b/pkg/backy/config.go @@ -236,9 +236,8 @@ func ReadConfig(opts *ConfigOpts) *ConfigFile { } } - var notificationsMap = make(map[string]interface{}) if backyViper.IsSet("notifications") { - notificationsMap = backyViper.GetStringMap("notifications") + notificationsMap := backyViper.GetStringMap("notifications") for id := range notificationsMap { notifConfig := backyViper.Sub(getNestedConfig("notifications", id)) config := &NotificationsConfig{ diff --git a/pkg/backy/types.go b/pkg/backy/types.go index fbe6660..7e499e6 100644 --- a/pkg/backy/types.go +++ b/pkg/backy/types.go @@ -100,6 +100,8 @@ type ( // Output determines if output is requested. // Only works if command is in a list. GetOutput bool `yaml:"getOutput,omitempty"` + + ScriptEnvFile string `yaml:"scriptEnvFile"` } BackyOptionFunc func(*ConfigOpts)