6
6
"encoding/json"
7
7
"fmt"
8
8
"io"
9
+ goruntime "runtime"
9
10
"strings"
10
11
"time"
11
12
@@ -22,19 +23,28 @@ import (
22
23
23
24
const diskFullStorageDriver = "vfs"
24
25
25
- // Adapted from github.com/NVIDIA/nvidia-container-toolkit/internal/lookup/library.go
26
- // These are destination candidates for the /usr/lib directory in the container,
27
- // in order of priority.
28
- // Depending on the inner image, the desired location may vary.
29
- // Note that we are excluding some nvidia-specific directories here and also
30
- // include a fallback to /usr/lib.
31
- var usrLibCandidates = []string {
32
- "/usr/lib/x86_64-linux-gnu" , // Debian uses a multiarch /usr/lib directory
33
- "/usr/lib/aarch64-linux-gnu" , // Above but for arm64.
34
- "/usr/lib64" , // Red Hat and friends.
35
- "/usr/lib" , // Fallback.
26
+ var usrLibMultiarchDir = map [string ]string {
27
+ "arm64" : "/usr/lib/aarch64-linux-gnu" ,
28
+ "amd64" : "/usr/lib/x86_64-linux-gnu" ,
36
29
}
37
30
31
+ // Adapted from https://github.com/NVIDIA/libnvidia-container/blob/v1.15.0/src/nvc_container.c#L152-L165
32
+ var usrLibDirs = map [string ]string {
33
+ // Debian-based distros use a multi-arch directory.
34
+ "debian" : usrLibMultiarchDir [goruntime .GOARCH ],
35
+ "ubuntu" : usrLibMultiarchDir [goruntime .GOARCH ],
36
+ // Fedora and Redhat use the standard /usr/lib64.
37
+ "fedora" : "/usr/lib64" ,
38
+ "redhat" : "/usr/lib64" ,
39
+ // Fall back to the standard /usr/lib.
40
+ "linux" : "/usr/lib" ,
41
+ }
42
+
43
+ // /etc/os-release is the standard location for system identification data on
44
+ // Linux systems running systemd.
45
+ // Ref: https://www.freedesktop.org/software/systemd/man/latest/os-release.html
46
+ var etcOsRelease = "/etc/os-release"
47
+
38
48
type PullImageConfig struct {
39
49
Client Client
40
50
Image string
@@ -161,11 +171,11 @@ func processImagePullEvents(r io.Reader, fn ImagePullProgressFn) error {
161
171
}
162
172
163
173
type ImageMetadata struct {
164
- UID string
165
- GID string
166
- HomeDir string
167
- HasInit bool
168
- UsrLibDir string
174
+ UID string
175
+ GID string
176
+ HomeDir string
177
+ HasInit bool
178
+ OsReleaseID string
169
179
}
170
180
171
181
// GetImageMetadata returns metadata about an image such as the UID/GID of the
@@ -240,32 +250,48 @@ func GetImageMetadata(ctx context.Context, client Client, img, username string)
240
250
return ImageMetadata {}, xerrors .Errorf ("no users returned for username %s" , username )
241
251
}
242
252
243
- // Find the "best" usr lib directory for the container.
244
- var foundUsrLibDir string
245
- for _ , candidate := range usrLibCandidates {
246
- _ , err := ExecContainer (ctx , client , ExecConfig {
247
- ContainerID : inspect .ID ,
248
- Cmd : "stat" ,
249
- Args : []string {candidate },
250
- })
251
- if err == nil {
252
- foundUsrLibDir = candidate
253
+ // Read the /etc/os-release file to get the ID of the OS.
254
+ out , err = ExecContainer (ctx , client , ExecConfig {
255
+ ContainerID : inspect .ID ,
256
+ Cmd : "cat" ,
257
+ Args : []string {etcOsRelease },
258
+ })
259
+ if err != nil {
260
+ return ImageMetadata {}, xerrors .Errorf ("read /etc/os-release: %w" , err )
261
+ }
262
+ // We only care about the ID field.
263
+ osReleaseID := ""
264
+ for _ , line := range strings .Split (string (out ), "\n " ) {
265
+ if strings .HasPrefix (line , "ID=" ) {
266
+ osReleaseID = strings .TrimPrefix (line , "ID=" )
267
+ // The value may be quoted.
268
+ osReleaseID = strings .Trim (osReleaseID , "\" " )
253
269
break
254
270
}
255
271
}
256
- if foundUsrLibDir == "" {
257
- return ImageMetadata {}, xerrors .Errorf ("no eligible /usr/lib directory found in container" )
272
+ if osReleaseID == "" {
273
+ // The default value is just "linux" if we can't find the ID.
274
+ osReleaseID = "linux"
258
275
}
259
276
260
277
return ImageMetadata {
261
- UID : users [0 ].Uid ,
262
- GID : users [0 ].Gid ,
263
- HomeDir : users [0 ].HomeDir ,
264
- HasInit : initExists ,
265
- UsrLibDir : foundUsrLibDir ,
278
+ UID : users [0 ].Uid ,
279
+ GID : users [0 ].Gid ,
280
+ HomeDir : users [0 ].HomeDir ,
281
+ HasInit : initExists ,
282
+ OsReleaseID : osReleaseID ,
266
283
}, nil
267
284
}
268
285
286
+ // UsrLibDir returns the path to the /usr/lib directory for the given
287
+ // operating system determined by the /etc/os-release file.
288
+ func (im ImageMetadata ) UsrLibDir () string {
289
+ if val , ok := usrLibDirs [im .OsReleaseID ]; ok {
290
+ return val
291
+ }
292
+ return usrLibDirs ["linux" ] // fallback
293
+ }
294
+
269
295
func DefaultLogImagePullFn (log buildlog.Logger ) func (ImagePullEvent ) error {
270
296
var (
271
297
// Avoid spamming too frequently, the messages can come quickly
0 commit comments