mirror of
https://github.com/containers/podman.git
synced 2025-10-19 04:03:23 +08:00
Show c/storage (Buildah/CRI-O) containers in ps
The `podman ps --all` command will now show containers that are under the control of other c/storage container systems and the new `ps --storage` option will show only containers that are in c/storage but are not controlled by libpod. In the below examples, the '*working-container' entries were created by Buildah. ``` podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9257ef8c786c docker.io/library/busybox:latest ls /etc 8 hours ago Exited (0) 8 hours ago gifted_jang d302c81856da docker.io/library/busybox:latest buildah 30 hours ago storage busybox-working-container 7a5a7b099d33 localhost/tom:latest ls -alF 30 hours ago Exited (0) 30 hours ago hopeful_hellman 01d601fca090 localhost/tom:latest ls -alf 30 hours ago Exited (1) 30 hours ago determined_panini ee58f429ff26 localhost/tom:latest buildah 33 hours ago storage alpine-working-container podman ps --external CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d302c81856da docker.io/library/busybox:latest buildah 30 hours ago external busybox-working-container ee58f429ff26 localhost/tom:latest buildah 33 hours ago external alpine-working-container ``` Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -13,6 +13,7 @@ import (
|
|||||||
tm "github.com/buger/goterm"
|
tm "github.com/buger/goterm"
|
||||||
"github.com/containers/buildah/pkg/formats"
|
"github.com/containers/buildah/pkg/formats"
|
||||||
"github.com/containers/podman/v2/cmd/podman/registry"
|
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||||
|
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||||
@ -56,9 +57,9 @@ func init() {
|
|||||||
func listFlagSet(flags *pflag.FlagSet) {
|
func listFlagSet(flags *pflag.FlagSet) {
|
||||||
flags.BoolVarP(&listOpts.All, "all", "a", false, "Show all the containers, default is only running containers")
|
flags.BoolVarP(&listOpts.All, "all", "a", false, "Show all the containers, default is only running containers")
|
||||||
flags.StringSliceVarP(&filters, "filter", "f", []string{}, "Filter output based on conditions given")
|
flags.StringSliceVarP(&filters, "filter", "f", []string{}, "Filter output based on conditions given")
|
||||||
|
flags.BoolVar(&listOpts.Storage, "storage", false, "Show containers in storage not controlled by Podman")
|
||||||
flags.StringVar(&listOpts.Format, "format", "", "Pretty-print containers to JSON or using a Go template")
|
flags.StringVar(&listOpts.Format, "format", "", "Pretty-print containers to JSON or using a Go template")
|
||||||
flags.IntVarP(&listOpts.Last, "last", "n", -1, "Print the n last created containers (all states)")
|
flags.IntVarP(&listOpts.Last, "last", "n", -1, "Print the n last created containers (all states)")
|
||||||
flags.BoolVar(&listOpts.Namespace, "namespace", false, "Display namespace information")
|
|
||||||
flags.BoolVar(&listOpts.Namespace, "ns", false, "Display namespace information")
|
flags.BoolVar(&listOpts.Namespace, "ns", false, "Display namespace information")
|
||||||
flags.BoolVar(&noTrunc, "no-trunc", false, "Display the extended information")
|
flags.BoolVar(&noTrunc, "no-trunc", false, "Display the extended information")
|
||||||
flags.BoolVarP(&listOpts.Pod, "pod", "p", false, "Print the ID and name of the pod the containers are associated with")
|
flags.BoolVarP(&listOpts.Pod, "pod", "p", false, "Print the ID and name of the pod the containers are associated with")
|
||||||
@ -69,6 +70,7 @@ func listFlagSet(flags *pflag.FlagSet) {
|
|||||||
|
|
||||||
sort := validate.Value(&listOpts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status")
|
sort := validate.Value(&listOpts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status")
|
||||||
flags.Var(sort, "sort", "Sort output by: "+sort.Choices())
|
flags.Var(sort, "sort", "Sort output by: "+sort.Choices())
|
||||||
|
flags.SetNormalizeFunc(utils.AliasFlags)
|
||||||
}
|
}
|
||||||
func checkFlags(c *cobra.Command) error {
|
func checkFlags(c *cobra.Command) error {
|
||||||
// latest, and last are mutually exclusive.
|
// latest, and last are mutually exclusive.
|
||||||
@ -102,6 +104,14 @@ func checkFlags(c *cobra.Command) error {
|
|||||||
if listOpts.Watch > 0 && listOpts.Latest {
|
if listOpts.Watch > 0 && listOpts.Latest {
|
||||||
return errors.New("the watch and latest flags cannot be used together")
|
return errors.New("the watch and latest flags cannot be used together")
|
||||||
}
|
}
|
||||||
|
cfg := registry.PodmanConfig()
|
||||||
|
if cfg.Engine.Namespace != "" {
|
||||||
|
if c.Flag("storage").Changed && listOpts.Storage {
|
||||||
|
return errors.New("--namespace and --storage flags can not both be set")
|
||||||
|
}
|
||||||
|
listOpts.Storage = false
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ func AliasFlags(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
|||||||
name = "network"
|
name = "network"
|
||||||
case "timeout":
|
case "timeout":
|
||||||
name = "time"
|
name = "time"
|
||||||
|
case "namespace":
|
||||||
|
name = "ns"
|
||||||
}
|
}
|
||||||
return pflag.NormalizedName(name)
|
return pflag.NormalizedName(name)
|
||||||
}
|
}
|
||||||
|
@ -2679,6 +2679,7 @@ _podman_ps() {
|
|||||||
--pod -p
|
--pod -p
|
||||||
--quiet -q
|
--quiet -q
|
||||||
--size -s
|
--size -s
|
||||||
|
--storage
|
||||||
--namespace --ns
|
--namespace --ns
|
||||||
--sync
|
--sync
|
||||||
"
|
"
|
||||||
|
@ -23,6 +23,8 @@ When the URL is an Containerfile, the Containerfile is downloaded to a temporary
|
|||||||
|
|
||||||
When a Git repository is set as the URL, the repository is cloned locally and then set as the context.
|
When a Git repository is set as the URL, the repository is cloned locally and then set as the context.
|
||||||
|
|
||||||
|
NOTE: `podman build` uses code sourced from the `buildah` project to build container images. This `buildah` code creates `buildah` containers for the `RUN` options in container storage. In certain situations, when the `podman build` crashes or users kill the `podman build` process, these external containers can be left in container storage. Use the `podman ps --all --storage` command to see these contaienrs. External containers can be removed with the `podman rm --storage` command.
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
|
|
||||||
**--add-host**=*host*
|
**--add-host**=*host*
|
||||||
@ -804,7 +806,7 @@ If you are using a useradd command within a Containerfile with a large UID/GID,
|
|||||||
If you are using `useradd` within your build script, you should pass the `--no-log-init or -l` option to the `useradd` command. This option tells useradd to stop creating the lastlog file.
|
If you are using `useradd` within your build script, you should pass the `--no-log-init or -l` option to the `useradd` command. This option tells useradd to stop creating the lastlog file.
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), buildah(1), containers-registries.conf(5), crun(8), runc(8), useradd(8)
|
podman(1), buildah(1), containers-registries.conf(5), crun(8), runc(8), useradd(8), podman-ps(1), podman-rm(1)
|
||||||
|
|
||||||
## HISTORY
|
## HISTORY
|
||||||
Aug 2020, Additional options and .dockerignore added by Dan Walsh <dwalsh@redhat.com>
|
Aug 2020, Additional options and .dockerignore added by Dan Walsh <dwalsh@redhat.com>
|
||||||
|
@ -32,12 +32,18 @@ all the containers information. By default it lists:
|
|||||||
|
|
||||||
**--all**, **-a**
|
**--all**, **-a**
|
||||||
|
|
||||||
Show all the containers, default is only running containers
|
Show all the containers created by Podman, default is only running containers.
|
||||||
|
|
||||||
|
Note: Podman shares containers storage with other tools such as Buildah and CRI-O. In some cases these `external` containers might also exist in the same storage. Use the `--storage` option to see these external containers. External containers show the 'storage' status.
|
||||||
|
|
||||||
**--pod**, **-p**
|
**--pod**, **-p**
|
||||||
|
|
||||||
Display the pods the containers are associated with
|
Display the pods the containers are associated with
|
||||||
|
|
||||||
|
**--storage**
|
||||||
|
|
||||||
|
Display external containers that are not controlled by Podman but are stored in containers storage. These external containers are generally created via other container technology such as Buildah or CRI-O and may depend on the same container images that Podman is also using. External containers are denoted with either a 'buildah' or 'storage' in the COMMAND and STATUS column of the ps output. Only used with the --all option.
|
||||||
|
|
||||||
**--no-trunc**
|
**--no-trunc**
|
||||||
|
|
||||||
Display the extended information
|
Display the extended information
|
||||||
@ -174,11 +180,20 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ podman ps --storage -a
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
69ed779d8ef9f redis:alpine "redis-server" 25 hours ago Created 6379/tcp k8s_container1_podsandbox1_redhat.test.crio_redhat-test-crio_1
|
||||||
|
38a8a78596f9 docker.io/library/busybox:latest buildah 2 hours ago storage busybox-working-container
|
||||||
|
fd7b786b5c32 docker.io/library/alpine:latest buildah 2 hours ago storage alpine-working-container
|
||||||
|
f78620804e00 scratch buildah 2 hours ago storage working-container
|
||||||
|
```
|
||||||
|
|
||||||
## ps
|
## ps
|
||||||
Print a list of containers
|
Print a list of containers
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1)
|
podman(1), buildah(1), crio(8)
|
||||||
|
|
||||||
## HISTORY
|
## HISTORY
|
||||||
August 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
|
August 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
|
||||||
|
@ -45,9 +45,9 @@ The latest option is not supported on the remote client.
|
|||||||
|
|
||||||
**--storage**
|
**--storage**
|
||||||
|
|
||||||
Remove the container from the storage library only.
|
Remove external containers from the storage library.
|
||||||
This is only possible with containers that are not present in libpod (cannot be seen by **podman ps**).
|
This is only possible with containers that are not present in libpod can be seen by **podman ps --all --storage**).
|
||||||
It is used to remove containers from **podman build** and **buildah**, and orphan containers which were only partially removed by **podman rm**.
|
It is used to remove external containers from **podman build** and **buildah**, and orphan containers which were only partially removed by **podman rm**.
|
||||||
The storage option conflicts with the **--all**, **--latest**, and **--volumes** options.
|
The storage option conflicts with the **--all**, **--latest**, and **--volumes** options.
|
||||||
|
|
||||||
**--volumes**, **-v**
|
**--volumes**, **-v**
|
||||||
@ -96,7 +96,7 @@ $ podman rm -f --latest
|
|||||||
**125** The command fails for a reason other than container did not exist or is paused/running
|
**125** The command fails for a reason other than container did not exist or is paused/running
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), podman-image-rm(1)
|
podman(1), podman-image-rm(1), podman-ps(1), podman-build(1)
|
||||||
|
|
||||||
## HISTORY
|
## HISTORY
|
||||||
August 2017, Originally compiled by Ryan Cole <rycole@redhat.com>
|
August 2017, Originally compiled by Ryan Cole <rycole@redhat.com>
|
||||||
|
@ -161,4 +161,8 @@ var (
|
|||||||
// ErrNetworkOnPodContainer indicates the user wishes to alter network attributes on a container
|
// ErrNetworkOnPodContainer indicates the user wishes to alter network attributes on a container
|
||||||
// in a pod. This cannot be done as the infra container has all the network information
|
// in a pod. This cannot be done as the infra container has all the network information
|
||||||
ErrNetworkOnPodContainer = errors.New("network cannot be configured when it is shared with a pod")
|
ErrNetworkOnPodContainer = errors.New("network cannot be configured when it is shared with a pod")
|
||||||
|
|
||||||
|
// ErrStoreNotInitialized indicates that the container storage was never
|
||||||
|
// initilized.
|
||||||
|
ErrStoreNotInitialized = errors.New("the container storage was never initilized")
|
||||||
)
|
)
|
||||||
|
@ -466,6 +466,14 @@ func (ir *Runtime) getImage(image string) (*storage.Image, error) {
|
|||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ir *Runtime) ImageNames(id string) ([]string, error) {
|
||||||
|
myImage, err := ir.getImage(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error getting image %s ", id)
|
||||||
|
}
|
||||||
|
return myImage.Names, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetImages retrieves all images present in storage
|
// GetImages retrieves all images present in storage
|
||||||
func (ir *Runtime) GetImages() ([]*Image, error) {
|
func (ir *Runtime) GetImages() ([]*Image, error) {
|
||||||
return ir.getImages(false)
|
return ir.getImages(false)
|
||||||
|
@ -137,7 +137,7 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
|
|||||||
}
|
}
|
||||||
if err := p.Remove(ctx, true); err != nil {
|
if err := p.Remove(ctx, true); err != nil {
|
||||||
if errors.Cause(err) == storage.ErrImageUsedByContainer {
|
if errors.Cause(err) == storage.ErrImageUsedByContainer {
|
||||||
logrus.Warnf("Failed to prune image %s as it is in use: %v", p.ID(), err)
|
logrus.Warnf("Failed to prune image %s as it is in use: %v.\nA container associated with containers/storage i.e. Buildah, CRI-O, etc., maybe associated with this image.\nUsing the rmi command with the --force option will remove the container and image, but may cause failures for other dependent systems.", p.ID(), err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "failed to prune image")
|
return nil, errors.Wrap(err, "failed to prune image")
|
||||||
|
@ -8,11 +8,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/buildah"
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
"github.com/containers/podman/v2/libpod/define"
|
"github.com/containers/podman/v2/libpod/define"
|
||||||
"github.com/containers/podman/v2/libpod/events"
|
"github.com/containers/podman/v2/libpod/events"
|
||||||
"github.com/containers/podman/v2/pkg/cgroups"
|
"github.com/containers/podman/v2/pkg/cgroups"
|
||||||
"github.com/containers/podman/v2/pkg/rootless"
|
"github.com/containers/podman/v2/pkg/rootless"
|
||||||
|
"github.com/containers/storage"
|
||||||
"github.com/containers/storage/pkg/stringid"
|
"github.com/containers/storage/pkg/stringid"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -905,3 +907,34 @@ func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int
|
|||||||
}
|
}
|
||||||
return prunedContainers, pruneErrors, nil
|
return prunedContainers, pruneErrors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StorageContainers returns a list of containers from containers/storage that
|
||||||
|
// are not currently known to Podman.
|
||||||
|
func (r *Runtime) StorageContainers() ([]storage.Container, error) {
|
||||||
|
|
||||||
|
if r.store == nil {
|
||||||
|
return nil, define.ErrStoreNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
storeContainers, err := r.store.Containers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error reading list of all storage containers")
|
||||||
|
}
|
||||||
|
retCtrs := []storage.Container{}
|
||||||
|
for _, container := range storeContainers {
|
||||||
|
exists, err := r.state.HasContainer(container.ID)
|
||||||
|
if err != nil && err != define.ErrNoSuchCtr {
|
||||||
|
return nil, errors.Wrapf(err, "failed to check if %s container exists in database", container.ID)
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
retCtrs = append(retCtrs, container)
|
||||||
|
}
|
||||||
|
|
||||||
|
return retCtrs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runtime) IsBuildahContainer(id string) (bool, error) {
|
||||||
|
return buildah.IsContainer(id, r.store)
|
||||||
|
}
|
||||||
|
@ -282,6 +282,7 @@ type ContainerListOptions struct {
|
|||||||
Quiet bool
|
Quiet bool
|
||||||
Size bool
|
Size bool
|
||||||
Sort string
|
Sort string
|
||||||
|
Storage bool
|
||||||
Sync bool
|
Sync bool
|
||||||
Watch uint
|
Watch uint
|
||||||
}
|
}
|
||||||
|
85
pkg/ps/ps.go
85
pkg/ps/ps.go
@ -14,6 +14,7 @@ import (
|
|||||||
lpfilters "github.com/containers/podman/v2/libpod/filters"
|
lpfilters "github.com/containers/podman/v2/libpod/filters"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
psdefine "github.com/containers/podman/v2/pkg/ps/define"
|
psdefine "github.com/containers/podman/v2/pkg/ps/define"
|
||||||
|
"github.com/containers/storage"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -54,12 +55,12 @@ func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOp
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if options.Last > 0 {
|
if options.Last > 0 {
|
||||||
// Sort the containers we got
|
// Sort the libpod containers
|
||||||
sort.Sort(SortCreateTime{SortContainers: cons})
|
sort.Sort(SortCreateTime{SortContainers: cons})
|
||||||
// we should perform the lopping before we start getting
|
// we should perform the lopping before we start getting
|
||||||
// the expensive information on containers
|
// the expensive information on containers
|
||||||
if options.Last < len(cons) {
|
if options.Last < len(cons) {
|
||||||
cons = cons[len(cons)-options.Last:]
|
cons = cons[:options.Last]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, con := range cons {
|
for _, con := range cons {
|
||||||
@ -68,7 +69,31 @@ func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOp
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pss = append(pss, listCon)
|
pss = append(pss, listCon)
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.All && options.Storage {
|
||||||
|
externCons, err := runtime.StorageContainers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, con := range externCons {
|
||||||
|
listCon, err := ListStorageContainer(runtime, con, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pss = append(pss, listCon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the containers we got
|
||||||
|
sort.Sort(SortPSCreateTime{SortPSContainers: pss})
|
||||||
|
|
||||||
|
if options.Last > 0 {
|
||||||
|
// only return the "last" containers caller requested
|
||||||
|
if options.Last < len(pss) {
|
||||||
|
pss = pss[:options.Last]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pss, nil
|
return pss, nil
|
||||||
}
|
}
|
||||||
@ -199,6 +224,48 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
|
|||||||
return ps, nil
|
return ps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ListStorageContainer(rt *libpod.Runtime, ctr storage.Container, opts entities.ContainerListOptions) (entities.ListContainer, error) {
|
||||||
|
name := "unknown"
|
||||||
|
if len(ctr.Names) > 0 {
|
||||||
|
name = ctr.Names[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
ps := entities.ListContainer{
|
||||||
|
ID: ctr.ID,
|
||||||
|
Created: ctr.Created.Unix(),
|
||||||
|
ImageID: ctr.ImageID,
|
||||||
|
State: "storage",
|
||||||
|
Names: []string{name},
|
||||||
|
}
|
||||||
|
|
||||||
|
buildahCtr, err := rt.IsBuildahContainer(ctr.ID)
|
||||||
|
if err != nil {
|
||||||
|
return ps, errors.Wrapf(err, "error determining buildah container for container %s", ctr.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if buildahCtr {
|
||||||
|
ps.Command = []string{"buildah"}
|
||||||
|
} else {
|
||||||
|
ps.Command = []string{"storage"}
|
||||||
|
}
|
||||||
|
|
||||||
|
imageName := ""
|
||||||
|
if ctr.ImageID != "" {
|
||||||
|
names, err := rt.ImageRuntime().ImageNames(ctr.ImageID)
|
||||||
|
if err != nil {
|
||||||
|
return ps, err
|
||||||
|
}
|
||||||
|
if len(names) > 0 {
|
||||||
|
imageName = names[0]
|
||||||
|
}
|
||||||
|
} else if buildahCtr {
|
||||||
|
imageName = "scratch"
|
||||||
|
}
|
||||||
|
|
||||||
|
ps.Image = imageName
|
||||||
|
return ps, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getNamespaceInfo(path string) (string, error) {
|
func getNamespaceInfo(path string) (string, error) {
|
||||||
val, err := os.Readlink(path)
|
val, err := os.Readlink(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -223,5 +290,17 @@ func (a SortContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|||||||
type SortCreateTime struct{ SortContainers }
|
type SortCreateTime struct{ SortContainers }
|
||||||
|
|
||||||
func (a SortCreateTime) Less(i, j int) bool {
|
func (a SortCreateTime) Less(i, j int) bool {
|
||||||
return a.SortContainers[i].CreatedTime().Before(a.SortContainers[j].CreatedTime())
|
return a.SortContainers[i].CreatedTime().After(a.SortContainers[j].CreatedTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortPSContainers helps us set-up ability to sort by createTime
|
||||||
|
type SortPSContainers []entities.ListContainer
|
||||||
|
|
||||||
|
func (a SortPSContainers) Len() int { return len(a) }
|
||||||
|
func (a SortPSContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
|
||||||
|
type SortPSCreateTime struct{ SortPSContainers }
|
||||||
|
|
||||||
|
func (a SortPSCreateTime) Less(i, j int) bool {
|
||||||
|
return a.SortPSContainers[i].Created > a.SortPSContainers[j].Created
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user