agent/app/agent.go
func (agent *ecsAgent) doStart(containerChangeEventStream *eventstream.EventStream,
	credentialsManager credentials.Manager,
	state dockerstate.TaskEngineState,
	imageManager engine.ImageManager,
	client api.ECSClient) int {

	// check docker version >= 1.9.0, exit agent if older
	if exitcode, ok := agent.verifyRequiredDockerVersion(); !ok {
		return exitcode
	}

	// Conditionally create '/ecs' cgroup root
	if agent.cfg.TaskCPUMemLimit.Enabled() {
		if err := agent.cgroupInit(); err != nil {
			seelog.Criticalf("Unable to initialize cgroup root for ECS: %v", err)
			return exitcodes.ExitTerminal
		}
	}
	if agent.cfg.GPUSupportEnabled {
		err := agent.initializeGPUManager()
		if err != nil {
			seelog.Criticalf("Could not initialize Nvidia GPU Manager: %v", err)
			return exitcodes.ExitError
		}
	}

	// Create the task engine
	taskEngine, currentEC2InstanceID, err := agent.newTaskEngine(containerChangeEventStream,
		credentialsManager, state, imageManager)
	if err != nil {
		return exitcodes.ExitTerminal
	}

	agent.initMetricsEngine()

	// Initialize the state manager
	stateManager, err := agent.newStateManager(taskEngine,
		&agent.cfg.Cluster, &agent.containerInstanceARN, &currentEC2InstanceID, &agent.availabilityZone)
	if err != nil {
		seelog.Criticalf("Error creating state manager: %v", err)
		return exitcodes.ExitTerminal
	}

	var vpcSubnetAttributes []*ecs.Attribute
	// Check if Task ENI is enabled
	if agent.cfg.TaskENIEnabled {
		err, terminal := agent.initializeTaskENIDependencies(state, taskEngine)
		switch err {
		case nil:
			// No error, we can proceed with the rest of initialization
			// Set vpc and subnet id attributes
			vpcSubnetAttributes = agent.constructVPCSubnetAttributes()
		case instanceNotLaunchedInVPCError:
			// We have ascertained that the EC2 Instance is not running in a VPC
			// No need to stop the ECS Agent in this case; all we need to do is
			// to not update the config to disable the TaskENIEnabled flag and
			// move on
			seelog.Warnf("Unable to detect VPC ID for the Instance, disabling Task ENI capability: %v", err)
			agent.cfg.TaskENIEnabled = false
		default:
			// Encountered an error initializing dependencies for dealing with
			// ENIs for Tasks. Exit with the appropriate error code
			seelog.Criticalf("Unable to initialize Task ENI dependencies: %v", err)
			if terminal {
				return exitcodes.ExitTerminal
			}
			return exitcodes.ExitError
		}
	}

	// Register the container instance
	err = agent.registerContainerInstance(stateManager, client, vpcSubnetAttributes)
	if err != nil {
		if isTransient(err) {
			return exitcodes.ExitError
		}
		return exitcodes.ExitTerminal
	}
	// Add container instance ARN to metadata manager
	if agent.cfg.ContainerMetadataEnabled {
		agent.metadataManager.SetContainerInstanceARN(agent.containerInstanceARN)
		agent.metadataManager.SetAvailabilityZone(agent.availabilityZone)
		agent.metadataManager.SetHostPublicIPv4Address(agent.getHostPublicIPv4AddressFromEC2Metadata())
	}

	// Begin listening to the docker daemon and saving changes
	taskEngine.SetSaver(stateManager)
	imageManager.SetSaver(stateManager)
	taskEngine.MustInit(agent.ctx)

	// Start back ground routines, including the telemetry session
	deregisterInstanceEventStream := eventstream.NewEventStream(
		deregisterContainerInstanceEventStreamName, agent.ctx)
	deregisterInstanceEventStream.StartListening()
	taskHandler := eventhandler.NewTaskHandler(agent.ctx, stateManager, state, client)
	agent.startAsyncRoutines(containerChangeEventStream, credentialsManager, imageManager,
		taskEngine, stateManager, deregisterInstanceEventStream, client, taskHandler, state)

	// Start the acs session, which should block doStart
	return agent.startACSSession(credentialsManager, taskEngine, stateManager,
		deregisterInstanceEventStream, client, state, taskHandler)
}
func (agent *ecsAgent) doStart(containerChangeEventStream *eventstream.EventStream,
	credentialsManager credentials.Manager,
	state dockerstate.TaskEngineState,
	imageManager engine.ImageManager,
	client api.ECSClient) int {

	// check docker version >= 1.9.0, exit agent if older
	if exitcode, ok := agent.verifyRequiredDockerVersion(); !ok {
		return exitcode
	}

	// Conditionally create '/ecs' cgroup root
	if agent.cfg.TaskCPUMemLimit.Enabled() {
		if err := agent.cgroupInit(); err != nil {
			seelog.Criticalf("Unable to initialize cgroup root for ECS: %v", err)
			return exitcodes.ExitTerminal
		}
	}
	if agent.cfg.GPUSupportEnabled {
		err := agent.initializeGPUManager()
		if err != nil {
			seelog.Criticalf("Could not initialize Nvidia GPU Manager: %v", err)
			return exitcodes.ExitError
		}
	}

	// Create the task engine
	taskEngine, currentEC2InstanceID, err := agent.newTaskEngine(containerChangeEventStream,
		credentialsManager, state, imageManager)
	if err != nil {
		return exitcodes.ExitTerminal
	}

	agent.initMetricsEngine()

	// Initialize the state manager
	stateManager, err := agent.newStateManager(taskEngine,
		&agent.cfg.Cluster, &agent.containerInstanceARN, &currentEC2InstanceID, &agent.availabilityZone)
	if err != nil {
		seelog.Criticalf("Error creating state manager: %v", err)
		return exitcodes.ExitTerminal
	}

	var vpcSubnetAttributes []*ecs.Attribute
	// Check if Task ENI is enabled
	if agent.cfg.TaskENIEnabled {
		err, terminal := agent.initializeTaskENIDependencies(state, taskEngine)
		switch err {
		case nil:
			// No error, we can proceed with the rest of initialization
			// Set vpc and subnet id attributes
			vpcSubnetAttributes = agent.constructVPCSubnetAttributes()
		case instanceNotLaunchedInVPCError:
			// We have ascertained that the EC2 Instance is not running in a VPC
			// No need to stop the ECS Agent in this case; all we need to do is
			// to not update the config to disable the TaskENIEnabled flag and
			// move on
			seelog.Warnf("Unable to detect VPC ID for the Instance, disabling Task ENI capability: %v", err)
			agent.cfg.TaskENIEnabled = false
		default:
			// Encountered an error initializing dependencies for dealing with
			// ENIs for Tasks. Exit with the appropriate error code
			seelog.Criticalf("Unable to initialize Task ENI dependencies: %v", err)
			if terminal {
				return exitcodes.ExitTerminal
			}
			return exitcodes.ExitError
		}
	}

	// Register the container instance
	err = agent.registerContainerInstance(stateManager, client, vpcSubnetAttributes)
	if err != nil {
		if isTransient(err) {
			return exitcodes.ExitError
		}
		return exitcodes.ExitTerminal
	}
	// Add container instance ARN to metadata manager
	if agent.cfg.ContainerMetadataEnabled {
		agent.metadataManager.SetContainerInstanceARN(agent.containerInstanceARN)
		agent.metadataManager.SetAvailabilityZone(agent.availabilityZone)
		agent.metadataManager.SetHostPublicIPv4Address(agent.getHostPublicIPv4AddressFromEC2Metadata())
	}

	// Begin listening to the docker daemon and saving changes
	taskEngine.SetSaver(stateManager)
	imageManager.SetSaver(stateManager)
	taskEngine.MustInit(agent.ctx)

	// Start back ground routines, including the telemetry session
	deregisterInstanceEventStream := eventstream.NewEventStream(
		deregisterContainerInstanceEventStreamName, agent.ctx)
	deregisterInstanceEventStream.StartListening()
	taskHandler := eventhandler.NewTaskHandler(agent.ctx, stateManager, state, client)
	agent.startAsyncRoutines(containerChangeEventStream, credentialsManager, imageManager,
		taskEngine, stateManager, deregisterInstanceEventStream, client, taskHandler, state)

	// Start the acs session, which should block doStart
	return agent.startACSSession(credentialsManager, taskEngine, stateManager,
		deregisterInstanceEventStream, client, state, taskHandler)
}
func ( agent * ecsAgent ) doStart ( containerChangeEventStream * eventstream . EventStream , credentialsManager credentials . Manager , state dockerstate . TaskEngineState , imageManager engine . ImageManager , client api . ECSClient ) int { // check docker version >= 1.9.0, exit agent if older if exitcode , ok := agent . verifyRequiredDockerVersion ( ) ; ! ok { return exitcode } // Conditionally create '/ecs' cgroup root if agent . cfg . TaskCPUMemLimit . Enabled ( ) { if err := agent . cgroupInit ( ) ; err != nil { seelog . Criticalf ( " " , err ) return exitcodes . ExitTerminal } } if agent . cfg . GPUSupportEnabled { err := agent . initializeGPUManager ( ) if err != nil { seelog . Criticalf ( " " , err ) return exitcodes . ExitError } } // Create the task engine taskEngine , currentEC2InstanceID , err := agent . newTaskEngine ( containerChangeEventStream , credentialsManager , state , imageManager ) if err != nil { return exitcodes . ExitTerminal } agent . initMetricsEngine ( ) // Initialize the state manager stateManager , err := agent . newStateManager ( taskEngine , & agent . cfg . Cluster , & agent . containerInstanceARN , & currentEC2InstanceID , & agent . availabilityZone ) if err != nil { seelog . Criticalf ( " " , err ) return exitcodes . ExitTerminal } var vpcSubnetAttributes [ ] * ecs . Attribute // Check if Task ENI is enabled if agent . cfg . TaskENIEnabled { err , terminal := agent . initializeTaskENIDependencies ( state , taskEngine ) switch err { case nil : // No error, we can proceed with the rest of initialization // Set vpc and subnet id attributes vpcSubnetAttributes = agent . constructVPCSubnetAttributes ( ) case instanceNotLaunchedInVPCError : // We have ascertained that the EC2 Instance is not running in a VPC // No need to stop the ECS Agent in this case; all we need to do is // to not update the config to disable the TaskENIEnabled flag and // move on seelog . Warnf ( " " , err ) agent . cfg . TaskENIEnabled = false default : // Encountered an error initializing dependencies for dealing with // ENIs for Tasks. Exit with the appropriate error code seelog . Criticalf ( " " , err ) if terminal { return exitcodes . ExitTerminal } return exitcodes . ExitError } } // Register the container instance err = agent . registerContainerInstance ( stateManager , client , vpcSubnetAttributes ) if err != nil { if isTransient ( err ) { return exitcodes . ExitError } return exitcodes . ExitTerminal } // Add container instance ARN to metadata manager if agent . cfg . ContainerMetadataEnabled { agent . metadataManager . SetContainerInstanceARN ( agent . containerInstanceARN ) agent . metadataManager . SetAvailabilityZone ( agent . availabilityZone ) agent . metadataManager . SetHostPublicIPv4Address ( agent . getHostPublicIPv4AddressFromEC2Metadata ( ) ) } // Begin listening to the docker daemon and saving changes taskEngine . SetSaver ( stateManager ) imageManager . SetSaver ( stateManager ) taskEngine . MustInit ( agent . ctx ) // Start back ground routines, including the telemetry session deregisterInstanceEventStream := eventstream . NewEventStream ( deregisterContainerInstanceEventStreamName , agent . ctx ) deregisterInstanceEventStream . StartListening ( ) taskHandler := eventhandler . NewTaskHandler ( agent . ctx , stateManager , state , client ) agent . startAsyncRoutines ( containerChangeEventStream , credentialsManager , imageManager , taskEngine , stateManager , deregisterInstanceEventStream , client , taskHandler , state ) // Start the acs session, which should block doStart return agent . startACSSession ( credentialsManager , taskEngine , stateManager , deregisterInstanceEventStream , client , state , taskHandler ) }
// doStart is the worker invoked by start for starting the ECS Agent. This involves
// initializing the docker task engine, state saver, image manager, credentials
// manager, poll and telemetry sessions, api handler etc
doStart is the worker invoked by start for starting the ECS Agent . This involves initializing the docker task engine state saver image manager credentials manager poll and telemetry sessions api handler etc