Container queries are now served from the consistent in-memory db, and
don't need to grab a lock on every container being listed.
Signed-off-by: Fabio Kung <fabio.kung@gmail.com>
| ... | ... |
@@ -10,7 +10,6 @@ import ( |
| 10 | 10 |
"github.com/Sirupsen/logrus" |
| 11 | 11 |
"github.com/docker/docker/api/types" |
| 12 | 12 |
"github.com/docker/docker/api/types/filters" |
| 13 |
- networktypes "github.com/docker/docker/api/types/network" |
|
| 14 | 13 |
"github.com/docker/docker/container" |
| 15 | 14 |
"github.com/docker/docker/image" |
| 16 | 15 |
"github.com/docker/docker/volume" |
| ... | ... |
@@ -47,7 +46,7 @@ type iterationAction int |
| 47 | 47 |
|
| 48 | 48 |
// containerReducer represents a reducer for a container. |
| 49 | 49 |
// Returns the object to serialize by the api. |
| 50 |
-type containerReducer func(*container.Container, *listContext) (*types.Container, error) |
|
| 50 |
+type containerReducer func(*container.Snapshot, *listContext) (*types.Container, error) |
|
| 51 | 51 |
|
| 52 | 52 |
const ( |
| 53 | 53 |
// includeContainer is the action to include a container in the reducer. |
| ... | ... |
@@ -83,9 +82,9 @@ type listContext struct {
|
| 83 | 83 |
exitAllowed []int |
| 84 | 84 |
|
| 85 | 85 |
// beforeFilter is a filter to ignore containers that appear before the one given |
| 86 |
- beforeFilter *container.Container |
|
| 86 |
+ beforeFilter *container.Snapshot |
|
| 87 | 87 |
// sinceFilter is a filter to stop the filtering when the iterator arrive to the given container |
| 88 |
- sinceFilter *container.Container |
|
| 88 |
+ sinceFilter *container.Snapshot |
|
| 89 | 89 |
|
| 90 | 90 |
// taskFilter tells if we should filter based on wether a container is part of a task |
| 91 | 91 |
taskFilter bool |
| ... | ... |
@@ -102,7 +101,7 @@ type listContext struct {
|
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 | 104 |
// byContainerCreated is a temporary type used to sort a list of containers by creation time. |
| 105 |
-type byContainerCreated []*container.Container |
|
| 105 |
+type byContainerCreated []container.Snapshot |
|
| 106 | 106 |
|
| 107 | 107 |
func (r byContainerCreated) Len() int { return len(r) }
|
| 108 | 108 |
func (r byContainerCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
| ... | ... |
@@ -115,7 +114,7 @@ func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*types.C |
| 115 | 115 |
return daemon.reduceContainers(config, daemon.transformContainer) |
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 |
-func (daemon *Daemon) filterByNameIDMatches(ctx *listContext) []*container.Container {
|
|
| 118 |
+func (daemon *Daemon) filterByNameIDMatches(view *container.View, ctx *listContext) ([]container.Snapshot, error) {
|
|
| 119 | 119 |
idSearch := false |
| 120 | 120 |
names := ctx.filters.Get("name")
|
| 121 | 121 |
ids := ctx.filters.Get("id")
|
| ... | ... |
@@ -123,7 +122,9 @@ func (daemon *Daemon) filterByNameIDMatches(ctx *listContext) []*container.Conta |
| 123 | 123 |
// if name or ID filters are not in use, return to |
| 124 | 124 |
// standard behavior of walking the entire container |
| 125 | 125 |
// list from the daemon's in-memory store |
| 126 |
- return daemon.List() |
|
| 126 |
+ all, err := view.All() |
|
| 127 |
+ sort.Sort(sort.Reverse(byContainerCreated(all))) |
|
| 128 |
+ return all, err |
|
| 127 | 129 |
} |
| 128 | 130 |
|
| 129 | 131 |
// idSearch will determine if we limit name matching to the IDs |
| ... | ... |
@@ -158,10 +159,14 @@ func (daemon *Daemon) filterByNameIDMatches(ctx *listContext) []*container.Conta |
| 158 | 158 |
} |
| 159 | 159 |
} |
| 160 | 160 |
|
| 161 |
- cntrs := make([]*container.Container, 0, len(matches)) |
|
| 161 |
+ cntrs := make([]container.Snapshot, 0, len(matches)) |
|
| 162 | 162 |
for id := range matches {
|
| 163 |
- if c := daemon.containers.Get(id); c != nil {
|
|
| 164 |
- cntrs = append(cntrs, c) |
|
| 163 |
+ c, err := view.Get(id) |
|
| 164 |
+ if err != nil {
|
|
| 165 |
+ return nil, err |
|
| 166 |
+ } |
|
| 167 |
+ if c != nil {
|
|
| 168 |
+ cntrs = append(cntrs, *c) |
|
| 165 | 169 |
} |
| 166 | 170 |
} |
| 167 | 171 |
|
| ... | ... |
@@ -169,27 +174,31 @@ func (daemon *Daemon) filterByNameIDMatches(ctx *listContext) []*container.Conta |
| 169 | 169 |
// Created gives us nanosec resolution for sorting |
| 170 | 170 |
sort.Sort(sort.Reverse(byContainerCreated(cntrs))) |
| 171 | 171 |
|
| 172 |
- return cntrs |
|
| 172 |
+ return cntrs, nil |
|
| 173 | 173 |
} |
| 174 | 174 |
|
| 175 | 175 |
// reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer. |
| 176 | 176 |
func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
|
| 177 | 177 |
var ( |
| 178 |
+ view = daemon.containersReplica.Snapshot() |
|
| 178 | 179 |
containers = []*types.Container{}
|
| 179 | 180 |
) |
| 180 | 181 |
|
| 181 |
- ctx, err := daemon.foldFilter(config) |
|
| 182 |
+ ctx, err := daemon.foldFilter(view, config) |
|
| 182 | 183 |
if err != nil {
|
| 183 | 184 |
return nil, err |
| 184 | 185 |
} |
| 185 | 186 |
|
| 186 | 187 |
// fastpath to only look at a subset of containers if specific name |
| 187 | 188 |
// or ID matches were provided by the user--otherwise we potentially |
| 188 |
- // end up locking and querying many more containers than intended |
|
| 189 |
- containerList := daemon.filterByNameIDMatches(ctx) |
|
| 189 |
+ // end up querying many more containers than intended |
|
| 190 |
+ containerList, err := daemon.filterByNameIDMatches(view, ctx) |
|
| 191 |
+ if err != nil {
|
|
| 192 |
+ return nil, err |
|
| 193 |
+ } |
|
| 190 | 194 |
|
| 191 |
- for _, container := range containerList {
|
|
| 192 |
- t, err := daemon.reducePsContainer(container, ctx, reducer) |
|
| 195 |
+ for i := range containerList {
|
|
| 196 |
+ t, err := daemon.reducePsContainer(&containerList[i], ctx, reducer) |
|
| 193 | 197 |
if err != nil {
|
| 194 | 198 |
if err != errStopIteration {
|
| 195 | 199 |
return nil, err |
| ... | ... |
@@ -206,23 +215,17 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc |
| 206 | 206 |
} |
| 207 | 207 |
|
| 208 | 208 |
// reducePsContainer is the basic representation for a container as expected by the ps command. |
| 209 |
-func (daemon *Daemon) reducePsContainer(container *container.Container, ctx *listContext, reducer containerReducer) (*types.Container, error) {
|
|
| 210 |
- container.Lock() |
|
| 211 |
- |
|
| 209 |
+func (daemon *Daemon) reducePsContainer(container *container.Snapshot, ctx *listContext, reducer containerReducer) (*types.Container, error) {
|
|
| 212 | 210 |
// filter containers to return |
| 213 |
- action := includeContainerInList(container, ctx) |
|
| 214 |
- switch action {
|
|
| 211 |
+ switch includeContainerInList(container, ctx) {
|
|
| 215 | 212 |
case excludeContainer: |
| 216 |
- container.Unlock() |
|
| 217 | 213 |
return nil, nil |
| 218 | 214 |
case stopIteration: |
| 219 |
- container.Unlock() |
|
| 220 | 215 |
return nil, errStopIteration |
| 221 | 216 |
} |
| 222 | 217 |
|
| 223 | 218 |
// transform internal container struct into api structs |
| 224 | 219 |
newC, err := reducer(container, ctx) |
| 225 |
- container.Unlock() |
|
| 226 | 220 |
if err != nil {
|
| 227 | 221 |
return nil, err |
| 228 | 222 |
} |
| ... | ... |
@@ -237,7 +240,7 @@ func (daemon *Daemon) reducePsContainer(container *container.Container, ctx *lis |
| 237 | 237 |
} |
| 238 | 238 |
|
| 239 | 239 |
// foldFilter generates the container filter based on the user's filtering options. |
| 240 |
-func (daemon *Daemon) foldFilter(config *types.ContainerListOptions) (*listContext, error) {
|
|
| 240 |
+func (daemon *Daemon) foldFilter(view *container.View, config *types.ContainerListOptions) (*listContext, error) {
|
|
| 241 | 241 |
psFilters := config.Filters |
| 242 | 242 |
|
| 243 | 243 |
if err := psFilters.Validate(acceptedPsFilterTags); err != nil {
|
| ... | ... |
@@ -294,10 +297,10 @@ func (daemon *Daemon) foldFilter(config *types.ContainerListOptions) (*listConte |
| 294 | 294 |
return nil, err |
| 295 | 295 |
} |
| 296 | 296 |
|
| 297 |
- var beforeContFilter, sinceContFilter *container.Container |
|
| 297 |
+ var beforeContFilter, sinceContFilter *container.Snapshot |
|
| 298 | 298 |
|
| 299 | 299 |
err = psFilters.WalkValues("before", func(value string) error {
|
| 300 |
- beforeContFilter, err = daemon.GetContainer(value) |
|
| 300 |
+ beforeContFilter, err = view.Get(value) |
|
| 301 | 301 |
return err |
| 302 | 302 |
}) |
| 303 | 303 |
if err != nil {
|
| ... | ... |
@@ -305,7 +308,7 @@ func (daemon *Daemon) foldFilter(config *types.ContainerListOptions) (*listConte |
| 305 | 305 |
} |
| 306 | 306 |
|
| 307 | 307 |
err = psFilters.WalkValues("since", func(value string) error {
|
| 308 |
- sinceContFilter, err = daemon.GetContainer(value) |
|
| 308 |
+ sinceContFilter, err = view.Get(value) |
|
| 309 | 309 |
return err |
| 310 | 310 |
}) |
| 311 | 311 |
if err != nil {
|
| ... | ... |
@@ -383,7 +386,7 @@ func portOp(key string, filter map[nat.Port]bool) func(value string) error {
|
| 383 | 383 |
|
| 384 | 384 |
// includeContainerInList decides whether a container should be included in the output or not based in the filter. |
| 385 | 385 |
// It also decides if the iteration should be stopped or not. |
| 386 |
-func includeContainerInList(container *container.Container, ctx *listContext) iterationAction {
|
|
| 386 |
+func includeContainerInList(container *container.Snapshot, ctx *listContext) iterationAction {
|
|
| 387 | 387 |
// Do not include container if it's in the list before the filter container. |
| 388 | 388 |
// Set the filter container to nil to include the rest of containers after this one. |
| 389 | 389 |
if ctx.beforeFilter != nil {
|
| ... | ... |
@@ -422,7 +425,7 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 422 | 422 |
} |
| 423 | 423 |
|
| 424 | 424 |
// Do not include container if any of the labels don't match |
| 425 |
- if !ctx.filters.MatchKVList("label", container.Config.Labels) {
|
|
| 425 |
+ if !ctx.filters.MatchKVList("label", container.Labels) {
|
|
| 426 | 426 |
return excludeContainer |
| 427 | 427 |
} |
| 428 | 428 |
|
| ... | ... |
@@ -440,7 +443,7 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 440 | 440 |
if len(ctx.exitAllowed) > 0 {
|
| 441 | 441 |
shouldSkip := true |
| 442 | 442 |
for _, code := range ctx.exitAllowed {
|
| 443 |
- if code == container.ExitCode() && !container.Running && !container.StartedAt.IsZero() {
|
|
| 443 |
+ if code == container.ExitCode && !container.Running && !container.StartedAt.IsZero() {
|
|
| 444 | 444 |
shouldSkip = false |
| 445 | 445 |
break |
| 446 | 446 |
} |
| ... | ... |
@@ -451,28 +454,34 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 451 | 451 |
} |
| 452 | 452 |
|
| 453 | 453 |
// Do not include container if its status doesn't match the filter |
| 454 |
- if !ctx.filters.Match("status", container.State.StateString()) {
|
|
| 454 |
+ if !ctx.filters.Match("status", container.State) {
|
|
| 455 | 455 |
return excludeContainer |
| 456 | 456 |
} |
| 457 | 457 |
|
| 458 | 458 |
// Do not include container if its health doesn't match the filter |
| 459 |
- if !ctx.filters.ExactMatch("health", container.State.HealthString()) {
|
|
| 459 |
+ if !ctx.filters.ExactMatch("health", container.Health) {
|
|
| 460 | 460 |
return excludeContainer |
| 461 | 461 |
} |
| 462 | 462 |
|
| 463 | 463 |
if ctx.filters.Include("volume") {
|
| 464 |
- volumesByName := make(map[string]*volume.MountPoint) |
|
| 465 |
- for _, m := range container.MountPoints {
|
|
| 464 |
+ volumesByName := make(map[string]types.MountPoint) |
|
| 465 |
+ for _, m := range container.Mounts {
|
|
| 466 | 466 |
if m.Name != "" {
|
| 467 | 467 |
volumesByName[m.Name] = m |
| 468 | 468 |
} else {
|
| 469 | 469 |
volumesByName[m.Source] = m |
| 470 | 470 |
} |
| 471 | 471 |
} |
| 472 |
+ volumesByDestination := make(map[string]types.MountPoint) |
|
| 473 |
+ for _, m := range container.Mounts {
|
|
| 474 |
+ if m.Destination != "" {
|
|
| 475 |
+ volumesByDestination[m.Destination] = m |
|
| 476 |
+ } |
|
| 477 |
+ } |
|
| 472 | 478 |
|
| 473 | 479 |
volumeExist := fmt.Errorf("volume mounted in container")
|
| 474 | 480 |
err := ctx.filters.WalkValues("volume", func(value string) error {
|
| 475 |
- if _, exist := container.MountPoints[value]; exist {
|
|
| 481 |
+ if _, exist := volumesByDestination[value]; exist {
|
|
| 476 | 482 |
return volumeExist |
| 477 | 483 |
} |
| 478 | 484 |
if _, exist := volumesByName[value]; exist {
|
| ... | ... |
@@ -489,7 +498,7 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 489 | 489 |
if len(ctx.images) == 0 {
|
| 490 | 490 |
return excludeContainer |
| 491 | 491 |
} |
| 492 |
- if !ctx.images[container.ImageID] {
|
|
| 492 |
+ if !ctx.images[image.ID(container.ImageID)] {
|
|
| 493 | 493 |
return excludeContainer |
| 494 | 494 |
} |
| 495 | 495 |
} |
| ... | ... |
@@ -501,7 +510,7 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 501 | 501 |
return networkExist |
| 502 | 502 |
} |
| 503 | 503 |
for _, nw := range container.NetworkSettings.Networks {
|
| 504 |
- if nw.EndpointSettings == nil {
|
|
| 504 |
+ if nw == nil {
|
|
| 505 | 505 |
continue |
| 506 | 506 |
} |
| 507 | 507 |
if strings.HasPrefix(nw.NetworkID, value) {
|
| ... | ... |
@@ -518,7 +527,7 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 518 | 518 |
if len(ctx.publish) > 0 {
|
| 519 | 519 |
shouldSkip := true |
| 520 | 520 |
for port := range ctx.publish {
|
| 521 |
- if _, ok := container.HostConfig.PortBindings[port]; ok {
|
|
| 521 |
+ if _, ok := container.PublishPorts[port]; ok {
|
|
| 522 | 522 |
shouldSkip = false |
| 523 | 523 |
break |
| 524 | 524 |
} |
| ... | ... |
@@ -531,7 +540,7 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 531 | 531 |
if len(ctx.expose) > 0 {
|
| 532 | 532 |
shouldSkip := true |
| 533 | 533 |
for port := range ctx.expose {
|
| 534 |
- if _, ok := container.Config.ExposedPorts[port]; ok {
|
|
| 534 |
+ if _, ok := container.ExposedPorts[port]; ok {
|
|
| 535 | 535 |
shouldSkip = false |
| 536 | 536 |
break |
| 537 | 537 |
} |
| ... | ... |
@@ -545,104 +554,38 @@ func includeContainerInList(container *container.Container, ctx *listContext) it |
| 545 | 545 |
} |
| 546 | 546 |
|
| 547 | 547 |
// transformContainer generates the container type expected by the docker ps command. |
| 548 |
-func (daemon *Daemon) transformContainer(container *container.Container, ctx *listContext) (*types.Container, error) {
|
|
| 548 |
+func (daemon *Daemon) transformContainer(container *container.Snapshot, ctx *listContext) (*types.Container, error) {
|
|
| 549 | 549 |
newC := &types.Container{
|
| 550 |
- ID: container.ID, |
|
| 551 |
- Names: ctx.names[container.ID], |
|
| 552 |
- ImageID: container.ImageID.String(), |
|
| 550 |
+ ID: container.ID, |
|
| 551 |
+ Names: ctx.names[container.ID], |
|
| 552 |
+ ImageID: container.ImageID, |
|
| 553 |
+ Command: container.Command, |
|
| 554 |
+ Created: container.Created.Unix(), |
|
| 555 |
+ State: container.State, |
|
| 556 |
+ Status: container.Status, |
|
| 557 |
+ NetworkSettings: &container.NetworkSettings, |
|
| 558 |
+ Ports: container.Ports, |
|
| 559 |
+ Labels: container.Labels, |
|
| 560 |
+ Mounts: container.Mounts, |
|
| 553 | 561 |
} |
| 554 | 562 |
if newC.Names == nil {
|
| 555 | 563 |
// Dead containers will often have no name, so make sure the response isn't null |
| 556 | 564 |
newC.Names = []string{}
|
| 557 | 565 |
} |
| 566 |
+ newC.HostConfig.NetworkMode = container.HostConfig.NetworkMode |
|
| 558 | 567 |
|
| 559 |
- image := container.Config.Image // if possible keep the original ref |
|
| 560 |
- if image != container.ImageID.String() {
|
|
| 568 |
+ image := container.Image // if possible keep the original ref |
|
| 569 |
+ if image != container.ImageID {
|
|
| 561 | 570 |
id, _, err := daemon.GetImageIDAndPlatform(image) |
| 562 | 571 |
if _, isDNE := err.(ErrImageDoesNotExist); err != nil && !isDNE {
|
| 563 | 572 |
return nil, err |
| 564 | 573 |
} |
| 565 |
- if err != nil || id != container.ImageID {
|
|
| 566 |
- image = container.ImageID.String() |
|
| 574 |
+ if err != nil || id.String() != container.ImageID {
|
|
| 575 |
+ image = container.ImageID |
|
| 567 | 576 |
} |
| 568 | 577 |
} |
| 569 | 578 |
newC.Image = image |
| 570 | 579 |
|
| 571 |
- if len(container.Args) > 0 {
|
|
| 572 |
- args := []string{}
|
|
| 573 |
- for _, arg := range container.Args {
|
|
| 574 |
- if strings.Contains(arg, " ") {
|
|
| 575 |
- args = append(args, fmt.Sprintf("'%s'", arg))
|
|
| 576 |
- } else {
|
|
| 577 |
- args = append(args, arg) |
|
| 578 |
- } |
|
| 579 |
- } |
|
| 580 |
- argsAsString := strings.Join(args, " ") |
|
| 581 |
- |
|
| 582 |
- newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString)
|
|
| 583 |
- } else {
|
|
| 584 |
- newC.Command = container.Path |
|
| 585 |
- } |
|
| 586 |
- newC.Created = container.Created.Unix() |
|
| 587 |
- newC.State = container.State.StateString() |
|
| 588 |
- newC.Status = container.State.String() |
|
| 589 |
- newC.HostConfig.NetworkMode = string(container.HostConfig.NetworkMode) |
|
| 590 |
- // copy networks to avoid races |
|
| 591 |
- networks := make(map[string]*networktypes.EndpointSettings) |
|
| 592 |
- for name, network := range container.NetworkSettings.Networks {
|
|
| 593 |
- if network == nil || network.EndpointSettings == nil {
|
|
| 594 |
- continue |
|
| 595 |
- } |
|
| 596 |
- networks[name] = &networktypes.EndpointSettings{
|
|
| 597 |
- EndpointID: network.EndpointID, |
|
| 598 |
- Gateway: network.Gateway, |
|
| 599 |
- IPAddress: network.IPAddress, |
|
| 600 |
- IPPrefixLen: network.IPPrefixLen, |
|
| 601 |
- IPv6Gateway: network.IPv6Gateway, |
|
| 602 |
- GlobalIPv6Address: network.GlobalIPv6Address, |
|
| 603 |
- GlobalIPv6PrefixLen: network.GlobalIPv6PrefixLen, |
|
| 604 |
- MacAddress: network.MacAddress, |
|
| 605 |
- NetworkID: network.NetworkID, |
|
| 606 |
- } |
|
| 607 |
- if network.IPAMConfig != nil {
|
|
| 608 |
- networks[name].IPAMConfig = &networktypes.EndpointIPAMConfig{
|
|
| 609 |
- IPv4Address: network.IPAMConfig.IPv4Address, |
|
| 610 |
- IPv6Address: network.IPAMConfig.IPv6Address, |
|
| 611 |
- } |
|
| 612 |
- } |
|
| 613 |
- } |
|
| 614 |
- newC.NetworkSettings = &types.SummaryNetworkSettings{Networks: networks}
|
|
| 615 |
- |
|
| 616 |
- newC.Ports = []types.Port{}
|
|
| 617 |
- for port, bindings := range container.NetworkSettings.Ports {
|
|
| 618 |
- p, err := nat.ParsePort(port.Port()) |
|
| 619 |
- if err != nil {
|
|
| 620 |
- return nil, err |
|
| 621 |
- } |
|
| 622 |
- if len(bindings) == 0 {
|
|
| 623 |
- newC.Ports = append(newC.Ports, types.Port{
|
|
| 624 |
- PrivatePort: uint16(p), |
|
| 625 |
- Type: port.Proto(), |
|
| 626 |
- }) |
|
| 627 |
- continue |
|
| 628 |
- } |
|
| 629 |
- for _, binding := range bindings {
|
|
| 630 |
- h, err := nat.ParsePort(binding.HostPort) |
|
| 631 |
- if err != nil {
|
|
| 632 |
- return nil, err |
|
| 633 |
- } |
|
| 634 |
- newC.Ports = append(newC.Ports, types.Port{
|
|
| 635 |
- PrivatePort: uint16(p), |
|
| 636 |
- PublicPort: uint16(h), |
|
| 637 |
- Type: port.Proto(), |
|
| 638 |
- IP: binding.HostIP, |
|
| 639 |
- }) |
|
| 640 |
- } |
|
| 641 |
- } |
|
| 642 |
- |
|
| 643 |
- newC.Labels = container.Config.Labels |
|
| 644 |
- newC.Mounts = addMountPoints(container) |
|
| 645 |
- |
|
| 646 | 580 |
return newC, nil |
| 647 | 581 |
} |
| 648 | 582 |
|
| ... | ... |
@@ -6,6 +6,6 @@ import "github.com/docker/docker/container" |
| 6 | 6 |
|
| 7 | 7 |
// excludeByIsolation is a platform specific helper function to support PS |
| 8 | 8 |
// filtering by Isolation. This is a Windows-only concept, so is a no-op on Unix. |
| 9 |
-func excludeByIsolation(container *container.Container, ctx *listContext) iterationAction {
|
|
| 9 |
+func excludeByIsolation(container *container.Snapshot, ctx *listContext) iterationAction {
|
|
| 10 | 10 |
return includeContainer |
| 11 | 11 |
} |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
// excludeByIsolation is a platform specific helper function to support PS |
| 10 | 10 |
// filtering by Isolation. This is a Windows-only concept, so is a no-op on Unix. |
| 11 |
-func excludeByIsolation(container *container.Container, ctx *listContext) iterationAction {
|
|
| 11 |
+func excludeByIsolation(container *container.Snapshot, ctx *listContext) iterationAction {
|
|
| 12 | 12 |
i := strings.ToLower(string(container.HostConfig.Isolation)) |
| 13 | 13 |
if i == "" {
|
| 14 | 14 |
i = "default" |