Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .papr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ tests:

inherit: true
host:
distro: centos/7/atomic/alpha
distro: centos/7/atomic/smoketested
specs:
ram: 8192

context: centos/7/atomic/alpha
context: centos/7/atomic/smoketested
31 changes: 17 additions & 14 deletions cmd/kpod/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ const (
)

var (
defaultEnvVariables = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "TERM=xterm"}
defaultEnvVariables = map[string]string{
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM": "xterm",
}
)

type createResourceConfig struct {
Expand Down Expand Up @@ -64,16 +67,16 @@ type createConfig struct {
cidFile string
cgroupParent string // cgroup-parent
command []string
detach bool // detach
devices []*pb.Device // device
dnsOpt []string //dns-opt
dnsSearch []string //dns-search
dnsServers []string //dns
entrypoint string //entrypoint
env []string //env
expose []string //expose
groupAdd []uint32 // group-add
hostname string //hostname
detach bool // detach
devices []*pb.Device // device
dnsOpt []string //dns-opt
dnsSearch []string //dns-search
dnsServers []string //dns
entrypoint string //entrypoint
env map[string]string //env
expose []string //expose
groupAdd []uint32 // group-add
hostname string //hostname
image string
interactive bool //interactive
ip6Address string //ipv6
Expand Down Expand Up @@ -264,8 +267,8 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
return &createConfig{}, errors.Wrapf(err, "unable to process labels")
}
// ENVIRONMENT VARIABLES
env, err := getAllEnvironmentVariables(c.StringSlice("env-file"), c.StringSlice("env"))
if err != nil {
env := defaultEnvVariables
if err := readKVStrings(env, c.StringSlice("env-file"), c.StringSlice("env")); err != nil {
return &createConfig{}, errors.Wrapf(err, "unable to process environment variables")
}

Expand Down Expand Up @@ -338,7 +341,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
dnsServers: c.StringSlice("dns"),
entrypoint: c.String("entrypoint"),
env: env,
expose: c.StringSlice("env"),
expose: c.StringSlice("expose"),
groupAdd: groupAdd,
hostname: c.String("hostname"),
image: image,
Expand Down
32 changes: 1 addition & 31 deletions cmd/kpod/create_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,14 @@ import (
)

func getAllLabels(labelFile, inputLabels []string) (map[string]string, error) {
var labelValues []string
labels := make(map[string]string)
labelValues, labelErr := readKVStrings(labelFile, inputLabels)
labelErr := readKVStrings(labels, labelFile, inputLabels)
if labelErr != nil {
return labels, errors.Wrapf(labelErr, "unable to process labels from --label and label-file")
}
// Process KEY=VALUE stringslice in string map for WithLabels func
if len(labelValues) > 0 {
for _, i := range labelValues {
spliti := strings.Split(i, "=")
if len(spliti) < 2 {
return labels, errors.Errorf("labels must be in KEY=VALUE format: %s is invalid", i)
}
labels[spliti[0]] = spliti[1]
}
}
return labels, nil
}

func getAllEnvironmentVariables(envFiles, envInput []string) ([]string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious as to why you're breaking this up. It doesn't seem necessary to completely refactor it out - can we just pass in a spec generator and not return anything?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not breaking anything up? I removed a non useful function, that was throwing errors on
--env foo, commands, If you want me to make a separate function for the spec file generation, I can do that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, fair enough. Would be difficult to test anyways, given that we'd only be modifying the spec generator.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mheon These three lines replace the getAllEnvironmentVariables.

-       env, err := getAllEnvironmentVariables(c.StringSlice("env-file"), c.StringSlice("env"))
+       env, err := readKVStrings(c.StringSlice("env-file"), c.StringSlice("env"))
        if err != nil {
                return &createConfig{}, errors.Wrapf(err, "unable to process environment variables")
        }
+       env = append(defaultEnvVariables, env...)

env, err := readKVStrings(envFiles, envInput)
if err != nil {
return []string{}, errors.Wrapf(err, "unable to process variables from --env and --env-file")
}
// Add default environment variables if nothing defined
if len(env) == 0 {
env = append(env, defaultEnvVariables...)
}
// Each environment variable must be in the K=V format
for _, i := range env {
spliti := strings.Split(i, "=")
if len(spliti) != 2 {
return env, errors.Errorf("environment variables must be in the format KEY=VALUE: %s is invalid", i)
}
}
return env, nil
}

func convertStringSliceToMap(strSlice []string, delimiter string) (map[string]string, error) {
sysctl := make(map[string]string)
for _, inputSysctl := range strSlice {
Expand Down
29 changes: 0 additions & 29 deletions cmd/kpod/create_cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,32 +68,3 @@ func TestGetAllLabelsFile(t *testing.T) {
result, _ := getAllLabels(fileLabels, Var1)
assert.Equal(t, len(result), 3)
}

func TestGetAllEnvironmentVariables(t *testing.T) {
fileEnvs := []string{}
result, _ := getAllEnvironmentVariables(fileEnvs, Var1)
assert.Equal(t, len(result), 2)
}

func TestGetAllEnvironmentVariablesBadKeyValue(t *testing.T) {
inEnvs := []string{"ONE1", "TWO=2"}
fileEnvs := []string{}
_, err := getAllEnvironmentVariables(fileEnvs, inEnvs)
assert.Error(t, err, assert.AnError)
}

func TestGetAllEnvironmentVariablesBadEnvFile(t *testing.T) {
fileEnvs := []string{"/foobar5001/be"}
_, err := getAllEnvironmentVariables(fileEnvs, Var1)
assert.Error(t, err, assert.AnError)
}

func TestGetAllEnvironmentVariablesFile(t *testing.T) {
content := []byte("THREE=3")
tFile, err := createTmpFile(content)
defer os.Remove(tFile)
assert.NoError(t, err)
fileEnvs := []string{tFile}
result, _ := getAllEnvironmentVariables(fileEnvs, Var1)
assert.Equal(t, len(result), 3)
}
63 changes: 35 additions & 28 deletions cmd/kpod/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,55 +327,62 @@ func doesEnvExist(name string) bool {
// 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
// for env-file and labels-file flags
func readKVStrings(files []string, override []string) ([]string, error) {
envVariables := []string{}
func readKVStrings(env map[string]string, files []string, override []string) error {
for _, ef := range files {
parsedVars, err := parseEnvFile(ef)
if err != nil {
return nil, err
if err := parseEnvFile(env, ef); err != nil {
return err
}
}
for _, line := range override {
if err := parseEnv(env, line); err != nil {
return err
}
envVariables = append(envVariables, parsedVars...)
}
// parse the '-e' and '--env' after, to allow override
envVariables = append(envVariables, override...)
return nil
}

func parseEnv(env map[string]string, line string) error {
data := strings.SplitN(line, "=", 2)

// trim the front of a variable, but nothing else
name := strings.TrimLeft(data[0], whiteSpaces)
if strings.ContainsAny(name, whiteSpaces) {
return errors.Errorf("name %q has white spaces, poorly formatted name", name)
}

return envVariables, nil
if len(data) > 1 {
env[name] = data[1]
} else {
// if only a pass-through variable is given, clean it up.
val, exists := os.LookupEnv(name)
if !exists {
return errors.Errorf("environment variable %q does not exist", name)
}
env[name] = val
}
return nil
}

// parseEnvFile reads a file with environment variables enumerated by lines
func parseEnvFile(filename string) ([]string, error) {
func parseEnvFile(env map[string]string, filename string) error {
fh, err := os.Open(filename)
if err != nil {
return []string{}, err
return err
}
defer fh.Close()

lines := []string{}
scanner := bufio.NewScanner(fh)
for scanner.Scan() {
// trim the line from all leading whitespace first
line := strings.TrimLeft(scanner.Text(), whiteSpaces)
// line is not empty, and not starting with '#'
if len(line) > 0 && !strings.HasPrefix(line, "#") {
data := strings.SplitN(line, "=", 2)

// trim the front of a variable, but nothing else
variable := strings.TrimLeft(data[0], whiteSpaces)
if strings.ContainsAny(variable, whiteSpaces) {
return []string{}, errors.Errorf("variable %q has white spaces, poorly formatted environment", variable)
}

if len(data) > 1 {

// pass the value through, no trimming
lines = append(lines, fmt.Sprintf("%s=%s", variable, data[1]))
} else {
// if only a pass-through variable is given, clean it up.
lines = append(lines, fmt.Sprintf("%s=%s", strings.TrimSpace(line), os.Getenv(line)))
if err := parseEnv(env, line); err != nil {
return err
}
}
}
return lines, scanner.Err()
return scanner.Err()
}

// NsIpc represents the container ipc stack.
Expand Down
9 changes: 7 additions & 2 deletions cmd/kpod/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
}
g.SetRootReadonly(config.readOnlyRootfs)
g.SetHostname(config.hostname)
if config.hostname != "" {
g.AddProcessEnv("HOSTNAME", config.hostname)
}

for _, sysctl := range config.sysctl {
s := strings.SplitN(sysctl, "=", 2)
Expand Down Expand Up @@ -124,6 +127,10 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
g.AddTmpfsMount(spliti[0], options)
}

for name, val := range config.env {
g.AddProcessEnv(name, val)
}

configSpec := g.Spec()

if config.seccompProfilePath != "" && config.seccompProfilePath != "unconfined" {
Expand All @@ -138,8 +145,6 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
configSpec.Linux.Seccomp = &seccompConfig
}

configSpec.Process.Env = config.env

// BIND MOUNTS
configSpec.Mounts = append(configSpec.Mounts, config.GetVolumeMounts()...)

Expand Down
2 changes: 1 addition & 1 deletion test/helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ elif [[ ! -z "$TRAVIS" ]]; then
elif [[ ! -z "$PAPR" ]]; then
CRIO_ROOT="/var/tmp/checkout"
else
CRIO_ROOT=$(cd "$INTEGRATION_ROOT/../.."; pwd -P)}
CRIO_ROOT=$(cd "$INTEGRATION_ROOT/.."; pwd -P)
fi

KPOD_BINARY=${KPOD_BINARY:-${CRIO_ROOT}/bin/kpod}
Expand Down
31 changes: 31 additions & 0 deletions test/kpod_run.bats
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,34 @@ ALPINE="docker.io/library/alpine:latest"
[ "$status" -eq 0 ]

}

@test "run environment test" {

${KPOD_BINARY} ${KPOD_OPTIONS} pull ${ALPINE}

run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} run -env FOO=BAR ${ALPINE} printenv FOO | tr -d '\r'"
echo "$output"
[ "$status" -eq 0 ]
[ $output = "BAR" ]

run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} run -env PATH="/bin" ${ALPINE} printenv PATH | tr -d '\r'"
echo "$output"
[ "$status" -eq 0 ]
[ $output = "/bin" ]

run bash -c "export FOO=BAR; ${KPOD_BINARY} ${KPOD_OPTIONS} run -env FOO ${ALPINE} printenv FOO | tr -d '\r'"
echo "$output"
[ "$status" -eq 0 ]
[ "$output" = "BAR" ]

run ${KPOD_BINARY} ${KPOD_OPTIONS} run -env FOO ${ALPINE} printenv
echo "$output"
[ "$status" -ne 0 ]

# We don't currently set the hostname in containers, since we are not setting up
# networking. As soon as kpod run gets network support we need to uncomment this
# test.
# run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} run ${ALPINE} sh -c printenv | grep HOSTNAME"
# echo "$output"
# [ "$status" -eq 0 ]
}