Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions cli/command/builder/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ package builder
import (
"context"

"github.com/moby/moby/api/types/build"
"github.com/moby/moby/client"
)

type fakeClient struct {
client.Client
builderPruneFunc func(ctx context.Context, opts client.BuildCachePruneOptions) (*build.CachePruneReport, error)
builderPruneFunc func(ctx context.Context, opts client.BuildCachePruneOptions) (client.BuildCachePruneResult, error)
}

func (c *fakeClient) BuildCachePrune(ctx context.Context, opts client.BuildCachePruneOptions) (*build.CachePruneReport, error) {
func (c *fakeClient) BuildCachePrune(ctx context.Context, opts client.BuildCachePruneOptions) (client.BuildCachePruneResult, error) {
if c.builderPruneFunc != nil {
return c.builderPruneFunc(ctx, opts)
}
return nil, nil
return client.BuildCachePruneResult{}, nil
}
4 changes: 2 additions & 2 deletions cli/command/builder/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ func runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions)
}
}

report, err := dockerCli.Client().BuildCachePrune(ctx, client.BuildCachePruneOptions{
resp, err := dockerCli.Client().BuildCachePrune(ctx, client.BuildCachePruneOptions{
All: options.all,
ReservedSpace: options.reservedSpace.Value(),
Filters: pruneFilters,
})
if err != nil {
return 0, "", err
}

report := resp.Report
if len(report.CachesDeleted) > 0 {
var sb strings.Builder
sb.WriteString("Deleted build cache objects:\n")
Expand Down
5 changes: 2 additions & 3 deletions cli/command/builder/prune_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"testing"

"github.com/docker/cli/internal/test"
"github.com/moby/moby/api/types/build"
"github.com/moby/moby/client"
)

Expand All @@ -16,8 +15,8 @@ func TestBuilderPromptTermination(t *testing.T) {
t.Cleanup(cancel)

cli := test.NewFakeCli(&fakeClient{
builderPruneFunc: func(ctx context.Context, opts client.BuildCachePruneOptions) (*build.CachePruneReport, error) {
return nil, errors.New("fakeClient builderPruneFunc should not be called")
builderPruneFunc: func(ctx context.Context, opts client.BuildCachePruneOptions) (client.BuildCachePruneResult, error) {
return client.BuildCachePruneResult{}, errors.New("fakeClient builderPruneFunc should not be called")
},
})
cmd := newPruneCommand(cli)
Expand Down
71 changes: 61 additions & 10 deletions cli/command/container/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net"
"net/netip"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -431,11 +432,42 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
return nil, err
}

ports, portBindings, err := nat.ParsePortSpecs(convertedOpts)
ports, natPortBindings, err := nat.ParsePortSpecs(convertedOpts)
if err != nil {
return nil, err
}

portBindings := make(map[network.Port][]network.PortBinding)
for port, bindings := range natPortBindings {
p, err := network.ParsePort(port.String())
if err != nil {
return nil, err
}
portBindings[p] = []network.PortBinding{}
for _, b := range bindings {
var hostIP netip.Addr
if b.HostIP.String() != "" {
hostIP, err = netip.ParseAddr(b.HostIP.String())
if err != nil {
return nil, err
}
}
portBindings[p] = append(portBindings[p], network.PortBinding{
HostIP: hostIP,
HostPort: b.HostPort,
})
}
}

exposedPorts := network.PortSet{}
for port := range ports {
p, err := network.ParsePort(port.String())
if err != nil {
return nil, err
}
exposedPorts[p] = struct{}{}
}

// Merge in exposed ports to the map of published ports
for _, e := range copts.expose.GetSlice() {
if strings.Contains(e, ":") {
Expand Down Expand Up @@ -626,7 +658,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
config := &container.Config{
Hostname: copts.hostname,
Domainname: copts.domainname,
ExposedPorts: ports,
ExposedPorts: exposedPorts,
User: copts.user,
Tty: copts.tty,
OpenStdin: copts.stdin,
Expand Down Expand Up @@ -662,7 +694,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
// but pre created containers can still have those nil values.
// See https://github.com/docker/docker/pull/17779
// for a more detailed explanation on why we don't want that.
DNS: copts.dns.GetAllOrEmpty(),
DNS: toNetipAddrSlice(copts.dns.GetAllOrEmpty()),
DNSSearch: copts.dnsSearch.GetAllOrEmpty(),
DNSOptions: copts.dnsOptions.GetAllOrEmpty(),
ExtraHosts: copts.extraHosts.GetSlice(),
Expand Down Expand Up @@ -805,10 +837,10 @@ func applyContainerOptions(n *opts.NetworkAttachmentOpts, copts *containerOption
if len(n.Links) > 0 && copts.links.Len() > 0 {
return invalidParameter(errors.New("conflicting options: cannot specify both --link and per-network links"))
}
if n.IPv4Address != "" && copts.ipv4Address != "" {
if n.IPv4Address.IsValid() && copts.ipv4Address != "" {
return invalidParameter(errors.New("conflicting options: cannot specify both --ip and per-network IPv4 address"))
}
if n.IPv6Address != "" && copts.ipv6Address != "" {
if n.IPv6Address.IsValid() && copts.ipv6Address != "" {
return invalidParameter(errors.New("conflicting options: cannot specify both --ip6 and per-network IPv6 address"))
}
if n.MacAddress != "" && copts.macAddress != "" {
Expand All @@ -828,17 +860,24 @@ func applyContainerOptions(n *opts.NetworkAttachmentOpts, copts *containerOption
copy(n.Links, copts.links.GetSlice())
}
if copts.ipv4Address != "" {
n.IPv4Address = copts.ipv4Address
var err error
n.IPv4Address, err = netip.ParseAddr(copts.ipv4Address)
if err != nil {
return err
}
}
if copts.ipv6Address != "" {
n.IPv6Address = copts.ipv6Address
var err error
n.IPv6Address, err = netip.ParseAddr(copts.ipv6Address)
if err != nil {
return err
}
}
if copts.macAddress != "" {
n.MacAddress = copts.macAddress
}
if copts.linkLocalIPs.Len() > 0 {
n.LinkLocalIPs = make([]string, copts.linkLocalIPs.Len())
copy(n.LinkLocalIPs, copts.linkLocalIPs.GetSlice())
n.LinkLocalIPs = toNetipAddrSlice(copts.linkLocalIPs.GetSlice())
}
return nil
}
Expand Down Expand Up @@ -867,7 +906,7 @@ func parseNetworkAttachmentOpt(ep opts.NetworkAttachmentOpts) (*network.Endpoint
if len(ep.Links) > 0 {
epConfig.Links = ep.Links
}
if ep.IPv4Address != "" || ep.IPv6Address != "" || len(ep.LinkLocalIPs) > 0 {
if ep.IPv4Address.IsValid() || ep.IPv6Address.IsValid() || len(ep.LinkLocalIPs) > 0 {
epConfig.IPAMConfig = &network.EndpointIPAMConfig{
IPv4Address: ep.IPv4Address,
IPv6Address: ep.IPv6Address,
Expand Down Expand Up @@ -1131,3 +1170,15 @@ func validateAttach(val string) (string, error) {
}
return val, errors.New("valid streams are STDIN, STDOUT and STDERR")
}

func toNetipAddrSlice(ips []string) []netip.Addr {
netips := make([]netip.Addr, 0, len(ips))
for _, ip := range ips {
addr, err := netip.ParseAddr(ip)
if err != nil {
continue
}
netips = append(netips, addr)
}
return netips
}
69 changes: 35 additions & 34 deletions cli/command/container/opts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import (
"errors"
"fmt"
"io"
"net/netip"
"os"
"runtime"
"strings"
"testing"
"time"

"github.com/moby/moby/api/types/container"
networktypes "github.com/moby/moby/api/types/network"
"github.com/moby/moby/api/types/network"
"github.com/spf13/pflag"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
Expand Down Expand Up @@ -42,7 +43,7 @@ func TestValidateAttach(t *testing.T) {
}
}

func parseRun(args []string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
func parseRun(args []string) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
flags, copts := setupRunFlags()
if err := flags.Parse(args); err != nil {
return nil, nil, nil, err
Expand All @@ -63,7 +64,7 @@ func setupRunFlags() (*pflag.FlagSet, *containerOptions) {
return flags, copts
}

func mustParse(t *testing.T, args string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig) {
func mustParse(t *testing.T, args string) (*container.Config, *container.HostConfig, *network.NetworkingConfig) {
t.Helper()
config, hostConfig, nwConfig, err := parseRun(append(strings.Split(args, " "), "ubuntu", "bash"))
assert.NilError(t, err)
Expand Down Expand Up @@ -447,12 +448,12 @@ func TestParseWithExpose(t *testing.T) {
}
})
t.Run("valid", func(t *testing.T) {
tests := map[string][]container.PortRangeProto{
"8080/tcp": {"8080/tcp"},
"8080/udp": {"8080/udp"},
"8080/ncp": {"8080/ncp"},
"8080-8080/udp": {"8080/udp"},
"8080-8082/tcp": {"8080/tcp", "8081/tcp", "8082/tcp"},
tests := map[string][]network.Port{
"8080/tcp": {network.MustParsePort("8080/tcp")},
"8080/udp": {network.MustParsePort("8080/udp")},
"8080/ncp": {network.MustParsePort("8080/ncp")},
"8080-8080/udp": {network.MustParsePort("8080/udp")},
"8080-8082/tcp": {network.MustParsePort("8080/tcp"), network.MustParsePort("8081/tcp"), network.MustParsePort("8082/tcp")},
}
for expose, exposedPorts := range tests {
t.Run(expose, func(t *testing.T) {
Expand All @@ -471,7 +472,7 @@ func TestParseWithExpose(t *testing.T) {
config, _, _, err := parseRun([]string{"--publish=80", "--expose=80-81/tcp", "img", "cmd"})
assert.NilError(t, err)
assert.Check(t, is.Len(config.ExposedPorts, 2))
ports := []container.PortRangeProto{"80/tcp", "81/tcp"}
ports := []network.Port{network.MustParsePort("80/tcp"), network.MustParsePort("81/tcp")}
for _, port := range ports {
_, ok := config.ExposedPorts[port]
assert.Check(t, ok, "missing port %q in exposed ports", port)
Expand Down Expand Up @@ -573,21 +574,21 @@ func TestParseNetworkConfig(t *testing.T) {
tests := []struct {
name string
flags []string
expected map[string]*networktypes.EndpointSettings
expected map[string]*network.EndpointSettings
expectedCfg container.Config
expectedHostCfg container.HostConfig
expectedErr string
}{
{
name: "single-network-legacy",
flags: []string{"--network", "net1"},
expected: map[string]*networktypes.EndpointSettings{},
expected: map[string]*network.EndpointSettings{},
expectedHostCfg: container.HostConfig{NetworkMode: "net1"},
},
{
name: "single-network-advanced",
flags: []string{"--network", "name=net1"},
expected: map[string]*networktypes.EndpointSettings{},
expected: map[string]*network.EndpointSettings{},
expectedHostCfg: container.HostConfig{NetworkMode: "net1"},
},
{
Expand All @@ -603,12 +604,12 @@ func TestParseNetworkConfig(t *testing.T) {
"--network-alias", "web1",
"--network-alias", "web2",
},
expected: map[string]*networktypes.EndpointSettings{
expected: map[string]*network.EndpointSettings{
"net1": {
IPAMConfig: &networktypes.EndpointIPAMConfig{
IPv4Address: "172.20.88.22",
IPv6Address: "2001:db8::8822",
LinkLocalIPs: []string{"169.254.2.2", "fe80::169:254:2:2"},
IPAMConfig: &network.EndpointIPAMConfig{
IPv4Address: netip.MustParseAddr("172.20.88.22"),
IPv6Address: netip.MustParseAddr("2001:db8::8822"),
LinkLocalIPs: []netip.Addr{netip.MustParseAddr("169.254.2.2"), netip.MustParseAddr("fe80::169:254:2:2")},
},
Links: []string{"foo:bar", "bar:baz"},
Aliases: []string{"web1", "web2"},
Expand All @@ -632,30 +633,30 @@ func TestParseNetworkConfig(t *testing.T) {
"--network", "name=net3,alias=web3,driver-opt=field3=value3,ip=172.20.88.22,ip6=2001:db8::8822",
"--network", "name=net4,mac-address=02:32:1c:23:00:04,link-local-ip=169.254.169.254",
},
expected: map[string]*networktypes.EndpointSettings{
expected: map[string]*network.EndpointSettings{
"net1": {
DriverOpts: map[string]string{"field1": "value1"},
IPAMConfig: &networktypes.EndpointIPAMConfig{
IPv4Address: "172.20.88.22",
IPv6Address: "2001:db8::8822",
LinkLocalIPs: []string{"169.254.2.2", "fe80::169:254:2:2"},
IPAMConfig: &network.EndpointIPAMConfig{
IPv4Address: netip.MustParseAddr("172.20.88.22"),
IPv6Address: netip.MustParseAddr("2001:db8::8822"),
LinkLocalIPs: []netip.Addr{netip.MustParseAddr("169.254.2.2"), netip.MustParseAddr("fe80::169:254:2:2")},
},
Links: []string{"foo:bar", "bar:baz"},
Aliases: []string{"web1", "web2"},
},
"net2": {},
"net3": {
DriverOpts: map[string]string{"field3": "value3"},
IPAMConfig: &networktypes.EndpointIPAMConfig{
IPv4Address: "172.20.88.22",
IPv6Address: "2001:db8::8822",
IPAMConfig: &network.EndpointIPAMConfig{
IPv4Address: netip.MustParseAddr("172.20.88.22"),
IPv6Address: netip.MustParseAddr("2001:db8::8822"),
},
Aliases: []string{"web3"},
},
"net4": {
MacAddress: "02:32:1c:23:00:04",
IPAMConfig: &networktypes.EndpointIPAMConfig{
LinkLocalIPs: []string{"169.254.169.254"},
IPAMConfig: &network.EndpointIPAMConfig{
LinkLocalIPs: []netip.Addr{netip.MustParseAddr("169.254.169.254")},
},
},
},
Expand All @@ -664,15 +665,15 @@ func TestParseNetworkConfig(t *testing.T) {
{
name: "single-network-advanced-with-options",
flags: []string{"--network", "name=net1,alias=web1,alias=web2,driver-opt=field1=value1,driver-opt=field2=value2,ip=172.20.88.22,ip6=2001:db8::8822,mac-address=02:32:1c:23:00:04"},
expected: map[string]*networktypes.EndpointSettings{
expected: map[string]*network.EndpointSettings{
"net1": {
DriverOpts: map[string]string{
"field1": "value1",
"field2": "value2",
},
IPAMConfig: &networktypes.EndpointIPAMConfig{
IPv4Address: "172.20.88.22",
IPv6Address: "2001:db8::8822",
IPAMConfig: &network.EndpointIPAMConfig{
IPv4Address: netip.MustParseAddr("172.20.88.22"),
IPv6Address: netip.MustParseAddr("2001:db8::8822"),
},
Aliases: []string{"web1", "web2"},
MacAddress: "02:32:1c:23:00:04",
Expand All @@ -684,13 +685,13 @@ func TestParseNetworkConfig(t *testing.T) {
{
name: "multiple-networks",
flags: []string{"--network", "net1", "--network", "name=net2"},
expected: map[string]*networktypes.EndpointSettings{"net1": {}, "net2": {}},
expected: map[string]*network.EndpointSettings{"net1": {}, "net2": {}},
expectedHostCfg: container.HostConfig{NetworkMode: "net1"},
},
{
name: "advanced-options-with-standalone-mac-address-flag",
flags: []string{"--network=name=net1,alias=foobar", "--mac-address", "52:0f:f3:dc:50:10"},
expected: map[string]*networktypes.EndpointSettings{
expected: map[string]*network.EndpointSettings{
"net1": {
Aliases: []string{"foobar"},
MacAddress: "52:0f:f3:dc:50:10",
Expand Down
Loading
Loading