2014-09-22 06:22:13 +04:00
|
|
|
package system
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"reflect"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/coreos/coreos-cloudinit/config"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
locksmithUnit = "locksmithd.service"
|
|
|
|
updateEngineUnit = "update-engine.service"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Update is a top-level structure which contains its underlying configuration,
|
|
|
|
// config.Update, a function for reading the configuration (the default
|
|
|
|
// implementation reading from the filesystem), and provides the system-specific
|
|
|
|
// File() and Unit().
|
|
|
|
type Update struct {
|
|
|
|
Config config.Update
|
|
|
|
ReadConfig func() (io.Reader, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func DefaultReadConfig() (io.Reader, error) {
|
|
|
|
etcUpdate := path.Join("/etc", "coreos", "update.conf")
|
|
|
|
usrUpdate := path.Join("/usr", "share", "coreos", "update.conf")
|
|
|
|
|
|
|
|
f, err := os.Open(etcUpdate)
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
f, err = os.Open(usrUpdate)
|
|
|
|
}
|
|
|
|
return f, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// File generates an `/etc/coreos/update.conf` file (if any update
|
|
|
|
// configuration options are set in cloud-config) by either rewriting the
|
|
|
|
// existing file on disk, or starting from `/usr/share/coreos/update.conf`
|
|
|
|
func (uc Update) File() (*File, error) {
|
|
|
|
if config.IsZero(uc.Config) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
if err := config.AssertValid(uc.Config); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate the list of possible substitutions to be performed based on the options that are configured
|
|
|
|
subs := map[string]string{}
|
|
|
|
uct := reflect.TypeOf(uc.Config)
|
|
|
|
ucv := reflect.ValueOf(uc.Config)
|
|
|
|
for i := 0; i < uct.NumField(); i++ {
|
|
|
|
val := ucv.Field(i).String()
|
|
|
|
if val == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
env := uct.Field(i).Tag.Get("env")
|
|
|
|
subs[env] = fmt.Sprintf("%s=%s", env, val)
|
|
|
|
}
|
|
|
|
|
|
|
|
conf, err := uc.ReadConfig()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
scanner := bufio.NewScanner(conf)
|
|
|
|
|
|
|
|
var out string
|
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
for env, value := range subs {
|
|
|
|
if strings.HasPrefix(line, env) {
|
|
|
|
line = value
|
|
|
|
delete(subs, env)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out += line
|
|
|
|
out += "\n"
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, key := range sortedKeys(subs) {
|
|
|
|
out += subs[key]
|
|
|
|
out += "\n"
|
|
|
|
}
|
|
|
|
|
2014-09-22 06:22:27 +04:00
|
|
|
return &File{config.File{
|
2014-09-22 06:22:13 +04:00
|
|
|
Path: path.Join("etc", "coreos", "update.conf"),
|
|
|
|
RawFilePermissions: "0644",
|
|
|
|
Content: out,
|
2014-09-22 06:22:27 +04:00
|
|
|
}}, nil
|
2014-09-22 06:22:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Units generates units for the cloud-init initializer to act on:
|
|
|
|
// - a locksmith Unit, if "reboot-strategy" was set in cloud-config
|
|
|
|
// - an update_engine Unit, if "group" or "server" was set in cloud-config
|
2014-10-07 02:14:29 +04:00
|
|
|
func (uc Update) Units() []Unit {
|
2014-09-22 06:22:13 +04:00
|
|
|
var units []Unit
|
|
|
|
if uc.Config.RebootStrategy != "" {
|
2014-09-22 06:22:38 +04:00
|
|
|
ls := &Unit{config.Unit{
|
2014-09-22 06:22:13 +04:00
|
|
|
Name: locksmithUnit,
|
|
|
|
Command: "restart",
|
|
|
|
Mask: false,
|
|
|
|
Runtime: true,
|
2014-09-22 06:22:38 +04:00
|
|
|
}}
|
2014-09-22 06:22:13 +04:00
|
|
|
|
|
|
|
if uc.Config.RebootStrategy == "off" {
|
|
|
|
ls.Command = "stop"
|
|
|
|
ls.Mask = true
|
|
|
|
}
|
|
|
|
units = append(units, *ls)
|
|
|
|
}
|
|
|
|
|
|
|
|
if uc.Config.Group != "" || uc.Config.Server != "" {
|
2014-09-22 06:22:38 +04:00
|
|
|
ue := Unit{config.Unit{
|
2014-09-22 06:22:13 +04:00
|
|
|
Name: updateEngineUnit,
|
|
|
|
Command: "restart",
|
2014-09-22 06:22:38 +04:00
|
|
|
}}
|
2014-09-22 06:22:13 +04:00
|
|
|
units = append(units, ue)
|
|
|
|
}
|
|
|
|
|
2014-10-07 02:14:29 +04:00
|
|
|
return units
|
2014-09-22 06:22:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func sortedKeys(m map[string]string) (keys []string) {
|
|
|
|
for key := range m {
|
|
|
|
keys = append(keys, key)
|
|
|
|
}
|
|
|
|
sort.Strings(keys)
|
|
|
|
return
|
|
|
|
}
|