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.
|
// iterationAction represents possible outcomes happening during the container iteration.
|
||||||
type iterationAction int
|
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 (
|
const (
|
||||||
// includeContainer is the action to include a container in the reducer.
|
// includeContainer is the action to include a container.
|
||||||
includeContainer iterationAction = iota
|
includeContainer iterationAction = iota
|
||||||
// excludeContainer is the action to exclude a container in the reducer.
|
// excludeContainer is the action to exclude a container.
|
||||||
excludeContainer
|
excludeContainer
|
||||||
// stopIteration is the action to stop iterating over the list of containers.
|
// stopIteration is the action to stop iterating over the list of containers.
|
||||||
stopIteration
|
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.
|
// List returns an array of all containers registered in the daemon.
|
||||||
func (daemon *Daemon) List() []*container.Container {
|
func (daemon *Daemon) List() []*container.Container {
|
||||||
return daemon.containers.List()
|
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.
|
// 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) {
|
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) {
|
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
|
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.
|
// 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) {
|
func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, config *types.ContainerListOptions) (*listContext, error) {
|
||||||
psFilters := config.Filters
|
psFilters := config.Filters
|
||||||
|
|
Loading…
Reference in a new issue