agent/engine/dependencygraph/graph.go
func DependenciesAreResolved(target *apicontainer.Container,
	by []*apicontainer.Container,
	id string,
	manager credentials.Manager,
	resources []taskresource.TaskResource) (*apicontainer.DependsOn, error) {
	if !executionCredentialsResolved(target, id, manager) {
		return nil, CredentialsNotResolvedErr
	}

	nameMap := make(map[string]*apicontainer.Container)
	for _, cont := range by {
		nameMap[cont.Name] = cont
	}
	neededVolumeContainers := make([]string, len(target.VolumesFrom))
	for i, volume := range target.VolumesFrom {
		neededVolumeContainers[i] = volume.SourceContainer
	}

	resourcesMap := make(map[string]taskresource.TaskResource)
	for _, resource := range resources {
		resourcesMap[resource.GetName()] = resource
	}

	if blocked, err := verifyContainerOrderingStatusResolvable(target, nameMap, containerOrderingDependenciesIsResolved); err != nil {
		return blocked, err
	}

	if !verifyStatusResolvable(target, nameMap, target.SteadyStateDependencies, onSteadyStateIsResolved) {
		return nil, DependentContainerNotResolvedErr
	}
	if err := verifyTransitionDependenciesResolved(target, nameMap, resourcesMap); err != nil {
		return nil, err
	}

	// If the target is desired terminal and isn't stopped, we should validate that it doesn't have any containers
	// that are dependent on it that need to shut down first.
	if target.DesiredTerminal() && !target.KnownTerminal() {
		if err := verifyShutdownOrder(target, nameMap); err != nil {
			return nil, err
		}
	}

	return nil, nil
}
func DependenciesAreResolved(target *apicontainer.Container,
	by []*apicontainer.Container,
	id string,
	manager credentials.Manager,
	resources []taskresource.TaskResource) (*apicontainer.DependsOn, error) {
	if !executionCredentialsResolved(target, id, manager) {
		return nil, CredentialsNotResolvedErr
	}

	nameMap := make(map[string]*apicontainer.Container)
	for _, cont := range by {
		nameMap[cont.Name] = cont
	}
	neededVolumeContainers := make([]string, len(target.VolumesFrom))
	for i, volume := range target.VolumesFrom {
		neededVolumeContainers[i] = volume.SourceContainer
	}

	resourcesMap := make(map[string]taskresource.TaskResource)
	for _, resource := range resources {
		resourcesMap[resource.GetName()] = resource
	}

	if blocked, err := verifyContainerOrderingStatusResolvable(target, nameMap, containerOrderingDependenciesIsResolved); err != nil {
		return blocked, err
	}

	if !verifyStatusResolvable(target, nameMap, target.SteadyStateDependencies, onSteadyStateIsResolved) {
		return nil, DependentContainerNotResolvedErr
	}
	if err := verifyTransitionDependenciesResolved(target, nameMap, resourcesMap); err != nil {
		return nil, err
	}

	// If the target is desired terminal and isn't stopped, we should validate that it doesn't have any containers
	// that are dependent on it that need to shut down first.
	if target.DesiredTerminal() && !target.KnownTerminal() {
		if err := verifyShutdownOrder(target, nameMap); err != nil {
			return nil, err
		}
	}

	return nil, nil
}
func DependenciesAreResolved ( target * apicontainer . Container , by [ ] * apicontainer . Container , id string , manager credentials . Manager , resources [ ] taskresource . TaskResource ) ( * apicontainer . DependsOn , error ) { if ! executionCredentialsResolved ( target , id , manager ) { return nil , CredentialsNotResolvedErr } nameMap := make ( map [ string ] * apicontainer . Container ) for _ , cont := range by { nameMap [ cont . Name ] = cont } neededVolumeContainers := make ( [ ] string , len ( target . VolumesFrom ) ) for i , volume := range target . VolumesFrom { neededVolumeContainers [ i ] = volume . SourceContainer } resourcesMap := make ( map [ string ] taskresource . TaskResource ) for _ , resource := range resources { resourcesMap [ resource . GetName ( ) ] = resource } if blocked , err := verifyContainerOrderingStatusResolvable ( target , nameMap , containerOrderingDependenciesIsResolved ) ; err != nil { return blocked , err } if ! verifyStatusResolvable ( target , nameMap , target . SteadyStateDependencies , onSteadyStateIsResolved ) { return nil , DependentContainerNotResolvedErr } if err := verifyTransitionDependenciesResolved ( target , nameMap , resourcesMap ) ; err != nil { return nil , err } // If the target is desired terminal and isn't stopped, we should validate that it doesn't have any containers // that are dependent on it that need to shut down first. if target . DesiredTerminal ( ) && ! target . KnownTerminal ( ) { if err := verifyShutdownOrder ( target , nameMap ) ; err != nil { return nil , err } } return nil , nil }
// DependenciesAreResolved validates that the `target` container can be
// transitioned given the current known state of the containers in `by`. If
// this function returns true, `target` should be technically able to launch
// without issues.
// Transitions are between known statuses (whether the container can move to
// the next known status), not desired statuses; the desired status typically
// is either RUNNING or STOPPED.
DependenciesAreResolved validates that the target container can be transitioned given the current known state of the containers in by . If this function returns true target should be technically able to launch without issues . Transitions are between known statuses ( whether the container can move to the next known status ) not desired statuses ; the desired status typically is either RUNNING or STOPPED .