You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ra...@apache.org on 2019/08/29 14:19:25 UTC
[openwhisk-runtime-go] branch master updated: Adds support for
initialization parameters. (#97)
This is an automated email from the ASF dual-hosted git repository.
rabbah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwhisk-runtime-go.git
The following commit(s) were added to refs/heads/master by this push:
new 555130c Adds support for initialization parameters. (#97)
555130c is described below
commit 555130ccbf70517ccbab23fdff611c79984ef0af
Author: Michele Sciabarra <30...@users.noreply.github.com>
AuthorDate: Thu Aug 29 16:19:20 2019 +0200
Adds support for initialization parameters. (#97)
---
common/gobuild.py.launcher.go | 1 -
examples/Makefile | 17 ++++++++++++
examples/bash-hello/Makefile | 17 ++++++++++++
examples/benchmark/Makefile | 17 ++++++++++++
examples/golang-hello-single/Makefile | 17 ++++++++++++
examples/golang-hello-vendor/Makefile | 17 ++++++++++++
examples/golang-main-package/Makefile | 17 ++++++++++++
examples/golang-main-single/Makefile | 19 +++++++++++++-
examples/golang-main-standalone/Makefile | 19 +++++++++++++-
examples/golang-main-vendor/Makefile | 17 ++++++++++++
openwhisk/_test/env.sh | 23 +++++++++++++++++
openwhisk/actionProxy.go | 22 +++++++++++++++-
openwhisk/actionProxy_test.go | 19 ++++++++++++++
openwhisk/executor.go | 7 ++---
openwhisk/executor_test.go | 30 +++++++++++++++++-----
openwhisk/initHandler.go | 11 +++++---
openwhisk/initHandler_test.go | 22 ++++++++++++++++
.../ActionLoopBasicGo12Tests.scala | 12 +++++++++
.../actionContainers/ActionLoopBasicGoTests.scala | 12 +++++++++
19 files changed, 300 insertions(+), 16 deletions(-)
diff --git a/common/gobuild.py.launcher.go b/common/gobuild.py.launcher.go
index 382b052..386c126 100644
--- a/common/gobuild.py.launcher.go
+++ b/common/gobuild.py.launcher.go
@@ -80,7 +80,6 @@ func main() {
log.Printf("%v\n", input)
}
// set environment variables
- err = json.Unmarshal(inbuf, &input)
for k, v := range input {
if k == "value" {
continue
diff --git a/examples/Makefile b/examples/Makefile
index 538ec75..50124b1 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
# prefix
IMAGES?=openwhisk
diff --git a/examples/bash-hello/Makefile b/examples/bash-hello/Makefile
index fe470ce..91948ca 100644
--- a/examples/bash-hello/Makefile
+++ b/examples/bash-hello/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
WSK?=wsk
OW_USER?=openwhisk
OW_RUNTIME?=$(OW_USER)/actionloop-base
diff --git a/examples/benchmark/Makefile b/examples/benchmark/Makefile
index 22a03f4..61e6bd5 100644
--- a/examples/benchmark/Makefile
+++ b/examples/benchmark/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
IMG?=whisk/actionloop-golang-v1.11
IMG2?=whisk/actionloop
diff --git a/examples/golang-hello-single/Makefile b/examples/golang-hello-single/Makefile
index 0d43f92..77a465d 100644
--- a/examples/golang-hello-single/Makefile
+++ b/examples/golang-hello-single/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
OW_USER?=openwhisk
OW_RUNTIME?=$(OW_USER)/actionloop-base
OW_COMPILER?=$(OW_USER)/actionloop-golang-v1.11
diff --git a/examples/golang-hello-vendor/Makefile b/examples/golang-hello-vendor/Makefile
index 66aa089..071cc18 100644
--- a/examples/golang-hello-vendor/Makefile
+++ b/examples/golang-hello-vendor/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
OW_USER?=openwhisk
OW_RUNTIME?=$(OW_USER)/actionloop-base
OW_COMPILER?=$(OW_USER)/actionloop-golang-v1.11
diff --git a/examples/golang-main-package/Makefile b/examples/golang-main-package/Makefile
index 59da7c2..8cafe1d 100644
--- a/examples/golang-main-package/Makefile
+++ b/examples/golang-main-package/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
OW_USER?=openwhisk
OW_RUNTIME?=$(OW_USER)/actionloop-base
OW_COMPILER?=$(OW_USER)/actionloop-golang-v1.11
diff --git a/examples/golang-main-single/Makefile b/examples/golang-main-single/Makefile
index 5296b8d..6207c41 100644
--- a/examples/golang-main-single/Makefile
+++ b/examples/golang-main-single/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
OW_USER?=openwhisk
OW_RUNTIME?=$(OW_USER)/actionloop-base
OW_COMPILER?=$(OW_USER)/actionloop-golang-v1.11
@@ -32,4 +49,4 @@ package.done:
$(WSK) package update $(PACKAGE)
touch package.done
-.PHONY: deploy devel test clean
\ No newline at end of file
+.PHONY: deploy devel test clean
diff --git a/examples/golang-main-standalone/Makefile b/examples/golang-main-standalone/Makefile
index e6ddcd7..cf33efd 100644
--- a/examples/golang-main-standalone/Makefile
+++ b/examples/golang-main-standalone/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
OW_USER?=openwhisk
OW_RUNTIME?=$(OW_USER)/actionloop-base
OW_COMPILER?=$(OW_USER)/actionloop-golang-v1.11
@@ -32,4 +49,4 @@ package.done:
$(WSK) package update $(PACKAGE)
touch package.done
-.PHONY: deploy test clean
\ No newline at end of file
+.PHONY: deploy test clean
diff --git a/examples/golang-main-vendor/Makefile b/examples/golang-main-vendor/Makefile
index 1c3d7ce..933858c 100644
--- a/examples/golang-main-vendor/Makefile
+++ b/examples/golang-main-vendor/Makefile
@@ -1,3 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
OW_USER?=openwhisk
OW_RUNTIME?=$(OW_USER)/actionloop-base
OW_COMPILER?=$(OW_USER)/actionloop-golang-v1.11
diff --git a/openwhisk/_test/env.sh b/openwhisk/_test/env.sh
new file mode 100755
index 0000000..1d0680b
--- /dev/null
+++ b/openwhisk/_test/env.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+while read line
+do echo '{ "env": "'$(env | grep TEST_ | sort)'"}' >&3
+done
+
+
diff --git a/openwhisk/actionProxy.go b/openwhisk/actionProxy.go
index 22bb31c..e922e66 100644
--- a/openwhisk/actionProxy.go
+++ b/openwhisk/actionProxy.go
@@ -18,6 +18,7 @@
package openwhisk
import (
+ "encoding/json"
"fmt"
"io"
"io/ioutil"
@@ -48,6 +49,9 @@ type ActionProxy struct {
// out and err files
outFile *os.File
errFile *os.File
+
+ // environment
+ env map[string]string
}
// NewActionProxy creates a new action proxy that can handle http requests
@@ -61,6 +65,22 @@ func NewActionProxy(baseDir string, compiler string, outFile *os.File, errFile *
nil,
outFile,
errFile,
+ map[string]string{},
+ }
+}
+
+//SetEnv sets the environment
+func (ap *ActionProxy) SetEnv(env map[string]interface{}) {
+ for k, v := range env {
+ s, ok := v.(string)
+ if ok {
+ ap.env[k] = s
+ continue
+ }
+ buf, err := json.Marshal(v)
+ if err == nil {
+ ap.env[k] = string(buf)
+ }
}
}
@@ -84,7 +104,7 @@ func (ap *ActionProxy) StartLatestAction() error {
// try to launch the action
executable := fmt.Sprintf("%s/%d/bin/exec", ap.baseDir, highestDir)
os.Chmod(executable, 0755)
- newExecutor := NewExecutor(ap.outFile, ap.errFile, executable)
+ newExecutor := NewExecutor(ap.outFile, ap.errFile, executable, ap.env)
Debug("starting %s", executable)
err := newExecutor.Start()
if err == nil {
diff --git a/openwhisk/actionProxy_test.go b/openwhisk/actionProxy_test.go
index 31901c0..2fdbd06 100644
--- a/openwhisk/actionProxy_test.go
+++ b/openwhisk/actionProxy_test.go
@@ -19,6 +19,7 @@ package openwhisk
import (
"bytes"
+ "encoding/json"
"fmt"
"io/ioutil"
"log"
@@ -123,5 +124,23 @@ func Example_compile_src() {
// ./action/c2/out/action/action/main.py
// ./action/c2/out/action/exec.py
// ./action/c2/out/exec
+}
+
+func Example_SetEnv() {
+ ap := NewActionProxy("", "", nil, nil)
+ fmt.Println(ap.env)
+ var m map[string]interface{}
+ json.Unmarshal([]byte(`{
+ "s": "string",
+ "n": 123,
+ "a": [1,2,3],
+ "o": {"a":1,"b":2}
+ }`), &m)
+ log.Println(m)
+ ap.SetEnv(m)
+ fmt.Println(ap.env["a"], ap.env["o"], ap.env["s"], ap.env["n"])
+ // Output:
+ // map[]
+ // [1,2,3] {"a":1,"b":2} string 123
}
diff --git a/openwhisk/executor.go b/openwhisk/executor.go
index 06d875c..707018d 100644
--- a/openwhisk/executor.go
+++ b/openwhisk/executor.go
@@ -44,12 +44,13 @@ type Executor struct {
// NewExecutor creates a child subprocess using the provided command line,
// writing the logs in the given file.
// You can then start it getting a communication channel
-func NewExecutor(logout *os.File, logerr *os.File, command string, args ...string) (proc *Executor) {
+func NewExecutor(logout *os.File, logerr *os.File, command string, env map[string]string, args ...string) (proc *Executor) {
cmd := exec.Command(command, args...)
cmd.Stdout = logout
cmd.Stderr = logerr
- cmd.Env = []string{
- "__OW_API_HOST=" + os.Getenv("__OW_API_HOST"),
+ cmd.Env = []string{}
+ for k, v := range env {
+ cmd.Env = append(cmd.Env, k+"="+v)
}
Debug("env: %v", cmd.Env)
if Debugging {
diff --git a/openwhisk/executor_test.go b/openwhisk/executor_test.go
index 6ab5bd7..93702ad 100644
--- a/openwhisk/executor_test.go
+++ b/openwhisk/executor_test.go
@@ -21,21 +21,23 @@ import (
"io/ioutil"
)
+var m = map[string]string{}
+
func ExampleNewExecutor_failed() {
log, _ := ioutil.TempFile("", "log")
- proc := NewExecutor(log, log, "true")
+ proc := NewExecutor(log, log, "true", m)
err := proc.Start()
fmt.Println(err)
proc.Stop()
- proc = NewExecutor(log, log, "/bin/pwd")
+ proc = NewExecutor(log, log, "/bin/pwd", m)
err = proc.Start()
fmt.Println(err)
proc.Stop()
- proc = NewExecutor(log, log, "donotexist")
+ proc = NewExecutor(log, log, "donotexist", m)
err = proc.Start()
fmt.Println(err)
proc.Stop()
- proc = NewExecutor(log, log, "/etc/passwd")
+ proc = NewExecutor(log, log, "/etc/passwd", m)
err = proc.Start()
fmt.Println(err)
proc.Stop()
@@ -48,7 +50,7 @@ func ExampleNewExecutor_failed() {
func ExampleNewExecutor_bc() {
log, _ := ioutil.TempFile("", "log")
- proc := NewExecutor(log, log, "_test/bc.sh")
+ proc := NewExecutor(log, log, "_test/bc.sh", m)
err := proc.Start()
fmt.Println(err)
res, _ := proc.Interact([]byte("2+2"))
@@ -64,7 +66,7 @@ func ExampleNewExecutor_bc() {
func ExampleNewExecutor_hello() {
log, _ := ioutil.TempFile("", "log")
- proc := NewExecutor(log, log, "_test/hello.sh")
+ proc := NewExecutor(log, log, "_test/hello.sh", m)
err := proc.Start()
fmt.Println(err)
res, _ := proc.Interact([]byte(`{"value":{"name":"Mike"}}`))
@@ -78,3 +80,19 @@ func ExampleNewExecutor_hello() {
// XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
// XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
}
+
+func ExampleNewExecutor_env() {
+ log, _ := ioutil.TempFile("", "log")
+ proc := NewExecutor(log, log, "_test/env.sh", map[string]string{"TEST_HELLO": "WORLD", "TEST_HI": "ALL"})
+ err := proc.Start()
+ fmt.Println(err)
+ res, _ := proc.Interact([]byte(`{"value":{"name":"Mike"}}`))
+ fmt.Printf("%s", res)
+ proc.Stop()
+ dump(log)
+ // Output:
+ // <nil>
+ // { "env": "TEST_HELLO=WORLD TEST_HI=ALL"}
+ // XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+ // XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+}
diff --git a/openwhisk/initHandler.go b/openwhisk/initHandler.go
index 1929c4f..0664508 100644
--- a/openwhisk/initHandler.go
+++ b/openwhisk/initHandler.go
@@ -29,9 +29,10 @@ import (
)
type initBodyRequest struct {
- Code string `json:"code,omitempty"`
- Binary bool `json:"binary,omitempty"`
- Main string `json:"main,omitempty"`
+ Code string `json:"code,omitempty"`
+ Binary bool `json:"binary,omitempty"`
+ Main string `json:"main,omitempty"`
+ Env map[string]interface{} `json:"env,omitempty"`
}
type initRequest struct {
@@ -90,6 +91,10 @@ func (ap *ActionProxy) initHandler(w http.ResponseWriter, r *http.Request) {
return
}
+ // passing the env to the action proxy
+ ap.SetEnv(request.Value.Env)
+
+ // setting main
main := request.Value.Main
if main == "" {
main = "main"
diff --git a/openwhisk/initHandler_test.go b/openwhisk/initHandler_test.go
index c76a86c..e18edd7 100644
--- a/openwhisk/initHandler_test.go
+++ b/openwhisk/initHandler_test.go
@@ -18,6 +18,7 @@
package openwhisk
import (
+ "encoding/json"
"fmt"
"path/filepath"
)
@@ -243,3 +244,24 @@ func Example_zip_init() {
// XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
// XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
}
+
+func Example_parse_env() {
+ var request initBodyRequest
+ body := []byte(`{"code":"code"}`)
+ json.Unmarshal(body, &request)
+ fmt.Println(request.Env)
+
+ var request1 initBodyRequest
+ body = []byte(`{"code":"code", "env":{"hello":"world"}}`)
+ json.Unmarshal(body, &request1)
+ fmt.Println(request1.Env["hello"])
+
+ var request2 initBodyRequest
+ body = []byte(`{"code":"code", "env": { "hello": "world", "hi": "all"}}`)
+ json.Unmarshal(body, &request2)
+ fmt.Println(request2.Env["hello"], request2.Env["hi"])
+ // Output:
+ // map[]
+ // world
+ // world all
+}
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGo12Tests.scala b/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGo12Tests.scala
index 7c38472..15ca741 100644
--- a/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGo12Tests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGo12Tests.scala
@@ -100,6 +100,18 @@ class ActionLoopBasicGo12Tests
|}
""".stripMargin)
+ override val testEnvParameters = TestConfig(
+ """
+ |package main
+ |import "os"
+ |func Main(args map[string]interface{}) map[string]interface{} {
+ | res := make(map[string]interface{})
+ | res["SOME_VAR"] = os.Getenv("SOME_VAR")
+ | res["ANOTHER_VAR"] = os.Getenv("ANOTHER_VAR")
+ | return res
+ |}
+ """.stripMargin)
+
override val testInitCannotBeCalledMoreThanOnce = TestConfig(
"""|package main
|func Main(args map[string]interface{}) map[string]interface{} {
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGoTests.scala b/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGoTests.scala
index bfb31e4..d485ada 100644
--- a/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGoTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGoTests.scala
@@ -100,6 +100,18 @@ class ActionLoopBasicGoTests
|}
""".stripMargin)
+ override val testEnvParameters = TestConfig(
+ """
+ |package main
+ |import "os"
+ |func Main(args map[string]interface{}) map[string]interface{} {
+ | res := make(map[string]interface{})
+ | res["SOME_VAR"] = os.Getenv("SOME_VAR")
+ | res["ANOTHER_VAR"] = os.Getenv("ANOTHER_VAR")
+ | return res
+ |}
+ """.stripMargin)
+
override val testInitCannotBeCalledMoreThanOnce = TestConfig(
"""|package main
|func Main(args map[string]interface{}) map[string]interface{} {