mirror of
https://github.com/rancher/os.git
synced 2025-09-02 07:15:41 +00:00
make cloud-config the configuration mechanism for RancherOS
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
.DS_Store
|
||||
.git
|
||||
.idea
|
||||
bin
|
||||
gopath
|
||||
tmp
|
||||
state
|
||||
build
|
||||
|
@@ -48,86 +48,51 @@ const (
|
||||
datasourceInterval = 100 * time.Millisecond
|
||||
datasourceMaxInterval = 30 * time.Second
|
||||
datasourceTimeout = 5 * time.Minute
|
||||
sshKeyName = "rancheros-cloud-config"
|
||||
baseConfigDir = "/var/lib/rancher/conf/cloud-config.d"
|
||||
)
|
||||
|
||||
var (
|
||||
baseConfigDir string
|
||||
outputDir string
|
||||
outputFile string
|
||||
metaDataFile string
|
||||
scriptFile string
|
||||
rancherYml string
|
||||
save bool
|
||||
execute bool
|
||||
network bool
|
||||
sshKeyName string
|
||||
flags *flag.FlagSet
|
||||
save bool
|
||||
execute bool
|
||||
network bool
|
||||
flags *flag.FlagSet
|
||||
)
|
||||
|
||||
func init() {
|
||||
flags = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||
flags.StringVar(&baseConfigDir, "base-config-dir", "/var/lib/rancher/conf/cloud-config.d", "base cloud config")
|
||||
flags.StringVar(&outputDir, "dir", "/var/lib/rancher/conf", "working directory")
|
||||
flags.StringVar(&outputFile, "file", "cloud-config-processed.yml", "output cloud config file name")
|
||||
flags.StringVar(&metaDataFile, "metadata", "metadata", "output metdata file name")
|
||||
flags.StringVar(&scriptFile, "script-file", "cloud-config-script", "output cloud config script file name")
|
||||
flags.StringVar(&rancherYml, "rancher", "cloud-config-rancher.yml", "output cloud config rancher file name")
|
||||
flags.StringVar(&sshKeyName, "ssh-key-name", "rancheros-cloud-config", "SSH key name")
|
||||
flags.BoolVar(&network, "network", true, "use network based datasources")
|
||||
flags.BoolVar(&save, "save", false, "save cloud config and exit")
|
||||
flags.BoolVar(&execute, "execute", false, "execute saved cloud config")
|
||||
}
|
||||
|
||||
func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadata) error {
|
||||
scriptOutput := path.Join(outputDir, scriptFile)
|
||||
cloudConfigOutput := path.Join(outputDir, outputFile)
|
||||
rancherYmlOutput := path.Join(outputDir, rancherYml)
|
||||
metaDataOutput := path.Join(outputDir, metaDataFile)
|
||||
|
||||
os.Remove(scriptOutput)
|
||||
os.Remove(cloudConfigOutput)
|
||||
os.Remove(rancherYmlOutput)
|
||||
os.Remove(metaDataOutput)
|
||||
os.Remove(rancherConfig.CloudConfigScriptFile)
|
||||
os.Remove(rancherConfig.CloudConfigFile)
|
||||
os.Remove(rancherConfig.MetaDataFile)
|
||||
|
||||
if len(scriptBytes) > 0 {
|
||||
log.Infof("Writing to %s", scriptOutput)
|
||||
if err := ioutil.WriteFile(scriptOutput, scriptBytes, 500); err != nil {
|
||||
log.Errorf("Error while writing file %s: %v", scriptOutput, err)
|
||||
log.Infof("Writing to %s", rancherConfig.CloudConfigScriptFile)
|
||||
if err := ioutil.WriteFile(rancherConfig.CloudConfigScriptFile, scriptBytes, 500); err != nil {
|
||||
log.Errorf("Error while writing file %s: %v", rancherConfig.CloudConfigScriptFile, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cloudConfigBytes = append([]byte("#cloud-config\n"), cloudConfigBytes...)
|
||||
log.Infof("Writing to %s", cloudConfigOutput)
|
||||
if err := ioutil.WriteFile(cloudConfigOutput, cloudConfigBytes, 500); err != nil {
|
||||
log.Errorf("Error while writing file %s: %v", cloudConfigOutput, err)
|
||||
if err := ioutil.WriteFile(rancherConfig.CloudConfigFile, cloudConfigBytes, 400); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ccData := make(map[string]interface{})
|
||||
if err := yaml.Unmarshal(cloudConfigBytes, ccData); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if rancher, ok := ccData["rancher"]; ok {
|
||||
bytes, err := yaml.Marshal(rancher)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(rancherYmlOutput, bytes, 400); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigFile, string(cloudConfigBytes))
|
||||
|
||||
metaDataBytes, err := yaml.Marshal(metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(metaDataOutput, metaDataBytes, 400); err != nil {
|
||||
if err = ioutil.WriteFile(rancherConfig.MetaDataFile, metaDataBytes, 400); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("Written to %s:\n%s", rancherConfig.MetaDataFile, string(metaDataBytes))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -258,24 +223,22 @@ func saveCloudConfig() error {
|
||||
}
|
||||
|
||||
func getSaveCloudConfig() (*config.CloudConfig, error) {
|
||||
cloudConfig := path.Join(outputDir, outputFile)
|
||||
|
||||
ds := file.NewDatasource(cloudConfig)
|
||||
ds := file.NewDatasource(rancherConfig.CloudConfigFile)
|
||||
if !ds.IsAvailable() {
|
||||
log.Infof("%s does not exist", cloudConfig)
|
||||
log.Infof("%s does not exist", rancherConfig.CloudConfigFile)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ccBytes, err := ds.FetchUserdata()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to read user-data from %s: %v", cloudConfig, err)
|
||||
log.Errorf("Failed to read user-data from %s: %v", rancherConfig.CloudConfigFile, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cc config.CloudConfig
|
||||
err = yaml.Unmarshal(ccBytes, &cc)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to unmarshall user-data from %s: %v", cloudConfig, err)
|
||||
log.Errorf("Failed to unmarshall user-data from %s: %v", rancherConfig.CloudConfigFile, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -290,7 +253,7 @@ func executeCloudConfig() error {
|
||||
|
||||
var metadata datasource.Metadata
|
||||
|
||||
metaDataBytes, err := ioutil.ReadFile(path.Join(outputDir, metaDataFile))
|
||||
metaDataBytes, err := ioutil.ReadFile(rancherConfig.MetaDataFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -338,6 +301,8 @@ func executeCloudConfig() error {
|
||||
func Main() {
|
||||
flags.Parse(rancherConfig.FilterGlobalConfig(os.Args[1:]))
|
||||
|
||||
log.Infof("Running cloud-init: save=%v, execute=%v", save, execute)
|
||||
|
||||
if save {
|
||||
err := saveCloudConfig()
|
||||
if err != nil {
|
||||
@@ -376,10 +341,10 @@ func mergeConfigs(cc *config.CloudConfig, md datasource.Metadata) (out config.Cl
|
||||
|
||||
// getDatasources creates a slice of possible Datasources for cloudinit based
|
||||
// on the different source command-line flags.
|
||||
func getDatasources(cfg *rancherConfig.Config) []datasource.Datasource {
|
||||
func getDatasources(cfg *rancherConfig.CloudConfig) []datasource.Datasource {
|
||||
dss := make([]datasource.Datasource, 0, 5)
|
||||
|
||||
for _, ds := range cfg.CloudInit.Datasources {
|
||||
for _, ds := range cfg.Rancher.CloudInit.Datasources {
|
||||
parts := strings.SplitN(ds, ":", 2)
|
||||
|
||||
switch parts[0] {
|
||||
|
@@ -76,16 +76,16 @@ func configSubcommands() []cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func imagesFromConfig(cfg *config.Config) []string {
|
||||
func imagesFromConfig(cfg *config.CloudConfig) []string {
|
||||
imagesMap := map[string]int{}
|
||||
|
||||
for _, service := range cfg.BootstrapContainers {
|
||||
for _, service := range cfg.Rancher.BootstrapContainers {
|
||||
imagesMap[service.Image] = 1
|
||||
}
|
||||
for _, service := range cfg.Autoformat {
|
||||
for _, service := range cfg.Rancher.Autoformat {
|
||||
imagesMap[service.Image] = 1
|
||||
}
|
||||
for _, service := range cfg.SystemContainers {
|
||||
for _, service := range cfg.Rancher.Services {
|
||||
imagesMap[service.Image] = 1
|
||||
}
|
||||
|
||||
@@ -165,12 +165,12 @@ func configGet(c *cli.Context) {
|
||||
|
||||
cfg, err := config.LoadConfig()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
val, err := cfg.Get(arg)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.WithFields(log.Fields{"cfg": cfg, "arg": arg, "val": val}).Panicln(err)
|
||||
}
|
||||
|
||||
printYaml := false
|
||||
@@ -192,50 +192,6 @@ func configGet(c *cli.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func getOrSetVal(args string, data map[interface{}]interface{}, value interface{}) interface{} {
|
||||
parts := strings.Split(args, ".")
|
||||
|
||||
for i, part := range parts {
|
||||
val, ok := data[part]
|
||||
last := i+1 == len(parts)
|
||||
|
||||
// Reached end, set the value
|
||||
if last && value != nil {
|
||||
if s, ok := value.(string); ok {
|
||||
value = config.DummyMarshall(s)
|
||||
}
|
||||
|
||||
data[part] = value
|
||||
return value
|
||||
}
|
||||
|
||||
// Missing intermediate key, create key
|
||||
if !last && value != nil && !ok {
|
||||
newData := map[interface{}]interface{}{}
|
||||
data[part] = newData
|
||||
data = newData
|
||||
continue
|
||||
}
|
||||
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
if last {
|
||||
return val
|
||||
}
|
||||
|
||||
newData, ok := val.(map[interface{}]interface{})
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
data = newData
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func merge(c *cli.Context) {
|
||||
bytes, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
|
@@ -20,8 +20,8 @@ func envAction(c *cli.Context) {
|
||||
args := c.Args()
|
||||
osEnv := os.Environ()
|
||||
|
||||
envMap := make(map[string]string, len(cfg.Environment)+len(osEnv))
|
||||
for k, v := range cfg.Environment {
|
||||
envMap := make(map[string]string, len(cfg.Rancher.Environment)+len(osEnv))
|
||||
for k, v := range cfg.Rancher.Environment {
|
||||
envMap[k] = v
|
||||
}
|
||||
for k, v := range util.KVPairs2Map(osEnv) {
|
||||
|
@@ -249,5 +249,5 @@ func getUpgradeUrl() (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return cfg.Upgrade.Url, nil
|
||||
return cfg.Rancher.Upgrade.Url, nil
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ package control
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
@@ -44,16 +44,16 @@ func disable(c *cli.Context) {
|
||||
}
|
||||
|
||||
for _, service := range c.Args() {
|
||||
if _, ok := cfg.ServicesInclude[service]; !ok {
|
||||
if _, ok := cfg.Rancher.ServicesInclude[service]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
cfg.ServicesInclude[service] = false
|
||||
cfg.Rancher.ServicesInclude[service] = false
|
||||
changed = true
|
||||
}
|
||||
|
||||
if changed {
|
||||
if err = cfg.Set("services_include", cfg.ServicesInclude); err != nil {
|
||||
if err = cfg.Set("rancher.services_include", cfg.Rancher.ServicesInclude); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -67,15 +67,15 @@ func del(c *cli.Context) {
|
||||
}
|
||||
|
||||
for _, service := range c.Args() {
|
||||
if _, ok := cfg.ServicesInclude[service]; !ok {
|
||||
if _, ok := cfg.Rancher.ServicesInclude[service]; !ok {
|
||||
continue
|
||||
}
|
||||
delete(cfg.ServicesInclude, service)
|
||||
delete(cfg.Rancher.ServicesInclude, service)
|
||||
changed = true
|
||||
}
|
||||
|
||||
if changed {
|
||||
if err = cfg.Set("services_include", cfg.ServicesInclude); err != nil {
|
||||
if err = cfg.Set("rancher.services_include", cfg.Rancher.ServicesInclude); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -89,20 +89,20 @@ func enable(c *cli.Context) {
|
||||
}
|
||||
|
||||
for _, service := range c.Args() {
|
||||
if val, ok := cfg.ServicesInclude[service]; !ok || !val {
|
||||
if val, ok := cfg.Rancher.ServicesInclude[service]; !ok || !val {
|
||||
if strings.HasPrefix(service, "/") && !strings.HasPrefix(service, "/var/lib/rancher/conf") {
|
||||
log.Fatalf("ERROR: Service should be in path /var/lib/rancher/conf")
|
||||
}
|
||||
if _, err := docker.LoadServiceResource(service, true, cfg); err != nil {
|
||||
log.Fatalf("could not load service %s", service)
|
||||
}
|
||||
cfg.ServicesInclude[service] = true
|
||||
cfg.Rancher.ServicesInclude[service] = true
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
if err = cfg.Set("services_include", cfg.ServicesInclude); err != nil {
|
||||
if err := cfg.Set("rancher.services_include", cfg.Rancher.ServicesInclude); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -115,11 +115,11 @@ func list(c *cli.Context) {
|
||||
}
|
||||
|
||||
clone := make(map[string]bool)
|
||||
for service, enabled := range cfg.ServicesInclude {
|
||||
for service, enabled := range cfg.Rancher.ServicesInclude {
|
||||
clone[service] = enabled
|
||||
}
|
||||
|
||||
services, err := util.GetServices(cfg.Repositories.ToArray())
|
||||
services, err := util.GetServices(cfg.Rancher.Repositories.ToArray())
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get services: %v", err)
|
||||
}
|
||||
|
@@ -44,12 +44,12 @@ func tlsConfCommands() []cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func writeCerts(generateServer bool, hostname []string, cfg *config.Config, certPath, keyPath, caCertPath, caKeyPath string) error {
|
||||
func writeCerts(generateServer bool, hostname []string, cfg *config.CloudConfig, certPath, keyPath, caCertPath, caKeyPath string) error {
|
||||
if !generateServer {
|
||||
return machineUtil.GenerateCert([]string{""}, certPath, keyPath, caCertPath, caKeyPath, NAME, BITS)
|
||||
}
|
||||
|
||||
if cfg.UserDocker.ServerKey == "" || cfg.UserDocker.ServerCert == "" {
|
||||
if cfg.Rancher.UserDocker.ServerKey == "" || cfg.Rancher.UserDocker.ServerCert == "" {
|
||||
err := machineUtil.GenerateCert(hostname, certPath, keyPath, caCertPath, caKeyPath, NAME, BITS)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -65,26 +65,28 @@ func writeCerts(generateServer bool, hostname []string, cfg *config.Config, cert
|
||||
return err
|
||||
}
|
||||
|
||||
return cfg.SetConfig(&config.Config{
|
||||
UserDocker: config.DockerConfig{
|
||||
CAKey: cfg.UserDocker.CAKey,
|
||||
CACert: cfg.UserDocker.CACert,
|
||||
ServerCert: string(cert),
|
||||
ServerKey: string(key),
|
||||
return cfg.SetConfig(&config.CloudConfig{
|
||||
Rancher: config.RancherConfig{
|
||||
UserDocker: config.DockerConfig{
|
||||
CAKey: cfg.Rancher.UserDocker.CAKey,
|
||||
CACert: cfg.Rancher.UserDocker.CACert,
|
||||
ServerCert: string(cert),
|
||||
ServerKey: string(key),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(certPath, []byte(cfg.UserDocker.ServerCert), 0400); err != nil {
|
||||
if err := ioutil.WriteFile(certPath, []byte(cfg.Rancher.UserDocker.ServerCert), 0400); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(keyPath, []byte(cfg.UserDocker.ServerKey), 0400)
|
||||
return ioutil.WriteFile(keyPath, []byte(cfg.Rancher.UserDocker.ServerKey), 0400)
|
||||
|
||||
}
|
||||
|
||||
func writeCaCerts(cfg *config.Config, caCertPath, caKeyPath string) error {
|
||||
if cfg.UserDocker.CACert == "" {
|
||||
func writeCaCerts(cfg *config.CloudConfig, caCertPath, caKeyPath string) error {
|
||||
if cfg.Rancher.UserDocker.CACert == "" {
|
||||
if err := machineUtil.GenerateCACertificate(caCertPath, caKeyPath, NAME, BITS); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -99,10 +101,12 @@ func writeCaCerts(cfg *config.Config, caCertPath, caKeyPath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cfg.SetConfig(&config.Config{
|
||||
UserDocker: config.DockerConfig{
|
||||
CAKey: string(caKey),
|
||||
CACert: string(caCert),
|
||||
err = cfg.SetConfig(&config.CloudConfig{
|
||||
Rancher: config.RancherConfig{
|
||||
UserDocker: config.DockerConfig{
|
||||
CAKey: string(caKey),
|
||||
CACert: string(caCert),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -112,11 +116,11 @@ func writeCaCerts(cfg *config.Config, caCertPath, caKeyPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(caCertPath, []byte(cfg.UserDocker.CACert), 0400); err != nil {
|
||||
if err := ioutil.WriteFile(caCertPath, []byte(cfg.Rancher.UserDocker.CACert), 0400); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(caKeyPath, []byte(cfg.UserDocker.CAKey), 0400)
|
||||
return ioutil.WriteFile(caKeyPath, []byte(cfg.Rancher.UserDocker.CAKey), 0400)
|
||||
}
|
||||
|
||||
func tlsConfCreate(c *cli.Context) {
|
||||
|
@@ -20,14 +20,14 @@ import (
|
||||
func Main() {
|
||||
args := os.Args
|
||||
if len(args) > 1 {
|
||||
fmt.Println("call " + args[0] + " to load network config from rancher.yml config file")
|
||||
fmt.Println("call " + args[0] + " to load network config from cloud-config.yml")
|
||||
return
|
||||
}
|
||||
cfg, err := config.LoadConfig()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ApplyNetworkConfigs(&cfg.Network)
|
||||
ApplyNetworkConfigs(&cfg.Rancher.Network)
|
||||
}
|
||||
|
||||
func createInterfaces(netCfg *config.NetworkConfig) error {
|
||||
|
@@ -68,7 +68,7 @@ func run(c *cli.Context) {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for _, line := range strings.Split(string(input), "\n") {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
if strings.TrimSpace(line) == "" || strings.Index(strings.TrimSpace(line), "#") == 0 {
|
||||
continue
|
||||
}
|
||||
wg.Add(1)
|
||||
|
170
config/config.go
170
config/config.go
@@ -2,58 +2,21 @@ package config
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rancherio/rancher-compose/librcompose/project"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/rancherio/os/util"
|
||||
"github.com/rancherio/rancher-compose/librcompose/project"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func (c *Config) privilegedMerge(newConfig Config) error {
|
||||
err := c.overlay(newConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k, v := range newConfig.SystemContainers {
|
||||
c.SystemContainers[k] = v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) overlay(newConfig Config) error {
|
||||
newConfig.clearReadOnly()
|
||||
return util.Convert(&newConfig, c)
|
||||
}
|
||||
|
||||
func (c *Config) clearReadOnly() {
|
||||
c.BootstrapContainers = make(map[string]*project.ServiceConfig, 0)
|
||||
c.SystemContainers = make(map[string]*project.ServiceConfig, 0)
|
||||
}
|
||||
|
||||
func clearReadOnly(data map[interface{}]interface{}) map[interface{}]interface{} {
|
||||
newData := make(map[interface{}]interface{})
|
||||
for k, v := range data {
|
||||
newData[k] = v
|
||||
}
|
||||
|
||||
delete(newData, "system_container")
|
||||
delete(newData, "bootstrap_container")
|
||||
|
||||
return newData
|
||||
}
|
||||
|
||||
func (c *Config) Import(bytes []byte) error {
|
||||
func (c *CloudConfig) Import(bytes []byte) error {
|
||||
data, err := readConfig(bytes, PrivateConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = saveToDisk(data); err != nil {
|
||||
if err := saveToDisk(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -61,7 +24,7 @@ func (c *Config) Import(bytes []byte) error {
|
||||
}
|
||||
|
||||
// This function only sets "non-empty" values
|
||||
func (c *Config) SetConfig(newConfig *Config) error {
|
||||
func (c *CloudConfig) SetConfig(newConfig *CloudConfig) error {
|
||||
bytes, err := yaml.Marshal(newConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -70,83 +33,63 @@ func (c *Config) SetConfig(newConfig *Config) error {
|
||||
return c.Merge(bytes)
|
||||
}
|
||||
|
||||
func (c *Config) Merge(bytes []byte) error {
|
||||
data, err := readSavedConfig(bytes)
|
||||
func (c *CloudConfig) Merge(bytes []byte) error {
|
||||
data, err := readConfig(bytes, LocalConfigFile, PrivateConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = saveToDisk(data)
|
||||
if err != nil {
|
||||
if err := saveToDisk(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Reload()
|
||||
}
|
||||
|
||||
func LoadConfig() (*Config, error) {
|
||||
func LoadConfig() (*CloudConfig, error) {
|
||||
cfg := NewConfig()
|
||||
if err := cfg.Reload(); err != nil {
|
||||
log.WithFields(log.Fields{"cfg": cfg}).Panicln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.Debug {
|
||||
if cfg.Rancher.Debug {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
if !util.Contains(cfg.UserDocker.Args, "-D") {
|
||||
cfg.UserDocker.Args = append(cfg.UserDocker.Args, "-D")
|
||||
if !util.Contains(cfg.Rancher.UserDocker.Args, "-D") {
|
||||
cfg.Rancher.UserDocker.Args = append(cfg.Rancher.UserDocker.Args, "-D")
|
||||
}
|
||||
if !util.Contains(cfg.SystemDocker.Args, "-D") {
|
||||
cfg.SystemDocker.Args = append(cfg.SystemDocker.Args, "-D")
|
||||
if !util.Contains(cfg.Rancher.SystemDocker.Args, "-D") {
|
||||
cfg.Rancher.SystemDocker.Args = append(cfg.Rancher.SystemDocker.Args, "-D")
|
||||
}
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (c *Config) readArgs() error {
|
||||
log.Debug("Reading config args")
|
||||
parts := make([]string, len(os.Args))
|
||||
|
||||
for _, arg := range os.Args[1:] {
|
||||
if strings.HasPrefix(arg, "--") {
|
||||
arg = arg[2:]
|
||||
}
|
||||
|
||||
kv := strings.SplitN(arg, "=", 2)
|
||||
kv[0] = strings.Replace(kv[0], "-", ".", -1)
|
||||
parts = append(parts, strings.Join(kv, "="))
|
||||
}
|
||||
|
||||
cmdLine := strings.Join(parts, " ")
|
||||
if len(cmdLine) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debugf("Config Args %s", cmdLine)
|
||||
|
||||
cmdLineObj := parseCmdline(strings.TrimSpace(cmdLine))
|
||||
|
||||
return c.merge(cmdLineObj)
|
||||
}
|
||||
|
||||
func (c *Config) merge(values map[interface{}]interface{}) error {
|
||||
values = clearReadOnly(values)
|
||||
func (c *CloudConfig) merge(values map[interface{}]interface{}) error {
|
||||
return util.Convert(values, c)
|
||||
}
|
||||
|
||||
func (c *Config) readFiles() error {
|
||||
data, err := readSavedConfig(nil)
|
||||
func (c *CloudConfig) readFiles() error {
|
||||
data, err := readConfig(nil, CloudConfigFile, LocalConfigFile, PrivateConfigFile)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return c.merge(data)
|
||||
if err := c.merge(data); err != nil {
|
||||
log.WithFields(log.Fields{"cfg": c, "data": data}).Panicln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) readCmdline() error {
|
||||
func (c *CloudConfig) readCmdline() error {
|
||||
log.Debug("Reading config cmdline")
|
||||
cmdLine, err := ioutil.ReadFile("/proc/cmdline")
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -157,16 +100,21 @@ func (c *Config) readCmdline() error {
|
||||
log.Debugf("Config cmdline %s", cmdLine)
|
||||
|
||||
cmdLineObj := parseCmdline(strings.TrimSpace(string(cmdLine)))
|
||||
return c.merge(cmdLineObj)
|
||||
|
||||
if err := c.merge(cmdLineObj); err != nil {
|
||||
log.WithFields(log.Fields{"cfg": c, "cmdLine": cmdLine, "data": cmdLineObj}).Panicln(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Dump(private, full bool) (string, error) {
|
||||
files := []string{CloudConfigFile, ConfigFile}
|
||||
files := []string{CloudConfigFile, LocalConfigFile}
|
||||
if private {
|
||||
files = append(files, PrivateConfigFile)
|
||||
}
|
||||
|
||||
c := &Config{}
|
||||
c := &CloudConfig{}
|
||||
|
||||
if full {
|
||||
c = NewConfig()
|
||||
@@ -177,23 +125,23 @@ func Dump(private, full bool) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = c.merge(data)
|
||||
if err != nil {
|
||||
if err := c.merge(data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = c.readGlobals()
|
||||
if err != nil {
|
||||
if err := c.readGlobals(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
c.amendNils()
|
||||
|
||||
bytes, err := yaml.Marshal(c)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func (c *Config) configureConsole() error {
|
||||
if console, ok := c.SystemContainers[CONSOLE_CONTAINER]; ok {
|
||||
if c.Console.Persistent {
|
||||
func (c *CloudConfig) configureConsole() error {
|
||||
if console, ok := c.Rancher.Services[CONSOLE_CONTAINER]; ok {
|
||||
if c.Rancher.Console.Persistent {
|
||||
console.Labels.MapParts()[REMOVE] = "false"
|
||||
} else {
|
||||
console.Labels.MapParts()[REMOVE] = "true"
|
||||
@@ -203,22 +151,41 @@ func (c *Config) configureConsole() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) readGlobals() error {
|
||||
func (c *CloudConfig) amendNils() error {
|
||||
if c.Rancher.Environment == nil {
|
||||
c.Rancher.Environment = map[string]string{}
|
||||
}
|
||||
if c.Rancher.Autoformat == nil {
|
||||
c.Rancher.Autoformat = map[string]*project.ServiceConfig{}
|
||||
}
|
||||
if c.Rancher.BootstrapContainers == nil {
|
||||
c.Rancher.BootstrapContainers = map[string]*project.ServiceConfig{}
|
||||
}
|
||||
if c.Rancher.Services == nil {
|
||||
c.Rancher.Services = map[string]*project.ServiceConfig{}
|
||||
}
|
||||
if c.Rancher.ServicesInclude == nil {
|
||||
c.Rancher.ServicesInclude = map[string]bool{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CloudConfig) readGlobals() error {
|
||||
return util.ShortCircuit(
|
||||
c.readCmdline,
|
||||
c.readArgs,
|
||||
c.configureConsole,
|
||||
c.configureConsole, // TODO: this smells (it is a write hidden inside a read)
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Config) Reload() error {
|
||||
func (c *CloudConfig) Reload() error {
|
||||
return util.ShortCircuit(
|
||||
c.readFiles,
|
||||
c.readGlobals,
|
||||
c.amendNils,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Config) Get(key string) (interface{}, error) {
|
||||
func (c *CloudConfig) Get(key string) (interface{}, error) {
|
||||
data := make(map[interface{}]interface{})
|
||||
err := util.Convert(c, &data)
|
||||
if err != nil {
|
||||
@@ -228,8 +195,8 @@ func (c *Config) Get(key string) (interface{}, error) {
|
||||
return getOrSetVal(key, data, nil), nil
|
||||
}
|
||||
|
||||
func (c *Config) Set(key string, value interface{}) error {
|
||||
data, err := readSavedConfig(nil)
|
||||
func (c *CloudConfig) Set(key string, value interface{}) error {
|
||||
data, err := readConfig(nil, LocalConfigFile, PrivateConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -242,8 +209,7 @@ func (c *Config) Set(key string, value interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = saveToDisk(data)
|
||||
if err != nil {
|
||||
if err := saveToDisk(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@@ -3,102 +3,252 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v2"
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/rancherio/os/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
"strings"
|
||||
)
|
||||
import "reflect"
|
||||
|
||||
func testParseCmdline(t *testing.T) {
|
||||
expected := map[string]interface{}{
|
||||
"rescue": true,
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"keyArray": []string{"1", "2"},
|
||||
"obj1": map[string]interface{}{
|
||||
"key3": "3value",
|
||||
"obj2": map[string]interface{}{
|
||||
"key4": true,
|
||||
func TestNilMap(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
var m map[string]interface{} = nil
|
||||
assert.True(m == nil)
|
||||
}
|
||||
|
||||
func TestMapCopy(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
m0 := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "4"}
|
||||
m1 := util.MapCopy(m0)
|
||||
|
||||
delete(m0, "a")
|
||||
assert.Equal(len(m1), len(m0)+1)
|
||||
|
||||
b0 := m0["b"].(map[interface{}]interface{})
|
||||
b1 := m1["b"].(map[interface{}]interface{})
|
||||
b1["e"] = "queer"
|
||||
|
||||
assert.Equal(len(b1), len(b0)+1)
|
||||
}
|
||||
|
||||
func TestMapsIntersection(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
m0 := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "4"}
|
||||
m1 := util.MapCopy(m0)
|
||||
|
||||
delete(m0, "a")
|
||||
b1 := m1["b"].(map[interface{}]interface{})
|
||||
delete(b1, "c")
|
||||
expected := map[interface{}]interface{}{"b": map[interface{}]interface{}{}, "d": "4"}
|
||||
assert.Equal(expected, util.MapsIntersection(m0, m1, util.Equal))
|
||||
}
|
||||
|
||||
func TestMapsUnion(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
m0 := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "4"}
|
||||
m1 := util.MapCopy(m0)
|
||||
m1["e"] = "added"
|
||||
m1["d"] = "replaced"
|
||||
|
||||
delete(m0, "a")
|
||||
b1 := m1["b"].(map[interface{}]interface{})
|
||||
delete(b1, "c")
|
||||
expected := map[interface{}]interface{}{"a": 1, "b": map[interface{}]interface{}{"c": 3}, "d": "replaced", "e": "added"}
|
||||
assert.Equal(expected, util.MapsUnion(m0, m1, util.Replace))
|
||||
}
|
||||
|
||||
func TestFilterKey(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
data := map[interface{}]interface{}{
|
||||
"ssh_authorized_keys": []string{"pubk1", "pubk2"},
|
||||
"hostname": "ros-test",
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"ssh": map[interface{}]interface{}{
|
||||
"keys": map[interface{}]interface{}{
|
||||
"dsa": "dsa-test1",
|
||||
"dsa-pub": "dsa-test2",
|
||||
},
|
||||
},
|
||||
"user_docker": map[interface{}]interface{}{
|
||||
"ca_key": "ca_key-test3",
|
||||
"ca_cert": "ca_cert-test4",
|
||||
"args": []string{"args_test5"},
|
||||
},
|
||||
},
|
||||
"key5": 5,
|
||||
}
|
||||
expectedFiltered := map[interface{}]interface{}{
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"ssh": map[interface{}]interface{}{
|
||||
"keys": map[interface{}]interface{}{
|
||||
"dsa": "dsa-test1",
|
||||
"dsa-pub": "dsa-test2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
expectedRest := map[interface{}]interface{}{
|
||||
"ssh_authorized_keys": []string{"pubk1", "pubk2"},
|
||||
"hostname": "ros-test",
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"user_docker": map[interface{}]interface{}{
|
||||
"ca_key": "ca_key-test3",
|
||||
"ca_cert": "ca_cert-test4",
|
||||
"args": []string{"args_test5"},
|
||||
},
|
||||
},
|
||||
}
|
||||
filtered, rest := filterKey(data, []string{"rancher", "ssh"})
|
||||
assert.Equal(expectedFiltered, filtered)
|
||||
assert.Equal(expectedRest, rest)
|
||||
}
|
||||
|
||||
func TestFilterDottedKeys(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
data := map[interface{}]interface{}{
|
||||
"ssh_authorized_keys": []string{"pubk1", "pubk2"},
|
||||
"hostname": "ros-test",
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"ssh": map[interface{}]interface{}{
|
||||
"keys": map[interface{}]interface{}{
|
||||
"dsa": "dsa-test1",
|
||||
"dsa-pub": "dsa-test2",
|
||||
},
|
||||
},
|
||||
"user_docker": map[interface{}]interface{}{
|
||||
"ca_key": "ca_key-test3",
|
||||
"ca_cert": "ca_cert-test4",
|
||||
"args": []string{"args_test5"},
|
||||
},
|
||||
},
|
||||
}
|
||||
expectedFiltered := map[interface{}]interface{}{
|
||||
"ssh_authorized_keys": []string{"pubk1", "pubk2"},
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"ssh": map[interface{}]interface{}{
|
||||
"keys": map[interface{}]interface{}{
|
||||
"dsa": "dsa-test1",
|
||||
"dsa-pub": "dsa-test2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
expectedRest := map[interface{}]interface{}{
|
||||
"hostname": "ros-test",
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"user_docker": map[interface{}]interface{}{
|
||||
"ca_key": "ca_key-test3",
|
||||
"ca_cert": "ca_cert-test4",
|
||||
"args": []string{"args_test5"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal([]string{"rancher", "ssh"}, strings.Split("rancher.ssh", "."))
|
||||
assert.Equal([]string{"ssh_authorized_keys"}, strings.Split("ssh_authorized_keys", "."))
|
||||
|
||||
filtered, rest := filterDottedKeys(data, []string{"ssh_authorized_keys", "rancher.ssh"})
|
||||
|
||||
assert.Equal(expectedFiltered, filtered)
|
||||
assert.Equal(expectedRest, rest)
|
||||
}
|
||||
|
||||
func TestParseCmdline(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
expected := map[interface{}]interface{}{
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"rescue": true,
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"keyArray": []string{"1", "2"},
|
||||
"obj1": map[interface{}]interface{}{
|
||||
"key3": "3value",
|
||||
"obj2": map[interface{}]interface{}{
|
||||
"key4": true,
|
||||
},
|
||||
},
|
||||
"key5": 5,
|
||||
},
|
||||
}
|
||||
|
||||
actual := parseCmdline("a b rancher.rescue rancher.keyArray=[1,2] rancher.key1=value1 c rancher.key2=value2 rancher.obj1.key3=3value rancher.obj1.obj2.key4 rancher.key5=5")
|
||||
|
||||
ok := reflect.DeepEqual(actual, expected)
|
||||
if !ok {
|
||||
t.Fatalf("%v != %v", actual, expected)
|
||||
}
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
data := map[interface{}]interface{}{
|
||||
"key": "value",
|
||||
"key2": map[interface{}]interface{}{
|
||||
"subkey": "subvalue",
|
||||
"subnum": 42,
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"key2": map[interface{}]interface{}{
|
||||
"subkey": "subvalue",
|
||||
"subnum": 42,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := map[string]interface{}{
|
||||
"key": "value",
|
||||
"key2.subkey": "subvalue",
|
||||
"key2.subnum": 42,
|
||||
"key2.subkey2": "",
|
||||
"foo": "",
|
||||
"key": "value",
|
||||
"rancher.key2.subkey": "subvalue",
|
||||
"rancher.key2.subnum": 42,
|
||||
"rancher.key2.subkey2": "",
|
||||
"foo": "",
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
if getOrSetVal(k, data, nil) != v {
|
||||
t.Fatalf("Expected %v, got %v, for key %s", v, getOrSetVal(k, data, nil), k)
|
||||
}
|
||||
assert.Equal(v, getOrSetVal(k, data, nil))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
data := map[interface{}]interface{}{
|
||||
"key": "value",
|
||||
"key2": map[interface{}]interface{}{
|
||||
"subkey": "subvalue",
|
||||
"subnum": 42,
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"key2": map[interface{}]interface{}{
|
||||
"subkey": "subvalue",
|
||||
"subnum": 42,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[interface{}]interface{}{
|
||||
"key": "value2",
|
||||
"key2": map[interface{}]interface{}{
|
||||
"subkey": "subvalue2",
|
||||
"subkey2": "value",
|
||||
"subkey3": 43,
|
||||
"subnum": 42,
|
||||
},
|
||||
"key3": map[interface{}]interface{}{
|
||||
"subkey3": 44,
|
||||
"rancher": map[interface{}]interface{}{
|
||||
"key2": map[interface{}]interface{}{
|
||||
"subkey": "subvalue2",
|
||||
"subkey2": "value",
|
||||
"subkey3": 43,
|
||||
"subnum": 42,
|
||||
},
|
||||
"key3": map[interface{}]interface{}{
|
||||
"subkey3": 44,
|
||||
},
|
||||
},
|
||||
"key4": "value4",
|
||||
}
|
||||
|
||||
tests := map[string]interface{}{
|
||||
"key": "value2",
|
||||
"key2.subkey": "subvalue2",
|
||||
"key2.subkey2": "value",
|
||||
"key2.subkey3": 43,
|
||||
"key3.subkey3": 44,
|
||||
"key4": "value4",
|
||||
"key": "value2",
|
||||
"rancher.key2.subkey": "subvalue2",
|
||||
"rancher.key2.subkey2": "value",
|
||||
"rancher.key2.subkey3": 43,
|
||||
"rancher.key3.subkey3": 44,
|
||||
"key4": "value4",
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
getOrSetVal(k, data, v)
|
||||
if getOrSetVal(k, data, nil) != v {
|
||||
t.Fatalf("Expected %v, got %v, for key %s", v, getOrSetVal(k, data, nil), k)
|
||||
}
|
||||
assert.Equal(v, getOrSetVal(k, data, nil))
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(data, expected) {
|
||||
t.Fatalf("Expected %v, got %v", expected, data)
|
||||
}
|
||||
assert.Equal(expected, data)
|
||||
}
|
||||
|
||||
type OuterData struct {
|
||||
@@ -149,43 +299,35 @@ one:
|
||||
}
|
||||
|
||||
func TestUserDocker(t *testing.T) {
|
||||
config := &Config{
|
||||
UserDocker: DockerConfig{
|
||||
TLS: true,
|
||||
assert := require.New(t)
|
||||
|
||||
config := &CloudConfig{
|
||||
Rancher: RancherConfig{
|
||||
UserDocker: DockerConfig{
|
||||
TLS: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
bytes, err := yaml.Marshal(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
assert.Nil(err)
|
||||
|
||||
config = NewConfig()
|
||||
err = yaml.Unmarshal(bytes, config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
assert.Nil(err)
|
||||
|
||||
data := make(map[interface{}]interface{})
|
||||
data := make(map[interface{}]map[interface{}]interface{})
|
||||
util.Convert(config, data)
|
||||
|
||||
fmt.Println(data)
|
||||
|
||||
val, ok := data["user_docker"]
|
||||
if !ok {
|
||||
t.Fatal("Failed to find user_docker")
|
||||
}
|
||||
val, ok := data["rancher"]["user_docker"]
|
||||
assert.True(ok)
|
||||
|
||||
if m, ok := val.(map[interface{}]interface{}); ok {
|
||||
if v, ok := m["tls"]; ok {
|
||||
if v != true {
|
||||
t.Fatal("user_docker.tls is not true")
|
||||
}
|
||||
} else {
|
||||
t.Fatal("user_docker.tls is not found")
|
||||
}
|
||||
} else {
|
||||
t.Fatal("Bad data")
|
||||
}
|
||||
m, ok := val.(map[interface{}]interface{})
|
||||
assert.True(ok)
|
||||
v, ok := m["tls"]
|
||||
assert.True(ok)
|
||||
assert.True(v.(bool))
|
||||
|
||||
}
|
||||
|
@@ -3,11 +3,60 @@ package config
|
||||
import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/rancherio/os/util"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func filterKey(data map[interface{}]interface{}, key []string) (filtered, rest map[interface{}]interface{}) {
|
||||
if len(key) == 0 {
|
||||
return data, map[interface{}]interface{}{}
|
||||
}
|
||||
|
||||
filtered = map[interface{}]interface{}{}
|
||||
rest = util.MapCopy(data)
|
||||
|
||||
k := key[0]
|
||||
if d, ok := data[k]; ok {
|
||||
switch d := d.(type) {
|
||||
|
||||
case map[interface{}]interface{}:
|
||||
f, r := filterKey(d, key[1:])
|
||||
|
||||
if len(f) != 0 {
|
||||
filtered[k] = f
|
||||
}
|
||||
|
||||
if len(r) != 0 {
|
||||
rest[k] = r
|
||||
} else {
|
||||
delete(rest, k)
|
||||
}
|
||||
|
||||
default:
|
||||
filtered[k] = d
|
||||
delete(rest, k)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func filterDottedKeys(data map[interface{}]interface{}, keys []string) (filtered, rest map[interface{}]interface{}) {
|
||||
filtered = map[interface{}]interface{}{}
|
||||
rest = util.MapCopy(data)
|
||||
|
||||
for _, key := range keys {
|
||||
f, r := filterKey(data, strings.Split(key, "."))
|
||||
filtered = util.MapsUnion(filtered, f, util.Replace)
|
||||
rest = util.MapsIntersection(rest, r, util.Equal)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getOrSetVal(args string, data map[interface{}]interface{}, value interface{}) interface{} {
|
||||
parts := strings.Split(args, ".")
|
||||
|
||||
@@ -95,7 +144,7 @@ outer:
|
||||
}
|
||||
|
||||
current := result
|
||||
keys := strings.Split(kv[0], ".")[1:]
|
||||
keys := strings.Split(kv[0], ".")
|
||||
for i, key := range keys {
|
||||
if i == len(keys)-1 {
|
||||
current[key] = DummyMarshall(value)
|
||||
|
@@ -1,13 +1,14 @@
|
||||
package config
|
||||
|
||||
func NewConfig() *Config {
|
||||
func NewConfig() *CloudConfig {
|
||||
return ReadConfig(OsConfigFile)
|
||||
}
|
||||
|
||||
func ReadConfig(file string) *Config {
|
||||
func ReadConfig(file string) *CloudConfig {
|
||||
if data, err := readConfig(nil, file); err == nil {
|
||||
c := &Config{}
|
||||
c := &CloudConfig{}
|
||||
c.merge(data)
|
||||
c.amendNils()
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
|
@@ -18,38 +18,15 @@ func writeToFile(data interface{}, filename string) error {
|
||||
}
|
||||
|
||||
func saveToDisk(data map[interface{}]interface{}) error {
|
||||
config := make(map[interface{}]interface{})
|
||||
private := make(map[interface{}]interface{})
|
||||
private, config := filterDottedKeys(data, []string{
|
||||
"rancher.ssh",
|
||||
"rancher.user_docker.ca_key",
|
||||
"rancher.user_docker.ca_cert",
|
||||
"rancher.user_docker.server_key",
|
||||
"rancher.user_docker.server_cert",
|
||||
})
|
||||
|
||||
for k, v := range data {
|
||||
if k == "ssh" {
|
||||
private[k] = v
|
||||
} else if k == "user_docker" {
|
||||
var userDockerConfig DockerConfig
|
||||
var userDockerConfigPrivate DockerConfig
|
||||
err := util.Convert(v, &userDockerConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userDockerConfigPrivate.CAKey = userDockerConfig.CAKey
|
||||
userDockerConfigPrivate.CACert = userDockerConfig.CACert
|
||||
userDockerConfigPrivate.ServerKey = userDockerConfig.ServerKey
|
||||
userDockerConfigPrivate.ServerCert = userDockerConfig.ServerCert
|
||||
|
||||
userDockerConfig.CAKey = ""
|
||||
userDockerConfig.CACert = ""
|
||||
userDockerConfig.ServerKey = ""
|
||||
userDockerConfig.ServerCert = ""
|
||||
|
||||
config[k] = userDockerConfig
|
||||
private[k] = userDockerConfigPrivate
|
||||
} else {
|
||||
config[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
err := writeToFile(config, ConfigFile)
|
||||
err := writeToFile(config, LocalConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -57,10 +34,6 @@ func saveToDisk(data map[interface{}]interface{}) error {
|
||||
return writeToFile(private, PrivateConfigFile)
|
||||
}
|
||||
|
||||
func readSavedConfig(bytes []byte) (map[interface{}]interface{}, error) {
|
||||
return readConfig(bytes, CloudConfigFile, ConfigFile, PrivateConfigFile)
|
||||
}
|
||||
|
||||
func readConfig(bytes []byte, files ...string) (map[interface{}]interface{}, error) {
|
||||
// You can't just overlay yaml bytes on to maps, it won't merge, but instead
|
||||
// just override the keys and not merge the map values.
|
||||
@@ -77,7 +50,7 @@ func readConfig(bytes []byte, files ...string) (map[interface{}]interface{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
util.MergeMaps(left, right)
|
||||
left = util.MapsUnion(left, right, util.Replace)
|
||||
}
|
||||
|
||||
if bytes != nil && len(bytes) > 0 {
|
||||
@@ -86,7 +59,7 @@ func readConfig(bytes []byte, files ...string) (map[interface{}]interface{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
util.MergeMaps(left, right)
|
||||
left = util.MapsUnion(left, right, util.Replace)
|
||||
}
|
||||
|
||||
return left, nil
|
||||
|
@@ -6,9 +6,9 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
type InitFunc func(*Config) error
|
||||
type InitFunc func(*CloudConfig) error
|
||||
|
||||
func RunInitFuncs(cfg *Config, initFuncs []InitFunc) error {
|
||||
func RunInitFuncs(cfg *CloudConfig, initFuncs []InitFunc) error {
|
||||
for i, initFunc := range initFuncs {
|
||||
log.Debugf("[%d/%d] Starting", i+1, len(initFuncs))
|
||||
if err := initFunc(cfg); err != nil {
|
||||
|
@@ -1,6 +1,9 @@
|
||||
package config
|
||||
|
||||
import "github.com/rancherio/rancher-compose/librcompose/project"
|
||||
import (
|
||||
"github.com/coreos/coreos-cloudinit/config"
|
||||
"github.com/rancherio/rancher-compose/librcompose/project"
|
||||
)
|
||||
|
||||
const (
|
||||
CONSOLE_CONTAINER = "console"
|
||||
@@ -24,14 +27,17 @@ const (
|
||||
RELOAD_CONFIG = "io.rancher.os.reloadconfig"
|
||||
SCOPE = "io.rancher.os.scope"
|
||||
SYSTEM = "system"
|
||||
|
||||
OsConfigFile = "/os-config.yml"
|
||||
CloudConfigFile = "/var/lib/rancher/conf/cloud-config.yml"
|
||||
CloudConfigScriptFile = "/var/lib/rancher/conf/cloud-config-script"
|
||||
MetaDataFile = "/var/lib/rancher/conf/metadata"
|
||||
LocalConfigFile = "/var/lib/rancher/conf/cloud-config-local.yml"
|
||||
PrivateConfigFile = "/var/lib/rancher/conf/cloud-config-private.yml"
|
||||
)
|
||||
|
||||
var (
|
||||
VERSION string
|
||||
OsConfigFile = "/os-config.yml"
|
||||
CloudConfigFile = "/var/lib/rancher/conf/cloud-config-rancher.yml"
|
||||
ConfigFile = "/var/lib/rancher/conf/rancher.yml"
|
||||
PrivateConfigFile = "/var/lib/rancher/conf/rancher-private.yml"
|
||||
VERSION string
|
||||
)
|
||||
|
||||
type ContainerConfig struct {
|
||||
@@ -49,7 +55,16 @@ type Repository struct {
|
||||
|
||||
type Repositories map[string]Repository
|
||||
|
||||
type Config struct {
|
||||
type CloudConfig struct {
|
||||
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
|
||||
WriteFiles []config.File `yaml:"write_files"`
|
||||
Hostname string `yaml:"hostname"`
|
||||
Users []config.User `yaml:"users"`
|
||||
|
||||
Rancher RancherConfig `yaml:"rancher,omitempty"`
|
||||
}
|
||||
|
||||
type RancherConfig struct {
|
||||
Environment map[string]string `yaml:"environment,omitempty"`
|
||||
Services map[string]*project.ServiceConfig `yaml:"services,omitempty"`
|
||||
BootstrapContainers map[string]*project.ServiceConfig `yaml:"bootstrap,omitempty"`
|
||||
@@ -65,7 +80,6 @@ type Config struct {
|
||||
Repositories Repositories `yaml:"repositories,omitempty"`
|
||||
Ssh SshConfig `yaml:"ssh,omitempty"`
|
||||
State StateConfig `yaml:"state,omitempty"`
|
||||
SystemContainers map[string]*project.ServiceConfig `yaml:"system_containers,omitempty"`
|
||||
SystemDocker DockerConfig `yaml:"system_docker,omitempty"`
|
||||
Upgrade UpgradeConfig `yaml:"upgrade,omitempty"`
|
||||
UserContainers []ContainerConfig `yaml:"user_containers,omitempty"`
|
||||
|
@@ -282,12 +282,10 @@ func (c *Container) addLink(link string) {
|
||||
func (c *Container) parseService() {
|
||||
if c.requiresSyslog() {
|
||||
c.addLink("syslog")
|
||||
log.Infof("[%v]: Implicitly linked to 'syslog'", c.Name)
|
||||
}
|
||||
|
||||
if c.requiresUserDocker() {
|
||||
c.addLink("dockerwait")
|
||||
log.Infof("[%v]: Implicitly linked to 'dockerwait'", c.Name)
|
||||
} else if c.ContainerCfg.Service.Image != "" {
|
||||
client, err := NewClient(c.dockerHost)
|
||||
if err != nil {
|
||||
@@ -298,7 +296,6 @@ func (c *Container) parseService() {
|
||||
i, _ := client.InspectImage(c.ContainerCfg.Service.Image)
|
||||
if i == nil {
|
||||
c.addLink("network")
|
||||
log.Infof("[%v]: Implicitly linked to 'network'", c.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,6 +535,7 @@ func appendVolumesFrom(client *dockerClient.Client, containerCfg *config.Contain
|
||||
}
|
||||
|
||||
func (c *Container) start(createOnly, wait bool) *Container {
|
||||
log.Debugf("Container: STARTING '%v', createOnly: %v, !detach: %v, wait: %v", c.Name, createOnly, !c.detach, wait)
|
||||
c.Lookup()
|
||||
c.Stage()
|
||||
|
||||
@@ -619,9 +617,11 @@ func (c *Container) start(createOnly, wait bool) *Container {
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Container: WAIT? '%v' !c.detach && wait: %v", c.Name, !c.detach && wait)
|
||||
if !c.detach && wait {
|
||||
var exitCode int
|
||||
exitCode, c.Err = client.WaitContainer(c.Container.ID)
|
||||
log.Debugf("Container: FINISHED '%v', exitCode: %v", c.Name, exitCode)
|
||||
if exitCode != 0 {
|
||||
c.Err = errors.New(fmt.Sprintf("Container %s exited with code %d", c.Name, exitCode))
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type ContainerFactory struct {
|
||||
cfg *config.Config
|
||||
cfg *config.CloudConfig
|
||||
}
|
||||
|
||||
type containerBasedService struct {
|
||||
@@ -18,10 +18,10 @@ type containerBasedService struct {
|
||||
project *project.Project
|
||||
container *Container
|
||||
serviceConfig *project.ServiceConfig
|
||||
cfg *config.Config
|
||||
cfg *config.CloudConfig
|
||||
}
|
||||
|
||||
func NewContainerFactory(cfg *config.Config) *ContainerFactory {
|
||||
func NewContainerFactory(cfg *config.CloudConfig) *ContainerFactory {
|
||||
return &ContainerFactory{
|
||||
cfg: cfg,
|
||||
}
|
||||
@@ -34,7 +34,7 @@ func (c *containerBasedService) Up() error {
|
||||
fakeCreate := false
|
||||
create := containerCfg.CreateOnly
|
||||
|
||||
if util.Contains(c.cfg.Disable, c.name) {
|
||||
if util.Contains(c.cfg.Rancher.Disable, c.name) {
|
||||
fakeCreate = true
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
type configEnvironment struct {
|
||||
cfg *config.Config
|
||||
cfg *config.CloudConfig
|
||||
}
|
||||
|
||||
func appendEnv(array []string, key, value string) []string {
|
||||
@@ -23,11 +23,11 @@ func appendEnv(array []string, key, value string) []string {
|
||||
return append(array, fmt.Sprintf("%s=%s", key, value))
|
||||
}
|
||||
|
||||
func lookupKeys(cfg *config.Config, keys ...string) []string {
|
||||
func lookupKeys(cfg *config.CloudConfig, keys ...string) []string {
|
||||
for _, key := range keys {
|
||||
if strings.HasSuffix(key, "*") {
|
||||
result := []string{}
|
||||
for envKey, envValue := range cfg.Environment {
|
||||
for envKey, envValue := range cfg.Rancher.Environment {
|
||||
keyPrefix := key[:len(key)-1]
|
||||
if strings.HasPrefix(envKey, keyPrefix) {
|
||||
result = appendEnv(result, envKey, envValue)
|
||||
@@ -37,7 +37,7 @@ func lookupKeys(cfg *config.Config, keys ...string) []string {
|
||||
if len(result) > 0 {
|
||||
return result
|
||||
}
|
||||
} else if value, ok := cfg.Environment[key]; ok {
|
||||
} else if value, ok := cfg.Rancher.Environment[key]; ok {
|
||||
return appendEnv([]string{}, key, value)
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (c *configEnvironment) Lookup(key, serviceName string, serviceConfig *proje
|
||||
return lookupKeys(c.cfg, fullKey, key)
|
||||
}
|
||||
|
||||
func RunServices(name string, cfg *config.Config, configs map[string]*project.ServiceConfig) error {
|
||||
func RunServices(name string, cfg *config.CloudConfig, configs map[string]*project.ServiceConfig) error {
|
||||
network := false
|
||||
projectEvents := make(chan project.ProjectEvent)
|
||||
p := project.NewProject(name, NewContainerFactory(cfg))
|
||||
@@ -61,21 +61,26 @@ func RunServices(name string, cfg *config.Config, configs map[string]*project.Se
|
||||
for name, serviceConfig := range configs {
|
||||
if err := p.AddConfig(name, serviceConfig); err != nil {
|
||||
log.Infof("Failed loading service %s", name)
|
||||
continue
|
||||
}
|
||||
enabled[name] = true
|
||||
}
|
||||
|
||||
p.ReloadCallback = func() error {
|
||||
err := cfg.Reload()
|
||||
if err != nil {
|
||||
if p.Name != "system-init" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := cfg.Reload(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for service, serviceEnabled := range cfg.ServicesInclude {
|
||||
for service, serviceEnabled := range cfg.Rancher.ServicesInclude {
|
||||
if !serviceEnabled {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := enabled[service]; ok {
|
||||
if en, ok := enabled[service]; ok && en {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -89,8 +94,7 @@ func RunServices(name string, cfg *config.Config, configs map[string]*project.Se
|
||||
continue
|
||||
}
|
||||
|
||||
err = p.Load(bytes)
|
||||
if err != nil {
|
||||
if err := p.Load(bytes); err != nil {
|
||||
log.Errorf("Failed to load %s : %v", service, err)
|
||||
continue
|
||||
}
|
||||
@@ -98,17 +102,15 @@ func RunServices(name string, cfg *config.Config, configs map[string]*project.Se
|
||||
enabled[service] = true
|
||||
}
|
||||
|
||||
for service, config := range cfg.Services {
|
||||
if _, ok := enabled[service]; ok {
|
||||
for service, config := range cfg.Rancher.Services {
|
||||
if en, ok := enabled[service]; ok && en {
|
||||
continue
|
||||
}
|
||||
|
||||
err = p.AddConfig(service, config)
|
||||
if err != nil {
|
||||
if err := p.AddConfig(service, config); err != nil {
|
||||
log.Errorf("Failed to load %s : %v", service, err)
|
||||
continue
|
||||
}
|
||||
|
||||
enabled[service] = true
|
||||
}
|
||||
|
||||
@@ -123,14 +125,13 @@ func RunServices(name string, cfg *config.Config, configs map[string]*project.Se
|
||||
}
|
||||
}()
|
||||
|
||||
err := p.ReloadCallback()
|
||||
if err != nil {
|
||||
if err := p.ReloadCallback(); err != nil {
|
||||
log.Errorf("Failed to reload %s : %v", name, err)
|
||||
return err
|
||||
}
|
||||
return p.Up()
|
||||
}
|
||||
|
||||
func LoadServiceResource(name string, network bool, cfg *config.Config) ([]byte, error) {
|
||||
return util.LoadResource(name, network, cfg.Repositories.ToArray())
|
||||
func LoadServiceResource(name string, network bool, cfg *config.CloudConfig) ([]byte, error) {
|
||||
return util.LoadResource(name, network, cfg.Rancher.Repositories.ToArray())
|
||||
}
|
||||
|
@@ -14,24 +14,24 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func autoformat(cfg *config.Config) error {
|
||||
if len(cfg.State.Autoformat) == 0 || util.ResolveDevice(cfg.State.Dev) != "" {
|
||||
func autoformat(cfg *config.CloudConfig) error {
|
||||
if len(cfg.Rancher.State.Autoformat) == 0 || util.ResolveDevice(cfg.Rancher.State.Dev) != "" {
|
||||
return nil
|
||||
}
|
||||
AUTOFORMAT := "AUTOFORMAT=" + strings.Join(cfg.State.Autoformat, " ")
|
||||
FORMATZERO := "FORMATZERO=" + fmt.Sprint(cfg.State.FormatZero)
|
||||
cfg.Autoformat["autoformat"].Environment = project.NewMaporEqualSlice([]string{AUTOFORMAT, FORMATZERO})
|
||||
AUTOFORMAT := "AUTOFORMAT=" + strings.Join(cfg.Rancher.State.Autoformat, " ")
|
||||
FORMATZERO := "FORMATZERO=" + fmt.Sprint(cfg.Rancher.State.FormatZero)
|
||||
cfg.Rancher.Autoformat["autoformat"].Environment = project.NewMaporEqualSlice([]string{AUTOFORMAT, FORMATZERO})
|
||||
log.Info("Running Autoformat services")
|
||||
err := docker.RunServices("autoformat", cfg, cfg.Autoformat)
|
||||
err := docker.RunServices("autoformat", cfg, cfg.Rancher.Autoformat)
|
||||
return err
|
||||
}
|
||||
|
||||
func runBootstrapContainers(cfg *config.Config) error {
|
||||
func runBootstrapContainers(cfg *config.CloudConfig) error {
|
||||
log.Info("Running Bootstrap services")
|
||||
return docker.RunServices("bootstrap", cfg, cfg.BootstrapContainers)
|
||||
return docker.RunServices("bootstrap", cfg, cfg.Rancher.BootstrapContainers)
|
||||
}
|
||||
|
||||
func startDocker(cfg *config.Config) (chan interface{}, error) {
|
||||
func startDocker(cfg *config.CloudConfig) (chan interface{}, error) {
|
||||
for _, d := range []string{config.DOCKER_SYSTEM_HOST, "/var/run"} {
|
||||
err := os.MkdirAll(d, 0700)
|
||||
if err != nil {
|
||||
@@ -39,8 +39,8 @@ func startDocker(cfg *config.Config) (chan interface{}, error) {
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command(cfg.BootstrapDocker.Args[0], cfg.BootstrapDocker.Args[1:]...)
|
||||
if cfg.Debug {
|
||||
cmd := exec.Command(cfg.Rancher.BootstrapDocker.Args[0], cfg.Rancher.BootstrapDocker.Args[1:]...)
|
||||
if cfg.Rancher.Debug {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func stopDocker(c chan interface{}) error {
|
||||
return os.RemoveAll(config.DOCKER_SYSTEM_HOME)
|
||||
}
|
||||
|
||||
func bootstrap(cfg *config.Config) error {
|
||||
func bootstrap(cfg *config.CloudConfig) error {
|
||||
log.Info("Launching Bootstrap Docker")
|
||||
c, err := startDocker(cfg)
|
||||
if err != nil {
|
||||
|
78
init/init.go
78
init/init.go
@@ -72,7 +72,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func createSymlinks(cfg *config.Config, symlinks map[string]string) error {
|
||||
func createSymlinks(cfg *config.CloudConfig, symlinks map[string]string) error {
|
||||
log.Debug("Creating symlinking")
|
||||
for dest, src := range symlinks {
|
||||
if _, err := os.Stat(dest); os.IsNotExist(err) {
|
||||
@@ -112,12 +112,12 @@ func createMounts(mounts ...[]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func remountRo(cfg *config.Config) error {
|
||||
func remountRo(cfg *config.CloudConfig) error {
|
||||
log.Info("Remouting root read only")
|
||||
return util.Remount("/", "ro")
|
||||
}
|
||||
|
||||
func mountCgroups(cfg *config.Config) error {
|
||||
func mountCgroups(cfg *config.CloudConfig) error {
|
||||
for _, cgroup := range cgroups {
|
||||
err := createDirs("/sys/fs/cgroup/" + cgroup)
|
||||
if err != nil {
|
||||
@@ -137,7 +137,7 @@ func mountCgroups(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractModules(cfg *config.Config) error {
|
||||
func extractModules(cfg *config.CloudConfig) error {
|
||||
if _, err := os.Stat(config.MODULES_ARCHIVE); os.IsNotExist(err) {
|
||||
log.Debug("Modules do not exist")
|
||||
return nil
|
||||
@@ -147,7 +147,7 @@ func extractModules(cfg *config.Config) error {
|
||||
return util.ExtractTar(config.MODULES_ARCHIVE, "/")
|
||||
}
|
||||
|
||||
func setResolvConf(cfg *config.Config) error {
|
||||
func setResolvConf(cfg *config.CloudConfig) error {
|
||||
log.Debug("Creating /etc/resolv.conf")
|
||||
//f, err := os.OpenFile("/etc/resolv.conf", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
f, err := os.Create("/etc/resolv.conf")
|
||||
@@ -157,14 +157,14 @@ func setResolvConf(cfg *config.Config) error {
|
||||
|
||||
defer f.Close()
|
||||
|
||||
for _, dns := range cfg.Network.Dns.Nameservers {
|
||||
for _, dns := range cfg.Rancher.Network.Dns.Nameservers {
|
||||
content := fmt.Sprintf("nameserver %s\n", dns)
|
||||
if _, err = f.Write([]byte(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
search := strings.Join(cfg.Network.Dns.Search, " ")
|
||||
search := strings.Join(cfg.Rancher.Network.Dns.Search, " ")
|
||||
if search != "" {
|
||||
content := fmt.Sprintf("search %s\n", search)
|
||||
if _, err = f.Write([]byte(content)); err != nil {
|
||||
@@ -172,8 +172,8 @@ func setResolvConf(cfg *config.Config) error {
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Network.Dns.Domain != "" {
|
||||
content := fmt.Sprintf("domain %s\n", cfg.Network.Dns.Domain)
|
||||
if cfg.Rancher.Network.Dns.Domain != "" {
|
||||
content := fmt.Sprintf("domain %s\n", cfg.Rancher.Network.Dns.Domain)
|
||||
if _, err = f.Write([]byte(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func setResolvConf(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadModules(cfg *config.Config) error {
|
||||
func loadModules(cfg *config.CloudConfig) error {
|
||||
filesystems, err := ioutil.ReadFile("/proc/filesystems")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -196,7 +196,7 @@ func loadModules(cfg *config.Config) error {
|
||||
}
|
||||
}
|
||||
|
||||
for _, module := range cfg.Modules {
|
||||
for _, module := range cfg.Rancher.Modules {
|
||||
log.Debugf("Loading module %s", module)
|
||||
err = exec.Command("/sbin/modprobe", module).Run()
|
||||
if err != nil {
|
||||
@@ -207,7 +207,7 @@ func loadModules(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func sysInit(cfg *config.Config) error {
|
||||
func sysInit(cfg *config.CloudConfig) error {
|
||||
args := append([]string{SYSINIT}, os.Args[1:]...)
|
||||
|
||||
var cmd *exec.Cmd
|
||||
@@ -227,9 +227,9 @@ func sysInit(cfg *config.Config) error {
|
||||
return os.Stdin.Close()
|
||||
}
|
||||
|
||||
func execDocker(cfg *config.Config) error {
|
||||
func execDocker(cfg *config.CloudConfig) error {
|
||||
log.Info("Launching System Docker")
|
||||
if !cfg.Debug {
|
||||
if !cfg.Rancher.Debug {
|
||||
output, err := os.Create("/var/log/system-docker.log")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -240,7 +240,7 @@ func execDocker(cfg *config.Config) error {
|
||||
}
|
||||
|
||||
os.Stdin.Close()
|
||||
return syscall.Exec(SYSTEM_DOCKER, cfg.SystemDocker.Args, os.Environ())
|
||||
return syscall.Exec(SYSTEM_DOCKER, cfg.Rancher.SystemDocker.Args, os.Environ())
|
||||
}
|
||||
|
||||
func MainInit() {
|
||||
@@ -249,24 +249,24 @@ func MainInit() {
|
||||
}
|
||||
}
|
||||
|
||||
func mountStateTmpfs(cfg *config.Config) error {
|
||||
func mountStateTmpfs(cfg *config.CloudConfig) error {
|
||||
log.Debugf("State will not be persisted")
|
||||
return util.Mount("none", STATE, "tmpfs", "")
|
||||
}
|
||||
|
||||
func mountState(cfg *config.Config) error {
|
||||
func mountState(cfg *config.CloudConfig) error {
|
||||
var err error
|
||||
|
||||
if cfg.State.Dev != "" {
|
||||
dev := util.ResolveDevice(cfg.State.Dev)
|
||||
if cfg.Rancher.State.Dev != "" {
|
||||
dev := util.ResolveDevice(cfg.Rancher.State.Dev)
|
||||
if dev == "" {
|
||||
msg := fmt.Sprintf("Could not resolve device %q", cfg.State.Dev)
|
||||
msg := fmt.Sprintf("Could not resolve device %q", cfg.Rancher.State.Dev)
|
||||
log.Infof(msg)
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
log.Infof("Mounting state device %s to %s", dev, STATE)
|
||||
|
||||
fsType := cfg.State.FsType
|
||||
fsType := cfg.Rancher.State.FsType
|
||||
if fsType == "auto" {
|
||||
fsType, err = util.GetFsType(dev)
|
||||
}
|
||||
@@ -282,16 +282,16 @@ func mountState(cfg *config.Config) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func tryMountAndBootstrap(cfg *config.Config) error {
|
||||
func tryMountAndBootstrap(cfg *config.CloudConfig) error {
|
||||
if err := mountState(cfg); err != nil {
|
||||
if err := bootstrap(cfg); err != nil {
|
||||
if cfg.State.Required {
|
||||
if cfg.Rancher.State.Required {
|
||||
return err
|
||||
}
|
||||
return mountStateTmpfs(cfg)
|
||||
}
|
||||
if err := mountState(cfg); err != nil {
|
||||
if cfg.State.Required {
|
||||
if cfg.Rancher.State.Required {
|
||||
return err
|
||||
}
|
||||
return mountStateTmpfs(cfg)
|
||||
@@ -300,11 +300,11 @@ func tryMountAndBootstrap(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createGroups(cfg *config.Config) error {
|
||||
func createGroups(cfg *config.CloudConfig) error {
|
||||
return ioutil.WriteFile("/etc/group", []byte("root:x:0:\n"), 0644)
|
||||
}
|
||||
|
||||
func touchSocket(cfg *config.Config) error {
|
||||
func touchSocket(cfg *config.CloudConfig) error {
|
||||
for _, path := range []string{"/var/run/docker.sock", "/var/run/system-docker.sock"} {
|
||||
if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
@@ -318,8 +318,8 @@ func touchSocket(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupSystemBridge(cfg *config.Config) error {
|
||||
bridge, cidr := cfg.SystemDocker.BridgeConfig()
|
||||
func setupSystemBridge(cfg *config.CloudConfig) error {
|
||||
bridge, cidr := cfg.Rancher.SystemDocker.BridgeConfig()
|
||||
if bridge == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -335,20 +335,20 @@ func setupSystemBridge(cfg *config.Config) error {
|
||||
}
|
||||
|
||||
func RunInit() error {
|
||||
var cfg config.Config
|
||||
var cfg config.CloudConfig
|
||||
|
||||
os.Setenv("PATH", "/sbin:/usr/sbin:/usr/bin")
|
||||
os.Setenv("DOCKER_RAMDISK", "true")
|
||||
|
||||
initFuncs := []config.InitFunc{
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
return createDirs(dirs...)
|
||||
},
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
log.Info("Setting up mounts")
|
||||
return createMounts(mounts...)
|
||||
},
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
newCfg, err := config.LoadConfig()
|
||||
if err == nil {
|
||||
newCfg, err = config.LoadConfig()
|
||||
@@ -357,17 +357,15 @@ func RunInit() error {
|
||||
*cfg = *newCfg
|
||||
}
|
||||
|
||||
if cfg.Debug {
|
||||
if cfg.Rancher.Debug {
|
||||
cfgString, _ := config.Dump(false, true)
|
||||
if cfgString != "" {
|
||||
log.Debugf("Config: %s", cfgString)
|
||||
}
|
||||
log.Debugf("os-config dump: \n%s", cfgString)
|
||||
}
|
||||
|
||||
return err
|
||||
},
|
||||
mountCgroups,
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
return createSymlinks(cfg, symlinks)
|
||||
},
|
||||
createGroups,
|
||||
@@ -376,15 +374,15 @@ func RunInit() error {
|
||||
setResolvConf,
|
||||
setupSystemBridge,
|
||||
tryMountAndBootstrap,
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
return cfg.Reload()
|
||||
},
|
||||
loadModules,
|
||||
setResolvConf,
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
return createDirs(postDirs...)
|
||||
},
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
return createMounts(postMounts...)
|
||||
},
|
||||
touchSocket,
|
||||
|
@@ -11,24 +11,6 @@ import (
|
||||
"github.com/rancherio/os/docker"
|
||||
)
|
||||
|
||||
func importImage(client *dockerClient.Client, name, fileName string) error {
|
||||
file, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
log.Debugf("Importing image for %s", fileName)
|
||||
repo, tag := dockerClient.ParseRepositoryTag(name)
|
||||
return client.ImportImage(dockerClient.ImportImageOptions{
|
||||
Source: "-",
|
||||
Repository: repo,
|
||||
Tag: tag,
|
||||
InputStream: file,
|
||||
})
|
||||
}
|
||||
|
||||
func hasImage(name string) bool {
|
||||
stamp := path.Join(STATE, name)
|
||||
if _, err := os.Stat(stamp); os.IsNotExist(err) {
|
||||
@@ -37,7 +19,7 @@ func hasImage(name string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func findImages(cfg *config.Config) ([]string, error) {
|
||||
func findImages(cfg *config.CloudConfig) ([]string, error) {
|
||||
log.Debugf("Looking for images at %s", config.IMAGES_PATH)
|
||||
|
||||
result := []string{}
|
||||
@@ -68,7 +50,7 @@ func findImages(cfg *config.Config) ([]string, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func loadImages(cfg *config.Config) error {
|
||||
func loadImages(cfg *config.CloudConfig) error {
|
||||
images, err := findImages(cfg)
|
||||
if err != nil || len(images) == 0 {
|
||||
return err
|
||||
@@ -106,12 +88,12 @@ func loadImages(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runContainers(cfg *config.Config) error {
|
||||
return docker.RunServices("system-init", cfg, cfg.SystemContainers)
|
||||
func runContainers(cfg *config.CloudConfig) error {
|
||||
return docker.RunServices("system-init", cfg, cfg.Rancher.Services)
|
||||
}
|
||||
|
||||
func tailConsole(cfg *config.Config) error {
|
||||
if !cfg.Console.Tail {
|
||||
func tailConsole(cfg *config.CloudConfig) error {
|
||||
if !cfg.Rancher.Console.Tail {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -120,7 +102,7 @@ func tailConsole(cfg *config.Config) error {
|
||||
return err
|
||||
}
|
||||
|
||||
console, ok := cfg.SystemContainers[config.CONSOLE_CONTAINER]
|
||||
console, ok := cfg.Rancher.Services[config.CONSOLE_CONTAINER]
|
||||
if !ok {
|
||||
log.Error("Console not found")
|
||||
return nil
|
||||
@@ -151,11 +133,11 @@ func SysInit() error {
|
||||
initFuncs := []config.InitFunc{
|
||||
loadImages,
|
||||
runContainers,
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
syscall.Sync()
|
||||
return nil
|
||||
},
|
||||
func(cfg *config.Config) error {
|
||||
func(cfg *config.CloudConfig) error {
|
||||
log.Infof("RancherOS %s started", config.VERSION)
|
||||
return nil
|
||||
},
|
||||
|
725
os-config.yml
725
os-config.yml
@@ -1,419 +1,310 @@
|
||||
bootstrap:
|
||||
udev:
|
||||
image: rancher/os-udev:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes:
|
||||
- /dev:/host/dev
|
||||
- /lib/modules:/lib/modules
|
||||
- /lib/firmware:/lib/firmware
|
||||
autoformat:
|
||||
rancher:
|
||||
bootstrap:
|
||||
udev:
|
||||
image: rancher/os-udev:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes:
|
||||
- /dev:/host/dev
|
||||
- /lib/modules:/lib/modules
|
||||
- /lib/firmware:/lib/firmware
|
||||
autoformat:
|
||||
image: rancher/os-autoformat:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
volumes: []
|
||||
udev:
|
||||
image: rancher/os-udev:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- autoformat
|
||||
log_driver: json-file
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes:
|
||||
- /dev:/host/dev
|
||||
- /lib/modules:/lib/modules
|
||||
- /lib/firmware:/lib/firmware
|
||||
bootstrap_docker:
|
||||
args: [docker, -d, -s, overlay, -b, none, --restart=false, -g, /var/lib/system-docker,
|
||||
-G, root, -H, 'unix:///var/run/system-docker.sock']
|
||||
cloud_init:
|
||||
datasources:
|
||||
- configdrive:/media/config-2
|
||||
services_include:
|
||||
ubuntu-console: false
|
||||
network:
|
||||
dns:
|
||||
nameservers: [8.8.8.8, 8.8.4.4]
|
||||
interfaces:
|
||||
eth*:
|
||||
dhcp: true
|
||||
lo:
|
||||
address: 127.0.0.1/8
|
||||
repositories:
|
||||
core:
|
||||
url: https://raw.githubusercontent.com/rancherio/os-services/v0.4.0
|
||||
state:
|
||||
fstype: auto
|
||||
dev: LABEL=RANCHER_STATE
|
||||
system_containers:
|
||||
acpid:
|
||||
image: rancher/os-acpid:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
all-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes_from:
|
||||
- docker-volumes
|
||||
- command-volumes
|
||||
- user-volumes
|
||||
- system-volumes
|
||||
cloud-init:
|
||||
image: rancher/os-cloudinit:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.reloadconfig: true
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- preload-user-images
|
||||
- cloud-init-pre
|
||||
- network
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
cloud-init-pre:
|
||||
image: rancher/os-cloudinit:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment:
|
||||
- CLOUD_INIT_NETWORK=false
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.reloadconfig: true
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- preload-system-images
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
command-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /init:/sbin/halt:ro
|
||||
- /init:/sbin/poweroff:ro
|
||||
- /init:/sbin/reboot:ro
|
||||
- /init:/sbin/shutdown:ro
|
||||
- /init:/sbin/netconf:ro
|
||||
- /init:/usr/bin/cloud-init:ro
|
||||
- /init:/usr/bin/rancherctl:ro
|
||||
- /init:/usr/bin/ros:ro
|
||||
- /init:/usr/bin/respawn:ro
|
||||
- /init:/usr/bin/system-docker:ro
|
||||
- /init:/usr/sbin/wait-for-docker:ro
|
||||
- /lib/modules:/lib/modules
|
||||
- /usr/bin/docker:/usr/bin/docker:ro
|
||||
console:
|
||||
image: rancher/os-console:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.remove: true
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init
|
||||
net: host
|
||||
uts: host
|
||||
pid: host
|
||||
ipc: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- all-volumes
|
||||
docker:
|
||||
image: rancher/os-docker:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- network
|
||||
net: host
|
||||
uts: host
|
||||
pid: host
|
||||
ipc: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- all-volumes
|
||||
docker-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /var/lib/rancher/conf:/var/lib/rancher/conf
|
||||
- /var/lib/docker:/var/lib/docker
|
||||
- /var/lib/system-docker:/var/lib/system-docker
|
||||
dockerwait:
|
||||
image: rancher/os-dockerwait:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- docker
|
||||
net: host
|
||||
uts: host
|
||||
volumes_from:
|
||||
- all-volumes
|
||||
autoformat:
|
||||
image: rancher/os-autoformat:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
udev:
|
||||
image: rancher/os-udev:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- autoformat
|
||||
log_driver: json-file
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes:
|
||||
- /dev:/host/dev
|
||||
- /lib/modules:/lib/modules
|
||||
- /lib/firmware:/lib/firmware
|
||||
bootstrap_docker:
|
||||
args: [docker, -d, -s, overlay, -b, none, --restart=false, -g, /var/lib/system-docker,
|
||||
-G, root, -H, 'unix:///var/run/system-docker.sock']
|
||||
cloud_init:
|
||||
datasources:
|
||||
- configdrive:/media/config-2
|
||||
services_include: {}
|
||||
network:
|
||||
image: rancher/os-network:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init-pre
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
ntp:
|
||||
image: rancher/os-ntp:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init
|
||||
- network
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
restart: always
|
||||
preload-system-images:
|
||||
image: rancher/os-preload:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
privileged: true
|
||||
volumes:
|
||||
- /var/run/system-docker.sock:/var/run/docker.sock
|
||||
- /var/lib/system-docker/preload:/mnt/preload
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
preload-user-images:
|
||||
image: rancher/os-preload:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- dockerwait
|
||||
privileged: true
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /var/lib/docker/preload:/mnt/preload
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
syslog:
|
||||
image: rancher/os-syslog:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- system-volumes
|
||||
system-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /dev:/host/dev
|
||||
- /os-config.yml:/os-config.yml
|
||||
- /var/lib/rancher:/var/lib/rancher
|
||||
- /var/lib/rancher/conf:/var/lib/rancher/conf
|
||||
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt.rancher
|
||||
- /lib/modules:/lib/modules
|
||||
- /lib/firmware:/lib/firmware
|
||||
- /var/run:/var/run
|
||||
- /var/log:/var/log
|
||||
udev:
|
||||
image: rancher/os-udev:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment:
|
||||
- DAEMON=true
|
||||
labels:
|
||||
io.rancher.os.detach: true
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- system-volumes
|
||||
user-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
command: []
|
||||
dns: []
|
||||
dns_search: []
|
||||
env_file: []
|
||||
environment: []
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
links: []
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /home:/home
|
||||
- /opt:/opt
|
||||
system_docker:
|
||||
args: [docker, -d, --log-driver, syslog, -s, overlay, -b, docker-sys, --fixed-cidr,
|
||||
172.18.42.1/16, --restart=false, -g, /var/lib/system-docker, -G, root,
|
||||
-H, 'unix:///var/run/system-docker.sock', --userland-proxy=false]
|
||||
upgrade:
|
||||
url: https://releases.rancher.com/os/versions.yml
|
||||
image: rancher/os
|
||||
user_docker:
|
||||
tls_args: [--tlsverify, --tlscacert=ca.pem, --tlscert=server-cert.pem, --tlskey=server-key.pem,
|
||||
'-H=0.0.0.0:2376']
|
||||
args: [docker, -d, -s, overlay, -G, docker, -H, 'unix:///var/run/docker.sock', --userland-proxy=false]
|
||||
dns:
|
||||
nameservers: [8.8.8.8, 8.8.4.4]
|
||||
interfaces:
|
||||
eth*:
|
||||
dhcp: true
|
||||
lo:
|
||||
address: 127.0.0.1/8
|
||||
repositories:
|
||||
core:
|
||||
url: https://raw.githubusercontent.com/rancherio/os-services/v0.4.0
|
||||
state:
|
||||
fstype: auto
|
||||
dev: LABEL=RANCHER_STATE
|
||||
services:
|
||||
acpid:
|
||||
image: rancher/os-acpid:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
all-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes_from:
|
||||
- docker-volumes
|
||||
- command-volumes
|
||||
- user-volumes
|
||||
- system-volumes
|
||||
cloud-init:
|
||||
image: rancher/os-cloudinit:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.reloadconfig: true
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init-pre
|
||||
- network
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
cloud-init-pre:
|
||||
image: rancher/os-cloudinit:v0.4.0-dev
|
||||
environment:
|
||||
- CLOUD_INIT_NETWORK=false
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.reloadconfig: true
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- preload-system-images
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
command-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /init:/sbin/halt:ro
|
||||
- /init:/sbin/poweroff:ro
|
||||
- /init:/sbin/reboot:ro
|
||||
- /init:/sbin/shutdown:ro
|
||||
- /init:/sbin/netconf:ro
|
||||
- /init:/usr/bin/cloud-init:ro
|
||||
- /init:/usr/bin/rancherctl:ro
|
||||
- /init:/usr/bin/ros:ro
|
||||
- /init:/usr/bin/respawn:ro
|
||||
- /init:/usr/bin/system-docker:ro
|
||||
- /init:/usr/sbin/wait-for-docker:ro
|
||||
- /lib/modules:/lib/modules
|
||||
- /usr/bin/docker:/usr/bin/docker:ro
|
||||
console:
|
||||
image: rancher/os-console:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.remove: true
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init
|
||||
- dockerwait # because console runs `loud-init -execute`, which may need docker
|
||||
net: host
|
||||
uts: host
|
||||
pid: host
|
||||
ipc: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- all-volumes
|
||||
docker:
|
||||
image: rancher/os-docker:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init
|
||||
- network
|
||||
net: host
|
||||
uts: host
|
||||
pid: host
|
||||
ipc: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- all-volumes
|
||||
docker-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /var/lib/rancher/conf:/var/lib/rancher/conf
|
||||
- /var/lib/docker:/var/lib/docker
|
||||
- /var/lib/system-docker:/var/lib/system-docker
|
||||
dockerwait:
|
||||
image: rancher/os-dockerwait:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- docker
|
||||
net: host
|
||||
uts: host
|
||||
volumes_from:
|
||||
- all-volumes
|
||||
network:
|
||||
image: rancher/os-network:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init-pre
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
ntp:
|
||||
image: rancher/os-ntp:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- cloud-init
|
||||
- network
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
restart: always
|
||||
preload-system-images:
|
||||
image: rancher/os-preload:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
privileged: true
|
||||
volumes:
|
||||
- /var/run/system-docker.sock:/var/run/docker.sock
|
||||
- /var/lib/system-docker/preload:/mnt/preload
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
preload-user-images:
|
||||
image: rancher/os-preload:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.detach: false
|
||||
io.rancher.os.scope: system
|
||||
links:
|
||||
- dockerwait
|
||||
privileged: true
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /var/lib/docker/preload:/mnt/preload
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
syslog:
|
||||
image: rancher/os-syslog:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- system-volumes
|
||||
system-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /dev:/host/dev
|
||||
- /os-config.yml:/os-config.yml
|
||||
- /var/lib/rancher:/var/lib/rancher
|
||||
- /var/lib/rancher/conf:/var/lib/rancher/conf
|
||||
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt.rancher
|
||||
- /lib/modules:/lib/modules
|
||||
- /lib/firmware:/lib/firmware
|
||||
- /var/run:/var/run
|
||||
- /var/log:/var/log
|
||||
udev:
|
||||
image: rancher/os-udev:v0.4.0-dev
|
||||
environment:
|
||||
- DAEMON=true
|
||||
labels:
|
||||
io.rancher.os.detach: true
|
||||
io.rancher.os.scope: system
|
||||
net: host
|
||||
uts: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- system-volumes
|
||||
user-volumes:
|
||||
image: rancher/os-state:v0.4.0-dev
|
||||
labels:
|
||||
io.rancher.os.createonly: true
|
||||
io.rancher.os.scope: system
|
||||
log_driver: json-file
|
||||
net: none
|
||||
privileged: true
|
||||
read_only: true
|
||||
volumes:
|
||||
- /home:/home
|
||||
- /opt:/opt
|
||||
system_docker:
|
||||
args: [docker, -d, --log-driver, syslog, -s, overlay, -b, docker-sys, --fixed-cidr,
|
||||
172.18.42.1/16, --restart=false, -g, /var/lib/system-docker, -G, root,
|
||||
-H, 'unix:///var/run/system-docker.sock', --userland-proxy=false]
|
||||
upgrade:
|
||||
url: https://releases.rancher.com/os/versions.yml
|
||||
image: rancher/os
|
||||
user_docker:
|
||||
tls_args: [--tlsverify, --tlscacert=ca.pem, --tlscert=server-cert.pem, --tlskey=server-key.pem,
|
||||
'-H=0.0.0.0:2376']
|
||||
args: [docker, -d, -s, overlay, -G, docker, -H, 'unix:///var/run/docker.sock', --userland-proxy=false]
|
||||
|
96
util/util.go
96
util/util.go
@@ -18,6 +18,7 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -154,6 +155,7 @@ func RandSeq(n int) string {
|
||||
func Convert(from, to interface{}) error {
|
||||
bytes, err := yaml.Marshal(from)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"from": from}).Panicln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -164,37 +166,93 @@ func MergeBytes(left, right []byte) ([]byte, error) {
|
||||
leftMap := make(map[interface{}]interface{})
|
||||
rightMap := make(map[interface{}]interface{})
|
||||
|
||||
err := yaml.Unmarshal(left, &leftMap)
|
||||
if err != nil {
|
||||
if err := yaml.Unmarshal(left, &leftMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(right, &rightMap)
|
||||
if err != nil {
|
||||
if err := yaml.Unmarshal(right, &rightMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
MergeMaps(leftMap, rightMap)
|
||||
|
||||
return yaml.Marshal(leftMap)
|
||||
return yaml.Marshal(MapsUnion(leftMap, rightMap, Replace))
|
||||
}
|
||||
|
||||
func MergeMaps(left, right map[interface{}]interface{}) {
|
||||
for k, v := range right {
|
||||
merged := false
|
||||
if existing, ok := left[k]; ok {
|
||||
if rightMap, ok := v.(map[interface{}]interface{}); ok {
|
||||
if leftMap, ok := existing.(map[interface{}]interface{}); ok {
|
||||
merged = true
|
||||
MergeMaps(leftMap, rightMap)
|
||||
func Copy(d interface{}) interface{} {
|
||||
switch d := d.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
return MapCopy(d)
|
||||
default:
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
func Replace(l, r interface{}) interface{} {
|
||||
return r
|
||||
}
|
||||
|
||||
func Equal(l, r interface{}) interface{} {
|
||||
if reflect.DeepEqual(l, r) {
|
||||
return l
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MapsUnion(left, right map[interface{}]interface{}, op func(interface{}, interface{}) interface{}) map[interface{}]interface{} {
|
||||
result := MapCopy(left)
|
||||
|
||||
for k, r := range right {
|
||||
if l, ok := result[k]; ok {
|
||||
switch l := l.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
switch r := r.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
result[k] = MapsUnion(l, r, op)
|
||||
default:
|
||||
result[k] = op(l, r)
|
||||
}
|
||||
default:
|
||||
result[k] = op(l, r)
|
||||
}
|
||||
} else {
|
||||
result[k] = Copy(r)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func MapsIntersection(left, right map[interface{}]interface{}, op func(interface{}, interface{}) interface{}) map[interface{}]interface{} {
|
||||
result := map[interface{}]interface{}{}
|
||||
|
||||
for k, l := range left {
|
||||
if r, ok := right[k]; ok {
|
||||
switch r := r.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
switch l := l.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
result[k] = MapsIntersection(l, r, op)
|
||||
default:
|
||||
if i := op(l, r); i != nil {
|
||||
result[k] = i
|
||||
}
|
||||
}
|
||||
default:
|
||||
if i := op(l, r); i != nil {
|
||||
result[k] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !merged {
|
||||
left[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func MapCopy(data map[interface{}]interface{}) map[interface{}]interface{} {
|
||||
result := map[interface{}]interface{}{}
|
||||
for k, v := range data {
|
||||
result[k] = Copy(v)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetServices(urls []string) ([]string, error) {
|
||||
|
Reference in New Issue
Block a user