cli: ensure HCL env vars are added to the job submission object. (#18832)

This commit is contained in:
James Rasell
2023-10-24 16:48:13 +01:00
committed by GitHub
parent 5e1bbf90fc
commit f64ade2304
3 changed files with 98 additions and 3 deletions

3
.changelog/18832.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:bug
cli: ensure HCL env vars are added to the job submission object in the `job run` command
```

View File

@@ -9,6 +9,7 @@ import (
"encoding/json"
"fmt"
"io"
"maps"
"os"
"path/filepath"
"strconv"
@@ -534,6 +535,10 @@ func (j *JobGetter) Get(jpath string) (*api.JobSubmission, *api.Job, error) {
return nil, nil, fmt.Errorf("Failed to parse HCL job: %w", err)
}
// Perform the environment listing here as it is used twice beyond this
// point.
osEnv := os.Environ()
// we are parsing HCL2, whether from a file or stdio
jobStruct, err = jobspec2.ParseWithConfig(&jobspec2.ParseConfig{
Path: pathName,
@@ -541,7 +546,7 @@ func (j *JobGetter) Get(jpath string) (*api.JobSubmission, *api.Job, error) {
ArgVars: j.Vars,
AllowFS: true,
VarFiles: j.VarFiles,
Envs: os.Environ(),
Envs: osEnv,
Strict: j.Strict,
})
@@ -549,15 +554,24 @@ func (j *JobGetter) Get(jpath string) (*api.JobSubmission, *api.Job, error) {
var readVarFileErr error
if err == nil {
// combine any -var-file data into one big blob
varFileCat, readVarFileErr = extractVarFiles([]string(j.VarFiles))
varFileCat, readVarFileErr = extractVarFiles(j.VarFiles)
if readVarFileErr != nil {
return nil, nil, fmt.Errorf("Failed to read var file(s): %w", readVarFileErr)
}
}
// Extract variables declared by the -var flag and as environment
// variables.
extractedVarFlags := extractVarFlags(j.Vars)
extractedEnvVars := extractJobSpecEnvVars(osEnv)
// Merge the two maps ensuring that variables defined by -var flags
// take precedence.
maps.Copy(extractedEnvVars, extractedVarFlags)
// submit the job with the submission with content from -var flags
jobSubmission = &api.JobSubmission{
VariableFlags: extractVarFlags(j.Vars),
VariableFlags: extractedEnvVars,
Variables: varFileCat,
Source: source.String(),
Format: formatHCL2,
@@ -606,6 +620,36 @@ func extractVarFlags(slice []string) map[string]string {
return m
}
// extractJobSpecEnvVars is used to extract Nomad specific HCL variables from
// the OS environment. The input envVars parameter is expected to be generated
// from the os.Environment function call. The result is never nil for
// convenience.
func extractJobSpecEnvVars(envVars []string) map[string]string {
m := make(map[string]string)
for _, raw := range envVars {
if !strings.HasPrefix(raw, jobspec2.VarEnvPrefix) {
continue
}
// Trim the prefix, so we just have the raw key=value variable
// remaining.
raw = raw[len(jobspec2.VarEnvPrefix):]
// Identify the index of the equals sign which is where we split the
// variable k/v pair. -1 indicates the equals sign is not found and
// therefore the var is not valid.
if eq := strings.Index(raw, "="); eq == -1 {
continue
} else if raw[:eq] != "" {
m[raw[:eq]] = raw[eq+1:]
}
}
return m
}
// mergeAutocompleteFlags is used to join multiple flag completion sets.
func mergeAutocompleteFlags(flags ...complete.Flags) complete.Flags {
merged := make(map[string]complete.Predictor, len(flags))

View File

@@ -685,3 +685,51 @@ func Test_extractVarFlags(t *testing.T) {
}, result)
})
}
func Test_extractJobSpecEnvVars(t *testing.T) {
ci.Parallel(t)
t.Run("nil", func(t *testing.T) {
must.MapEmpty(t, extractJobSpecEnvVars(nil))
})
t.Run("complete", func(t *testing.T) {
result := extractJobSpecEnvVars([]string{
"NOMAD_VAR_count=13",
"GOPATH=/Users/jrasell/go",
"NOMAD_VAR_image=redis:7",
})
must.Eq(t, map[string]string{
"count": "13",
"image": "redis:7",
}, result)
})
t.Run("whitespace", func(t *testing.T) {
result := extractJobSpecEnvVars([]string{
"NOMAD_VAR_count = 13",
"GOPATH = /Users/jrasell/go",
})
must.Eq(t, map[string]string{
"count ": " 13",
}, result)
})
t.Run("empty key", func(t *testing.T) {
result := extractJobSpecEnvVars([]string{
"NOMAD_VAR_=13",
"=/Users/jrasell/go",
})
must.Eq(t, map[string]string{}, result)
})
t.Run("empty value", func(t *testing.T) {
result := extractJobSpecEnvVars([]string{
"NOMAD_VAR_count=",
"GOPATH=",
})
must.Eq(t, map[string]string{
"count": "",
}, result)
})
}