1
0
mirror of https://github.com/rancher/os.git synced 2025-08-01 23:17:50 +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

@ -9,13 +9,15 @@ import (
"os"
"strings"
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
yaml "github.com/cloudfoundry-incubator/candiedyaml"
dockerClient "github.com/fsouza/go-dockerclient"
"github.com/codegangsta/cli"
"github.com/docker/libcompose/project"
dockerClient "github.com/docker/engine-api/client"
composeConfig "github.com/docker/libcompose/config"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/cmd/power"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
@ -127,8 +129,8 @@ func osMetaDataGet(c *cli.Context) {
}
for _, image := range images.Available {
_, err := client.InspectImage(image)
if err == dockerClient.ErrNoSuchImage {
_, _, err := client.ImageInspectWithRaw(context.Background(), image, false)
if dockerClient.IsErrImageNotFound(err) {
fmt.Println(image, "remote")
} else {
fmt.Println(image, "local")
@ -209,16 +211,16 @@ func startUpgradeContainer(image string, stage, force, reboot, kexec bool, upgra
}
}
container, err := compose.CreateService(nil, "os-upgrade", &project.ServiceConfig{
container, err := compose.CreateService(nil, "os-upgrade", &composeConfig.ServiceConfigV1{
LogDriver: "json-file",
Privileged: true,
Net: "host",
Pid: "host",
Image: image,
Labels: project.NewSliceorMap(map[string]string{
Labels: map[string]string{
config.SCOPE: config.SYSTEM,
}),
Command: project.NewCommand(command...),
},
Command: command,
})
if err != nil {
return err
@ -230,8 +232,8 @@ func startUpgradeContainer(image string, stage, force, reboot, kexec bool, upgra
}
// Only pull image if not found locally
if _, err := client.InspectImage(image); err != nil {
if err := container.Pull(); err != nil {
if _, _, err := client.ImageInspectWithRaw(context.Background(), image, false); err != nil {
if err := container.Pull(context.Background()); err != nil {
return err
}
}
@ -252,19 +254,19 @@ func startUpgradeContainer(image string, stage, force, reboot, kexec bool, upgra
// If there is already an upgrade container, delete it
// Up() should to this, but currently does not due to a bug
if err := container.Delete(); err != nil {
if err := container.Delete(context.Background(), options.Delete{}); err != nil {
return err
}
if err := container.Up(); err != nil {
if err := container.Up(context.Background(), options.Up{}); err != nil {
return err
}
if err := container.Log(); err != nil {
if err := container.Log(context.Background(), true); err != nil {
return err
}
if err := container.Delete(); err != nil {
if err := container.Delete(context.Background(), options.Delete{}); err != nil {
return err
}

View File

@ -17,7 +17,7 @@ import (
type projectFactory struct {
}
func (p *projectFactory) Create(c *cli.Context) (*project.Project, error) {
func (p *projectFactory) Create(c *cli.Context) (project.APIProject, error) {
cfg, err := config.LoadConfig()
if err != nil {
return nil, err

View File

@ -9,8 +9,12 @@ import (
"strings"
"syscall"
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
dockerClient "github.com/fsouza/go-dockerclient"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/filters"
"github.com/rancher/os/docker"
)
@ -36,12 +40,9 @@ func runDocker(name string) error {
cmd = os.Args
}
exiting, err := client.InspectContainer(name)
if exiting != nil {
err := client.RemoveContainer(dockerClient.RemoveContainerOptions{
ID: exiting.ID,
Force: true,
})
existing, err := client.ContainerInspect(context.Background(), name)
if err == nil && existing.ID != "" {
err := client.ContainerRemove(context.Background(), existing.ID, types.ContainerRemoveOptions{})
if err != nil {
return err
@ -53,48 +54,44 @@ func runDocker(name string) error {
return err
}
currentContainer, err := client.InspectContainer(currentContainerId)
currentContainer, err := client.ContainerInspect(context.Background(), currentContainerId)
if err != nil {
return err
}
powerContainer, err := client.CreateContainer(dockerClient.CreateContainerOptions{
Name: name,
Config: &dockerClient.Config{
powerContainer, err := client.ContainerCreate(context.Background(),
&container.Config{
Image: currentContainer.Config.Image,
Cmd: cmd,
Env: []string{
"IN_DOCKER=true",
},
},
HostConfig: &dockerClient.HostConfig{
&container.HostConfig{
PidMode: "host",
VolumesFrom: []string{
currentContainer.ID,
},
Privileged: true,
},
})
}, nil, name)
if err != nil {
return err
}
go func() {
client.AttachToContainer(dockerClient.AttachToContainerOptions{
Container: powerContainer.ID,
OutputStream: os.Stdout,
ErrorStream: os.Stderr,
Stderr: true,
Stdout: true,
client.ContainerAttach(context.Background(), powerContainer.ID, types.ContainerAttachOptions{
Stream: true,
Stderr: true,
Stdout: true,
})
}()
err = client.StartContainer(powerContainer.ID, powerContainer.HostConfig)
err = client.ContainerStart(context.Background(), powerContainer.ID)
if err != nil {
return err
}
_, err = client.WaitContainer(powerContainer.ID)
_, err = client.ContainerWait(context.Background(), powerContainer.ID)
if err != nil {
log.Fatal(err)
@ -172,14 +169,15 @@ func shutDownContainers() error {
return err
}
opts := dockerClient.ListContainersOptions{
All: true,
Filters: map[string][]string{
"status": {"running"},
},
filter := filters.NewArgs()
filter.Add("status", "running")
opts := types.ContainerListOptions{
All: true,
Filter: filter,
}
containers, err := client.ListContainers(opts)
containers, err := client.ContainerList(context.Background(), opts)
if err != nil {
return err
}
@ -197,7 +195,7 @@ func shutDownContainers() error {
}
log.Infof("Stopping %s : %v", container.ID[:12], container.Names)
stopErr := client.StopContainer(container.ID, uint(timeout))
stopErr := client.ContainerStop(context.Background(), container.ID, timeout)
if stopErr != nil {
stopErrorStrings = append(stopErrorStrings, " ["+container.ID+"] "+stopErr.Error())
}
@ -209,7 +207,7 @@ func shutDownContainers() error {
if container.ID == currentContainerId {
continue
}
_, waitErr := client.WaitContainer(container.ID)
_, waitErr := client.ContainerWait(context.Background(), container.ID)
if waitErr != nil {
waitErrorStrings = append(waitErrorStrings, " ["+container.ID+"] "+waitErr.Error())
}

View File

@ -11,8 +11,10 @@ import (
"syscall"
"time"
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
"github.com/docker/libcompose/docker"
composeClient "github.com/docker/libcompose/docker/client"
"github.com/docker/libcompose/project"
"github.com/rancher/os/cmd/control"
"github.com/rancher/os/compose"
@ -166,7 +168,7 @@ func getPid(service string, project *project.Project) (int, error) {
return 0, err
}
containers, err := s.Containers()
containers, err := s.Containers(context.Background())
if err != nil {
return 0, err
}
@ -175,7 +177,7 @@ func getPid(service string, project *project.Project) (int, error) {
return 0, nil
}
client, err := docker.CreateClient(docker.ClientOpts{
client, err := composeClient.Create(composeClient.Options{
Host: config.DOCKER_SYSTEM_HOST,
})
if err != nil {
@ -187,8 +189,8 @@ func getPid(service string, project *project.Project) (int, error) {
return 0, err
}
info, err := client.InspectContainer(id)
if err != nil || info == nil {
info, err := client.ContainerInspect(context.Background(), id)
if err != nil || info.ID == "" {
return 0, err
}

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) {

View File

@ -11,7 +11,7 @@ import (
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/coreos/coreos-cloudinit/datasource"
"github.com/coreos/coreos-cloudinit/initialize"
"github.com/docker/libcompose/project"
composeConfig "github.com/docker/libcompose/config"
"github.com/rancher/os/util"
)
@ -191,13 +191,13 @@ func amendNils(c *CloudConfig) (*CloudConfig, error) {
t.Rancher.Environment = map[string]string{}
}
if t.Rancher.Autoformat == nil {
t.Rancher.Autoformat = map[string]*project.ServiceConfig{}
t.Rancher.Autoformat = map[string]*composeConfig.ServiceConfigV1{}
}
if t.Rancher.BootstrapContainers == nil {
t.Rancher.BootstrapContainers = map[string]*project.ServiceConfig{}
t.Rancher.BootstrapContainers = map[string]*composeConfig.ServiceConfigV1{}
}
if t.Rancher.Services == nil {
t.Rancher.Services = map[string]*project.ServiceConfig{}
t.Rancher.Services = map[string]*composeConfig.ServiceConfigV1{}
}
if t.Rancher.ServicesInclude == nil {
t.Rancher.ServicesInclude = map[string]bool{}
@ -206,7 +206,7 @@ func amendNils(c *CloudConfig) (*CloudConfig, error) {
}
func amendContainerNames(c *CloudConfig) (*CloudConfig, error) {
for _, scm := range []map[string]*project.ServiceConfig{
for _, scm := range []map[string]*composeConfig.ServiceConfigV1{
c.Rancher.Autoformat,
c.Rancher.BootstrapContainers,
c.Rancher.Services,

View File

@ -1,10 +1,11 @@
package config
import (
"github.com/coreos/coreos-cloudinit/config"
"github.com/docker/libcompose/project"
"github.com/rancher/netconf"
"runtime"
"github.com/coreos/coreos-cloudinit/config"
composeConfig "github.com/docker/libcompose/config"
"github.com/rancher/netconf"
)
const (
@ -77,27 +78,27 @@ type CloudConfig struct {
}
type RancherConfig struct {
Environment map[string]string `yaml:"environment,omitempty"`
Services map[string]*project.ServiceConfig `yaml:"services,omitempty"`
BootstrapContainers map[string]*project.ServiceConfig `yaml:"bootstrap,omitempty"`
Autoformat map[string]*project.ServiceConfig `yaml:"autoformat,omitempty"`
BootstrapDocker DockerConfig `yaml:"bootstrap_docker,omitempty"`
CloudInit CloudInit `yaml:"cloud_init,omitempty"`
Debug bool `yaml:"debug,omitempty"`
RmUsr bool `yaml:"rm_usr,omitempty"`
Log bool `yaml:"log,omitempty"`
ForceConsoleRebuild bool `yaml:"force_console_rebuild,omitempty"`
Disable []string `yaml:"disable,omitempty"`
ServicesInclude map[string]bool `yaml:"services_include,omitempty"`
Modules []string `yaml:"modules,omitempty"`
Network netconf.NetworkConfig `yaml:"network,omitempty"`
DefaultNetwork netconf.NetworkConfig `yaml:"default_network,omitempty"`
Repositories Repositories `yaml:"repositories,omitempty"`
Ssh SshConfig `yaml:"ssh,omitempty"`
State StateConfig `yaml:"state,omitempty"`
SystemDocker DockerConfig `yaml:"system_docker,omitempty"`
Upgrade UpgradeConfig `yaml:"upgrade,omitempty"`
Docker DockerConfig `yaml:"docker,omitempty"`
Environment map[string]string `yaml:"environment,omitempty"`
Services map[string]*composeConfig.ServiceConfigV1 `yaml:"services,omitempty"`
BootstrapContainers map[string]*composeConfig.ServiceConfigV1 `yaml:"bootstrap,omitempty"`
Autoformat map[string]*composeConfig.ServiceConfigV1 `yaml:"autoformat,omitempty"`
BootstrapDocker DockerConfig `yaml:"bootstrap_docker,omitempty"`
CloudInit CloudInit `yaml:"cloud_init,omitempty"`
Debug bool `yaml:"debug,omitempty"`
RmUsr bool `yaml:"rm_usr,omitempty"`
Log bool `yaml:"log,omitempty"`
ForceConsoleRebuild bool `yaml:"force_console_rebuild,omitempty"`
Disable []string `yaml:"disable,omitempty"`
ServicesInclude map[string]bool `yaml:"services_include,omitempty"`
Modules []string `yaml:"modules,omitempty"`
Network netconf.NetworkConfig `yaml:"network,omitempty"`
DefaultNetwork netconf.NetworkConfig `yaml:"default_network,omitempty"`
Repositories Repositories `yaml:"repositories,omitempty"`
Ssh SshConfig `yaml:"ssh,omitempty"`
State StateConfig `yaml:"state,omitempty"`
SystemDocker DockerConfig `yaml:"system_docker,omitempty"`
Upgrade UpgradeConfig `yaml:"upgrade,omitempty"`
Docker DockerConfig `yaml:"docker,omitempty"`
}
type UpgradeConfig struct {

View File

@ -1,26 +1,27 @@
package docker
import (
dockerClient "github.com/fsouza/go-dockerclient"
dockerClient "github.com/docker/engine-api/client"
"github.com/rancher/os/config"
"golang.org/x/net/context"
)
func NewSystemClient() (*dockerClient.Client, error) {
func NewSystemClient() (dockerClient.APIClient, error) {
return NewClient(config.DOCKER_SYSTEM_HOST)
}
func NewDefaultClient() (*dockerClient.Client, error) {
func NewDefaultClient() (dockerClient.APIClient, error) {
return NewClient(config.DOCKER_HOST)
}
func NewClient(endpoint string) (*dockerClient.Client, error) {
client, err := dockerClient.NewClient(endpoint)
func NewClient(endpoint string) (dockerClient.APIClient, error) {
client, err := dockerClient.NewClient(endpoint, "", nil, nil)
if err != nil {
return nil, err
}
err = ClientOK(endpoint, func() bool {
_, err := client.Info()
_, err := client.Info(context.Background())
return err == nil
})

View File

@ -4,34 +4,36 @@ import (
"fmt"
"sync"
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
"github.com/docker/libcompose/docker"
dockerclient "github.com/docker/engine-api/client"
composeClient "github.com/docker/libcompose/docker/client"
"github.com/docker/libcompose/project"
dockerclient "github.com/fsouza/go-dockerclient"
"github.com/rancher/os/config"
"github.com/rancher/os/util"
)
type ClientFactory struct {
userClient *dockerclient.Client
systemClient *dockerclient.Client
userClient dockerclient.APIClient
systemClient dockerclient.APIClient
userOnce sync.Once
systemOnce sync.Once
}
func NewClientFactory(opts docker.ClientOpts) (docker.ClientFactory, error) {
func NewClientFactory(opts composeClient.Options) (project.ClientFactory, error) {
userOpts := opts
systemOpts := opts
userOpts.Host = config.DOCKER_HOST
systemOpts.Host = config.DOCKER_SYSTEM_HOST
userClient, err := docker.CreateClient(userOpts)
userClient, err := composeClient.Create(userOpts)
if err != nil {
return nil, err
}
systemClient, err := docker.CreateClient(systemOpts)
systemClient, err := composeClient.Create(systemOpts)
if err != nil {
return nil, err
}
@ -42,7 +44,7 @@ func NewClientFactory(opts docker.ClientOpts) (docker.ClientFactory, error) {
}, nil
}
func (c *ClientFactory) Create(service project.Service) *dockerclient.Client {
func (c *ClientFactory) Create(service project.Service) dockerclient.APIClient {
if IsSystemContainer(service.Config()) {
waitFor(&c.systemOnce, c.systemClient, config.DOCKER_SYSTEM_HOST)
return c.systemClient
@ -52,10 +54,10 @@ func (c *ClientFactory) Create(service project.Service) *dockerclient.Client {
return c.userClient
}
func waitFor(once *sync.Once, client *dockerclient.Client, endpoint string) {
func waitFor(once *sync.Once, client dockerclient.APIClient, endpoint string) {
once.Do(func() {
err := ClientOK(endpoint, func() bool {
_, err := client.Info()
_, err := client.Info(context.Background())
return err == nil
})
if err != nil {

View File

@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"github.com/docker/libcompose/project"
composeConfig "github.com/docker/libcompose/config"
"github.com/rancher/os/config"
)
@ -53,7 +53,7 @@ func (c *ConfigEnvironment) SetConfig(cfg *config.CloudConfig) {
c.cfg = cfg
}
func (c *ConfigEnvironment) Lookup(key, serviceName string, serviceConfig *project.ServiceConfig) []string {
func (c *ConfigEnvironment) Lookup(key, serviceName string, serviceConfig *composeConfig.ServiceConfig) []string {
fullKey := fmt.Sprintf("%s/%s", serviceName, key)
return lookupKeys(c.cfg, fullKey, key)
}

View File

@ -2,10 +2,14 @@ package docker
import (
"github.com/Sirupsen/logrus"
dockerclient "github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
composeConfig "github.com/docker/libcompose/config"
"github.com/docker/libcompose/docker"
"github.com/docker/libcompose/project"
dockerclient "github.com/fsouza/go-dockerclient"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/config"
"golang.org/x/net/context"
)
type Service struct {
@ -15,7 +19,7 @@ type Service struct {
project *project.Project
}
func NewService(factory *ServiceFactory, name string, serviceConfig *project.ServiceConfig, context *docker.Context, project *project.Project) *Service {
func NewService(factory *ServiceFactory, name string, serviceConfig *composeConfig.ServiceConfig, context *docker.Context, project *project.Project) *Service {
return &Service{
Service: docker.NewService(name, serviceConfig, context),
deps: factory.Deps,
@ -50,20 +54,20 @@ func (s *Service) missingImage() bool {
return false
}
client := s.context.ClientFactory.Create(s)
i, err := client.InspectImage(s.Config().Image)
return err != nil || i == nil
_, _, err := client.ImageInspectWithRaw(context.Background(), s.Config().Image, false)
return err != nil
}
func (s *Service) requiresSyslog() bool {
return s.Config().LogDriver == "syslog"
return s.Config().Logging.Driver == "syslog"
}
func (s *Service) requiresUserDocker() bool {
return s.Config().Labels.MapParts()[config.SCOPE] != config.SYSTEM
return s.Config().Labels[config.SCOPE] != config.SYSTEM
}
func appendLink(deps []project.ServiceRelationship, name string, optional bool, p *project.Project) []project.ServiceRelationship {
if _, ok := p.Configs[name]; !ok {
if _, ok := p.ServiceConfigs.Get(name); !ok {
return deps
}
rel := project.NewServiceRelationship(name, project.RelTypeLink)
@ -71,8 +75,8 @@ func appendLink(deps []project.ServiceRelationship, name string, optional bool,
return append(deps, rel)
}
func (s *Service) shouldRebuild() (bool, error) {
containers, err := s.Containers()
func (s *Service) shouldRebuild(ctx context.Context) (bool, error) {
containers, err := s.Containers(ctx)
if err != nil {
return false, err
}
@ -81,19 +85,19 @@ func (s *Service) shouldRebuild() (bool, error) {
return false, err
}
for _, c := range containers {
outOfSync, err := c.(*docker.Container).OutOfSync(s.Service.Config().Image)
outOfSync, err := c.(*docker.Container).OutOfSync(ctx, s.Service.Config().Image)
if err != nil {
return false, err
}
_, containerInfo, err := s.getContainer()
if containerInfo == nil || err != nil {
_, containerInfo, err := s.getContainer(ctx)
if err != nil {
return false, err
}
name := containerInfo.Name[1:]
origRebuildLabel := containerInfo.Config.Labels[config.REBUILD]
newRebuildLabel := s.Config().Labels.MapParts()[config.REBUILD]
newRebuildLabel := s.Config().Labels[config.REBUILD]
rebuildLabelChanged := newRebuildLabel != origRebuildLabel
logrus.WithFields(logrus.Fields{
"origRebuildLabel": origRebuildLabel,
@ -103,6 +107,9 @@ func (s *Service) shouldRebuild() (bool, error) {
rebuilding := false
if outOfSync {
if s.Name() != "console" {
continue
}
if cfg.Rancher.ForceConsoleRebuild && s.Name() == "console" {
cfg.Rancher.ForceConsoleRebuild = false
if err := cfg.Save(); err != nil {
@ -124,36 +131,37 @@ func (s *Service) shouldRebuild() (bool, error) {
return false, nil
}
func (s *Service) Up() error {
labels := s.Config().Labels.MapParts()
func (s *Service) Up(ctx context.Context, options options.Up) error {
labels := s.Config().Labels
if err := s.Service.Create(); err != nil {
if err := s.Service.Create(ctx, options.Create); err != nil {
return err
}
shouldRebuild, err := s.shouldRebuild()
shouldRebuild, err := s.shouldRebuild(ctx)
if err != nil {
return err
}
if shouldRebuild {
cs, err := s.Service.Containers()
cs, err := s.Service.Containers(ctx)
if err != nil {
return err
}
for _, c := range cs {
if _, err := c.(*docker.Container).Recreate(s.Config().Image); err != nil {
if _, err := c.(*docker.Container).Recreate(ctx, s.Config().Image); err != nil {
return err
}
}
s.rename()
s.rename(ctx)
}
if labels[config.CREATE_ONLY] == "true" {
return s.checkReload(labels)
}
if err := s.Service.Up(); err != nil {
if err := s.Service.Up(ctx, options); err != nil {
return err
}
if labels[config.DETACH] == "false" {
if err := s.wait(); err != nil {
if err := s.wait(ctx); err != nil {
return err
}
}
@ -168,52 +176,53 @@ func (s *Service) checkReload(labels map[string]string) error {
return nil
}
func (s *Service) Create() error {
return s.Service.Create()
func (s *Service) Create(ctx context.Context, options options.Create) error {
return s.Service.Create(ctx, options)
}
func (s *Service) getContainer() (*dockerclient.Client, *dockerclient.Container, error) {
containers, err := s.Service.Containers()
func (s *Service) getContainer(ctx context.Context) (dockerclient.APIClient, types.ContainerJSON, error) {
containers, err := s.Service.Containers(ctx)
if err != nil {
return nil, nil, err
return nil, types.ContainerJSON{}, err
}
if len(containers) == 0 {
return nil, nil, nil
return nil, types.ContainerJSON{}, nil
}
id, err := containers[0].ID()
if err != nil {
return nil, nil, err
return nil, types.ContainerJSON{}, err
}
client := s.context.ClientFactory.Create(s)
info, err := client.InspectContainer(id)
info, err := client.ContainerInspect(context.Background(), id)
return client, info, err
}
func (s *Service) wait() error {
client, info, err := s.getContainer()
if err != nil || info == nil {
func (s *Service) wait(ctx context.Context) error {
client, info, err := s.getContainer(ctx)
if err != nil {
return err
}
if _, err := client.WaitContainer(info.ID); err != nil {
if _, err := client.ContainerWait(context.Background(), info.ID); err != nil {
return err
}
return nil
}
func (s *Service) rename() error {
client, info, err := s.getContainer()
if err != nil || info == nil {
func (s *Service) rename(ctx context.Context) error {
client, info, err := s.getContainer(ctx)
if err != nil {
return err
}
if len(info.Name) > 0 && info.Name[1:] != s.Name() {
logrus.Debugf("Renaming container %s => %s", info.Name[1:], s.Name())
return client.RenameContainer(dockerclient.RenameContainerOptions{ID: info.ID, Name: s.Name()})
return client.ContainerRename(context.Background(), info.ID, s.Name())
} else {
return nil
}

View File

@ -1,6 +1,7 @@
package docker
import (
composeConfig "github.com/docker/libcompose/config"
"github.com/docker/libcompose/docker"
"github.com/docker/libcompose/project"
"github.com/rancher/os/util"
@ -11,13 +12,13 @@ type ServiceFactory struct {
Deps map[string][]string
}
func (s *ServiceFactory) Create(project *project.Project, name string, serviceConfig *project.ServiceConfig) (project.Service, error) {
if after := serviceConfig.Labels.MapParts()["io.rancher.os.after"]; after != "" {
func (s *ServiceFactory) Create(project *project.Project, name string, serviceConfig *composeConfig.ServiceConfig) (project.Service, error) {
if after := serviceConfig.Labels["io.rancher.os.after"]; after != "" {
for _, dep := range util.TrimSplit(after, ",") {
s.Deps[name] = append(s.Deps[name], dep)
}
}
if before := serviceConfig.Labels.MapParts()["io.rancher.os.before"]; before != "" {
if before := serviceConfig.Labels["io.rancher.os.before"]; before != "" {
for _, dep := range util.TrimSplit(before, ",") {
s.Deps[dep] = append(s.Deps[dep], name)
}

View File

@ -1,11 +1,11 @@
package docker
import (
"github.com/docker/libcompose/project"
composeConfig "github.com/docker/libcompose/config"
"github.com/rancher/os/config"
)
func IsSystemContainer(serviceConfig *project.ServiceConfig) bool {
return serviceConfig.Labels.MapParts()[config.SCOPE] == config.SYSTEM
func IsSystemContainer(serviceConfig *composeConfig.ServiceConfig) bool {
return serviceConfig.Labels[config.SCOPE] == config.SYSTEM
}

View File

@ -7,7 +7,6 @@ import (
"strings"
log "github.com/Sirupsen/logrus"
"github.com/docker/libcompose/project"
"github.com/rancher/docker-from-scratch"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
@ -21,7 +20,7 @@ func autoformat(cfg *config.CloudConfig) (*config.CloudConfig, error) {
AUTOFORMAT := "AUTOFORMAT=" + strings.Join(cfg.Rancher.State.Autoformat, " ")
FORMATZERO := "FORMATZERO=" + fmt.Sprint(cfg.Rancher.State.FormatZero)
t := *cfg
t.Rancher.Autoformat["autoformat"].Environment = project.NewMaporEqualSlice([]string{AUTOFORMAT, FORMATZERO})
t.Rancher.Autoformat["autoformat"].Environment = []string{AUTOFORMAT, FORMATZERO}
log.Info("Running Autoformat services")
_, err := compose.RunServiceSet("autoformat", &t, t.Rancher.Autoformat)
return &t, err

View File

@ -5,8 +5,10 @@ import (
"path"
"syscall"
"golang.org/x/net/context"
log "github.com/Sirupsen/logrus"
dockerClient "github.com/fsouza/go-dockerclient"
"github.com/docker/libcompose/project/options"
"github.com/rancher/os/compose"
"github.com/rancher/os/config"
"github.com/rancher/os/docker"
@ -76,10 +78,7 @@ func loadImages(cfg *config.CloudConfig) (*config.CloudConfig, error) {
defer input.Close()
log.Infof("Loading images from %s", inputFileName)
err = client.LoadImage(dockerClient.LoadImageOptions{
InputStream: input,
})
if err != nil {
if _, err = client.ImageLoad(context.Background(), input, true); err != nil {
return cfg, err
}
@ -102,7 +101,11 @@ func SysInit() error {
if err != nil {
return cfg, err
}
return cfg, p.Up()
return cfg, p.Up(context.Background(), options.Up{
Create: options.Create{
NoRecreate: true,
},
})
},
func(cfg *config.CloudConfig) (*config.CloudConfig, error) {
syscall.Sync()

View File

@ -183,6 +183,7 @@ rancher:
network-pre:
image: {{.OS_REPO}}/os-network:{{.VERSION}}{{.SUFFIX}}
labels:
io.rancher.os.detach: "false"
io.rancher.os.scope: system
io.rancher.os.after: cloud-init-pre
net: host

View File

@ -9,7 +9,7 @@ import:
repo: https://github.com/rancher/candiedyaml
- package: github.com/codegangsta/cli
version: v1.2.0
version: 839f07bfe4819fa1434fa907d0804ce6ec45a5df
- package: github.com/coreos/coreos-cloudinit
version: 65031e1ab2d3574544d26f5b5d7ddddd0032fd00
@ -22,13 +22,23 @@ import:
version: 6b16a5714269b2f70720a45406b1babd947a17ef
- package: github.com/docker/distribution
version: v2.3.0
version: 467fc068d88aa6610691b7f1a677271a3fac4aac
- package: github.com/docker/docker
version: 58b270c338e831ac6668a29788c72d202f9fc251
version: 9837ec4da53f15f9120d53a6e1517491ba8b0261
- package: github.com/docker/engine-api
version: fd7f99d354831e7e809386087e7ec3129fdb1520
- package: github.com/docker/go-connections
version: v0.2.0
- package: github.com/docker/go-units
version: 651fc226e7441360384da338d0fd37f2440ffbe3
- package: github.com/docker/libcompose
version: d4939c5f375cfe102e04810cf0db4127cfbb1875
version: b4407312d861c21e0290d088deef15c2f8c8aa74
repo: https://github.com/rancher/libcompose
- package: github.com/docker/libcontainer
version: 83a102cc68a09d890cce3b6c2e5c14c49e6373a0
@ -45,9 +55,6 @@ import:
- package: github.com/flynn/go-shlex
version: 3f9db97f856818214da2e1057f8ad84803971cff
- package: github.com/fsouza/go-dockerclient
version: b515e07d61c4e873407b54c4843b0f3ac9aa16f1
- package: github.com/gorilla/context
version: 14f550f51af52180c2eefed15e5fd18d63c0a64a
@ -64,7 +71,7 @@ import:
version: d57d9d2d5be197e12d9dee142d855470d83ce62f
- package: github.com/opencontainers/runc
version: 1349b37bd56f4f5ce2690b5b2c0f53f88a261c67
version: 2441732d6fcc0fb0a542671a4372e0c7bc99c19e
- package: github.com/rancher/docker-from-scratch
version: v1.10.3
@ -99,3 +106,15 @@ import:
- package: github.com/packethost/packngo
version: 92012705236896736875186c9e49557897c6af90
repo: https://github.com/ibuildthecloud/packngo.git
- package: github.com/vbatts/tar-split
version: v0.9.11
- package: github.com/xeipuuv/gojsonpointer
version: e0fe6f68307607d540ed8eac07a342c33fa1b54a
- package: github.com/xeipuuv/gojsonreference
version: e02fc20de94c78484cd5ffb007f8af96be030a45
- package: github.com/xeipuuv/gojsonschema
version: ac452913faa25c08bb78810d3e6f88b8a39f8f25