1
0
mirror of https://github.com/rancher/os.git synced 2025-06-02 20:06:06 +00:00
os/config/config.go

211 lines
4.8 KiB
Go
Raw Normal View History

2015-02-09 04:38:37 +00:00
package config
import (
"encoding/json"
"io/ioutil"
2015-02-14 16:29:07 +00:00
"os"
2015-02-09 04:38:37 +00:00
"regexp"
"strconv"
"strings"
log "github.com/Sirupsen/logrus"
2015-02-14 16:29:07 +00:00
"github.com/rancherio/os/util"
2015-02-09 04:38:37 +00:00
)
2015-02-17 08:18:48 +00:00
const (
CONSOLE_CONTAINER = "console"
DOCKER_BIN = "/usr/bin/docker"
DOCKER_SYSTEM_HOST = "unix:///var/run/system-docker.sock"
DOCKER_HOST = "unix:///var/run/docker.sock"
IMAGES_PATH = "/"
IMAGES_PATTERN = "images*.tar"
SYS_INIT = "/sbin/init-sys"
USER_INIT = "/sbin/init-user"
MODULES_ARCHIVE = "/modules.tar"
DEBUG = true
)
2015-02-09 04:38:37 +00:00
type InitFunc func(*Config) error
type ContainerConfig struct {
2015-02-14 16:29:07 +00:00
Id string `json:"id,omitempty"`
Cmd []string `json:"run,omitempty"`
//Config *runconfig.Config `json:"-"`
//HostConfig *runconfig.HostConfig `json:"-"`
2015-02-09 04:38:37 +00:00
}
type Config struct {
2015-02-14 16:29:07 +00:00
//BootstrapContainers []ContainerConfig `json:"bootstrapContainers,omitempty"`
2015-02-17 08:18:48 +00:00
//UserContainers []ContainerConfig `json:"userContainser,omitempty"`
2015-02-14 16:29:07 +00:00
ConsoleContainer string `json:"consoleContainer,omitempty"`
Debug bool `json:"debug,omitempty"`
Disable []string `json:"disable,omitempty"`
Dns []string `json:"dns,omitempty"`
Rescue bool `json:"rescue,omitempty"`
RescueContainer ContainerConfig `json:"rescueContainer,omitempty"`
2015-02-17 08:18:48 +00:00
State ConfigState `json:"state,omitempty"`
2015-02-14 16:29:07 +00:00
SystemContainers []ContainerConfig `json:"systemContainers,omitempty"`
SystemDockerArgs []string `json:"systemDockerArgs,omitempty"`
Modules []string `json:"modules,omitempty"`
2015-02-17 08:18:48 +00:00
}
type ConfigState struct {
FsType string `json:"fsType,omitempty"`
Dev string `json:"dev,omitempty"`
Required bool `json:"required,omitempty"`
2015-02-14 16:29:07 +00:00
}
func (c *Config) Dump() string {
content, err := json.MarshalIndent(c, "", " ")
if err == nil {
return string(content)
} else {
return err.Error()
}
2015-02-09 04:38:37 +00:00
}
func LoadConfig() (*Config, error) {
cfg := NewConfig()
if err := cfg.Reload(); err != nil {
return nil, err
}
if cfg.Debug {
log.SetLevel(log.DebugLevel)
}
return cfg, nil
}
2015-02-14 16:29:07 +00:00
func (c *Config) readArgs() error {
log.Debug("Reading config args")
cmdLine := strings.Join(os.Args[1:], " ")
if len(cmdLine) == 0 {
return nil
2015-02-09 04:38:37 +00:00
}
2015-02-14 16:29:07 +00:00
log.Debugf("Config Args %s", cmdLine)
cmdLineObj := parseCmdline(strings.TrimSpace(cmdLine))
return c.merge(cmdLineObj)
}
2015-02-09 04:38:37 +00:00
2015-02-14 16:29:07 +00:00
func (c *Config) merge(values map[string]interface{}) error {
2015-02-09 04:38:37 +00:00
// Lazy way to assign values to *Config
2015-02-14 16:29:07 +00:00
override, err := json.Marshal(values)
if err != nil {
return err
}
return json.Unmarshal(override, c)
}
func (c *Config) readCmdline() error {
log.Debug("Reading config cmdline")
cmdLine, err := ioutil.ReadFile("/proc/cmdline")
2015-02-09 04:38:37 +00:00
if err != nil {
return err
}
2015-02-14 16:29:07 +00:00
if len(cmdLine) == 0 {
return nil
}
log.Debugf("Config cmdline %s", cmdLine)
cmdLineObj := parseCmdline(strings.TrimSpace(string(cmdLine)))
return c.merge(cmdLineObj)
2015-02-09 04:38:37 +00:00
}
func dummyMarshall(value string) interface{} {
if value == "true" {
return true
} else if value == "false" {
return false
} else if ok, _ := regexp.MatchString("^[0-9]+$", value); ok {
i, err := strconv.Atoi(value)
if err != nil {
panic(err)
}
return i
}
return value
}
func parseCmdline(cmdLine string) map[string]interface{} {
result := make(map[string]interface{})
outer:
for _, part := range strings.Split(cmdLine, " ") {
if !strings.HasPrefix(part, "rancher.") {
continue
}
var value string
kv := strings.SplitN(part, "=", 2)
if len(kv) == 1 {
value = "true"
} else {
value = kv[1]
}
current := result
keys := strings.Split(kv[0], ".")[1:]
for i, key := range keys {
if i == len(keys)-1 {
2015-02-14 16:29:07 +00:00
if strings.HasPrefix(value, "[") && strings.HasSuffix(value, "]") {
current[key] = strings.Split(value[1:len(value)-1], ",")
} else {
current[key] = dummyMarshall(value)
}
2015-02-09 04:38:37 +00:00
} else {
if obj, ok := current[key]; ok {
if newCurrent, ok := obj.(map[string]interface{}); ok {
current = newCurrent
} else {
continue outer
}
} else {
newCurrent := make(map[string]interface{})
current[key] = newCurrent
current = newCurrent
}
}
}
}
2015-02-14 16:29:07 +00:00
log.Debugf("Input obj %s", result)
2015-02-09 04:38:37 +00:00
return result
}
func (c *Config) Reload() error {
2015-02-14 16:29:07 +00:00
return util.ShortCircuit(
c.readCmdline,
c.readArgs,
)
}
func (c *Config) GetContainerById(id string) *ContainerConfig {
for _, c := range c.SystemContainers {
if c.Id == id {
return &c
}
}
return nil
2015-02-09 04:38:37 +00:00
}
func RunInitFuncs(cfg *Config, initFuncs []InitFunc) error {
for i, initFunc := range initFuncs {
log.Debugf("[%d/%d] Starting", i+1, len(initFuncs))
if err := initFunc(cfg); err != nil {
log.Errorf("Failed [%d/%d] %d%%", i+1, len(initFuncs), ((i + 1) * 100 / len(initFuncs)))
return err
}
log.Debugf("[%d/%d] Done %d%%", i+1, len(initFuncs), ((i + 1) * 100 / len(initFuncs)))
}
return nil
}