func()

in agent/engine/daemonmanager/daemon_manager.go [67:179]


func (dm *daemonManager) CreateDaemonTask() (*apitask.Task, error) {
	imageName := dm.managedDaemon.GetImageName()
	// create daemon-specific host mounts
	if err := dm.initDaemonDirectoryMounts(imageName); err != nil {
		logger.Error("initDaemonDirectory failure",
			logger.Fields{
				field.Error: err,
			})
		return nil, err
	}

	loadedImageRef := dm.managedDaemon.GetLoadedDaemonImageRef()
	containerRunning := apicontainerstatus.ContainerRunning
	stringCaps := []string{}
	if dm.managedDaemon.GetLinuxParameters() != nil {
		caps := dm.managedDaemon.GetLinuxParameters().Capabilities.Add
		for _, cap := range caps {
			stringCaps = append(stringCaps, *cap)
		}
	}
	dockerHostConfig := dockercontainer.HostConfig{
		Mounts:      []dockermount.Mount{},
		NetworkMode: apitask.HostNetworkMode,
		// the default value of 0 for MaximumRetryCount means retry indefinitely
		RestartPolicy: dockercontainer.RestartPolicy{
			Name:              "on-failure",
			MaximumRetryCount: 0,
		},
		Privileged: dm.managedDaemon.GetPrivileged(),
		CapAdd:     stringCaps,
	}
	if !dm.managedDaemon.IsValidManagedDaemon() {
		return nil, fmt.Errorf("%s is an invalid managed daemon", imageName)
	}

	for _, mp := range dm.managedDaemon.GetMountPoints() {
		if err := mkdirAllAndChown(mp.SourceVolumeHostPath, daemonMountPermission, daemonUID, os.Getegid()); err != nil {
			return nil, err
		}
		var bindOptions = dockermount.BindOptions{}

		if mp.PropagationShared {
			// https://github.com/moby/moby/blob/master/api/types/mount/mount.go#L52
			bindOptions = dockermount.BindOptions{Propagation: dockermount.PropagationShared}
		}
		logger.Info(fmt.Sprintf("bindMount Propagation: %s", bindOptions.Propagation),
			logger.Fields{
				field.Image: loadedImageRef,
			})
		typeBind := dockermount.TypeBind
		mountPoint := dockermount.Mount{}
		if mp.SourceVolumeType == "npipe" {
			typeBind = dockermount.TypeNamedPipe
			mountPoint = dockermount.Mount{
				Type:   typeBind,
				Source: mp.SourceVolumeHostPath,
				Target: mp.ContainerPath,
			}
		} else {
			mountPoint = dockermount.Mount{
				Type:        typeBind,
				Source:      mp.SourceVolumeHostPath,
				Target:      mp.ContainerPath,
				BindOptions: &bindOptions,
			}
		}
		dockerHostConfig.Mounts = append(dockerHostConfig.Mounts, mountPoint)
	}
	rawHostConfig, err := json.Marshal(&dockerHostConfig)
	if err != nil {
		return nil, err
	}
	healthConfig := dm.managedDaemon.GetDockerHealthConfig()
	var rawConfig = ""
	rawHealthConfig, err := json.Marshal(&healthConfig)
	if err != nil {
		return nil, err
	}
	// The raw host config needs to be created this way - if we marshal the entire config object
	// directly, and the object only contains healthcheck, all other fields will be written as empty/nil
	// in the result string. This will override the configurations that comes with the container image
	// (CMD for example)
	// TODO update User in raw config to use either runAs user or runAsRoot from managed daemon config
	rawConfig = fmt.Sprintf(rawContainerConfigurationTemplate, string(rawHealthConfig))
	daemonTask := &apitask.Task{
		Arn:                 fmt.Sprintf("arn:::::/%s-%s", dm.managedDaemon.GetImageName(), uuid.NewUUID()),
		DesiredStatusUnsafe: apitaskstatus.TaskRunning,
		Containers: []*apicontainer.Container{{
			// name must be unique among running containers
			// We should only have a single managed daemon of each type per instance
			Name:                      fmt.Sprintf("ecs-managed-%s", dm.managedDaemon.GetImageName()),
			Image:                     loadedImageRef,
			ContainerArn:              fmt.Sprintf("arn:::::/instance-%s", imageName),
			Type:                      apicontainer.ContainerManagedDaemon,
			Command:                   dm.managedDaemon.GetCommand(),
			TransitionDependenciesMap: make(map[apicontainerstatus.ContainerStatus]apicontainer.TransitionDependencySet),
			Essential:                 true,
			SteadyStateStatusUnsafe:   &containerRunning,
			DockerConfig: apicontainer.DockerConfig{
				Config:     aws.String(rawConfig),
				HostConfig: aws.String(string(rawHostConfig)),
			},
			HealthCheckType: "DOCKER",
		}},
		LaunchType:         "EC2",
		NetworkMode:        apitask.HostNetworkMode,
		ResourcesMapUnsafe: make(map[string][]taskresource.TaskResource),
		IsInternal:         true,
	}
	// add managed daemon environment to daemon task container
	daemonTask.Containers[0].MergeEnvironmentVariables(dm.managedDaemon.GetEnvironment())
	return daemonTask, nil
}