From c9b0a21bb1f25b7b5a49998e61417b58b6e1cab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 17:51:24 +0100 Subject: [PATCH 01/13] modernize: Use `b.Loop` (introduced in Go 1.24) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- .../remotecontext/internal/tarsum/tarsum_test.go | 8 ++++---- daemon/container/view_test.go | 16 ++++++++-------- .../filiedescriptors_linux_test.go | 2 +- daemon/internal/stdcopymux/stdcopy_test.go | 4 ++-- .../internal/stream/bytespipe/bytespipe_test.go | 4 ++-- daemon/internal/stream/unbuffered_test.go | 4 ++-- daemon/libnetwork/etchosts/etchosts_test.go | 2 +- .../internal/resolvconf/resolvconf_test.go | 2 +- .../ipams/defaultipam/allocator_test.go | 4 ++-- .../portallocator/portallocator_test.go | 2 +- daemon/links/links_test.go | 4 ++-- daemon/logger/awslogs/cloudwatchlogs_test.go | 7 +++---- daemon/logger/ring_test.go | 16 ++++++++-------- internal/namesgenerator/names-generator_test.go | 2 +- pkg/tailfile/tailfile_test.go | 4 ++-- 15 files changed, 40 insertions(+), 41 deletions(-) diff --git a/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go b/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go index 1169fc453b..bd932ae3e9 100644 --- a/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go +++ b/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go @@ -580,8 +580,8 @@ func Benchmark9kTar(b *testing.B) { reader := bytes.NewReader(buf.Bytes()) b.SetBytes(n) - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { reader.Seek(0, 0) ts, err := NewTarSum(reader, true, Version0) if err != nil { @@ -611,8 +611,8 @@ func Benchmark9kTarGzip(b *testing.B) { reader := bytes.NewReader(buf.Bytes()) b.SetBytes(n) - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { reader.Seek(0, 0) ts, err := NewTarSum(reader, false, Version0) if err != nil { diff --git a/daemon/container/view_test.go b/daemon/container/view_test.go index 4e91ed5fd9..198791c360 100644 --- a/daemon/container/view_test.go +++ b/daemon/container/view_test.go @@ -350,8 +350,8 @@ func BenchmarkDBAdd100(b *testing.B) { for i := 0; i < 100; i++ { testSet = append(testSet, stringid.GenerateRandomID()) } - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { db, err := NewViewDB() if err != nil { b.Fatal(err) @@ -381,8 +381,8 @@ func BenchmarkDBGetByPrefix100(b *testing.B) { l := rand.Intn(12) + 12 testKeys = append(testKeys, id[:l]) } - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { for _, id := range testKeys { if res, err := db.GetByPrefix(id); err != nil { b.Fatal(res, err) @@ -408,8 +408,8 @@ func BenchmarkDBGetByPrefix250(b *testing.B) { l := rand.Intn(12) + 12 testKeys = append(testKeys, id[:l]) } - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { for _, id := range testKeys { if res, err := db.GetByPrefix(id); err != nil { b.Fatal(res, err) @@ -435,8 +435,8 @@ func BenchmarkDBGetByPrefix500(b *testing.B) { l := rand.Intn(12) + 12 testKeys = append(testKeys, id[:l]) } - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { for _, id := range testKeys { if res, err := db.GetByPrefix(id); err != nil { b.Fatal(res, err) diff --git a/daemon/internal/filedescriptors/filiedescriptors_linux_test.go b/daemon/internal/filedescriptors/filiedescriptors_linux_test.go index 261c13b2e3..ad91ce3d33 100644 --- a/daemon/internal/filedescriptors/filiedescriptors_linux_test.go +++ b/daemon/internal/filedescriptors/filiedescriptors_linux_test.go @@ -8,7 +8,7 @@ import ( func BenchmarkGetTotalUsedFds(b *testing.B) { ctx := context.Background() b.ReportAllocs() - for i := 0; i < b.N; i++ { + for b.Loop() { _ = GetTotalUsedFds(ctx) } } diff --git a/daemon/internal/stdcopymux/stdcopy_test.go b/daemon/internal/stdcopymux/stdcopy_test.go index b3ec459e79..a2b2e2c163 100644 --- a/daemon/internal/stdcopymux/stdcopy_test.go +++ b/daemon/internal/stdcopymux/stdcopy_test.go @@ -287,8 +287,8 @@ func BenchmarkWrite(b *testing.B) { data := []byte("Test line for testing stdwriter performance\n") data = bytes.Repeat(data, 100) b.SetBytes(int64(len(data))) - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { if _, err := w.Write(data); err != nil { b.Fatal(err) } diff --git a/daemon/internal/stream/bytespipe/bytespipe_test.go b/daemon/internal/stream/bytespipe/bytespipe_test.go index 58a71c574f..92c25e934e 100644 --- a/daemon/internal/stream/bytespipe/bytespipe_test.go +++ b/daemon/internal/stream/bytespipe/bytespipe_test.go @@ -184,7 +184,7 @@ func TestBytesPipeWriteRandomChunks(t *testing.T) { func BenchmarkBytesPipeWrite(b *testing.B) { b.ReportAllocs() testData := []byte("pretty short line, because why not?") - for i := 0; i < b.N; i++ { + for b.Loop() { readBuf := make([]byte, 1024) buf := New() go func() { @@ -203,7 +203,7 @@ func BenchmarkBytesPipeWrite(b *testing.B) { func BenchmarkBytesPipeRead(b *testing.B) { b.ReportAllocs() rd := make([]byte, 512) - for i := 0; i < b.N; i++ { + for b.Loop() { b.StopTimer() buf := New() for j := 0; j < 500; j++ { diff --git a/daemon/internal/stream/unbuffered_test.go b/daemon/internal/stream/unbuffered_test.go index 0da9987c16..282149bc8b 100644 --- a/daemon/internal/stream/unbuffered_test.go +++ b/daemon/internal/stream/unbuffered_test.go @@ -145,8 +145,8 @@ func BenchmarkUnbuffered(b *testing.B) { buf.WriteString(testLine) testText := buf.Bytes() b.SetBytes(int64(5 * len(testText))) - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { b.StopTimer() setUpWriter() b.StartTimer() diff --git a/daemon/libnetwork/etchosts/etchosts_test.go b/daemon/libnetwork/etchosts/etchosts_test.go index e73d684174..85bc239158 100644 --- a/daemon/libnetwork/etchosts/etchosts_test.go +++ b/daemon/libnetwork/etchosts/etchosts_test.go @@ -453,7 +453,7 @@ func benchDelete(b *testing.B) { } func BenchmarkDelete(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { benchDelete(b) } } diff --git a/daemon/libnetwork/internal/resolvconf/resolvconf_test.go b/daemon/libnetwork/internal/resolvconf/resolvconf_test.go index c15b711f9a..f029f13513 100644 --- a/daemon/libnetwork/internal/resolvconf/resolvconf_test.go +++ b/daemon/libnetwork/internal/resolvconf/resolvconf_test.go @@ -580,7 +580,7 @@ func BenchmarkGenerate(b *testing.B) { } b.ReportAllocs() - for i := 0; i < b.N; i++ { + for b.Loop() { _, err := rc.Generate(true) if err != nil { b.Fatal(err) diff --git a/daemon/libnetwork/ipams/defaultipam/allocator_test.go b/daemon/libnetwork/ipams/defaultipam/allocator_test.go index 4cc51c5e7e..5f9859b0bb 100644 --- a/daemon/libnetwork/ipams/defaultipam/allocator_test.go +++ b/daemon/libnetwork/ipams/defaultipam/allocator_test.go @@ -1331,7 +1331,7 @@ func BenchmarkPoolIDToString(b *testing.B) { } b.ReportAllocs() - for i := 0; i < b.N; i++ { + for b.Loop() { _ = k.String() } } @@ -1340,7 +1340,7 @@ func BenchmarkPoolIDFromString(b *testing.B) { const poolIDString = "default/172.27.0.0/16/172.27.3.0/24" b.ReportAllocs() - for i := 0; i < b.N; i++ { + for b.Loop() { _, err := PoolIDFromString(poolIDString) if err != nil { b.Fatal(err) diff --git a/daemon/libnetwork/portallocator/portallocator_test.go b/daemon/libnetwork/portallocator/portallocator_test.go index f58c0a3e40..49b3743bd5 100644 --- a/daemon/libnetwork/portallocator/portallocator_test.go +++ b/daemon/libnetwork/portallocator/portallocator_test.go @@ -147,7 +147,7 @@ func TestAllocateAllPorts(t *testing.T) { func BenchmarkAllocatePorts(b *testing.B) { p := newInstance() - for n := 0; n < b.N; n++ { + for b.Loop() { for i := 0; i <= p.end-p.begin; i++ { port, err := p.RequestPort(net.IPv4zero, "tcp", 0) if err != nil { diff --git a/daemon/links/links_test.go b/daemon/links/links_test.go index 7d76c0c4b7..99411e3240 100644 --- a/daemon/links/links_test.go +++ b/daemon/links/links_test.go @@ -143,8 +143,8 @@ func TestLinkMultipleEnv(t *testing.T) { func BenchmarkLinkMultipleEnv(b *testing.B) { b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { _ = EnvVars("172.0.17.3", "172.0.17.2", "/db/docker", []string{"PASSWORD=gordon"}, network.PortSet{ network.MustParsePort("6300/udp"): struct{}{}, network.MustParsePort("6379/tcp"): struct{}{}, diff --git a/daemon/logger/awslogs/cloudwatchlogs_test.go b/daemon/logger/awslogs/cloudwatchlogs_test.go index 2ecd7fd244..94bde68a09 100644 --- a/daemon/logger/awslogs/cloudwatchlogs_test.go +++ b/daemon/logger/awslogs/cloudwatchlogs_test.go @@ -728,7 +728,7 @@ func TestCollectBatchMultilinePattern(t *testing.T) { } func BenchmarkCollectBatch(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { mockClient := &mockClient{} stream := &logStream{ client: mockClient, @@ -759,7 +759,7 @@ func BenchmarkCollectBatch(b *testing.B) { } func BenchmarkCollectBatchMultilinePattern(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { mockClient := &mockClient{} multilinePattern := regexp.MustCompile(`\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1,2][0-9]|3[0,1]) (?:[0,1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]`) stream := &logStream{ @@ -1666,8 +1666,7 @@ func BenchmarkUnwrapEvents(b *testing.B) { } } - b.ResetTimer() - for i := 0; i < b.N; i++ { + for b.Loop() { res := unwrapEvents(events) assert.Check(b, is.Len(res, maximumLogEventsPerPut)) } diff --git a/daemon/logger/ring_test.go b/daemon/logger/ring_test.go index f90ef839d2..54124f4aea 100644 --- a/daemon/logger/ring_test.go +++ b/daemon/logger/ring_test.go @@ -158,7 +158,7 @@ func BenchmarkRingLoggerThroughputNoReceiver(b *testing.B) { msg := &Message{Line: []byte("hello humans and everyone else!")} b.SetBytes(int64(len(msg.Line))) - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } @@ -170,7 +170,7 @@ func BenchmarkRingLoggerThroughputWithReceiverDelay0(b *testing.B) { msg := &Message{Line: []byte("hello humans and everyone else!")} b.SetBytes(int64(len(msg.Line))) - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } @@ -206,7 +206,7 @@ func BenchmarkRingLoggerThroughputConsumeDelay1(b *testing.B) { cancel := consumeWithDelay(1*time.Millisecond, mockLog.c) defer cancel() - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } @@ -223,7 +223,7 @@ func BenchmarkRingLoggerThroughputConsumeDelay10(b *testing.B) { cancel := consumeWithDelay(10*time.Millisecond, mockLog.c) defer cancel() - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } @@ -240,7 +240,7 @@ func BenchmarkRingLoggerThroughputConsumeDelay50(b *testing.B) { cancel := consumeWithDelay(50*time.Millisecond, mockLog.c) defer cancel() - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } @@ -257,7 +257,7 @@ func BenchmarkRingLoggerThroughputConsumeDelay100(b *testing.B) { cancel := consumeWithDelay(100*time.Millisecond, mockLog.c) defer cancel() - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } @@ -274,7 +274,7 @@ func BenchmarkRingLoggerThroughputConsumeDelay300(b *testing.B) { cancel := consumeWithDelay(300*time.Millisecond, mockLog.c) defer cancel() - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } @@ -291,7 +291,7 @@ func BenchmarkRingLoggerThroughputConsumeDelay500(b *testing.B) { cancel := consumeWithDelay(500*time.Millisecond, mockLog.c) defer cancel() - for i := 0; i < b.N; i++ { + for b.Loop() { if err := l.Log(msg); err != nil { b.Fatal(err) } diff --git a/internal/namesgenerator/names-generator_test.go b/internal/namesgenerator/names-generator_test.go index 2a1b40f012..95ad322543 100644 --- a/internal/namesgenerator/names-generator_test.go +++ b/internal/namesgenerator/names-generator_test.go @@ -28,7 +28,7 @@ func TestNameRetries(t *testing.T) { func BenchmarkGetRandomName(b *testing.B) { b.ReportAllocs() var out string - for n := 0; n < b.N; n++ { + for b.Loop() { out = GetRandomName(5) } b.Log("Last result:", out) diff --git a/pkg/tailfile/tailfile_test.go b/pkg/tailfile/tailfile_test.go index a9add26795..aef9b31c49 100644 --- a/pkg/tailfile/tailfile_test.go +++ b/pkg/tailfile/tailfile_test.go @@ -151,8 +151,8 @@ func BenchmarkTail(b *testing.B) { b.Fatal(err) } } - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { if _, err := TailFile(f, 1000); err != nil { b.Fatal(err) } From a25907b48552e0a8032f0761b6f886a6182630b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 17:53:59 +0100 Subject: [PATCH 02/13] modernize: Prefer `strings.SplitSeq` instead of `Split` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids extra allocations. Added in Go 1.24. Signed-off-by: Paweł Gronowski --- daemon/container_operations.go | 2 +- daemon/containerd/image_push.go | 2 +- daemon/events/testutils/testutils.go | 2 +- daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go | 2 +- daemon/graphdriver/overlay2/overlay.go | 2 +- daemon/info_unix.go | 4 ++-- .../builder-next/exporter/mobyexporter/export.go | 2 +- daemon/internal/builder-next/exporter/wrapper.go | 2 +- daemon/internal/distribution/manifest.go | 4 ++-- daemon/logger/loginfo.go | 4 ++-- daemon/oci_linux.go | 2 +- daemon/volume/local/local.go | 4 ++-- daemon/volume/mounts/linux_parser.go | 8 ++++---- daemon/volume/mounts/volume_copy.go | 2 +- integration-cli/docker_api_build_test.go | 2 +- integration-cli/docker_cli_images_test.go | 4 ++-- integration-cli/docker_cli_logs_test.go | 4 ++-- integration-cli/docker_cli_ps_test.go | 2 +- integration-cli/docker_cli_pull_test.go | 2 +- integration-cli/docker_cli_push_test.go | 4 ++-- integration-cli/docker_utils_test.go | 6 +++--- integration-cli/events_utils_test.go | 10 +++++----- integration-cli/utils_test.go | 4 ++-- integration/build/build_test.go | 2 +- integration/network/bridge/bridge_linux_test.go | 2 +- integration/networking/bridge_linux_test.go | 6 +++--- integration/networking/port_mapping_linux_test.go | 4 ++-- pkg/parsers/operatingsystem/operatingsystem_linux.go | 2 +- pkg/sysinfo/sysinfo_linux.go | 4 ++-- 29 files changed, 50 insertions(+), 50 deletions(-) diff --git a/daemon/container_operations.go b/daemon/container_operations.go index c7795ecc76..2bd21760ac 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -545,7 +545,7 @@ func validateEndpointSettings(nw *libnetwork.Network, nwName string, epConfig *n } if sysctls, ok := epConfig.DriverOpts[netlabel.EndpointSysctls]; ok { - for _, sysctl := range strings.Split(sysctls, ",") { + for sysctl := range strings.SplitSeq(sysctls, ",") { scname := strings.SplitN(sysctl, ".", 5) // Allow "ifname" as well as "IFNAME", because the CLI converts to lower case. if len(scname) != 5 || diff --git a/daemon/containerd/image_push.go b/daemon/containerd/image_push.go index 384a528102..0248bb6741 100644 --- a/daemon/containerd/image_push.go +++ b/daemon/containerd/image_push.go @@ -404,7 +404,7 @@ func extractDistributionSources(labels map[string]string) []distributionSource { // if yes, read it as source for k, v := range labels { if reg := strings.TrimPrefix(k, containerdlabels.LabelDistributionSource); reg != k { - for _, repo := range strings.Split(v, ",") { + for repo := range strings.SplitSeq(v, ",") { ref, err := reference.ParseNamed(reg + "/" + repo) if err != nil { continue diff --git a/daemon/events/testutils/testutils.go b/daemon/events/testutils/testutils.go index ad853ca3f0..282cdc3274 100644 --- a/daemon/events/testutils/testutils.go +++ b/daemon/events/testutils/testutils.go @@ -56,7 +56,7 @@ func Scan(text string) (*events.Message, error) { } attrs := make(map[string]string) - for _, a := range strings.Split(md["attributes"], ", ") { + for a := range strings.SplitSeq(md["attributes"], ", ") { k, v, _ := strings.Cut(a, "=") attrs[k] = v } diff --git a/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go b/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go index b1782a8849..735c756428 100644 --- a/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go +++ b/daemon/graphdriver/fuse-overlayfs/fuseoverlayfs.go @@ -264,7 +264,7 @@ func (d *Driver) getLowerDirs(id string) ([]string, error) { var lowersArray []string lowers, err := os.ReadFile(path.Join(d.dir(id), lowerFile)) if err == nil { - for _, s := range strings.Split(string(lowers), ":") { + for s := range strings.SplitSeq(string(lowers), ":") { lp, err := os.Readlink(path.Join(d.home, s)) if err != nil { return nil, err diff --git a/daemon/graphdriver/overlay2/overlay.go b/daemon/graphdriver/overlay2/overlay.go index aa38f73a5f..b1704e1bb7 100644 --- a/daemon/graphdriver/overlay2/overlay.go +++ b/daemon/graphdriver/overlay2/overlay.go @@ -469,7 +469,7 @@ func (d *Driver) getLowerDirs(id string) ([]string, error) { var lowersArray []string lowers, err := os.ReadFile(path.Join(d.dir(id), lowerFile)) if err == nil { - for _, s := range strings.Split(string(lowers), ":") { + for s := range strings.SplitSeq(string(lowers), ":") { lp, err := os.Readlink(path.Join(d.home, s)) if err != nil { return nil, err diff --git a/daemon/info_unix.go b/daemon/info_unix.go index 829dea5fb1..5108cef844 100644 --- a/daemon/info_unix.go +++ b/daemon/info_unix.go @@ -361,8 +361,8 @@ func parseInitVersion(v string) (version string, commit string, _ error) { // commit: 69663f0bd4b60df09991c08812a60108003fa340 // spec: 1.0.0 func parseRuntimeVersion(v string) (runtime, version, commit string, _ error) { - lines := strings.Split(strings.TrimSpace(v), "\n") - for _, line := range lines { + lines := strings.SplitSeq(strings.TrimSpace(v), "\n") + for line := range lines { if strings.Contains(line, "version") { s := strings.Split(line, "version") runtime = strings.TrimSpace(s[0]) diff --git a/daemon/internal/builder-next/exporter/mobyexporter/export.go b/daemon/internal/builder-next/exporter/mobyexporter/export.go index 3aac1d258f..408c6cf6e9 100644 --- a/daemon/internal/builder-next/exporter/mobyexporter/export.go +++ b/daemon/internal/builder-next/exporter/mobyexporter/export.go @@ -60,7 +60,7 @@ func (e *imageExporter) Resolve(ctx context.Context, id int, attrs map[string]st for k, v := range attrs { switch exptypes.ImageExporterOptKey(k) { case exptypes.OptKeyName: - for _, v := range strings.Split(v, ",") { + for v := range strings.SplitSeq(v, ",") { ref, err := reference.ParseNormalizedNamed(v) if err != nil { return nil, err diff --git a/daemon/internal/builder-next/exporter/wrapper.go b/daemon/internal/builder-next/exporter/wrapper.go index bdd5424140..a5f252af6d 100644 --- a/daemon/internal/builder-next/exporter/wrapper.go +++ b/daemon/internal/builder-next/exporter/wrapper.go @@ -100,7 +100,7 @@ func (i *imageExporterInstanceWrapper) processNamedCallback(ctx context.Context, return } - for _, name := range strings.Split(imageName, ",") { + for name := range strings.SplitSeq(imageName, ",") { ref, err := reference.ParseNormalizedNamed(name) if err != nil { // Shouldn't happen, but log if it does and continue. diff --git a/daemon/internal/distribution/manifest.go b/daemon/internal/distribution/manifest.go index b92c5b4749..bb9fa87c3b 100644 --- a/daemon/internal/distribution/manifest.go +++ b/daemon/internal/distribution/manifest.go @@ -86,8 +86,8 @@ func appendDistributionSourceLabel(originLabel, repo string) string { } func hasDistributionSource(label, repo string) bool { - sources := strings.Split(label, ",") - for _, s := range sources { + sources := strings.SplitSeq(label, ",") + for s := range sources { if s == repo { return true } diff --git a/daemon/logger/loginfo.go b/daemon/logger/loginfo.go index 2c3fc09857..8b0576cdcf 100644 --- a/daemon/logger/loginfo.go +++ b/daemon/logger/loginfo.go @@ -31,7 +31,7 @@ func (info *Info) ExtraAttributes(keyMod func(string) string) (map[string]string extra := make(map[string]string) if labels, ok := info.Config["labels"]; ok && labels != "" { - for _, l := range strings.Split(labels, ",") { + for l := range strings.SplitSeq(labels, ",") { if v, ok := info.ContainerLabels[l]; ok { if keyMod != nil { l = keyMod(l) @@ -69,7 +69,7 @@ func (info *Info) ExtraAttributes(keyMod func(string) string) (map[string]string } if env, ok := info.Config["env"]; ok && env != "" { - for _, l := range strings.Split(env, ",") { + for l := range strings.SplitSeq(env, ",") { if v, ok := envMapping[l]; ok { if keyMod != nil { l = keyMod(l) diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index 8d936f6096..b8177a67ba 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -408,7 +408,7 @@ const ( // hasMountInfoOption checks if any of the passed any of the given option values // are set in the passed in option string. func hasMountInfoOption(opts string, vals ...string) bool { - for _, opt := range strings.Split(opts, " ") { + for opt := range strings.SplitSeq(opts, " ") { for _, val := range vals { if strings.HasPrefix(opt, val) { return true diff --git a/daemon/volume/local/local.go b/daemon/volume/local/local.go index c0088afabb..75d7cdddec 100644 --- a/daemon/volume/local/local.go +++ b/daemon/volume/local/local.go @@ -419,7 +419,7 @@ func (v *localVolume) LiveRestoreVolume(ctx context.Context, _ string) error { // getAddress finds out address/hostname from options func getAddress(opts string) string { - for _, opt := range strings.Split(opts, ",") { + for opt := range strings.SplitSeq(opts, ",") { if strings.HasPrefix(opt, "addr=") { return strings.TrimPrefix(opt, "addr=") } @@ -429,7 +429,7 @@ func getAddress(opts string) string { // getPassword finds out a password from options func getPassword(opts string) string { - for _, opt := range strings.Split(opts, ",") { + for opt := range strings.SplitSeq(opts, ",") { if strings.HasPrefix(opt, "password=") { return strings.TrimPrefix(opt, "password=") } diff --git a/daemon/volume/mounts/linux_parser.go b/daemon/volume/mounts/linux_parser.go index 16d6a2de3d..c80b456863 100644 --- a/daemon/volume/mounts/linux_parser.go +++ b/daemon/volume/mounts/linux_parser.go @@ -174,7 +174,7 @@ var linuxPropagationModes = map[mount.Propagation]bool{ const linuxDefaultPropagationMode = mount.PropagationRPrivate func linuxGetPropagation(mode string) mount.Propagation { - for _, o := range strings.Split(mode, ",") { + for o := range strings.SplitSeq(mode, ",") { prop := mount.Propagation(o) if linuxPropagationModes[prop] { return prop @@ -184,7 +184,7 @@ func linuxGetPropagation(mode string) mount.Propagation { } func linuxHasPropagation(mode string) bool { - for _, o := range strings.Split(mode, ",") { + for o := range strings.SplitSeq(mode, ",") { if linuxPropagationModes[mount.Propagation(o)] { return true } @@ -203,7 +203,7 @@ func linuxValidMountMode(mode string) bool { copyModeCount := 0 consistencyModeCount := 0 - for _, o := range strings.Split(mode, ",") { + for o := range strings.SplitSeq(mode, ",") { switch { case rwModes[o]: rwModeCount++ @@ -256,7 +256,7 @@ func (p *linuxParser) ReadWrite(mode string) bool { return false } - for _, o := range strings.Split(mode, ",") { + for o := range strings.SplitSeq(mode, ",") { if o == "ro" { return false } diff --git a/daemon/volume/mounts/volume_copy.go b/daemon/volume/mounts/volume_copy.go index 2b5706f14b..a8d068740a 100644 --- a/daemon/volume/mounts/volume_copy.go +++ b/daemon/volume/mounts/volume_copy.go @@ -14,7 +14,7 @@ func copyModeExists(mode string) bool { // GetCopyMode gets the copy mode from the mode string for mounts func getCopyMode(mode string, def bool) (bool, bool) { - for _, o := range strings.Split(mode, ",") { + for o := range strings.SplitSeq(mode, ",") { if isEnabled, exists := copyModes[o]; exists { return isEnabled, true } diff --git a/integration-cli/docker_api_build_test.go b/integration-cli/docker_api_build_test.go index b0d600cb91..51f5d1227f 100644 --- a/integration-cli/docker_api_build_test.go +++ b/integration-cli/docker_api_build_test.go @@ -569,7 +569,7 @@ type buildLine struct { func getImageIDsFromBuild(t *testing.T, output []byte) []string { var ids []string - for _, line := range bytes.Split(output, []byte("\n")) { + for line := range bytes.SplitSeq(output, []byte("\n")) { if len(line) == 0 { continue } diff --git a/integration-cli/docker_cli_images_test.go b/integration-cli/docker_cli_images_test.go index d7125a4256..5b95e26deb 100644 --- a/integration-cli/docker_cli_images_test.go +++ b/integration-cli/docker_cli_images_test.go @@ -199,8 +199,8 @@ func (s *DockerCLIImagesSuite) TestImagesFilterSinceAndBefore(c *testing.T) { func getImageIDs(out string) []string { var actual []string - imgs := strings.Split(out, "\n") - for _, l := range imgs { + imgs := strings.SplitSeq(out, "\n") + for l := range imgs { imgTag, imgDigest, _ := strings.Cut(l, "\t") if strings.HasPrefix(imgTag, "test_") { actual = append(actual, imgDigest) diff --git a/integration-cli/docker_cli_logs_test.go b/integration-cli/docker_cli_logs_test.go index c0af4e73f8..299d243e99 100644 --- a/integration-cli/docker_cli_logs_test.go +++ b/integration-cli/docker_cli_logs_test.go @@ -217,8 +217,8 @@ func (s *DockerCLILogsSuite) TestLogsSinceFutureFollow(c *testing.T) { since := t.Unix() + 2 out := cli.DockerCmd(c, "logs", "-t", "-f", fmt.Sprintf("--since=%v", since), name).Combined() assert.Assert(c, out != "", "cannot read from empty log") - lines := strings.Split(strings.TrimSpace(out), "\n") - for _, v := range lines { + lines := strings.SplitSeq(strings.TrimSpace(out), "\n") + for v := range lines { ts, err := time.Parse(time.RFC3339Nano, strings.Split(v, " ")[0]) assert.NilError(c, err, "cannot parse timestamp output from log: '%v'", v) assert.Assert(c, ts.Unix() >= since, "earlier log found. since=%v logdate=%v", since, ts) diff --git a/integration-cli/docker_cli_ps_test.go b/integration-cli/docker_cli_ps_test.go index 5e17a592e5..b4cc7f0106 100644 --- a/integration-cli/docker_cli_ps_test.go +++ b/integration-cli/docker_cli_ps_test.go @@ -531,7 +531,7 @@ func (s *DockerCLIPsSuite) TestPsListContainersFilterCreated(c *testing.T) { out = cli.DockerCmd(c, "ps", "-a").Stdout() hits := 0 - for _, line := range strings.Split(out, "\n") { + for line := range strings.SplitSeq(out, "\n") { if !strings.Contains(line, shortCID) { continue } diff --git a/integration-cli/docker_cli_pull_test.go b/integration-cli/docker_cli_pull_test.go index 9a5e0625b1..2e8b91bf7b 100644 --- a/integration-cli/docker_cli_pull_test.go +++ b/integration-cli/docker_cli_pull_test.go @@ -157,7 +157,7 @@ func (s *DockerHubPullSuite) TestPullAllTagsFromCentralRegistry(c *testing.T) { // Verify that the line for 'dockercore/engine-pull-all-test-fixture:latest' is left unchanged. var latestLine string - for _, line := range strings.Split(outImageAllTagCmd, "\n") { + for line := range strings.SplitSeq(outImageAllTagCmd, "\n") { if strings.HasPrefix(line, "dockercore/engine-pull-all-test-fixture") && strings.Contains(line, "latest") { latestLine = line break diff --git a/integration-cli/docker_cli_push_test.go b/integration-cli/docker_cli_push_test.go index b51a8dd898..862a5626db 100644 --- a/integration-cli/docker_cli_push_test.go +++ b/integration-cli/docker_cli_push_test.go @@ -79,7 +79,7 @@ func (s *DockerRegistrySuite) TestPushMultipleTags(c *testing.T) { // Ensure layer list is equivalent for repoTag1 and repoTag2 out1 := cli.DockerCmd(c, "push", repoTag1).Combined() var out1Lines []string - for _, outputLine := range strings.Split(out1, "\n") { + for outputLine := range strings.SplitSeq(out1, "\n") { if strings.Contains(outputLine, imageAlreadyExists) { out1Lines = append(out1Lines, outputLine) } @@ -87,7 +87,7 @@ func (s *DockerRegistrySuite) TestPushMultipleTags(c *testing.T) { out2 := cli.DockerCmd(c, "push", repoTag2).Combined() var out2Lines []string - for _, outputLine := range strings.Split(out2, "\n") { + for outputLine := range strings.SplitSeq(out2, "\n") { if strings.Contains(outputLine, imageAlreadyExists) { out2Lines = append(out2Lines, outputLine) } diff --git a/integration-cli/docker_utils_test.go b/integration-cli/docker_utils_test.go index 571f83bc52..5b25312bf0 100644 --- a/integration-cli/docker_utils_test.go +++ b/integration-cli/docker_utils_test.go @@ -55,8 +55,8 @@ func getContainerCount(t *testing.T) int { result := icmd.RunCommand(dockerBinary, "info") result.Assert(t, icmd.Success) - lines := strings.Split(result.Combined(), "\n") - for _, line := range lines { + lines := strings.SplitSeq(result.Combined(), "\n") + for line := range lines { if strings.Contains(line, containers) { output := strings.TrimSpace(line) output = strings.TrimPrefix(output, containers) @@ -435,7 +435,7 @@ func loadSpecialImage(t *testing.T, imageFunc specialimage.SpecialImageFunc) str out := cli.DockerCmd(t, "load", "-i", imgTar).Stdout() - for _, line := range strings.Split(out, "\n") { + for line := range strings.SplitSeq(out, "\n") { line = strings.TrimSpace(line) if _, imageID, hasID := strings.Cut(line, "Loaded image ID: "); hasID { diff --git a/integration-cli/events_utils_test.go b/integration-cli/events_utils_test.go index 762e6d4191..d06d378562 100644 --- a/integration-cli/events_utils_test.go +++ b/integration-cli/events_utils_test.go @@ -102,8 +102,8 @@ func (e *eventObserver) CheckEventError(t *testing.T, id, event string, match ev if e.disconnectionError != nil { until := daemonUnixTime(t) out := cli.DockerCmd(t, "events", "--since", e.startTime, "--until", until).Stdout() - events := strings.Split(strings.TrimSpace(out), "\n") - for _, e := range events { + events := strings.SplitSeq(strings.TrimSpace(out), "\n") + for e := range events { if _, ok := match(e); ok { foundEvent = true break @@ -176,7 +176,7 @@ func matchEventID(matches map[string]string, id string) bool { if !matchID && matches["attributes"] != "" { // try matching a name in the attributes attributes := map[string]string{} - for _, a := range strings.Split(matches["attributes"], ", ") { + for a := range strings.SplitSeq(matches["attributes"], ", ") { kv := strings.Split(a, "=") attributes[kv[0]] = kv[1] } @@ -186,8 +186,8 @@ func matchEventID(matches map[string]string, id string) bool { } func parseEvents(t *testing.T, out, match string) { - events := strings.Split(strings.TrimSpace(out), "\n") - for _, event := range events { + events := strings.SplitSeq(strings.TrimSpace(out), "\n") + for event := range events { matches := eventstestutils.ScanMap(event) matched, err := regexp.MatchString(match, matches["action"]) assert.NilError(t, err) diff --git a/integration-cli/utils_test.go b/integration-cli/utils_test.go index c741859557..be26c7818b 100644 --- a/integration-cli/utils_test.go +++ b/integration-cli/utils_test.go @@ -24,7 +24,7 @@ func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) { // a map which cgroup name as key and path as value. func ParseCgroupPaths(procCgroupData string) map[string]string { cgroupPaths := map[string]string{} - for _, line := range strings.Split(procCgroupData, "\n") { + for line := range strings.SplitSeq(procCgroupData, "\n") { parts := strings.Split(line, ":") if len(parts) != 3 { continue @@ -120,7 +120,7 @@ func existingElements(t *testing.T, opts elementListOptions) []string { } out := cli.DockerCmd(t, args...).Combined() var lines []string - for _, l := range strings.Split(out, "\n") { + for l := range strings.SplitSeq(out, "\n") { if l != "" { lines = append(lines, l) } diff --git a/integration/build/build_test.go b/integration/build/build_test.go index c5ea9cc61e..46b3d9132d 100644 --- a/integration/build/build_test.go +++ b/integration/build/build_test.go @@ -861,7 +861,7 @@ type buildLine struct { func getImageIDsFromBuild(output []byte) ([]string, error) { var ids []string - for _, line := range bytes.Split(output, []byte("\n")) { + for line := range bytes.SplitSeq(output, []byte("\n")) { if len(line) == 0 { continue } diff --git a/integration/network/bridge/bridge_linux_test.go b/integration/network/bridge/bridge_linux_test.go index f322cbea14..89b986d25d 100644 --- a/integration/network/bridge/bridge_linux_test.go +++ b/integration/network/bridge/bridge_linux_test.go @@ -891,7 +891,7 @@ func TestFirewallBackendSwitch(t *testing.T) { }) // TODO: (When Go 1.24 is min version) Replace with `strings.Lines(dump)`. - for _, line := range strings.Split(dump, "\n") { + for line := range strings.SplitSeq(dump, "\n") { line = strings.TrimSpace(line) if line == "" { continue diff --git a/integration/networking/bridge_linux_test.go b/integration/networking/bridge_linux_test.go index ec79954b4d..43edd9e1c0 100644 --- a/integration/networking/bridge_linux_test.go +++ b/integration/networking/bridge_linux_test.go @@ -1591,7 +1591,7 @@ func checkProxies(ctx context.Context, t *testing.T, c *client.Client, daemonPid t.Error(res) return } - for _, line := range strings.Split(res.Stdout(), "\n") { + for line := range strings.SplitSeq(res.Stdout(), "\n") { _, args, ok := strings.Cut(line, "docker-proxy") if !ok { continue @@ -1785,7 +1785,7 @@ func TestAdvertiseAddresses(t *testing.T) { // the associated MAC address. findNeighMAC := func(neighOut, ip string) string { t.Helper() - for _, line := range strings.Split(neighOut, "\n") { + for line := range strings.SplitSeq(neighOut, "\n") { // Lines look like ... // 172.22.22.22 dev eth0 lladdr 36:bc:ce:67:f3:e4 ref 1 used 0/7/0 probes 1 DELAY fields := strings.Fields(line) @@ -2015,7 +2015,7 @@ func TestLegacyLinksEnvVars(t *testing.T) { // Check the list of environment variables set in the linking container. var found bool - for _, l := range strings.Split(exportRes.Stdout.String(), "\n") { + for l := range strings.SplitSeq(exportRes.Stdout.String(), "\n") { if strings.HasPrefix(l, "export CTR1_") { // Legacy links env var found, but not expected. if !tc.expectEnvVars { diff --git a/integration/networking/port_mapping_linux_test.go b/integration/networking/port_mapping_linux_test.go index a33f3410d9..99bf62ae33 100644 --- a/integration/networking/port_mapping_linux_test.go +++ b/integration/networking/port_mapping_linux_test.go @@ -281,8 +281,8 @@ func enableIPv6OnAll(t *testing.T) func() { ifaces := map[string]string{} var allVal string - sysctls := strings.Split(string(out), "\n") - for _, sysctl := range sysctls { + sysctls := strings.SplitSeq(string(out), "\n") + for sysctl := range sysctls { if sysctl == "" { continue } diff --git a/pkg/parsers/operatingsystem/operatingsystem_linux.go b/pkg/parsers/operatingsystem/operatingsystem_linux.go index 3c1ee18a1c..1492f8a4d4 100644 --- a/pkg/parsers/operatingsystem/operatingsystem_linux.go +++ b/pkg/parsers/operatingsystem/operatingsystem_linux.go @@ -71,7 +71,7 @@ func IsContainerized() (bool, error) { if err != nil { return false, err } - for _, line := range bytes.Split(b, []byte{'\n'}) { + for line := range bytes.SplitSeq(b, []byte{'\n'}) { if len(line) > 0 && !bytes.HasSuffix(line, []byte(":/")) && !bytes.HasSuffix(line, []byte(":/init.scope")) { return true, nil } diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go index 47a982b35d..4f57301ff6 100644 --- a/pkg/sysinfo/sysinfo_linux.go +++ b/pkg/sysinfo/sysinfo_linux.go @@ -55,7 +55,7 @@ func findCgroupV1Mountpoints() (map[string]string, error) { mps := make(map[string]string) for _, mi := range mounts { - for _, opt := range strings.Split(mi.VFSOptions, ",") { + for opt := range strings.SplitSeq(mi.VFSOptions, ",") { seen, known := allMap[opt] if known && !seen { allMap[opt] = true @@ -375,7 +375,7 @@ func parseUintList(val string, maximum int) (map[int]struct{}, error) { availableInts := make(map[int]struct{}) errInvalidFormat := fmt.Errorf("invalid format: %s", val) - for _, r := range strings.Split(val, ",") { + for r := range strings.SplitSeq(val, ",") { if !strings.Contains(r, "-") { v, err := strconv.Atoi(r) if err != nil { From ff33808a79914b18db97ac00074ab515246bd29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 17:56:10 +0100 Subject: [PATCH 03/13] modernize: Use strings.Cut instead of strings.Index where possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- .../remotecontext/internal/tarsum/versioning.go | 6 +++--- daemon/container/env.go | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/daemon/builder/remotecontext/internal/tarsum/versioning.go b/daemon/builder/remotecontext/internal/tarsum/versioning.go index 60aa170e7c..4494bfa7e6 100644 --- a/daemon/builder/remotecontext/internal/tarsum/versioning.go +++ b/daemon/builder/remotecontext/internal/tarsum/versioning.go @@ -34,11 +34,11 @@ func WriteV1Header(h *tar.Header, w io.Writer) { // the string or an empty string if no label separator is found. func VersionLabelForChecksum(checksum string) string { // Checksums are in the form: {versionLabel}+{hashID}:{hex} - sepIndex := strings.Index(checksum, "+") - if sepIndex < 0 { + before, _, ok := strings.Cut(checksum, "+") + if !ok { return "" } - return checksum[:sepIndex] + return before } // GetVersions gets a list of all known tarsum versions. diff --git a/daemon/container/env.go b/daemon/container/env.go index a9a72e305d..943503234d 100644 --- a/daemon/container/env.go +++ b/daemon/container/env.go @@ -9,14 +9,14 @@ import ( func ReplaceOrAppendEnvValues(defaults, overrides []string) []string { cache := make(map[string]int, len(defaults)) for i, e := range defaults { - index := strings.Index(e, "=") - cache[e[:index]] = i + before, _, _ := strings.Cut(e, "=") + cache[before] = i } for _, value := range overrides { // Values w/o = means they want this env to be removed/unset. - index := strings.Index(value, "=") - if index < 0 { + before, _, ok := strings.Cut(value, "=") + if !ok { // no "=" in value if i, exists := cache[value]; exists { defaults[i] = "" // Used to indicate it should be removed @@ -24,7 +24,7 @@ func ReplaceOrAppendEnvValues(defaults, overrides []string) []string { continue } - if i, exists := cache[value[:index]]; exists { + if i, exists := cache[before]; exists { defaults[i] = value } else { defaults = append(defaults, value) From cdce8f4f92bffc4b75b10a36441cffc4e042fb1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:18:12 +0100 Subject: [PATCH 04/13] modernize: Use maps.Copy instead of for loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- daemon/builder/dockerfile/buildargs.go | 9 +++---- .../cluster/executor/container/container.go | 17 ++++--------- daemon/commit.go | 5 ++-- daemon/config/config.go | 5 ++-- daemon/container/exec.go | 5 ++-- daemon/container_operations.go | 5 ++-- daemon/containerd/image_events.go | 5 ++-- daemon/events.go | 5 ++-- daemon/images/image_events.go | 5 ++-- daemon/inspect.go | 5 ++-- daemon/internal/builder-next/builder.go | 5 ++-- daemon/internal/filters/parse.go | 5 ++-- .../cnmallocator/networkallocator.go | 9 +++---- daemon/libnetwork/endpoint.go | 4 +--- daemon/libnetwork/network.go | 24 +++++-------------- daemon/libnetwork/sandbox.go | 9 +++---- daemon/logger/fluentd/fluentd.go | 5 ++-- daemon/logger/fluentd/fluentd_test.go | 5 ++-- daemon/logger/journald/journald.go | 9 +++---- daemon/logger/log_cache_opts.go | 6 ++--- daemon/network.go | 4 +--- daemon/oci_linux.go | 5 ++-- daemon/pkg/registry/config.go | 4 +--- .../router/container/container_routes_test.go | 5 ++-- daemon/volume/drivers/adapter.go | 5 ++-- daemon/volume/service/store.go | 9 +++---- daemon/volumes.go | 5 ++-- .../testutil/labelstore/memory_label_store.go | 5 ++-- 28 files changed, 66 insertions(+), 123 deletions(-) diff --git a/daemon/builder/dockerfile/buildargs.go b/daemon/builder/dockerfile/buildargs.go index 93099a4eb5..f123087b44 100644 --- a/daemon/builder/dockerfile/buildargs.go +++ b/daemon/builder/dockerfile/buildargs.go @@ -3,6 +3,7 @@ package dockerfile import ( "fmt" "io" + "maps" "sort" ) @@ -47,12 +48,8 @@ func NewBuildArgs(argsFromOptions map[string]*string) *BuildArgs { // Clone returns a copy of the BuildArgs type func (b *BuildArgs) Clone() *BuildArgs { result := NewBuildArgs(b.argsFromOptions) - for k, v := range b.allowedBuildArgs { - result.allowedBuildArgs[k] = v - } - for k, v := range b.allowedMetaArgs { - result.allowedMetaArgs[k] = v - } + maps.Copy(result.allowedBuildArgs, b.allowedBuildArgs) + maps.Copy(result.allowedMetaArgs, b.allowedMetaArgs) for k := range b.referencedArgs { result.referencedArgs[k] = struct{}{} } diff --git a/daemon/cluster/executor/container/container.go b/daemon/cluster/executor/container/container.go index 1b84d45e2b..6af3079942 100644 --- a/daemon/cluster/executor/container/container.go +++ b/daemon/cluster/executor/container/container.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "maps" "math" "net" "net/netip" @@ -261,15 +262,11 @@ func (c *containerConfig) labels() map[string]string { ) // base labels are those defined in the spec. - for k, v := range c.spec().Labels { - labels[k] = v - } + maps.Copy(labels, c.spec().Labels) // we then apply the overrides from the task, which may be set via the // orchestrator. - for k, v := range c.task.Annotations.Labels { - labels[k] = v - } + maps.Copy(labels, c.task.Annotations.Labels) // finally, we apply the system labels, which override all labels. for k, v := range system { @@ -367,9 +364,7 @@ func convertMount(m api.Mount) enginemount.Mount { } if m.VolumeOptions.Labels != nil { mount.VolumeOptions.Labels = make(map[string]string, len(m.VolumeOptions.Labels)) - for k, v := range m.VolumeOptions.Labels { - mount.VolumeOptions.Labels[k] = v - } + maps.Copy(mount.VolumeOptions.Labels, m.VolumeOptions.Labels) } if m.VolumeOptions.DriverConfig != nil { mount.VolumeOptions.DriverConfig = &enginemount.Driver{ @@ -377,9 +372,7 @@ func convertMount(m api.Mount) enginemount.Mount { } if m.VolumeOptions.DriverConfig.Options != nil { mount.VolumeOptions.DriverConfig.Options = make(map[string]string, len(m.VolumeOptions.DriverConfig.Options)) - for k, v := range m.VolumeOptions.DriverConfig.Options { - mount.VolumeOptions.DriverConfig.Options[k] = v - } + maps.Copy(mount.VolumeOptions.DriverConfig.Options, m.VolumeOptions.DriverConfig.Options) } } } diff --git a/daemon/commit.go b/daemon/commit.go index fe6d9feb81..852b335ef1 100644 --- a/daemon/commit.go +++ b/daemon/commit.go @@ -3,6 +3,7 @@ package daemon import ( "context" "fmt" + "maps" "runtime" "strings" "time" @@ -109,9 +110,7 @@ func merge(userConf, imageConf *containertypes.Config) error { if len(userConf.Volumes) == 0 { userConf.Volumes = imageConf.Volumes } else { - for k, v := range imageConf.Volumes { - userConf.Volumes[k] = v - } + maps.Copy(userConf.Volumes, imageConf.Volumes) } if userConf.StopSignal == "" { diff --git a/daemon/config/config.go b/daemon/config/config.go index 1bcf1c517b..ffe9e11495 100644 --- a/daemon/config/config.go +++ b/daemon/config/config.go @@ -5,6 +5,7 @@ import ( "encoding/json" stderrors "errors" "fmt" + "maps" "net" "net/netip" "net/url" @@ -587,9 +588,7 @@ func configValuesSet(config map[string]any) map[string]any { flatten := make(map[string]any) for k, v := range config { if m, isMap := v.(map[string]any); isMap && !flatOptions[k] { - for km, vm := range m { - flatten[km] = vm - } + maps.Copy(flatten, m) continue } diff --git a/daemon/container/exec.go b/daemon/container/exec.go index c82fa89b21..3bcbd9f1d5 100644 --- a/daemon/container/exec.go +++ b/daemon/container/exec.go @@ -2,6 +2,7 @@ package container import ( "context" + "maps" "runtime" "sync" @@ -91,9 +92,7 @@ func NewExecStore() *ExecStore { func (e *ExecStore) Commands() map[string]*ExecConfig { e.mu.RLock() byID := make(map[string]*ExecConfig, len(e.byID)) - for id, config := range e.byID { - byID[id] = config - } + maps.Copy(byID, e.byID) e.mu.RUnlock() return byID } diff --git a/daemon/container_operations.go b/daemon/container_operations.go index 2bd21760ac..7f19f9a89e 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "maps" "net/netip" "os" "runtime" @@ -413,9 +414,7 @@ func (daemon *Daemon) allocateNetwork(ctx context.Context, cfg *config.Config, c // An intermediate map is necessary because "connectToNetwork" modifies "container.NetworkSettings.Networks" networks := make(map[string]*network.EndpointSettings) - for n, epConf := range ctr.NetworkSettings.Networks { - networks[n] = epConf - } + maps.Copy(networks, ctr.NetworkSettings.Networks) for netName, epConf := range networks { cleanOperationalData(epConf) if err := daemon.connectToNetwork(ctx, cfg, ctr, netName, epConf); err != nil { diff --git a/daemon/containerd/image_events.go b/daemon/containerd/image_events.go index 81935e737e..70e26d95ad 100644 --- a/daemon/containerd/image_events.go +++ b/daemon/containerd/image_events.go @@ -2,6 +2,7 @@ package containerd import ( "context" + "maps" c8dimages "github.com/containerd/containerd/v2/core/images" "github.com/moby/moby/api/types/events" @@ -45,7 +46,5 @@ func copyAttributes(attributes, labels map[string]string) { if labels == nil { return } - for k, v := range labels { - attributes[k] = v - } + maps.Copy(attributes, labels) } diff --git a/daemon/events.go b/daemon/events.go index 16ab112394..dc8f81d879 100644 --- a/daemon/events.go +++ b/daemon/events.go @@ -2,6 +2,7 @@ package daemon import ( "context" + "maps" "strconv" "strings" "time" @@ -94,9 +95,7 @@ func copyAttributes(attributes, labels map[string]string) { if labels == nil { return } - for k, v := range labels { - attributes[k] = v - } + maps.Copy(attributes, labels) } // ProcessClusterNotifications gets changes from store and add them to event list diff --git a/daemon/images/image_events.go b/daemon/images/image_events.go index 2ffd3993dd..714eaff4ae 100644 --- a/daemon/images/image_events.go +++ b/daemon/images/image_events.go @@ -2,6 +2,7 @@ package images import ( "context" + "maps" "github.com/moby/moby/api/types/events" "github.com/moby/moby/v2/daemon/server/imagebackend" @@ -32,7 +33,5 @@ func copyAttributes(attributes, labels map[string]string) { if labels == nil { return } - for k, v := range labels { - attributes[k] = v - } + maps.Copy(attributes, labels) } diff --git a/daemon/inspect.go b/daemon/inspect.go index 284cced10d..13a54ee264 100644 --- a/daemon/inspect.go +++ b/daemon/inspect.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "maps" "runtime" "time" @@ -35,9 +36,7 @@ func (daemon *Daemon) ContainerInspect(ctx context.Context, name string, options // TODO(thaJeztah): do we need a deep copy here? Otherwise we could use maps.Clone (see https://github.com/moby/moby/commit/7917a36cc787ada58987320e67cc6d96858f3b55) ports := make(networktypes.PortMap, len(ctr.NetworkSettings.Ports)) - for k, pm := range ctr.NetworkSettings.Ports { - ports[k] = pm - } + maps.Copy(ports, ctr.NetworkSettings.Ports) apiNetworks := make(map[string]*networktypes.EndpointSettings) for nwName, epConf := range ctr.NetworkSettings.Networks { diff --git a/daemon/internal/builder-next/builder.go b/daemon/internal/builder-next/builder.go index 1b59e0e3ac..58a616026c 100644 --- a/daemon/internal/builder-next/builder.go +++ b/daemon/internal/builder-next/builder.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "maps" "net/netip" "strconv" "strings" @@ -213,9 +214,7 @@ func (b *Builder) Prune(ctx context.Context, opts buildbackend.CachePruneOptions validFilters["until"] = true validFilters["label"] = true // TODO(tiborvass): handle label validFilters["label!"] = true // TODO(tiborvass): handle label! - for k, v := range cacheFields { - validFilters[k] = v - } + maps.Copy(validFilters, cacheFields) if err := opts.Filters.Validate(validFilters); err != nil { return 0, nil, err } diff --git a/daemon/internal/filters/parse.go b/daemon/internal/filters/parse.go index 396657bb19..bb4be6a013 100644 --- a/daemon/internal/filters/parse.go +++ b/daemon/internal/filters/parse.go @@ -6,6 +6,7 @@ package filters import ( "encoding/json" + "maps" "regexp" "strings" ) @@ -280,9 +281,7 @@ func (args Args) Clone() (newArgs Args) { var mm map[string]bool if m != nil { mm = make(map[string]bool, len(m)) - for kk, v := range m { - mm[kk] = v - } + maps.Copy(mm, m) } newArgs.fields[k] = mm } diff --git a/daemon/libnetwork/cnmallocator/networkallocator.go b/daemon/libnetwork/cnmallocator/networkallocator.go index f374e840f3..4bd8b27c6f 100644 --- a/daemon/libnetwork/cnmallocator/networkallocator.go +++ b/daemon/libnetwork/cnmallocator/networkallocator.go @@ -3,6 +3,7 @@ package cnmallocator import ( "context" "fmt" + "maps" "net" "net/netip" "slices" @@ -725,14 +726,10 @@ func (na *cnmNetworkAllocator) allocateDriverState(d *networkDriver, n *api.Netw // reconcile the driver specific options from the network spec // and from the operational state retrieved from the store if n.Spec.DriverConfig != nil { - for k, v := range n.Spec.DriverConfig.Options { - options[k] = v - } + maps.Copy(options, n.Spec.DriverConfig.Options) } if n.DriverState != nil { - for k, v := range n.DriverState.Options { - options[k] = v - } + maps.Copy(options, n.DriverState.Options) } // Construct IPAM data for driver consumption. diff --git a/daemon/libnetwork/endpoint.go b/daemon/libnetwork/endpoint.go index 7ae3cf536b..1cfb2614d8 100644 --- a/daemon/libnetwork/endpoint.go +++ b/daemon/libnetwork/endpoint.go @@ -1036,9 +1036,7 @@ func (ep *Endpoint) getEtcHostsAddrs() []netip.Addr { // in a Dictionary of Key-Value pair func EndpointOptionGeneric(generic map[string]any) EndpointOption { return func(ep *Endpoint) { - for k, v := range generic { - ep.generic[k] = v - } + maps.Copy(ep.generic, generic) } } diff --git a/daemon/libnetwork/network.go b/daemon/libnetwork/network.go index cbbaa736c5..be7d82d6dc 100644 --- a/daemon/libnetwork/network.go +++ b/daemon/libnetwork/network.go @@ -476,9 +476,7 @@ func (n *Network) applyConfigurationTo(to *Network) error { } if len(n.generic) > 0 { to.generic = options.Generic{} - for k, v := range n.generic { - to.generic[k] = v - } + maps.Copy(to.generic, n.generic) } // Network drivers only see generic flags. So, make sure they match. @@ -525,15 +523,11 @@ func (n *Network) CopyTo(o datastore.KVObject) error { if dstN.labels == nil { dstN.labels = make(map[string]string, len(n.labels)) } - for k, v := range n.labels { - dstN.labels[k] = v - } + maps.Copy(dstN.labels, n.labels) if n.ipamOptions != nil { dstN.ipamOptions = make(map[string]string, len(n.ipamOptions)) - for k, v := range n.ipamOptions { - dstN.ipamOptions[k] = v - } + maps.Copy(dstN.ipamOptions, n.ipamOptions) } for _, c := range n.ipamV4Config { @@ -553,9 +547,7 @@ func (n *Network) CopyTo(o datastore.KVObject) error { } dstN.generic = options.Generic{} - for k, v := range n.generic { - dstN.generic[k] = v - } + maps.Copy(dstN.generic, n.generic) return nil } @@ -793,9 +785,7 @@ func NetworkOptionGeneric(generic map[string]any) NetworkOption { if val, ok := generic[netlabel.Internal]; ok { n.internal = val.(bool) } - for k, v := range generic { - n.generic[k] = v - } + maps.Copy(n.generic, generic) } } @@ -1875,9 +1865,7 @@ func (n *Network) Labels() map[string]string { defer n.mu.Unlock() lbls := make(map[string]string, len(n.labels)) - for k, v := range n.labels { - lbls[k] = v - } + maps.Copy(lbls, n.labels) return lbls } diff --git a/daemon/libnetwork/sandbox.go b/daemon/libnetwork/sandbox.go index 8f5e531188..065dd2f894 100644 --- a/daemon/libnetwork/sandbox.go +++ b/daemon/libnetwork/sandbox.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "maps" "net" "net/netip" "slices" @@ -126,9 +127,7 @@ func (sb *Sandbox) Labels() map[string]any { sb.mu.Lock() defer sb.mu.Unlock() opts := make(map[string]any, len(sb.config.generic)) - for k, v := range sb.config.generic { - opts[k] = v - } + maps.Copy(opts, sb.config.generic) return opts } @@ -280,9 +279,7 @@ func (sb *Sandbox) UpdateLabels(labels map[string]any) { if sb.config.generic == nil { sb.config.generic = make(map[string]any, len(labels)) } - for k, v := range labels { - sb.config.generic[k] = v - } + maps.Copy(sb.config.generic, labels) } func (sb *Sandbox) MarshalJSON() ([]byte, error) { diff --git a/daemon/logger/fluentd/fluentd.go b/daemon/logger/fluentd/fluentd.go index 6e71d7c41f..fdda8b19e1 100644 --- a/daemon/logger/fluentd/fluentd.go +++ b/daemon/logger/fluentd/fluentd.go @@ -4,6 +4,7 @@ package fluentd import ( "context" + "maps" "math" "net/url" "strconv" @@ -120,9 +121,7 @@ func (f *fluentd) Log(msg *logger.Message) error { "source": msg.Source, "log": string(msg.Line), } - for k, v := range f.extra { - data[k] = v - } + maps.Copy(data, f.extra) if msg.PLogMetaData != nil { data["partial_message"] = "true" data["partial_id"] = msg.PLogMetaData.ID diff --git a/daemon/logger/fluentd/fluentd_test.go b/daemon/logger/fluentd/fluentd_test.go index 3f9b9bbece..09b5f61a2a 100644 --- a/daemon/logger/fluentd/fluentd_test.go +++ b/daemon/logger/fluentd/fluentd_test.go @@ -3,6 +3,7 @@ package fluentd import ( "bufio" "context" + "maps" "net" "path/filepath" "runtime" @@ -350,9 +351,7 @@ func TestReadWriteTimeoutsAreEffective(t *testing.T) { "fluentd-buffer-limit": "1", } // Update the config with test specific configs. - for k, v := range tc.cfg { - cfg[k] = v - } + maps.Copy(cfg, tc.cfg) f, err := New(logger.Info{ ContainerName: "/test-container", diff --git a/daemon/logger/journald/journald.go b/daemon/logger/journald/journald.go index 2169d00f45..62c2a40819 100644 --- a/daemon/logger/journald/journald.go +++ b/daemon/logger/journald/journald.go @@ -5,6 +5,7 @@ package journald import ( "errors" "fmt" + "maps" "strconv" "sync/atomic" "time" @@ -129,9 +130,7 @@ func newJournald(info logger.Info) (*journald, error) { if err != nil { return nil, err } - for k, v := range extraAttrs { - vars[k] = v - } + maps.Copy(vars, extraAttrs) return &journald{ epoch: epoch, vars: vars, @@ -159,9 +158,7 @@ func validateLogOpt(cfg map[string]string) error { func (s *journald) Log(msg *logger.Message) error { vars := map[string]string{} - for k, v := range s.vars { - vars[k] = v - } + maps.Copy(vars, s.vars) if !msg.Timestamp.IsZero() { vars[fieldSyslogTimestamp] = msg.Timestamp.Format(time.RFC3339Nano) } diff --git a/daemon/logger/log_cache_opts.go b/daemon/logger/log_cache_opts.go index 8d09c489ed..5b7641328a 100644 --- a/daemon/logger/log_cache_opts.go +++ b/daemon/logger/log_cache_opts.go @@ -1,5 +1,7 @@ package logger +import "maps" + var externalValidators []LogOptValidator // RegisterExternalValidator adds the validator to the list of external validators. @@ -14,9 +16,7 @@ func RegisterExternalValidator(v LogOptValidator) { // not be exposed as a usable log driver to the API. // This should only be called on package initialization. func AddBuiltinLogOpts(opts map[string]bool) { - for k, v := range opts { - builtInLogOpts[k] = v - } + maps.Copy(builtInLogOpts, opts) } func validateExternal(cfg map[string]string) error { diff --git a/daemon/network.go b/daemon/network.go index bf75a3f500..859d9af722 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -304,9 +304,7 @@ func (daemon *Daemon) createNetwork(ctx context.Context, cfg *config.Config, cre } networkOptions := make(map[string]string) - for k, v := range create.Options { - networkOptions[k] = v - } + maps.Copy(networkOptions, create.Options) if defaultOpts, ok := cfg.DefaultNetworkOpts[driver]; create.ConfigFrom == nil && ok { for k, v := range defaultOpts { if _, ok := networkOptions[k]; !ok { diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index b8177a67ba..237049ea20 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -3,6 +3,7 @@ package daemon import ( "context" "fmt" + "maps" "os" "path/filepath" "strconv" @@ -985,9 +986,7 @@ func WithSysctls(c *container.Container) coci.SpecOpts { } // We merge the sysctls injected above with the HostConfig (latter takes // precedence for backwards-compatibility reasons). - for k, v := range c.HostConfig.Sysctls { - s.Linux.Sysctl[k] = v - } + maps.Copy(s.Linux.Sysctl, c.HostConfig.Sysctls) return nil } } diff --git a/daemon/pkg/registry/config.go b/daemon/pkg/registry/config.go index dea7c87634..6983a6163c 100644 --- a/daemon/pkg/registry/config.go +++ b/daemon/pkg/registry/config.go @@ -102,9 +102,7 @@ func newServiceConfig(options ServiceOptions) (*serviceConfig, error) { // copy constructs a new ServiceConfig with a copy of the configuration in config. func (config *serviceConfig) copy() *registry.ServiceConfig { ic := make(map[string]*registry.IndexInfo) - for key, value := range config.IndexConfigs { - ic[key] = value - } + maps.Copy(ic, config.IndexConfigs) return ®istry.ServiceConfig{ InsecureRegistryCIDRs: slices.Clone(config.InsecureRegistryCIDRs), IndexConfigs: ic, diff --git a/daemon/server/router/container/container_routes_test.go b/daemon/server/router/container/container_routes_test.go index fa468c1cdb..2cc8b63cdd 100644 --- a/daemon/server/router/container/container_routes_test.go +++ b/daemon/server/router/container/container_routes_test.go @@ -1,6 +1,7 @@ package container import ( + "maps" "strings" "testing" @@ -315,9 +316,7 @@ func TestHandleSysctlBC(t *testing.T) { NetworkMode: container.NetworkMode(tc.networkMode), Sysctls: map[string]string{}, } - for k, v := range tc.sysctls { - hostCfg.Sysctls[k] = v - } + maps.Copy(hostCfg.Sysctls, tc.sysctls) netCfg := &network.NetworkingConfig{ EndpointsConfig: tc.epConfig, } diff --git a/daemon/volume/drivers/adapter.go b/daemon/volume/drivers/adapter.go index 2178a8316e..8217de0af9 100644 --- a/daemon/volume/drivers/adapter.go +++ b/daemon/volume/drivers/adapter.go @@ -3,6 +3,7 @@ package drivers import ( "context" "errors" + "maps" "strings" "time" @@ -169,8 +170,6 @@ func (a *volumeAdapter) CreatedAt() (time.Time, error) { func (a *volumeAdapter) Status() map[string]any { out := make(map[string]any, len(a.status)) - for k, v := range a.status { - out[k] = v - } + maps.Copy(out, a.status) return out } diff --git a/daemon/volume/service/store.go b/daemon/volume/service/store.go index 7b3f9975b0..8f6fb8a7be 100644 --- a/daemon/volume/service/store.go +++ b/daemon/volume/service/store.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "maps" "net" "os" "path/filepath" @@ -39,9 +40,7 @@ func (v volumeWrapper) Options() map[string]string { return nil } options := make(map[string]string, len(v.options)) - for key, value := range v.options { - options[key] = value - } + maps.Copy(options, v.options) return options } @@ -51,9 +50,7 @@ func (v volumeWrapper) Labels() map[string]string { } labels := make(map[string]string, len(v.labels)) - for key, value := range v.labels { - labels[key] = value - } + maps.Copy(labels, v.labels) return labels } diff --git a/daemon/volumes.go b/daemon/volumes.go index e5aafa084c..a0c553d15d 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -3,6 +3,7 @@ package daemon import ( "context" "encoding/hex" + "maps" "os" "path/filepath" "sort" @@ -97,9 +98,7 @@ func (daemon *Daemon) registerMountPoints(ctr *container.Container, defaultReadO } // 1. Read already configured mount points. - for destination, point := range ctr.MountPoints { - mountPoints[destination] = point - } + maps.Copy(mountPoints, ctr.MountPoints) // 2. Read volumes from other containers. for _, v := range ctr.HostConfig.VolumesFrom { diff --git a/internal/testutil/labelstore/memory_label_store.go b/internal/testutil/labelstore/memory_label_store.go index 979cc9f060..9c55dcfcc6 100644 --- a/internal/testutil/labelstore/memory_label_store.go +++ b/internal/testutil/labelstore/memory_label_store.go @@ -1,6 +1,7 @@ package labelstore import ( + "maps" "sync" "github.com/opencontainers/go-digest" @@ -40,9 +41,7 @@ func (s *InMemory) Update(dgst digest.Digest, update map[string]string) (map[str if !ok { labels = map[string]string{} } - for k, v := range update { - labels[k] = v - } + maps.Copy(labels, update) if s.labels == nil { s.labels = map[digest.Digest]map[string]string{} } From 39c19d9161c1ec8d4d786e7dd95b56fd3e0fa12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:25:00 +0100 Subject: [PATCH 05/13] modernize: Use fmt.Appendf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added in Go 1.19 Signed-off-by: Paweł Gronowski --- daemon/internal/image/store_test.go | 2 +- daemon/libnetwork/networkdb/networkdb.go | 12 ++++++------ daemon/libnetwork/networkdb/networkdb_test.go | 6 +++--- integration-cli/docker_cli_build_test.go | 2 +- integration-cli/docker_cli_daemon_test.go | 4 ++-- integration-cli/docker_cli_logout_test.go | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/daemon/internal/image/store_test.go b/daemon/internal/image/store_test.go index 7a53cd0787..1708e5e1b2 100644 --- a/daemon/internal/image/store_test.go +++ b/daemon/internal/image/store_test.go @@ -188,7 +188,7 @@ func TestStoreLen(t *testing.T) { expected := 10 for i := range expected { - _, err := imgStore.Create([]byte(fmt.Sprintf(`{"comment": "abc%d", "rootfs": {"type": "layers"}}`, i))) + _, err := imgStore.Create(fmt.Appendf(nil, `{"comment": "abc%d", "rootfs": {"type": "layers"}}`, i)) assert.NilError(t, err) } numImages := imgStore.Len() diff --git a/daemon/libnetwork/networkdb/networkdb.go b/daemon/libnetwork/networkdb/networkdb.go index 34821d5a8f..36b71d90c8 100644 --- a/daemon/libnetwork/networkdb/networkdb.go +++ b/daemon/libnetwork/networkdb/networkdb.go @@ -393,7 +393,7 @@ func (nDB *NetworkDB) GetEntry(tname, nid, key string) ([]byte, error) { } func (nDB *NetworkDB) getEntry(tname, nid, key string) (*entry, error) { - e, ok := nDB.indexes[byTable].Get([]byte(fmt.Sprintf("/%s/%s/%s", tname, nid, key))) + e, ok := nDB.indexes[byTable].Get(fmt.Appendf(nil, "/%s/%s/%s", tname, nid, key)) if !ok { return nil, types.NotFoundErrorf("could not get entry in table %s with network id %s and key %s", tname, nid, key) } @@ -470,7 +470,7 @@ func (nDB *NetworkDB) GetTableByNetwork(tname, nid string) map[string]*TableElem root := nDB.indexes[byTable].Root() nDB.RUnlock() entries := make(map[string]*TableElem) - root.WalkPrefix([]byte(fmt.Sprintf("/%s/%s", tname, nid)), func(k []byte, v *entry) bool { + root.WalkPrefix(fmt.Appendf(nil, "/%s/%s", tname, nid), func(k []byte, v *entry) bool { if v.deleting { return false } @@ -794,8 +794,8 @@ func (nDB *NetworkDB) updateLocalNetworkTime() { // createOrUpdateEntry this function handles the creation or update of entries into the local // tree store. It is also used to keep in sync the entries number of the network (all tables are aggregated) func (nDB *NetworkDB) createOrUpdateEntry(nid, tname, key string, v *entry) (okTable bool, okNetwork bool) { - nDB.indexes[byTable], _, okTable = nDB.indexes[byTable].Insert([]byte(fmt.Sprintf("/%s/%s/%s", tname, nid, key)), v) - nDB.indexes[byNetwork], _, okNetwork = nDB.indexes[byNetwork].Insert([]byte(fmt.Sprintf("/%s/%s/%s", nid, tname, key)), v) + nDB.indexes[byTable], _, okTable = nDB.indexes[byTable].Insert(fmt.Appendf(nil, "/%s/%s/%s", tname, nid, key), v) + nDB.indexes[byNetwork], _, okNetwork = nDB.indexes[byNetwork].Insert(fmt.Appendf(nil, "/%s/%s/%s", nid, tname, key), v) if !okNetwork { // Add only if it is an insert not an update n, ok := nDB.thisNodeNetworks[nid] @@ -809,8 +809,8 @@ func (nDB *NetworkDB) createOrUpdateEntry(nid, tname, key string, v *entry) (okT // deleteEntry this function handles the deletion of entries into the local tree store. // It is also used to keep in sync the entries number of the network (all tables are aggregated) func (nDB *NetworkDB) deleteEntry(nid, tname, key string) (okTable bool, okNetwork bool) { - nDB.indexes[byTable], _, okTable = nDB.indexes[byTable].Delete([]byte(fmt.Sprintf("/%s/%s/%s", tname, nid, key))) - nDB.indexes[byNetwork], _, okNetwork = nDB.indexes[byNetwork].Delete([]byte(fmt.Sprintf("/%s/%s/%s", nid, tname, key))) + nDB.indexes[byTable], _, okTable = nDB.indexes[byTable].Delete(fmt.Appendf(nil, "/%s/%s/%s", tname, nid, key)) + nDB.indexes[byNetwork], _, okNetwork = nDB.indexes[byNetwork].Delete(fmt.Appendf(nil, "/%s/%s/%s", nid, tname, key)) if okNetwork { // Remove only if the delete is successful n, ok := nDB.thisNodeNetworks[nid] diff --git a/daemon/libnetwork/networkdb/networkdb_test.go b/daemon/libnetwork/networkdb/networkdb_test.go index a63de7e9df..829ec6f44e 100644 --- a/daemon/libnetwork/networkdb/networkdb_test.go +++ b/daemon/libnetwork/networkdb/networkdb_test.go @@ -324,14 +324,14 @@ func TestNetworkDBCRUDTableEntries(t *testing.T) { for i := 1; i <= n; i++ { err = dbs[0].CreateEntry("test_table", "network1", fmt.Sprintf("test_key0%d", i), - []byte(fmt.Sprintf("test_value0%d", i))) + fmt.Appendf(nil, "test_value0%d", i)) assert.NilError(t, err) } for i := 1; i <= n; i++ { err = dbs[1].CreateEntry("test_table", "network1", fmt.Sprintf("test_key1%d", i), - []byte(fmt.Sprintf("test_value1%d", i))) + fmt.Appendf(nil, "test_value1%d", i)) assert.NilError(t, err) } @@ -445,7 +445,7 @@ func TestNetworkDBBulkSync(t *testing.T) { for i := 1; i <= n; i++ { err = dbs[0].CreateEntry("test_table", "network1", fmt.Sprintf("test_key0%d", i), - []byte(fmt.Sprintf("test_value0%d", i))) + fmt.Appendf(nil, "test_value0%d", i)) assert.NilError(t, err) } diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 34535bfc53..aa249241b4 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -5645,7 +5645,7 @@ func (s *DockerCLIBuildSuite) TestBuildMultiStageCopyFromSyntax(c *testing.T) { assert.Equal(c, strings.Count(result.Combined(), "Using cache"), 7) assert.Equal(c, getIDByName(c, "build1"), getIDByName(c, "build2")) - err := os.WriteFile(filepath.Join(ctx.Dir, "Dockerfile"), []byte(fmt.Sprintf(dockerfile, "COPY baz/aa foo")), 0o644) + err := os.WriteFile(filepath.Join(ctx.Dir, "Dockerfile"), fmt.Appendf(nil, dockerfile, "COPY baz/aa foo"), 0o644) assert.NilError(c, err) // changing file in parent block should not affect last block diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index 76a8e710fb..aa83a7250a 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -2125,7 +2125,7 @@ func (s *DockerDaemonSuite) TestShmSizeReload(c *testing.T) { configFile := filepath.Join(configPath, "config.json") size := 67108864 * 2 - configData := []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) + configData := fmt.Appendf(nil, `{"default-shm-size": "%dM"}`, size/1024/1024) assert.Assert(c, os.WriteFile(configFile, configData, 0o666) == nil, "could not write temp file for config reload") pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) @@ -2140,7 +2140,7 @@ func (s *DockerDaemonSuite) TestShmSizeReload(c *testing.T) { assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%v", size)) size = 67108864 * 3 - configData = []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) + configData = fmt.Appendf(nil, `{"default-shm-size": "%dM"}`, size/1024/1024) assert.Assert(c, os.WriteFile(configFile, configData, 0o666) == nil, "could not write temp file for config reload") pattern = regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) diff --git a/integration-cli/docker_cli_logout_test.go b/integration-cli/docker_cli_logout_test.go index 47d09d84f9..7874017964 100644 --- a/integration-cli/docker_cli_logout_test.go +++ b/integration-cli/docker_cli_logout_test.go @@ -77,7 +77,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithWrongHostnamesStored(c * c.Setenv("PATH", testPath) cmd := exec.Command("docker-credential-shell-test", "store") - stdin := bytes.NewReader([]byte(fmt.Sprintf(`{"ServerURL": "https://%s", "Username": %q, "Secret": %q}`, privateRegistryURL, s.reg.Username(), s.reg.Password()))) + stdin := bytes.NewReader(fmt.Appendf(nil, `{"ServerURL": "https://%s", "Username": %q, "Secret": %q}`, privateRegistryURL, s.reg.Username(), s.reg.Password())) cmd.Stdin = stdin assert.NilError(c, cmd.Run()) From e548a31d28d49d70c7f1070bf131fd705120e4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:25:30 +0100 Subject: [PATCH 06/13] modernize: Use `min` built-in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- .../distribution/metadata/v2_metadata_service_test.go | 5 +---- daemon/internal/netiputil/netiputil.go | 5 +---- daemon/internal/stream/bytespipe/bytespipe.go | 5 +---- daemon/internal/versions/compare.go | 5 +---- daemon/libnetwork/internal/addrset/addrset.go | 10 ++-------- daemon/libnetwork/sandbox_store.go | 5 +---- daemon/list.go | 5 +---- daemon/logger/copier.go | 5 +---- daemon/logger/splunk/splunk.go | 5 +---- pkg/tailfile/tailfile.go | 10 ++-------- pkg/tailfile/tailfile_test.go | 5 +---- 11 files changed, 13 insertions(+), 52 deletions(-) diff --git a/daemon/internal/distribution/metadata/v2_metadata_service_test.go b/daemon/internal/distribution/metadata/v2_metadata_service_test.go index 3ac6cabd4a..50e86bbbe5 100644 --- a/daemon/internal/distribution/metadata/v2_metadata_service_test.go +++ b/daemon/internal/distribution/metadata/v2_metadata_service_test.go @@ -63,10 +63,7 @@ func TestV2MetadataService(t *testing.T) { if err != nil { t.Fatalf("error calling Get: %v", err) } - expectedMetadataEntries := len(vec.metadata) - if expectedMetadataEntries > 50 { - expectedMetadataEntries = 50 - } + expectedMetadataEntries := min(len(vec.metadata), 50) if !reflect.DeepEqual(metadata, vec.metadata[len(vec.metadata)-expectedMetadataEntries:len(vec.metadata)]) { t.Fatal("Get returned incorrect layer ID") } diff --git a/daemon/internal/netiputil/netiputil.go b/daemon/internal/netiputil/netiputil.go index e8c30b4b10..20cc44f65b 100644 --- a/daemon/internal/netiputil/netiputil.go +++ b/daemon/internal/netiputil/netiputil.go @@ -81,10 +81,7 @@ func PrefixCompare(a, b netip.Prefix) int { // PrefixAfter returns the prefix of size 'sz' right after 'prev'. func PrefixAfter(prev netip.Prefix, sz int) netip.Prefix { - s := sz - if prev.Bits() < sz { - s = prev.Bits() - } + s := min(prev.Bits(), sz) addr := ipbits.Add(prev.Addr(), 1, uint(prev.Addr().BitLen()-s)) if addr.IsUnspecified() { return netip.Prefix{} diff --git a/daemon/internal/stream/bytespipe/bytespipe.go b/daemon/internal/stream/bytespipe/bytespipe.go index 499cbfecc9..601704cf88 100644 --- a/daemon/internal/stream/bytespipe/bytespipe.go +++ b/daemon/internal/stream/bytespipe/bytespipe.go @@ -96,10 +96,7 @@ loop0: } // add new byte slice to the buffers slice and continue writing - nextCap := b.Cap() * 2 - if nextCap > maxCap { - nextCap = maxCap - } + nextCap := min(b.Cap()*2, maxCap) bp.buf = append(bp.buf, getBuffer(nextCap)) } bp.wait.Broadcast() diff --git a/daemon/internal/versions/compare.go b/daemon/internal/versions/compare.go index 1a0325c7ed..bcc5b69703 100644 --- a/daemon/internal/versions/compare.go +++ b/daemon/internal/versions/compare.go @@ -16,10 +16,7 @@ func compare(v1, v2 string) int { otherTab = strings.Split(v2, ".") ) - maxVer := len(currTab) - if len(otherTab) > maxVer { - maxVer = len(otherTab) - } + maxVer := max(len(otherTab), len(currTab)) for i := 0; i < maxVer; i++ { var currInt, otherInt int diff --git a/daemon/libnetwork/internal/addrset/addrset.go b/daemon/libnetwork/internal/addrset/addrset.go index e5b5771bfe..64764f6d06 100644 --- a/daemon/libnetwork/internal/addrset/addrset.go +++ b/daemon/libnetwork/internal/addrset/addrset.go @@ -203,10 +203,7 @@ func (as *AddrSet) AddrsInPrefix(prefix netip.Prefix) (hi, lo uint64) { } func (as *AddrSet) getBitmap(addr netip.Addr) (*bitmap.Bitmap, netip.Prefix, error) { - bits := as.pool.Addr().BitLen() - as.pool.Bits() - if bits > maxBitsPerBitmap { - bits = maxBitsPerBitmap - } + bits := min(as.pool.Addr().BitLen()-as.pool.Bits(), maxBitsPerBitmap) bmKey, err := addr.Prefix(as.pool.Addr().BitLen() - bits) if err != nil { return nil, netip.Prefix{}, err @@ -220,10 +217,7 @@ func (as *AddrSet) getBitmap(addr netip.Addr) (*bitmap.Bitmap, netip.Prefix, err } func (as *AddrSet) addrsPerBitmap() uint64 { - bits := as.pool.Addr().BitLen() - as.pool.Bits() - if bits > maxBitsPerBitmap { - bits = maxBitsPerBitmap - } + bits := min(as.pool.Addr().BitLen()-as.pool.Bits(), maxBitsPerBitmap) return uint64(1) << bits } diff --git a/daemon/libnetwork/sandbox_store.go b/daemon/libnetwork/sandbox_store.go index 95f9581368..4b9e94132d 100644 --- a/daemon/libnetwork/sandbox_store.go +++ b/daemon/libnetwork/sandbox_store.go @@ -66,10 +66,7 @@ func (sbs *sbState) Index() uint64 { return sbs.dbIndex } - maxIndex := sb.dbIndex - if sbs.dbIndex > maxIndex { - maxIndex = sbs.dbIndex - } + maxIndex := max(sbs.dbIndex, sb.dbIndex) return maxIndex } diff --git a/daemon/list.go b/daemon/list.go index 56f2eadb02..4bac1ecd25 100644 --- a/daemon/list.go +++ b/daemon/list.go @@ -134,10 +134,7 @@ func (daemon *Daemon) Containers(ctx context.Context, config *backend.ContainerL // dispatch a set number of worker goroutines to do the jobs. We choose // log2(numContainers) workers to avoid creating too many goroutines // for large number of containers. - numWorkers := int(math.Log2(float64(numContainers))) - if numWorkers < 1 { - numWorkers = 1 - } + numWorkers := max(int(math.Log2(float64(numContainers))), 1) resultsMut := sync.Mutex{} results := make([]containertypes.Summary, numContainers) diff --git a/daemon/logger/copier.go b/daemon/logger/copier.go index 1e605e39ce..a946cc2a9b 100644 --- a/daemon/logger/copier.go +++ b/daemon/logger/copier.go @@ -78,10 +78,7 @@ func (c *Copier) copySrc(name string, src io.Reader) { return default: // Work out how much more data we are okay with reading this time. - upto := n + readSize - if upto > cap(buf) { - upto = cap(buf) - } + upto := min(n+readSize, cap(buf)) // Try to read that data. if upto > n { read, err := src.Read(buf[n:upto]) diff --git a/daemon/logger/splunk/splunk.go b/daemon/logger/splunk/splunk.go index 44d438703c..db6dad78a1 100644 --- a/daemon/logger/splunk/splunk.go +++ b/daemon/logger/splunk/splunk.go @@ -421,10 +421,7 @@ func (l *splunkLogger) postMessages(messages []*splunkMessage, lastChance bool) messagesLen := len(messages) for i := 0; i < messagesLen; i += l.postMessagesBatchSize { - upperBound := i + l.postMessagesBatchSize - if upperBound > messagesLen { - upperBound = messagesLen - } + upperBound := min(i+l.postMessagesBatchSize, messagesLen) if err := l.tryPostMessages(ctx, messages[i:upperBound]); err != nil { log.G(ctx).WithError(err).WithField("module", "logger/splunk").Warn("Error while sending logs") diff --git a/pkg/tailfile/tailfile.go b/pkg/tailfile/tailfile.go index aa39fb603d..25487d0dce 100644 --- a/pkg/tailfile/tailfile.go +++ b/pkg/tailfile/tailfile.go @@ -103,10 +103,7 @@ func NewTailReaderWithDelimiter(ctx context.Context, r SizeReaderAt, reqLines in func newScanner(r SizeReaderAt, delim []byte) *scanner { size := r.Size() - readSize := blockSize - if readSize > int(size) { - readSize = int(size) - } + readSize := min(blockSize, int(size)) // silly case... if len(delim) >= readSize/2 { readSize = len(delim)*2 + 2 @@ -178,10 +175,7 @@ func (s *scanner) Scan(ctx context.Context) bool { idx := s.idx - len(s.delim) if idx < 0 { - readSize := int(s.pos) - if readSize > len(s.buf) { - readSize = len(s.buf) - } + readSize := min(int(s.pos), len(s.buf)) if readSize < len(s.delim) { return false diff --git a/pkg/tailfile/tailfile_test.go b/pkg/tailfile/tailfile_test.go index aef9b31c49..d4645c7b4d 100644 --- a/pkg/tailfile/tailfile_test.go +++ b/pkg/tailfile/tailfile_test.go @@ -210,10 +210,7 @@ func TestNewTailReader(t *testing.T) { test := test t.Parallel() - maxLen := len(test.data) - if maxLen > 10 { - maxLen = 10 - } + maxLen := min(len(test.data), 10) s := strings.Join(test.data, string(delim)) if len(test.data) > 0 { From 3df05205f4cd707b4dc5bfc8358e084b12d7ad84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:26:55 +0100 Subject: [PATCH 07/13] modernize: Use range int MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added in Go 1.22 Signed-off-by: Paweł Gronowski --- daemon/builder/dockerfile/dispatchers.go | 2 +- .../internal/tarsum/tarsum_test.go | 2 +- daemon/command/daemon_test.go | 2 +- daemon/container/env_test.go | 2 +- daemon/container/view_test.go | 8 ++-- daemon/containerd/image_list_test.go | 4 +- daemon/events/events_test.go | 4 +- daemon/graphdriver/copy/copy_test.go | 6 +-- .../metadata/v2_metadata_service_test.go | 2 +- .../stream/bytespipe/bytespipe_test.go | 6 +-- daemon/internal/stream/unbuffered_test.go | 6 +-- daemon/internal/versions/compare.go | 2 +- daemon/libnetwork/bitmap/sequence_test.go | 4 +- .../cmd/networkdb-test/dbclient/ndbClient.go | 40 ++++++++--------- .../drivers/bridge/bridge_linux_test.go | 6 +-- daemon/libnetwork/etchosts/etchosts_test.go | 6 +-- .../ipams/defaultipam/allocator_test.go | 6 +-- .../ipams/defaultipam/parallel_test.go | 4 +- daemon/libnetwork/iptables/iptables_test.go | 2 +- daemon/libnetwork/libnetwork_internal_test.go | 4 +- daemon/libnetwork/netutils/utils_linux.go | 2 +- daemon/libnetwork/networkdb/networkdb_test.go | 44 +++++++++---------- daemon/libnetwork/nlwrap/nlwrap_linux.go | 2 +- daemon/libnetwork/osl/netlinkutil_linux.go | 2 +- daemon/logger/awslogs/cloudwatchlogs_test.go | 14 +++--- daemon/logger/copier_test.go | 10 ++--- daemon/logger/jsonfilelog/jsonfilelog_test.go | 2 +- daemon/logger/local/read.go | 2 +- .../loggerutils/cache/log_cache_test.go | 2 +- daemon/logger/loggerutils/sharedtemp_test.go | 6 +-- daemon/logger/ring_test.go | 8 ++-- daemon/logger/splunk/splunk_test.go | 12 ++--- daemon/names.go | 2 +- daemon/reload_test.go | 2 +- integration-cli/benchmark_test.go | 6 +-- integration-cli/daemon/daemon_swarm.go | 2 +- .../docker_api_exec_resize_test.go | 2 +- integration-cli/docker_api_logs_test.go | 4 +- .../docker_api_swarm_service_test.go | 10 ++--- integration-cli/docker_api_swarm_test.go | 10 ++--- integration-cli/docker_cli_attach_test.go | 2 +- integration-cli/docker_cli_build_test.go | 4 +- integration-cli/docker_cli_daemon_test.go | 2 +- integration-cli/docker_cli_exec_test.go | 6 +-- .../docker_cli_external_volume_driver_test.go | 2 +- integration-cli/docker_cli_history_test.go | 2 +- .../docker_cli_network_unix_test.go | 4 +- integration-cli/docker_cli_port_test.go | 6 +-- integration-cli/docker_cli_ps_test.go | 2 +- integration-cli/docker_cli_run_test.go | 6 +-- .../docker_cli_service_logs_test.go | 2 +- integration-cli/docker_cli_swarm_test.go | 6 +-- .../networking/port_mapping_linux_test.go | 2 +- .../plugin/logging/logging_linux_test.go | 2 +- integration/service/create_test.go | 2 +- integration/service/list_test.go | 2 +- internal/testutil/specialimage/emptyfs.go | 2 +- internal/testutil/specialimage/random.go | 2 +- pkg/tailfile/tailfile_test.go | 4 +- 59 files changed, 161 insertions(+), 161 deletions(-) diff --git a/daemon/builder/dockerfile/dispatchers.go b/daemon/builder/dockerfile/dispatchers.go index 3346018432..483e7f9d02 100644 --- a/daemon/builder/dockerfile/dispatchers.go +++ b/daemon/builder/dockerfile/dispatchers.go @@ -628,7 +628,7 @@ func parsePortSpec(rawPort string) ([]network.PortMap, error) { count := endPort - startPort + 1 ports := make([]network.PortMap, 0, count) - for i := uint16(0); i < count; i++ { + for i := range count { hPort := "" if hostPort != "" { hPort = strconv.Itoa(int(startHostPort + i)) diff --git a/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go b/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go index bd932ae3e9..706d325920 100644 --- a/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go +++ b/daemon/builder/remotecontext/internal/tarsum/tarsum_test.go @@ -302,7 +302,7 @@ func TestTarSumsReadSize(t *testing.T) { // Test always on the same layer (that is big enough) layer := testLayers[0] - for i := 0; i < 5; i++ { + for i := range 5 { reader, err := os.Open(layer.filename) if err != nil { t.Fatal(err) diff --git a/daemon/command/daemon_test.go b/daemon/command/daemon_test.go index c8ae36ccce..e494d2a2f6 100644 --- a/daemon/command/daemon_test.go +++ b/daemon/command/daemon_test.go @@ -296,7 +296,7 @@ func TestOtelMeterLeak(t *testing.T) { runtime.ReadMemStats(&before) const counters = 10 * 1000 * 1000 - for i := 0; i < counters; i++ { + for range counters { _, _ = meter.Int64Counter("bar") } diff --git a/daemon/container/env_test.go b/daemon/container/env_test.go index fb29205ef0..c1e64a25a4 100644 --- a/daemon/container/env_test.go +++ b/daemon/container/env_test.go @@ -41,7 +41,7 @@ func benchmarkReplaceOrAppendEnvValues(b *testing.B, extraEnv int) { if extraEnv > 0 { buf := make([]byte, 5) - for i := 0; i < extraEnv; i++ { + for range extraEnv { n, err := rand.Read(buf) assert.NilError(b, err) key := string(buf[:n]) diff --git a/daemon/container/view_test.go b/daemon/container/view_test.go index 198791c360..e4b9f47e66 100644 --- a/daemon/container/view_test.go +++ b/daemon/container/view_test.go @@ -347,7 +347,7 @@ func assertIndexGet(t *testing.T, snapshot *ViewDB, input, expectedResult string func BenchmarkDBAdd100(b *testing.B) { var testSet []string - for i := 0; i < 100; i++ { + for range 100 { testSet = append(testSet, stringid.GenerateRandomID()) } @@ -367,7 +367,7 @@ func BenchmarkDBAdd100(b *testing.B) { func BenchmarkDBGetByPrefix100(b *testing.B) { var testSet []string var testKeys []string - for i := 0; i < 100; i++ { + for range 100 { testSet = append(testSet, stringid.GenerateRandomID()) } db, err := NewViewDB() @@ -394,7 +394,7 @@ func BenchmarkDBGetByPrefix100(b *testing.B) { func BenchmarkDBGetByPrefix250(b *testing.B) { var testSet []string var testKeys []string - for i := 0; i < 250; i++ { + for range 250 { testSet = append(testSet, stringid.GenerateRandomID()) } db, err := NewViewDB() @@ -421,7 +421,7 @@ func BenchmarkDBGetByPrefix250(b *testing.B) { func BenchmarkDBGetByPrefix500(b *testing.B) { var testSet []string var testKeys []string - for i := 0; i < 500; i++ { + for range 500 { testSet = append(testSet, stringid.GenerateRandomID()) } db, err := NewViewDB() diff --git a/daemon/containerd/image_list_test.go b/daemon/containerd/image_list_test.go index fab797ac13..5b7c2c725b 100644 --- a/daemon/containerd/image_list_test.go +++ b/daemon/containerd/image_list_test.go @@ -49,7 +49,7 @@ func BenchmarkImageList(b *testing.B) { // Use constant seed for reproducibility src := rand.NewSource(1982731263716) - for i := 0; i < count; i++ { + for i := range count { platform := platforms.DefaultSpec() // 20% is other architecture than the host @@ -73,7 +73,7 @@ func BenchmarkImageList(b *testing.B) { } containersCount := r2 % maxContainerCount - for j := 0; j < containersCount; j++ { + for range containersCount { id := digest.FromString(desc.Name + strconv.Itoa(i)).String() target := desc.Target diff --git a/daemon/events/events_test.go b/daemon/events/events_test.go index d95f6e826d..e88ee1f997 100644 --- a/daemon/events/events_test.go +++ b/daemon/events/events_test.go @@ -74,7 +74,7 @@ func TestEventsLogTimeout(t *testing.T) { func TestLogEvents(t *testing.T) { e := New() - for i := 0; i < eventsLimit+16; i++ { + for i := range eventsLimit + 16 { num := strconv.Itoa(i) e.Log(events.Action("action_"+num), events.ContainerEventType, events.Actor{ ID: "cont_" + num, @@ -83,7 +83,7 @@ func TestLogEvents(t *testing.T) { } time.Sleep(50 * time.Millisecond) current, l, _ := e.Subscribe() - for i := 0; i < 10; i++ { + for i := range 10 { num := strconv.Itoa(i + eventsLimit + 16) e.Log(events.Action("action_"+num), events.ContainerEventType, events.Actor{ ID: "cont_" + num, diff --git a/daemon/graphdriver/copy/copy_test.go b/daemon/graphdriver/copy/copy_test.go index 1e8feb2c35..703877cc38 100644 --- a/daemon/graphdriver/copy/copy_test.go +++ b/daemon/graphdriver/copy/copy_test.go @@ -77,7 +77,7 @@ func TestCopyDir(t *testing.T) { } func randomMode(baseMode int) os.FileMode { - for i := 0; i < 7; i++ { + for i := range 7 { baseMode = baseMode | (1&rand.Intn(2))< i { diff --git a/daemon/libnetwork/bitmap/sequence_test.go b/daemon/libnetwork/bitmap/sequence_test.go index 427ea2bea8..0876f28431 100644 --- a/daemon/libnetwork/bitmap/sequence_test.go +++ b/daemon/libnetwork/bitmap/sequence_test.go @@ -923,7 +923,7 @@ func TestMethods(t *testing.T) { t.Fatalf("Unexpected sequence string: %s", hnd.head.toString()) } - for i := 0; i < 192; i++ { + for range 192 { _, err := hnd.SetAny(false) if err != nil { t.Fatal(err) @@ -1185,7 +1185,7 @@ func TestMarshalJSON(t *testing.T) { hnd := New(uint64(len(expected) * 8)) for i, c := range expected { - for j := 0; j < 8; j++ { + for j := range 8 { if c&(1< Date: Mon, 15 Dec 2025 18:27:23 +0100 Subject: [PATCH 08/13] reflect: Use `TypeFor` instead of `TypeOf` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added in Go 1.22 Signed-off-by: Paweł Gronowski --- daemon/config/config_test.go | 4 ++-- internal/test/suite/suite.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/daemon/config/config_test.go b/daemon/config/config_test.go index 2b1b9d6d4e..559131b690 100644 --- a/daemon/config/config_test.go +++ b/daemon/config/config_test.go @@ -468,7 +468,7 @@ type overwriteTransformer struct { } func (tf overwriteTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { - if typ == reflect.TypeOf(CommonConfig{}) { + if typ == reflect.TypeFor[CommonConfig]() { return func(dst, src reflect.Value) error { dst.FieldByName(tf.fieldName).Set(src.FieldByName(tf.fieldName)) return nil @@ -702,7 +702,7 @@ func TestConfigInvalidDNS(t *testing.T) { } func field(field string) cmp.Option { - tmp := reflect.TypeOf(Config{}) + tmp := reflect.TypeFor[Config]() ignoreFields := make([]string, 0, tmp.NumField()) for i := 0; i < tmp.NumField(); i++ { if tmp.Field(i).Name != field { diff --git a/internal/test/suite/suite.go b/internal/test/suite/suite.go index 4ec9973281..0338d6b125 100644 --- a/internal/test/suite/suite.go +++ b/internal/test/suite/suite.go @@ -16,7 +16,7 @@ import ( // TimeoutFlag is the flag to set a per-test timeout when running tests. Defaults to `-timeout`. var TimeoutFlag = flag.Duration("timeout", 0, "DO NOT USE") -var typTestingT = reflect.TypeOf(new(testing.T)) +var typTestingT = reflect.TypeFor[*testing.T]() // Run takes a testing suite and runs all of the tests attached to it. func Run(ctx context.Context, t *testing.T, suite any) { From 62ed24a87c337e91ea14990d526dd6b00cf0add2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:27:58 +0100 Subject: [PATCH 09/13] modernize: Use slices.Contains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- .../internal/tarsum/versioning_test.go | 8 ++------ daemon/daemon_linux.go | 7 +++---- daemon/internal/distribution/pull_v2.go | 7 +++---- daemon/libnetwork/controller.go | 7 +++---- daemon/libnetwork/iptables/firewalld.go | 14 ++++---------- daemon/libnetwork/network.go | 6 ++---- daemon/libnetwork/networkdb/cluster.go | 8 +++----- daemon/libnetwork/networkdb/delegate.go | 8 +++----- daemon/libnetwork/networkdb/networkdb.go | 7 +++---- daemon/list_test.go | 7 +++---- daemon/network.go | 7 +++---- daemon/oci_linux.go | 8 ++------ daemon/pkg/oci/caps/utils.go | 8 ++------ daemon/pkg/opts/opts.go | 8 ++------ daemon/pkg/plugin/v2/settable.go | 15 ++++----------- daemon/volume/service/store.go | 8 ++------ integration-cli/docker_cli_build_test.go | 16 ++++------------ pkg/plugins/plugins.go | 8 ++------ 18 files changed, 50 insertions(+), 107 deletions(-) diff --git a/daemon/builder/remotecontext/internal/tarsum/versioning_test.go b/daemon/builder/remotecontext/internal/tarsum/versioning_test.go index da7946f636..285d4f9480 100644 --- a/daemon/builder/remotecontext/internal/tarsum/versioning_test.go +++ b/daemon/builder/remotecontext/internal/tarsum/versioning_test.go @@ -4,6 +4,7 @@ import ( "archive/tar" "errors" "fmt" + "slices" "strings" "testing" @@ -96,12 +97,7 @@ func TestGetVersions(t *testing.T) { } func containsVersion(versions []Version, version Version) bool { - for _, v := range versions { - if v == version { - return true - } - } - return false + return slices.Contains(versions, version) } func TestSelectXattrsV1(t *testing.T) { diff --git a/daemon/daemon_linux.go b/daemon/daemon_linux.go index 5adbbad299..37259d65f8 100644 --- a/daemon/daemon_linux.go +++ b/daemon/daemon_linux.go @@ -7,6 +7,7 @@ import ( "io" "os" "regexp" + "slices" "strings" "sync" @@ -231,10 +232,8 @@ func supportsRecursivelyReadOnly(cfg *configStore, runtime string) error { if features == nil { return fmt.Errorf("rro is not supported by runtime %q: OCI features struct is not available", runtime) } - for _, s := range features.MountOptions { - if s == "rro" { - return nil - } + if slices.Contains(features.MountOptions, "rro") { + return nil } return fmt.Errorf("rro is not supported by runtime %q", runtime) } diff --git a/daemon/internal/distribution/pull_v2.go b/daemon/internal/distribution/pull_v2.go index 8a2f26899e..4156183d62 100644 --- a/daemon/internal/distribution/pull_v2.go +++ b/daemon/internal/distribution/pull_v2.go @@ -6,6 +6,7 @@ import ( "io" "os" "runtime" + "slices" "strings" "time" @@ -452,10 +453,8 @@ func (p *puller) validateMediaType(mediaType string) error { } else { allowedMediaTypes = defaultImageTypes } - for _, t := range allowedMediaTypes { - if mediaType == t { - return nil - } + if slices.Contains(allowedMediaTypes, mediaType) { + return nil } configClass := mediaTypeClasses[mediaType] diff --git a/daemon/libnetwork/controller.go b/daemon/libnetwork/controller.go index 637e46d4af..64d6d9f7fd 100644 --- a/daemon/libnetwork/controller.go +++ b/daemon/libnetwork/controller.go @@ -49,6 +49,7 @@ import ( "net" "path/filepath" "runtime" + "slices" "strings" "sync" "time" @@ -831,10 +832,8 @@ func (c *Controller) Networks(ctx context.Context) []*Network { // WalkNetworks uses the provided function to walk the Network(s) managed by this controller. func (c *Controller) WalkNetworks(walker NetworkWalker) { - for _, n := range c.Networks(context.TODO()) { - if walker(n) { - return - } + if slices.ContainsFunc(c.Networks(context.TODO()), walker) { + return } } diff --git a/daemon/libnetwork/iptables/firewalld.go b/daemon/libnetwork/iptables/firewalld.go index 5453d6c520..7c82e9dab4 100644 --- a/daemon/libnetwork/iptables/firewalld.go +++ b/daemon/libnetwork/iptables/firewalld.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "os" + "slices" "strings" "sync" "sync/atomic" @@ -177,10 +178,8 @@ func reloaded() { // OnReloaded add callback func OnReloaded(callback func()) { - for _, pf := range onReloaded { - if pf == &callback { - return - } + if slices.Contains(onReloaded, &callback) { + return } onReloaded = append(onReloaded, &callback) } @@ -366,10 +365,5 @@ type interfaceNotFound struct{ error } func (interfaceNotFound) NotFound() {} func contains(list []string, val string) bool { - for _, v := range list { - if v == val { - return true - } - } - return false + return slices.Contains(list, val) } diff --git a/daemon/libnetwork/network.go b/daemon/libnetwork/network.go index be7d82d6dc..ad87d74c03 100644 --- a/daemon/libnetwork/network.go +++ b/daemon/libnetwork/network.go @@ -1275,10 +1275,8 @@ func (n *Network) HasContainerAttachments() bool { // WalkEndpoints uses the provided function to walk the Endpoints. func (n *Network) WalkEndpoints(walker EndpointWalker) { - for _, e := range n.Endpoints() { - if walker(e) { - return - } + if slices.ContainsFunc(n.Endpoints(), walker) { + return } } diff --git a/daemon/libnetwork/networkdb/cluster.go b/daemon/libnetwork/networkdb/cluster.go index c356abf8d1..2ed3a2c619 100644 --- a/daemon/libnetwork/networkdb/cluster.go +++ b/daemon/libnetwork/networkdb/cluster.go @@ -9,6 +9,7 @@ import ( rnd "math/rand" "net" "net/netip" + "slices" "strings" "time" @@ -543,11 +544,8 @@ func (nDB *NetworkDB) bulkSyncTables() { updatedNetworks := make([]string, 0, len(networks)) for _, nid := range networks { var found bool - for _, completedNid := range completed { - if nid == completedNid { - found = true - break - } + if slices.Contains(completed, nid) { + found = true } if !found { diff --git a/daemon/libnetwork/networkdb/delegate.go b/daemon/libnetwork/networkdb/delegate.go index 198dc7bea6..85bdc37af5 100644 --- a/daemon/libnetwork/networkdb/delegate.go +++ b/daemon/libnetwork/networkdb/delegate.go @@ -3,6 +3,7 @@ package networkdb import ( "context" "net" + "slices" "time" "github.com/containerd/log" @@ -154,11 +155,8 @@ func (nDB *NetworkDB) handleTableEvent(tEvent *TableEvent, isBulkSync bool) bool // Check if the owner of the event is still part of the network nodes := nDB.networkNodes[tEvent.NetworkID] var nodePresent bool - for _, node := range nodes { - if node == tEvent.NodeName { - nodePresent = true - break - } + if slices.Contains(nodes, tEvent.NodeName) { + nodePresent = true } if !ok || network.leaving || !nodePresent { diff --git a/daemon/libnetwork/networkdb/networkdb.go b/daemon/libnetwork/networkdb/networkdb.go index 36b71d90c8..6b97bff2ff 100644 --- a/daemon/libnetwork/networkdb/networkdb.go +++ b/daemon/libnetwork/networkdb/networkdb.go @@ -9,6 +9,7 @@ import ( "math/rand/v2" "net/netip" "os" + "slices" "strings" "sync" "sync/atomic" @@ -730,10 +731,8 @@ func (nDB *NetworkDB) LeaveNetwork(nid string) error { // should hold the NetworkDB lock while calling this func (nDB *NetworkDB) addNetworkNode(nid string, nodeName string) { nodes := nDB.networkNodes[nid] - for _, node := range nodes { - if node == nodeName { - return - } + if slices.Contains(nodes, nodeName) { + return } nDB.networkNodes[nid] = append(nDB.networkNodes[nid], nodeName) diff --git a/daemon/list_test.go b/daemon/list_test.go index e389106577..f0d5c252ab 100644 --- a/daemon/list_test.go +++ b/daemon/list_test.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "testing" "time" @@ -72,10 +73,8 @@ func setupContainerWithName(t *testing.T, name string, daemon *Daemon) *containe func containerListContainsName(containers []containertypes.Summary, name string) bool { for _, ctr := range containers { - for _, containerName := range ctr.Names { - if containerName == name { - return true - } + if slices.Contains(ctr.Names, name) { + return true } } diff --git a/daemon/network.go b/daemon/network.go index 859d9af722..f42d6aa806 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -7,6 +7,7 @@ import ( "maps" "net" "net/netip" + "slices" "sort" "strconv" "strings" @@ -433,10 +434,8 @@ func (daemon *Daemon) pluginRefCount(driver, capability string, mode int) { // other capabilities can be ignored for now } - for _, d := range builtinDrivers { - if d == driver { - return - } + if slices.Contains(builtinDrivers, driver) { + return } if daemon.PluginStore != nil { diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index 237049ea20..445fd6a4da 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -6,6 +6,7 @@ import ( "maps" "os" "path/filepath" + "slices" "strconv" "strings" @@ -468,12 +469,7 @@ var ( // inSlice tests whether a string is contained in a slice of strings or not. // Comparison is case sensitive func inSlice(slice []string, s string) bool { - for _, ss := range slice { - if s == ss { - return true - } - } - return false + return slices.Contains(slice, s) } // withMounts sets the container's mounts diff --git a/daemon/pkg/oci/caps/utils.go b/daemon/pkg/oci/caps/utils.go index dc29fc429b..9bed97b297 100644 --- a/daemon/pkg/oci/caps/utils.go +++ b/daemon/pkg/oci/caps/utils.go @@ -2,6 +2,7 @@ package caps import ( "fmt" + "slices" "strings" "github.com/moby/moby/v2/errdefs" @@ -39,12 +40,7 @@ func knownCapabilities() map[string]*struct{} { // inSlice tests whether a string is contained in a slice of strings or not. func inSlice(slice []string, s string) bool { - for _, ss := range slice { - if s == ss { - return true - } - } - return false + return slices.Contains(slice, s) } const allCapabilities = "ALL" diff --git a/daemon/pkg/opts/opts.go b/daemon/pkg/opts/opts.go index 1ec148a13e..8268a6735e 100644 --- a/daemon/pkg/opts/opts.go +++ b/daemon/pkg/opts/opts.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "path" + "slices" "strings" "github.com/docker/go-units" @@ -94,12 +95,7 @@ func (opts *ListOpts) GetAllOrEmpty() []string { // Get checks the existence of the specified key. func (opts *ListOpts) Get(key string) bool { - for _, k := range *opts.values { - if k == key { - return true - } - } - return false + return slices.Contains(*opts.values, key) } // Len returns the amount of element in the slice. diff --git a/daemon/pkg/plugin/v2/settable.go b/daemon/pkg/plugin/v2/settable.go index 8d1d8ab460..f7695108af 100644 --- a/daemon/pkg/plugin/v2/settable.go +++ b/daemon/pkg/plugin/v2/settable.go @@ -3,6 +3,7 @@ package v2 import ( "errors" "fmt" + "slices" "strings" ) @@ -71,19 +72,11 @@ func (set *settable) isSettable(allowedSettableFields []string, settable []strin } } - isAllowed := false - for _, allowedSettableField := range allowedSettableFields { - if set.field == allowedSettableField { - isAllowed = true - break - } - } + isAllowed := slices.Contains(allowedSettableFields, set.field) if isAllowed { - for _, settableField := range settable { - if set.field == settableField { - return true, nil - } + if slices.Contains(settable, set.field) { + return true, nil } } diff --git a/daemon/volume/service/store.go b/daemon/volume/service/store.go index 8f6fb8a7be..7f6073a4fc 100644 --- a/daemon/volume/service/store.go +++ b/daemon/volume/service/store.go @@ -7,6 +7,7 @@ import ( "net" "os" "path/filepath" + "slices" "sync" "time" @@ -229,12 +230,7 @@ type VolumeStore struct { func filterByDriver(names []string) filterFunc { return func(v volume.Volume) bool { - for _, name := range names { - if name == v.DriverName() { - return true - } - } - return false + return slices.Contains(names, v.DriverName()) } } diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index c653c86c9c..343ddc9900 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -12,6 +12,7 @@ import ( "reflect" "regexp" "runtime" + "slices" "strconv" "strings" "testing" @@ -4357,13 +4358,7 @@ func (s *DockerCLIBuildSuite) TestBuildBuildTimeArgExpansion(c *testing.T) { var resArr []string inspectFieldAndUnmarshall(c, imgName, "Config.Env", &resArr) - found := false - for _, v := range resArr { - if fmt.Sprintf("%s=%s", envVar, envVal) == v { - found = true - break - } - } + found := slices.Contains(resArr, fmt.Sprintf("%s=%s", envVar, envVal)) if !found { c.Fatalf("Config.Env value mismatch. Expected to exist: %s=%s, got: %v", envVar, envVal, resArr) @@ -4707,11 +4702,8 @@ func (s *DockerCLIBuildSuite) TestBuildTagEvent(c *testing.T) { events := strings.Split(strings.TrimSpace(out), "\n") actions := eventActionsByIDAndType(c, events, imgName+":latest", "image") var foundTag bool - for _, a := range actions { - if a == "tag" { - foundTag = true - break - } + if slices.Contains(actions, "tag") { + foundTag = true } assert.Assert(c, foundTag, "No tag event found:\n%s", out) diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 1baa1a3465..8e2f76dc69 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -26,6 +26,7 @@ import ( "context" "errors" "fmt" + "slices" "sync" "time" @@ -193,12 +194,7 @@ func (p *Plugin) implements(kind string) bool { if p.Manifest == nil { return false } - for _, driver := range p.Manifest.Implements { - if driver == kind { - return true - } - } - return false + return slices.Contains(p.Manifest.Implements, kind) } func loadWithRetry(name string, retry bool) (*Plugin, error) { From 71fd582aa2c33fabcddcf6037444c4a3009e243d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:28:50 +0100 Subject: [PATCH 10/13] modernize: Use strings.Builder instead of string concatenation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- daemon/builder/dockerfile/dispatchers.go | 7 ++++--- daemon/internal/image/tarexport/load.go | 7 ++++--- daemon/libnetwork/diagnostic/server.go | 7 ++++--- daemon/libnetwork/diagnostic/types.go | 8 +++++--- .../bridge/internal/iptabler/iptabler_test.go | 6 +++--- .../internal/resolvconf/resolvconf_test.go | 10 +++++----- dockerversion/useragent.go | 9 +++++---- pkg/plugins/pluginrpc-gen/template.go | 13 +++++++------ 8 files changed, 37 insertions(+), 30 deletions(-) diff --git a/daemon/builder/dockerfile/dispatchers.go b/daemon/builder/dockerfile/dispatchers.go index 483e7f9d02..c70e3bcc0f 100644 --- a/daemon/builder/dockerfile/dispatchers.go +++ b/daemon/builder/dockerfile/dispatchers.go @@ -79,12 +79,13 @@ func dispatchLabel(ctx context.Context, d dispatchRequest, c *instructions.Label if d.state.runConfig.Labels == nil { d.state.runConfig.Labels = make(map[string]string) } - commitStr := "LABEL" + var commitStr strings.Builder + commitStr.WriteString("LABEL") for _, v := range c.Labels { d.state.runConfig.Labels[v.Key] = v.Value - commitStr += " " + v.String() + commitStr.WriteString(" " + v.String()) } - return d.builder.commit(ctx, d.state, commitStr) + return d.builder.commit(ctx, d.state, commitStr.String()) } // ADD foo /path diff --git a/daemon/internal/image/tarexport/load.go b/daemon/internal/image/tarexport/load.go index b86eef2ec1..6d7eaa4c0a 100644 --- a/daemon/internal/image/tarexport/load.go +++ b/daemon/internal/image/tarexport/load.go @@ -10,6 +10,7 @@ import ( "path/filepath" "reflect" "runtime" + "strings" "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" @@ -78,7 +79,7 @@ func (l *tarexporter) Load(ctx context.Context, inTar io.ReadCloser, outStream i } var parentLinks []parentLink - var imageIDsStr string + var imageIDsStr strings.Builder var imageRefCount int for _, m := range manifest { @@ -142,7 +143,7 @@ func (l *tarexporter) Load(ctx context.Context, inTar io.ReadCloser, outStream i if err != nil { return err } - imageIDsStr += fmt.Sprintf("Loaded image ID: %s\n", imgID) + imageIDsStr.WriteString(fmt.Sprintf("Loaded image ID: %s\n", imgID)) imageRefCount = 0 for _, repoTag := range m.RepoTags { @@ -172,7 +173,7 @@ func (l *tarexporter) Load(ctx context.Context, inTar io.ReadCloser, outStream i } if imageRefCount == 0 { - outStream.Write([]byte(imageIDsStr)) + outStream.Write([]byte(imageIDsStr.String())) } return nil diff --git a/daemon/libnetwork/diagnostic/server.go b/daemon/libnetwork/diagnostic/server.go index 51610e4b2e..12ec3f7586 100644 --- a/daemon/libnetwork/diagnostic/server.go +++ b/daemon/libnetwork/diagnostic/server.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "strconv" + "strings" "sync" "time" @@ -154,13 +155,13 @@ func (s *Server) help(w http.ResponseWriter, r *http.Request) { "url": r.URL.String(), }).Info("help done") - var result string + var result strings.Builder s.mu.Lock() for path := range s.handlers { - result += fmt.Sprintf("%s\n", path) + result.WriteString(fmt.Sprintf("%s\n", path)) } s.mu.Unlock() - _, _ = HTTPReply(w, CommandSucceed(&StringCmd{Info: result}), jsonOutput) + _, _ = HTTPReply(w, CommandSucceed(&StringCmd{Info: result.String()}), jsonOutput) } func ready(w http.ResponseWriter, r *http.Request) { diff --git a/daemon/libnetwork/diagnostic/types.go b/daemon/libnetwork/diagnostic/types.go index a800d4464b..690c85168f 100644 --- a/daemon/libnetwork/diagnostic/types.go +++ b/daemon/libnetwork/diagnostic/types.go @@ -3,6 +3,7 @@ package diagnostic import ( "fmt" "net/netip" + "strings" ) // StringInterface interface that has to be implemented by messages @@ -82,11 +83,12 @@ type TableObj struct { } func (t *TableObj) String() string { - output := fmt.Sprintf("total entries: %d\n", t.Length) + var output strings.Builder + output.WriteString(fmt.Sprintf("total entries: %d\n", t.Length)) for _, e := range t.Elements { - output += e.String() + output.WriteString(e.String()) } - return output + return output.String() } // PeerEntryObj entry in the networkdb peer table diff --git a/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler_test.go b/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler_test.go index e392d90891..0124938228 100644 --- a/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler_test.go +++ b/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler_test.go @@ -163,16 +163,16 @@ func testIptabler(t *testing.T, tn string, config firewaller.Config, netConfig f // - iptables-nft and iptables-legacy pick a different order when dumping all tables // - if the raw table isn't used it's not included in the all-tables dump but, once it's been used, it's always // included ... so, "cleaned" results would differ only in the empty raw table. - var dump string + var dump strings.Builder for _, table := range []string{"raw", "filter", "nat"} { res := icmd.RunCommand(cmd+"-save", "-t", table) assert.Assert(t, res.Error) if !en { name = tn + "/no" } - dump += res.Combined() + dump.WriteString(res.Combined()) } - assert.Check(t, golden.String(stripComments(dump), name+"__"+cmd+".golden")) + assert.Check(t, golden.String(stripComments(dump.String()), name+"__"+cmd+".golden")) } makePB := func(hip string, cip netip.Addr) types.PortBinding { diff --git a/daemon/libnetwork/internal/resolvconf/resolvconf_test.go b/daemon/libnetwork/internal/resolvconf/resolvconf_test.go index f029f13513..e1079653e4 100644 --- a/daemon/libnetwork/internal/resolvconf/resolvconf_test.go +++ b/daemon/libnetwork/internal/resolvconf/resolvconf_test.go @@ -199,19 +199,19 @@ func TestRCModify(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { tc := tc - var input string + var input strings.Builder if len(tc.inputNS) != 0 { for _, ns := range tc.inputNS { - input += "nameserver " + ns + "\n" + input.WriteString("nameserver " + ns + "\n") } } if len(tc.inputSearch) != 0 { - input += "search " + strings.Join(tc.inputSearch, " ") + "\n" + input.WriteString("search " + strings.Join(tc.inputSearch, " ") + "\n") } if len(tc.inputOptions) != 0 { - input += "options " + strings.Join(tc.inputOptions, " ") + "\n" + input.WriteString("options " + strings.Join(tc.inputOptions, " ") + "\n") } - rc, err := Parse(bytes.NewBufferString(input), "") + rc, err := Parse(bytes.NewBufferString(input.String()), "") assert.NilError(t, err) assert.Check(t, is.DeepEqual(a2s(rc.NameServers()), tc.inputNS, cmpopts.EquateEmpty())) assert.Check(t, is.DeepEqual(rc.Search(), tc.inputSearch)) diff --git a/dockerversion/useragent.go b/dockerversion/useragent.go index 23eca2ddab..5762bce43d 100644 --- a/dockerversion/useragent.go +++ b/dockerversion/useragent.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "runtime" + "strings" "sync" "github.com/moby/moby/v2/pkg/parsers/kernel" @@ -80,19 +81,19 @@ const charsToEscape = `();\` // escapeStr returns s with every rune in charsToEscape escaped by a backslash func escapeStr(s string) string { - var ret string + var ret strings.Builder for _, currRune := range s { appended := false for _, escapableRune := range charsToEscape { if currRune == escapableRune { - ret += `\` + string(currRune) + ret.WriteString(`\` + string(currRune)) appended = true break } } if !appended { - ret += string(currRune) + ret.WriteRune(currRune) } } - return ret + return ret.String() } diff --git a/pkg/plugins/pluginrpc-gen/template.go b/pkg/plugins/pluginrpc-gen/template.go index 9bb1266bd7..5a1db851c2 100644 --- a/pkg/plugins/pluginrpc-gen/template.go +++ b/pkg/plugins/pluginrpc-gen/template.go @@ -16,19 +16,20 @@ func printArgs(args []fnArg) string { } func buildImports(specs []importSpec) string { - imports := ` + var imports strings.Builder + imports.WriteString(` import( "errors" "time" "github.com/moby/moby/v2/pkg/plugins" -` +`) for _, i := range specs { - imports += "\t" + i.String() + "\n" + imports.WriteString("\t" + i.String() + "\n") } - imports += `) -` - return imports + imports.WriteString(`) +`) + return imports.String() } func marshalType(t string) string { From 6c5233e1098dc689b2e665087780695ac8864e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:32:55 +0100 Subject: [PATCH 11/13] modernize: Use `strings.CutSuffix` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added in Go 1.20 Signed-off-by: Paweł Gronowski --- daemon/containerd/image_list.go | 4 ++-- daemon/containerd/image_push.go | 2 +- daemon/info_unix.go | 8 ++++---- daemon/libnetwork/osl/namespace_linux.go | 4 ++-- daemon/volume/local/local.go | 8 ++++---- pkg/parsers/operatingsystem/operatingsystem_linux.go | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/daemon/containerd/image_list.go b/daemon/containerd/image_list.go index c8941c5b08..562542825a 100644 --- a/daemon/containerd/image_list.go +++ b/daemon/containerd/image_list.go @@ -634,8 +634,8 @@ func setupLabelFilter(ctx context.Context, store content.Store, fltrs filters.Ar negate := strings.HasSuffix(fltrName, "!") // If filter value is key!=value then flip the above. - if strings.HasSuffix(k, "!") { - k = strings.TrimSuffix(k, "!") + if before, ok := strings.CutSuffix(k, "!"); ok { + k = before negate = !negate } diff --git a/daemon/containerd/image_push.go b/daemon/containerd/image_push.go index 0248bb6741..03396abb5b 100644 --- a/daemon/containerd/image_push.go +++ b/daemon/containerd/image_push.go @@ -403,7 +403,7 @@ func extractDistributionSources(labels map[string]string) []distributionSource { // Check if this blob has a distributionSource label // if yes, read it as source for k, v := range labels { - if reg := strings.TrimPrefix(k, containerdlabels.LabelDistributionSource); reg != k { + if reg, ok := strings.CutPrefix(k, containerdlabels.LabelDistributionSource); ok { for repo := range strings.SplitSeq(v, ",") { ref, err := reference.ParseNamed(reg + "/" + repo) if err != nil { diff --git a/daemon/info_unix.go b/daemon/info_unix.go index 5108cef844..6b05706021 100644 --- a/daemon/info_unix.go +++ b/daemon/info_unix.go @@ -343,8 +343,8 @@ func parseInitVersion(v string) (version string, commit string, _ error) { } } parts[0] = strings.TrimSpace(parts[0]) - if strings.HasPrefix(parts[0], "tini version ") { - version = strings.TrimPrefix(parts[0], "tini version ") + if after, ok := strings.CutPrefix(parts[0], "tini version "); ok { + version = after } if version == "" && commit == "" { return "", "", errors.Errorf("unknown output format: %s", v) @@ -369,8 +369,8 @@ func parseRuntimeVersion(v string) (runtime, version, commit string, _ error) { version = strings.TrimSpace(s[len(s)-1]) continue } - if strings.HasPrefix(line, "commit:") { - commit = strings.TrimSpace(strings.TrimPrefix(line, "commit:")) + if after, ok := strings.CutPrefix(line, "commit:"); ok { + commit = strings.TrimSpace(after) continue } } diff --git a/daemon/libnetwork/osl/namespace_linux.go b/daemon/libnetwork/osl/namespace_linux.go index cff4b525d1..0139c3f359 100644 --- a/daemon/libnetwork/osl/namespace_linux.go +++ b/daemon/libnetwork/osl/namespace_linux.go @@ -76,8 +76,8 @@ func GenerateKey(containerID string) string { for _, v := range dir { id := v.Name() - if strings.HasSuffix(id, containerID[:maxLen-1]) { - indexStr = strings.TrimSuffix(id, containerID[:maxLen-1]) + if before, ok := strings.CutSuffix(id, containerID[:maxLen-1]); ok { + indexStr = before tmpindex, err := strconv.Atoi(indexStr) if err != nil { return "" diff --git a/daemon/volume/local/local.go b/daemon/volume/local/local.go index 75d7cdddec..c3b9380f8b 100644 --- a/daemon/volume/local/local.go +++ b/daemon/volume/local/local.go @@ -420,8 +420,8 @@ func (v *localVolume) LiveRestoreVolume(ctx context.Context, _ string) error { // getAddress finds out address/hostname from options func getAddress(opts string) string { for opt := range strings.SplitSeq(opts, ",") { - if strings.HasPrefix(opt, "addr=") { - return strings.TrimPrefix(opt, "addr=") + if after, ok := strings.CutPrefix(opt, "addr="); ok { + return after } } return "" @@ -430,8 +430,8 @@ func getAddress(opts string) string { // getPassword finds out a password from options func getPassword(opts string) string { for opt := range strings.SplitSeq(opts, ",") { - if strings.HasPrefix(opt, "password=") { - return strings.TrimPrefix(opt, "password=") + if after, ok := strings.CutPrefix(opt, "password="); ok { + return after } } return "" diff --git a/pkg/parsers/operatingsystem/operatingsystem_linux.go b/pkg/parsers/operatingsystem/operatingsystem_linux.go index 1492f8a4d4..ad0a6d11a3 100644 --- a/pkg/parsers/operatingsystem/operatingsystem_linux.go +++ b/pkg/parsers/operatingsystem/operatingsystem_linux.go @@ -56,8 +56,8 @@ func getValueFromOsRelease(key string) (string, error) { scanner := bufio.NewScanner(osReleaseFile) for scanner.Scan() { line := scanner.Text() - if strings.HasPrefix(line, key+"=") { - value = strings.TrimPrefix(line, key+"=") + if after, ok := strings.CutPrefix(line, key+"="); ok { + value = after value = strings.Trim(value, `"' `) // remove leading/trailing quotes and whitespace } } From 51d197450097b1f06eb9b2e2086b1f55c23a2e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Mon, 15 Dec 2025 18:33:38 +0100 Subject: [PATCH 12/13] daemon/cluster/test: Use `t.Context()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- daemon/cluster/executor/container/adapter_test.go | 4 +--- daemon/cluster/executor/container/health_test.go | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/daemon/cluster/executor/container/adapter_test.go b/daemon/cluster/executor/container/adapter_test.go index 3e34a9d4fa..8a37deb2b0 100644 --- a/daemon/cluster/executor/container/adapter_test.go +++ b/daemon/cluster/executor/container/adapter_test.go @@ -1,7 +1,6 @@ package container import ( - "context" "testing" "time" @@ -71,8 +70,7 @@ func TestWaitNodeAttachment(t *testing.T) { } // create a context to do call the method with - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() // create a channel to allow the goroutine that we run the method call in // to signal that it's done. diff --git a/daemon/cluster/executor/container/health_test.go b/daemon/cluster/executor/container/health_test.go index f79f56dc3b..da84a7e9cf 100644 --- a/daemon/cluster/executor/container/health_test.go +++ b/daemon/cluster/executor/container/health_test.go @@ -3,7 +3,6 @@ package container import ( - "context" "errors" "testing" "time" @@ -59,8 +58,7 @@ func TestHealthStates(t *testing.T) { } errChan := make(chan error, 1) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() // fire checkHealth go func() { From 0ae3f972adb6b346cee2e2e9937b7812170f9219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Tue, 16 Dec 2025 13:06:20 +0100 Subject: [PATCH 13/13] daemon: Simplify slices.Contains usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecessary intermediate variables and helper functions when using slices.Contains. Signed-off-by: Paweł Gronowski --- daemon/libnetwork/networkdb/cluster.go | 7 +------ daemon/libnetwork/networkdb/delegate.go | 5 +---- daemon/libnetwork/networkdb/networkdb.go | 3 +-- daemon/oci_linux.go | 8 +------- daemon/oci_linux_test.go | 3 ++- daemon/pkg/oci/caps/utils.go | 13 ++++--------- daemon/pkg/oci/caps/utils_linux.go | 3 ++- 7 files changed, 12 insertions(+), 30 deletions(-) diff --git a/daemon/libnetwork/networkdb/cluster.go b/daemon/libnetwork/networkdb/cluster.go index 2ed3a2c619..3c7ceb7c34 100644 --- a/daemon/libnetwork/networkdb/cluster.go +++ b/daemon/libnetwork/networkdb/cluster.go @@ -543,12 +543,7 @@ func (nDB *NetworkDB) bulkSyncTables() { // successfully completed bulk sync in this iteration. updatedNetworks := make([]string, 0, len(networks)) for _, nid := range networks { - var found bool - if slices.Contains(completed, nid) { - found = true - } - - if !found { + if !slices.Contains(completed, nid) { updatedNetworks = append(updatedNetworks, nid) } } diff --git a/daemon/libnetwork/networkdb/delegate.go b/daemon/libnetwork/networkdb/delegate.go index 85bdc37af5..9b363eb545 100644 --- a/daemon/libnetwork/networkdb/delegate.go +++ b/daemon/libnetwork/networkdb/delegate.go @@ -154,10 +154,7 @@ func (nDB *NetworkDB) handleTableEvent(tEvent *TableEvent, isBulkSync bool) bool network, ok := nDB.thisNodeNetworks[tEvent.NetworkID] // Check if the owner of the event is still part of the network nodes := nDB.networkNodes[tEvent.NetworkID] - var nodePresent bool - if slices.Contains(nodes, tEvent.NodeName) { - nodePresent = true - } + nodePresent := slices.Contains(nodes, tEvent.NodeName) if !ok || network.leaving || !nodePresent { // I'm out of the network OR the event owner is not anymore part of the network so do not propagate diff --git a/daemon/libnetwork/networkdb/networkdb.go b/daemon/libnetwork/networkdb/networkdb.go index 6b97bff2ff..3e077b9cb5 100644 --- a/daemon/libnetwork/networkdb/networkdb.go +++ b/daemon/libnetwork/networkdb/networkdb.go @@ -730,8 +730,7 @@ func (nDB *NetworkDB) LeaveNetwork(nid string) error { // in the passed network only if it is not already present. Caller // should hold the NetworkDB lock while calling this func (nDB *NetworkDB) addNetworkNode(nid string, nodeName string) { - nodes := nDB.networkNodes[nid] - if slices.Contains(nodes, nodeName) { + if slices.Contains(nDB.networkNodes[nid], nodeName) { return } diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index 445fd6a4da..0c8f282138 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -466,12 +466,6 @@ var ( } ) -// inSlice tests whether a string is contained in a slice of strings or not. -// Comparison is case sensitive -func inSlice(slice []string, s string) bool { - return slices.Contains(slice, s) -} - // withMounts sets the container's mounts func withMounts(daemon *Daemon, daemonCfg *configStore, c *container.Container, mounts []container.Mount) coci.SpecOpts { return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error { @@ -641,7 +635,7 @@ func withMounts(daemon *Daemon, daemonCfg *configStore, c *container.Container, continue } if _, ok := userMounts[m.Destination]; !ok { - if !inSlice(m.Options, "ro") { + if !slices.Contains(m.Options, "ro") { s.Mounts[i].Options = append(s.Mounts[i].Options, "ro") } } diff --git a/daemon/oci_linux_test.go b/daemon/oci_linux_test.go index 8a6320f590..9e2c361a83 100644 --- a/daemon/oci_linux_test.go +++ b/daemon/oci_linux_test.go @@ -4,6 +4,7 @@ import ( "context" "os" "path/filepath" + "slices" "testing" "github.com/google/go-cmp/cmp/cmpopts" @@ -119,7 +120,7 @@ func TestIpcPrivateVsReadonly(t *testing.T) { if m.Destination != "/dev/shm" { continue } - assert.Check(t, is.Equal(false, inSlice(m.Options, "ro"))) + assert.Check(t, is.Equal(false, slices.Contains(m.Options, "ro"))) } } diff --git a/daemon/pkg/oci/caps/utils.go b/daemon/pkg/oci/caps/utils.go index 9bed97b297..aa3513e808 100644 --- a/daemon/pkg/oci/caps/utils.go +++ b/daemon/pkg/oci/caps/utils.go @@ -38,11 +38,6 @@ func knownCapabilities() map[string]*struct{} { return knownCaps } -// inSlice tests whether a string is contained in a slice of strings or not. -func inSlice(slice []string, s string) bool { - return slices.Contains(slice, s) -} - const allCapabilities = "ALL" // NormalizeLegacyCapabilities normalizes, and validates CapAdd/CapDrop capabilities @@ -99,20 +94,20 @@ func TweakCapabilities(basics, adds, drops []string, privileged bool) ([]string, var caps []string switch { - case inSlice(capAdd, allCapabilities): + case slices.Contains(capAdd, allCapabilities): // Add all capabilities except ones on capDrop for _, c := range GetAllCapabilities() { - if !inSlice(capDrop, c) { + if !slices.Contains(capDrop, c) { caps = append(caps, c) } } - case inSlice(capDrop, allCapabilities): + case slices.Contains(capDrop, allCapabilities): // "Drop" all capabilities; use what's in capAdd instead caps = capAdd default: // First drop some capabilities for _, c := range basics { - if !inSlice(capDrop, c) { + if !slices.Contains(capDrop, c) { caps = append(caps, c) } } diff --git a/daemon/pkg/oci/caps/utils_linux.go b/daemon/pkg/oci/caps/utils_linux.go index e40b84b5fe..da90ef68a8 100644 --- a/daemon/pkg/oci/caps/utils_linux.go +++ b/daemon/pkg/oci/caps/utils_linux.go @@ -2,6 +2,7 @@ package caps import ( "context" + "slices" "sync" ccaps "github.com/containerd/containerd/v2/pkg/cap" @@ -27,7 +28,7 @@ func initCaps() { // old (pre-detection) behavior, and prevents creating containers with // no capabilities. The OCI runtime or kernel may still refuse capa- // bilities that are not available, and produce an error in that case. - if len(curCaps) > 0 && !inSlice(curCaps, capName) { + if len(curCaps) > 0 && !slices.Contains(curCaps, capName) { knownCaps[capName] = nil continue }