Merge pull request #46484 from vchiranjeeviak/vchiranjeeviak/container-list-code-refactor
daemon: containers list code refactor
This commit is contained in:
commit
7f6bd671fe
1 changed files with 55 additions and 79 deletions
134
daemon/list.go
134
daemon/list.go
|
@ -39,22 +39,15 @@ var acceptedPsFilterTags = map[string]bool{
|
|||
// iterationAction represents possible outcomes happening during the container iteration.
|
||||
type iterationAction int
|
||||
|
||||
// containerReducer represents a reducer for a container.
|
||||
// Returns the object to serialize by the api.
|
||||
type containerReducer func(context.Context, *container.Snapshot) (*types.Container, error)
|
||||
|
||||
const (
|
||||
// includeContainer is the action to include a container in the reducer.
|
||||
// includeContainer is the action to include a container.
|
||||
includeContainer iterationAction = iota
|
||||
// excludeContainer is the action to exclude a container in the reducer.
|
||||
// excludeContainer is the action to exclude a container.
|
||||
excludeContainer
|
||||
// stopIteration is the action to stop iterating over the list of containers.
|
||||
stopIteration
|
||||
)
|
||||
|
||||
// errStopIteration makes the iterator to stop without returning an error.
|
||||
var errStopIteration = errors.New("container list iteration stopped")
|
||||
|
||||
// List returns an array of all containers registered in the daemon.
|
||||
func (daemon *Daemon) List() []*container.Container {
|
||||
return daemon.containers.List()
|
||||
|
@ -106,7 +99,59 @@ func (r byCreatedDescending) Less(i, j int) bool {
|
|||
|
||||
// Containers returns the list of containers to show given the user's filtering.
|
||||
func (daemon *Daemon) Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error) {
|
||||
return daemon.reduceContainers(ctx, config, daemon.refreshImage)
|
||||
if err := config.Filters.Validate(acceptedPsFilterTags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
view = daemon.containersReplica.Snapshot()
|
||||
containers = []*types.Container{}
|
||||
)
|
||||
|
||||
filter, err := daemon.foldFilter(ctx, view, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// fastpath to only look at a subset of containers if specific name
|
||||
// or ID matches were provided by the user--otherwise we potentially
|
||||
// end up querying many more containers than intended
|
||||
containerList, err := daemon.filterByNameIDMatches(view, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range containerList {
|
||||
currentContainer := &containerList[i]
|
||||
switch includeContainerInList(currentContainer, filter) {
|
||||
case excludeContainer:
|
||||
continue
|
||||
case stopIteration:
|
||||
return containers, nil
|
||||
}
|
||||
|
||||
// transform internal container struct into api structs
|
||||
newC, err := daemon.refreshImage(ctx, currentContainer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// release lock because size calculation is slow
|
||||
if filter.Size {
|
||||
sizeRw, sizeRootFs, err := daemon.imageService.GetContainerLayerSize(ctx, newC.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newC.SizeRw = sizeRw
|
||||
newC.SizeRootFs = sizeRootFs
|
||||
}
|
||||
if newC != nil {
|
||||
containers = append(containers, newC)
|
||||
filter.idx++
|
||||
}
|
||||
}
|
||||
|
||||
return containers, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listContext) ([]container.Snapshot, error) {
|
||||
|
@ -178,75 +223,6 @@ func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listCo
|
|||
return cntrs, nil
|
||||
}
|
||||
|
||||
// reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer.
|
||||
func (daemon *Daemon) reduceContainers(ctx context.Context, config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
|
||||
if err := config.Filters.Validate(acceptedPsFilterTags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
view = daemon.containersReplica.Snapshot()
|
||||
containers = []*types.Container{}
|
||||
)
|
||||
|
||||
filter, err := daemon.foldFilter(ctx, view, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// fastpath to only look at a subset of containers if specific name
|
||||
// or ID matches were provided by the user--otherwise we potentially
|
||||
// end up querying many more containers than intended
|
||||
containerList, err := daemon.filterByNameIDMatches(view, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range containerList {
|
||||
t, err := daemon.reducePsContainer(ctx, &containerList[i], filter, reducer)
|
||||
if err != nil {
|
||||
if err != errStopIteration {
|
||||
return nil, err
|
||||
}
|
||||
break
|
||||
}
|
||||
if t != nil {
|
||||
containers = append(containers, t)
|
||||
filter.idx++
|
||||
}
|
||||
}
|
||||
|
||||
return containers, nil
|
||||
}
|
||||
|
||||
// reducePsContainer is the basic representation for a container as expected by the ps command.
|
||||
func (daemon *Daemon) reducePsContainer(ctx context.Context, container *container.Snapshot, filter *listContext, reducer containerReducer) (*types.Container, error) {
|
||||
// filter containers to return
|
||||
switch includeContainerInList(container, filter) {
|
||||
case excludeContainer:
|
||||
return nil, nil
|
||||
case stopIteration:
|
||||
return nil, errStopIteration
|
||||
}
|
||||
|
||||
// transform internal container struct into api structs
|
||||
newC, err := reducer(ctx, container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// release lock because size calculation is slow
|
||||
if filter.Size {
|
||||
sizeRw, sizeRootFs, err := daemon.imageService.GetContainerLayerSize(ctx, newC.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newC.SizeRw = sizeRw
|
||||
newC.SizeRootFs = sizeRootFs
|
||||
}
|
||||
return newC, nil
|
||||
}
|
||||
|
||||
// foldFilter generates the container filter based on the user's filtering options.
|
||||
func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, config *types.ContainerListOptions) (*listContext, error) {
|
||||
psFilters := config.Filters
|
||||
|
|
Loading…
Reference in a new issue