diff --git a/agent/engine/docker_task_engine.go b/agent/engine/docker_task_engine.go index 876706ac9cb..0156c3f935f 100644 --- a/agent/engine/docker_task_engine.go +++ b/agent/engine/docker_task_engine.go @@ -25,6 +25,7 @@ import ( "github.com/aws/amazon-ecs-agent/agent/api" "github.com/aws/amazon-ecs-agent/agent/config" "github.com/aws/amazon-ecs-agent/agent/credentials" + "github.com/aws/amazon-ecs-agent/agent/engine/dependencygraph" "github.com/aws/amazon-ecs-agent/agent/engine/dockerclient" "github.com/aws/amazon-ecs-agent/agent/engine/dockerstate" "github.com/aws/amazon-ecs-agent/agent/eventstream" @@ -447,12 +448,24 @@ func (engine *DockerTaskEngine) AddTask(task *api.Task) error { existingTask, exists := engine.state.TaskByArn(task.Arn) if !exists { + // This will update the container desired status + task.UpdateDesiredStatus() + engine.state.AddTask(task) - engine.startTask(task) - } else { - engine.updateTask(existingTask, task) + if dependencygraph.ValidDependencies(task) { + engine.startTask(task) + } else { + seelog.Errorf("Task cannot move forward due to the dependencies of containers cannot be resolved, task: %s", task.String()) + task.SetKnownStatus(api.TaskStopped) + task.SetDesiredStatus(api.TaskStopped) + engine.emitTaskEvent(task, "impossibleTransitionError: Cannot resolve the dependencies of containers in the task definition") + } + return nil } + // Update task + engine.updateTask(existingTask, task) + return nil } diff --git a/agent/engine/docker_task_engine_test.go b/agent/engine/docker_task_engine_test.go index 4141da0cc46..c1fb6775546 100644 --- a/agent/engine/docker_task_engine_test.go +++ b/agent/engine/docker_task_engine_test.go @@ -1146,3 +1146,27 @@ func TestEngineDisableConcurrentPull(t *testing.T) { assert.False(t, dockerTaskEngine.enableConcurrentPull, "Task engine should not be able to perform concurrent pulling for version < 1.11.1") } + +// TestTaskWithCircularDependency tests the task with containers of which the +// dependencies can't be resolved +func TestTaskWithCircularDependency(t *testing.T) { + ctrl, client, _, taskEngine, _, _ := mocks(t, &defaultConfig) + defer ctrl.Finish() + + client.EXPECT().Version().Return("1.12.6", nil) + client.EXPECT().ContainerEvents(gomock.Any()) + + task := testdata.LoadTask("circular_dependency") + + taskEngine.Init() + taskEvents, _ := taskEngine.TaskEvents() + + go taskEngine.AddTask(task) + + assert.Equal(t, (<-taskEvents).Status, api.TaskStopped, "Expected task to move to stopped directly") + _, ok := taskEngine.(*DockerTaskEngine).state.TaskByArn(task.Arn) + assert.True(t, ok, "Task state should be added to the agent state") + + _, ok = taskEngine.(*DockerTaskEngine).managedTasks[task.Arn] + assert.False(t, ok, "Task should not be added to task manager for processing") +} diff --git a/agent/engine/testdata/test_tasks/circular_dependency.json b/agent/engine/testdata/test_tasks/circular_dependency.json new file mode 100644 index 00000000000..5cb8e312fd8 --- /dev/null +++ b/agent/engine/testdata/test_tasks/circular_dependency.json @@ -0,0 +1,25 @@ +{ + "Arn":"arn:aws:ecs:us-west-2:123456789012:task/12345678-90ab-cdef-1234-56780abcdef1-circular-dependency", + "Family":"circular-dependency", + "Version":"2", + "Containers": + [{ + "Name": "web", + "Image": "busybox", + "Command": ["sleep", "1000"], + "Links":["web-db:web-db"] + }, + { + "Name": "web-db", + "Image": "busybox", + "Command": ["sleep", "1000"], + "volumesFrom": [{ + "sourceContainer": "web" + }] + }], + "volumes": [], + "DesiredStatus": "RUNNING", + "KnownStatus": "NONE", + "KnownTime": "0001-01-01T00:00:00Z", + "SentStatus": "NONE" +}