lang: core: embedded: provisioner: Implement handoff

Here's a good first way to implement handoff. What's particularly
elegant about handoff here, is that this is the first form of it I know,
where handoff happens between a provisioning tool and a configuration
management tool and those are the same tool! As a result, this can allow
for some really elegant integration, and the end-user never has to deal
with the combinatorial explosion of the N * M scenario of gluing each
provisioning tool to each different configuration management tool.

We'll have other forms of handoff in the future, but this simple
approach is useful already.
This commit is contained in:
James Shubin
2024-10-29 16:36:06 -04:00
parent 93eb8b2b76
commit 3c665174cc
3 changed files with 178 additions and 2 deletions

View File

@@ -167,6 +167,10 @@ type localArgs struct {
// other or the base installation packages.
Packages []string `arg:"--packages" help:"list of additional distro packages to install (comma separated)" func:"cli_packages"`
// HandoffCode specifies that we want to handoff to this machine with a
// 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/
// OnlyUnify tells the compiler to stop after type unification. This is
// used for testing.
OnlyUnify bool `arg:"--only-unify" help:"stop after type unification"`
@@ -362,6 +366,60 @@ func (obj *provisioner) Customize(a interface{}) (*cli.RunArgs, error) {
obj.init.Logf("packages: %+v", strings.Join(obj.localArgs.Packages, ","))
}
if p := obj.localArgs.HandoffCode; p != "" {
if strings.HasPrefix(p, "~") {
expanded, err := util.ExpandHome(p)
if err != nil {
return nil, err
}
obj.localArgs.HandoffCode = expanded
}
// Make path absolute.
if !strings.HasPrefix(obj.localArgs.HandoffCode, "/") {
dir, err := os.Getwd()
if err != nil {
return nil, err
}
dir = dir + "/" // dir's should have a trailing slash!
obj.localArgs.HandoffCode = dir + obj.localArgs.HandoffCode
}
// Does this path actually exist?
if _, err := os.Stat(obj.localArgs.HandoffCode); err != nil {
return nil, err
}
binary, err := util.ExecutablePath() // path to mgmt binary
if err != nil {
return nil, err
}
// Type check this path before we provision?
out := ""
cmdOpts := &util.SimpleCmdOpts{
Debug: true,
Logf: func(format string, v ...interface{}) {
// XXX: HACK to make output more beautiful!
errorText := "cli parse error: "
s := fmt.Sprintf(format+"\n", v...)
for _, x := range strings.Split(s, "\n") {
if !strings.HasPrefix(x, errorText) {
continue
}
out = strings.TrimPrefix(x, errorText)
}
},
}
// TODO: Add a --quiet flag instead of the above filter hack.
cmdArgs := []string{"run", "--tmp-prefix", "lang", "--only-unify", 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)
}
// Do this last to let others fail early b/c this has user interaction.
if obj.localArgs.Password == nil {
b, err := password.ReadPasswordCtxPrompt(ctx, "["+ModuleName+"] password: ")