1
0
mirror of https://github.com/rancher/os.git synced 2025-09-05 08:42:38 +00:00

Sync with libcompose

This commit is contained in:
Josh Curl
2016-05-23 17:21:28 -07:00
parent 448f12acb1
commit 42e48476e7
17 changed files with 278 additions and 182 deletions

View File

@@ -2,17 +2,24 @@ package compose
import (
"fmt"
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/docker/libcompose/cli/logger"
composeConfig "github.com/docker/libcompose/config"
"github.com/docker/libcompose/docker"
composeClient "github.com/docker/libcompose/docker/client"
"github.com/docker/libcompose/project"
"github.com/docker/libcompose/project/events"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/config"
rosDocker "github.com/rancher/os/docker"
"github.com/rancher/os/util"
)
func CreateService(cfg *config.CloudConfig, name string, serviceConfig *project.ServiceConfig) (project.Service, error) {
func CreateService(cfg *config.CloudConfig, name string, serviceConfig *composeConfig.ServiceConfigV1) (project.Service, error) {
if cfg == nil {
var err error
cfg, err = config.LoadConfig()
@@ -21,7 +28,7 @@ func CreateService(cfg *config.CloudConfig, name string, serviceConfig *project.
}
}
p, err := CreateServiceSet("once", cfg, map[string]*project.ServiceConfig{
p, err := CreateServiceSet("once", cfg, map[string]*composeConfig.ServiceConfigV1{
name: serviceConfig,
})
if err != nil {
@@ -31,7 +38,7 @@ func CreateService(cfg *config.CloudConfig, name string, serviceConfig *project.
return p.CreateService(name)
}
func CreateServiceSet(name string, cfg *config.CloudConfig, configs map[string]*project.ServiceConfig) (*project.Project, error) {
func CreateServiceSet(name string, cfg *config.CloudConfig, configs map[string]*composeConfig.ServiceConfigV1) (*project.Project, error) {
p, err := newProject(name, cfg, nil)
if err != nil {
return nil, err
@@ -42,21 +49,20 @@ func CreateServiceSet(name string, cfg *config.CloudConfig, configs map[string]*
return p, nil
}
func RunServiceSet(name string, cfg *config.CloudConfig, configs map[string]*project.ServiceConfig) (*project.Project, error) {
func RunServiceSet(name string, cfg *config.CloudConfig, configs map[string]*composeConfig.ServiceConfigV1) (*project.Project, error) {
p, err := CreateServiceSet(name, cfg, configs)
if err != nil {
return nil, err
}
return p, p.Up()
return p, p.Up(context.Background(), options.Up{})
}
func GetProject(cfg *config.CloudConfig, networkingAvailable bool) (*project.Project, error) {
return newCoreServiceProject(cfg, networkingAvailable)
}
func newProject(name string, cfg *config.CloudConfig, environmentLookup project.EnvironmentLookup) (*project.Project, error) {
clientFactory, err := rosDocker.NewClientFactory(docker.ClientOpts{})
func newProject(name string, cfg *config.CloudConfig, environmentLookup composeConfig.EnvironmentLookup) (*project.Project, error) {
clientFactory, err := rosDocker.NewClientFactory(composeClient.Options{})
if err != nil {
return nil, err
}
@@ -72,23 +78,75 @@ func newProject(name string, cfg *config.CloudConfig, environmentLookup project.
ClientFactory: clientFactory,
Context: project.Context{
ProjectName: name,
NoRecreate: true, // for libcompose to not recreate on project reload, looping up the boot :)
EnvironmentLookup: environmentLookup,
ServiceFactory: serviceFactory,
Log: cfg.Rancher.Log,
LoggerFactory: logger.NewColorLoggerFactory(),
},
}
serviceFactory.Context = context
return docker.NewProject(context)
return docker.NewProject(context, &composeConfig.ParseOptions{
Interpolate: true,
Validate: false,
Preprocess: preprocessServiceMap,
})
}
func addServices(p *project.Project, enabled map[interface{}]interface{}, configs map[string]*project.ServiceConfig) map[interface{}]interface{} {
func preprocessServiceMap(serviceMap composeConfig.RawServiceMap) (composeConfig.RawServiceMap, error) {
newServiceMap := make(composeConfig.RawServiceMap)
for k, v := range serviceMap {
newServiceMap[k] = make(composeConfig.RawService)
for k2, v2 := range v {
if k2 == "environment" || k2 == "labels" {
newServiceMap[k][k2] = preprocess(v2, true)
} else {
newServiceMap[k][k2] = preprocess(v2, false)
}
}
}
return newServiceMap, nil
}
func preprocess(item interface{}, replaceTypes bool) interface{} {
switch typedDatas := item.(type) {
case map[interface{}]interface{}:
newMap := make(map[interface{}]interface{})
for key, value := range typedDatas {
newMap[key] = preprocess(value, replaceTypes)
}
return newMap
case []interface{}:
// newArray := make([]interface{}, 0) will cause golint to complain
var newArray []interface{}
newArray = make([]interface{}, 0)
for _, value := range typedDatas {
newArray = append(newArray, preprocess(value, replaceTypes))
}
return newArray
default:
if replaceTypes {
return fmt.Sprint(item)
}
return item
}
}
func addServices(p *project.Project, enabled map[interface{}]interface{}, configs map[string]*composeConfig.ServiceConfigV1) map[interface{}]interface{} {
serviceConfigsV2, _ := composeConfig.ConvertServices(configs)
// Note: we ignore errors while loading services
unchanged := true
for name, serviceConfig := range configs {
hash := project.GetServiceHash(name, serviceConfig)
for name, serviceConfig := range serviceConfigsV2 {
hash := composeConfig.GetServiceHash(name, serviceConfig)
if enabled[name] == hash {
continue
@@ -121,8 +179,8 @@ func adjustContainerNames(m map[interface{}]interface{}) map[interface{}]interfa
return m
}
func newCoreServiceProject(cfg *config.CloudConfig, network bool) (*project.Project, error) {
projectEvents := make(chan project.Event)
func newCoreServiceProject(cfg *config.CloudConfig, useNetwork bool) (*project.Project, error) {
projectEvents := make(chan events.Event)
enabled := map[interface{}]interface{}{}
environmentLookup := rosDocker.NewConfigEnvironment(cfg)
@@ -151,7 +209,7 @@ func newCoreServiceProject(cfg *config.CloudConfig, network bool) (*project.Proj
continue
}
bytes, err := LoadServiceResource(service, network, cfg)
bytes, err := LoadServiceResource(service, useNetwork, cfg)
if err != nil {
if err == util.ErrNoNetwork {
log.Debugf("Can not load %s, networking not enabled", service)
@@ -185,8 +243,8 @@ func newCoreServiceProject(cfg *config.CloudConfig, network bool) (*project.Proj
go func() {
for event := range projectEvents {
if event.EventType == project.EventContainerStarted && event.ServiceName == "ntp" {
network = true
if event.EventType == events.ContainerStarted && event.ServiceName == "ntp" {
useNetwork = true
}
}
}()
@@ -229,15 +287,15 @@ func StageServices(cfg *config.CloudConfig, services ...string) error {
}
// Reduce service configurations to just image and labels
for serviceName, serviceConfig := range p.Configs {
p.Configs[serviceName] = &project.ServiceConfig{
for _, serviceName := range p.ServiceConfigs.Keys() {
serviceConfig, _ := p.ServiceConfigs.Get(serviceName)
p.ServiceConfigs.Add(serviceName, &composeConfig.ServiceConfig{
Image: serviceConfig.Image,
Labels: serviceConfig.Labels,
}
})
}
return p.Pull()
return p.Pull(context.Background())
}
func LoadServiceResource(name string, network bool, cfg *config.CloudConfig) ([]byte, error) {