internal/sandbox: support appending to environment
Make it possible to append environment variables to
the sandbox environment, instead of replacing it.
Change-Id: If431bc34abb46ac239867bde7a32b750664a13bc
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/475235
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/internal/sandbox/runner.go b/internal/sandbox/runner.go
index 77fa922..1b0f362 100644
--- a/internal/sandbox/runner.go
+++ b/internal/sandbox/runner.go
@@ -31,10 +31,16 @@
log.Fatal(err)
}
log.Printf("read %q", in)
- var cmd exec.Cmd
+ var cmd struct {
+ exec.Cmd
+ AppendToEnv bool
+ }
if err := json.Unmarshal(in, &cmd); err != nil {
log.Fatal(err)
}
+ if cmd.AppendToEnv {
+ cmd.Env = append(os.Environ(), cmd.Env...)
+ }
log.Printf("cmd: %+v", cmd)
out, err := cmd.Output()
if err != nil {
diff --git a/internal/sandbox/sandbox.go b/internal/sandbox/sandbox.go
index c2b0855..a239cc2 100644
--- a/internal/sandbox/sandbox.go
+++ b/internal/sandbox/sandbox.go
@@ -60,6 +60,10 @@
// runsc provides by default.
Env []string
+ // If AppendToEnv is true, the contents of Env are appended
+ // to the sandbox's existing environment, instead of replacing it.
+ AppendToEnv bool
+
// Dir specifies the working directory of the command.
// If Dir is the empty string, Run runs the command in the
// root of the sandbox filesystem.
diff --git a/internal/sandbox/sandbox_test.go b/internal/sandbox/sandbox_test.go
index 60fa51f..8bb163c 100644
--- a/internal/sandbox/sandbox_test.go
+++ b/internal/sandbox/sandbox_test.go
@@ -25,33 +25,44 @@
sb := New("testdata/bundle")
sb.Runsc = "/usr/local/bin/runsc" // must match path in Makefile
- t.Run("printargs", func(t *testing.T) {
- out, err := sb.Command("printargs", "a", "b").Output()
+ check := func(t *testing.T, cmd *Cmd, want string) {
+ t.Helper()
+ out, err := cmd.Output()
if err != nil {
t.Fatal(derrors.IncludeStderr(err))
}
-
- want := `args:
-0: "a"
-1: "b"`
got := string(out)
if got != want {
t.Fatalf("got\n%q\nwant\n%q", got, want)
}
+ }
+
+ t.Run("printargs", func(t *testing.T) {
+ check(t, sb.Command("printargs", "a", "b"), `args:
+0: "a"
+1: "b"`)
})
t.Run("space in arg", func(t *testing.T) {
- out, err := sb.Command("printargs", "a", "b c\td").Output()
- if err != nil {
- t.Fatal(derrors.IncludeStderr(err))
- }
- want := `args:
+ check(t, sb.Command("printargs", "a", "b c\td"), `args:
0: "a"
-1: "b c\td"`
- got := string(out)
- if got != want {
- t.Fatalf("got\n%q\nwant\n%q", got, want)
- }
+1: "b c\td"`)
+ })
+
+ t.Run("replace env", func(t *testing.T) {
+ cmd := sb.Command("printargs", "$HOME", "$FOO")
+ cmd.Env = []string{"FOO=17"}
+ check(t, cmd, `args:
+0: ""
+1: "17"`)
+ })
+ t.Run("append to env", func(t *testing.T) {
+ cmd := sb.Command("printargs", "$HOME", "$FOO")
+ cmd.Env = []string{"FOO=17"}
+ cmd.AppendToEnv = true
+ check(t, cmd, `args:
+0: "/"
+1: "17"`)
})
t.Run("no program", func(t *testing.T) {
_, err := sb.Command("foo").Output()
diff --git a/internal/sandbox/testdata/printargs.go b/internal/sandbox/testdata/printargs.go
index 2a03b5e..7f65410 100644
--- a/internal/sandbox/testdata/printargs.go
+++ b/internal/sandbox/testdata/printargs.go
@@ -5,8 +5,9 @@
//go:build ignore
// This program prints its arguments and exits.
+// If an argument begins with a "$", it prints
+// the value of the environment variable instead.
// It is used for testing the sandbox package.
-
package main
import (
@@ -17,6 +18,10 @@
func main() {
fmt.Printf("args:\n")
for i, arg := range os.Args[1:] {
- fmt.Printf("%d: %q\n", i, arg)
+ val := arg
+ if len(arg) > 0 && arg[0] == '$' {
+ val = os.Getenv(arg[1:])
+ }
+ fmt.Printf("%d: %q\n", i, val)
}
}