2023-02-23 20:01:24 +00:00
/ * *
# Copyright ( c ) NVIDIA CORPORATION . All rights reserved .
#
# Licensed under the Apache License , Version 2.0 ( the "License" ) ;
# you may not use this file except in compliance with the License .
# You may obtain a copy of the License at
#
# http : //www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing , software
# distributed under the License is distributed on an "AS IS" BASIS ,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
# See the License for the specific language governing permissions and
# limitations under the License .
* * /
package containerd
import (
"fmt"
"github.com/pelletier/go-toml"
2023-12-01 01:10:10 +00:00
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine"
2023-02-23 20:01:24 +00:00
)
// AddRuntime adds a runtime to the containerd config
2024-05-15 20:19:18 +00:00
func ( c * Config ) AddRuntime ( name string , path string , setAsDefault bool , configOverrides ... map [ string ] interface { } ) error {
2023-02-23 20:01:24 +00:00
if c == nil || c . Tree == nil {
return fmt . Errorf ( "config is nil" )
}
config := * c . Tree
config . Set ( "version" , int64 ( 2 ) )
2024-07-02 08:26:41 +00:00
// By default we extract the runtime options from the runc settings; if this does not exist we get the options from the default runtime specified in the config.
runtimeNamesForConfig := [ ] string { "runc" }
if name , ok := config . GetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "default_runtime_name" } ) . ( string ) ; ok && name != "" {
runtimeNamesForConfig = append ( runtimeNamesForConfig , name )
}
for _ , r := range runtimeNamesForConfig {
if options , ok := config . GetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , r } ) . ( * toml . Tree ) ; ok {
c . Logger . Debugf ( "using options from runtime %v: %v" , r , options . String ( ) )
options , _ = toml . Load ( options . String ( ) )
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name } , options )
break
}
2023-02-23 20:01:24 +00:00
}
if config . GetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name } ) == nil {
2024-07-02 08:26:41 +00:00
c . Logger . Warningf ( "could not infer options from runtimes %v; using defaults" , runtimeNamesForConfig )
2023-02-23 20:01:24 +00:00
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name , "runtime_type" } , c . RuntimeType )
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name , "runtime_root" } , "" )
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name , "runtime_engine" } , "" )
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name , "privileged_without_host_devices" } , false )
}
2023-03-01 14:06:28 +00:00
2023-03-23 19:12:23 +00:00
if len ( c . ContainerAnnotations ) > 0 {
annotations , err := c . getRuntimeAnnotations ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name , "container_annotations" } )
if err != nil {
return err
}
annotations = append ( c . ContainerAnnotations , annotations ... )
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name , "container_annotations" } , annotations )
2023-03-01 14:06:28 +00:00
}
2023-02-23 20:01:24 +00:00
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name , "options" , "BinaryName" } , path )
if setAsDefault {
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "default_runtime_name" } , name )
}
2024-05-15 20:19:18 +00:00
runtimeSubtree := subtreeAtPath ( config , "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name )
if err := runtimeSubtree . applyOverrides ( configOverrides ... ) ; err != nil {
return fmt . Errorf ( "failed to apply config overrides: %w" , err )
}
2023-02-23 20:01:24 +00:00
* c . Tree = config
return nil
}
2023-03-23 19:12:23 +00:00
func ( c * Config ) getRuntimeAnnotations ( path [ ] string ) ( [ ] string , error ) {
if c == nil || c . Tree == nil {
return nil , nil
}
config := * c . Tree
if ! config . HasPath ( path ) {
return nil , nil
}
annotationsI , ok := config . GetPath ( path ) . ( [ ] interface { } )
if ! ok {
return nil , fmt . Errorf ( "invalid annotations: %v" , annotationsI )
}
var annotations [ ] string
for _ , annotation := range annotationsI {
a , ok := annotation . ( string )
if ! ok {
return nil , fmt . Errorf ( "invalid annotation: %v" , annotation )
}
annotations = append ( annotations , a )
}
return annotations , nil
}
2023-10-31 14:24:27 +00:00
// Set sets the specified containerd option.
2023-12-01 23:59:34 +00:00
func ( c * Config ) Set ( key string , value interface { } ) {
2023-10-31 14:24:27 +00:00
config := * c . Tree
config . SetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , key } , value )
* c . Tree = config
}
2023-02-23 20:01:24 +00:00
// DefaultRuntime returns the default runtime for the cri-o config
func ( c Config ) DefaultRuntime ( ) string {
if runtime , ok := c . GetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "default_runtime_name" } ) . ( string ) ; ok {
return runtime
}
return ""
}
// RemoveRuntime removes a runtime from the docker config
func ( c * Config ) RemoveRuntime ( name string ) error {
if c == nil || c . Tree == nil {
return nil
}
config := * c . Tree
config . DeletePath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name } )
if runtime , ok := config . GetPath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "default_runtime_name" } ) . ( string ) ; ok {
if runtime == name {
config . DeletePath ( [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "default_runtime_name" } )
}
}
runtimePath := [ ] string { "plugins" , "io.containerd.grpc.v1.cri" , "containerd" , "runtimes" , name }
for i := 0 ; i < len ( runtimePath ) ; i ++ {
if runtimes , ok := config . GetPath ( runtimePath [ : len ( runtimePath ) - i ] ) . ( * toml . Tree ) ; ok {
if len ( runtimes . Keys ( ) ) == 0 {
config . DeletePath ( runtimePath [ : len ( runtimePath ) - i ] )
}
}
}
if len ( config . Keys ( ) ) == 1 && config . Keys ( ) [ 0 ] == "version" {
config . Delete ( "version" )
}
* c . Tree = config
return nil
}
// Save writes the config to the specified path
func ( c Config ) Save ( path string ) ( int64 , error ) {
config := c . Tree
2023-07-03 13:14:22 +00:00
output , err := config . Marshal ( )
2023-02-23 20:01:24 +00:00
if err != nil {
return 0 , fmt . Errorf ( "unable to convert to TOML: %v" , err )
}
2023-07-03 13:14:22 +00:00
n , err := engine . Config ( path ) . Write ( output )
2023-02-23 20:01:24 +00:00
return int64 ( n ) , err
}