diff --git a/NEWS b/NEWS index dc8987883..84975cae1 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,16 @@ +0.4 +=== + +### Enhancements + +* Added the '--env' option to 'run' to pass environment variables to the + Toolbx container +* Added the '--use-fallback-shell' option to 'run' to fall back to /bin/bash + and /bin/sh if the specified command is not found +* Added the '--workdir' option to 'run' to override the working directory used + inside the Toolbx container + + 0.3 === diff --git a/doc/toolbox-run.1.md b/doc/toolbox-run.1.md index bfcceeff0..563c9b845 100644 --- a/doc/toolbox-run.1.md +++ b/doc/toolbox-run.1.md @@ -6,8 +6,11 @@ toolbox\-run - Run a command in an existing Toolbx container ## SYNOPSIS **toolbox run** [*--container NAME* | *-c NAME*] [*--distro DISTRO* | *-d DISTRO*] + [*--env KEY=VALUE*] [*--preserve-fds N*] [*--release RELEASE* | *-r RELEASE*] + [*--use-fallback-shell*] + [*--workdir DIR*] [*COMMAND*] ## DESCRIPTION @@ -38,6 +41,12 @@ Run command inside a Toolbx container for a different operating system DISTRO than the host. Has to be coupled with `--release` unless the selected DISTRO matches the host system. +**--env** KEY=VALUE + +Set an environment variable in the form of KEY=VALUE for use inside the Toolbx +container. This option can be specified multiple times to set multiple +environment variables. + **--preserve-fds** N Pass down to command N additional file descriptors (in addition to 0, 1, 2). @@ -48,6 +57,16 @@ The total number of file descriptors will be 3+N. Run command inside a Toolbx container for a different operating system RELEASE than the host. +**--use-fallback-shell** + +Fall back to /bin/bash and /bin/sh if the specified command is not found inside +the Toolbx container. + +**--workdir** DIR + +Override the working directory used inside the Toolbx container. The value must +be an absolute path. + ## EXIT STATUS The exit code gives information about why the command within the container diff --git a/src/cmd/enter.go b/src/cmd/enter.go index 9ba84d6ad..16ea148c0 100644 --- a/src/cmd/enter.go +++ b/src/cmd/enter.go @@ -121,7 +121,7 @@ func enter(cmd *cobra.Command, args []string) error { command := []string{userShell, "-l"} - if err := runCommand(container, defaultContainer, image, release, 0, command, true, true, false); err != nil { + if err := runCommand(container, defaultContainer, image, release, 0, command, nil, true, true, false); err != nil { return err } diff --git a/src/cmd/run.go b/src/cmd/run.go index ed421aa68..e5da7249b 100644 --- a/src/cmd/run.go +++ b/src/cmd/run.go @@ -52,13 +52,16 @@ type entryPointError struct { var ( runFlags struct { - container string - distro string - preserveFDs uint - release string + container string + distro string + env []string + preserveFDs uint + release string + useFallbackShell bool + workDir string } - runFallbackCommands = [][]string{{"/bin/bash", "-l"}} + runFallbackCommands = [][]string{{"/bin/bash", "-l"}, {"/bin/sh", "-l"}} runFallbackWorkDirs = []string{"" /* $HOME */} ) @@ -96,6 +99,21 @@ func init() { "", "Run command inside a Toolbx container for a different operating system release than the host") + flags.StringArrayVar(&runFlags.env, + "env", + nil, + "Set environment variables in the form of KEY=VALUE for use inside the Toolbx container") + + flags.BoolVar(&runFlags.useFallbackShell, + "use-fallback-shell", + false, + "Fall back to /bin/bash and /bin/sh if the command is not found") + + flags.StringVar(&runFlags.workDir, + "workdir", + "", + "Override the working directory used inside the Toolbx container") + runCmd.SetHelpFunc(runHelp) if err := runCmd.RegisterFlagCompletionFunc("container", completionContainerNames); err != nil { @@ -141,6 +159,20 @@ func run(cmd *cobra.Command, args []string) error { command := args + if runFlags.workDir != "" { + if !filepath.IsAbs(runFlags.workDir) { + var builder strings.Builder + fmt.Fprintf(&builder, "invalid argument for '--workdir'\n") + fmt.Fprintf(&builder, "The working directory must be an absolute path.\n") + fmt.Fprintf(&builder, "Run '%s --help' for usage.", executableBase) + + errMsg := builder.String() + return errors.New(errMsg) + } + + workingDirectory = runFlags.workDir + } + container, image, release, err := resolveContainerAndImageNames(runFlags.container, "--container", runFlags.distro, @@ -157,8 +189,9 @@ func run(cmd *cobra.Command, args []string) error { release, runFlags.preserveFDs, command, + runFlags.env, false, - false, + runFlags.useFallbackShell, true); err != nil { return err } @@ -170,7 +203,7 @@ func runCommand(container string, defaultContainer bool, image, release string, preserveFDs uint, - command []string, + command, extraEnviron []string, emitEscapeSequence, fallbackToBash, pedantic bool) error { if !pedantic { @@ -347,6 +380,7 @@ func runCommand(container string, logrus.Debugf("Container %s is initialized", container) environ := append(cdiEnviron, p11KitServerEnviron...) + environ = append(environ, extraEnviron...) if err := runCommandWithFallbacks(container, preserveFDs, command, diff --git a/test/system/104-run.bats b/test/system/104-run.bats index 64c0cd5e9..07417153f 100644 --- a/test/system/104-run.bats +++ b/test/system/104-run.bats @@ -862,6 +862,58 @@ teardown() { assert [ ${#stderr_lines[@]} -eq 2 ] } +@test "run: Ensure that --env passes an environment variable to the container" { + create_default_container + + run --keep-empty-lines "$TOOLBX" run --env FOO=bar printenv FOO + + assert_success + assert_line --index 0 "bar" + assert [ ${#lines[@]} -eq 1 ] +} + +@test "run: Ensure that multiple --env flags work" { + create_default_container + + run --keep-empty-lines "$TOOLBX" run --env FOO=bar --env BAZ=qux /bin/sh -c 'printenv FOO && printenv BAZ' + + assert_success + assert_line --index 0 "bar" + assert_line --index 1 "qux" + assert [ ${#lines[@]} -eq 2 ] +} + +@test "run: Ensure that --workdir sets the working directory" { + create_default_container + + run --keep-empty-lines "$TOOLBX" run --workdir /tmp pwd + + assert_success + assert_line --index 0 "/tmp" + assert [ ${#lines[@]} -eq 1 ] +} + +@test "run: Try --workdir with a relative path" { + run --keep-empty-lines --separate-stderr "$TOOLBX" run --workdir relative/path true + + assert_failure + assert [ ${#lines[@]} -eq 0 ] + lines=("${stderr_lines[@]}") + assert_line --index 0 "Error: invalid argument for '--workdir'" + assert_line --index 1 "The working directory must be an absolute path." + assert_line --index 2 "Run 'toolbox --help' for usage." + assert [ ${#stderr_lines[@]} -eq 3 ] +} + +@test "run: Ensure that --use-fallback-shell works with an existing command" { + create_default_container + + run --keep-empty-lines "$TOOLBX" run --use-fallback-shell true + + assert_success + assert_output "" +} + @test "run: Try an old unsupported container" { local default_image default_image="$(get_default_image)"