1
0
mirror of https://github.com/rancher/os.git synced 2025-08-12 20:06:46 +00:00

Services as compose format

This commit is contained in:
Darren Shepherd 2015-04-15 23:16:23 -07:00
parent 61b5525d5b
commit be8fa8e5b7
6 changed files with 101 additions and 47 deletions

View File

@ -6,7 +6,6 @@ import (
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/rancherio/os/config" "github.com/rancherio/os/config"
"github.com/rancherio/os/util"
) )
func serviceSubCommands() []cli.Command { func serviceSubCommands() []cli.Command {
@ -37,21 +36,16 @@ func disable(c *cli.Context) {
} }
for _, service := range c.Args() { for _, service := range c.Args() {
filtered := make([]string, 0, len(c.Args())) if _, ok := cfg.Services[service]; !ok {
for _, existing := range cfg.EnabledServices { continue
if existing != service {
filtered = append(filtered, existing)
}
} }
if len(filtered) != len(c.Args()) { cfg.Services[service] = false
cfg.EnabledServices = filtered
changed = true changed = true
} }
}
if changed { if changed {
if err = cfg.Set("enabled_services", cfg.EnabledServices); err != nil { if err = cfg.Set("services", cfg.Services); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
@ -65,14 +59,14 @@ func enable(c *cli.Context) {
} }
for _, service := range c.Args() { for _, service := range c.Args() {
if !util.Contains(cfg.EnabledServices, service) { if val, ok := cfg.Services[service]; !ok || !val {
cfg.EnabledServices = append(cfg.EnabledServices, service) cfg.Services[service] = true
changed = true changed = true
} }
} }
if changed { if changed {
if err = cfg.Set("enabled_services", cfg.EnabledServices); err != nil { if err = cfg.Set("services", cfg.Services); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
@ -84,22 +78,11 @@ func list(c *cli.Context) {
log.Fatal(err) log.Fatal(err)
} }
enabled := map[string]bool{} for service, enabled := range cfg.Services {
if enabled {
for _, service := range cfg.EnabledServices {
enabled[service] = true
}
for service, _ := range cfg.Services {
if _, ok := enabled[service]; ok {
delete(enabled, service)
fmt.Printf("enabled %s\n", service) fmt.Printf("enabled %s\n", service)
} else { } else {
fmt.Printf("disabled %s\n", service) fmt.Printf("disabled %s\n", service)
} }
} }
for service, _ := range enabled {
fmt.Printf("enabled %s\n", service)
}
} }

View File

@ -301,8 +301,10 @@ func NewConfig() *Config {
Net: "host", Net: "host",
}, },
}, },
EnabledServices: []string{}, Services: map[string]bool{
Services: map[string]Config{ "ubuntu-console": false,
},
BundledServices: map[string]Config{
"ubuntu-console": { "ubuntu-console": {
SystemContainers: map[string]*project.ServiceConfig{ SystemContainers: map[string]*project.ServiceConfig{
"console": { "console": {

View File

@ -43,14 +43,15 @@ type ContainerConfig struct {
} }
type Config struct { type Config struct {
Services map[string]Config `yaml:"services,omitempty"` Environment map[string]string `yaml:"environment,omitempty"`
BundledServices map[string]Config `yaml:"bundled_services,omitempty"`
BootstrapContainers map[string]*project.ServiceConfig `yaml:"bootstrap_containers,omitempty"` BootstrapContainers map[string]*project.ServiceConfig `yaml:"bootstrap_containers,omitempty"`
BootstrapDocker DockerConfig `yaml:"bootstrap_docker,omitempty"` BootstrapDocker DockerConfig `yaml:"bootstrap_docker,omitempty"`
CloudInit CloudInit `yaml:"cloud_init,omitempty"` CloudInit CloudInit `yaml:"cloud_init,omitempty"`
Console ConsoleConfig `yaml:"console,omitempty"` Console ConsoleConfig `yaml:"console,omitempty"`
Debug bool `yaml:"debug,omitempty"` Debug bool `yaml:"debug,omitempty"`
Disable []string `yaml:"disable,omitempty"` Disable []string `yaml:"disable,omitempty"`
EnabledServices []string `yaml:"enabled_services,omitempty"` Services map[string]bool `yaml:"services,omitempty"`
Modules []string `yaml:"modules,omitempty"` Modules []string `yaml:"modules,omitempty"`
Network NetworkConfig `yaml:"network,omitempty"` Network NetworkConfig `yaml:"network,omitempty"`
Ssh SshConfig `yaml:"ssh,omitempty"` Ssh SshConfig `yaml:"ssh,omitempty"`

View File

@ -170,11 +170,36 @@ func (c *Container) Reset() *Container {
return c return c
} }
func (c *Container) requiresSyslog() bool {
return (c.ContainerCfg.Service.LogDriver == "" || c.ContainerCfg.Service.LogDriver == "syslog")
}
func (c *Container) hasLink(link string) bool {
return util.Contains(c.ContainerCfg.Service.Links, link)
}
func (c *Container) addLink(link string) {
c.ContainerCfg.Service.Links = append(c.ContainerCfg.Service.Links, link)
}
func (c *Container) parseService() { func (c *Container) parseService() {
if (c.ContainerCfg.Service.LogDriver == "" || c.ContainerCfg.Service.LogDriver == "syslog") && client, err := NewClient(c.dockerHost)
!util.Contains(c.ContainerCfg.Service.Links, "syslog") { if err != nil {
c.Err = err
return
}
if c.ContainerCfg.Service.Image != "" {
i, _ := client.InspectImage(c.ContainerCfg.Service.Image)
if i == nil && !c.hasLink("network") {
log.Debugf("Adding network link to %s", c.Name)
c.addLink("network")
}
}
if c.requiresSyslog() && !c.hasLink("syslog") {
log.Debugf("Adding syslog link to %s\n", c.Name) log.Debugf("Adding syslog link to %s\n", c.Name)
c.ContainerCfg.Service.Links = append(c.ContainerCfg.Service.Links, "syslog") c.addLink("syslog")
} }
cfg, hostConfig, err := docker.Convert(c.ContainerCfg.Service) cfg, hostConfig, err := docker.Convert(c.ContainerCfg.Service)

View File

@ -110,40 +110,51 @@ func loadImages(cfg *config.Config) error {
} }
func runServices(name string, cfg *config.Config, configs map[string]*project.ServiceConfig) error { func runServices(name string, cfg *config.Config, configs map[string]*project.ServiceConfig) error {
project := project.NewProject(name, docker.NewContainerFactory(cfg)) network := false
projectEvents := make(chan project.ProjectEvent)
p := project.NewProject(name, docker.NewContainerFactory(cfg))
p.AddListener(projectEvents)
enabled := make(map[string]bool) enabled := make(map[string]bool)
for name, serviceConfig := range configs { for name, serviceConfig := range configs {
if err := project.AddConfig(name, serviceConfig); err != nil { if err := p.AddConfig(name, serviceConfig); err != nil {
log.Infof("Failed loading service %s", name) log.Infof("Failed loading service %s", name)
} }
} }
project.ReloadCallback = func() error { p.ReloadCallback = func() error {
err := cfg.Reload() err := cfg.Reload()
if err != nil { if err != nil {
return err return err
} }
for _, service := range cfg.EnabledServices { for service, serviceEnabled := range cfg.Services {
if !serviceEnabled {
continue
}
if _, ok := enabled[service]; ok { if _, ok := enabled[service]; ok {
continue continue
} }
if config, ok := cfg.Services[service]; ok { if config, ok := cfg.BundledServices[service]; ok {
for name, s := range config.SystemContainers { for name, s := range config.SystemContainers {
if err := project.AddConfig(name, s); err != nil { if err := p.AddConfig(name, s); err != nil {
log.Errorf("Failed to load %s : %v", name, err) log.Errorf("Failed to load %s : %v", name, err)
} }
} }
} else { } else {
bytes, err := util.LoadResource(service) bytes, err := util.LoadResource(service, network)
if err != nil { if err != nil {
if err == util.ErrNoNetwork {
log.Debugf("Can not load %s, networking not enabled", service)
} else {
log.Errorf("Failed to load %s : %v", service, err) log.Errorf("Failed to load %s : %v", service, err)
}
continue continue
} }
err = project.Load(bytes) err = p.Load(bytes)
if err != nil { if err != nil {
log.Errorf("Failed to load %s : %v", service, err) log.Errorf("Failed to load %s : %v", service, err)
continue continue
@ -156,12 +167,20 @@ func runServices(name string, cfg *config.Config, configs map[string]*project.Se
return nil return nil
} }
err := project.ReloadCallback() go func() {
for event := range projectEvents {
if event.Event == project.CONTAINER_STARTED && event.Service.Name() == "network" {
network = true
}
}
}()
err := p.ReloadCallback()
if err != nil { if err != nil {
log.Errorf("Failed to reload %s : %v", name, err) log.Errorf("Failed to reload %s : %v", name, err)
return err return err
} }
return project.Up() return p.Up()
} }
func runContainers(cfg *config.Config) error { func runContainers(cfg *config.Config) error {

View File

@ -2,6 +2,7 @@ package util
import ( import (
"archive/tar" "archive/tar"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -18,6 +19,7 @@ import (
var ( var (
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
ErrNoNetwork = errors.New("Networking not available to load resource")
) )
func mountProc() error { func mountProc() error {
@ -168,6 +170,25 @@ func Convert(from, to interface{}) error {
return yaml.Unmarshal(bytes, to) return yaml.Unmarshal(bytes, to)
} }
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 {
return nil, err
}
err = yaml.Unmarshal(right, &rightMap)
if err != nil {
return nil, err
}
MergeMaps(leftMap, rightMap)
return yaml.Marshal(leftMap)
}
func MergeMaps(left, right map[interface{}]interface{}) { func MergeMaps(left, right map[interface{}]interface{}) {
for k, v := range right { for k, v := range right {
merged := false merged := false
@ -186,8 +207,11 @@ func MergeMaps(left, right map[interface{}]interface{}) {
} }
} }
func LoadResource(location string) ([]byte, error) { func LoadResource(location string, network bool) ([]byte, error) {
if strings.HasPrefix(location, "http:/") || strings.HasPrefix(location, "https:/") { if strings.HasPrefix(location, "http:/") || strings.HasPrefix(location, "https:/") {
if !network {
return nil, ErrNoNetwork
}
resp, err := http.Get(location) resp, err := http.Get(location)
if err != nil { if err != nil {
return nil, err return nil, err