2014-03-18 20:00:41 +04:00
|
|
|
package initialize
|
2014-03-05 04:36:05 +04:00
|
|
|
|
|
|
|
import (
|
2014-03-13 03:52:32 +04:00
|
|
|
"fmt"
|
2014-03-05 04:36:05 +04:00
|
|
|
"log"
|
2014-03-18 20:00:41 +04:00
|
|
|
"path"
|
2014-03-05 04:36:05 +04:00
|
|
|
|
2014-03-13 06:36:31 +04:00
|
|
|
"github.com/coreos/coreos-cloudinit/third_party/launchpad.net/goyaml"
|
2014-03-05 04:36:05 +04:00
|
|
|
|
2014-03-18 20:00:41 +04:00
|
|
|
"github.com/coreos/coreos-cloudinit/system"
|
|
|
|
)
|
2014-03-06 02:30:38 +04:00
|
|
|
|
2014-03-05 04:36:05 +04:00
|
|
|
type CloudConfig struct {
|
2014-03-13 22:39:31 +04:00
|
|
|
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
|
|
|
|
Coreos struct {
|
2014-03-18 02:09:59 +04:00
|
|
|
Etcd EtcdEnvironment
|
2014-03-18 20:00:41 +04:00
|
|
|
Units []system.Unit
|
2014-03-23 22:06:43 +04:00
|
|
|
OEM OEMRelease
|
2014-03-12 03:13:07 +04:00
|
|
|
}
|
2014-04-02 02:02:12 +04:00
|
|
|
WriteFiles []system.File `yaml:"write_files"`
|
|
|
|
Hostname string
|
|
|
|
Users []system.User
|
|
|
|
ManageEtcHosts string `yaml:"manage_etc_hosts"`
|
2014-03-05 04:36:05 +04:00
|
|
|
}
|
|
|
|
|
2014-03-21 21:35:18 +04:00
|
|
|
func NewCloudConfig(contents string) (*CloudConfig, error) {
|
2014-03-05 04:36:05 +04:00
|
|
|
var cfg CloudConfig
|
2014-03-21 21:35:18 +04:00
|
|
|
err := goyaml.Unmarshal([]byte(contents), &cfg)
|
2014-03-05 04:36:05 +04:00
|
|
|
return &cfg, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cc CloudConfig) String() string {
|
|
|
|
bytes, err := goyaml.Marshal(cc)
|
2014-03-13 03:52:32 +04:00
|
|
|
if err != nil {
|
2014-03-05 04:36:05 +04:00
|
|
|
return ""
|
|
|
|
}
|
2014-03-13 03:52:32 +04:00
|
|
|
|
|
|
|
stringified := string(bytes)
|
|
|
|
stringified = fmt.Sprintf("#cloud-config\n%s", stringified)
|
|
|
|
|
|
|
|
return stringified
|
2014-03-05 04:36:05 +04:00
|
|
|
}
|
|
|
|
|
2014-03-18 20:00:41 +04:00
|
|
|
func Apply(cfg CloudConfig, env *Environment) error {
|
2014-03-13 09:30:24 +04:00
|
|
|
if cfg.Hostname != "" {
|
2014-03-18 20:00:41 +04:00
|
|
|
if err := system.SetHostname(cfg.Hostname); err != nil {
|
2014-03-13 09:30:24 +04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Printf("Set hostname to %s", cfg.Hostname)
|
|
|
|
}
|
|
|
|
|
2014-03-23 22:06:43 +04:00
|
|
|
if cfg.Coreos.OEM.ID != "" {
|
|
|
|
if err := WriteOEMRelease(&cfg.Coreos.OEM, env.Root()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Printf("Wrote /etc/oem-release to filesystem")
|
|
|
|
}
|
|
|
|
|
2014-03-13 21:56:59 +04:00
|
|
|
if len(cfg.Users) > 0 {
|
|
|
|
for _, user := range cfg.Users {
|
|
|
|
if user.Name == "" {
|
|
|
|
log.Printf("User object has no 'name' field, skipping")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2014-03-18 20:00:41 +04:00
|
|
|
if system.UserExists(&user) {
|
2014-03-13 21:56:59 +04:00
|
|
|
log.Printf("User '%s' exists, ignoring creation-time fields", user.Name)
|
|
|
|
if user.PasswordHash != "" {
|
|
|
|
log.Printf("Setting '%s' user's password", user.Name)
|
2014-03-18 20:00:41 +04:00
|
|
|
if err := system.SetUserPassword(user.Name, user.PasswordHash); err != nil {
|
2014-03-13 21:56:59 +04:00
|
|
|
log.Printf("Failed setting '%s' user's password: %v", user.Name, err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Printf("Creating user '%s'", user.Name)
|
2014-03-18 20:00:41 +04:00
|
|
|
if err := system.CreateUser(&user); err != nil {
|
2014-03-13 21:56:59 +04:00
|
|
|
log.Printf("Failed creating user '%s': %v", user.Name, err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(user.SSHAuthorizedKeys) > 0 {
|
|
|
|
log.Printf("Authorizing %d SSH keys for user '%s'", len(user.SSHAuthorizedKeys), user.Name)
|
2014-03-18 20:00:41 +04:00
|
|
|
if err := system.AuthorizeSSHKeys(user.Name, env.SSHKeyName(), user.SSHAuthorizedKeys); err != nil {
|
2014-03-13 21:56:59 +04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2014-03-19 19:54:45 +04:00
|
|
|
if user.SSHImportGithubUser != "" {
|
|
|
|
log.Printf("Authorizing github user %s SSH keys for CoreOS user '%s'", user.SSHImportGithubUser, user.Name)
|
|
|
|
if err := SSHImportGithubUser(user.Name, user.SSHImportGithubUser); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2014-03-23 02:26:18 +04:00
|
|
|
if user.SSHImportURL != "" {
|
|
|
|
log.Printf("Authorizing SSH keys for CoreOS user '%s' from '%s'", user.Name, user.SSHImportURL)
|
|
|
|
if err := SSHImportKeysFromURL(user.Name, user.SSHImportURL); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2014-03-13 21:56:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-13 22:39:31 +04:00
|
|
|
if len(cfg.SSHAuthorizedKeys) > 0 {
|
2014-03-18 20:00:41 +04:00
|
|
|
err := system.AuthorizeSSHKeys("core", env.SSHKeyName(), cfg.SSHAuthorizedKeys)
|
2014-03-05 04:36:05 +04:00
|
|
|
if err == nil {
|
|
|
|
log.Printf("Authorized SSH keys for core user")
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-13 22:40:33 +04:00
|
|
|
if len(cfg.WriteFiles) > 0 {
|
|
|
|
for _, file := range cfg.WriteFiles {
|
2014-03-18 20:00:41 +04:00
|
|
|
file.Path = path.Join(env.Root(), file.Path)
|
|
|
|
if err := system.WriteFile(&file); err != nil {
|
2014-03-12 04:46:58 +04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Printf("Wrote file %s to filesystem", file.Path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-18 02:09:59 +04:00
|
|
|
if len(cfg.Coreos.Etcd) > 0 {
|
2014-03-18 20:00:41 +04:00
|
|
|
if err := WriteEtcdEnvironment(cfg.Coreos.Etcd, env.Root()); err != nil {
|
2014-03-18 02:09:59 +04:00
|
|
|
log.Fatalf("Failed to write etcd config to filesystem: %v", err)
|
2014-03-05 04:36:05 +04:00
|
|
|
}
|
2014-03-18 02:09:59 +04:00
|
|
|
|
|
|
|
log.Printf("Wrote etcd config file to filesystem")
|
2014-03-05 04:36:05 +04:00
|
|
|
}
|
|
|
|
|
2014-03-13 02:43:51 +04:00
|
|
|
if len(cfg.Coreos.Units) > 0 {
|
2014-03-20 02:52:24 +04:00
|
|
|
commands := make(map[string]string, 0)
|
|
|
|
|
2014-03-13 02:43:51 +04:00
|
|
|
for _, unit := range cfg.Coreos.Units {
|
2014-03-20 02:52:24 +04:00
|
|
|
if unit.Content != "" {
|
|
|
|
log.Printf("Writing unit %s to filesystem", unit.Name)
|
|
|
|
dst, err := system.PlaceUnit(&unit, env.Root())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Printf("Placed unit %s at %s", unit.Name, dst)
|
|
|
|
|
2014-04-14 21:02:18 +04:00
|
|
|
if unit.Enable {
|
|
|
|
if unit.Group() != "network" {
|
|
|
|
log.Printf("Enabling unit file %s", dst)
|
|
|
|
if err := system.EnableUnitFile(dst, unit.Runtime); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Printf("Enabled unit %s", unit.Name)
|
|
|
|
} else {
|
|
|
|
log.Printf("Skipping enable for network-like unit %s", unit.Name)
|
2014-03-20 02:52:24 +04:00
|
|
|
}
|
|
|
|
}
|
2014-03-13 02:43:51 +04:00
|
|
|
}
|
|
|
|
|
2014-03-25 01:12:52 +04:00
|
|
|
if unit.Group() == "network" {
|
2014-03-20 02:52:24 +04:00
|
|
|
commands["systemd-networkd.service"] = "restart"
|
2014-03-25 01:12:52 +04:00
|
|
|
} else {
|
|
|
|
if unit.Command != "" {
|
2014-04-02 02:02:12 +04:00
|
|
|
commands[unit.Name] = unit.Command
|
2014-03-25 01:12:52 +04:00
|
|
|
}
|
2014-03-13 02:43:51 +04:00
|
|
|
}
|
|
|
|
}
|
2014-03-20 02:52:24 +04:00
|
|
|
|
|
|
|
for unit, command := range commands {
|
|
|
|
log.Printf("Calling unit command '%s %s'", command, unit)
|
|
|
|
res, err := system.RunUnitCommand(command, unit)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Printf("Result of '%s %s': %s", command, unit, res)
|
|
|
|
}
|
2014-03-13 02:43:51 +04:00
|
|
|
}
|
|
|
|
|
2014-04-02 02:02:12 +04:00
|
|
|
if cfg.ManageEtcHosts != "" {
|
|
|
|
|
|
|
|
if err := WriteEtcHosts(cfg.ManageEtcHosts, env.Root()); err != nil {
|
|
|
|
log.Fatalf("Failed to write /etc/hosts to filesystem: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Wrote /etc/hosts file to filesystem")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-03-05 04:36:05 +04:00
|
|
|
return nil
|
|
|
|
}
|