@@ -19,6 +19,7 @@ package image
1919import (
2020 "fmt"
2121 "path/filepath"
22+ "slices"
2223 "strconv"
2324 "strings"
2425
@@ -143,8 +144,8 @@ func (i CUDA) HasDisableRequire() bool {
143144 return false
144145}
145146
146- // DevicesFromEnvvars returns the devices requested by the image through environment variables
147- func (i CUDA ) DevicesFromEnvvars (envVars ... string ) VisibleDevices {
147+ // devicesFromEnvvars returns the devices requested by the image through environment variables
148+ func (i CUDA ) devicesFromEnvvars (envVars ... string ) [] string {
148149 // We concantenate all the devices from the specified env.
149150 var isSet bool
150151 var devices []string
@@ -165,15 +166,15 @@ func (i CUDA) DevicesFromEnvvars(envVars ...string) VisibleDevices {
165166
166167 // Environment variable unset with legacy image: default to "all".
167168 if ! isSet && len (devices ) == 0 && i .IsLegacy () {
168- return NewVisibleDevices ( "all" )
169+ devices = [] string { "all" }
169170 }
170171
171172 // Environment variable unset or empty or "void": return nil
172173 if len (devices ) == 0 || requested ["void" ] {
173- return NewVisibleDevices ( "void" )
174+ devices = [] string { "void" }
174175 }
175176
176- return NewVisibleDevices (devices ... )
177+ return NewVisibleDevices (devices ... ). List ()
177178}
178179
179180// GetDriverCapabilities returns the requested driver capabilities.
@@ -232,6 +233,22 @@ func (i CUDA) OnlyFullyQualifiedCDIDevices() bool {
232233 return hasCDIdevice
233234}
234235
236+ // visibleEnvVars returns the environment variables that are used to determine device visibility.
237+ // It returns the preferred environment variables that are set, or NVIDIA_VISIBLE_DEVICES if none are set.
238+ func (i CUDA ) visibleEnvVars () []string {
239+ var envVars []string
240+ for _ , envVar := range i .preferredVisibleDeviceEnvVars {
241+ if ! i .HasEnvvar (envVar ) {
242+ continue
243+ }
244+ envVars = append (envVars , envVar )
245+ }
246+ if len (envVars ) > 0 {
247+ return envVars
248+ }
249+ return []string {EnvVarNvidiaVisibleDevices }
250+ }
251+
235252// VisibleDevices returns a list of devices requested in the container image.
236253// If volume mount requests are enabled these are returned if requested,
237254// otherwise device requests through environment variables are considered.
@@ -253,7 +270,7 @@ func (i CUDA) VisibleDevices() []string {
253270 }
254271
255272 // Get the Fallback to reading from the environment variable if privileges are correct
256- envVarDeviceRequests := i .VisibleDevicesFromEnvVar ()
273+ envVarDeviceRequests := i .visibleDevicesFromEnvVar ()
257274 if len (envVarDeviceRequests ) == 0 {
258275 return nil
259276 }
@@ -265,7 +282,10 @@ func (i CUDA) VisibleDevices() []string {
265282 }
266283
267284 // We log a warning if we are ignoring the environment variable requests.
268- i .logger .Warningf ("Ignoring devices specified in NVIDIA_VISIBLE_DEVICES in unprivileged container" )
285+ envVars := i .visibleEnvVars ()
286+ if len (envVars ) > 0 {
287+ i .logger .Warningf ("Ignoring devices requested by environment variable(s) in unprivileged container: %v" , envVars )
288+ }
269289
270290 return nil
271291}
@@ -281,31 +301,34 @@ func (i CUDA) cdiDeviceRequestsFromAnnotations() []string {
281301 return nil
282302 }
283303
284- var devices []string
285- for key , value := range i .annotations {
304+ var annotationKeys []string
305+ for key := range i .annotations {
286306 for _ , prefix := range i .annotationsPrefixes {
287307 if strings .HasPrefix (key , prefix ) {
288- devices = append (devices , strings . Split ( value , "," ) ... )
308+ annotationKeys = append (annotationKeys , key )
289309 // There is no need to check additional prefixes since we
290310 // typically deduplicate devices in any case.
291311 break
292312 }
293313 }
294314 }
315+ // We sort the annotationKeys for consistent results.
316+ slices .Sort (annotationKeys )
317+
318+ var devices []string
319+ for _ , key := range annotationKeys {
320+ devices = append (devices , strings .Split (i .annotations [key ], "," )... )
321+ }
295322 return devices
296323}
297324
298- // VisibleDevicesFromEnvVar returns the set of visible devices requested through environment variables.
325+ // visibleDevicesFromEnvVar returns the set of visible devices requested through environment variables.
299326// If any of the preferredVisibleDeviceEnvVars are present in the image, they
300327// are used to determine the visible devices. If this is not the case, the
301328// NVIDIA_VISIBLE_DEVICES environment variable is used.
302- func (i CUDA ) VisibleDevicesFromEnvVar () []string {
303- for _ , envVar := range i .preferredVisibleDeviceEnvVars {
304- if i .HasEnvvar (envVar ) {
305- return i .DevicesFromEnvvars (i .preferredVisibleDeviceEnvVars ... ).List ()
306- }
307- }
308- return i .DevicesFromEnvvars (EnvVarNvidiaVisibleDevices ).List ()
329+ func (i CUDA ) visibleDevicesFromEnvVar () []string {
330+ envVars := i .visibleEnvVars ()
331+ return i .devicesFromEnvvars (envVars ... )
309332}
310333
311334// visibleDevicesFromMounts returns the set of visible devices requested as mounts.
@@ -391,7 +414,7 @@ func (m cdiDeviceMountRequest) qualifiedName() (string, error) {
391414
392415// ImexChannelsFromEnvVar returns the list of IMEX channels requested for the image.
393416func (i CUDA ) ImexChannelsFromEnvVar () []string {
394- imexChannels := i .DevicesFromEnvvars (EnvVarNvidiaImexChannels ). List ( )
417+ imexChannels := i .devicesFromEnvvars (EnvVarNvidiaImexChannels )
395418 if len (imexChannels ) == 1 && imexChannels [0 ] == "all" {
396419 return nil
397420 }
0 commit comments