func TestUnavailableVersionError(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mockDocker := mock_dockeriface.NewMockClient(ctrl) mockDocker.EXPECT().Ping().Return(nil) factory := mock_dockerclient.NewMockFactory(ctrl) factory.EXPECT().GetDefaultClient().Return(mockDocker, nil) client, err := NewDockerGoClient(factory, "", config.NewSensitiveRawMessage([]byte{}), false) if err != nil { t.Fatal(err) } vclient := client.WithVersion(dockerclient.DockerVersion("1.21")) factory.EXPECT().GetClient(dockerclient.DockerVersion("1.21")).Times(1).Return(nil, errors.New("Cannot get client")) metadata := vclient.StartContainer("foo") if metadata.Error == nil { t.Fatal("Expected error, didn't get one") } if namederr, ok := metadata.Error.(api.NamedError); ok { if namederr.ErrorName() != "CannotGetDockerclientError" { t.Fatal("Wrong error name, expected CannotGetDockerclientError but got " + namederr.ErrorName()) } } else { t.Fatal("Error was not a named error") } }
func (engine *DockerTaskEngine) createContainer(task *api.Task, container *api.Container) DockerContainerMetadata { log.Info("Creating container", "task", task, "container", container) client := engine.client if container.DockerConfig.Version != nil { client = client.WithVersion(dockerclient.DockerVersion(*container.DockerConfig.Version)) } // Resolve HostConfig // we have to do this in create, not start, because docker no longer handles // merging create config with start hostconfig the same; e.g. memory limits // get lost containerMap, ok := engine.state.ContainerMapByArn(task.Arn) if !ok { containerMap = make(map[string]*api.DockerContainer) } hostConfig, hcerr := task.DockerHostConfig(container, containerMap) hostConfig.NetworkMode = "host" if hcerr != nil { return DockerContainerMetadata{Error: api.NamedError(hcerr)} } config, err := task.DockerConfig(container) if err != nil { return DockerContainerMetadata{Error: api.NamedError(err)} } name := "" for i := 0; i < len(container.Name); i++ { c := container.Name[i] if !((c <= '9' && c >= '0') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '-')) { continue } name += string(c) } containerName := "ecs-" + task.Family + "-" + task.Version + "-" + name + "-" + utils.RandHex() // Pre-add the container in case we stop before the next, more useful, // AddContainer call. This ensures we have a way to get the container if // we die before 'createContainer' returns because we can inspect by // name engine.state.AddContainer(&api.DockerContainer{DockerName: containerName, Container: container}, task) metadata := client.CreateContainer(config, hostConfig, containerName) if metadata.Error != nil { return metadata } engine.state.AddContainer(&api.DockerContainer{DockerId: metadata.DockerId, DockerName: containerName, Container: container}, task) hostConfig.NetworkMode = "host" log.Info("Created container successfully", "task", task, "container", container) return metadata }
func TestUsesVersionedClient(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mockDocker := mock_dockeriface.NewMockClient(ctrl) mockDocker.EXPECT().Ping().Return(nil) factory := mock_dockerclient.NewMockFactory(ctrl) factory.EXPECT().GetDefaultClient().Return(mockDocker, nil) client, err := NewDockerGoClient(factory, "", config.NewSensitiveRawMessage([]byte{}), false) if err != nil { t.Fatal(err) } vclient := client.WithVersion(dockerclient.DockerVersion("1.20")) factory.EXPECT().GetClient(dockerclient.DockerVersion("1.20")).Times(2).Return(mockDocker, nil) mockDocker.EXPECT().StartContainer(gomock.Any(), gomock.Any()).Return(nil) mockDocker.EXPECT().InspectContainer(gomock.Any()).Return(nil, errors.New("err")) vclient.StartContainer("foo") }
func (engine *DockerTaskEngine) startContainer(task *api.Task, container *api.Container) DockerContainerMetadata { log.Info("Starting container", "task", task, "container", container) client := engine.client if container.DockerConfig.Version != nil { client = client.WithVersion(dockerclient.DockerVersion(*container.DockerConfig.Version)) } containerMap, ok := engine.state.ContainerMapByArn(task.Arn) if !ok { return DockerContainerMetadata{Error: CannotXContainerError{"Start", "Container belongs to unrecognized task " + task.Arn}} } dockerContainer, ok := containerMap[container.Name] if !ok { return DockerContainerMetadata{Error: CannotXContainerError{"Start", "Container not recorded as created"}} } return client.StartContainer(dockerContainer.DockerId) }
func (engine *DockerTaskEngine) createContainer(task *api.Task, container *api.Container) DockerContainerMetadata { log.Info("Creating container", "task", task, "container", container) client := engine.client if container.DockerConfig.Version != nil { client = client.WithVersion(dockerclient.DockerVersion(*container.DockerConfig.Version)) } // Resolve HostConfig // we have to do this in create, not start, because docker no longer handles // merging create config with start hostconfig the same; e.g. memory limits // get lost containerMap, ok := engine.state.ContainerMapByArn(task.Arn) if !ok { containerMap = make(map[string]*api.DockerContainer) } hostConfig, hcerr := task.DockerHostConfig(container, containerMap) if hcerr != nil { return DockerContainerMetadata{Error: api.NamedError(hcerr)} } config, err := task.DockerConfig(container) if err != nil { return DockerContainerMetadata{Error: api.NamedError(err)} } // Augment labels with some metadata from the agent. Explicitly do this last // such that it will always override duplicates in the provided raw config // data. config.Labels[labelPrefix+"task-arn"] = task.Arn config.Labels[labelPrefix+"container-name"] = container.Name config.Labels[labelPrefix+"task-definition-family"] = task.Family config.Labels[labelPrefix+"task-definition-version"] = task.Version config.Labels[labelPrefix+"cluster"] = engine.cfg.Cluster name := "" for i := 0; i < len(container.Name); i++ { c := container.Name[i] if !((c <= '9' && c >= '0') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '-')) { continue } name += string(c) } containerName := "ecs-" + task.Family + "-" + task.Version + "-" + name + "-" + utils.RandHex() // Pre-add the container in case we stop before the next, more useful, // AddContainer call. This ensures we have a way to get the container if // we die before 'createContainer' returns because we can inspect by // name engine.state.AddContainer(&api.DockerContainer{DockerName: containerName, Container: container}, task) seelog.Infof("Created container name mapping for task %s - %s -> %s", task, container, containerName) engine.saver.ForceSave() metadata := client.CreateContainer(config, hostConfig, containerName) if metadata.DockerId != "" { engine.state.AddContainer(&api.DockerContainer{DockerId: metadata.DockerId, DockerName: containerName, Container: container}, task) } seelog.Infof("Created docker container for task %s: %s -> %s", task, container, metadata.DockerId) return metadata }