refactor: miscellaneous small cleanups (forEach, filters, Set)

Assisted-By: docker-agent
Signed-off-by: Nicolas De loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De loof 2026-04-27 11:28:42 +00:00 committed by Guillaume Lours
parent 98163f5616
commit 40d363baf9
10 changed files with 25 additions and 60 deletions

View file

@ -62,7 +62,7 @@ func getDefaultFilters(projectName string, oneOff oneOff, selectedServices ...st
if len(selectedServices) == 1 {
f.Add("label", serviceFilter(selectedServices[0]))
}
f.Add("label", hasConfigHashLabel())
f.Add("label", api.ConfigHashLabel)
switch oneOff {
case oneOffOnly:
f.Add("label", oneOffFilter(true))
@ -167,12 +167,6 @@ func (containers Containers) names() []string {
return names
}
func (containers Containers) forEach(fn func(container.Summary)) {
for _, c := range containers {
fn(c)
}
}
// forEachContainerConcurrent runs fn for every container concurrently and waits for all goroutines.
func forEachContainerConcurrent(ctx context.Context, containers Containers, fn func(context.Context, container.Summary) error) error {
eg, ctx := errgroup.WithContext(ctx)
@ -184,6 +178,7 @@ func forEachContainerConcurrent(ctx context.Context, containers Containers, fn f
return eg.Wait()
}
// sorted sorts containers in place by canonical name and returns the (same) slice.
func (containers Containers) sorted() Containers {
sort.Slice(containers, func(i, j int) bool {
return getCanonicalContainerName(containers[i]) < getCanonicalContainerName(containers[j])

View file

@ -73,7 +73,7 @@ func TestServiceLinks(t *testing.T) {
Filters: projectFilter(testProject).Add("label",
serviceFilter("db"),
oneOffFilter(false),
hasConfigHashLabel(),
api.ConfigHashLabel,
),
All: true,
}
@ -201,7 +201,7 @@ func TestServiceLinks(t *testing.T) {
Filters: projectFilter(testProject).Add("label",
serviceFilter("web"),
oneOffFilter(false),
hasConfigHashLabel(),
api.ConfigHashLabel,
),
All: true,
}

View file

@ -24,16 +24,21 @@ import (
"github.com/docker/compose/v5/pkg/api"
)
// labelFilter returns a label filter string of the form "key=value".
func labelFilter(key, value string) string {
return fmt.Sprintf("%s=%s", key, value)
}
func projectFilter(projectName string) client.Filters {
return make(client.Filters).Add("label", fmt.Sprintf("%s=%s", api.ProjectLabel, projectName))
return make(client.Filters).Add("label", labelFilter(api.ProjectLabel, projectName))
}
func serviceFilter(serviceName string) string {
return fmt.Sprintf("%s=%s", api.ServiceLabel, serviceName)
return labelFilter(api.ServiceLabel, serviceName)
}
func networkFilter(name string) string {
return fmt.Sprintf("%s=%s", api.NetworkLabel, name)
return labelFilter(api.NetworkLabel, name)
}
func oneOffFilter(b bool) string {
@ -45,9 +50,5 @@ func oneOffFilter(b bool) string {
}
func containerNumberFilter(index int) string {
return fmt.Sprintf("%s=%d", api.ContainerNumberLabel, index)
}
func hasConfigHashLabel() string {
return api.ConfigHashLabel
return labelFilter(api.ContainerNumberLabel, fmt.Sprintf("%d", index))
}

View file

@ -44,7 +44,7 @@ func TestKillAll(t *testing.T) {
name := strings.ToLower(testProject)
api.EXPECT().ContainerList(t.Context(), client.ContainerListOptions{
Filters: projectFilter(name).Add("label", hasConfigHashLabel()),
Filters: projectFilter(name).Add("label", api.ConfigHashLabel),
}).Return(client.ContainerListResult{
Items: []container.Summary{
testContainer("service1", "123", false),
@ -83,7 +83,7 @@ func TestKillSignal(t *testing.T) {
name := strings.ToLower(testProject)
listOptions := client.ContainerListOptions{
Filters: projectFilter(name).Add("label", serviceFilter(serviceName), hasConfigHashLabel()),
Filters: projectFilter(name).Add("label", serviceFilter(serviceName), api.ConfigHashLabel),
}
api.EXPECT().ContainerList(t.Context(), listOptions).Return(client.ContainerListResult{
@ -145,7 +145,7 @@ func anyCancellableContext() gomock.Matcher {
}
func projectFilterListOpt(withOneOff bool) client.ContainerListOptions {
filter := projectFilter(strings.ToLower(testProject)).Add("label", hasConfigHashLabel())
filter := projectFilter(strings.ToLower(testProject)).Add("label", api.ConfigHashLabel)
if !withOneOff {
filter.Add("label", oneOffFilter(false))
}

View file

@ -98,7 +98,7 @@ func TestComposeService_Logs_Demux(t *testing.T) {
api.EXPECT().ContainerList(t.Context(), client.ContainerListOptions{
All: true,
Filters: projectFilter(name).Add("label", oneOffFilter(false), hasConfigHashLabel()),
Filters: projectFilter(name).Add("label", oneOffFilter(false), api.ConfigHashLabel),
}).Return(
client.ContainerListResult{
Items: []containerType.Summary{
@ -166,7 +166,7 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) {
api.EXPECT().ContainerList(t.Context(), client.ContainerListOptions{
All: true,
Filters: projectFilter(name).Add("label", oneOffFilter(false), hasConfigHashLabel()),
Filters: projectFilter(name).Add("label", oneOffFilter(false), api.ConfigHashLabel),
}).Return(
client.ContainerListResult{
Items: []containerType.Summary{

View file

@ -60,7 +60,7 @@ func (c *monitor) Start(ctx context.Context) error {
All: true,
Filters: projectFilter(c.project).Add("label",
oneOffFilter(false),
hasConfigHashLabel(),
api.ConfigHashLabel,
),
})
if err != nil {

View file

@ -38,7 +38,7 @@ func TestPs(t *testing.T) {
assert.NilError(t, err)
listOpts := client.ContainerListOptions{
Filters: projectFilter(strings.ToLower(testProject)).Add("label", hasConfigHashLabel(), oneOffFilter(false)),
Filters: projectFilter(strings.ToLower(testProject)).Add("label", api.ConfigHashLabel, oneOffFilter(false)),
All: false,
}
c1, inspect1 := containerDetails("service1", "123", containerType.StateRunning, containerType.Healthy, 0)

View file

@ -21,7 +21,6 @@ import (
"fmt"
"strings"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
"golang.org/x/sync/errgroup"
@ -71,9 +70,9 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
}
var names []string
stoppedContainers.forEach(func(c container.Summary) {
for _, c := range stoppedContainers {
names = append(names, getCanonicalContainerName(c))
})
}
if len(names) == 0 {
return api.ErrNoResources

View file

@ -51,9 +51,9 @@ func (s Set[T]) Remove(v T) bool {
return ok
}
func (s Set[T]) Clear() {
for v := range s {
delete(s, v)
func (s Set[T]) RemoveAll(elements ...T) {
for _, e := range elements {
s.Remove(e)
}
}
@ -65,12 +65,6 @@ func (s Set[T]) Elements() []T {
return elements
}
func (s Set[T]) RemoveAll(elements ...T) {
for _, e := range elements {
s.Remove(e)
}
}
func (s Set[T]) Diff(other Set[T]) Set[T] {
out := make(Set[T])
for k := range s {
@ -81,13 +75,3 @@ func (s Set[T]) Diff(other Set[T]) Set[T] {
return out
}
func (s Set[T]) Union(other Set[T]) Set[T] {
out := make(Set[T])
for k := range s {
out[k] = struct{}{}
}
for k := range other {
out[k] = struct{}{}
}
return out
}

View file

@ -15,7 +15,6 @@
package utils
import (
"slices"
"testing"
"gotest.tools/v3/assert"
@ -33,16 +32,3 @@ func TestSet_Diff(t *testing.T) {
assert.DeepEqual(t, []int{1}, a.Diff(b).Elements())
assert.DeepEqual(t, []int{3}, b.Diff(a).Elements())
}
func TestSet_Union(t *testing.T) {
a := NewSet[int](1, 2)
b := NewSet[int](2, 3)
actual := a.Union(b).Elements()
slices.Sort(actual)
assert.DeepEqual(t, []int{1, 2, 3}, actual)
actual = b.Union(a).Elements()
slices.Sort(actual)
assert.DeepEqual(t, []int{1, 2, 3}, actual)
}