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:
parent
61b5525d5b
commit
be8fa8e5b7
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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": {
|
||||
|
@ -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"`
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
28
util/util.go
28
util/util.go
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user