diff --git a/lang/core/embedded/provisioner/main.mcl b/lang/core/embedded/provisioner/main.mcl index 70b1cf8b..87301a10 100644 --- a/lang/core/embedded/provisioner/main.mcl +++ b/lang/core/embedded/provisioner/main.mcl @@ -558,6 +558,7 @@ class base:host($name, $config) { $handoff_type = $config->handoff || "" $handoff_code = $config->handoff_code || "" + $handoff_module_path = $config->handoff_module_path || "" panic($handoff_code != "" and not strings.has_prefix($handoff_code, "/")) $handoff_hostname = $config->handoff_hostname || "" @@ -700,6 +701,7 @@ class base:host($name, $config) { tar "${abs_tar}" { inputs => [ $handoff_code, # code comes in here! + strings.trim_suffix($handoff_module_path, "/"), # remove trailing slash to include the dir name ], Before => Gzip["${abs_gz}"], @@ -717,6 +719,8 @@ class base:host($name, $config) { $firstboot_scripts_dir = "/var/lib/mgmt-firstboot/" # TODO: /usr/lib/ instead? $firstboot_done_dir = "/var/lib/mgmt-firstboot/done/" $deploy_dir = "/root/mgmt-deploy/" # deploy code dir + $modules_chunk = filepath.base(strings.trim_suffix($handoff_module_path, "/")) # "modules" typically + $deploy_dir_modules = "${deploy_dir}${modules_chunk}/" # TODO: we can customize these more precisely based on $handoff_type $handoff_packages = deploy.bootstrap_packages($distro) # TODO: catch errors here with || [] panic($handoff_type != "" and len($handoff_packages) == 0) @@ -760,7 +764,7 @@ class base:host($name, $config) { # passed into the provisioner. It's just now in a deploy subdir. # If it's a dir, then this becomes the empty strings. # XXX: The deploy could instead happen over the network to etcd. - "echo '#!/bin/bash' > ${firstboot_scripts_dir}mgmt-deploy.sh && echo '${handoff_binary_path} deploy lang --seeds=http://127.0.0.1:2379 --no-git ${deploy_dir}${handoff_code_chunk}' >> ${firstboot_scripts_dir}mgmt-deploy.sh && chmod u+x ${firstboot_scripts_dir}mgmt-deploy.sh" + "echo '#!/bin/bash' > ${firstboot_scripts_dir}mgmt-deploy.sh && echo '${handoff_binary_path} deploy lang --seeds=http://127.0.0.1:2379 --no-git --module-path=${deploy_dir_modules} ${deploy_dir}${handoff_code_chunk}' >> ${firstboot_scripts_dir}mgmt-deploy.sh && chmod u+x ${firstboot_scripts_dir}mgmt-deploy.sh" } # TODO: Do we want to signal an http:flag if we're a "default" host? diff --git a/lang/core/embedded/provisioner/provisioner.go b/lang/core/embedded/provisioner/provisioner.go index 3e6d8501..978e18d7 100644 --- a/lang/core/embedded/provisioner/provisioner.go +++ b/lang/core/embedded/provisioner/provisioner.go @@ -171,6 +171,10 @@ type localArgs struct { // static code deploy bolus. This is useful for isolated, one-time runs. HandoffCode string `arg:"--handoff-code" help:"code dir to handoff to host" func:"cli_handoff_code"` // eg: /etc/mgmt/ + // HandoffModulePath is the code handoff module path dir that we use. + // It's an absolute path on this local machine. (The provisioner!) + HandoffModulePath string `arg:"--handoff-module-path" help:"module path dir to use for handoff" func:"cli_handoff_module_path"` // eg: /etc/mgmt/modules/ + // HandoffHostname specifies that we want to handoff a hostname to set // on this machine. This is useful to make initial code handoff easier. HandoffHostname string `arg:"--handoff-hostname" help:"hostname to handoff to host" func:"cli_handoff_hostname"` // eg: server1 @@ -374,6 +378,35 @@ func (obj *provisioner) Customize(a interface{}) (*cli.RunArgs, error) { obj.init.Logf("packages: %+v", strings.Join(obj.localArgs.Packages, ",")) } + modulePathArgs := []string{} + if p := obj.localArgs.HandoffModulePath; p != "" { + if strings.HasPrefix(p, "~") { + expanded, err := util.ExpandHome(p) + if err != nil { + return nil, err + } + obj.localArgs.HandoffModulePath = expanded + } + + // Make path absolute. + if !strings.HasPrefix(obj.localArgs.HandoffModulePath, "/") { + dir, err := os.Getwd() + if err != nil { + return nil, err + } + dir = dir + "/" // dir's should have a trailing slash! + obj.localArgs.HandoffModulePath = dir + obj.localArgs.HandoffModulePath + } + + // Does this path actually exist? + if _, err := os.Stat(obj.localArgs.HandoffModulePath); err != nil { + return nil, err + } + + s := fmt.Sprintf("--module-path=%s", obj.localArgs.HandoffModulePath) + modulePathArgs = append(modulePathArgs, s) + } + if p := obj.localArgs.HandoffCode; p != "" { if strings.HasPrefix(p, "~") { expanded, err := util.ExpandHome(p) @@ -420,12 +453,17 @@ func (obj *provisioner) Customize(a interface{}) (*cli.RunArgs, error) { }, } // TODO: Add a --quiet flag instead of the above filter hack. - cmdArgs := []string{"run", "--tmp-prefix", "lang", "--only-unify", obj.localArgs.HandoffCode} + cmdArgs := []string{"run", "--tmp-prefix", "lang", "--only-unify"} + cmdArgs = append(cmdArgs, modulePathArgs...) + cmdArgs = append(cmdArgs, obj.localArgs.HandoffCode) if err := util.SimpleCmd(ctx, binary, cmdArgs, cmdOpts); err != nil { return nil, fmt.Errorf("handoff code didn't type check: %s", out) } obj.init.Logf("handoff: %s", obj.localArgs.HandoffCode) + if len(modulePathArgs) > 0 { + obj.init.Logf("handoff module path: %s", obj.localArgs.HandoffModulePath) + } } if h := obj.localArgs.HandoffHostname; h != "" { obj.init.Logf("handoff hostname: %s", h) diff --git a/lang/core/embedded/provisioner/top.mcl b/lang/core/embedded/provisioner/top.mcl index 9a1b6f15..770bde0b 100644 --- a/lang/core/embedded/provisioner/top.mcl +++ b/lang/core/embedded/provisioner/top.mcl @@ -79,6 +79,7 @@ include base.host("host0", struct{ # TODO: do we need a usable name anywhere? handoff => $handoff, # alternatively some code word or querystring #handoff_code => "/etc/mgmt/", # one way to do it handoff_code => provisioner.cli_handoff_code(), + handoff_module_path => provisioner.cli_handoff_module_path(), handoff_hostname => provisioner.cli_handoff_hostname(), bmc_uri => provisioner.cli_bmc_uri(), }) as host0