@@ -18,6 +18,7 @@ package container
18
18
19
19
import (
20
20
"context"
21
+ "encoding/json"
21
22
"fmt"
22
23
"os"
23
24
"strings"
@@ -26,10 +27,16 @@ import (
26
27
"github.com/containerd/containerd"
27
28
"github.com/containerd/containerd/cio"
28
29
"github.com/containerd/containerd/errdefs"
30
+ gocni "github.com/containerd/go-cni"
29
31
"github.com/containerd/log"
30
32
"github.com/containerd/nerdctl/v2/pkg/api/types"
31
33
"github.com/containerd/nerdctl/v2/pkg/containerutil"
32
34
"github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker"
35
+ "github.com/containerd/nerdctl/v2/pkg/labels"
36
+ "github.com/containerd/nerdctl/v2/pkg/netutil"
37
+ "github.com/containerd/nerdctl/v2/pkg/netutil/nettype"
38
+ "github.com/containerd/nerdctl/v2/pkg/portutil"
39
+ "github.com/containerd/nerdctl/v2/pkg/rootlessutil"
33
40
"github.com/moby/sys/signal"
34
41
)
35
42
@@ -50,6 +57,9 @@ func Kill(ctx context.Context, client *containerd.Client, reqs []string, options
50
57
if found .MatchCount > 1 {
51
58
return fmt .Errorf ("multiple IDs found with provided prefix: %s" , found .Req )
52
59
}
60
+ if err := cleanupNetwork (ctx , found .Container , options .GOptions ); err != nil {
61
+ return fmt .Errorf ("unable to cleanup network for container: %s, %q" , found .Req , err )
62
+ }
53
63
if err := killContainer (ctx , found .Container , parsedSignal ); err != nil {
54
64
if errdefs .IsNotFound (err ) {
55
65
fmt .Fprintf (options .Stderr , "No such container: %s\n " , found .Req )
@@ -106,3 +116,77 @@ func killContainer(ctx context.Context, container containerd.Container, signal s
106
116
}
107
117
return nil
108
118
}
119
+
120
+ // cleanupNetwork removes cni network setup, specifically the forwards
121
+ func cleanupNetwork (ctx context.Context , container containerd.Container , globalOpts types.GlobalCommandOptions ) error {
122
+ return rootlessutil .WithDetachedNetNSIfAny (func () error {
123
+ // retrieve info to get current active port mappings
124
+ info , err := container .Info (ctx , containerd .WithoutRefreshedMetadata )
125
+ if err != nil {
126
+ return err
127
+ }
128
+ ports , portErr := portutil .ParsePortsLabel (info .Labels )
129
+ if portErr != nil {
130
+ return fmt .Errorf ("no oci spec: %q" , portErr )
131
+ }
132
+ portMappings := []gocni.NamespaceOpts {
133
+ gocni .WithCapabilityPortMap (ports ),
134
+ }
135
+
136
+ // retrieve info to get cni instance
137
+ spec , err := container .Spec (ctx )
138
+ if err != nil {
139
+ return err
140
+ }
141
+ networksJSON := spec .Annotations [labels .Networks ]
142
+ var networks []string
143
+ if err := json .Unmarshal ([]byte (networksJSON ), & networks ); err != nil {
144
+ return err
145
+ }
146
+ netType , err := nettype .Detect (networks )
147
+ if err != nil {
148
+ return err
149
+ }
150
+
151
+ switch netType {
152
+ case nettype .Host , nettype .None , nettype .Container :
153
+ // NOP
154
+ case nettype .CNI :
155
+ e , err := netutil .NewCNIEnv (globalOpts .CNIPath , globalOpts .CNINetConfPath , netutil .WithDefaultNetwork ())
156
+ if err != nil {
157
+ return err
158
+ }
159
+ cniOpts := []gocni.Opt {
160
+ gocni .WithPluginDir ([]string {globalOpts .CNIPath }),
161
+ }
162
+ netMap , err := e .NetworkMap ()
163
+ if err != nil {
164
+ return err
165
+ }
166
+ for _ , netstr := range networks {
167
+ net , ok := netMap [netstr ]
168
+ if ! ok {
169
+ return fmt .Errorf ("no such network: %q" , netstr )
170
+ }
171
+ cniOpts = append (cniOpts , gocni .WithConfListBytes (net .Bytes ))
172
+ }
173
+ cni , err := gocni .New (cniOpts ... )
174
+ if err != nil {
175
+ return err
176
+ }
177
+
178
+ var namespaceOpts []gocni.NamespaceOpts
179
+ namespaceOpts = append (namespaceOpts , portMappings ... )
180
+ namespace := spec .Annotations [labels .Namespace ]
181
+ fullID := namespace + "-" + container .ID ()
182
+ if err := cni .Remove (ctx , fullID , "" , namespaceOpts ... ); err != nil {
183
+ log .L .WithError (err ).Errorf ("failed to call cni.Remove" )
184
+ return err
185
+ }
186
+ return nil
187
+ default :
188
+ return fmt .Errorf ("unexpected network type %v" , netType )
189
+ }
190
+ return nil
191
+ })
192
+ }
0 commit comments