6
6
7
7
"github.com/containerd/containerd"
8
8
"github.com/containerd/containerd/containers"
9
+ "github.com/containerd/containerd/images"
9
10
"github.com/containerd/containerd/namespaces"
10
11
"google.golang.org/grpc"
11
12
"google.golang.org/grpc/credentials/insecure"
@@ -17,12 +18,15 @@ import (
17
18
18
19
type containerdEnricher struct {
19
20
containers containers.Store
20
- images cri.ImageServiceClient
21
+ images images.Store
22
+ images_cri cri.ImageServiceClient
21
23
namespaces namespaces.Store
22
24
}
23
25
24
26
func ContainerdEnricher (socket string ) (ContainerEnricher , error ) {
25
27
enricher := containerdEnricher {}
28
+
29
+ // avoid duplicate unix:// prefix
26
30
unixSocket := "unix://" + strings .TrimPrefix (socket , "unix://" )
27
31
28
32
client , err := containerd .New (socket )
@@ -38,9 +42,10 @@ func ContainerdEnricher(socket string) (ContainerEnricher, error) {
38
42
return nil , errfmt .WrapError (err )
39
43
}
40
44
41
- enricher .images = cri .NewImageServiceClient (conn )
45
+ enricher .images_cri = cri .NewImageServiceClient (conn )
42
46
enricher .containers = client .ContainerService ()
43
47
enricher .namespaces = client .NamespaceService ()
48
+ enricher .images = client .ImageService ()
44
49
45
50
return & enricher , nil
46
51
}
@@ -54,6 +59,7 @@ func (e *containerdEnricher) Get(ctx context.Context, containerId string) (Conta
54
59
return metadata , errfmt .Errorf ("failed to fetch namespaces %s" , err .Error ())
55
60
}
56
61
for _ , namespace := range nsList {
62
+ // always query with namespace applied
57
63
nsCtx := namespaces .WithNamespace (ctx , namespace )
58
64
59
65
// if containers is not in current namespace, search the next one
@@ -62,27 +68,24 @@ func (e *containerdEnricher) Get(ctx context.Context, containerId string) (Conta
62
68
continue
63
69
}
64
70
65
- imageName := container .Image
66
- imageDigest := container .Image
67
71
image := container .Image
68
- // container may not have image name as id, if so fetch from the sha256 id
69
- if strings . HasPrefix ( image , "sha256:" ) {
70
- imageInfo , err := e .images . ImageStatus ( ctx , & cri. ImageStatusRequest {
71
- Image : & cri. ImageSpec {
72
- Image : strings . TrimPrefix ( image , "sha256:" ),
73
- },
74
- })
75
- if err != nil {
72
+ var imageName , imageDigest string
73
+
74
+ i , d , err := e .getImageInfoStore ( nsCtx , image )
75
+ if err != nil {
76
+ // try using cri directly
77
+ i , d , err2 := e . getImageInfoCri ( nsCtx , image )
78
+ if err2 != nil {
79
+ logger . Debugw ( "failed to extract image digest from containerd service and cri" , " err" , err , "err_cri" , err2 )
76
80
imageName = image
77
81
imageDigest = image
78
82
} else {
79
- if len (imageInfo .Image .RepoTags ) > 0 {
80
- imageName = imageInfo .Image .RepoTags [0 ]
81
- }
82
- if len (imageInfo .Image .RepoDigests ) > 0 {
83
- imageDigest = imageInfo .Image .RepoTags [0 ]
84
- }
83
+ imageName = i
84
+ imageDigest = d
85
85
}
86
+ } else {
87
+ imageName = i
88
+ imageDigest = d
86
89
}
87
90
88
91
// if in k8s we can extract pod info from labels
@@ -111,3 +114,51 @@ func (e *containerdEnricher) Get(ctx context.Context, containerId string) (Conta
111
114
func (e * containerdEnricher ) isSandbox (labels map [string ]string ) bool {
112
115
return labels [ContainerTypeContainerdLabel ] == "sandbox"
113
116
}
117
+
118
+ func (e * containerdEnricher ) getImageInfoStore (ctx context.Context , image string ) (string , string , error ) {
119
+ r , err := e .images .Get (ctx , image )
120
+ if err != nil {
121
+ return "" , "" , err
122
+ }
123
+
124
+ i := r .Name
125
+ d := r .Target .Digest .String ()
126
+ return i , d , nil
127
+ }
128
+
129
+ func (e * containerdEnricher ) getImageInfoCri (ctx context.Context , image string ) (string , string , error ) {
130
+ var imageName , imageDigest string
131
+ var imageInfo * cri.ImageStatusResponse
132
+ var err error
133
+
134
+ if strings .HasPrefix (image , "sha256:" ) {
135
+ // container may not have image name as id, if so fetch from the sha256 id
136
+ imageInfo , err = e .images_cri .ImageStatus (ctx , & cri.ImageStatusRequest {
137
+ Image : & cri.ImageSpec {
138
+ Image : strings .TrimPrefix (image , "sha256:" ),
139
+ },
140
+ })
141
+ } else {
142
+ // else query directly
143
+ imageInfo , err = e .images_cri .ImageStatus (ctx , & cri.ImageStatusRequest {
144
+ Image : & cri.ImageSpec {
145
+ UserSpecifiedImage : image ,
146
+ },
147
+ })
148
+ }
149
+ if err != nil {
150
+ return "" , "" , err
151
+ } else if imageInfo .Image != nil {
152
+ // if imag
153
+ if len (imageInfo .Image .RepoTags ) > 0 {
154
+ imageName = imageInfo .Image .RepoTags [0 ]
155
+ }
156
+ if len (imageInfo .Image .RepoDigests ) > 0 {
157
+ imageDigest = imageInfo .Image .RepoDigests [0 ]
158
+ }
159
+ } else {
160
+ // image was nil - no image found
161
+ return "" , "" , errfmt .Errorf ("no image info found in containerd cri (query: %s)" , image )
162
+ }
163
+ return imageName , imageDigest , nil
164
+ }
0 commit comments