func()

in agent/engine/task_manager.go [433:526]


func (mtask *managedTask) handleContainerChange(containerChange dockerContainerChange) {
	// locate the container
	container := containerChange.container
	runtimeID := container.GetRuntimeID()
	event := containerChange.event
	containerKnownStatus := container.GetKnownStatus()
	if event.Status != containerKnownStatus {
		logger.Info("Handling container change event", logger.Fields{
			field.TaskARN:   mtask.Arn,
			field.Container: container.Name,
			field.RuntimeID: runtimeID,
			field.Status:    event.Status.String(),
		})
	}
	found := mtask.isContainerFound(container)
	if !found {
		logger.Critical("State error; invoked with another task's container!", logger.Fields{
			field.TaskARN:   mtask.Arn,
			field.Container: container.Name,
			field.RuntimeID: runtimeID,
			field.Status:    event.Status.String(),
		})
		return
	}

	// If this is a backwards transition stopped->running, the first time set it
	// to be known running so it will be stopped. Subsequently ignore these backward transitions
	mtask.handleStoppedToRunningContainerTransition(event.Status, container)
	if event.Status <= containerKnownStatus {
		logger.Debug("Container change is redundant", logger.Fields{
			field.TaskARN:     mtask.Arn,
			field.Container:   container.Name,
			field.RuntimeID:   runtimeID,
			field.Status:      event.Status.String(),
			field.KnownStatus: containerKnownStatus.String(),
		})

		// Only update container metadata when status stays RUNNING
		if event.Status == containerKnownStatus && event.Status == apicontainerstatus.ContainerRunning {
			updateContainerMetadata(&event.DockerContainerMetadata, container, mtask.Task)
		}
		return
	}

	// Container has progressed its status if we reach here. Make sure to save it to database.
	defer mtask.engine.saveContainerData(container)

	// Update the container to be known
	currentKnownStatus := containerKnownStatus
	container.SetKnownStatus(event.Status)
	updateContainerMetadata(&event.DockerContainerMetadata, container, mtask.Task)

	if event.Error != nil {
		proceedAnyway := mtask.handleEventError(containerChange, currentKnownStatus)
		if !proceedAnyway {
			return
		}
	}

	if execcmd.IsExecEnabledContainer(container) && container.GetKnownStatus() == apicontainerstatus.ContainerStopped {
		// if this is an execute-command-enabled container STOPPED event, we should emit a corresponding managedAgent event
		mtask.handleManagedAgentStoppedTransition(container, execcmd.ExecuteCommandAgentName)
	}

	mtask.RecordExecutionStoppedAt(container)
	logger.Debug("Sending container change event to tcs", logger.Fields{
		field.TaskARN:   mtask.Arn,
		field.Container: container.Name,
		field.RuntimeID: runtimeID,
		field.Status:    event.Status.String(),
	})
	err := mtask.containerChangeEventStream.WriteToEventStream(event)
	if err != nil {
		logger.Warn("Failed to write container change event to tcs event stream",
			logger.Fields{
				field.TaskARN:   mtask.Arn,
				field.Container: container.Name,
				field.RuntimeID: runtimeID,
				field.Error:     err,
			})
	}

	mtask.emitContainerEvent(mtask.Task, container, "")
	if mtask.UpdateStatus() {
		// If knownStatus changed, let it be known
		var taskStateChangeReason string
		if mtask.GetKnownStatus().Terminal() {
			taskStateChangeReason = mtask.Task.GetTerminalReason()
		}
		mtask.emitTaskEvent(mtask.Task, taskStateChangeReason)
		// Save the new task status to database.
		mtask.engine.saveTaskData(mtask.Task)
	}
}