Fix: use --all in podman stats to get all containers stats

* Set query all when options.All is true
* Update API to support the "all" option in stats

Signed-off-by: Boaz Shuster <boaz.shuster.github@gmail.com>
This commit is contained in:
Boaz Shuster 2023-07-16 22:43:26 +03:00
parent 1f455cf619
commit de122bb44e
8 changed files with 64 additions and 4 deletions

View File

@ -120,6 +120,7 @@ func stats(cmd *cobra.Command, args []string) error {
Latest: statsOptions.Latest,
Stream: !statsOptions.NoStream,
Interval: statsOptions.Interval,
All: statsOptions.All,
}
args = putils.RemoveSlash(args)
statsChan, err := registry.ContainerEngine().ContainerStats(registry.Context(), args, opts)

View File

@ -34,9 +34,11 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
Containers []string `schema:"containers"`
Stream bool `schema:"stream"`
Interval int `schema:"interval"`
All bool `schema:"all"`
}{
Stream: true,
Interval: 5,
All: false,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
@ -50,6 +52,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
statsOptions := entities.ContainerStatsOptions{
Stream: query.Stream,
Interval: query.Interval,
All: query.All,
}
// Stats will stop if the connection is closed.

View File

@ -208,6 +208,7 @@ type StartOptions struct {
//
//go:generate go run ../generator/generator.go StatsOptions
type StatsOptions struct {
All *bool
Stream *bool
Interval *int
}

View File

@ -17,6 +17,21 @@ func (o *StatsOptions) ToParams() (url.Values, error) {
return util.ToParams(o)
}
// WithAll set field All to given value
func (o *StatsOptions) WithAll(value bool) *StatsOptions {
o.All = &value
return o
}
// GetAll returns value of field All
func (o *StatsOptions) GetAll() bool {
if o.All == nil {
var z bool
return z
}
return *o.All
}
// WithStream set field Stream to given value
func (o *StatsOptions) WithStream(value bool) *StatsOptions {
o.Stream = &value

View File

@ -472,6 +472,8 @@ type ContainerCpOptions struct {
// ContainerStatsOptions describes input options for getting
// stats on containers
type ContainerStatsOptions struct {
// Get all containers stats
All bool
// Operate on the latest known container. Only supported for local
// clients.
Latest bool

View File

@ -1526,7 +1526,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
}
statsChan = make(chan entities.ContainerStatsReport, 1)
containerFunc := ic.Libpod.GetRunningContainers
var containerFunc func() ([]*libpod.Container, error)
queryAll := false
switch {
case options.Latest:
@ -1539,10 +1539,14 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
}
case len(namesOrIds) > 0:
containerFunc = func() ([]*libpod.Container, error) { return ic.Libpod.GetContainersByList(namesOrIds) }
default:
// No containers, no latest -> query all!
case options.All:
queryAll = true
containerFunc = ic.Libpod.GetAllContainers
default:
// queryAll is used to ignore errors when the container was removed between listing and
// checking stats which we should do for running containers as well
queryAll = true
containerFunc = ic.Libpod.GetRunningContainers
}
go func() {

View File

@ -1049,7 +1049,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
if options.Latest {
return nil, errors.New("latest is not supported for the remote client")
}
return containers.Stats(ic.ClientCtx, namesOrIds, new(containers.StatsOptions).WithStream(options.Stream).WithInterval(options.Interval))
return containers.Stats(ic.ClientCtx, namesOrIds, new(containers.StatsOptions).WithStream(options.Stream).WithInterval(options.Interval).WithAll(options.All))
}
// ShouldRestart reports back whether the container will restart.

View File

@ -264,4 +264,38 @@ var _ = Describe("Podman stats", func() {
Expect(err).ToNot(HaveOccurred())
Expect(limit).To(BeNumerically("==", 100*1024*1024))
})
It("podman stats --all", func() {
runningContainersession := podmanTest.RunTopContainer("")
runningContainersession.WaitWithDefaultTimeout()
Expect(runningContainersession).Should(Exit(0))
runningCtrID := runningContainersession.OutputToString()[0:12]
createdContainerSession, _, _ := podmanTest.CreatePod(map[string][]string{
"--infra": {"true"},
})
createdContainerSession.WaitWithDefaultTimeout()
Expect(createdContainerSession).Should(Exit(0))
sessionAll := podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.ID}}"})
sessionAll.WaitWithDefaultTimeout()
Expect(sessionAll).Should(Exit(0))
Expect(sessionAll.OutputToString()).Should(Equal(runningCtrID))
sessionAll = podmanTest.Podman([]string{"stats", "--no-stream", "--all=false", "--format", "{{.ID}}"})
sessionAll.WaitWithDefaultTimeout()
Expect(sessionAll).Should(Exit(0))
Expect(sessionAll.OutputToString()).Should(Equal(runningCtrID))
sessionAll = podmanTest.Podman([]string{"stats", "--all=true", "--no-stream", "--format", "{{.ID}}"})
sessionAll.WaitWithDefaultTimeout()
Expect(sessionAll).Should(Exit(0))
Expect(sessionAll.OutputToStringArray()).Should(HaveLen(2))
sessionAll = podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "{{.ID}}"})
sessionAll.WaitWithDefaultTimeout()
Expect(sessionAll).Should(Exit(0))
Expect(sessionAll.OutputToStringArray()).Should(HaveLen(2))
})
})