WIP: updated log level on some log entries and added environment variable expansion for command line and its arguments
This commit is contained in:
19
task/cron.go
19
task/cron.go
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
wmenv "gitea.suyono.dev/suyono/wingmate/task/env"
|
||||
"time"
|
||||
|
||||
"gitea.suyono.dev/suyono/wingmate"
|
||||
@@ -224,19 +225,25 @@ func (c *CronTask) UtilDepCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CronTask) Command() string {
|
||||
func (c *CronTask) Command(env ...string) string {
|
||||
if len(env) > 0 {
|
||||
return wmenv.ExpandEnv(env, []string{c.cmdLine[0]})[0]
|
||||
}
|
||||
return c.cmdLine[0]
|
||||
}
|
||||
|
||||
func (c *CronTask) Arguments() []string {
|
||||
func (c *CronTask) Arguments(env ...string) []string {
|
||||
if len(c.cmdLine) == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
retval := make([]string, len(c.cmdLine)-1)
|
||||
copy(retval, c.cmdLine[1:])
|
||||
argCopy := make([]string, len(c.cmdLine)-1)
|
||||
copy(argCopy, c.cmdLine[1:])
|
||||
if len(env) > 0 {
|
||||
argCopy = wmenv.ExpandEnv(env, argCopy)
|
||||
}
|
||||
|
||||
return retval
|
||||
return argCopy
|
||||
}
|
||||
|
||||
func (c *CronTask) EnvLen() int {
|
||||
@@ -250,7 +257,7 @@ func (c *CronTask) Environ() []string {
|
||||
}
|
||||
|
||||
func (c *CronTask) PatchEnv(env []string) []string {
|
||||
return patchEnv(env, c.environ)
|
||||
return wmenv.PatchEnv(env, c.environ)
|
||||
}
|
||||
|
||||
func (c *CronTask) Setsid() bool {
|
||||
|
||||
97
task/env/env.go
vendored
Normal file
97
task/env/env.go
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.suyono.dev/suyono/wingmate"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
envCapture = regexp.MustCompile(`\$+[a-zA-Z_][a-zA-Z0-9_]*|\$+{[a-zA-Z_][a-zA-Z0-9_]*}`)
|
||||
envEsc = regexp.MustCompile(`^\$\$+[^$]+$`) // escaped, starts with two or more $ character
|
||||
envRef = regexp.MustCompile(`^\$([^$]+)$`) // capture the variable name
|
||||
envRefExplicit = regexp.MustCompile(`^\${([^$]+)}$`) // capture the variable name - explicit
|
||||
)
|
||||
|
||||
func expandEnv(envMap map[string]string, input string) string {
|
||||
if envEsc.MatchString(input) {
|
||||
return input
|
||||
}
|
||||
|
||||
if envName := envRefExplicit.FindStringSubmatch(input); envName != nil && envName[1] != "" {
|
||||
exVal, ok := envMap[envName[1]]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return exVal
|
||||
}
|
||||
|
||||
if envName := envRef.FindStringSubmatch(input); envName != nil && envName[1] != "" {
|
||||
exVal, ok := envMap[envName[1]]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return exVal
|
||||
}
|
||||
return input
|
||||
|
||||
}
|
||||
|
||||
func PatchEnv(existing, new []string) []string {
|
||||
tMap := make(map[string]string)
|
||||
for _, e := range existing {
|
||||
key, value, ok := strings.Cut(e, "=")
|
||||
if !ok {
|
||||
wingmate.Log().Warn().Msgf("removing invalid environment:", e)
|
||||
continue
|
||||
}
|
||||
tMap[key] = value
|
||||
}
|
||||
|
||||
for _, e := range new {
|
||||
key, value, ok := strings.Cut(e, "=")
|
||||
if !ok {
|
||||
wingmate.Log().Warn().Msgf("removing invalid environment:", e)
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.ContainsAny(key, "$") {
|
||||
wingmate.Log().Error().Err(fmt.Errorf("variable name contains $")).Msgf("removing invalid environment:", e)
|
||||
continue
|
||||
}
|
||||
|
||||
value = envCapture.ReplaceAllStringFunc(value, func(rep string) string {
|
||||
return expandEnv(tMap, rep)
|
||||
})
|
||||
|
||||
tMap[key] = value
|
||||
}
|
||||
|
||||
outEnv := make([]string, 0, len(existing))
|
||||
for key, val := range tMap {
|
||||
outEnv = append(outEnv, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
|
||||
return outEnv
|
||||
}
|
||||
|
||||
func ExpandEnv(env []string, input []string) []string {
|
||||
envMap := make(map[string]string)
|
||||
for _, e := range env {
|
||||
key, value, ok := strings.Cut(e, "=")
|
||||
if !ok {
|
||||
wingmate.Log().Warn().Msgf("removing bad environment:", e)
|
||||
continue
|
||||
}
|
||||
envMap[key] = value
|
||||
}
|
||||
|
||||
for i, s := range input {
|
||||
s = envCapture.ReplaceAllStringFunc(s, func(rep string) string {
|
||||
return expandEnv(envMap, rep)
|
||||
})
|
||||
input[i] = s
|
||||
}
|
||||
return input
|
||||
}
|
||||
88
task/task.go
88
task/task.go
@@ -4,19 +4,9 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gitea.suyono.dev/suyono/wingmate"
|
||||
|
||||
wminit "gitea.suyono.dev/suyono/wingmate/init"
|
||||
)
|
||||
|
||||
var (
|
||||
envCapture = regexp.MustCompile(`\$+[a-zA-Z_][a-zA-Z0-9_]*|\$+{[a-zA-Z_][a-zA-Z0-9_]*}`)
|
||||
envEsc = regexp.MustCompile(`^\$\$+[^\$]+$`) // escaped, starts with two or more $ character
|
||||
envRef = regexp.MustCompile(`^\$([^\$]+)$`) // capture the variable name
|
||||
envRefExplicit = regexp.MustCompile(`^\${([^\$]+)}$`) // capture the variable name - explicit
|
||||
wmenv "gitea.suyono.dev/suyono/wingmate/task/env"
|
||||
)
|
||||
|
||||
type config interface {
|
||||
@@ -227,6 +217,7 @@ func (t *ServiceTask) Name() string {
|
||||
}
|
||||
|
||||
func (t *ServiceTask) prepareCommandLine() []string {
|
||||
//TODO: is this method used somewhere? if not, can I remove this?
|
||||
if len(t.cmdLine) > 0 {
|
||||
return t.cmdLine
|
||||
}
|
||||
@@ -288,19 +279,25 @@ func (t *ServiceTask) UtilDepCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ServiceTask) Command() string {
|
||||
func (t *ServiceTask) Command(env ...string) string {
|
||||
if len(env) > 0 {
|
||||
return wmenv.ExpandEnv(env, []string{t.cmdLine[0]})[0]
|
||||
}
|
||||
return t.cmdLine[0]
|
||||
}
|
||||
|
||||
func (t *ServiceTask) Arguments() []string {
|
||||
func (t *ServiceTask) Arguments(env ...string) []string {
|
||||
if len(t.cmdLine) == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
retval := make([]string, len(t.cmdLine)-1)
|
||||
copy(retval, t.cmdLine[1:])
|
||||
argCopy := make([]string, len(t.cmdLine)-1)
|
||||
copy(argCopy, t.cmdLine[1:])
|
||||
if len(env) > 0 {
|
||||
argCopy = wmenv.ExpandEnv(env, argCopy)
|
||||
}
|
||||
|
||||
return retval
|
||||
return argCopy
|
||||
}
|
||||
|
||||
func (t *ServiceTask) EnvLen() int {
|
||||
@@ -314,7 +311,7 @@ func (t *ServiceTask) Environ() []string {
|
||||
}
|
||||
|
||||
func (t *ServiceTask) PatchEnv(env []string) []string {
|
||||
return patchEnv(env, t.environ)
|
||||
return wmenv.PatchEnv(env, t.environ)
|
||||
}
|
||||
|
||||
func (t *ServiceTask) Setsid() bool {
|
||||
@@ -385,60 +382,3 @@ func validate(validators ...func() error) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func patchEnv(existing, new []string) []string {
|
||||
tMap := make(map[string]string)
|
||||
for _, e := range existing {
|
||||
key, value, ok := strings.Cut(e, "=")
|
||||
if !ok {
|
||||
wingmate.Log().Warn().Msgf("removing invalid environment:", e)
|
||||
continue
|
||||
}
|
||||
tMap[key] = value
|
||||
}
|
||||
|
||||
for _, e := range new {
|
||||
key, value, ok := strings.Cut(e, "=")
|
||||
if !ok {
|
||||
wingmate.Log().Warn().Msgf("removing invalid environment:", e)
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.ContainsAny(key, "$") {
|
||||
wingmate.Log().Error().Err(fmt.Errorf("variable name contains $")).Msgf("removing invalid environment:", e)
|
||||
continue
|
||||
}
|
||||
|
||||
value = envCapture.ReplaceAllStringFunc(value, func(rep string) string {
|
||||
if envEsc.MatchString(rep) {
|
||||
return rep
|
||||
}
|
||||
|
||||
if envName := envRefExplicit.FindStringSubmatch(rep); envName != nil && envName[1] != "" {
|
||||
exVal, ok := tMap[envName[1]]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return exVal
|
||||
}
|
||||
|
||||
if envName := envRef.FindStringSubmatch(rep); envName != nil && envName[1] != "" {
|
||||
exVal, ok := tMap[envName[1]]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return exVal
|
||||
}
|
||||
return rep
|
||||
})
|
||||
|
||||
tMap[key] = value
|
||||
}
|
||||
|
||||
outEnv := make([]string, 0, len(existing))
|
||||
for key, val := range tMap {
|
||||
outEnv = append(outEnv, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
|
||||
return outEnv
|
||||
}
|
||||
|
||||
@@ -112,17 +112,20 @@ func TestServiceTaskPatchEnv(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name+" - service", func(t *testing.T) {
|
||||
st := NewServiceTask(tt.name)
|
||||
st.SetEnv(tt.serviceEnv...)
|
||||
result := st.PatchEnv(tt.systemEnv)
|
||||
assert.ElementsMatch(t, result, tt.expected)
|
||||
})
|
||||
t.Run(tt.name+" - cron", func(t *testing.T) {
|
||||
st := NewCronTask(tt.name)
|
||||
st.SetEnv(tt.serviceEnv...)
|
||||
result := st.PatchEnv(tt.systemEnv)
|
||||
assert.ElementsMatch(t, result, tt.expected)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Run("service", func(t *testing.T) {
|
||||
st := NewServiceTask(tt.name)
|
||||
st.SetEnv(tt.serviceEnv...)
|
||||
result := st.PatchEnv(tt.systemEnv)
|
||||
assert.ElementsMatch(t, result, tt.expected)
|
||||
})
|
||||
|
||||
t.Run("cron", func(t *testing.T) {
|
||||
st := NewCronTask(tt.name)
|
||||
st.SetEnv(tt.serviceEnv...)
|
||||
result := st.PatchEnv(tt.systemEnv)
|
||||
assert.ElementsMatch(t, result, tt.expected)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user