agent/engine/dockerstate/docker_task_engine_state.go (500 lines of code) (raw):
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package dockerstate
import (
"encoding/json"
"strings"
"sync"
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
apitask "github.com/aws/amazon-ecs-agent/agent/api/task"
"github.com/aws/amazon-ecs-agent/agent/engine/image"
apiresource "github.com/aws/amazon-ecs-agent/ecs-agent/api/attachment/resource"
ni "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/networkinterface"
"github.com/cihub/seelog"
)
// TaskEngineState keeps track of all mappings between tasks we know about
// and containers docker runs
type TaskEngineState interface {
// AllTasks returns all of the tasks
AllTasks() []*apitask.Task
// AllExternalTasks returns all tasks with IsInternal==false (i.e. customer-initiated tasks).
// Currently, ServiceConnect AppNet Relay task is the only internal task.
AllExternalTasks() []*apitask.Task
// AllENIAttachments returns all of the eni attachments
AllENIAttachments() []*ni.ENIAttachment
// AllImageStates returns all of the image.ImageStates
AllImageStates() []*image.ImageState
// GetAllContainerIDs returns all of the Container Ids
GetAllContainerIDs() []string
// ContainerByID returns an apicontainer.DockerContainer for a given container ID
ContainerByID(id string) (*apicontainer.DockerContainer, bool)
// ContainerMapByArn returns a map of containers belonging to a particular task ARN
ContainerMapByArn(arn string) (map[string]*apicontainer.DockerContainer, bool)
// PulledContainerMapByArn returns a map of pulled containers belonging to a particular task ARN
PulledContainerMapByArn(arn string) (map[string]*apicontainer.DockerContainer, bool)
// TaskByShortID retrieves the task of a given docker short container id
TaskByShortID(cid string) ([]*apitask.Task, bool)
// TaskByID returns an apitask.Task for a given container ID
TaskByID(cid string) (*apitask.Task, bool)
// TaskByArn returns a task for a given ARN
TaskByArn(arn string) (*apitask.Task, bool)
// AddTask adds a task to the state to be stored
AddTask(task *apitask.Task)
// AddPulledContainer adds a pulled container to the state to be stored for a given task
AddPulledContainer(container *apicontainer.DockerContainer, task *apitask.Task)
// AddContainer adds a container to the state to be stored for a given task
AddContainer(container *apicontainer.DockerContainer, task *apitask.Task)
// AddImageState adds an image.ImageState to be stored
AddImageState(imageState *image.ImageState)
// AddENIAttachment adds an eni attachment from acs to be stored
AddENIAttachment(eni *ni.ENIAttachment)
// RemoveENIAttachment removes an eni attachment to stop tracking
RemoveENIAttachment(mac string)
// ENIByMac returns the specific ENIAttachment of the given mac address
ENIByMac(mac string) (*ni.ENIAttachment, bool)
// RemoveTask removes a task from the state
RemoveTask(task *apitask.Task)
// Reset resets all the fileds in the state
Reset()
// RemoveImageState removes an image.ImageState
RemoveImageState(imageState *image.ImageState)
// AddTaskIPAddress adds ip adddress for a task arn into the state
AddTaskIPAddress(addr string, taskARN string)
// GetTaskByIPAddress gets the task arn for an IP address
GetTaskByIPAddress(addr string) (string, bool)
// GetIPAddressByTaskARN gets the local ip address of a task.
GetIPAddressByTaskARN(taskARN string) (string, bool)
// DockerIDByV3EndpointID returns a docker ID for a given v3 endpoint ID
DockerIDByV3EndpointID(v3EndpointID string) (string, bool)
// TaskARNByV3EndpointID returns a taskARN for a given v3 endpoint ID
TaskARNByV3EndpointID(v3EndpointID string) (string, bool)
// GetAllEBSAttachments returns all of the ebs attachments
GetAllEBSAttachments() []*apiresource.ResourceAttachment
// AllPendingEBSAttachments reutrns all of the ebs attachments that haven't sent a state change
GetAllPendingEBSAttachments() []*apiresource.ResourceAttachment
// GetAllPendingEBSAttachmentWithKey returns a map of all pending ebs attachments along with the corresponding volume ID as the key
GetAllPendingEBSAttachmentsWithKey() map[string]*apiresource.ResourceAttachment
// AddEBSAttachment adds an ebs attachment from acs to be stored
AddEBSAttachment(ebs *apiresource.ResourceAttachment)
// RemoveEBSAttachment removes an ebs attachment to stop tracking
RemoveEBSAttachment(volumeId string)
// EBSByVolumeId returns the specific EBSAttachment of the given volume ID
GetEBSByVolumeId(volumeId string) (*apiresource.ResourceAttachment, bool)
json.Marshaler
json.Unmarshaler
}
// DockerTaskEngineState keeps track of all mappings between tasks we know about
// and containers docker runs
// It contains a mutex that can be used to ensure out-of-date state cannot be
// accessed before an update comes and to ensure multiple goroutines can safely
// work with it.
//
// The methods on it will acquire the read lock, but not all acquire the write
// lock (sometimes it is up to the caller). This is because the write lock for
// containers should encapsulate the creation of the resource as well as adding,
// and creating the resource (docker container) is outside the scope of this
// package. This isn't ideal usage and I'm open to this being reworked/improved.
//
// Some information is duplicated in the interest of having efficient lookups
type DockerTaskEngineState struct {
lock sync.RWMutex
tasks map[string]*apitask.Task // taskarn -> apitask.Task
idToTask map[string]string // DockerId -> taskarn
taskToID map[string]map[string]*apicontainer.DockerContainer // taskarn -> (containername -> c.DockerContainer)
taskToPulledContainer map[string]map[string]*apicontainer.DockerContainer // taskarn -> (containername -> c.DockerContainer)
idToContainer map[string]*apicontainer.DockerContainer // DockerId -> c.DockerContainer
ebsAttachments map[string]*apiresource.ResourceAttachment // VolumeID -> apiresource.ResourceAttachment
eniAttachments map[string]*ni.ENIAttachment // ENIMac -> ni.ENIAttachment
imageStates map[string]*image.ImageState
ipToTask map[string]string // ip address -> task arn
v3EndpointIDToTask map[string]string // container's v3 endpoint id -> taskarn
v3EndpointIDToDockerID map[string]string // container's v3 endpoint id -> DockerId
}
// NewTaskEngineState returns a new TaskEngineState
func NewTaskEngineState() TaskEngineState {
return newDockerTaskEngineState()
}
func newDockerTaskEngineState() *DockerTaskEngineState {
state := &DockerTaskEngineState{}
state.initializeDockerTaskEngineState()
return state
}
func (state *DockerTaskEngineState) initializeDockerTaskEngineState() {
state.lock.Lock()
defer state.lock.Unlock()
state.tasks = make(map[string]*apitask.Task)
state.idToTask = make(map[string]string)
state.taskToID = make(map[string]map[string]*apicontainer.DockerContainer)
state.taskToPulledContainer = make(map[string]map[string]*apicontainer.DockerContainer)
state.idToContainer = make(map[string]*apicontainer.DockerContainer)
state.imageStates = make(map[string]*image.ImageState)
state.ebsAttachments = make(map[string]*apiresource.ResourceAttachment)
state.eniAttachments = make(map[string]*ni.ENIAttachment)
state.ipToTask = make(map[string]string)
state.v3EndpointIDToTask = make(map[string]string)
state.v3EndpointIDToDockerID = make(map[string]string)
}
// Reset resets all the states
func (state *DockerTaskEngineState) Reset() {
state.initializeDockerTaskEngineState()
}
// AllTasks returns all of the tasks
func (state *DockerTaskEngineState) AllTasks() []*apitask.Task {
state.lock.RLock()
defer state.lock.RUnlock()
return state.allTasksUnsafe()
}
func (state *DockerTaskEngineState) allTasksUnsafe() []*apitask.Task {
return state.getFilteredTasksUnsafe(false)
}
// AllExternalTasks returns all tasks with IsInternal==false (i.e. all customer-initiated tasks)
func (state *DockerTaskEngineState) AllExternalTasks() []*apitask.Task {
state.lock.RLock()
defer state.lock.RUnlock()
return state.allExternalTasksUnsafe()
}
func (state *DockerTaskEngineState) allExternalTasksUnsafe() []*apitask.Task {
return state.getFilteredTasksUnsafe(true)
}
func (state *DockerTaskEngineState) getFilteredTasksUnsafe(excludeInternal bool) []*apitask.Task {
ret := make([]*apitask.Task, len(state.tasks))
ndx := 0
for _, task := range state.tasks {
if excludeInternal && task.IsInternal {
continue
}
ret[ndx] = task
ndx++
}
return ret[:ndx]
}
// AllImageStates returns all of the image.ImageStates
func (state *DockerTaskEngineState) AllImageStates() []*image.ImageState {
state.lock.RLock()
defer state.lock.RUnlock()
return state.allImageStatesUnsafe()
}
func (state *DockerTaskEngineState) allImageStatesUnsafe() []*image.ImageState {
var allImageStates []*image.ImageState
for _, imageState := range state.imageStates {
allImageStates = append(allImageStates, imageState)
}
return allImageStates
}
// AllENIAttachments returns all the enis managed by ecs on the instance
func (state *DockerTaskEngineState) AllENIAttachments() []*ni.ENIAttachment {
state.lock.RLock()
defer state.lock.RUnlock()
return state.allENIAttachmentsUnsafe()
}
func (state *DockerTaskEngineState) allENIAttachmentsUnsafe() []*ni.ENIAttachment {
var allENIAttachments []*ni.ENIAttachment
for _, v := range state.eniAttachments {
allENIAttachments = append(allENIAttachments, v)
}
return allENIAttachments
}
// ENIByMac returns the eni object that match the give mac address
func (state *DockerTaskEngineState) ENIByMac(mac string) (*ni.ENIAttachment, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
eni, ok := state.eniAttachments[mac]
return eni, ok
}
// AddENIAttachment adds the eni into the state
func (state *DockerTaskEngineState) AddENIAttachment(eniAttachment *ni.ENIAttachment) {
if eniAttachment == nil {
seelog.Debug("Cannot add empty eni attachment information")
return
}
state.lock.Lock()
defer state.lock.Unlock()
if _, ok := state.eniAttachments[eniAttachment.MACAddress]; !ok {
state.eniAttachments[eniAttachment.MACAddress] = eniAttachment
} else {
seelog.Debugf("Duplicate eni attachment information: %v", eniAttachment)
}
}
// RemoveENIAttachment removes the eni from state and stop managing
func (state *DockerTaskEngineState) RemoveENIAttachment(mac string) {
if mac == "" {
seelog.Debug("Cannot remove empty eni attachment information")
return
}
state.lock.Lock()
defer state.lock.Unlock()
if _, ok := state.eniAttachments[mac]; ok {
delete(state.eniAttachments, mac)
} else {
seelog.Debugf("Delete non-existed eni attachment: %v", mac)
}
}
// GetAllEBSAttachments returns all the ebs volumes managed by ecs on the instance
func (state *DockerTaskEngineState) GetAllEBSAttachments() []*apiresource.ResourceAttachment {
state.lock.RLock()
defer state.lock.RUnlock()
return state.allEBSAttachmentsUnsafe()
}
func (state *DockerTaskEngineState) allEBSAttachmentsUnsafe() []*apiresource.ResourceAttachment {
var allEBSAttachments []*apiresource.ResourceAttachment
for _, v := range state.ebsAttachments {
allEBSAttachments = append(allEBSAttachments, v)
}
return allEBSAttachments
}
// GetAllPendingEBSAttachments returns all the ebs volumes managed by ecs on the instance that haven't been found attached on the host
func (state *DockerTaskEngineState) GetAllPendingEBSAttachments() []*apiresource.ResourceAttachment {
state.lock.RLock()
defer state.lock.RUnlock()
return state.allPendingEBSAttachmentsUnsafe()
}
func (state *DockerTaskEngineState) allPendingEBSAttachmentsUnsafe() []*apiresource.ResourceAttachment {
var pendingEBSAttachments []*apiresource.ResourceAttachment
for _, v := range state.ebsAttachments {
if !v.IsAttached() || !v.IsSent() {
pendingEBSAttachments = append(pendingEBSAttachments, v)
}
}
return pendingEBSAttachments
}
// GetAllPendingEBSAttachmentsWithKey returns all the ebs volumes managed by ecs on the instance that haven't been found attached on the host as a map
// with the corresponding volume ID as the key
func (state *DockerTaskEngineState) GetAllPendingEBSAttachmentsWithKey() map[string]*apiresource.ResourceAttachment {
state.lock.RLock()
defer state.lock.RUnlock()
return state.allPendingEBSAttachmentsWithKeyUnsafe()
}
func (state *DockerTaskEngineState) allPendingEBSAttachmentsWithKeyUnsafe() map[string]*apiresource.ResourceAttachment {
pendingEBSAttachments := make(map[string]*apiresource.ResourceAttachment)
for k, v := range state.ebsAttachments {
if !v.IsAttached() || !v.IsSent() {
pendingEBSAttachments[k] = v
}
}
return pendingEBSAttachments
}
// AddEBSAttachment adds the ebs volume to state
func (state *DockerTaskEngineState) AddEBSAttachment(ebsAttachment *apiresource.ResourceAttachment) {
if ebsAttachment == nil {
seelog.Debug("Cannot add empty ebs attachment information")
return
}
state.lock.Lock()
defer state.lock.Unlock()
volumeId := ebsAttachment.AttachmentProperties[apiresource.VolumeIdKey]
if _, ok := state.ebsAttachments[volumeId]; !ok {
state.ebsAttachments[volumeId] = ebsAttachment
seelog.Debugf("Successfully added EBS attachment: %v", ebsAttachment.EBSToString())
} else {
seelog.Debugf("Duplicate ebs attachment information: %v", ebsAttachment.EBSToString())
}
}
// RemoveEBSAttachment removes the ebs volume from state and stops managing
func (state *DockerTaskEngineState) RemoveEBSAttachment(volumeId string) {
if volumeId == "" {
seelog.Debug("Cannot remove empty ebs attachment information")
return
}
state.lock.Lock()
defer state.lock.Unlock()
if ebs, ok := state.ebsAttachments[volumeId]; ok {
delete(state.ebsAttachments, volumeId)
seelog.Debugf("Successfully deleted EBS attachment: %v", ebs.EBSToString())
} else {
seelog.Debugf("RemoveEBSAttachment: The requested EBS attachment with volume ID: %v does not exist", volumeId)
}
}
// GetEBSByVolumeId returns the ebs object that matches the given volume ID
func (state *DockerTaskEngineState) GetEBSByVolumeId(volumeId string) (*apiresource.ResourceAttachment, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
ebs, ok := state.ebsAttachments[volumeId]
return ebs, ok
}
// GetAllContainerIDs returns all of the Container Ids
func (state *DockerTaskEngineState) GetAllContainerIDs() []string {
state.lock.RLock()
defer state.lock.RUnlock()
var ids []string
for id := range state.idToTask {
ids = append(ids, id)
}
return ids
}
// ContainerByID returns an apicontainer.DockerContainer for a given container ID
func (state *DockerTaskEngineState) ContainerByID(id string) (*apicontainer.DockerContainer, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
c, ok := state.idToContainer[id]
return c, ok
}
// ContainerMapByArn returns a map of containers belonging to a particular task ARN
func (state *DockerTaskEngineState) ContainerMapByArn(arn string) (map[string]*apicontainer.DockerContainer, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
ret, ok := state.taskToID[arn]
if !ok {
return ret, ok
}
// Copy the map to avoid data race
mc := make(map[string]*apicontainer.DockerContainer)
for k, v := range ret {
mc[k] = v
}
return mc, ok
}
// PulledContainerMapByArn returns a map of pulled containers belonging to a particular task ARN
func (state *DockerTaskEngineState) PulledContainerMapByArn(arn string) (map[string]*apicontainer.DockerContainer, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
ret, ok := state.taskToPulledContainer[arn]
if !ok {
return ret, ok
}
// Copy the map to avoid data race
mc := make(map[string]*apicontainer.DockerContainer)
for k, v := range ret {
mc[k] = v
}
return mc, ok
}
// TaskByShortID retrieves the task of a given docker short container id
func (state *DockerTaskEngineState) TaskByShortID(cid string) ([]*apitask.Task, bool) {
containerIDs := state.GetAllContainerIDs()
var tasks []*apitask.Task
for _, id := range containerIDs {
if strings.HasPrefix(id, cid) {
if task, ok := state.TaskByID(id); ok {
tasks = append(tasks, task)
}
}
}
return tasks, len(tasks) > 0
}
// TaskByID retrieves the task of a given docker container id
func (state *DockerTaskEngineState) TaskByID(cid string) (*apitask.Task, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
arn, found := state.idToTask[cid]
if !found {
return nil, false
}
return state.taskByArn(arn)
}
// TaskByArn returns a task for a given ARN
func (state *DockerTaskEngineState) TaskByArn(arn string) (*apitask.Task, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
return state.taskByArn(arn)
}
func (state *DockerTaskEngineState) taskByArn(arn string) (*apitask.Task, bool) {
t, ok := state.tasks[arn]
return t, ok
}
// AddTask adds a new task to the state
func (state *DockerTaskEngineState) AddTask(task *apitask.Task) {
state.lock.Lock()
defer state.lock.Unlock()
state.tasks[task.Arn] = task
}
// AddPulledContainer adds a pulled container to the state
func (state *DockerTaskEngineState) AddPulledContainer(container *apicontainer.DockerContainer, task *apitask.Task) {
state.lock.Lock()
defer state.lock.Unlock()
if task == nil || container == nil {
seelog.Critical("AddPulledContainer called with nil task/container")
return
}
_, exists := state.tasks[task.Arn]
if !exists {
seelog.Debugf("AddPulledContainer called with unknown task; adding", "arn", task.Arn)
state.tasks[task.Arn] = task
}
existingMap, exists := state.taskToPulledContainer[task.Arn]
if !exists {
existingMap = make(map[string]*apicontainer.DockerContainer, len(task.Containers))
state.taskToPulledContainer[task.Arn] = existingMap
}
existingMap[container.Container.Name] = container
}
// AddContainer adds a container to the state.
// If the container has been added with only a name and no docker-id, this
// updates the state to include the docker id
func (state *DockerTaskEngineState) AddContainer(container *apicontainer.DockerContainer, task *apitask.Task) {
state.lock.Lock()
defer state.lock.Unlock()
if task == nil || container == nil {
seelog.Critical("AddContainer called with nil task/container")
return
}
_, exists := state.tasks[task.Arn]
if !exists {
seelog.Debugf("AddContainer called with unknown task; adding", "arn", task.Arn)
state.tasks[task.Arn] = task
}
_, pulledExist := state.taskToPulledContainer[task.Arn]
if pulledExist {
seelog.Debugf("Delete a pulled container named %s from the pulled container map associated with the"+
" task ARN %s since AddContainer is called", container.Container.Name, task.Arn)
delete(state.taskToPulledContainer[task.Arn], container.Container.Name)
if len(state.taskToPulledContainer[task.Arn]) == 0 {
delete(state.taskToPulledContainer, task.Arn)
}
}
state.storeIDToContainerTaskUnsafe(container, task)
dockerID := container.DockerID
v3EndpointID := container.Container.V3EndpointID
// stores the v3EndpointID mappings only if container's dockerID exists and container's v3EndpointID has been generated
if dockerID != "" && v3EndpointID != "" {
state.storeV3EndpointIDToTaskUnsafe(v3EndpointID, task.Arn)
state.storeV3EndpointIDToDockerIDUnsafe(v3EndpointID, dockerID)
}
existingMap, exists := state.taskToID[task.Arn]
if !exists {
existingMap = make(map[string]*apicontainer.DockerContainer, len(task.Containers))
state.taskToID[task.Arn] = existingMap
}
existingMap[container.Container.Name] = container
}
// AddImageState adds an image.ImageState to be stored
func (state *DockerTaskEngineState) AddImageState(imageState *image.ImageState) {
if imageState == nil {
seelog.Debug("Cannot add empty image state")
return
}
if imageState.Image.ImageID == "" {
seelog.Debug("Cannot add image state with empty image id")
return
}
state.lock.Lock()
defer state.lock.Unlock()
state.imageStates[imageState.Image.ImageID] = imageState
}
// RemoveTask removes a task from this state. It removes all containers and
// other associated metadata. It does acquire the write lock.
func (state *DockerTaskEngineState) RemoveTask(task *apitask.Task) {
state.lock.Lock()
defer state.lock.Unlock()
task, ok := state.tasks[task.Arn]
if !ok {
seelog.Warnf("Failed to locate task %s for removal from state", task.Arn)
return
}
delete(state.tasks, task.Arn)
if ip, ok := state.taskToIPUnsafe(task.Arn); ok {
delete(state.ipToTask, ip)
}
containerMap, ok := state.taskToID[task.Arn]
if !ok {
seelog.Warnf("Failed to locate containerMap for task %s for removal from state", task.Arn)
return
}
delete(state.taskToID, task.Arn)
for _, dockerContainer := range containerMap {
state.removeIDToContainerTaskUnsafe(dockerContainer)
// remove v3 endpoint mappings
state.removeV3EndpointIDToTaskContainerUnsafe(dockerContainer.Container.V3EndpointID)
}
delete(state.taskToPulledContainer, task.Arn)
}
// taskToIPUnsafe gets the ip address for a given task arn
func (state *DockerTaskEngineState) taskToIPUnsafe(arn string) (string, bool) {
for ip, taskARN := range state.ipToTask {
if arn == taskARN {
return ip, true
}
}
return "", false
}
// storeIDToContainerTaskUnsafe stores the container in the idToContainer and idToTask maps. The key to the maps is
// either the Docker-generated ID or the agent-generated name (if the ID is not available). If the container is updated
// with an ID, a subsequent call to this function will update the map to use the ID as the key.
func (state *DockerTaskEngineState) storeIDToContainerTaskUnsafe(container *apicontainer.DockerContainer, task *apitask.Task) {
if container.DockerID != "" {
// Update the container id to the state
state.idToContainer[container.DockerID] = container
state.idToTask[container.DockerID] = task.Arn
// Remove the previously added name mapping
delete(state.idToContainer, container.DockerName)
delete(state.idToTask, container.DockerName)
} else if container.DockerName != "" {
// Update the container name mapping to the state when the ID isn't available
state.idToContainer[container.DockerName] = container
state.idToTask[container.DockerName] = task.Arn
}
}
// removeIDToContainerTaskUnsafe removes the container from the idToContainer and idToTask maps. They key to the maps
// is either the Docker-generated ID or the agent-generated name (if the ID is not available). This function assumes
// that the ID takes precedence and will delete by the ID when the ID is available.
func (state *DockerTaskEngineState) removeIDToContainerTaskUnsafe(container *apicontainer.DockerContainer) {
// The key to these maps is either the Docker ID or agent-generated name. We use the agent-generated name
// before a Docker ID is available.
key := container.DockerID
if key == "" {
key = container.DockerName
}
delete(state.idToTask, key)
delete(state.idToContainer, key)
}
// removeV3EndpointIDToTaskContainerUnsafe removes the container from v3EndpointIDToTask and v3EndpointIDToDockerID maps
func (state *DockerTaskEngineState) removeV3EndpointIDToTaskContainerUnsafe(v3EndpointID string) {
if v3EndpointID != "" {
delete(state.v3EndpointIDToTask, v3EndpointID)
delete(state.v3EndpointIDToDockerID, v3EndpointID)
}
}
// RemoveImageState removes an image.ImageState
func (state *DockerTaskEngineState) RemoveImageState(imageState *image.ImageState) {
if imageState == nil {
seelog.Debug("Cannot remove empty image state")
return
}
state.lock.Lock()
defer state.lock.Unlock()
imageState, ok := state.imageStates[imageState.Image.ImageID]
if !ok {
seelog.Debug("Image State is not found. Cannot be removed")
return
}
delete(state.imageStates, imageState.Image.ImageID)
}
// AddTaskIPAddress adds ip adddress for a task arn into the state
func (state *DockerTaskEngineState) AddTaskIPAddress(addr string, taskARN string) {
state.lock.Lock()
defer state.lock.Unlock()
state.ipToTask[addr] = taskARN
}
// GetTaskByIPAddress gets the task arn for an IP address
func (state *DockerTaskEngineState) GetTaskByIPAddress(addr string) (string, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
taskARN, ok := state.ipToTask[addr]
return taskARN, ok
}
// GetIPAddressByTaskARN gets the local ip address of a task.
func (state *DockerTaskEngineState) GetIPAddressByTaskARN(taskARN string) (string, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
for addr, arn := range state.ipToTask {
if arn == taskARN {
return addr, true
}
}
return "", false
}
// storeV3EndpointIDToTaskUnsafe adds v3EndpointID -> taskARN mapping to state
func (state *DockerTaskEngineState) storeV3EndpointIDToTaskUnsafe(v3EndpointID, taskARN string) {
state.v3EndpointIDToTask[v3EndpointID] = taskARN
}
// storeV3EndpointIDToContainerNameUnsafe adds v3EndpointID -> dockerID mapping to state
func (state *DockerTaskEngineState) storeV3EndpointIDToDockerIDUnsafe(v3EndpointID, dockerID string) {
state.v3EndpointIDToDockerID[v3EndpointID] = dockerID
}
// DockerIDByV3EndpointID returns a docker ID for a given v3 endpoint ID
func (state *DockerTaskEngineState) DockerIDByV3EndpointID(v3EndpointID string) (string, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
dockerID, ok := state.v3EndpointIDToDockerID[v3EndpointID]
return dockerID, ok
}
// TaskARNByV3EndpointID returns a taskARN for a given v3 endpoint ID
func (state *DockerTaskEngineState) TaskARNByV3EndpointID(v3EndpointID string) (string, bool) {
state.lock.RLock()
defer state.lock.RUnlock()
taskArn, ok := state.v3EndpointIDToTask[v3EndpointID]
return taskArn, ok
}