Skip to content

Commit

Permalink
wasi: Support sharing envvar to container
Browse files Browse the repository at this point in the history
Signed-off-by: Kohei Tokunaga <[email protected]>
  • Loading branch information
ktock committed Sep 2, 2023
1 parent cabdb37 commit b90592f
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 3 deletions.
2 changes: 2 additions & 0 deletions cmd/init/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ func patchSpec(s runtimespec.Spec, infoD []byte, imageConfig imagespec.Image) ru
args = append(args, strings.ReplaceAll(string(o[prev:]), "\\ ", " "))
case "e":
entrypoint = []string{o}
case "env":
s.Process.Env = append(s.Process.Env, o)
default:
log.Printf("unsupported prefix: %q", inst)
}
Expand Down
43 changes: 43 additions & 0 deletions patches/bochs/Bochs/bochs/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#ifdef WASI
#include <wizer.h>
#include <wasi/libc-environ.h>
extern "C" {
#include "jmp.h"
}
Expand Down Expand Up @@ -382,6 +383,34 @@ int write_args(FSVirtFile *f, int argc, char **argv, int optind, int pos1)
return pos - pos1;
}

int write_env(FSVirtFile *f, int pos1, const char *env)
{
int p, pos = pos1;

p = write_info(f, pos, 5, "env: ");
if (p < 0) {
return -1;
}
pos += p;
for (int j = 0; j < strlen(env); j++) {
if (env[j] == '\n') {
p = write_info(f, pos, 2, "\\\n");
if (p != 2) {
return -1;
}
pos += p;
continue;
}
if (putchar_info(f, pos++, env[j]) != 1) {
return -1;
}
}
if (putchar_info(f, pos++, '\n') != 1) {
return -1;
}
return pos - pos1;
}

static struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "no-stdin", no_argument },
Expand Down Expand Up @@ -465,6 +494,19 @@ int init_wasi_info(int argc, char **argv, FSVirtFile *info)
pos += p;
}

#ifdef WASI
// TODO: support emscripten; it seems some default variables are passed, which shouldn't be inherited by the container.
// https://github.com/emscripten-core/emscripten/blob/0566a76b500bd2bbd535e108f657fce1db7f6f75/src/library_wasi.js#L62
for (char **env = environ; *env; ++env) {
int p = write_env(info, pos, *env);
if (p < 0) {
printf("failed to prepare env info\n");
exit(1);
}
pos += p;
}
#endif

info->len = pos;
#ifdef WASI
info->len += write_preopen_info(info, pos);
Expand Down Expand Up @@ -752,6 +794,7 @@ int CDECL start_vm(void)
int CDECL main(int argc, char *argv[])
{
#ifdef WASI
__wasilibc_ensure_environ();
__wasi_vfs_rt_init();
if (populate_preopens() != 0) { // register wasi-vfs dir to wasi-libc and our list
fprintf(stderr, "failed to populate preopens");
Expand Down
43 changes: 43 additions & 0 deletions patches/tinyemu/tinyemu/temu.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
#include "wasi.h"
#endif

extern char **environ;

#ifdef ON_BROWSER
#include <emscripten.h>
#endif
Expand Down Expand Up @@ -918,6 +920,34 @@ int write_args(FSVirtFile *f, int argc, char **argv, int optind, int pos1)
return pos - pos1;
}

int write_env(FSVirtFile *f, int pos1, const char *env)
{
int p, pos = pos1;

p = write_info(f, pos, 5, "env: ");
if (p < 0) {
return -1;
}
pos += p;
for (int j = 0; j < strlen(env); j++) {
if (env[j] == '\n') {
p = write_info(f, pos, 2, "\\\n");
if (p != 2) {
return -1;
}
pos += p;
continue;
}
if (putchar_info(f, pos++, env[j]) != 1) {
return -1;
}
}
if (putchar_info(f, pos++, '\n') != 1) {
return -1;
}
return pos - pos1;
}

int main(int argc, char **argv)
{
#ifdef WASI
Expand Down Expand Up @@ -984,6 +1014,19 @@ int main(int argc, char **argv)
pos += p;
}

#ifdef WASI
// TODO: support emscripten; it seems some default variables are passed, which shouldn't be inherited by the container.
// https://github.com/emscripten-core/emscripten/blob/0566a76b500bd2bbd535e108f657fce1db7f6f75/src/library_wasi.js#L62
for (char **env = environ; *env; ++env) {
int p = write_env(info, pos, *env);
if (p < 0) {
printf("failed to prepare env info\n");
exit(1);
}
pos += p;
}
#endif

info->len = pos;
#ifdef WASI
info->len += write_preopen_info(info, pos);
Expand Down
2 changes: 2 additions & 0 deletions patches/tinyemu/tinyemu/wasi.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <string.h>

#include <wasi/libc.h>
#include <wasi/libc-environ.h>

#include "cutils.h"
#include "fs.h"
Expand Down Expand Up @@ -160,6 +161,7 @@ extern void __wasi_vfs_rt_init(void);

int init_wasi()
{
__wasilibc_ensure_environ();
__wasi_vfs_rt_init(); // initialize wasi-vfs
if (populate_preopens() != 0) { // register mapdir and wasi-vfs dir to wasi-libc and our list
fprintf(stderr, "failed to populate preopens");
Expand Down
15 changes: 15 additions & 0 deletions tests/integration/wamr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,20 @@ func TestWamr(t *testing.T) {
},
),
},
{
Name: "wamr-env",
Runtime: "iwasm",
Inputs: []utils.Input{
{Image: "alpine:3.17", Architecture: utils.X86_64},
{Image: "riscv64/alpine:20221110", ConvertOpts: []string{"--target-arch=riscv64"}, Architecture: utils.RISCV64},
},
ImageName: "test2.wasm",
Prepare: func(t *testing.T, workdir string) {
assert.NilError(t, exec.Command("wamrc", "-o", filepath.Join(workdir, "test2.wasm"), filepath.Join(workdir, "test.wasm")).Run())
},
RuntimeOpts: utils.StringFlags("--env=AAA=hello", "--env=BBB=world"),
Args: utils.StringFlags("/bin/sh", "-c", "echo -n $AAA $BBB"),
Want: utils.WantString("hello world"),
},
}...)
}
15 changes: 15 additions & 0 deletions tests/integration/wasmedge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,20 @@ func TestWasmedge(t *testing.T) {
Args: utils.StringFlags("--no-stdin", "cat", "/map/dir/hi"),
Want: utils.WantString("teststring"),
},
{
Name: "wasmedge-env",
Runtime: "wasmedge",
Inputs: []utils.Input{
{Image: "alpine:3.17", Architecture: utils.X86_64},
{Image: "riscv64/alpine:20221110", ConvertOpts: []string{"--target-arch=riscv64"}, Architecture: utils.RISCV64},
},
ImageName: "test2.wasm",
Prepare: func(t *testing.T, workdir string) {
assert.NilError(t, exec.Command("wasmedgec", filepath.Join(workdir, "test.wasm"), filepath.Join(workdir, "test2.wasm")).Run())
},
RuntimeOpts: utils.StringFlags("--env=AAA=hello", "--env=BBB=world"),
Args: utils.StringFlags("--no-stdin", "/bin/sh", "-c", "echo -n $AAA $BBB"), // NOTE: stdin unsupported on wasmedge as of now
Want: utils.WantString("hello world"),
},
}...)
}
11 changes: 11 additions & 0 deletions tests/integration/wasmer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,16 @@ func TestWasmer(t *testing.T) {
Args: utils.StringFlags("--", "--no-stdin", "cat", "/mapped/dir/test/hi"),
Want: utils.WantString("teststring"),
},
{
Name: "wasmer-env",
Runtime: "wasmer",
Inputs: []utils.Input{
{Image: "alpine:3.17", Architecture: utils.X86_64},
{Image: "riscv64/alpine:20221110", ConvertOpts: []string{"--target-arch=riscv64"}, Architecture: utils.RISCV64},
},
RuntimeOpts: utils.StringFlags("--env=AAA=hello", "--env=BBB=world"),
Args: utils.StringFlags("--", "--no-stdin", "/bin/sh", "-c", "echo -n $AAA $BBB"), // wasmer requires "--" before flags we pass to the wasm program.
Want: utils.WantString("hello world"),
},
}...)
}
11 changes: 11 additions & 0 deletions tests/integration/wasmtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ func TestWasmtime(t *testing.T) {
[2]string{"echo -n hello > /mapped/dir/test/from-guest/testhello\n", ""},
),
},
{
Name: "wasmtime-env",
Runtime: "wasmtime",
Inputs: []utils.Input{
{Image: "alpine:3.17", Architecture: utils.X86_64},
{Image: "riscv64/alpine:20221110", ConvertOpts: []string{"--target-arch=riscv64"}, Architecture: utils.RISCV64},
},
RuntimeOpts: utils.StringFlags("--env=AAA=hello", "--env=BBB=world"),
Args: utils.StringFlags("/bin/sh", "-c", "echo -n $AAA $BBB"),
Want: utils.WantString("hello world"),
},
// Other architectures
{
Name: "wasmtime-hello-arch-aarch64",
Expand Down
11 changes: 11 additions & 0 deletions tests/integration/wazero_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,16 @@ func TestWazero(t *testing.T) {
[2]string{"echo -n hello > /mapdir/from-guest/testhello\n", ""},
),
},
{
Name: "wazero-env",
Runtime: "wazero-test",
Inputs: []utils.Input{
{Image: "alpine:3.17", Architecture: utils.X86_64},
{Image: "riscv64/alpine:20221110", ConvertOpts: []string{"--target-arch=riscv64"}, Architecture: utils.RISCV64},
},
RuntimeOpts: utils.StringFlags("--env=AAA=hello", "--env=BBB=world"),
Args: utils.StringFlags("/bin/sh", "-c", "echo -n $AAA $BBB"),
Want: utils.WantString("hello world"),
},
}...)
}
26 changes: 23 additions & 3 deletions tests/wazero/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
crand "crypto/rand"
"flag"
"fmt"
"os"
"strings"

Expand All @@ -15,6 +16,8 @@ func main() {
var (
mapDir = flag.String("mapdir", "", "directory mapping to the image")
)
var envs envFlags
flag.Var(&envs, "env", "environment variables")

flag.Parse()
args := flag.Args()
Expand All @@ -41,11 +44,28 @@ func main() {
if err != nil {
panic(err)
}
// we forcibly enable non-blocking read of stdin.
_, err = r.InstantiateModule(ctx, compiled,
wazero.NewModuleConfig().WithSysWalltime().WithSysNanotime().WithSysNanosleep().WithRandSource(crand.Reader).WithStdout(os.Stdout).WithStderr(os.Stderr).WithStdin(os.Stdin).WithFSConfig(fsConfig).WithArgs(append([]string{"arg0"}, args[1:]...)...))
conf := wazero.NewModuleConfig().WithSysWalltime().WithSysNanotime().WithSysNanosleep().WithRandSource(crand.Reader).WithStdout(os.Stdout).WithStderr(os.Stderr).WithStdin(os.Stdin).WithFSConfig(fsConfig).WithArgs(append([]string{"arg0"}, args[1:]...)...)
for _, v := range envs {
es := strings.SplitN(v, "=", 2)
if len(es) == 2 {
conf = conf.WithEnv(es[0], es[1])
} else {
panic("env must be a key value pair")
}
}
_, err = r.InstantiateModule(ctx, compiled, conf)
if err != nil {
panic(err)
}
return
}

type envFlags []string

func (i *envFlags) String() string {
return fmt.Sprintf("%v", []string(*i))
}
func (i *envFlags) Set(value string) error {
*i = append(*i, value)
return nil
}

0 comments on commit b90592f

Please sign in to comment.