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