diff --git a/config/config.go b/config/config.go index 6049d2f..d2b5a9a 100644 --- a/config/config.go +++ b/config/config.go @@ -45,6 +45,17 @@ type CloudConfig struct { NetworkConfig string `yaml:"-"` } +func IsCloudConfig(userdata string) bool { + header := strings.SplitN(userdata, "\n", 2)[0] + + // Explicitly trim the header so we can handle user-data from + // non-unix operating systems. The rest of the file is parsed + // by yaml, which correctly handles CRLF. + header = strings.TrimSuffix(header, "\r") + + return (header == "#cloud-config") +} + // NewCloudConfig instantiates a new CloudConfig from the given contents (a // string of YAML), returning any error encountered. It will ignore unknown // fields but log encountering them. diff --git a/config/script.go b/config/script.go new file mode 100644 index 0000000..c8de6c2 --- /dev/null +++ b/config/script.go @@ -0,0 +1,16 @@ +package config + +import ( + "strings" +) + +type Script []byte + +func IsScript(userdata string) bool { + header := strings.SplitN(userdata, "\n", 2)[0] + return strings.HasPrefix(header, "#!") +} + +func NewScript(userdata string) (Script, error) { + return Script(userdata), nil +} diff --git a/coreos-cloudinit.go b/coreos-cloudinit.go index 20def1d..cb7f879 100644 --- a/coreos-cloudinit.go +++ b/coreos-cloudinit.go @@ -180,7 +180,7 @@ func main() { userdata := env.Apply(string(userdataBytes)) var ccm, ccu *config.CloudConfig - var script *system.Script + var script *config.Script if ccm, err = initialize.ParseMetaData(string(metadataBytes)); err != nil { fmt.Printf("Failed to parse meta-data: %v\n", err) os.Exit(1) @@ -203,7 +203,7 @@ func main() { switch t := ud.(type) { case *config.CloudConfig: ccu = t - case system.Script: + case config.Script: script = &t } } @@ -362,7 +362,7 @@ func selectDatasource(sources []datasource.Datasource) datasource.Datasource { } // TODO(jonboulle): this should probably be refactored and moved into a different module -func runScript(script system.Script, env *initialize.Environment) error { +func runScript(script config.Script, env *initialize.Environment) error { err := initialize.PrepWorkspace(env.Workspace()) if err != nil { fmt.Printf("Failed preparing workspace: %v\n", err) diff --git a/initialize/user_data.go b/initialize/user_data.go index cb477c4..b2b71be 100644 --- a/initialize/user_data.go +++ b/initialize/user_data.go @@ -17,32 +17,25 @@ package initialize import ( - "fmt" + "errors" "log" - "strings" "github.com/coreos/coreos-cloudinit/config" - "github.com/coreos/coreos-cloudinit/system" ) func ParseUserData(contents string) (interface{}, error) { if len(contents) == 0 { return nil, nil } - header := strings.SplitN(contents, "\n", 2)[0] - // Explicitly trim the header so we can handle user-data from - // non-unix operating systems. The rest of the file is parsed - // by yaml, which correctly handles CRLF. - header = strings.TrimSpace(header) - - if strings.HasPrefix(header, "#!") { + switch { + case config.IsScript(contents): log.Printf("Parsing user-data as script") - return system.Script(contents), nil - } else if header == "#cloud-config" { + return config.NewScript(contents) + case config.IsCloudConfig(contents): log.Printf("Parsing user-data as cloud-config") return config.NewCloudConfig(contents) - } else { - return nil, fmt.Errorf("Unrecognized user-data header: %s", header) + default: + return nil, errors.New("Unrecognized user-data format") } } diff --git a/initialize/workspace.go b/initialize/workspace.go index 8af319d..b9d8fc8 100644 --- a/initialize/workspace.go +++ b/initialize/workspace.go @@ -38,7 +38,7 @@ func PrepWorkspace(workspace string) error { return nil } -func PersistScriptInWorkspace(script system.Script, workspace string) (string, error) { +func PersistScriptInWorkspace(script config.Script, workspace string) (string, error) { scriptsPath := path.Join(workspace, "scripts") tmp, err := ioutil.TempFile(scriptsPath, "") if err != nil { diff --git a/system/unit.go b/system/unit.go index 5d34e99..26e9bbc 100644 --- a/system/unit.go +++ b/system/unit.go @@ -41,8 +41,6 @@ type Unit struct { config.Unit } -type Script []byte - // Destination builds the appropriate absolute file path for // the Unit. The root argument indicates the effective base // directory of the system (similar to a chroot).