cli/command/container: runStats(): move code to where it's used

The monitorContainerEvents and getContainerList closures where only
used when collecting "all" containers, so let's define them in that
branch of the code.

Also move some of the other variables closer to where they're used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2023-12-20 11:54:12 +01:00
parent 5ed6c128e8
commit 633ba88c26

View File

@ -60,37 +60,8 @@ func NewStatsCommand(dockerCLI command.Cli) *cobra.Command {
//
//nolint:gocyclo
func runStats(ctx context.Context, dockerCLI command.Cli, options *statsOptions) error {
showAll := len(options.containers) == 0
closeChan := make(chan error)
apiClient := dockerCLI.Client()
// monitorContainerEvents watches for container creation and removal (only
// used when calling `docker stats` without arguments).
monitorContainerEvents := func(started chan<- struct{}, c chan events.Message, stopped <-chan struct{}) {
f := filters.NewArgs()
f.Add("type", string(events.ContainerEventType))
eventChan, errChan := apiClient.Events(ctx, types.EventsOptions{
Filters: f,
})
// Whether we successfully subscribed to eventChan or not, we can now
// unblock the main goroutine.
close(started)
defer close(c)
for {
select {
case <-stopped:
return
case event := <-eventChan:
c <- event
case err := <-errChan:
closeChan <- err
return
}
}
}
// Get the daemonOSType if not set already
if daemonOSType == "" {
sv, err := apiClient.ServerVersion(ctx)
@ -102,26 +73,10 @@ func runStats(ctx context.Context, dockerCLI command.Cli, options *statsOptions)
// waitFirst is a WaitGroup to wait first stat data's reach for each container
waitFirst := &sync.WaitGroup{}
closeChan := make(chan error)
cStats := stats{}
// getContainerList simulates creation event for all previously existing
// containers (only used when calling `docker stats` without arguments).
getContainerList := func() {
cs, err := apiClient.ContainerList(ctx, container.ListOptions{
All: options.all,
})
if err != nil {
closeChan <- err
}
for _, ctr := range cs {
s := NewStats(ctr.ID[:12])
if cStats.add(s) {
waitFirst.Add(1)
go collect(ctx, s, apiClient, !options.noStream, waitFirst)
}
}
}
showAll := len(options.containers) == 0
if showAll {
// If no names were specified, start a long-running goroutine which
// monitors container events. We make sure we're subscribed before
@ -153,6 +108,51 @@ func runStats(ctx context.Context, dockerCLI command.Cli, options *statsOptions)
})
}
// monitorContainerEvents watches for container creation and removal (only
// used when calling `docker stats` without arguments).
monitorContainerEvents := func(started chan<- struct{}, c chan events.Message, stopped <-chan struct{}) {
f := filters.NewArgs()
f.Add("type", string(events.ContainerEventType))
eventChan, errChan := apiClient.Events(ctx, types.EventsOptions{
Filters: f,
})
// Whether we successfully subscribed to eventChan or not, we can now
// unblock the main goroutine.
close(started)
defer close(c)
for {
select {
case <-stopped:
return
case event := <-eventChan:
c <- event
case err := <-errChan:
closeChan <- err
return
}
}
}
// getContainerList simulates creation event for all previously existing
// containers (only used when calling `docker stats` without arguments).
getContainerList := func() {
cs, err := apiClient.ContainerList(ctx, container.ListOptions{
All: options.all,
})
if err != nil {
closeChan <- err
}
for _, ctr := range cs {
s := NewStats(ctr.ID[:12])
if cStats.add(s) {
waitFirst.Add(1)
go collect(ctx, s, apiClient, !options.noStream, waitFirst)
}
}
}
eventChan := make(chan events.Message)
go eh.Watch(eventChan)
stopped := make(chan struct{})