agent/dockerclient/dockerapi/docker_client.go
func MetadataFromContainer(dockerContainer *types.ContainerJSON) DockerContainerMetadata {
	var bindings []apicontainer.PortBinding
	var err apierrors.NamedError
	if dockerContainer.NetworkSettings != nil {
		// Convert port bindings into the format our container expects
		bindings, err = apicontainer.PortBindingFromDockerPortBinding(dockerContainer.NetworkSettings.Ports)
		if err != nil {
			seelog.Criticalf("DockerGoClient: Docker had network bindings we couldn't understand: %v", err)
			return DockerContainerMetadata{Error: apierrors.NamedError(err)}
		}
	}

	createdTime, _ := time.Parse(time.RFC3339, dockerContainer.Created)
	startedTime := time.Time{}
	finishedTime := time.Time{}
	// Need to check for nil to make sure we do not try to access fields of nil pointer
	if dockerContainer.State != nil {
		startedTime, _ = time.Parse(time.RFC3339, dockerContainer.State.StartedAt)
		finishedTime, _ = time.Parse(time.RFC3339, dockerContainer.State.FinishedAt)
	}

	metadata := DockerContainerMetadata{
		DockerID:     dockerContainer.ID,
		PortBindings: bindings,
		Volumes:      dockerContainer.Mounts,
		CreatedAt:    createdTime,
		StartedAt:    startedTime,
		FinishedAt:   finishedTime,
	}

	if dockerContainer.NetworkSettings != nil {
		metadata.NetworkSettings = dockerContainer.NetworkSettings
	}

	if dockerContainer.HostConfig != nil {
		metadata.NetworkMode = string(dockerContainer.HostConfig.NetworkMode)
	}

	if dockerContainer.Config != nil {
		metadata.Labels = dockerContainer.Config.Labels
	}

	if dockerContainer.State == nil {
		return metadata
	}
	if !dockerContainer.State.Running && !finishedTime.IsZero() {
		// Only record an exitcode if it has exited
		metadata.ExitCode = &dockerContainer.State.ExitCode
	}
	if dockerContainer.State.Error != "" {
		metadata.Error = NewDockerStateError(dockerContainer.State.Error)
	}
	if dockerContainer.State.OOMKilled {
		metadata.Error = OutOfMemoryError{}
	}
	// Health field in Docker SDK is a pointer, need to check before not nil before dereference.
	if dockerContainer.State.Health == nil || dockerContainer.State.Health.Status == "" || dockerContainer.State.Health.Status == healthCheckStarting {
		return metadata
	}
	// Record the health check information if exists
	metadata.Health = getMetadataHealthCheck(dockerContainer)
	return metadata
}
func MetadataFromContainer(dockerContainer *types.ContainerJSON) DockerContainerMetadata {
	var bindings []apicontainer.PortBinding
	var err apierrors.NamedError
	if dockerContainer.NetworkSettings != nil {
		// Convert port bindings into the format our container expects
		bindings, err = apicontainer.PortBindingFromDockerPortBinding(dockerContainer.NetworkSettings.Ports)
		if err != nil {
			seelog.Criticalf("DockerGoClient: Docker had network bindings we couldn't understand: %v", err)
			return DockerContainerMetadata{Error: apierrors.NamedError(err)}
		}
	}

	createdTime, _ := time.Parse(time.RFC3339, dockerContainer.Created)
	startedTime := time.Time{}
	finishedTime := time.Time{}
	// Need to check for nil to make sure we do not try to access fields of nil pointer
	if dockerContainer.State != nil {
		startedTime, _ = time.Parse(time.RFC3339, dockerContainer.State.StartedAt)
		finishedTime, _ = time.Parse(time.RFC3339, dockerContainer.State.FinishedAt)
	}

	metadata := DockerContainerMetadata{
		DockerID:     dockerContainer.ID,
		PortBindings: bindings,
		Volumes:      dockerContainer.Mounts,
		CreatedAt:    createdTime,
		StartedAt:    startedTime,
		FinishedAt:   finishedTime,
	}

	if dockerContainer.NetworkSettings != nil {
		metadata.NetworkSettings = dockerContainer.NetworkSettings
	}

	if dockerContainer.HostConfig != nil {
		metadata.NetworkMode = string(dockerContainer.HostConfig.NetworkMode)
	}

	if dockerContainer.Config != nil {
		metadata.Labels = dockerContainer.Config.Labels
	}

	if dockerContainer.State == nil {
		return metadata
	}
	if !dockerContainer.State.Running && !finishedTime.IsZero() {
		// Only record an exitcode if it has exited
		metadata.ExitCode = &dockerContainer.State.ExitCode
	}
	if dockerContainer.State.Error != "" {
		metadata.Error = NewDockerStateError(dockerContainer.State.Error)
	}
	if dockerContainer.State.OOMKilled {
		metadata.Error = OutOfMemoryError{}
	}
	// Health field in Docker SDK is a pointer, need to check before not nil before dereference.
	if dockerContainer.State.Health == nil || dockerContainer.State.Health.Status == "" || dockerContainer.State.Health.Status == healthCheckStarting {
		return metadata
	}
	// Record the health check information if exists
	metadata.Health = getMetadataHealthCheck(dockerContainer)
	return metadata
}
// MetadataFromContainer translates dockerContainer into DockerContainerMetadata