diff --git a/cmd/control/os.go b/cmd/control/os.go index 490e64bc..c7371a9d 100644 --- a/cmd/control/os.go +++ b/cmd/control/os.go @@ -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 } diff --git a/cmd/control/service.go b/cmd/control/service.go index 2f48f057..ca425ba2 100644 --- a/cmd/control/service.go +++ b/cmd/control/service.go @@ -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 diff --git a/cmd/power/power.go b/cmd/power/power.go index 4d1c550c..fa2d3069 100644 --- a/cmd/power/power.go +++ b/cmd/power/power.go @@ -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()) } diff --git a/cmd/userdocker/main.go b/cmd/userdocker/main.go index 194a5038..64550035 100644 --- a/cmd/userdocker/main.go +++ b/cmd/userdocker/main.go @@ -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 } diff --git a/compose/project.go b/compose/project.go index d15a527f..28d305a8 100644 --- a/compose/project.go +++ b/compose/project.go @@ -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) { diff --git a/config/disk.go b/config/disk.go index a9015ecd..989834ba 100644 --- a/config/disk.go +++ b/config/disk.go @@ -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, diff --git a/config/types.go b/config/types.go index d7ef4dad..d41510c8 100644 --- a/config/types.go +++ b/config/types.go @@ -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 { diff --git a/docker/client.go b/docker/client.go index d8d3cc84..b49f39e1 100644 --- a/docker/client.go +++ b/docker/client.go @@ -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 }) diff --git a/docker/client_factory.go b/docker/client_factory.go index b0f479b1..cc12dfcd 100644 --- a/docker/client_factory.go +++ b/docker/client_factory.go @@ -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 { diff --git a/docker/env.go b/docker/env.go index 4e044977..48c79872 100644 --- a/docker/env.go +++ b/docker/env.go @@ -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) } diff --git a/docker/service.go b/docker/service.go index c9ffadf6..5cd6be5b 100644 --- a/docker/service.go +++ b/docker/service.go @@ -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 } diff --git a/docker/service_factory.go b/docker/service_factory.go index 5835929c..6126aa0d 100644 --- a/docker/service_factory.go +++ b/docker/service_factory.go @@ -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) } diff --git a/docker/util.go b/docker/util.go index 52ebdf3b..71622281 100644 --- a/docker/util.go +++ b/docker/util.go @@ -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 } diff --git a/init/bootstrap.go b/init/bootstrap.go index 79fb0d9a..5622475d 100644 --- a/init/bootstrap.go +++ b/init/bootstrap.go @@ -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 diff --git a/init/sysinit.go b/init/sysinit.go index 7935b4fe..bf6f3f84 100644 --- a/init/sysinit.go +++ b/init/sysinit.go @@ -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() diff --git a/os-config.tpl.yml b/os-config.tpl.yml index 188faee2..f76675b6 100644 --- a/os-config.tpl.yml +++ b/os-config.tpl.yml @@ -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 diff --git a/trash.yml b/trash.yml index c75d03d8..60e60582 100644 --- a/trash.yml +++ b/trash.yml @@ -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