Move the code for parsing key-value files, such as used for env-files and label-files to a separate package. This allows other projects (such as compose) to use the same parsing logic, but provide custom lookup functions for their situation (which is slightly different). The new package provides utilities for parsing key-value files for either a file or an io.Reader. Most tests for EnvFile were now testing functionality that's already tested in the new package, so were (re)moved. Co-authored-by: Nicolas De Loof <nicolas.deloof@gmail.com> Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com> Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
98 lines
2.9 KiB
Go
98 lines
2.9 KiB
Go
package opts
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/cli/pkg/kvfile"
|
|
"github.com/docker/docker/api/types/container"
|
|
)
|
|
|
|
// ReadKVStrings reads a file of line terminated key=value pairs, and overrides any keys
|
|
// present in the file with additional pairs specified in the override parameter
|
|
func ReadKVStrings(files []string, override []string) ([]string, error) {
|
|
return readKVStrings(files, override, nil)
|
|
}
|
|
|
|
// ReadKVEnvStrings reads a file of line terminated key=value pairs, and overrides any keys
|
|
// present in the file with additional pairs specified in the override parameter.
|
|
// If a key has no value, it will get the value from the environment.
|
|
func ReadKVEnvStrings(files []string, override []string) ([]string, error) {
|
|
return readKVStrings(files, override, os.LookupEnv)
|
|
}
|
|
|
|
func readKVStrings(files []string, override []string, emptyFn func(string) (string, bool)) ([]string, error) {
|
|
var variables []string
|
|
for _, ef := range files {
|
|
parsedVars, err := kvfile.Parse(ef, emptyFn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
variables = append(variables, parsedVars...)
|
|
}
|
|
// parse the '-e' and '--env' after, to allow override
|
|
variables = append(variables, override...)
|
|
|
|
return variables, nil
|
|
}
|
|
|
|
// ConvertKVStringsToMap converts ["key=value"] to {"key":"value"}
|
|
func ConvertKVStringsToMap(values []string) map[string]string {
|
|
result := make(map[string]string, len(values))
|
|
for _, value := range values {
|
|
k, v, _ := strings.Cut(value, "=")
|
|
result[k] = v
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ConvertKVStringsToMapWithNil converts ["key=value"] to {"key":"value"}
|
|
// but set unset keys to nil - meaning the ones with no "=" in them.
|
|
// We use this in cases where we need to distinguish between
|
|
//
|
|
// FOO= and FOO
|
|
//
|
|
// where the latter case just means FOO was mentioned but not given a value
|
|
func ConvertKVStringsToMapWithNil(values []string) map[string]*string {
|
|
result := make(map[string]*string, len(values))
|
|
for _, value := range values {
|
|
k, v, ok := strings.Cut(value, "=")
|
|
if !ok {
|
|
result[k] = nil
|
|
} else {
|
|
result[k] = &v
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ParseRestartPolicy returns the parsed policy or an error indicating what is incorrect
|
|
func ParseRestartPolicy(policy string) (container.RestartPolicy, error) {
|
|
if policy == "" {
|
|
// for backward-compatibility, we don't set the default ("no")
|
|
// policy here, because older versions of the engine may not
|
|
// support it.
|
|
return container.RestartPolicy{}, nil
|
|
}
|
|
|
|
p := container.RestartPolicy{}
|
|
k, v, ok := strings.Cut(policy, ":")
|
|
if ok && k == "" {
|
|
return container.RestartPolicy{}, errors.New("invalid restart policy format: no policy provided before colon")
|
|
}
|
|
if v != "" {
|
|
count, err := strconv.Atoi(v)
|
|
if err != nil {
|
|
return container.RestartPolicy{}, errors.New("invalid restart policy format: maximum retry count must be an integer")
|
|
}
|
|
p.MaximumRetryCount = count
|
|
}
|
|
|
|
p.Name = container.RestartPolicyMode(k)
|
|
return p, nil
|
|
}
|