// ConfigureScript generates the bash script that applies // the specified cloud-config. func ConfigureScript(cloudcfg *cloudinit.Config) (string, error) { if cloudcfg == nil { panic("cloudcfg is nil") } // TODO(axw): 2013-08-23 bug 1215777 // Carry out configuration for ssh-keys-per-user, // machine-updates-authkeys, using cloud-init config. // // We should work with smoser to get a supported // command in (or next to) cloud-init for manually // invoking cloud-config. This would address the // above comment by removing the need to generate a // script "by hand". // Bootcmds must be run before anything else, // as they may affect package installation. bootcmds, err := cmdlist(cloudcfg.BootCmds()) if err != nil { return "", err } // Depending on cloudcfg, potentially add package sources and packages. pkgcmds, err := addPackageCommands(cloudcfg) if err != nil { return "", err } // Runcmds come last. runcmds, err := cmdlist(cloudcfg.RunCmds()) if err != nil { return "", err } // We prepend "set -xe". This is already in runcmds, // but added here to avoid relying on that to be // invariant. script := []string{"#!/bin/bash", "set -e"} // We must initialise progress reporting before entering // the subshell and redirecting stderr. script = append(script, cloudinit.InitProgressCmd()) stdout, stderr := cloudcfg.Output(cloudinit.OutAll) script = append(script, "(") if stderr != "" { script = append(script, "(") } script = append(script, bootcmds...) script = append(script, pkgcmds...) script = append(script, runcmds...) if stderr != "" { script = append(script, ") "+stdout) script = append(script, ") "+stderr) } else { script = append(script, ") "+stdout+" 2>&1") } return strings.Join(script, "\n"), nil }