Support environmental variables in Occlum.json
1. Now we support set App's env in Occlum.json, for example: "env": [ "OCCLUM=yes", "TEST=true" ] 2. Rewrite env test cases 3. Update Dockerfile to install "jq" tool
This commit is contained in:
parent
f37eb34038
commit
8ef52c7c2d
@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ffi::CString;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sgxfs::SgxFile;
|
||||
|
||||
@ -96,6 +97,7 @@ fn parse_mac(mac_str: &str) -> Result<sgx_aes_gcm_128bit_tag_t, Error> {
|
||||
pub struct Config {
|
||||
pub vm: ConfigVM,
|
||||
pub process: ConfigProcess,
|
||||
pub env: Vec<CString>,
|
||||
pub mount: Vec<ConfigMount>,
|
||||
}
|
||||
|
||||
@ -137,6 +139,13 @@ impl Config {
|
||||
fn from_input(input: &InputConfig) -> Result<Config, Error> {
|
||||
let vm = ConfigVM::from_input(&input.vm)?;
|
||||
let process = ConfigProcess::from_input(&input.process)?;
|
||||
let env = {
|
||||
let mut env = Vec::new();
|
||||
for input_env in &input.env {
|
||||
env.push(CString::new(input_env.clone())?);
|
||||
}
|
||||
env
|
||||
};
|
||||
let mount = {
|
||||
let mut mount = Vec::new();
|
||||
for input_mount in &input.mount {
|
||||
@ -144,7 +153,12 @@ impl Config {
|
||||
}
|
||||
mount
|
||||
};
|
||||
Ok(Config { vm, process, mount })
|
||||
Ok(Config {
|
||||
vm,
|
||||
process,
|
||||
env,
|
||||
mount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,6 +262,8 @@ struct InputConfig {
|
||||
#[serde(default)]
|
||||
pub process: InputConfigProcess,
|
||||
#[serde(default)]
|
||||
pub env: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub mount: Vec<InputConfigMount>,
|
||||
}
|
||||
|
||||
|
@ -76,11 +76,10 @@ fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> {
|
||||
// info!("boot: path: {:?}, argv: {:?}", path_str, argv);
|
||||
util::mpx_util::mpx_enable()?;
|
||||
|
||||
// The default environment variables
|
||||
let envp = vec![CString::new("OCCLUM=yes").unwrap()];
|
||||
let envp = &config::LIBOS_CONFIG.env;
|
||||
let file_actions = Vec::new();
|
||||
let parent = &process::IDLE_PROCESS;
|
||||
process::do_spawn(&path_str, argv, &envp, &file_actions, parent)?;
|
||||
process::do_spawn(&path_str, argv, envp, &file_actions, parent)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use prelude::*;
|
||||
use std::{convert, error, fmt};
|
||||
use std::{convert, error, ffi, fmt};
|
||||
|
||||
// TODO: remove errno.h
|
||||
|
||||
@ -31,6 +31,12 @@ impl convert::From<std::io::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl convert::From<std::ffi::NulError> for Error {
|
||||
fn from(info: std::ffi::NulError) -> Error {
|
||||
Error::new(Errno::EINVAL, "std::ffi::NulError")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
self.desc
|
||||
|
@ -36,7 +36,7 @@ all: build
|
||||
build: prebuild $(BUILD_TARGETS) postbuild
|
||||
|
||||
prebuild:
|
||||
@$(RM) -rf $(BUILD_DIR)/test/*
|
||||
@$(RM) -rf $(BUILD_DIR)/test
|
||||
@mkdir -p $(BUILD_DIR)/test
|
||||
@cd $(BUILD_DIR)/test && \
|
||||
$(PROJECT_DIR)/build/bin/occlum init
|
||||
@ -86,4 +86,4 @@ $(BENCH_TARGETS): bench-%: %
|
||||
#############################################################################
|
||||
|
||||
clean:
|
||||
@$(RM) -rf $(BUILD_DIR)/test/*
|
||||
@$(RM) -rf $(BUILD_DIR)/test
|
||||
|
@ -7,6 +7,10 @@
|
||||
"default_heap_size": "16MB",
|
||||
"default_mmap_size": "32MB"
|
||||
},
|
||||
"env": [
|
||||
"OCCLUM=yes",
|
||||
"TEST=true"
|
||||
],
|
||||
"mount": [
|
||||
{
|
||||
"target": "/",
|
||||
|
8
test/env/Makefile
vendored
8
test/env/Makefile
vendored
@ -6,9 +6,9 @@ ARG2 := arg2
|
||||
ARG3 := this is a string with spaces
|
||||
|
||||
EXTRA_C_FLAGS := \
|
||||
-DEXPECTED_ARGC=$(ARGC) \
|
||||
-DEXPECTED_ARG1="\"$(ARG1)\"" \
|
||||
-DEXPECTED_ARG2="\"$(ARG2)\"" \
|
||||
-DEXPECTED_ARG3="\"$(ARG3)\""
|
||||
-DEXPECT_ARGC=$(ARGC) \
|
||||
-DEXPECT_ARG1="\"$(ARG1)\"" \
|
||||
-DEXPECT_ARG2="\"$(ARG2)\"" \
|
||||
-DEXPECT_ARG3="\"$(ARG3)\""
|
||||
EXTRA_LINK_FLAGS :=
|
||||
BIN_ARGS := "$(ARG1)" "$(ARG2)" "$(ARG3)"
|
||||
|
200
test/env/main.c
vendored
200
test/env/main.c
vendored
@ -2,56 +2,200 @@
|
||||
#include <stdio.h>
|
||||
#include <elf.h>
|
||||
#include <errno.h>
|
||||
#include <spawn.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include "test.h"
|
||||
|
||||
// ============================================================================
|
||||
// Helper structs & variables & functions
|
||||
// ============================================================================
|
||||
|
||||
const char** g_argv;
|
||||
int g_argc;
|
||||
|
||||
// Expected arguments are given by Makefile throught macro ARGC, ARG1, ARG2 and
|
||||
// ARG3
|
||||
const char* expected_argv[EXPECTED_ARGC] = {
|
||||
const char* expect_argv[EXPECT_ARGC] = {
|
||||
"env",
|
||||
EXPECTED_ARG1,
|
||||
EXPECTED_ARG2,
|
||||
EXPECTED_ARG3,
|
||||
EXPECT_ARG1,
|
||||
EXPECT_ARG2,
|
||||
EXPECT_ARG3,
|
||||
};
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
// Test argc
|
||||
if (argc != EXPECTED_ARGC) {
|
||||
printf("ERROR: expect %d arguments, but %d are given\n", EXPECTED_ARGC, argc);
|
||||
return -1;
|
||||
}
|
||||
// Expected child arguments
|
||||
const int child_argc = 2;
|
||||
const char* child_argv[child_argc + 1] = {
|
||||
"env",
|
||||
"child",
|
||||
NULL
|
||||
};
|
||||
|
||||
// Test argv
|
||||
for (int arg_i = 0; arg_i < argc; arg_i++) {
|
||||
printf("arg[%d] = %s\n", arg_i, argv[arg_i]);
|
||||
const char* actual_arg = argv[arg_i];
|
||||
const char* expected_arg = expected_argv[arg_i];
|
||||
if (strcmp(actual_arg, expected_arg) != 0) {
|
||||
// Expected child environment variables
|
||||
const char* child_envp[] = {
|
||||
"ENV_CHILD=ok",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int test_argv_val(const char** expect_argv) {
|
||||
for (int arg_i = 0; arg_i < g_argc; arg_i++) {
|
||||
const char* actual_arg = *(g_argv + arg_i);
|
||||
const char* expect_arg = *(expect_argv + arg_i);
|
||||
if (strcmp(actual_arg, expect_arg) != 0) {
|
||||
printf("ERROR: expect argument %d is %s, but given %s\n",
|
||||
arg_i, expected_arg, actual_arg);
|
||||
arg_i, expect_arg, actual_arg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test envp
|
||||
// Occlum LibOS by default passes an environment OCCLUM=yes
|
||||
const char* env_val = getenv("OCCLUM");
|
||||
if (env_val == 0) {
|
||||
printf("ERROR: cannot find environment variable OCCLUM\n");
|
||||
static int test_env_val(const char* expect_env_key, const char* expect_env_val) {
|
||||
const char* actual_env_val = getenv(expect_env_key);
|
||||
if (actual_env_val == NULL) {
|
||||
printf("ERROR: cannot find %s\n", expect_env_key);
|
||||
return -1;
|
||||
}
|
||||
else if (strcmp(env_val, "yes") != 0) {
|
||||
printf("ERROR: environment variable OCCLUM=yes expected, but given %s\n",
|
||||
env_val);
|
||||
if (strcmp(actual_env_val, expect_env_val) != 0) {
|
||||
printf("ERROR: environment variable %s=%s expected, but given %s\n",
|
||||
expect_env_key, expect_env_val, actual_env_val);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test aux
|
||||
// ============================================================================
|
||||
// Test cases for argv
|
||||
// ============================================================================
|
||||
|
||||
static int test_env_getargv() {
|
||||
// Test argc
|
||||
if (g_argc != EXPECT_ARGC) {
|
||||
printf("ERROR: expect %d arguments, but %d are given\n", EXPECT_ARGC, g_argc);
|
||||
throw_error("arguments count is not expected");
|
||||
}
|
||||
// Test argv
|
||||
if (test_argv_val(expect_argv) < 0) {
|
||||
throw_error("argument variables are not expected");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test cases for aux
|
||||
// ============================================================================
|
||||
|
||||
static int test_env_getauxval() {
|
||||
unsigned long page_size = getauxval(AT_PAGESZ);
|
||||
if (errno != 0 || page_size != 4096) {
|
||||
printf("ERROR: auxilary vector does not pass correct the value\n");
|
||||
return -1;
|
||||
throw_error("auxilary vector does not pass correct the value");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test cases for env
|
||||
// ============================================================================
|
||||
|
||||
// The environment variables are specified in Occlum.json
|
||||
static int test_env_getenv() {
|
||||
if (test_env_val("OCCLUM", "yes") < 0) {
|
||||
throw_error("get environment variable failed");
|
||||
}
|
||||
|
||||
// Here we call getenv() again to make sure that
|
||||
// LibOS can handle several environment variables in Occlum.json correctly
|
||||
if (test_env_val("TEST", "true") < 0) {
|
||||
throw_error("get environment variable failed");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_env_set_child_env_and_argv() {
|
||||
int status, child_pid;
|
||||
int ret = posix_spawn(&child_pid,
|
||||
"/bin/env", NULL, NULL,
|
||||
(char *const *)child_argv,
|
||||
(char *const *)child_envp);
|
||||
if (ret < 0) {
|
||||
throw_error("spawn process error");
|
||||
}
|
||||
printf("Spawn a child process with pid=%d\n", child_pid);
|
||||
ret = wait4(-1, &status, 0, NULL);
|
||||
if (ret < 0) {
|
||||
throw_error("failed to wait4 the child process");
|
||||
}
|
||||
if (!WIFEXITED(status)) {
|
||||
throw_error("test cases in child faild");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Child Test cases for argv
|
||||
// ============================================================================
|
||||
|
||||
static int test_env_child_getargv() {
|
||||
// Test argc
|
||||
if (g_argc != child_argc) {
|
||||
printf("ERROR: expect %d arguments, but %d are given\n", child_argc, g_argc);
|
||||
throw_error("arguments count is not expected");
|
||||
}
|
||||
// Test argv
|
||||
if (test_argv_val(child_argv) < 0) {
|
||||
throw_error("argument variables are not expected");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Child Test cases for env
|
||||
// ============================================================================
|
||||
|
||||
#define ENV_SIZE (256)
|
||||
static int test_env_child_getenv() {
|
||||
char env_key[ENV_SIZE];
|
||||
char env_val[ENV_SIZE];
|
||||
for (int i = 0; child_envp[i] != NULL; ++i) {
|
||||
int num = sscanf(child_envp[i], "%[^=]=%s", env_key, env_val);
|
||||
if (num != 2) {
|
||||
throw_error("parse environment variable failed");
|
||||
}
|
||||
if (test_env_val(env_key, env_val) < 0) {
|
||||
throw_error("get environment variable failed");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test suite main
|
||||
// ============================================================================
|
||||
|
||||
static test_case_t test_cases[] = {
|
||||
TEST_CASE(test_env_getargv),
|
||||
TEST_CASE(test_env_getauxval),
|
||||
TEST_CASE(test_env_getenv),
|
||||
TEST_CASE(test_env_set_child_env_and_argv),
|
||||
};
|
||||
|
||||
static test_case_t child_test_cases[] = {
|
||||
TEST_CASE(test_env_getauxval),
|
||||
TEST_CASE(test_env_child_getargv),
|
||||
TEST_CASE(test_env_child_getenv),
|
||||
};
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
// Save argument for test cases
|
||||
g_argc = argc;
|
||||
g_argv = argv;
|
||||
// Test argc
|
||||
if (getpid() > 1) {
|
||||
return test_suite_run(child_test_cases, ARRAY_SIZE(child_test_cases));
|
||||
} else {
|
||||
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
|
||||
int client_pid;
|
||||
char* client_argv[] = {"client", "127.0.0.1"};
|
||||
char* client_argv[] = {"client", "127.0.0.1", NULL};
|
||||
ret = posix_spawn(&client_pid, "/bin/client", NULL, NULL, client_argv, NULL);
|
||||
if (ret < 0) {
|
||||
printf("spawn client process error: %s(errno: %d)\n", strerror(errno), errno);
|
||||
|
@ -65,7 +65,7 @@ main(int argc, char *argv[]) {
|
||||
|
||||
// spawn clients
|
||||
int client_pid;
|
||||
char* client_argv[] = {"client", "127.0.0.1"};
|
||||
char* client_argv[] = {"client", "127.0.0.1", NULL};
|
||||
for(int i=0; i<3; ++i) {
|
||||
int ret = posix_spawn(&client_pid, "/bin/client", NULL, NULL, client_argv, NULL);
|
||||
if (ret < 0) {
|
||||
|
@ -14,6 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
expect \
|
||||
gdb \
|
||||
git-core \
|
||||
jq \
|
||||
kmod \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
|
@ -103,7 +103,10 @@ cmd_build() {
|
||||
export OCCLUM_CONF_DEFAULT_MMAP_SIZE=`get_conf_default_mmap_size`
|
||||
cd "$context_dir/build"
|
||||
"$occlum_dir/build/bin/occlum-gen-default-occlum-json"\
|
||||
> "Occlum_new.json"
|
||||
jq -s '.[0] + .[1]' "../../Occlum.json" "Occlum_new.json"\
|
||||
> "Occlum.json"
|
||||
rm -f "Occlum_new.json"
|
||||
"$occlum_dir/build/bin/occlum-protect-integrity" protect Occlum.json
|
||||
|
||||
export OCCLUM_BUILTIN_CONF_FILE_MAC=`get_occlum_conf_file_mac`
|
||||
|
Loading…
Reference in New Issue
Block a user