Skip to content

Commit 4bcd59f

Browse files
committed
feat(shim): add containerd access session
Signed-off-by: sidneychang <2190206983@qq.com>
1 parent d951084 commit 4bcd59f

4 files changed

Lines changed: 179 additions & 1 deletion

File tree

.github/linters/urunc-dict.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ cntr
131131
containerdshim
132132
containerd
133133
containerd's
134+
containersapi
135+
contentapi
134136
cpio
135137
creack
136138
crictl
@@ -152,6 +154,7 @@ elevateprivileges
152154
elfloader
153155
endmacro
154156
epoll
157+
errdefs
155158
etest
156159
etesting
157160
etfs
@@ -179,6 +182,7 @@ httpreply
179182
iface
180183
ifaces
181184
ifname
185+
imagesapi
182186
initpipe
183187
initrds
184188
inlinehilite
@@ -200,6 +204,7 @@ kwds
200204
lazytime
201205
lenag
202206
lenpg
207+
leasesapi
203208
levarage
204209
libc
205210
libcontainer
@@ -298,6 +303,7 @@ setgroup
298303
settime
299304
sgid
300305
sharedfs
306+
snapshotsapi
301307
sigaction
302308
sigreturn
303309
sigstr

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/initrd/*.go)
7373
URUNC_SRC += $(wildcard $(CURDIR)/pkg/network/*.go)
7474
SHIM_SRC := $(wildcard $(CURDIR)/cmd/containerd-shim-urunc-v2/*.go)
7575
SHIM_SRC += $(wildcard $(CURDIR)/pkg/containerd-shim/*.go)
76+
SHIM_SRC += $(wildcard $(CURDIR)/pkg/containerd-shim/containerd/*.go)
7677

7778
#? CNTR_TOOL Tool to run the linter container (default: docker)
7879
CNTR_TOOL ?= docker

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ require (
2828
github.com/vishvananda/netlink v1.3.1
2929
github.com/vishvananda/netns v0.0.5
3030
golang.org/x/sys v0.43.0
31+
google.golang.org/grpc v1.79.3
3132
k8s.io/cri-api v0.35.4
3233
)
3334

@@ -79,7 +80,6 @@ require (
7980
golang.org/x/tools v0.41.0 // indirect
8081
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect
8182
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
82-
google.golang.org/grpc v1.79.3 // indirect
8383
google.golang.org/protobuf v1.36.11 // indirect
8484
gopkg.in/yaml.v3 v3.0.1 // indirect
8585
)
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright (c) 2023-2026, Nubificus LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package containerd
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"time"
21+
22+
containersapi "github.com/containerd/containerd/api/services/containers/v1"
23+
contentapi "github.com/containerd/containerd/api/services/content/v1"
24+
imagesapi "github.com/containerd/containerd/api/services/images/v1"
25+
leasesapi "github.com/containerd/containerd/api/services/leases/v1"
26+
snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1"
27+
"github.com/containerd/containerd/defaults"
28+
"github.com/containerd/containerd/errdefs"
29+
"github.com/containerd/containerd/namespaces"
30+
"github.com/containerd/containerd/pkg/dialer"
31+
"google.golang.org/grpc"
32+
"google.golang.org/grpc/backoff"
33+
"google.golang.org/grpc/credentials/insecure"
34+
)
35+
36+
const defaultConnectTimeout = 10 * time.Second
37+
38+
type Session struct {
39+
conn *grpc.ClientConn
40+
41+
namespace string
42+
containerID string
43+
container *containersapi.Container
44+
}
45+
46+
// OpenSession opens a containerd session and loads the task container metadata.
47+
func OpenSession(ctx context.Context, address, containerID string) (*Session, error) {
48+
if address == "" {
49+
return nil, fmt.Errorf("containerd address is empty")
50+
}
51+
if containerID == "" {
52+
return nil, fmt.Errorf("container id is empty")
53+
}
54+
55+
namespace, err := namespaces.NamespaceRequired(ctx)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
backoffConfig := backoff.DefaultConfig
61+
backoffConfig.MaxDelay = 3 * time.Second
62+
dialOptions := []grpc.DialOption{
63+
grpc.WithBlock(),
64+
grpc.WithTransportCredentials(insecure.NewCredentials()),
65+
grpc.FailOnNonTempDialError(true),
66+
grpc.WithConnectParams(grpc.ConnectParams{Backoff: backoffConfig}),
67+
grpc.WithContextDialer(dialer.ContextDialer),
68+
grpc.WithReturnConnectionError(),
69+
grpc.WithDefaultCallOptions(
70+
grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize),
71+
grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize),
72+
),
73+
}
74+
75+
dialCtx, cancel := context.WithTimeout(ctx, defaultConnectTimeout)
76+
defer cancel()
77+
78+
conn, err := grpc.DialContext(dialCtx, dialer.DialAddress(address), dialOptions...)
79+
if err != nil {
80+
return nil, fmt.Errorf("dial containerd at %q: %w", address, err)
81+
}
82+
83+
session := &Session{
84+
conn: conn,
85+
namespace: namespace,
86+
containerID: containerID,
87+
}
88+
89+
container, err := loadContainer(ctx, namespace, containerID, session.containersClient())
90+
if err != nil {
91+
if closeErr := conn.Close(); closeErr != nil {
92+
return nil, fmt.Errorf("loadContainer failed: %w; close containerd connection: %v", err, closeErr)
93+
}
94+
return nil, fmt.Errorf("loadContainer failed: %w", err)
95+
}
96+
session.container = container
97+
98+
return session, nil
99+
}
100+
101+
func (s *Session) Close() error {
102+
if s == nil || s.conn == nil {
103+
return nil
104+
}
105+
return s.conn.Close()
106+
}
107+
108+
func (s *Session) GetNamespace() string {
109+
return s.namespace
110+
}
111+
112+
func (s *Session) GetContainerID() string {
113+
return s.containerID
114+
}
115+
116+
func (s *Session) GetContainer() *containersapi.Container {
117+
return s.container
118+
}
119+
120+
func loadContainer(ctx context.Context, namespace, containerID string, client containersapi.ContainersClient) (*containersapi.Container, error) {
121+
resp, err := client.Get(withNamespace(ctx, namespace), &containersapi.GetContainerRequest{
122+
ID: containerID,
123+
})
124+
if err != nil {
125+
return nil, fmt.Errorf("get container %q: %w", containerID, containerdErr(err))
126+
}
127+
container := resp.GetContainer()
128+
if container == nil {
129+
return nil, fmt.Errorf("get container %q: response missing container", containerID)
130+
}
131+
132+
return container, nil
133+
}
134+
135+
func withNamespace(ctx context.Context, namespace string) context.Context {
136+
if ctx == nil {
137+
ctx = context.Background()
138+
}
139+
return namespaces.WithNamespace(ctx, namespace)
140+
}
141+
142+
func containerdErr(err error) error {
143+
if err == nil {
144+
return nil
145+
}
146+
return errdefs.FromGRPC(err)
147+
}
148+
149+
func (s *Session) containersClient() containersapi.ContainersClient {
150+
return containersapi.NewContainersClient(s.conn)
151+
}
152+
153+
//nolint:unused // Used by follow-up feature-specific access constructors.
154+
func (s *Session) imagesClient() imagesapi.ImagesClient {
155+
return imagesapi.NewImagesClient(s.conn)
156+
}
157+
158+
//nolint:unused // Used by follow-up feature-specific access constructors.
159+
func (s *Session) contentClient() contentapi.ContentClient {
160+
return contentapi.NewContentClient(s.conn)
161+
}
162+
163+
//nolint:unused // Used by follow-up feature-specific access constructors.
164+
func (s *Session) snapshotsClient() snapshotsapi.SnapshotsClient {
165+
return snapshotsapi.NewSnapshotsClient(s.conn)
166+
}
167+
168+
//nolint:unused // Used by follow-up feature-specific access constructors.
169+
func (s *Session) leasesClient() leasesapi.LeasesClient {
170+
return leasesapi.NewLeasesClient(s.conn)
171+
}

0 commit comments

Comments
 (0)