1
0
mirror of https://github.com/rancher/os.git synced 2025-07-31 22:47:16 +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/rancherio/os/config"
"github.com/rancherio/os/util"
)
func serviceSubCommands() []cli.Command {
@ -37,21 +36,16 @@ func disable(c *cli.Context) {
}
for _, service := range c.Args() {
filtered := make([]string, 0, len(c.Args()))
for _, existing := range cfg.EnabledServices {
if existing != service {
filtered = append(filtered, existing)
}
if _, ok := cfg.Services[service]; !ok {
continue
}
if len(filtered) != len(c.Args()) {
cfg.EnabledServices = filtered
changed = true
}
cfg.Services[service] = false
changed = true
}
if changed {
if err = cfg.Set("enabled_services", cfg.EnabledServices); err != nil {
if err = cfg.Set("services", cfg.Services); err != nil {
log.Fatal(err)
}
}
@ -65,14 +59,14 @@ func enable(c *cli.Context) {
}
for _, service := range c.Args() {
if !util.Contains(cfg.EnabledServices, service) {
cfg.EnabledServices = append(cfg.EnabledServices, service)
if val, ok := cfg.Services[service]; !ok || !val {
cfg.Services[service] = true
changed = true
}
}
if changed {
if err = cfg.Set("enabled_services", cfg.EnabledServices); err != nil {
if err = cfg.Set("services", cfg.Services); err != nil {
log.Fatal(err)
}
}
@ -84,22 +78,11 @@ func list(c *cli.Context) {
log.Fatal(err)
}
enabled := map[string]bool{}
for _, service := range cfg.EnabledServices {
enabled[service] = true
}
for service, _ := range cfg.Services {
if _, ok := enabled[service]; ok {
delete(enabled, service)
for service, enabled := range cfg.Services {
if enabled {
fmt.Printf("enabled %s\n", service)
} else {
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",
},
},
EnabledServices: []string{},
Services: map[string]Config{
Services: map[string]bool{
"ubuntu-console": false,
},
BundledServices: map[string]Config{
"ubuntu-console": {
SystemContainers: map[string]*project.ServiceConfig{
"console": {

View File

@ -43,14 +43,15 @@ type ContainerConfig 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"`
BootstrapDocker DockerConfig `yaml:"bootstrap_docker,omitempty"`
CloudInit CloudInit `yaml:"cloud_init,omitempty"`
Console ConsoleConfig `yaml:"console,omitempty"`
Debug bool `yaml:"debug,omitempty"`
Disable []string `yaml:"disable,omitempty"`
EnabledServices []string `yaml:"enabled_services,omitempty"`
Services map[string]bool `yaml:"services,omitempty"`
Modules []string `yaml:"modules,omitempty"`
Network NetworkConfig `yaml:"network,omitempty"`
Ssh SshConfig `yaml:"ssh,omitempty"`

View File

@ -170,11 +170,36 @@ func (c *Container) Reset() *Container {
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() {
if (c.ContainerCfg.Service.LogDriver == "" || c.ContainerCfg.Service.LogDriver == "syslog") &&
!util.Contains(c.ContainerCfg.Service.Links, "syslog") {
client, err := NewClient(c.dockerHost)
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)
c.ContainerCfg.Service.Links = append(c.ContainerCfg.Service.Links, "syslog")
c.addLink("syslog")
}
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 {
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)
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)
}
}
project.ReloadCallback = func() error {
p.ReloadCallback = func() error {
err := cfg.Reload()
if err != nil {
return err
}
for _, service := range cfg.EnabledServices {
for service, serviceEnabled := range cfg.Services {
if !serviceEnabled {
continue
}
if _, ok := enabled[service]; ok {
continue
}
if config, ok := cfg.Services[service]; ok {
if config, ok := cfg.BundledServices[service]; ok {
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)
}
}
} else {
bytes, err := util.LoadResource(service)
bytes, err := util.LoadResource(service, network)
if err != nil {
log.Errorf("Failed to load %s : %v", service, err)
if err == util.ErrNoNetwork {
log.Debugf("Can not load %s, networking not enabled", service)
} else {
log.Errorf("Failed to load %s : %v", service, err)
}
continue
}
err = project.Load(bytes)
err = p.Load(bytes)
if err != nil {
log.Errorf("Failed to load %s : %v", service, err)
continue
@ -156,12 +167,20 @@ func runServices(name string, cfg *config.Config, configs map[string]*project.Se
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 {
log.Errorf("Failed to reload %s : %v", name, err)
return err
}
return project.Up()
return p.Up()
}
func runContainers(cfg *config.Config) error {

View File

@ -2,6 +2,7 @@ package util
import (
"archive/tar"
"errors"
"fmt"
"io"
"io/ioutil"
@ -17,7 +18,8 @@ import (
)
var (
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
ErrNoNetwork = errors.New("Networking not available to load resource")
)
func mountProc() error {
@ -168,6 +170,25 @@ func Convert(from, to interface{}) error {
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{}) {
for k, v := range right {
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 !network {
return nil, ErrNoNetwork
}
resp, err := http.Get(location)
if err != nil {
return nil, err