Skip to content

Commit 2e3b636

Browse files
committed
Fix netwalker issues
Current implementation of netwalker (henceforth network inspect and remove) suffers from many issues, rooting from mixing names and identifiers in the same namespace, faulty erroring logic, and overly complicated design making debugging and reasonning harder. This commit removes the walker and replaces it with a simpler approach. Next commit will add tests. Signed-off-by: apostasie <[email protected]>
1 parent 24b97cb commit 2e3b636

File tree

9 files changed

+181
-221
lines changed

9 files changed

+181
-221
lines changed

cmd/nerdctl/completion/completion.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,13 @@ func NetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCo
124124
if err != nil {
125125
return nil, cobra.ShellCompDirectiveError
126126
}
127-
for netName := range netConfigs {
127+
for netName, network := range netConfigs {
128128
if _, ok := excludeMap[netName]; !ok {
129129
candidates = append(candidates, netName)
130+
if network.NerdctlID != nil {
131+
candidates = append(candidates, *network.NerdctlID)
132+
candidates = append(candidates, (*network.NerdctlID)[0:12])
133+
}
130134
}
131135
}
132136
for _, s := range []string{"host", "none"} {

pkg/cmd/container/kill.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,12 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO
161161
cniOpts := []gocni.Opt{
162162
gocni.WithPluginDir([]string{globalOpts.CNIPath}),
163163
}
164-
netMap, err := e.NetworkMap()
165-
if err != nil {
166-
return err
167-
}
164+
var netw *netutil.NetworkConfig
168165
for _, netstr := range networks {
169-
net, ok := netMap[netstr]
170-
if !ok {
171-
return fmt.Errorf("no such network: %q", netstr)
166+
if netw, err = e.NetworkByNameOrID(netstr); err != nil {
167+
return err
172168
}
173-
cniOpts = append(cniOpts, gocni.WithConfListBytes(net.Bytes))
169+
cniOpts = append(cniOpts, gocni.WithConfListBytes(netw.Bytes))
174170
}
175171
cni, err := gocni.New(cniOpts...)
176172
if err != nil {

pkg/cmd/network/inspect.go

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,62 +19,71 @@ package network
1919
import (
2020
"context"
2121
"encoding/json"
22+
"errors"
2223
"fmt"
2324

2425
"github.com/containerd/log"
2526

2627
"github.com/containerd/nerdctl/v2/pkg/api/types"
2728
"github.com/containerd/nerdctl/v2/pkg/formatter"
28-
"github.com/containerd/nerdctl/v2/pkg/idutil/netwalker"
2929
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
3030
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/native"
3131
"github.com/containerd/nerdctl/v2/pkg/netutil"
3232
)
3333

3434
func Inspect(ctx context.Context, options types.NetworkInspectOptions) error {
35-
globalOptions := options.GOptions
36-
e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace))
35+
if options.Mode != "native" && options.Mode != "dockercompat" {
36+
return fmt.Errorf("unknown mode %q", options.Mode)
37+
}
3738

39+
cniEnv, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace))
3840
if err != nil {
3941
return err
4042
}
41-
if options.Mode != "native" && options.Mode != "dockercompat" {
42-
return fmt.Errorf("unknown mode %q", options.Mode)
43-
}
4443

4544
var result []interface{}
46-
walker := netwalker.NetworkWalker{
47-
Client: e,
48-
OnFound: func(ctx context.Context, found netwalker.Found) error {
49-
if found.MatchCount > 1 {
50-
return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req)
51-
}
52-
r := &native.Network{
53-
CNI: json.RawMessage(found.Network.Bytes),
54-
NerdctlID: found.Network.NerdctlID,
55-
NerdctlLabels: found.Network.NerdctlLabels,
56-
File: found.Network.File,
57-
}
58-
switch options.Mode {
59-
case "native":
60-
result = append(result, r)
61-
case "dockercompat":
62-
compat, err := dockercompat.NetworkFromNative(r)
63-
if err != nil {
64-
return err
65-
}
66-
result = append(result, compat)
45+
netLists, errs := cniEnv.ListNetworksMatch(options.Networks, true)
46+
47+
for req, netList := range netLists {
48+
if len(netList) > 1 {
49+
errs = append(errs, fmt.Errorf("multiple IDs found with provided prefix: %s", req))
50+
continue
51+
}
52+
if len(netList) == 0 {
53+
errs = append(errs, fmt.Errorf("no network found matching: %s", req))
54+
continue
55+
}
56+
network := netList[0]
57+
r := &native.Network{
58+
CNI: json.RawMessage(network.Bytes),
59+
NerdctlID: network.NerdctlID,
60+
NerdctlLabels: network.NerdctlLabels,
61+
File: network.File,
62+
}
63+
switch options.Mode {
64+
case "native":
65+
result = append(result, r)
66+
case "dockercompat":
67+
compat, err := dockercompat.NetworkFromNative(r)
68+
if err != nil {
69+
return err
6770
}
68-
return nil
69-
},
71+
result = append(result, compat)
72+
}
7073
}
7174

72-
// `network inspect` doesn't support pseudo network.
73-
err = walker.WalkAll(ctx, options.Networks, true, false)
7475
if len(result) > 0 {
7576
if formatErr := formatter.FormatSlice(options.Format, options.Stdout, result); formatErr != nil {
7677
log.G(ctx).Error(formatErr)
7778
}
79+
err = nil
80+
} else {
81+
err = errors.New("unable to find any network matching the provided request")
82+
}
83+
84+
for _, unErr := range errs {
85+
log.G(ctx).Error(unErr)
7886
}
87+
7988
return err
8089
}

pkg/cmd/network/remove.go

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ package network
1818

1919
import (
2020
"context"
21+
"errors"
2122
"fmt"
2223

2324
containerd "github.com/containerd/containerd/v2/client"
25+
"github.com/containerd/log"
2426

2527
"github.com/containerd/nerdctl/v2/pkg/api/types"
26-
"github.com/containerd/nerdctl/v2/pkg/idutil/netwalker"
2728
"github.com/containerd/nerdctl/v2/pkg/netutil"
2829
)
2930

3031
func Remove(ctx context.Context, client *containerd.Client, options types.NetworkRemoveOptions) error {
31-
e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace))
32+
cniEnv, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace))
3233
if err != nil {
3334
return err
3435
}
@@ -38,28 +39,52 @@ func Remove(ctx context.Context, client *containerd.Client, options types.Networ
3839
return err
3940
}
4041

41-
walker := netwalker.NetworkWalker{
42-
Client: e,
43-
OnFound: func(ctx context.Context, found netwalker.Found) error {
44-
if found.MatchCount > 1 {
45-
return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req)
46-
}
47-
if value, ok := usedNetworkInfo[found.Network.Name]; ok {
48-
return fmt.Errorf("network %q is in use by container %q", found.Req, value)
49-
}
50-
if found.Network.NerdctlID == nil {
51-
return fmt.Errorf("%s is managed outside nerdctl and cannot be removed", found.Req)
52-
}
53-
if found.Network.File == "" {
54-
return fmt.Errorf("%s is a pre-defined network and cannot be removed", found.Req)
55-
}
56-
if err := e.RemoveNetwork(found.Network); err != nil {
57-
return err
58-
}
59-
fmt.Fprintln(options.Stdout, found.Req)
60-
return nil
61-
},
42+
var result []string
43+
netLists, errs := cniEnv.ListNetworksMatch(options.Networks, false)
44+
45+
for req, netList := range netLists {
46+
if len(netList) > 1 {
47+
errs = append(errs, fmt.Errorf("multiple IDs found with provided prefix: %s", req))
48+
continue
49+
}
50+
if len(netList) == 0 {
51+
errs = append(errs, fmt.Errorf("no network found matching: %s", req))
52+
continue
53+
}
54+
network := netList[0]
55+
if value, ok := usedNetworkInfo[network.Name]; ok {
56+
errs = append(errs, fmt.Errorf("network %q is in use by container %q", req, value))
57+
continue
58+
}
59+
if network.Name == "bridge" {
60+
errs = append(errs, errors.New("cannot remove pre-defined network bridge"))
61+
continue
62+
}
63+
if network.File == "" {
64+
errs = append(errs, fmt.Errorf("%s is a pre-defined network and cannot be removed", req))
65+
continue
66+
}
67+
if network.NerdctlID == nil {
68+
errs = append(errs, fmt.Errorf("%s is managed outside nerdctl and cannot be removed", req))
69+
continue
70+
}
71+
if err := cniEnv.RemoveNetwork(network); err != nil {
72+
errs = append(errs, err)
73+
} else {
74+
result = append(result, req)
75+
}
76+
}
77+
for _, unErr := range errs {
78+
log.G(ctx).Error(unErr)
79+
}
80+
if len(result) > 0 {
81+
for _, id := range result {
82+
fmt.Fprintln(options.Stdout, id)
83+
}
84+
err = nil
85+
} else {
86+
err = errors.New("no network could be removed")
6287
}
6388

64-
return walker.WalkAll(ctx, options.Networks, true, false)
89+
return err
6590
}

pkg/containerutil/container_network_manager.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -667,17 +667,14 @@ func writeEtcHostnameForContainer(globalOptions types.GlobalCommandOptions, host
667667
// from the networkSlice is of a type within supportedTypes.
668668
// nolint:unused
669669
func verifyNetworkTypes(env *netutil.CNIEnv, networkSlice []string, supportedTypes []string) (map[string]*netutil.NetworkConfig, error) {
670-
netMap, err := env.NetworkMap()
671-
if err != nil {
672-
return nil, err
673-
}
674-
675670
res := make(map[string]*netutil.NetworkConfig, len(networkSlice))
671+
var netConfig *netutil.NetworkConfig
672+
var err error
676673
for _, netstr := range networkSlice {
677-
netConfig, ok := netMap[netstr]
678-
if !ok {
679-
return nil, fmt.Errorf("network %s not found", netstr)
674+
if netConfig, err = env.NetworkByNameOrID(netstr); err != nil {
675+
return nil, err
680676
}
677+
681678
netType := netConfig.Plugins[0].Network.Type
682679
if supportedTypes != nil && !strutil.InStringSlice(supportedTypes, netType) {
683680
return nil, fmt.Errorf("network type %q is not supported for network mapping %q, must be one of: %v", netType, netstr, supportedTypes)

pkg/idutil/netwalker/netwalker.go

Lines changed: 0 additions & 119 deletions
This file was deleted.

0 commit comments

Comments
 (0)