From 73980f9c73e8e64bf985363967aed4d7095b666c Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 14 Mar 2017 12:05:07 +1000 Subject: [PATCH] save the elided cmdline into an env var Signed-off-by: Sven Dowideit --- config/disk.go | 43 +++++++++++++++++-- docs/os/running-rancheros/server/pxe/index.md | 2 + scripts/build-images | 4 +- scripts/tar-images | 4 ++ tests/cmdline_test.go | 28 +++++++++++- 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/config/disk.go b/config/disk.go index 57927e4f..c367012e 100755 --- a/config/disk.go +++ b/config/disk.go @@ -5,6 +5,7 @@ import ( "os" "path" "path/filepath" + "reflect" "sort" "strings" @@ -48,6 +49,7 @@ func loadRawDiskConfig(dirPrefix string, full bool) map[interface{}]interface{} func loadRawConfig(dirPrefix string, full bool) map[interface{}]interface{} { rawCfg := loadRawDiskConfig(dirPrefix, full) rawCfg = util.Merge(rawCfg, readCmdline()) + rawCfg = util.Merge(rawCfg, readElidedCmdline(rawCfg)) rawCfg = applyDebugFlags(rawCfg) return mergeMetadata(rawCfg, readMetadata()) } @@ -69,13 +71,31 @@ func LoadConfigWithPrefix(dirPrefix string) *CloudConfig { return cfg } +func Insert(m interface{}, args ...interface{}) interface{} { + // TODO: move to util.go + if len(args)%2 != 0 { + panic("must have pairs of keys and values") + } + mv := reflect.ValueOf(m) + if mv.IsNil() { + mv = reflect.MakeMap(mv.Type()) + } + for i := 0; i < len(args); i += 2 { + mv.SetMapIndex(reflect.ValueOf(args[i]), reflect.ValueOf(args[i+1])) + } + return mv.Interface() +} + func SaveInitCmdline(cmdLineArgs string) { - log.Infof("INITINIT: %s", cmdLineArgs) - elidedCfg := parseCmdline(cmdLineArgs) - log.Infof("SaveInitCmdline: %#v", elidedCfg) - if err := WriteToFile(elidedCfg, CloudConfigInitFile); err != nil { + env := Insert(make(map[interface{}]interface{}), interface{}("EXTRA_CMDLINE"), interface{}(cmdLineArgs)) + rancher := Insert(make(map[interface{}]interface{}), interface{}("environment"), env) + newCfg := Insert(elidedCfg, interface{}("rancher"), rancher) + // make it easy for readElidedCmdline(rawCfg) + newCfg = Insert(newCfg, interface{}("EXTRA_CMDLINE"), interface{}(cmdLineArgs)) + + if err := WriteToFile(newCfg, CloudConfigInitFile); err != nil { log.Errorf("Failed to write init-cmdline config: %s", err) } } @@ -171,6 +191,20 @@ func readMetadata() datasource.Metadata { return metadata } +func readElidedCmdline(rawCfg map[interface{}]interface{}) map[interface{}]interface{} { + + for k, v := range rawCfg { + if key, _ := k.(string); key == "EXTRA_CMDLINE" { + if val, ok := v.(string); ok { + cmdLineObj := parseCmdline(strings.TrimSpace(util.UnescapeKernelParams(string(val)))) + + return cmdLineObj + } + } + } + return nil +} + func readCmdline() map[interface{}]interface{} { cmdLine, err := ioutil.ReadFile("/proc/cmdline") if err != nil { @@ -241,6 +275,7 @@ func readConfigs(bytes []byte, substituteMetadataVars, returnErr bool, files ... left := make(map[interface{}]interface{}) metadata := readMetadata() for _, file := range files { + //os.Stderr.WriteString(fmt.Sprintf("READCONFIGS(%s)", file)) content, err := readConfigFile(file) if err != nil { if returnErr { diff --git a/docs/os/running-rancheros/server/pxe/index.md b/docs/os/running-rancheros/server/pxe/index.md index 2331cd17..f9a7f517 100644 --- a/docs/os/running-rancheros/server/pxe/index.md +++ b/docs/os/running-rancheros/server/pxe/index.md @@ -29,6 +29,8 @@ For example, the `kernel` line above could be written as: kernel ${base-url}/vmlinuz rancher.state.dev=LABEL=RANCHER_STATE rancher.state.autoformat=[/dev/sda] -- rancher.cloud_init.datasources=[url:http://example.com/cloud-config] ``` +The hidden part of the command line can be accessed with either `sudo ros config get rancher.environment.EXTRA_CMDLINE`, or by using a service file's environment array. + ### cloud-init Datasources diff --git a/scripts/build-images b/scripts/build-images index a3d677c2..8353870e 100755 --- a/scripts/build-images +++ b/scripts/build-images @@ -14,7 +14,7 @@ touch dist/images for i in $BASE/[0-9]*; do name="os-$(echo ${i} | cut -f2 -d-)" tag="${OS_REPO}/${name}:${VERSION}${SUFFIX}" - echo Building ${tag} + echo "build-image: Building ${tag}" if [ -x ${i}/prebuild.sh ]; then ${i}/prebuild.sh fi @@ -28,3 +28,5 @@ for i in $BASE/[0-9]*; do echo "WARN: Skipping ${tag}" fi done + +echo "build-image: DONE" diff --git a/scripts/tar-images b/scripts/tar-images index 93b3afdd..dc1b0563 100755 --- a/scripts/tar-images +++ b/scripts/tar-images @@ -4,10 +4,14 @@ set -e cd $(dirname $0)/.. IMAGES=$(bin/host_ros c images -i build/initrd/usr/share/ros/os-config.yml) +echo "tar-image: IMAGES=$IMAGES" for i in $IMAGES; do + echo "tar-image: pull($i)" if [ "${FORCE_PULL}" = "1" ] || ! docker inspect $i >/dev/null 2>&1; then docker pull $i fi done +echo "tar-images: docker save ${IMAGES} > build/images.tar" docker save ${IMAGES} > build/images.tar +echo "tar-images: DONE" diff --git a/tests/cmdline_test.go b/tests/cmdline_test.go index ae53dbb4..14fbffc2 100755 --- a/tests/cmdline_test.go +++ b/tests/cmdline_test.go @@ -1,15 +1,39 @@ package integration import . "gopkg.in/check.v1" +import "fmt" func (s *QemuSuite) TestElideCmdLine(c *C) { + extra := "cc.hostname=nope rancher.password=three" runArgs := []string{ "--fresh", + "--append", + "cc.something=yes rancher.password=two", "--append-init", - "cc.hostname=nope rancher.debug=true", + extra, } s.RunQemuWith(c, runArgs...) s.CheckOutput(c, "nope\n", Equals, "hostname") - s.CheckOutput(c, "printk.devkmsg=on rancher.debug=true rancher.password=rancher console=ttyS0 rancher.autologin=ttyS0 rancher.state.dev=LABEL=RANCHER_STATE rancher.state.autoformat=[/dev/sda,/dev/vda] rancher.rm_usr -- \n", Equals, "cat /proc/cmdline") + s.CheckOutput(c, + "printk.devkmsg=on rancher.debug=true rancher.password=rancher console=ttyS0 rancher.autologin=ttyS0 cc.something=yes rancher.password=two rancher.state.dev=LABEL=RANCHER_STATE rancher.state.autoformat=[/dev/sda,/dev/vda] rancher.rm_usr -- \n", + Equals, + "cat /proc/cmdline", + ) + s.CheckOutput(c, + fmt.Sprintf("/init %s\n", extra), + Equals, + "sudo ros config get rancher.environment.EXTRA_CMDLINE", + ) + // TODO: it seems that rancher.password and rancher.autologin are in `ros config export`, but accessible as `ros config get` + s.CheckOutput(c, "\n", Equals, "sudo ros config get rancher.password") + s.CheckOutput(c, + "EXTRA_CMDLINE: /init cc.hostname=nope rancher.password=three\n"+ + " EXTRA_CMDLINE: /init cc.hostname=nope rancher.password=three\n"+ + " password: three\n", + Equals, + "sudo ros config export | grep password", + ) + + // And then add a service.yml file example. }