veyron/lib/flags,veyron/lib/exec: pipe parent config opts to child's flags parse
This change adds a way to override flags in the child via the parent config object passed through the vanadium exec mechanism.
Specifically, lib/flags.Parse gets a new argument (config), which overrides/adds
flag values after parsing the command-line args. The runtime grabs the config from the exec handle and passes it to Parse.
Sundry test cases to test the new logic added.
Change-Id: Ied173b770e375d6d36e5de8076219e20bd682fba
diff --git a/lib/exec/child.go b/lib/exec/child.go
index 72678d9..80ebfd2 100644
--- a/lib/exec/child.go
+++ b/lib/exec/child.go
@@ -55,6 +55,11 @@
return childHandle, childHandleErr
}
+// TODO(caprita): There's nothing preventing SetReady and SetFailed from being
+// called multiple times (e.g. from different instances of the runtime
+// intializing themselves). This results in errors for all but the first
+// invocation. Should we instead run these with sync.Once?
+
// SetReady writes a 'ready' status to its parent.
func (c *ChildHandle) SetReady() error {
_, err := c.statusPipe.Write([]byte(readyStatus))
diff --git a/lib/exec/config.go b/lib/exec/config.go
index aae2c26..52c622f 100644
--- a/lib/exec/config.go
+++ b/lib/exec/config.go
@@ -38,6 +38,8 @@
// values for keys that already exist and creating new key-value pairs
// for keys that don't.
MergeFrom(string) error
+ // Dump returns the config information as a map from ket to value.
+ Dump() map[string]string
}
type cfg struct {
@@ -66,6 +68,16 @@
return v, nil
}
+func (c cfg) Dump() (res map[string]string) {
+ res = make(map[string]string)
+ c.RLock()
+ defer c.RUnlock()
+ for k, v := range c.m {
+ res[k] = v
+ }
+ return
+}
+
func (c cfg) Clear(key string) {
c.Lock()
defer c.Unlock()
diff --git a/lib/exec/config_test.go b/lib/exec/config_test.go
index 2580078..cfd2637 100644
--- a/lib/exec/config_test.go
+++ b/lib/exec/config_test.go
@@ -1,7 +1,9 @@
package exec
import (
+ "reflect"
"testing"
+
"v.io/core/veyron2/verror2"
)
@@ -29,6 +31,9 @@
checkPresent(t, c, "foo", "baz")
c.Clear("foo")
checkAbsent(t, c, "foo")
+ if want, got := map[string]string{}, c.Dump(); !reflect.DeepEqual(want, got) {
+ t.Errorf("Expected %v for Dump, got %v instead", want, got)
+ }
}
// TestSerialize checks that serializing the config and merging from a
@@ -65,4 +70,7 @@
checkPresent(t, readC, "k2", "v2")
checkPresent(t, readC, "k3", "v3")
checkPresent(t, readC, "k4", "v4")
+ if want, got := map[string]string{"k1": "newv1", "k2": "v2", "k3": "v3", "k4": "v4"}, readC.Dump(); !reflect.DeepEqual(want, got) {
+ t.Errorf("Expected %v for Dump, got %v instead", want, got)
+ }
}