go fix for go1.26

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2026-08-28 21:21:35 +02:00
parent 8eb66b47e3
commit be9ca38f8b
22 changed files with 99 additions and 120 deletions
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package manager
import (
@@ -167,8 +170,7 @@ func (p *Plugin) RunHook(ctx context.Context, hookData hooks.Request) ([]byte, e
out, err := pCmd.Output()
if err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
if _, ok := errors.AsType[*exec.ExitError](err); ok {
return nil, wrapAsPluginError(err, "plugin hook subcommand exited unsuccessfully")
}
return nil, wrapAsPluginError(err, "failed to execute plugin hook subcommand: "+pCmd.String())
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package plugin
import (
@@ -97,8 +100,7 @@ func Run(makeCmd func(command.Cli) *cobra.Command, meta metadata.Metadata, ops .
plugin := makeCmd(dockerCLI)
if err := RunPlugin(dockerCLI, plugin, meta); err != nil {
var stErr cli.StatusError
if errors.As(err, &stErr) {
if stErr, ok := errors.AsType[cli.StatusError](err); ok {
// StatusError should only be used for errors, and all errors should
// have a non-zero exit status, so never exit with 0
if stErr.StatusCode == 0 { // FIXME(thaJeztah): this should never be used with a zero status-code. Check if we do this anywhere.
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package container
import (
@@ -169,8 +172,7 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er
}
}
if attachErr := <-cErr; attachErr != nil {
var escapeError term.EscapeError
if errors.As(attachErr, &escapeError) {
if _, ok := errors.AsType[term.EscapeError](attachErr); ok {
// The user entered the detach escape sequence.
return nil
}
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package context
import (
@@ -69,8 +72,7 @@ func parseBool(config map[string]string, name string) (bool, error) {
}
res, err := strconv.ParseBool(strVal)
if err != nil {
var nErr *strconv.NumError
if errors.As(err, &nErr) {
if nErr, ok := errors.AsType[*strconv.NumError](err); ok {
return res, fmt.Errorf("%s: parsing %q: %w", name, nErr.Num, nErr.Err)
}
return res, fmt.Errorf("%s: %w", name, err)
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package image
import (
@@ -364,8 +367,7 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
err = jsonstream.Display(ctx, response.Body, streams.NewOut(buildBuff), jsonstream.WithAuxCallback(aux))
if err != nil {
var jerr *jsonstream.JSONError
if errors.As(err, &jerr) {
if jerr, ok := errors.AsType[*jsonstream.JSONError](err); ok {
// If no error code is set, default to 1
if jerr.Code == 0 {
jerr.Code = 1
+6 -10
View File
@@ -189,8 +189,6 @@ func TestNetworkCreateWithFlags(t *testing.T) {
// TestNetworkCreateIPv4 verifies behavior of the "--ipv4" option. This option
// is an optional bool, and must default to "nil", not "true" or "false".
func TestNetworkCreateIPv4(t *testing.T) {
boolPtr := func(val bool) *bool { return &val }
tests := []struct {
doc, name string
flags []string
@@ -205,19 +203,19 @@ func TestNetworkCreateIPv4(t *testing.T) {
doc: "IPv4 enabled",
name: "ipv4-enabled",
flags: []string{"--ipv4=true"},
expected: boolPtr(true),
expected: new(true),
},
{
doc: "IPv4 enabled (shorthand)",
name: "ipv4-enabled-shorthand",
flags: []string{"--ipv4"},
expected: boolPtr(true),
expected: new(true),
},
{
doc: "IPv4 disabled",
name: "ipv4-disabled",
flags: []string{"--ipv4=false"},
expected: boolPtr(false),
expected: new(false),
},
}
@@ -243,8 +241,6 @@ func TestNetworkCreateIPv4(t *testing.T) {
// TestNetworkCreateIPv6 verifies behavior of the "--ipv6" option. This option
// is an optional bool, and must default to "nil", not "true" or "false".
func TestNetworkCreateIPv6(t *testing.T) {
strPtr := func(val bool) *bool { return &val }
tests := []struct {
doc, name string
flags []string
@@ -259,19 +255,19 @@ func TestNetworkCreateIPv6(t *testing.T) {
doc: "IPV6 enabled",
name: "ipv6-enabled",
flags: []string{"--ipv6=true"},
expected: strPtr(true),
expected: new(true),
},
{
doc: "IPV6 enabled (shorthand)",
name: "ipv6-enabled-shorthand",
flags: []string{"--ipv6"},
expected: strPtr(true),
expected: new(true),
},
{
doc: "IPV6 disabled",
name: "ipv6-disabled",
flags: []string{"--ipv6=false"},
expected: strPtr(false),
expected: new(false),
},
}
+1 -2
View File
@@ -29,8 +29,7 @@ func loadComposeFile(streams command.Streams, opts deployOptions) (*composetypes
config, err := loader.Load(configDetails)
if err != nil {
var fpe *loader.ForbiddenPropertiesError
if errors.As(err, &fpe) {
if fpe, ok := errors.AsType[*loader.ForbiddenPropertiesError](err); ok {
// this error is intentionally formatted multi-line
return nil, fmt.Errorf("compose file contains unsupported options:\n\n%s\n", propertyWarnings(fpe.Properties)) //nolint:staticcheck // ignore ST1005
}
+3 -8
View File
@@ -399,7 +399,7 @@ func convertFileObject(
}
mode := config.Mode
if mode == nil {
mode = uint32Ptr(0o444)
mode = new(uint32(0o444))
}
return swarmReferenceObject{
@@ -413,10 +413,6 @@ func convertFileObject(
}, nil
}
func uint32Ptr(value uint32) *uint32 {
return &value
}
// convertExtraHosts converts <host>:<ip> mappings to SwarmKit notation:
// "IP-address hostname(s)". The original order of mappings is preserved.
func convertExtraHosts(extraHosts composetypes.HostsList) []string {
@@ -501,8 +497,7 @@ func convertRestartPolicy(restart string, restartPolicy *composetypes.RestartPol
if i <= 0 {
return nil
}
p := uint64(i)
return &p
return new(uint64(i))
}
switch policy.Name {
@@ -529,7 +524,7 @@ func convertUpdateConfig(source *composetypes.UpdateConfig) *swarm.UpdateConfig
if source == nil {
return nil
}
parallel := uint64(1)
var parallel uint64 = 1
if source.Parallelism != nil {
parallel = *source.Parallelism
}
+4 -8
View File
@@ -66,14 +66,10 @@ func TestConvertRestartPolicy(t *testing.T) {
}
}
func strPtr(val string) *string {
return &val
}
func TestConvertEnvironment(t *testing.T) {
source := map[string]*string{
"foo": strPtr("bar"),
"key": strPtr("value"),
"foo": new("bar"),
"key": new("value"),
}
env := convertEnvironment(source)
assert.Check(t, is.DeepEqual([]string{"foo=bar", "key=value"}, env))
@@ -81,7 +77,7 @@ func TestConvertEnvironment(t *testing.T) {
func TestConvertEnvironmentWhenNilValueExists(t *testing.T) {
source := map[string]*string{
"key": strPtr("value"),
"key": new("value"),
"keyWithNoValue": nil,
}
env := convertEnvironment(source)
@@ -466,7 +462,7 @@ func TestConvertFileObject(t *testing.T) {
Target: "target",
UID: "user",
GID: "group",
Mode: uint32Ptr(0o644),
Mode: new(uint32(0o644)),
}
swarmRef, err := convertFileObject(namespace, config, lookupConfig)
assert.NilError(t, err)
+19 -19
View File
@@ -36,7 +36,7 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
Build: types.BuildConfig{
Context: "./dir",
Dockerfile: "Dockerfile",
Args: map[string]*string{"foo": strPtr("bar")},
Args: map[string]*string{"foo": new("bar")},
Target: "foo",
Network: "foo",
CacheFrom: []string{"foo", "bar"},
@@ -59,17 +59,17 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
Target: "/my_config",
UID: "103",
GID: "103",
Mode: uint32Ptr(0o440),
Mode: new(uint32(0o440)),
},
},
ContainerName: "my-web-container",
DependsOn: []string{"db", "redis"},
Deploy: types.DeployConfig{
Mode: "replicated",
Replicas: uint64Ptr(6),
Replicas: new(uint64(6)),
Labels: map[string]string{"FOO": "BAR"},
RollbackConfig: &types.UpdateConfig{
Parallelism: uint64Ptr(3),
Parallelism: new(uint64(3)),
Delay: types.Duration(10 * time.Second),
FailureAction: "continue",
Monitor: types.Duration(60 * time.Second),
@@ -77,7 +77,7 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
Order: "start-first",
},
UpdateConfig: &types.UpdateConfig{
Parallelism: uint64Ptr(3),
Parallelism: new(uint64(3)),
Delay: types.Duration(10 * time.Second),
FailureAction: "continue",
Monitor: types.Duration(60 * time.Second),
@@ -111,9 +111,9 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
},
RestartPolicy: &types.RestartPolicy{
Condition: "on-failure",
Delay: durationPtr(5 * time.Second),
MaxAttempts: uint64Ptr(3),
Window: durationPtr(2 * time.Minute),
Delay: new(types.Duration(5 * time.Second)),
MaxAttempts: new(uint64(3)),
Window: new(types.Duration(2 * time.Minute)),
},
Placement: types.Placement{
Constraints: []string{"node=foo"},
@@ -132,10 +132,10 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
DomainName: "foo.com",
Entrypoint: []string{"/code/entrypoint.sh", "-p", "3000"},
Environment: map[string]*string{
"FOO": strPtr("foo_from_env_file"),
"BAR": strPtr("bar_from_env_file_2"),
"BAZ": strPtr("baz_from_service_def"),
"QUX": strPtr("qux_from_environment"),
"FOO": new("foo_from_env_file"),
"BAR": new("bar_from_env_file_2"),
"BAZ": new("baz_from_service_def"),
"QUX": new("qux_from_environment"),
},
EnvFile: []string{
"./example1.env",
@@ -158,11 +158,11 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
},
HealthCheck: &types.HealthCheckConfig{
Test: types.HealthCheckTest([]string{"CMD-SHELL", "echo \"hello world\""}),
Interval: durationPtr(10 * time.Second),
Timeout: durationPtr(1 * time.Second),
Retries: uint64Ptr(5),
StartPeriod: durationPtr(15 * time.Second),
StartInterval: durationPtr(1 * time.Second),
Interval: new(types.Duration(10 * time.Second)),
Timeout: new(types.Duration(1 * time.Second)),
Retries: new(uint64(5)),
StartPeriod: new(types.Duration(15 * time.Second)),
StartInterval: new(types.Duration(1 * time.Second)),
},
Hostname: "foo",
Image: "redis",
@@ -348,7 +348,7 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
Target: "my_secret",
UID: "103",
GID: "103",
Mode: uint32Ptr(0o440),
Mode: new(uint32(0o440)),
},
},
SecurityOpt: []string{
@@ -357,7 +357,7 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
},
StdinOpen: true,
StopSignal: "SIGUSR1",
StopGracePeriod: durationPtr(20 * time.Second),
StopGracePeriod: new(types.Duration(20 * time.Second)),
Sysctls: map[string]string{
"net.core.somaxconn": "1024",
"net.ipv4.tcp_syncookies": "0",
+16 -34
View File
@@ -9,7 +9,6 @@ import (
"runtime"
"sort"
"testing"
"time"
"github.com/docker/cli/cli/compose/types"
"github.com/google/go-cmp/cmp/cmpopts"
@@ -179,10 +178,6 @@ var samplePortsConfig = []types.ServicePortConfig{
},
}
func strPtr(val string) *string {
return &val
}
var sampleConfig = types.Config{
Version: "3.13",
Services: []types.ServiceConfig{
@@ -197,7 +192,7 @@ var sampleConfig = types.Config{
{
Name: "bar",
Image: "busybox",
Environment: map[string]*string{"FOO": strPtr("1")},
Environment: map[string]*string{"FOO": new("1")},
Networks: map[string]*types.ServiceNetworkConfig{
"with_ipam": nil,
},
@@ -530,10 +525,10 @@ services:
assert.NilError(t, err)
expected := types.MappingWithEquals{
"FOO": strPtr("1"),
"BAR": strPtr("2"),
"BAZ": strPtr("2.5"),
"QUX": strPtr("qux"),
"FOO": new("1"),
"BAR": new("2"),
"BAZ": new("2.5"),
"QUX": new("qux"),
"QUUX": nil,
}
@@ -685,31 +680,31 @@ networks:
Configs: []types.ServiceConfigObjConfig{
{
Source: "appconfig",
Mode: uint32Ptr(555),
Mode: new(uint32(555)),
},
},
Secrets: []types.ServiceSecretConfig{
{
Source: "super",
Mode: uint32Ptr(555),
Mode: new(uint32(555)),
},
},
HealthCheck: &types.HealthCheckConfig{
Retries: uint64Ptr(555),
Retries: new(uint64(555)),
Disable: true,
},
Deploy: types.DeployConfig{
Replicas: uint64Ptr(555),
Replicas: new(uint64(555)),
UpdateConfig: &types.UpdateConfig{
Parallelism: uint64Ptr(555),
Parallelism: new(uint64(555)),
MaxFailureRatio: 3.14,
},
RollbackConfig: &types.UpdateConfig{
Parallelism: uint64Ptr(555),
Parallelism: new(uint64(555)),
MaxFailureRatio: 3.14,
},
RestartPolicy: &types.RestartPolicy{
MaxAttempts: uint64Ptr(555),
MaxAttempts: new(uint64(555)),
},
Placement: types.Placement{
MaxReplicas: 555,
@@ -798,10 +793,10 @@ services:
- example2.env
`))
expectedEnvironmentMap := types.MappingWithEquals{
"FOO": strPtr("foo_from_env_file"),
"BAZ": strPtr("baz_from_env_file"),
"BAR": strPtr("bar_from_env_file_2"), // Original value is overwritten by example2.env
"QUX": strPtr("quz_from_env_file_2"),
"FOO": new("foo_from_env_file"),
"BAZ": new("baz_from_env_file"),
"BAR": new("bar_from_env_file_2"), // Original value is overwritten by example2.env
"QUX": new("quz_from_env_file_2"),
}
assert.NilError(t, err)
configDetails := buildConfigDetails(dict, nil)
@@ -957,19 +952,6 @@ volumes:
assert.Check(t, is.ErrorContains(err, `external_volume`))
}
func durationPtr(value time.Duration) *types.Duration {
result := types.Duration(value)
return &result
}
func uint64Ptr(value uint64) *uint64 {
return &value
}
func uint32Ptr(value uint32) *uint32 {
return &value
}
func TestFullExample(t *testing.T) {
skip.If(t, runtime.GOOS == "windows", "FIXME: substitutes platform-specific HOME-dirs and requires platform-specific golden files; see https://github.com/docker/cli/pull/4610")
+7 -7
View File
@@ -920,8 +920,8 @@ func TestLoadMultipleConfigs(t *testing.T) {
Context: ".",
Dockerfile: "foo.Dockerfile",
Args: types.MappingWithEquals{
"buildno": strPtr("1"),
"password": strPtr("secret"),
"buildno": new("1"),
"password": new("secret"),
},
},
Ports: []types.ServicePortConfig{
@@ -1246,13 +1246,13 @@ func TestMergeServiceOverrideReplicasZero(t *testing.T) {
base := types.ServiceConfig{
Name: "someService",
Deploy: types.DeployConfig{
Replicas: uint64Ptr(3),
Replicas: new(uint64(3)),
},
}
override := types.ServiceConfig{
Name: "someService",
Deploy: types.DeployConfig{
Replicas: uint64Ptr(0),
Replicas: new(uint64(0)),
},
}
services, err := mergeServices([]types.ServiceConfig{base}, []types.ServiceConfig{override})
@@ -1265,7 +1265,7 @@ func TestMergeServiceOverrideReplicasZero(t *testing.T) {
types.ServiceConfig{
Name: "someService",
Deploy: types.DeployConfig{
Replicas: uint64Ptr(0),
Replicas: new(uint64(0)),
},
},
)
@@ -1275,7 +1275,7 @@ func TestMergeServiceOverrideReplicasNotNil(t *testing.T) {
base := types.ServiceConfig{
Name: "someService",
Deploy: types.DeployConfig{
Replicas: uint64Ptr(3),
Replicas: new(uint64(3)),
},
}
override := types.ServiceConfig{
@@ -1292,7 +1292,7 @@ func TestMergeServiceOverrideReplicasNotNil(t *testing.T) {
types.ServiceConfig{
Name: "someService",
Deploy: types.DeployConfig{
Replicas: uint64Ptr(3),
Replicas: new(uint64(3)),
},
},
)
+1 -2
View File
@@ -101,8 +101,7 @@ func Validate(config map[string]any, version string) error {
}
if err := schema.Validate(toJSONValue(config)); err != nil {
var validationErr *jsonschema.ValidationError
if errors.As(err, &validationErr) {
if validationErr, ok := errors.AsType[*jsonschema.ValidationError](err); ok {
return getMostSpecificError(validationErr)
}
return err
+1 -2
View File
@@ -79,8 +79,7 @@ func ConvertDurationPtr(d *Duration) *time.Duration {
if d == nil {
return nil
}
res := time.Duration(*d)
return &res
return new(time.Duration(*d))
}
// MarshalJSON makes Duration implement json.Marshaler
+1 -2
View File
@@ -232,8 +232,7 @@ func (c *ConfigFile) Save() (retErr error) {
cfgFile = f
} else if os.IsNotExist(err) {
// extract the path from the error if the configfile does not exist or is a dangling symlink
var pathError *os.PathError
if errors.As(err, &pathError) {
if pathError, ok := errors.AsType[*os.PathError](err); ok {
cfgFile = pathError.Path
}
}
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
// Package ssh provides the connection helper for ssh:// URL.
package ssh
@@ -15,8 +18,7 @@ import (
func ParseURL(daemonURL string) (*Spec, error) {
u, err := url.Parse(daemonURL)
if err != nil {
var urlErr *url.Error
if errors.As(err, &urlErr) {
if urlErr, ok := errors.AsType[*url.Error](err); ok {
err = urlErr.Unwrap()
}
return nil, fmt.Errorf("invalid SSH URL: %w", err)
+1 -2
View File
@@ -101,8 +101,7 @@ func getExitCode(err error) int {
return 0
}
var userTerminatedErr errCtxSignalTerminated
if errors.As(err, &userTerminatedErr) {
if userTerminatedErr, ok := errors.AsType[errCtxSignalTerminated](err); ok {
s, ok := userTerminatedErr.signal.(syscall.Signal)
if !ok {
return 1
+1 -2
View File
@@ -12,8 +12,7 @@ import (
)
func translateV2AuthError(err error) error {
var e *url.Error
if errors.As(err, &e) {
if e, ok := errors.AsType[*url.Error](err); ok {
var e2 errcode.Error
if errors.As(e, &e2) && errors.Is(e2.Code, errcode.ErrorCodeUnauthorized) {
return unauthorizedErr{err}
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package registryclient
import (
@@ -244,8 +247,7 @@ func (c *client) iterateEndpoints(ctx context.Context, namedRef reference.Named,
repo, err := c.getRepositoryForReference(ctx, namedRef, repoEndpoint)
if err != nil {
logrus.Debugf("error %s with repo endpoint %+v", err, repoEndpoint)
var protoErr httpProtoError
if errors.As(err, &protoErr) {
if _, ok := errors.AsType[httpProtoError](err); ok {
continue
}
return err
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package opts
import (
@@ -21,8 +24,7 @@ func parseCount(s string) (int, error) {
}
i, err := strconv.Atoi(s)
if err != nil {
var numErr *strconv.NumError
if errors.As(err, &numErr) {
if numErr, ok := errors.AsType[*strconv.NumError](err); ok {
err = numErr.Err
}
return 0, fmt.Errorf(`invalid count (%s): value must be either "all" or an integer: %w`, s, err)
+4 -2
View File
@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.26
package opts
import (
@@ -100,8 +103,7 @@ func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo
case gwPriorityOpt:
netOpt.GwPriority, err = strconv.Atoi(val)
if err != nil {
var numErr *strconv.NumError
if errors.As(err, &numErr) {
if numErr, ok := errors.AsType[*strconv.NumError](err); ok {
err = numErr.Err
}
return fmt.Errorf("invalid gw-priority (%s): %w", val, err)
+2 -4
View File
@@ -73,8 +73,7 @@ func (p *PortOpt) Set(value string) error {
case portOptTargetPort:
tPort, err := strconv.ParseUint(val, 10, 16)
if err != nil {
var numErr *strconv.NumError
if errors.As(err, &numErr) {
if numErr, ok := errors.AsType[*strconv.NumError](err); ok {
err = numErr.Err
}
return fmt.Errorf("invalid target port (%s): value must be an integer: %w", val, err)
@@ -84,8 +83,7 @@ func (p *PortOpt) Set(value string) error {
case portOptPublishedPort:
pPort, err := strconv.ParseUint(val, 10, 16)
if err != nil {
var numErr *strconv.NumError
if errors.As(err, &numErr) {
if numErr, ok := errors.AsType[*strconv.NumError](err); ok {
err = numErr.Err
}
return fmt.Errorf("invalid published port (%s): value must be an integer: %w", val, err)