/** # Copyright (c) 2021-2022, 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 docker import ( "bytes" "encoding/json" "fmt" "io/ioutil" "os" log "github.com/sirupsen/logrus" ) // LoadConfig loads the docker config from disk func LoadConfig(configFilePath string) (map[string]interface{}, error) { log.Infof("Loading docker config from %v", configFilePath) info, err := os.Stat(configFilePath) if os.IsExist(err) && info.IsDir() { return nil, fmt.Errorf("config file is a directory") } cfg := make(map[string]interface{}) if os.IsNotExist(err) { log.Infof("Config file does not exist, creating new one") return cfg, nil } readBytes, err := ioutil.ReadFile(configFilePath) if err != nil { return nil, fmt.Errorf("unable to read config: %v", err) } reader := bytes.NewReader(readBytes) if err := json.NewDecoder(reader).Decode(&cfg); err != nil { return nil, err } log.Infof("Successfully loaded config") return cfg, nil } // UpdateConfig updates the docker config to include the nvidia runtimes func UpdateConfig(config map[string]interface{}, runtimeName string, runtimePath string, setAsDefault bool) error { // Read the existing runtimes runtimes := make(map[string]interface{}) if _, exists := config["runtimes"]; exists { runtimes = config["runtimes"].(map[string]interface{}) } // Add / update the runtime definitions runtimes[runtimeName] = map[string]interface{}{ "path": runtimePath, "args": []string{}, } // Update the runtimes definition if len(runtimes) > 0 { config["runtimes"] = runtimes } if setAsDefault { config["default-runtime"] = runtimeName } return nil } // FlushConfig flushes the updated/reverted config out to disk func FlushConfig(cfg map[string]interface{}, configFilePath string) error { log.Infof("Flushing docker config to %v", configFilePath) output, err := json.MarshalIndent(cfg, "", " ") if err != nil { return fmt.Errorf("unable to convert to JSON: %v", err) } switch len(output) { case 0: err := os.Remove(configFilePath) if err != nil { return fmt.Errorf("unable to remove empty file: %v", err) } log.Infof("Config empty, removing file") default: f, err := os.Create(configFilePath) if err != nil { return fmt.Errorf("unable to open %v for writing: %v", configFilePath, err) } defer f.Close() _, err = f.WriteString(string(output)) if err != nil { return fmt.Errorf("unable to write output: %v", err) } } log.Infof("Successfully flushed config") return nil }