func (mr *MockResponseWriterMockRecorder) WriteHeader(arg0 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteHeader", reflect.TypeOf((*MockResponseWriter)(nil).WriteHeader), arg0)
}

func ( mr * MockResponseWriterMockRecorder ) WriteHeader ( arg0 interface { } ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockResponseWriter ) ( nil ) . WriteHeader ) , arg0 ) }

// WriteHeader indicates an expected call of WriteHeader


func compareDockerVersions(lhs, rhs dockerVersion) int {
	switch {
	case lhs.major < rhs.major:
		return -1
	case lhs.major > rhs.major:
		return 1
	case lhs.minor < rhs.minor:
		return -1
	case lhs.minor > rhs.minor:
		return 1
	}
	return 0
}

func compareDockerVersions ( lhs , rhs dockerVersion ) int { switch { case lhs . major < rhs . major : return - 1 case lhs . major > rhs . major : return 1 case lhs . minor < rhs . minor : return - 1 case lhs . minor > rhs . minor : return 1 } return 0 }

// compareDockerVersions compares two docker api versions, 'lhs' and 'rhs', and returns -1 if lhs is less
// than rhs, 0 if they are equal, and 1 if lhs is greater than rhs

compareDockerVersions compares two docker api versions lhs and rhs and returns - 1 if lhs is less than rhs 0 if they are equal and 1 if lhs is greater than rhs


func SignHTTPRequest(req *http.Request, region, service string, creds *credentials.Credentials, body io.ReadSeeker) error {
	signer := v4.NewSigner(creds)
	_, err := signer.Sign(req, body, service, region, time.Now())
	if err != nil {
		seelog.Warnf("Signing HTTP request failed: %v", err)
		return errors.Wrap(err, "aws sdk http signer: failed to sign http request")
	}
	return nil
}

func SignHTTPRequest ( req * http . Request , region , service string , creds * credentials . Credentials , body io . ReadSeeker ) error { signer := v4 . NewSigner ( creds ) _ , err := signer . Sign ( req , body , service , region , time . Now ( ) ) if err != nil { seelog . Warnf ( " " , err ) return errors . Wrap ( err , " " ) } return nil }

// SignHTTPRequest signs an http.Request struct with authv4 using the given region, service, and credentials.

SignHTTPRequest signs an http . Request struct with authv4 using the given region service and credentials .


func (f *factory) GetClient(version dockerclient.DockerVersion) (sdkclient.Client, error) {
	return f.getClient(version)
}

func ( f * factory ) GetClient ( version dockerclient . DockerVersion ) ( sdkclient . Client , error ) { return f . getClient ( version ) }

// GetClient on linux will simply return the cached client from the map


func getAgentVersions() []dockerclient.DockerVersion {
	return []dockerclient.DockerVersion{
		dockerclient.Version_1_17,
		dockerclient.Version_1_18,
		dockerclient.Version_1_19,
		dockerclient.Version_1_20,
		dockerclient.Version_1_21,
		dockerclient.Version_1_22,
		dockerclient.Version_1_23,
		dockerclient.Version_1_24,
		dockerclient.Version_1_25,
		dockerclient.Version_1_26,
		dockerclient.Version_1_27,
		dockerclient.Version_1_28,
		dockerclient.Version_1_29,
		dockerclient.Version_1_30,
		dockerclient.Version_1_31,
		dockerclient.Version_1_32,
	}
}

func getAgentVersions ( ) [ ] dockerclient . DockerVersion { return [ ] dockerclient . DockerVersion { dockerclient . Version_1_17 , dockerclient . Version_1_18 , dockerclient . Version_1_19 , dockerclient . Version_1_20 , dockerclient . Version_1_21 , dockerclient . Version_1_22 , dockerclient . Version_1_23 , dockerclient . Version_1_24 , dockerclient . Version_1_25 , dockerclient . Version_1_26 , dockerclient . Version_1_27 , dockerclient . Version_1_28 , dockerclient . Version_1_29 , dockerclient . Version_1_30 , dockerclient . Version_1_31 , dockerclient . Version_1_32 , } }

// getAgentVersions returns a list of supported agent-supported versions for linux

getAgentVersions returns a list of supported agent - supported versions for linux


func (task *Task) dockerCPUShares(containerCPU uint) int64 {
	if containerCPU <= 1 {
		seelog.Debugf(
			"Converting CPU shares to allowed minimum of 2 for task arn: [%s] and cpu shares: %d",
			task.Arn, containerCPU)
		return 2
	}
	return int64(containerCPU)
}

func ( task * Task ) dockerCPUShares ( containerCPU uint ) int64 { if containerCPU <= 1 { seelog . Debugf ( " " , task . Arn , containerCPU ) return 2 } return int64 ( containerCPU ) }

// duplicate of dockerCPUShares in task_linux.go

duplicate of dockerCPUShares in task_linux . go


func verifyTasksMetadata(tasksMetadataRawMsg json.RawMessage) error {
	var tasksMetadataMap map[string]json.RawMessage
	json.Unmarshal(tasksMetadataRawMsg, &tasksMetadataMap)

	if tasksMetadataMap["Tasks"] == nil {
		return notEmptyErrMsg("Tasks")
	}

	var tasksMetadataArray []json.RawMessage
	json.Unmarshal(tasksMetadataMap["Tasks"], &tasksMetadataArray)

	if len(tasksMetadataArray) != 1 {
		return fmt.Errorf("incorrect number of tasks, expected 1, received %d",
			len(tasksMetadataArray))
	}

	return verifyTaskMetadata(tasksMetadataArray[0])
}

func verifyTasksMetadata ( tasksMetadataRawMsg json . RawMessage ) error { var tasksMetadataMap map [ string ] json . RawMessage json . Unmarshal ( tasksMetadataRawMsg , & tasksMetadataMap ) if tasksMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } var tasksMetadataArray [ ] json . RawMessage json . Unmarshal ( tasksMetadataMap [ " " ] , & tasksMetadataArray ) if len ( tasksMetadataArray ) != 1 { return fmt . Errorf ( " " , len ( tasksMetadataArray ) ) } return verifyTaskMetadata ( tasksMetadataArray [ 0 ] ) }

// verifyTasksMetadata verifies the number of tasks in tasks metadata.

verifyTasksMetadata verifies the number of tasks in tasks metadata .


func verifyTaskMetadata(taskMetadataRawMsg json.RawMessage) error {
	taskMetadataMap := make(map[string]json.RawMessage)
	json.Unmarshal(taskMetadataRawMsg, &taskMetadataMap)

	if taskMetadataMap["Arn"] == nil {
		return notEmptyErrMsg("Arn")
	}

	if taskMetadataMap["DesiredStatus"] == nil {
		return notEmptyErrMsg("DesiredStatus")
	}

	if taskMetadataMap["KnownStatus"] == nil {
		return notEmptyErrMsg("KnownStatus")
	}

	if taskMetadataMap["Family"] == nil {
		return notEmptyErrMsg("Family")
	}

	if taskMetadataMap["Version"] == nil {
		return notEmptyErrMsg("Version")
	}

	if taskMetadataMap["Containers"] == nil {
		return notEmptyErrMsg("Containers")
	}

	var containersMetadataArray []json.RawMessage
	json.Unmarshal(taskMetadataMap["Containers"], &containersMetadataArray)
	if len(containersMetadataArray) != 1 {
		return fmt.Errorf("incorrect number of containers, expected 1, received %d",
			len(containersMetadataArray))
	}

	return verifyContainerMetadata(containersMetadataArray[0])
}

func verifyTaskMetadata ( taskMetadataRawMsg json . RawMessage ) error { taskMetadataMap := make ( map [ string ] json . RawMessage ) json . Unmarshal ( taskMetadataRawMsg , & taskMetadataMap ) if taskMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } if taskMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } if taskMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } if taskMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } if taskMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } if taskMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } var containersMetadataArray [ ] json . RawMessage json . Unmarshal ( taskMetadataMap [ " " ] , & containersMetadataArray ) if len ( containersMetadataArray ) != 1 { return fmt . Errorf ( " " , len ( containersMetadataArray ) ) } return verifyContainerMetadata ( containersMetadataArray [ 0 ] ) }

// verifyTaskMetadata verifies the number of containers in task metadata, make
// sure each necessary field is not empty, we cannot check the values of those fields
// since they are dynamic. It also verifies the container metadata.

verifyTaskMetadata verifies the number of containers in task metadata make sure each necessary field is not empty we cannot check the values of those fields since they are dynamic . It also verifies the container metadata .


func verifyContainerMetadata(containerMetadataRawMsg json.RawMessage) error {
	containerMetadataMap := make(map[string]json.RawMessage)
	json.Unmarshal(containerMetadataRawMsg, &containerMetadataMap)

	if containerMetadataMap["Name"] == nil {
		return notEmptyErrMsg("Name")
	}

	var actualContainerName string
	json.Unmarshal(containerMetadataMap["Name"], &actualContainerName)

	if actualContainerName != containerName {
		return fmt.Errorf("incorrect container name, expected %s, received %s",
			containerName, actualContainerName)
	}

	if containerMetadataMap["DockerId"] == nil {
		return notEmptyErrMsg("DockerId")
	}

	if containerMetadataMap["DockerName"] == nil {
		return notEmptyErrMsg("DockerName")
	}

	if containerMetadataMap["Volumes"] == nil {
		return notEmptyErrMsg("Volumes")
	}

	return nil
}

func verifyContainerMetadata ( containerMetadataRawMsg json . RawMessage ) error { containerMetadataMap := make ( map [ string ] json . RawMessage ) json . Unmarshal ( containerMetadataRawMsg , & containerMetadataMap ) if containerMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } var actualContainerName string json . Unmarshal ( containerMetadataMap [ " " ] , & actualContainerName ) if actualContainerName != containerName { return fmt . Errorf ( " " , containerName , actualContainerName ) } if containerMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } if containerMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } if containerMetadataMap [ " " ] == nil { return notEmptyErrMsg ( " " ) } return nil }

// verifyContainerMetadata verifies the container name of the container metadata,
// and each necessary field is not empty.

verifyContainerMetadata verifies the container name of the container metadata and each necessary field is not empty .


func NewMockResult(ctrl *gomock.Controller) *MockResult {
	mock := &MockResult{ctrl: ctrl}
	mock.recorder = &MockResultMockRecorder{mock}
	return mock
}

func NewMockResult ( ctrl * gomock . Controller ) * MockResult { mock := & MockResult { ctrl : ctrl } mock . recorder = & MockResultMockRecorder { mock } return mock }

// NewMockResult creates a new mock instance


func (m *MockResult) GetAsVersion(arg0 string) (types.Result, error) {
	ret := m.ctrl.Call(m, "GetAsVersion", arg0)
	ret0, _ := ret[0].(types.Result)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockResult ) GetAsVersion ( arg0 string ) ( types . Result , error ) { ret := m . ctrl . Call ( m , " " , arg0 ) ret0 , _ := ret [ 0 ] . ( types . Result ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (mr *MockResultMockRecorder) GetAsVersion(arg0 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAsVersion", reflect.TypeOf((*MockResult)(nil).GetAsVersion), arg0)
}

func ( mr * MockResultMockRecorder ) GetAsVersion ( arg0 interface { } ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockResult ) ( nil ) . GetAsVersion ) , arg0 ) }

// GetAsVersion indicates an expected call of GetAsVersion


func (m *MockResult) Print() error {
	ret := m.ctrl.Call(m, "Print")
	ret0, _ := ret[0].(error)
	return ret0
}

func ( m * MockResult ) Print ( ) error { ret := m . ctrl . Call ( m , " " ) ret0 , _ := ret [ 0 ] . ( error ) return ret0 }


func (mr *MockResultMockRecorder) Print() *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Print", reflect.TypeOf((*MockResult)(nil).Print))
}

func ( mr * MockResultMockRecorder ) Print ( ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockResult ) ( nil ) . Print ) ) }

// Print indicates an expected call of Print


func (m *MockClient) ContainerCreate(arg0 context.Context, arg1 *container.Config, arg2 *container.HostConfig, arg3 *network.NetworkingConfig, arg4 string) (container.ContainerCreateCreatedBody, error) {
	ret := m.ctrl.Call(m, "ContainerCreate", arg0, arg1, arg2, arg3, arg4)
	ret0, _ := ret[0].(container.ContainerCreateCreatedBody)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ContainerCreate ( arg0 context . Context , arg1 * container . Config , arg2 * container . HostConfig , arg3 * network . NetworkingConfig , arg4 string ) ( container . ContainerCreateCreatedBody , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 , arg3 , arg4 ) ret0 , _ := ret [ 0 ] . ( container . ContainerCreateCreatedBody ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ContainerInspect(arg0 context.Context, arg1 string) (types.ContainerJSON, error) {
	ret := m.ctrl.Call(m, "ContainerInspect", arg0, arg1)
	ret0, _ := ret[0].(types.ContainerJSON)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ContainerInspect ( arg0 context . Context , arg1 string ) ( types . ContainerJSON , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( types . ContainerJSON ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ContainerList(arg0 context.Context, arg1 types.ContainerListOptions) ([]types.Container, error) {
	ret := m.ctrl.Call(m, "ContainerList", arg0, arg1)
	ret0, _ := ret[0].([]types.Container)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ContainerList ( arg0 context . Context , arg1 types . ContainerListOptions ) ( [ ] types . Container , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( [ ] types . Container ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ContainerRemove(arg0 context.Context, arg1 string, arg2 types.ContainerRemoveOptions) error {
	ret := m.ctrl.Call(m, "ContainerRemove", arg0, arg1, arg2)
	ret0, _ := ret[0].(error)
	return ret0
}

func ( m * MockClient ) ContainerRemove ( arg0 context . Context , arg1 string , arg2 types . ContainerRemoveOptions ) error { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( error ) return ret0 }


func (m *MockClient) ContainerStart(arg0 context.Context, arg1 string, arg2 types.ContainerStartOptions) error {
	ret := m.ctrl.Call(m, "ContainerStart", arg0, arg1, arg2)
	ret0, _ := ret[0].(error)
	return ret0
}

func ( m * MockClient ) ContainerStart ( arg0 context . Context , arg1 string , arg2 types . ContainerStartOptions ) error { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( error ) return ret0 }


func (m *MockClient) ContainerStats(arg0 context.Context, arg1 string, arg2 bool) (types.ContainerStats, error) {
	ret := m.ctrl.Call(m, "ContainerStats", arg0, arg1, arg2)
	ret0, _ := ret[0].(types.ContainerStats)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ContainerStats ( arg0 context . Context , arg1 string , arg2 bool ) ( types . ContainerStats , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( types . ContainerStats ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ContainerStop(arg0 context.Context, arg1 string, arg2 *time.Duration) error {
	ret := m.ctrl.Call(m, "ContainerStop", arg0, arg1, arg2)
	ret0, _ := ret[0].(error)
	return ret0
}

func ( m * MockClient ) ContainerStop ( arg0 context . Context , arg1 string , arg2 * time . Duration ) error { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( error ) return ret0 }


func (m *MockClient) Events(arg0 context.Context, arg1 types.EventsOptions) (<-chan events.Message, <-chan error) {
	ret := m.ctrl.Call(m, "Events", arg0, arg1)
	ret0, _ := ret[0].(<-chan events.Message)
	ret1, _ := ret[1].(<-chan error)
	return ret0, ret1
}

func ( m * MockClient ) Events ( arg0 context . Context , arg1 types . EventsOptions ) ( <- chan events . Message , <- chan error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( <- chan events . Message ) ret1 , _ := ret [ 1 ] . ( <- chan error ) return ret0 , ret1 }


func (m *MockClient) ImageImport(arg0 context.Context, arg1 types.ImageImportSource, arg2 string, arg3 types.ImageImportOptions) (io.ReadCloser, error) {
	ret := m.ctrl.Call(m, "ImageImport", arg0, arg1, arg2, arg3)
	ret0, _ := ret[0].(io.ReadCloser)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ImageImport ( arg0 context . Context , arg1 types . ImageImportSource , arg2 string , arg3 types . ImageImportOptions ) ( io . ReadCloser , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 , arg3 ) ret0 , _ := ret [ 0 ] . ( io . ReadCloser ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ImageInspectWithRaw(arg0 context.Context, arg1 string) (types.ImageInspect, []byte, error) {
	ret := m.ctrl.Call(m, "ImageInspectWithRaw", arg0, arg1)
	ret0, _ := ret[0].(types.ImageInspect)
	ret1, _ := ret[1].([]byte)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

func ( m * MockClient ) ImageInspectWithRaw ( arg0 context . Context , arg1 string ) ( types . ImageInspect , [ ] byte , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( types . ImageInspect ) ret1 , _ := ret [ 1 ] . ( [ ] byte ) ret2 , _ := ret [ 2 ] . ( error ) return ret0 , ret1 , ret2 }

// ImageInspectWithRaw mocks base method


func (m *MockClient) ImageList(arg0 context.Context, arg1 types.ImageListOptions) ([]types.ImageSummary, error) {
	ret := m.ctrl.Call(m, "ImageList", arg0, arg1)
	ret0, _ := ret[0].([]types.ImageSummary)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ImageList ( arg0 context . Context , arg1 types . ImageListOptions ) ( [ ] types . ImageSummary , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( [ ] types . ImageSummary ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ImageLoad(arg0 context.Context, arg1 io.Reader, arg2 bool) (types.ImageLoadResponse, error) {
	ret := m.ctrl.Call(m, "ImageLoad", arg0, arg1, arg2)
	ret0, _ := ret[0].(types.ImageLoadResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ImageLoad ( arg0 context . Context , arg1 io . Reader , arg2 bool ) ( types . ImageLoadResponse , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( types . ImageLoadResponse ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ImagePull(arg0 context.Context, arg1 string, arg2 types.ImagePullOptions) (io.ReadCloser, error) {
	ret := m.ctrl.Call(m, "ImagePull", arg0, arg1, arg2)
	ret0, _ := ret[0].(io.ReadCloser)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ImagePull ( arg0 context . Context , arg1 string , arg2 types . ImagePullOptions ) ( io . ReadCloser , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( io . ReadCloser ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) ImageRemove(arg0 context.Context, arg1 string, arg2 types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) {
	ret := m.ctrl.Call(m, "ImageRemove", arg0, arg1, arg2)
	ret0, _ := ret[0].([]types.ImageDeleteResponseItem)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) ImageRemove ( arg0 context . Context , arg1 string , arg2 types . ImageRemoveOptions ) ( [ ] types . ImageDeleteResponseItem , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( [ ] types . ImageDeleteResponseItem ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) Ping(arg0 context.Context) (types.Ping, error) {
	ret := m.ctrl.Call(m, "Ping", arg0)
	ret0, _ := ret[0].(types.Ping)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) Ping ( arg0 context . Context ) ( types . Ping , error ) { ret := m . ctrl . Call ( m , " " , arg0 ) ret0 , _ := ret [ 0 ] . ( types . Ping ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) PluginList(arg0 context.Context, arg1 filters.Args) (types.PluginsListResponse, error) {
	ret := m.ctrl.Call(m, "PluginList", arg0, arg1)
	ret0, _ := ret[0].(types.PluginsListResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) PluginList ( arg0 context . Context , arg1 filters . Args ) ( types . PluginsListResponse , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( types . PluginsListResponse ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) VolumeCreate(arg0 context.Context, arg1 volume.VolumeCreateBody) (types.Volume, error) {
	ret := m.ctrl.Call(m, "VolumeCreate", arg0, arg1)
	ret0, _ := ret[0].(types.Volume)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) VolumeCreate ( arg0 context . Context , arg1 volume . VolumeCreateBody ) ( types . Volume , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( types . Volume ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) VolumeInspect(arg0 context.Context, arg1 string) (types.Volume, error) {
	ret := m.ctrl.Call(m, "VolumeInspect", arg0, arg1)
	ret0, _ := ret[0].(types.Volume)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockClient ) VolumeInspect ( arg0 context . Context , arg1 string ) ( types . Volume , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( types . Volume ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }


func (m *MockClient) VolumeRemove(arg0 context.Context, arg1 string, arg2 bool) error {
	ret := m.ctrl.Call(m, "VolumeRemove", arg0, arg1, arg2)
	ret0, _ := ret[0].(error)
	return ret0
}

func ( m * MockClient ) VolumeRemove ( arg0 context . Context , arg1 string , arg2 bool ) error { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( error ) return ret0 }


func (resolver *DockerContainerMetadataResolver) ResolveTask(dockerID string) (*apitask.Task, error) {
	if resolver.dockerTaskEngine == nil {
		return nil, fmt.Errorf("Docker task engine uninitialized")
	}
	task, found := resolver.dockerTaskEngine.State().TaskByID(dockerID)
	if !found {
		return nil, fmt.Errorf("Could not map docker id to task: %s", dockerID)
	}

	return task, nil
}

func ( resolver * DockerContainerMetadataResolver ) ResolveTask ( dockerID string ) ( * apitask . Task , error ) { if resolver . dockerTaskEngine == nil { return nil , fmt . Errorf ( " " ) } task , found := resolver . dockerTaskEngine . State ( ) . TaskByID ( dockerID ) if ! found { return nil , fmt . Errorf ( " " , dockerID ) } return task , nil }

// ResolveTask resolves the api task object, given container id.

ResolveTask resolves the api task object given container id .


func (resolver *DockerContainerMetadataResolver) ResolveContainer(dockerID string) (*apicontainer.DockerContainer, error) {
	if resolver.dockerTaskEngine == nil {
		return nil, fmt.Errorf("Docker task engine uninitialized")
	}
	container, found := resolver.dockerTaskEngine.State().ContainerByID(dockerID)
	if !found {
		return nil, fmt.Errorf("Could not map docker id to container: %s", dockerID)
	}

	return container, nil
}

func ( resolver * DockerContainerMetadataResolver ) ResolveContainer ( dockerID string ) ( * apicontainer . DockerContainer , error ) { if resolver . dockerTaskEngine == nil { return nil , fmt . Errorf ( " " ) } container , found := resolver . dockerTaskEngine . State ( ) . ContainerByID ( dockerID ) if ! found { return nil , fmt . Errorf ( " " , dockerID ) } return container , nil }

// ResolveContainer resolves the api container object, given container id.

ResolveContainer resolves the api container object given container id .


func (engine *DockerStatsEngine) synchronizeState() error {
	listContainersResponse := engine.client.ListContainers(engine.ctx, false, dockerclient.ListContainersTimeout)
	if listContainersResponse.Error != nil {
		return listContainersResponse.Error
	}

	for _, containerID := range listContainersResponse.DockerIDs {
		engine.addAndStartStatsContainer(containerID)
	}
	return nil
}

func ( engine * DockerStatsEngine ) synchronizeState ( ) error { listContainersResponse := engine . client . ListContainers ( engine . ctx , false , dockerclient . ListContainersTimeout ) if listContainersResponse . Error != nil { return listContainersResponse . Error } for _ , containerID := range listContainersResponse . DockerIDs { engine . addAndStartStatsContainer ( containerID ) } return nil }

// synchronizeState goes through all the containers on the instance to synchronize the state on agent start


func (engine *DockerStatsEngine) addAndStartStatsContainer(containerID string) {
	engine.lock.Lock()
	defer engine.lock.Unlock()
	statsContainer, err := engine.addContainerUnsafe(containerID)
	if err != nil {
		seelog.Debugf("Adding container to stats watch list failed, container: %s, err: %v", containerID, err)
		return
	}

	if engine.disableMetrics || statsContainer == nil {
		return
	}

	statsContainer.StartStatsCollection()
}

func ( engine * DockerStatsEngine ) addAndStartStatsContainer ( containerID string ) { engine . lock . Lock ( ) defer engine . lock . Unlock ( ) statsContainer , err := engine . addContainerUnsafe ( containerID ) if err != nil { seelog . Debugf ( " " , containerID , err ) return } if engine . disableMetrics || statsContainer == nil { return } statsContainer . StartStatsCollection ( ) }

// addAndStartStatsContainer add the container into stats engine and start collecting the container stats


func (engine *DockerStatsEngine) MustInit(ctx context.Context, taskEngine ecsengine.TaskEngine, cluster string, containerInstanceArn string) error {
	derivedCtx, cancel := context.WithCancel(ctx)
	engine.stopEngine = cancel

	engine.ctx = derivedCtx
	// TODO ensure that this is done only once per engine object
	seelog.Info("Initializing stats engine")
	engine.cluster = cluster
	engine.containerInstanceArn = containerInstanceArn

	var err error
	engine.resolver, err = newDockerContainerMetadataResolver(taskEngine)
	if err != nil {
		return err
	}

	// Subscribe to the container change event stream
	err = engine.containerChangeEventStream.Subscribe(containerChangeHandler, engine.handleDockerEvents)
	if err != nil {
		return fmt.Errorf("Failed to subscribe to container change event stream, err %v", err)
	}

	err = engine.synchronizeState()
	if err != nil {
		seelog.Warnf("Synchronize the container state failed, err: %v", err)
	}

	go engine.waitToStop()
	return nil
}

// MustInit initializes fields of the DockerStatsEngine object.

MustInit initializes fields of the DockerStatsEngine object .


func (engine *DockerStatsEngine) waitToStop() {
	// Waiting for the event stream to close
	ctx := engine.containerChangeEventStream.Context()
	select {
	case <-ctx.Done():
		seelog.Debug("Event stream closed, stop listening to the event stream")
		engine.containerChangeEventStream.Unsubscribe(containerChangeHandler)
		engine.removeAll()
	}
}

// waitToStop waits for the container change event stream close ans stop collection metrics


func (engine *DockerStatsEngine) removeAll() {
	engine.lock.Lock()
	defer engine.lock.Unlock()

	for task, containers := range engine.tasksToContainers {
		for _, statsContainer := range containers {
			statsContainer.StopStatsCollection()
		}
		delete(engine.tasksToContainers, task)
	}

	for task := range engine.tasksToHealthCheckContainers {
		delete(engine.tasksToContainers, task)
	}
}

func ( engine * DockerStatsEngine ) removeAll ( ) { engine . lock . Lock ( ) defer engine . lock . Unlock ( ) for task , containers := range engine . tasksToContainers { for _ , statsContainer := range containers { statsContainer . StopStatsCollection ( ) } delete ( engine . tasksToContainers , task ) } for task := range engine . tasksToHealthCheckContainers { delete ( engine . tasksToContainers , task ) } }

// removeAll stops the periodic usage data collection for all containers


func (engine *DockerStatsEngine) addContainerUnsafe(dockerID string) (*StatsContainer, error) {
	// Make sure that this container belongs to a task and that the task
	// is not terminal.
	task, err := engine.resolver.ResolveTask(dockerID)
	if err != nil {
		return nil, errors.Wrapf(err, "could not map container to task, ignoring container: %s", dockerID)
	}

	if len(task.Arn) == 0 || len(task.Family) == 0 {
		return nil, errors.Errorf("stats add container: invalid task fields, arn: %s, familiy: %s", task.Arn, task.Family)
	}

	if task.GetKnownStatus().Terminal() {
		return nil, errors.Errorf("stats add container: task is terminal, ignoring container: %s, task: %s", dockerID, task.Arn)
	}

	seelog.Debugf("Adding container to stats watch list, id: %s, task: %s", dockerID, task.Arn)
	statsContainer := newStatsContainer(dockerID, engine.client, engine.resolver)
	engine.tasksToDefinitions[task.Arn] = &taskDefinition{family: task.Family, version: task.Version}

	watchStatsContainer := false
	if !engine.disableMetrics {
		// Adding container to the map for collecting stats
		watchStatsContainer = engine.addToStatsContainerMapUnsafe(task.Arn, dockerID, statsContainer, engine.containerMetricsMapUnsafe)
	}

	if dockerContainer, err := engine.resolver.ResolveContainer(dockerID); err != nil {
		seelog.Debugf("Could not map container ID to container, container: %s, err: %s", dockerID, err)
	} else if dockerContainer.Container.HealthStatusShouldBeReported() {
		// Track the container health status
		engine.addToStatsContainerMapUnsafe(task.Arn, dockerID, statsContainer, engine.healthCheckContainerMapUnsafe)
		seelog.Debugf("Adding container to stats health check watch list, id: %s, task: %s", dockerID, task.Arn)
	}

	if !watchStatsContainer {
		return nil, nil
	}
	return statsContainer, nil
}

// addContainerUnsafe adds a container to the map of containers being watched.

addContainerUnsafe adds a container to the map of containers being watched .


func (engine *DockerStatsEngine) addToStatsContainerMapUnsafe(
	taskARN, containerID string,
	statsContainer *StatsContainer,
	statsMapToUpdate func() map[string]map[string]*StatsContainer) bool {

	taskToContainerMap := statsMapToUpdate()

	// Check if this container is already being watched.
	_, taskExists := taskToContainerMap[taskARN]
	if taskExists {
		// task arn exists in map.
		_, containerExists := taskToContainerMap[taskARN][containerID]
		if containerExists {
			// container arn exists in map.
			seelog.Debugf("Container already being watched, ignoring, id: %s", containerID)
			return false
		}
	} else {
		// Create a map for the task arn if it doesn't exist yet.
		taskToContainerMap[taskARN] = make(map[string]*StatsContainer)
	}
	taskToContainerMap[taskARN][containerID] = statsContainer

	return true
}

// addToStatsContainerMapUnsafe adds the statscontainer into stats for tracking and returns a boolean indicates
// whether this container should be tracked for collecting metrics

addToStatsContainerMapUnsafe adds the statscontainer into stats for tracking and returns a boolean indicates whether this container should be tracked for collecting metrics


func (engine *DockerStatsEngine) GetInstanceMetrics() (*ecstcs.MetricsMetadata, []*ecstcs.TaskMetric, error) {
	var taskMetrics []*ecstcs.TaskMetric
	idle := engine.isIdle()
	metricsMetadata := &ecstcs.MetricsMetadata{
		Cluster:           aws.String(engine.cluster),
		ContainerInstance: aws.String(engine.containerInstanceArn),
		Idle:              aws.Bool(idle),
		MessageId:         aws.String(uuid.NewRandom().String()),
	}

	if idle {
		seelog.Debug("Instance is idle. No task metrics to report")
		fin := true
		metricsMetadata.Fin = &fin
		return metricsMetadata, taskMetrics, nil
	}

	engine.lock.Lock()
	defer engine.lock.Unlock()

	for taskArn := range engine.tasksToContainers {
		containerMetrics, err := engine.taskContainerMetricsUnsafe(taskArn)
		if err != nil {
			seelog.Debugf("Error getting container metrics for task: %s, err: %v", taskArn, err)
			continue
		}

		if len(containerMetrics) == 0 {
			seelog.Debugf("Empty containerMetrics for task, ignoring, task: %s", taskArn)
			continue
		}

		taskDef, exists := engine.tasksToDefinitions[taskArn]
		if !exists {
			seelog.Debugf("Could not map task to definition, task: %s", taskArn)
			continue
		}

		metricTaskArn := taskArn
		taskMetric := &ecstcs.TaskMetric{
			TaskArn:               &metricTaskArn,
			TaskDefinitionFamily:  &taskDef.family,
			TaskDefinitionVersion: &taskDef.version,
			ContainerMetrics:      containerMetrics,
		}
		taskMetrics = append(taskMetrics, taskMetric)
	}

	if len(taskMetrics) == 0 {
		// Not idle. Expect taskMetrics to be there.
		return nil, nil, EmptyMetricsError
	}

	// Reset current stats. Retaining older stats results in incorrect utilization stats
	// until they are removed from the queue.
	engine.resetStatsUnsafe()
	return metricsMetadata, taskMetrics, nil
}

// GetInstanceMetrics gets all task metrics and instance metadata from stats engine.

GetInstanceMetrics gets all task metrics and instance metadata from stats engine .


func (engine *DockerStatsEngine) GetTaskHealthMetrics() (*ecstcs.HealthMetadata, []*ecstcs.TaskHealth, error) {
	var taskHealths []*ecstcs.TaskHealth
	metadata := &ecstcs.HealthMetadata{
		Cluster:           aws.String(engine.cluster),
		ContainerInstance: aws.String(engine.containerInstanceArn),
		MessageId:         aws.String(uuid.NewRandom().String()),
	}

	if !engine.containerHealthsToMonitor() {
		return metadata, taskHealths, nil
	}

	engine.lock.RLock()
	defer engine.lock.RUnlock()

	for taskARN := range engine.tasksToHealthCheckContainers {
		taskHealth := engine.getTaskHealthUnsafe(taskARN)
		if taskHealth == nil {
			continue
		}
		taskHealths = append(taskHealths, taskHealth)
	}

	if len(taskHealths) == 0 {
		return nil, nil, EmptyHealthMetricsError
	}

	return metadata, taskHealths, nil
}

func ( engine * DockerStatsEngine ) GetTaskHealthMetrics ( ) ( * ecstcs . HealthMetadata , [ ] * ecstcs . TaskHealth , error ) { var taskHealths [ ] * ecstcs . TaskHealth metadata := & ecstcs . HealthMetadata { Cluster : aws . String ( engine . cluster ) , ContainerInstance : aws . String ( engine . containerInstanceArn ) , MessageId : aws . String ( uuid . NewRandom ( ) . String ( ) ) , } if ! engine . containerHealthsToMonitor ( ) { return metadata , taskHealths , nil } engine . lock . RLock ( ) defer engine . lock . RUnlock ( ) for taskARN := range engine . tasksToHealthCheckContainers { taskHealth := engine . getTaskHealthUnsafe ( taskARN ) if taskHealth == nil { continue } taskHealths = append ( taskHealths , taskHealth ) } if len ( taskHealths ) == 0 { return nil , nil , EmptyHealthMetricsError } return metadata , taskHealths , nil }

// GetTaskHealthMetrics returns the container health metrics


func (engine *DockerStatsEngine) stopTrackingContainerUnsafe(container *StatsContainer, taskARN string) bool {
	terminal, err := container.terminal()
	if err != nil {
		// Error determining if the container is terminal. This means that the container
		// id could not be resolved to a container that is being tracked by the
		// docker task engine. If the docker task engine has already removed
		// the container from its state, there's no point in stats engine tracking the
		// container. So, clean-up anyway.
		seelog.Warnf("Error determining if the container %s is terminal, removing from stats, err: %v", container.containerMetadata.DockerID, err)
		engine.doRemoveContainerUnsafe(container, taskARN)
		return true
	}
	if terminal {
		// Container is in known terminal state. Stop collection metrics.
		seelog.Infof("Container %s is terminal, removing from stats", container.containerMetadata.DockerID)
		engine.doRemoveContainerUnsafe(container, taskARN)
		return true
	}

	return false
}

// stopTrackingContainerUnsafe removes the StatsContainer from stats engine and
// returns true if the container is stopped or no longer tracked in agent. Otherwise
// it does nothing and return false

stopTrackingContainerUnsafe removes the StatsContainer from stats engine and returns true if the container is stopped or no longer tracked in agent . Otherwise it does nothing and return false


func (engine *DockerStatsEngine) handleDockerEvents(events ...interface{}) error {
	for _, event := range events {
		dockerContainerChangeEvent, ok := event.(dockerapi.DockerContainerChangeEvent)
		if !ok {
			return fmt.Errorf("Unexpected event received, expected docker container change event")
		}

		switch dockerContainerChangeEvent.Status {
		case apicontainerstatus.ContainerRunning:
			engine.addAndStartStatsContainer(dockerContainerChangeEvent.DockerID)
		case apicontainerstatus.ContainerStopped:
			engine.removeContainer(dockerContainerChangeEvent.DockerID)
		default:
			seelog.Debugf("Ignoring event for container, id: %s, status: %d", dockerContainerChangeEvent.DockerID, dockerContainerChangeEvent.Status)
		}
	}

	return nil
}

func ( engine * DockerStatsEngine ) handleDockerEvents ( events ... interface { } ) error { for _ , event := range events { dockerContainerChangeEvent , ok := event . ( dockerapi . DockerContainerChangeEvent ) if ! ok { return fmt . Errorf ( " " ) } switch dockerContainerChangeEvent . Status { case apicontainerstatus . ContainerRunning : engine . addAndStartStatsContainer ( dockerContainerChangeEvent . DockerID ) case apicontainerstatus . ContainerStopped : engine . removeContainer ( dockerContainerChangeEvent . DockerID ) default : seelog . Debugf ( " " , dockerContainerChangeEvent . DockerID , dockerContainerChangeEvent . Status ) } } return nil }

// handleDockerEvents must be called after openEventstream; it processes each
// event that it reads from the docker event stream.

handleDockerEvents must be called after openEventstream ; it processes each event that it reads from the docker event stream .


func (engine *DockerStatsEngine) removeContainer(dockerID string) {
	engine.lock.Lock()
	defer engine.lock.Unlock()

	// Make sure that this container belongs to a task.
	task, err := engine.resolver.ResolveTask(dockerID)
	if err != nil {
		seelog.Debugf("Could not map container to task, ignoring, err: %v, id: %s", err, dockerID)
		return
	}

	_, taskExists := engine.tasksToContainers[task.Arn]
	if !taskExists {
		seelog.Debugf("Container not being watched, id: %s", dockerID)
		return
	}

	// task arn exists in map.
	container, containerExists := engine.tasksToContainers[task.Arn][dockerID]
	if !containerExists {
		// container arn does not exist in map.
		seelog.Debugf("Container not being watched, id: %s", dockerID)
		return
	}

	engine.doRemoveContainerUnsafe(container, task.Arn)
}

// removeContainer deletes the container from the map of containers being watched.
// It also stops the periodic usage data collection for the container.

removeContainer deletes the container from the map of containers being watched . It also stops the periodic usage data collection for the container .


func newDockerContainerMetadataResolver(taskEngine ecsengine.TaskEngine) (*DockerContainerMetadataResolver, error) {
	dockerTaskEngine, ok := taskEngine.(*ecsengine.DockerTaskEngine)
	if !ok {
		// Error type casting docker task engine.
		return nil, fmt.Errorf("Could not load docker task engine")
	}

	resolver := &DockerContainerMetadataResolver{
		dockerTaskEngine: dockerTaskEngine,
	}

	return resolver, nil
}

// newDockerContainerMetadataResolver returns a new instance of DockerContainerMetadataResolver.

newDockerContainerMetadataResolver returns a new instance of DockerContainerMetadataResolver .


func (engine *DockerStatsEngine) taskContainerMetricsUnsafe(taskArn string) ([]*ecstcs.ContainerMetric, error) {
	containerMap, taskExists := engine.tasksToContainers[taskArn]
	if !taskExists {
		return nil, fmt.Errorf("Task not found")
	}

	var containerMetrics []*ecstcs.ContainerMetric
	for _, container := range containerMap {
		dockerID := container.containerMetadata.DockerID
		// Check if the container is terminal. If it is, make sure that it is
		// cleaned up properly. We might sometimes miss events from docker task
		// engine and this helps in reconciling the state. The tcs client's
		// GetInstanceMetrics probe is used as the trigger for this.
		if engine.stopTrackingContainerUnsafe(container, taskArn) {
			continue
		}

		if !container.statsQueue.enoughDatapointsInBuffer() &&
			!container.statsQueue.resetThresholdElapsed(queueResetThreshold) {
			seelog.Debugf("Stats not ready for container %s", dockerID)
			continue
		}

		// Container is not terminal. Get CPU stats set.
		cpuStatsSet, err := container.statsQueue.GetCPUStatsSet()
		if err != nil {
			seelog.Warnf("Error getting cpu stats, err: %v, container: %v", err, dockerID)
			continue
		}

		// Get memory stats set.
		memoryStatsSet, err := container.statsQueue.GetMemoryStatsSet()
		if err != nil {
			seelog.Warnf("Error getting memory stats, err: %v, container: %v", err, dockerID)
			continue
		}

		containerMetrics = append(containerMetrics, &ecstcs.ContainerMetric{
			CpuStatsSet:    cpuStatsSet,
			MemoryStatsSet: memoryStatsSet,
		})

	}

	return containerMetrics, nil
}

// taskContainerMetricsUnsafe gets all container metrics for a task arn.

taskContainerMetricsUnsafe gets all container metrics for a task arn .


func (engine *DockerStatsEngine) resetStatsUnsafe() {
	for _, containerMap := range engine.tasksToContainers {
		for _, container := range containerMap {
			container.statsQueue.Reset()
		}
	}
}

func ( engine * DockerStatsEngine ) resetStatsUnsafe ( ) { for _ , containerMap := range engine . tasksToContainers { for _ , container := range containerMap { container . statsQueue . Reset ( ) } } }

// resetStatsUnsafe resets stats for all watched containers.

resetStatsUnsafe resets stats for all watched containers .


func (engine *DockerStatsEngine) ContainerDockerStats(taskARN string, containerID string) (*types.StatsJSON, error) {
	engine.lock.RLock()
	defer engine.lock.RUnlock()

	containerIDToStatsContainer, ok := engine.tasksToContainers[taskARN]
	if !ok {
		return nil, errors.Errorf("stats engine: task '%s' for container '%s' not found",
			taskARN, containerID)
	}

	container, ok := containerIDToStatsContainer[containerID]
	if !ok {
		return nil, errors.Errorf("stats engine: container not found: %s", containerID)
	}
	return container.statsQueue.GetLastStat(), nil

}

func ( engine * DockerStatsEngine ) ContainerDockerStats ( taskARN string , containerID string ) ( * types . StatsJSON , error ) { engine . lock . RLock ( ) defer engine . lock . RUnlock ( ) containerIDToStatsContainer , ok := engine . tasksToContainers [ taskARN ] if ! ok { return nil , errors . Errorf ( " " , taskARN , containerID ) } container , ok := containerIDToStatsContainer [ containerID ] if ! ok { return nil , errors . Errorf ( " " , containerID ) } return container . statsQueue . GetLastStat ( ) , nil }

// ContainerDockerStats returns the last stored raw docker stats object for a container


func newMetricsMetadata(cluster *string, containerInstance *string) *ecstcs.MetricsMetadata {
	return &ecstcs.MetricsMetadata{
		Cluster:           cluster,
		ContainerInstance: containerInstance,
	}
}

func newMetricsMetadata ( cluster * string , containerInstance * string ) * ecstcs . MetricsMetadata { return & ecstcs . MetricsMetadata { Cluster : cluster , ContainerInstance : containerInstance , } }

// newMetricsMetadata creates the singleton metadata object.

newMetricsMetadata creates the singleton metadata object .


func compareSemver(lhs, rhs semver) int {
	if lhs.major < rhs.major {
		return -1
	}
	if lhs.major > rhs.major {
		return 1
	}
	if lhs.minor < rhs.minor {
		return -1
	}
	if lhs.minor > rhs.minor {
		return 1
	}
	if lhs.patch < rhs.patch {
		return -1
	}
	if lhs.patch > rhs.patch {
		return 1
	}
	if lhs.preReleaseVersion != "" && rhs.preReleaseVersion == "" {
		return -1
	}
	if lhs.preReleaseVersion == "" && rhs.preReleaseVersion != "" {
		return 1
	}
	if lhs.preReleaseVersion < rhs.preReleaseVersion {
		return -1
	}
	if lhs.preReleaseVersion > rhs.preReleaseVersion {
		return 1
	}
	return 0
}

func compareSemver ( lhs , rhs semver ) int { if lhs . major < rhs . major { return - 1 } if lhs . major > rhs . major { return 1 } if lhs . minor < rhs . minor { return - 1 } if lhs . minor > rhs . minor { return 1 } if lhs . patch < rhs . patch { return - 1 } if lhs . patch > rhs . patch { return 1 } if lhs . preReleaseVersion != " " && rhs . preReleaseVersion == " " { return - 1 } if lhs . preReleaseVersion == " " && rhs . preReleaseVersion != " " { return 1 } if lhs . preReleaseVersion < rhs . preReleaseVersion { return - 1 } if lhs . preReleaseVersion > rhs . preReleaseVersion { return 1 } return 0 }

// compareSemver compares two semvers, 'lhs' and 'rhs', and returns -1 if lhs is less
// than rhs, 0 if they are equal, and 1 lhs is greater than rhs

compareSemver compares two semvers lhs and rhs and returns - 1 if lhs is less than rhs 0 if they are equal and 1 lhs is greater than rhs


func ExtractVersion(input string) string {
	versionNumberRegex := regexp.MustCompile(` v(\d+\.\d+\.\d+(\-[\S\.\-]+)?(\+[\S\.\-]+)?)`)
	versionNumberStr := versionNumberRegex.FindStringSubmatch(input)
	if len(versionNumberStr) >= 2 {
		return string(versionNumberStr[1])
	}
	return "UNKNOWN"
}

// ExtractVersion extracts a matching version from the version number string


func (role *TaskIAMRoleCredentials) GetIAMRoleCredentials() IAMRoleCredentials {
	role.lock.RLock()
	defer role.lock.RUnlock()

	return role.IAMRoleCredentials
}

func ( role * TaskIAMRoleCredentials ) GetIAMRoleCredentials ( ) IAMRoleCredentials { role . lock . RLock ( ) defer role . lock . RUnlock ( ) return role . IAMRoleCredentials }

// GetIAMRoleCredentials returns the IAM role credentials in the task IAM role struct


func (roleCredentials *IAMRoleCredentials) GenerateCredentialsEndpointRelativeURI() string {
	return fmt.Sprintf(credentialsEndpointRelativeURIFormat, CredentialsPath, roleCredentials.CredentialsID)
}

func ( roleCredentials * IAMRoleCredentials ) GenerateCredentialsEndpointRelativeURI ( ) string { return fmt . Sprintf ( credentialsEndpointRelativeURIFormat , CredentialsPath , roleCredentials . CredentialsID ) }

// GenerateCredentialsEndpointRelativeURI generates the relative URI for the
// credentials endpoint, for a given task id.

GenerateCredentialsEndpointRelativeURI generates the relative URI for the credentials endpoint for a given task id .


func IAMRoleCredentialsFromACS(roleCredentials *ecsacs.IAMRoleCredentials, roleType string) IAMRoleCredentials {
	return IAMRoleCredentials{
		CredentialsID:   aws.StringValue(roleCredentials.CredentialsId),
		SessionToken:    aws.StringValue(roleCredentials.SessionToken),
		RoleArn:         aws.StringValue(roleCredentials.RoleArn),
		AccessKeyID:     aws.StringValue(roleCredentials.AccessKeyId),
		SecretAccessKey: aws.StringValue(roleCredentials.SecretAccessKey),
		Expiration:      aws.StringValue(roleCredentials.Expiration),
		RoleType:        roleType,
	}
}

func IAMRoleCredentialsFromACS ( roleCredentials * ecsacs . IAMRoleCredentials , roleType string ) IAMRoleCredentials { return IAMRoleCredentials { CredentialsID : aws . StringValue ( roleCredentials . CredentialsId ) , SessionToken : aws . StringValue ( roleCredentials . SessionToken ) , RoleArn : aws . StringValue ( roleCredentials . RoleArn ) , AccessKeyID : aws . StringValue ( roleCredentials . AccessKeyId ) , SecretAccessKey : aws . StringValue ( roleCredentials . SecretAccessKey ) , Expiration : aws . StringValue ( roleCredentials . Expiration ) , RoleType : roleType , } }

// IAMRoleCredentialsFromACS translates ecsacs.IAMRoleCredentials object to
// api.IAMRoleCredentials

IAMRoleCredentialsFromACS translates ecsacs . IAMRoleCredentials object to api . IAMRoleCredentials


func (manager *credentialsManager) SetTaskCredentials(taskCredentials *TaskIAMRoleCredentials) error {
	manager.taskCredentialsLock.Lock()
	defer manager.taskCredentialsLock.Unlock()

	credentials := taskCredentials.IAMRoleCredentials
	// Validate that credentials id is not empty
	if credentials.CredentialsID == "" {
		return fmt.Errorf("CredentialsId is empty")
	}

	// Validate that task arn is not empty
	if taskCredentials.ARN == "" {
		return fmt.Errorf("task ARN is empty")
	}

	manager.idToTaskCredentials[credentials.CredentialsID] = TaskIAMRoleCredentials{
		ARN:                taskCredentials.ARN,
		IAMRoleCredentials: taskCredentials.GetIAMRoleCredentials(),
	}

	return nil
}

// SetTaskCredentials adds or updates credentials in the credentials manager


func (manager *credentialsManager) GetTaskCredentials(id string) (TaskIAMRoleCredentials, bool) {
	manager.taskCredentialsLock.RLock()
	defer manager.taskCredentialsLock.RUnlock()

	taskCredentials, ok := manager.idToTaskCredentials[id]

	if !ok {
		return TaskIAMRoleCredentials{}, ok
	}
	return TaskIAMRoleCredentials{
		ARN:                taskCredentials.ARN,
		IAMRoleCredentials: taskCredentials.GetIAMRoleCredentials(),
	}, ok
}

func ( manager * credentialsManager ) GetTaskCredentials ( id string ) ( TaskIAMRoleCredentials , bool ) { manager . taskCredentialsLock . RLock ( ) defer manager . taskCredentialsLock . RUnlock ( ) taskCredentials , ok := manager . idToTaskCredentials [ id ] if ! ok { return TaskIAMRoleCredentials { } , ok } return TaskIAMRoleCredentials { ARN : taskCredentials . ARN , IAMRoleCredentials : taskCredentials . GetIAMRoleCredentials ( ) , } , ok }

// GetTaskCredentials retrieves credentials for a given credentials id


func (manager *credentialsManager) RemoveCredentials(id string) {
	manager.taskCredentialsLock.Lock()
	defer manager.taskCredentialsLock.Unlock()

	delete(manager.idToTaskCredentials, id)
}

func ( manager * credentialsManager ) RemoveCredentials ( id string ) { manager . taskCredentialsLock . Lock ( ) defer manager . taskCredentialsLock . Unlock ( ) delete ( manager . idToTaskCredentials , id ) }

// RemoveCredentials removes credentials from the credentials manager


func verifyResponseFieldNames(expectedFields []string, responseBody []byte, responseName string) error {
	var responseMap map[string]json.RawMessage
	if err := json.Unmarshal(responseBody, &responseMap); err != nil {
		fmt.Errorf("unable to unmarshal %s response to response map", responseName)
	}

	for _, field := range expectedFields {
		if _, ok := responseMap[field]; !ok {
			return fmt.Errorf("missing field '%s' in %s response", field, responseName)
		}
	}

	return nil
}

func verifyResponseFieldNames ( expectedFields [ ] string , responseBody [ ] byte , responseName string ) error { var responseMap map [ string ] json . RawMessage if err := json . Unmarshal ( responseBody , & responseMap ) ; err != nil { fmt . Errorf ( " " , responseName ) } for _ , field := range expectedFields { if _ , ok := responseMap [ field ] ; ! ok { return fmt . Errorf ( " " , field , responseName ) } } return nil }

// verify all the field names in the response are what we expected. this is needed because a direct unmarshal
// is not case sensitive so can't ensure that the response is in valid format

verify all the field names in the response are what we expected . this is needed because a direct unmarshal is not case sensitive so can t ensure that the response is in valid format


func (m *MockOS) Getpid() int {
	ret := m.ctrl.Call(m, "Getpid")
	ret0, _ := ret[0].(int)
	return ret0
}

func ( m * MockOS ) Getpid ( ) int { ret := m . ctrl . Call ( m , " " ) ret0 , _ := ret [ 0 ] . ( int ) return ret0 }


func (mr *MockOSMockRecorder) Getpid() *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Getpid", reflect.TypeOf((*MockOS)(nil).Getpid))
}

func ( mr * MockOSMockRecorder ) Getpid ( ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockOS ) ( nil ) . Getpid ) ) }

// Getpid indicates an expected call of Getpid


func AppMeshFromACS(proxyConfig *ecsacs.ProxyConfiguration) (*AppMesh, error) {

	if *proxyConfig.Type != appMesh {
		return nil, fmt.Errorf("agent does not support proxy type other than app mesh")
	}

	return &AppMesh{
		ContainerName:      aws.StringValue(proxyConfig.ContainerName),
		IgnoredUID:         aws.StringValue(proxyConfig.Properties[ignoredUID]),
		IgnoredGID:         aws.StringValue(proxyConfig.Properties[ignoredGID]),
		ProxyIngressPort:   aws.StringValue(proxyConfig.Properties[proxyIngressPort]),
		ProxyEgressPort:    aws.StringValue(proxyConfig.Properties[proxyEgressPort]),
		AppPorts:           buildAppPorts(proxyConfig),
		EgressIgnoredIPs:   buildEgressIgnoredIPs(proxyConfig),
		EgressIgnoredPorts: buildEgressIgnoredPorts(proxyConfig),
	}, nil
}

func AppMeshFromACS ( proxyConfig * ecsacs . ProxyConfiguration ) ( * AppMesh , error ) { if * proxyConfig . Type != appMesh { return nil , fmt . Errorf ( " " ) } return & AppMesh { ContainerName : aws . StringValue ( proxyConfig . ContainerName ) , IgnoredUID : aws . StringValue ( proxyConfig . Properties [ ignoredUID ] ) , IgnoredGID : aws . StringValue ( proxyConfig . Properties [ ignoredGID ] ) , ProxyIngressPort : aws . StringValue ( proxyConfig . Properties [ proxyIngressPort ] ) , ProxyEgressPort : aws . StringValue ( proxyConfig . Properties [ proxyEgressPort ] ) , AppPorts : buildAppPorts ( proxyConfig ) , EgressIgnoredIPs : buildEgressIgnoredIPs ( proxyConfig ) , EgressIgnoredPorts : buildEgressIgnoredPorts ( proxyConfig ) , } , nil }

// AppMeshFromACS validates proxy config if it is app mesh type and creates AppMesh object


func buildAppPorts(proxyConfig *ecsacs.ProxyConfiguration) []string {
	var inputAppPorts []string
	if proxyConfig.Properties[appPorts] != nil {
		inputAppPorts = strings.Split(*proxyConfig.Properties[appPorts], splitter)
	}
	return inputAppPorts
}

func buildAppPorts ( proxyConfig * ecsacs . ProxyConfiguration ) [ ] string { var inputAppPorts [ ] string if proxyConfig . Properties [ appPorts ] != nil { inputAppPorts = strings . Split ( * proxyConfig . Properties [ appPorts ] , splitter ) } return inputAppPorts }

// buildAppPorts creates app ports from proxy config


func buildEgressIgnoredIPs(proxyConfig *ecsacs.ProxyConfiguration) []string {
	var inputEgressIgnoredIPs []string
	if proxyConfig.Properties[egressIgnoredIPs] != nil {
		inputEgressIgnoredIPs = strings.Split(*proxyConfig.Properties[egressIgnoredIPs], splitter)
	}
	// append agent default egress ignored IPs
	return appendDefaultEgressIgnoredIPs(inputEgressIgnoredIPs)
}

// buildEgressIgnoredIPs creates egress ignored IPs from proxy config


func buildEgressIgnoredPorts(proxyConfig *ecsacs.ProxyConfiguration) []string {
	var inputEgressIgnoredPorts []string
	if proxyConfig.Properties[egressIgnoredPorts] != nil {
		inputEgressIgnoredPorts = strings.Split(*proxyConfig.Properties[egressIgnoredPorts], splitter)
	}
	return inputEgressIgnoredPorts
}

func buildEgressIgnoredPorts ( proxyConfig * ecsacs . ProxyConfiguration ) [ ] string { var inputEgressIgnoredPorts [ ] string if proxyConfig . Properties [ egressIgnoredPorts ] != nil { inputEgressIgnoredPorts = strings . Split ( * proxyConfig . Properties [ egressIgnoredPorts ] , splitter ) } return inputEgressIgnoredPorts }

// buildEgressIgnoredPorts creates egress ignored ports from proxy config


func appendDefaultEgressIgnoredIPs(egressIgnoredIPs []string) []string {
	hasTaskMetadataEndpointIP := false
	hasInstanceMetadataEndpointIP := false
	for _, egressIgnoredIP := range egressIgnoredIPs {
		if strings.TrimSpace(egressIgnoredIP) == taskMetadataEndpointIP {
			hasTaskMetadataEndpointIP = true
		}
		if strings.TrimSpace(egressIgnoredIP) == instanceMetadataEndpointIP {
			hasInstanceMetadataEndpointIP = true
		}
	}

	if !hasTaskMetadataEndpointIP {
		egressIgnoredIPs = append(egressIgnoredIPs, taskMetadataEndpointIP)
	}
	if !hasInstanceMetadataEndpointIP {
		egressIgnoredIPs = append(egressIgnoredIPs, instanceMetadataEndpointIP)
	}

	return egressIgnoredIPs
}

func appendDefaultEgressIgnoredIPs ( egressIgnoredIPs [ ] string ) [ ] string { hasTaskMetadataEndpointIP := false hasInstanceMetadataEndpointIP := false for _ , egressIgnoredIP := range egressIgnoredIPs { if strings . TrimSpace ( egressIgnoredIP ) == taskMetadataEndpointIP { hasTaskMetadataEndpointIP = true } if strings . TrimSpace ( egressIgnoredIP ) == instanceMetadataEndpointIP { hasInstanceMetadataEndpointIP = true } } if ! hasTaskMetadataEndpointIP { egressIgnoredIPs = append ( egressIgnoredIPs , taskMetadataEndpointIP ) } if ! hasInstanceMetadataEndpointIP { egressIgnoredIPs = append ( egressIgnoredIPs , instanceMetadataEndpointIP ) } return egressIgnoredIPs }

// appendDefaultEgressIgnoredIPs append task metadata endpoint ip and
// instance metadata ip address to egress ignored IPs if does not exist

appendDefaultEgressIgnoredIPs append task metadata endpoint ip and instance metadata ip address to egress ignored IPs if does not exist


func IsInstanceTypeChangedError(err error) bool {
	if awserr, ok := err.(awserr.Error); ok {
		return strings.Contains(awserr.Message(), InstanceTypeChangedErrorMessage)
	}
	return false
}

func IsInstanceTypeChangedError ( err error ) bool { if awserr , ok := err . ( awserr . Error ) ; ok { return strings . Contains ( awserr . Message ( ) , InstanceTypeChangedErrorMessage ) } return false }

// IsInstanceTypeChangedError returns true if the error when
// registering the container instance is because of instance type being
// changed

IsInstanceTypeChangedError returns true if the error when registering the container instance is because of instance type being changed


func NewNamedError(err error) *DefaultNamedError {
	if namedErr, ok := err.(NamedError); ok {
		return &DefaultNamedError{Err: namedErr.Error(), Name: namedErr.ErrorName()}
	}
	return &DefaultNamedError{Err: err.Error()}
}

func NewNamedError ( err error ) * DefaultNamedError { if namedErr , ok := err . ( NamedError ) ; ok { return & DefaultNamedError { Err : namedErr . Error ( ) , Name : namedErr . ErrorName ( ) } } return & DefaultNamedError { Err : err . Error ( ) } }


func (err *ResourceInitError) Error() string {
	return fmt.Sprintf("resource cannot be initialized for task %s: %v", err.taskARN, err.origErr)
}

func ( err * ResourceInitError ) Error ( ) string { return fmt . Sprintf ( " " , err . taskARN , err . origErr ) }


func (task *Task) BuildLinuxResourceSpec() (specs.LinuxResources, error) {
	linuxResourceSpec := specs.LinuxResources{}

	// If task level CPU limits are requested, set CPU quota + CPU period
	// Else set CPU shares
	if task.CPU > 0 {
		linuxCPUSpec, err := task.buildExplicitLinuxCPUSpec()
		if err != nil {
			return specs.LinuxResources{}, err
		}
		linuxResourceSpec.CPU = &linuxCPUSpec
	} else {
		linuxCPUSpec := task.buildImplicitLinuxCPUSpec()
		linuxResourceSpec.CPU = &linuxCPUSpec
	}

	// Validate and build task memory spec
	// NOTE: task memory specifications are optional
	if task.Memory > 0 {
		linuxMemorySpec, err := task.buildLinuxMemorySpec()
		if err != nil {
			return specs.LinuxResources{}, err
		}
		linuxResourceSpec.Memory = &linuxMemorySpec
	}

	return linuxResourceSpec, nil
}

// BuildLinuxResourceSpec returns a linuxResources object for the task cgroup


func (task *Task) buildExplicitLinuxCPUSpec() (specs.LinuxCPU, error) {
	if task.CPU > maxTaskVCPULimit {
		return specs.LinuxCPU{},
			errors.Errorf("task CPU spec builder: unsupported CPU limits, requested=%f, max-supported=%d",
				task.CPU, maxTaskVCPULimit)
	}
	taskCPUPeriod := uint64(defaultCPUPeriod / time.Microsecond)
	taskCPUQuota := int64(task.CPU * float64(taskCPUPeriod))

	// TODO: DefaultCPUPeriod only permits 10VCPUs.
	// Adaptive calculation of CPUPeriod required for further support
	// (samuelkarp) The largest available EC2 instance in terms of CPU count is a x1.32xlarge,
	// with 128 vCPUs. If we assume a fixed evaluation period of 100ms (100000us),
	// we'd need a quota of 12800000us, which is longer than the maximum of 1000000.
	// For 128 vCPUs, we'd probably need something like a 1ms (1000us - the minimum)
	// evaluation period, an 128000us quota in order to stay within the min/max limits.
	return specs.LinuxCPU{
		Quota:  &taskCPUQuota,
		Period: &taskCPUPeriod,
	}, nil
}

// buildExplicitLinuxCPUSpec builds CPU spec when task CPU limits are
// explicitly requested

buildExplicitLinuxCPUSpec builds CPU spec when task CPU limits are explicitly requested


func (task *Task) buildImplicitLinuxCPUSpec() specs.LinuxCPU {
	// If task level CPU limits are missing,
	// aggregate container CPU shares when present
	var taskCPUShares uint64
	for _, container := range task.Containers {
		if container.CPU > 0 {
			taskCPUShares += uint64(container.CPU)
		}
	}

	// If there are are no CPU limits at task or container level,
	// default task CPU shares
	if taskCPUShares == 0 {
		// Set default CPU shares
		taskCPUShares = minimumCPUShare
	}

	return specs.LinuxCPU{
		Shares: &taskCPUShares,
	}
}

// buildImplicitLinuxCPUSpec builds the implicit task CPU spec when
// task CPU and memory limit feature is enabled

buildImplicitLinuxCPUSpec builds the implicit task CPU spec when task CPU and memory limit feature is enabled


func (task *Task) buildLinuxMemorySpec() (specs.LinuxMemory, error) {
	// If task memory limit is not present, cgroup parent memory is not set
	// If task memory limit is set, ensure that no container
	// of this task has a greater request
	for _, container := range task.Containers {
		containerMemoryLimit := int64(container.Memory)
		if containerMemoryLimit > task.Memory {
			return specs.LinuxMemory{},
				errors.Errorf("task memory spec builder: container memory limit(%d) greater than task memory limit(%d)",
					containerMemoryLimit, task.Memory)
		}
	}

	// Kernel expects memory to be expressed in bytes
	memoryBytes := task.Memory * bytesPerMegabyte
	return specs.LinuxMemory{
		Limit: &memoryBytes,
	}, nil
}

// buildLinuxMemorySpec validates and builds the task memory spec


func (task *Task) platformHostConfigOverride(hostConfig *dockercontainer.HostConfig) error {
	// Override cgroup parent
	return task.overrideCgroupParent(hostConfig)
}

func
(
task
*
Task
)
platformHostConfigOverride
(
hostConfig
*
dockercontainer
.
HostConfig
)
error
{
// Override cgroup parent
return
task
.
overrideCgroupParent
(
hostConfig
)
}

// platformHostConfigOverride to override platform specific feature sets


func (task *Task) overrideCgroupParent(hostConfig *dockercontainer.HostConfig) error {
	task.lock.RLock()
	defer task.lock.RUnlock()
	if task.MemoryCPULimitsEnabled {
		cgroupRoot, err := task.BuildCgroupRoot()
		if err != nil {
			return errors.Wrapf(err, "task cgroup override: unable to obtain cgroup root for task: %s", task.Arn)
		}
		hostConfig.CgroupParent = cgroupRoot
	}
	return nil
}

func ( task * Task ) overrideCgroupParent ( hostConfig * dockercontainer . HostConfig ) error { task . lock . RLock ( ) defer task . lock . RUnlock ( ) if task . MemoryCPULimitsEnabled { cgroupRoot , err := task . BuildCgroupRoot ( ) if err != nil { return errors . Wrapf ( err , " " , task . Arn ) } hostConfig . CgroupParent = cgroupRoot } return nil }

// overrideCgroupParent updates hostconfig with cgroup parent when task cgroups
// are enabled

overrideCgroupParent updates hostconfig with cgroup parent when task cgroups are enabled


func GetMACAddress(ctx context.Context,
	timeout time.Duration,
	dev string,
	netlinkClient netlinkwrapper.NetLink) (string, error) {
	retriever := &macAddressRetriever{
		dev:           dev,
		netlinkClient: netlinkClient,
		ctx:           ctx,
		timeout:       timeout,
	}
	return retriever.retrieve()
}

func GetMACAddress ( ctx context . Context , timeout time . Duration , dev string , netlinkClient netlinkwrapper . NetLink ) ( string , error ) { retriever := & macAddressRetriever { dev : dev , netlinkClient : netlinkClient , ctx : ctx , timeout : timeout , } return retriever . retrieve ( ) }

// GetMACAddress retrieves the MAC address of a device using netlink


func (retriever *macAddressRetriever) retrieve() (string, error) {
	backoff := retry.NewExponentialBackoff(macAddressBackoffMin, macAddressBackoffMax,
		macAddressBackoffJitter, macAddressBackoffMultiple)
	ctx, cancel := context.WithTimeout(retriever.ctx, retriever.timeout)
	defer cancel()

	err := retry.RetryWithBackoffCtx(ctx, backoff, func() error {
		retErr := retriever.retrieveOnce()
		if retErr != nil {
			seelog.Warnf("Unable to retrieve mac address for device '%s': %v",
				retriever.dev, retErr)
			return retErr
		}

		if retriever.macAddress == "" {
			seelog.Debugf("Empty mac address for device '%s'", retriever.dev)
			// Return a retriable error when mac address is empty. If the error
			// is not wrapped with the RetriableError interface, RetryWithBackoffCtx
			// treats them as retriable by default
			return errors.Errorf("eni mac address: retrieved empty address for device %s",
				retriever.dev)
		}

		return nil
	})
	if err != nil {
		return "", err
	}
	// RetryWithBackoffCtx returns nil when the context is cancelled. Check if there was
	// a timeout here. TODO: Fix RetryWithBackoffCtx to return ctx.Err() on context Done()
	if err = ctx.Err(); err != nil {
		return "", errors.Wrapf(err, "eni mac address: timed out waiting for eni device '%s'",
			retriever.dev)
	}

	return retriever.macAddress, nil
}

// retrieve retrives the mac address of a network device. If the retrieved mac
// address is empty, it retries the operation with a timeout specified by the
// caller

retrieve retrives the mac address of a network device . If the retrieved mac address is empty it retries the operation with a timeout specified by the caller


func (retriever *macAddressRetriever) retrieveOnce() error {
	dev := filepath.Base(retriever.dev)
	link, err := retriever.netlinkClient.LinkByName(dev)
	if err != nil {
		return apierrors.NewRetriableError(apierrors.NewRetriable(false), err)
	}
	retriever.macAddress = link.Attrs().HardwareAddr.String()
	return nil
}

func ( retriever * macAddressRetriever ) retrieveOnce ( ) error { dev := filepath . Base ( retriever . dev ) link , err := retriever . netlinkClient . LinkByName ( dev ) if err != nil { return apierrors . NewRetriableError ( apierrors . NewRetriable ( false ) , err ) } retriever . macAddress = link . Attrs ( ) . HardwareAddr . String ( ) return nil }

// retrieveOnce retrieves the MAC address of a device using netlink.LinkByName

retrieveOnce retrieves the MAC address of a device using netlink . LinkByName


func IsValidNetworkDevice(devicePath string) bool {
	/*
	* DevicePath Samples:
	* eth1 -> /devices/pci0000:00/0000:00:05.0/net/eth1
	* eth0 -> ../../devices/pci0000:00/0000:00:03.0/net/eth0
	* lo   -> ../../devices/virtual/net/lo
	 */
	splitDevLink := strings.SplitN(devicePath, "devices/", 2)
	if len(splitDevLink) != 2 {
		seelog.Warnf("Cannot determine device validity: %s", devicePath)
		return false
	}
	/*
	* CoreOS typically employs the vif style for physical net interfaces
	* Amazon Linux, Ubuntu, RHEL, Fedora, Suse use the traditional pci convention
	 */
	if strings.HasPrefix(splitDevLink[1], pciDevicePrefix) || strings.HasPrefix(splitDevLink[1], vifDevicePrefix) {
		return true
	}
	if strings.HasPrefix(splitDevLink[1], virtualDevicePrefix) {
		return false
	}
	// NOTE: Should never reach here
	seelog.Criticalf("Failed to validate device path: %s", devicePath)
	return false
}

// IsValidNetworkDevice is used to differentiate virtual and physical devices
// Returns true only for pci or vif interfaces

IsValidNetworkDevice is used to differentiate virtual and physical devices Returns true only for pci or vif interfaces


func (r *eventLogReceiver) ReceiveMessage(message string, level seelog.LogLevel, context seelog.LogContextInterface) error {
	switch level {
	case seelog.DebugLvl, seelog.InfoLvl:
		return eventLog.Info(eventLogID, message)
	case seelog.WarnLvl:
		return eventLog.Warning(eventLogID, message)
	case seelog.ErrorLvl, seelog.CriticalLvl:
		return eventLog.Error(eventLogID, message)
	}
	return nil
}

func ( r * eventLogReceiver ) ReceiveMessage ( message string , level seelog . LogLevel , context seelog . LogContextInterface ) error { switch level { case seelog . DebugLvl , seelog . InfoLvl : return eventLog . Info ( eventLogID , message ) case seelog . WarnLvl : return eventLog . Warning ( eventLogID , message ) case seelog . ErrorLvl , seelog . CriticalLvl : return eventLog . Error ( eventLogID , message ) } return nil }

// ReceiveMessage receives a log line from seelog and emits it to the Windows event log


func (client *ecrClient) GetAuthorizationToken(registryId string) (*ecrapi.AuthorizationData, error) {
	log.Debugf("Calling GetAuthorizationToken for %q", registryId)

	output, err := client.sdkClient.GetAuthorizationToken(&ecrapi.GetAuthorizationTokenInput{
		RegistryIds: []*string{aws.String(registryId)},
	})

	if err != nil {
		return nil, err
	}

	if len(output.AuthorizationData) != 1 {
		return nil, fmt.Errorf("unexpected number of results in AuthorizationData (%d)", len(output.AuthorizationData))
	}
	return output.AuthorizationData[0], nil
}

func ( client * ecrClient ) GetAuthorizationToken ( registryId string ) ( * ecrapi . AuthorizationData , error ) { log . Debugf ( " " , registryId ) output , err := client . sdkClient . GetAuthorizationToken ( & ecrapi . GetAuthorizationTokenInput { RegistryIds : [ ] * string { aws . String ( registryId ) } , } ) if err != nil { return nil , err } if len ( output . AuthorizationData ) != 1 { return nil , fmt . Errorf ( " " , len ( output . AuthorizationData ) ) } return output . AuthorizationData [ 0 ] , nil }

// GetAuthorizationToken calls the ecr api to get the docker auth for the specified registry


func NewMockEngine(ctrl *gomock.Controller) *MockEngine {
	mock := &MockEngine{ctrl: ctrl}
	mock.recorder = &MockEngineMockRecorder{mock}
	return mock
}

func NewMockEngine ( ctrl * gomock . Controller ) * MockEngine { mock := & MockEngine { ctrl : ctrl } mock . recorder = & MockEngineMockRecorder { mock } return mock }

// NewMockEngine creates a new mock instance


func (m *MockEngine) ContainerDockerStats(arg0, arg1 string) (*types.StatsJSON, error) {
	ret := m.ctrl.Call(m, "ContainerDockerStats", arg0, arg1)
	ret0, _ := ret[0].(*types.StatsJSON)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func ( m * MockEngine ) ContainerDockerStats ( arg0 , arg1 string ) ( * types . StatsJSON , error ) { ret := m . ctrl . Call ( m , " " , arg0 , arg1 ) ret0 , _ := ret [ 0 ] . ( * types . StatsJSON ) ret1 , _ := ret [ 1 ] . ( error ) return ret0 , ret1 }

// ContainerDockerStats mocks base method


func (mr *MockEngineMockRecorder) ContainerDockerStats(arg0, arg1 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerDockerStats", reflect.TypeOf((*MockEngine)(nil).ContainerDockerStats), arg0, arg1)
}

func ( mr * MockEngineMockRecorder ) ContainerDockerStats ( arg0 , arg1 interface { } ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockEngine ) ( nil ) . ContainerDockerStats ) , arg0 , arg1 ) }

// ContainerDockerStats indicates an expected call of ContainerDockerStats


func (m *MockEngine) GetInstanceMetrics() (*ecstcs.MetricsMetadata, []*ecstcs.TaskMetric, error) {
	ret := m.ctrl.Call(m, "GetInstanceMetrics")
	ret0, _ := ret[0].(*ecstcs.MetricsMetadata)
	ret1, _ := ret[1].([]*ecstcs.TaskMetric)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

func ( m * MockEngine ) GetInstanceMetrics ( ) ( * ecstcs . MetricsMetadata , [ ] * ecstcs . TaskMetric , error ) { ret := m . ctrl . Call ( m , " " ) ret0 , _ := ret [ 0 ] . ( * ecstcs . MetricsMetadata ) ret1 , _ := ret [ 1 ] . ( [ ] * ecstcs . TaskMetric ) ret2 , _ := ret [ 2 ] . ( error ) return ret0 , ret1 , ret2 }


func (mr *MockEngineMockRecorder) GetInstanceMetrics() *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInstanceMetrics", reflect.TypeOf((*MockEngine)(nil).GetInstanceMetrics))
}

func ( mr * MockEngineMockRecorder ) GetInstanceMetrics ( ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockEngine ) ( nil ) . GetInstanceMetrics ) ) }

// GetInstanceMetrics indicates an expected call of GetInstanceMetrics


func (m *MockEngine) GetTaskHealthMetrics() (*ecstcs.HealthMetadata, []*ecstcs.TaskHealth, error) {
	ret := m.ctrl.Call(m, "GetTaskHealthMetrics")
	ret0, _ := ret[0].(*ecstcs.HealthMetadata)
	ret1, _ := ret[1].([]*ecstcs.TaskHealth)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

func ( m * MockEngine ) GetTaskHealthMetrics ( ) ( * ecstcs . HealthMetadata , [ ] * ecstcs . TaskHealth , error ) { ret := m . ctrl . Call ( m , " " ) ret0 , _ := ret [ 0 ] . ( * ecstcs . HealthMetadata ) ret1 , _ := ret [ 1 ] . ( [ ] * ecstcs . TaskHealth ) ret2 , _ := ret [ 2 ] . ( error ) return ret0 , ret1 , ret2 }

// GetTaskHealthMetrics mocks base method


func RetryWithBackoff(backoff Backoff, fn func() error) error {
	return RetryWithBackoffCtx(context.Background(), backoff, fn)
}

func RetryWithBackoff ( backoff Backoff , fn func ( ) error ) error { return RetryWithBackoffCtx ( context . Background ( ) , backoff , fn ) }

// RetryWithBackoff takes a Backoff and a function to call that returns an error
// If the error is nil then the function will no longer be called
// If the error is Retriable then that will be used to determine if it should be
// retried

RetryWithBackoff takes a Backoff and a function to call that returns an error If the error is nil then the function will no longer be called If the error is Retriable then that will be used to determine if it should be retried


func RetryWithBackoffCtx(ctx context.Context, backoff Backoff, fn func() error) error {
	var err error
	for {
		select {
		case <-ctx.Done():
			return nil
		default:
		}

		err = fn()

		retriableErr, isRetriableErr := err.(apierrors.Retriable)

		if err == nil || (isRetriableErr && !retriableErr.Retry()) {
			return err
		}

		_time.Sleep(backoff.Duration())
	}
}

func RetryWithBackoffCtx ( ctx context . Context , backoff Backoff , fn func ( ) error ) error { var err error for { select { case <- ctx . Done ( ) : return nil default : } err = fn ( ) retriableErr , isRetriableErr := err . ( apierrors . Retriable ) if err == nil || ( isRetriableErr && ! retriableErr . Retry ( ) ) { return err } _time . Sleep ( backoff . Duration ( ) ) } }

// RetryWithBackoffCtx takes a context, a Backoff, and a function to call that returns an error
// If the context is done, nil will be returned
// If the error is nil then the function will no longer be called
// If the error is Retriable then that will be used to determine if it should be
// retried

RetryWithBackoffCtx takes a context a Backoff and a function to call that returns an error If the context is done nil will be returned If the error is nil then the function will no longer be called If the error is Retriable then that will be used to determine if it should be retried


func RetryNWithBackoff(backoff Backoff, n int, fn func() error) error {
	return RetryNWithBackoffCtx(context.Background(), backoff, n, fn)
}

func RetryNWithBackoff ( backoff Backoff , n int , fn func ( ) error ) error { return RetryNWithBackoffCtx ( context . Background ( ) , backoff , n , fn ) }

// RetryNWithBackoff takes a Backoff, a maximum number of tries 'n', and a
// function that returns an error. The function is called until either it does
// not return an error or the maximum tries have been reached.
// If the error returned is Retriable, the Retriability of it will be respected.
// If the number of tries is exhausted, the last error will be returned.

RetryNWithBackoff takes a Backoff a maximum number of tries n and a function that returns an error . The function is called until either it does not return an error or the maximum tries have been reached . If the error returned is Retriable the Retriability of it will be respected . If the number of tries is exhausted the last error will be returned .


func RetryNWithBackoffCtx(ctx context.Context, backoff Backoff, n int, fn func() error) error {
	var err error
	RetryWithBackoffCtx(ctx, backoff, func() error {
		err = fn()
		n--
		if n == 0 {
			// Break out after n tries
			return nil
		}
		return err
	})
	return err
}

func
RetryNWithBackoffCtx
(
ctx
context
.
Context
,
backoff
Backoff
,
n
int
,
fn
func
(
)
error
)
error
{
var
err
error
RetryWithBackoffCtx
(
ctx
,
backoff
,
func
(
)
error
{
err
=
fn
(
)
n
if
n
==
0
{
// Break out after n tries
return
}
return
err
}
)
return
err
}

// RetryNWithBackoffCtx takes a context, a Backoff, a maximum number of tries 'n', and a function that returns an error.
// The function is called until it does not return an error, the context is done, or the maximum tries have been
// reached.
// If the error returned is Retriable, the Retriability of it will be respected.
// If the number of tries is exhausted, the last error will be returned.

RetryNWithBackoffCtx takes a context a Backoff a maximum number of tries n and a function that returns an error . The function is called until it does not return an error the context is done or the maximum tries have been reached . If the error returned is Retriable the Retriability of it will be respected . If the number of tries is exhausted the last error will be returned .


func AddJitter(duration time.Duration, jitter time.Duration) time.Duration {
	var randJitter int64
	if jitter.Nanoseconds() == 0 {
		randJitter = 0
	} else {
		randJitter = rand.Int63n(jitter.Nanoseconds())
	}
	return time.Duration(duration.Nanoseconds() + randJitter)
}

func AddJitter ( duration time . Duration , jitter time . Duration ) time . Duration { var randJitter int64 if jitter . Nanoseconds ( ) == 0 { randJitter = 0 } else { randJitter = rand . Int63n ( jitter . Nanoseconds ( ) ) } return time . Duration ( duration . Nanoseconds ( ) + randJitter ) }

// AddJitter adds an amount of jitter between 0 and the given jitter to the
// given duration

AddJitter adds an amount of jitter between 0 and the given jitter to the given duration


func NewMockIOUtil(ctrl *gomock.Controller) *MockIOUtil {
	mock := &MockIOUtil{ctrl: ctrl}
	mock.recorder = &MockIOUtilMockRecorder{mock}
	return mock
}

func NewMockIOUtil ( ctrl * gomock . Controller ) * MockIOUtil { mock := & MockIOUtil { ctrl : ctrl } mock . recorder = & MockIOUtilMockRecorder { mock } return mock }

// NewMockIOUtil creates a new mock instance


func (m *MockIOUtil) WriteFile(arg0 string, arg1 []byte, arg2 os.FileMode) error {
	ret := m.ctrl.Call(m, "WriteFile", arg0, arg1, arg2)
	ret0, _ := ret[0].(error)
	return ret0
}

func ( m * MockIOUtil ) WriteFile ( arg0 string , arg1 [ ] byte , arg2 os . FileMode ) error { ret := m . ctrl . Call ( m , " " , arg0 , arg1 , arg2 ) ret0 , _ := ret [ 0 ] . ( error ) return ret0 }


func (mr *MockIOUtilMockRecorder) WriteFile(arg0, arg1, arg2 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteFile", reflect.TypeOf((*MockIOUtil)(nil).WriteFile), arg0, arg1, arg2)
}

func ( mr * MockIOUtilMockRecorder ) WriteFile ( arg0 , arg1 , arg2 interface { } ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockIOUtil ) ( nil ) . WriteFile ) , arg0 , arg1 , arg2 ) }

// WriteFile indicates an expected call of WriteFile


func (c *ClientImpl) DescribeECSTagsForInstance(instanceID string) ([]*ecs.Tag, error) {
	describeTagsInput := ec2sdk.DescribeTagsInput{
		Filters: []*ec2sdk.Filter{
			{
				Name:   aws.String(ResourceIDFilterName),
				Values: []*string{aws.String(instanceID)},
			},
			{
				Name:   aws.String(ResourceTypeFilterName),
				Values: []*string{aws.String(ResourceTypeFilterValueInstance)},
			},
		},
		MaxResults: aws.Int64(InstanceMaxTagsNum),
	}
	res, err := c.client.DescribeTags(&describeTagsInput)

	if err != nil {
		seelog.Criticalf("Error calling DescribeTags API: %v", err)
		return nil, err
	}

	var tags []*ecs.Tag
	// Convert ec2 tags to ecs tags
	for _, ec2Tag := range res.Tags {
		// Filter out all tags "aws:" prefix
		if !strings.HasPrefix(strings.ToLower(aws.StringValue(ec2Tag.Key)), awsTagPrefix) &&
			!strings.HasPrefix(strings.ToLower(aws.StringValue(ec2Tag.Value)), awsTagPrefix) {
			tags = append(tags, &ecs.Tag{
				Key:   ec2Tag.Key,
				Value: ec2Tag.Value,
			})
		}
	}
	return tags, nil
}

func
(
c
*
ClientImpl
)
DescribeECSTagsForInstance
(
instanceID
string
)
(
[
]
*
ecs
.
Tag
,
error
)
{
describeTagsInput
:=
ec2sdk
.
DescribeTagsInput
{
Filters
:
[
]
*
ec2sdk
.
Filter
{
{
Name
:
aws
.
String
(
ResourceIDFilterName
)
,
Values
:
[
]
*
string
{
aws
.
String
(
instanceID
)
}
,
}
,
{
Name
:
aws
.
String
(
ResourceTypeFilterName
)
,
Values
:
[
]
*
string
{
aws
.
String
(
ResourceTypeFilterValueInstance
)
}
,
}
,
}
,
MaxResults
:
aws
.
Int64
(
InstanceMaxTagsNum
)
,
}
res
,
err
:=
c
.
client
.
DescribeTags
(
&
describeTagsInput
)
if
err
!=
{
seelog
.
Criticalf
(
"
"
,
err
)
return
,
err
}
var
tags
[
]
*
ecs
.
Tag
// Convert ec2 tags to ecs tags
for
_
,
ec2Tag
:=
range
res
.
Tags
{
// Filter out all tags "aws:" prefix
if
!
strings
.
HasPrefix
(
strings
.
ToLower
(
aws
.
StringValue
(
ec2Tag
.
Key
)
)
,
awsTagPrefix
)
&&
!
strings
.
HasPrefix
(
strings
.
ToLower
(
aws
.
StringValue
(
ec2Tag
.
Value
)
)
,
awsTagPrefix
)
{
tags
=
append
(
tags
,
&
ecs
.
Tag
{
Key
:
ec2Tag
.
Key
,
Value
:
ec2Tag
.
Value
,
}
)
}
}
return
tags
,
}

// DescribeECSTagsForInstance calls DescribeTags API to get the EC2 tags of the
// instance id, and return it back as ECS tags

DescribeECSTagsForInstance calls DescribeTags API to get the EC2 tags of the instance id and return it back as ECS tags


func TaskContainerStatsHandler(state dockerstate.TaskEngineState, statsEngine stats.Engine) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		taskARN, err := getTaskARNByRequest(r, state)
		if err != nil {
			errResponseJSON, _ := json.Marshal(
				fmt.Sprintf("Unable to get task arn from request: %s", err.Error()))
			utils.WriteJSONToResponse(w, http.StatusBadRequest, errResponseJSON, utils.RequestTypeTaskStats)
			return
		}
		if containerID, ok := utils.GetMuxValueFromRequest(r, statsContainerIDMuxName); ok {
			seelog.Infof("V2 task/container stats handler: writing response for container '%s'", containerID)
			WriteContainerStatsResponse(w, taskARN, containerID, statsEngine)
			return
		}

		seelog.Infof("V2 task/container stats handler: writing response for task '%s'", taskARN)
		WriteTaskStatsResponse(w, taskARN, state, statsEngine)
	}
}

func TaskContainerStatsHandler ( state dockerstate . TaskEngineState , statsEngine stats . Engine ) func ( http . ResponseWriter , * http . Request ) { return func ( w http . ResponseWriter , r * http . Request ) { taskARN , err := getTaskARNByRequest ( r , state ) if err != nil { errResponseJSON , _ := json . Marshal ( fmt . Sprintf ( " " , err . Error ( ) ) ) utils . WriteJSONToResponse ( w , http . StatusBadRequest , errResponseJSON , utils . RequestTypeTaskStats ) return } if containerID , ok := utils . GetMuxValueFromRequest ( r , statsContainerIDMuxName ) ; ok { seelog . Infof ( " " , containerID ) WriteContainerStatsResponse ( w , taskARN , containerID , statsEngine ) return } seelog . Infof ( " " , taskARN ) WriteTaskStatsResponse ( w , taskARN , state , statsEngine ) } }

// TaskContainerStatsHandler returns the handler method for handling task and container stats requests.

TaskContainerStatsHandler returns the handler method for handling task and container stats requests .


func WriteTaskStatsResponse(w http.ResponseWriter,
	taskARN string,
	state dockerstate.TaskEngineState,
	statsEngine stats.Engine) {

	taskStatsResponse, err := NewTaskStatsResponse(taskARN, state, statsEngine)
	if err != nil {
		seelog.Warnf("Unable to get task stats for task '%s': %v", taskARN, err)
		errResponseJSON, _ := json.Marshal("Unable to get task stats for: " + taskARN)
		utils.WriteJSONToResponse(w, http.StatusBadRequest, errResponseJSON, utils.RequestTypeTaskStats)
		return
	}

	responseJSON, _ := json.Marshal(taskStatsResponse)
	utils.WriteJSONToResponse(w, http.StatusOK, responseJSON, utils.RequestTypeTaskStats)
}

func WriteTaskStatsResponse ( w http . ResponseWriter , taskARN string , state dockerstate . TaskEngineState , statsEngine stats . Engine ) { taskStatsResponse , err := NewTaskStatsResponse ( taskARN , state , statsEngine ) if err != nil { seelog . Warnf ( " " , taskARN , err ) errResponseJSON , _ := json . Marshal ( " " + taskARN ) utils . WriteJSONToResponse ( w , http . StatusBadRequest , errResponseJSON , utils . RequestTypeTaskStats ) return } responseJSON , _ := json . Marshal ( taskStatsResponse ) utils . WriteJSONToResponse ( w , http . StatusOK , responseJSON , utils . RequestTypeTaskStats ) }

// WriteTaskStatsResponse writes the task stats to response writer.

WriteTaskStatsResponse writes the task stats to response writer .


func WriteContainerStatsResponse(w http.ResponseWriter,
	taskARN string,
	containerID string,
	statsEngine stats.Engine) {
	dockerStats, err := statsEngine.ContainerDockerStats(taskARN, containerID)
	if err != nil {
		errResponseJSON, _ := json.Marshal("Unable to get container stats for: " + containerID)
		utils.WriteJSONToResponse(w, http.StatusBadRequest, errResponseJSON, utils.RequestTypeContainerStats)
		return
	}

	responseJSON, _ := json.Marshal(dockerStats)
	utils.WriteJSONToResponse(w, http.StatusOK, responseJSON, utils.RequestTypeContainerStats)
}

func WriteContainerStatsResponse ( w http . ResponseWriter , taskARN string , containerID string , statsEngine stats . Engine ) { dockerStats , err := statsEngine . ContainerDockerStats ( taskARN , containerID ) if err != nil { errResponseJSON , _ := json . Marshal ( " " + containerID ) utils . WriteJSONToResponse ( w , http . StatusBadRequest , errResponseJSON , utils . RequestTypeContainerStats ) return } responseJSON , _ := json . Marshal ( dockerStats ) utils . WriteJSONToResponse ( w , http . StatusOK , responseJSON , utils . RequestTypeContainerStats ) }

// WriteContainerStatsResponse writes the container stats to response writer.

WriteContainerStatsResponse writes the container stats to response writer .


func NewTaskResponse(task *apitask.Task, containerMap map[string]*apicontainer.DockerContainer) *TaskResponse {
	containers := []ContainerResponse{}
	for _, container := range containerMap {
		if container.Container.IsInternal() {
			continue
		}
		containerResponse := NewContainerResponse(container, task.GetTaskENI())
		containers = append(containers, containerResponse)
	}

	knownStatus := task.GetKnownStatus()
	knownBackendStatus := knownStatus.BackendStatus()
	desiredStatusInAgent := task.GetDesiredStatus()
	desiredStatus := desiredStatusInAgent.BackendStatus()

	if (knownBackendStatus == "STOPPED" && desiredStatus != "STOPPED") || (knownBackendStatus == "RUNNING" && desiredStatus == "PENDING") {
		desiredStatus = ""
	}

	return &TaskResponse{
		Arn:           task.Arn,
		DesiredStatus: desiredStatus,
		KnownStatus:   knownBackendStatus,
		Family:        task.Family,
		Version:       task.Version,
		Containers:    containers,
	}
}

func NewTaskResponse ( task * apitask . Task , containerMap map [ string ] * apicontainer . DockerContainer ) * TaskResponse { containers := [ ] ContainerResponse { } for _ , container := range containerMap { if container . Container . IsInternal ( ) { continue } containerResponse := NewContainerResponse ( container , task . GetTaskENI ( ) ) containers = append ( containers , containerResponse ) } knownStatus := task . GetKnownStatus ( ) knownBackendStatus := knownStatus . BackendStatus ( ) desiredStatusInAgent := task . GetDesiredStatus ( ) desiredStatus := desiredStatusInAgent . BackendStatus ( ) if ( knownBackendStatus == " " && desiredStatus != " " ) || ( knownBackendStatus == " " && desiredStatus == " " ) { desiredStatus = " " } return & TaskResponse { Arn : task . Arn , DesiredStatus : desiredStatus , KnownStatus : knownBackendStatus , Family : task . Family , Version : task . Version , Containers : containers , } }

// NewTaskResponse creates a TaskResponse for a task.

NewTaskResponse creates a TaskResponse for a task .


func NewContainerResponse(dockerContainer *apicontainer.DockerContainer, eni *apieni.ENI) ContainerResponse {
	container := dockerContainer.Container
	resp := ContainerResponse{
		Name:       container.Name,
		DockerID:   dockerContainer.DockerID,
		DockerName: dockerContainer.DockerName,
	}

	resp.Ports = NewPortBindingsResponse(dockerContainer, eni)
	resp.Volumes = NewVolumesResponse(dockerContainer)

	if eni != nil {
		resp.Networks = []containermetadata.Network{
			{
				NetworkMode:   utils.NetworkModeAWSVPC,
				IPv4Addresses: eni.GetIPV4Addresses(),
				IPv6Addresses: eni.GetIPV6Addresses(),
			},
		}
	}
	return resp
}

func NewContainerResponse ( dockerContainer * apicontainer . DockerContainer , eni * apieni . ENI ) ContainerResponse { container := dockerContainer . Container resp := ContainerResponse { Name : container . Name , DockerID : dockerContainer . DockerID , DockerName : dockerContainer . DockerName , } resp . Ports = NewPortBindingsResponse ( dockerContainer , eni ) resp . Volumes = NewVolumesResponse ( dockerContainer ) if eni != nil { resp . Networks = [ ] containermetadata . Network { { NetworkMode : utils . NetworkModeAWSVPC , IPv4Addresses : eni . GetIPV4Addresses ( ) , IPv6Addresses : eni . GetIPV6Addresses ( ) , } , } } return resp }

// NewContainerResponse creates ContainerResponse for a container.

NewContainerResponse creates ContainerResponse for a container .


func NewPortBindingsResponse(dockerContainer *apicontainer.DockerContainer, eni *apieni.ENI) []PortResponse {
	container := dockerContainer.Container
	resp := []PortResponse{}

	bindings := container.GetKnownPortBindings()

	// if KnownPortBindings list is empty, then we use the port mapping
	// information that was passed down from ACS.
	if len(bindings) == 0 {
		bindings = container.Ports
	}

	for _, binding := range bindings {
		port := PortResponse{
			ContainerPort: binding.ContainerPort,
			Protocol:      binding.Protocol.String(),
		}

		if eni == nil {
			port.HostPort = binding.HostPort
		} else {
			port.HostPort = port.ContainerPort
		}

		resp = append(resp, port)
	}
	return resp
}

// NewPortBindingsResponse creates PortResponse for a container.

NewPortBindingsResponse creates PortResponse for a container .


func NewVolumesResponse(dockerContainer *apicontainer.DockerContainer) []VolumeResponse {
	container := dockerContainer.Container
	var resp []VolumeResponse

	volumes := container.GetVolumes()

	for _, volume := range volumes {
		volResp := VolumeResponse{
			DockerName:  volume.Name,
			Source:      volume.Source,
			Destination: volume.Destination,
		}

		resp = append(resp, volResp)
	}
	return resp
}

func NewVolumesResponse ( dockerContainer * apicontainer . DockerContainer ) [ ] VolumeResponse { container := dockerContainer . Container var resp [ ] VolumeResponse volumes := container . GetVolumes ( ) for _ , volume := range volumes { volResp := VolumeResponse { DockerName : volume . Name , Source : volume . Source , Destination : volume . Destination , } resp = append ( resp , volResp ) } return resp }

// NewVolumesResponse creates VolumeResponse for a container


func NewTasksResponse(state dockerstate.TaskEngineState) *TasksResponse {
	allTasks := state.AllTasks()
	taskResponses := make([]*TaskResponse, len(allTasks))
	for ndx, task := range allTasks {
		containerMap, _ := state.ContainerMapByArn(task.Arn)
		taskResponses[ndx] = NewTaskResponse(task, containerMap)
	}

	return &TasksResponse{Tasks: taskResponses}
}

func NewTasksResponse ( state dockerstate . TaskEngineState ) * TasksResponse { allTasks := state . AllTasks ( ) taskResponses := make ( [ ] * TaskResponse , len ( allTasks ) ) for ndx , task := range allTasks { containerMap , _ := state . ContainerMapByArn ( task . Arn ) taskResponses [ ndx ] = NewTaskResponse ( task , containerMap ) } return & TasksResponse { Tasks : taskResponses } }

// NewTasksResponse creates TasksResponse for all the tasks.

NewTasksResponse creates TasksResponse for all the tasks .


func NewPublishMetricsRequest(metadata *MetricsMetadata, taskMetrics []*TaskMetric) *PublishMetricsRequest {
	return &PublishMetricsRequest{
		Metadata:    metadata,
		TaskMetrics: taskMetrics,
		Timestamp:   aws.Time(time.Now()),
	}
}

func NewPublishMetricsRequest ( metadata * MetricsMetadata , taskMetrics [ ] * TaskMetric ) * PublishMetricsRequest { return & PublishMetricsRequest { Metadata : metadata , TaskMetrics : taskMetrics , Timestamp : aws . Time ( time . Now ( ) ) , } }

// NewPublishMetricsRequest creates a PublishMetricsRequest object.

NewPublishMetricsRequest creates a PublishMetricsRequest object .


func NewPublishHealthMetricsRequest(metadata *HealthMetadata, healthMetrics []*TaskHealth) *PublishHealthRequest {
	return &PublishHealthRequest{
		Metadata:  metadata,
		Tasks:     healthMetrics,
		Timestamp: aws.Time(time.Now()),
	}
}

func NewPublishHealthMetricsRequest ( metadata * HealthMetadata , healthMetrics [ ] * TaskHealth ) * PublishHealthRequest { return & PublishHealthRequest { Metadata : metadata , Tasks : healthMetrics , Timestamp : aws . Time ( time . Now ( ) ) , } }

// NewPublishHealthMetricsRequest creates a PublishHealthRequest


func (buffer *InfiniteBuffer) StartListening(ctx context.Context, eventChan <-chan events.Message) {
	for {
		select {
		// If context is cancelled, drain remaining events and return
		case <-ctx.Done():
			for len(eventChan) > 0 {
				event := <-eventChan
				go buffer.CopyEvents(&event)
			}
			return
		case event := <-eventChan:
			go buffer.CopyEvents(&event)
		}
	}
}

// StartListening starts reading from the input channel and writes to the buffer
// When context is cancelled, stop listening

StartListening starts reading from the input channel and writes to the buffer When context is cancelled stop listening


func (buffer *InfiniteBuffer) CopyEvents(event *events.Message) {
	if event.ID == "" || event.Type != containerTypeEvent {
		return
	}

	// Only add the events agent is interested
	for _, containerEvent := range containerEvents {
		if event.Status == containerEvent {
			buffer.lock.Lock()
			defer buffer.lock.Unlock()

			buffer.events = append(buffer.events, event)
			// Check if there is consumer waiting for events
			if buffer.empty {
				buffer.empty = false

				// Unblock the consumer
				buffer.waitForEvent.Done()
			}
			return
		}
	}
}

// CopyEvents copies the event into the buffer


func (buffer *InfiniteBuffer) Consume(in chan<- *events.Message) {
	for {
		buffer.lock.Lock()

		if len(buffer.events) == 0 {
			// Mark the buffer as empty and start waiting for events
			buffer.empty = true
			buffer.waitForEvent.Add(1)
			buffer.lock.Unlock()
			buffer.waitForEvent.Wait()
		} else {
			event := buffer.events[0]
			buffer.events = buffer.events[1:]
			buffer.lock.Unlock()

			// Send event to the buffer listener
			in <- event
		}
	}
}

// Consume reads the buffer and write to a listener channel


func ContainerStatsHandler(state dockerstate.TaskEngineState, statsEngine stats.Engine) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		taskARN, err := getTaskARNByRequest(r, state)
		if err != nil {
			errResponseJSON, _ := json.Marshal(
				fmt.Sprintf("V3 container stats handler: unable to get task arn from request: %s", err.Error()))
			utils.WriteJSONToResponse(w, http.StatusBadRequest, errResponseJSON, utils.RequestTypeTaskStats)
			return
		}

		containerID, err := getContainerIDByRequest(r, state)
		if err != nil {
			responseJSON, _ := json.Marshal(
				fmt.Sprintf("V3 container stats handler: unable to get container ID from request: %s", err.Error()))
			utils.WriteJSONToResponse(w, http.StatusBadRequest, responseJSON, utils.RequestTypeContainerStats)
			return
		}

		seelog.Infof("V3 container stats handler: writing response for container '%s'", containerID)

		// v3 handler shares the same container stats response format with v2 handler.
		v2.WriteContainerStatsResponse(w, taskARN, containerID, statsEngine)
	}
}

// ContainerStatsHandler returns the handler method for handling container stats requests.

ContainerStatsHandler returns the handler method for handling container stats requests .


func NewMetricsClient(api APIType, registry *prometheus.Registry) MetricsClient {
	switch api {
	case DockerAPI:
		return NewGenericMetricsClient(DockerSubsystem, registry)
	case TaskEngine:
		return NewGenericMetricsClient(TaskEngineSubsystem, registry)
	case StateManager:
		return NewGenericMetricsClient(StateManagerSubsystem, registry)
	case ECSClient:
		return NewGenericMetricsClient(ECSClientSubsystem, registry)
	default:
		seelog.Error("Unmanaged MetricsClient cannot be created.")
		return nil
	}
}

func NewMetricsClient ( api APIType , registry * prometheus . Registry ) MetricsClient { switch api { case DockerAPI : return NewGenericMetricsClient ( DockerSubsystem , registry ) case TaskEngine : return NewGenericMetricsClient ( TaskEngineSubsystem , registry ) case StateManager : return NewGenericMetricsClient ( StateManagerSubsystem , registry ) case ECSClient : return NewGenericMetricsClient ( ECSClientSubsystem , registry ) default : seelog . Error ( " " ) return nil } }

// A factory method that enables various MetricsClients to be created.

A factory method that enables various MetricsClients to be created .


func NewMockECRSDK(ctrl *gomock.Controller) *MockECRSDK {
	mock := &MockECRSDK{ctrl: ctrl}
	mock.recorder = &MockECRSDKMockRecorder{mock}
	return mock
}

func NewMockECRSDK ( ctrl * gomock . Controller ) * MockECRSDK { mock := & MockECRSDK { ctrl : ctrl } mock . recorder = & MockECRSDKMockRecorder { mock } return mock }

// NewMockECRSDK creates a new mock instance


func NewMockECRFactory(ctrl *gomock.Controller) *MockECRFactory {
	mock := &MockECRFactory{ctrl: ctrl}
	mock.recorder = &MockECRFactoryMockRecorder{mock}
	return mock
}

func NewMockECRFactory ( ctrl * gomock . Controller ) * MockECRFactory { mock := & MockECRFactory { ctrl : ctrl } mock . recorder = & MockECRFactoryMockRecorder { mock } return mock }

// NewMockECRFactory creates a new mock instance


func (mr *MockECRFactoryMockRecorder) GetClient(arg0 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClient", reflect.TypeOf((*MockECRFactory)(nil).GetClient), arg0)
}

func ( mr * MockECRFactoryMockRecorder ) GetClient ( arg0 interface { } ) * gomock . Call { return mr . mock . ctrl . RecordCallWithMethodType ( mr . mock , " " , reflect . TypeOf ( ( * MockECRFactory ) ( nil ) . GetClient ) , arg0 ) }

// GetClient indicates an expected call of GetClient


func NewMockECRClient(ctrl *gomock.Controller) *MockECRClient {
	mock := &MockECRClient{ctrl: ctrl}
	mock.recorder = &MockECRClientMockRecorder{mock}
	return mock
}

func NewMockECRClient ( ctrl * gomock . Controller ) * MockECRClient { mock := & MockECRClient { ctrl : ctrl } mock . recorder = & MockECRClientMockRecorder { mock } return mock }

// NewMockECRClient creates a new mock instance