mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2024-12-02 00:54:48 +00:00
159 lines
3.6 KiB
Go
159 lines
3.6 KiB
Go
|
/*
|
||
|
# Copyright (c) 2021, 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 config
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
|
||
|
"github.com/pelletier/go-toml"
|
||
|
log "github.com/sirupsen/logrus"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
configFileRelativePath = "nvidia-container-runtime/config.toml"
|
||
|
configOverride = "XDG_CONFIG_HOME"
|
||
|
defaultConfigRoot = "/etc"
|
||
|
|
||
|
nvidiaContainerCliSection = "nvidia-container-cli"
|
||
|
nvidiaContainerRuntimeConfigSection = "nvidia-container-runtime"
|
||
|
nvidiaContainerRuntimeExperimentalConfigSection = "nvidia-container-runtime.experimental"
|
||
|
)
|
||
|
|
||
|
type tomlConfig struct {
|
||
|
logger *log.Logger
|
||
|
path string
|
||
|
sections []tomlSection
|
||
|
}
|
||
|
|
||
|
type tomlSection struct {
|
||
|
section string
|
||
|
keys map[string]struct{}
|
||
|
}
|
||
|
|
||
|
func newDefaultConfigFileWithLogger(logger *log.Logger) configUpdater {
|
||
|
configDir := defaultConfigRoot
|
||
|
if XDGConfigDir := os.Getenv(configOverride); len(XDGConfigDir) != 0 {
|
||
|
configDir = XDGConfigDir
|
||
|
}
|
||
|
configFilePath := filepath.Join(configDir, configFileRelativePath)
|
||
|
|
||
|
return newConfigFromFileWithLogger(logger, configFilePath)
|
||
|
}
|
||
|
|
||
|
func newConfigFromFileWithLogger(logger *log.Logger, filepath string) configUpdater {
|
||
|
if _, err := os.Stat(filepath); os.IsNotExist(err) {
|
||
|
logger.Warnf("The config file '%v' does not exist", filepath)
|
||
|
return newNoopConfigUpdater()
|
||
|
}
|
||
|
|
||
|
sections := []tomlSection{
|
||
|
{
|
||
|
section: nvidiaContainerRuntimeConfigSection,
|
||
|
},
|
||
|
{
|
||
|
section: nvidiaContainerRuntimeExperimentalConfigSection,
|
||
|
},
|
||
|
{
|
||
|
section: nvidiaContainerCliSection,
|
||
|
keys: map[string]struct{}{
|
||
|
"root": {},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
c := tomlConfig{
|
||
|
logger: logger,
|
||
|
path: filepath,
|
||
|
sections: sections,
|
||
|
}
|
||
|
|
||
|
return &c
|
||
|
}
|
||
|
|
||
|
func (c tomlConfig) Update(cfg *Config) error {
|
||
|
configFile, err := os.Open(c.path)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("error opening config file %v: %v", c.path, err)
|
||
|
}
|
||
|
defer configFile.Close()
|
||
|
|
||
|
return c.updateFromReader(cfg, configFile)
|
||
|
}
|
||
|
|
||
|
func (c tomlConfig) updateFromReader(cfg *Config, reader io.Reader) error {
|
||
|
toml, err := toml.LoadReader(reader)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("error reading TOML contents: %v", err)
|
||
|
}
|
||
|
|
||
|
for _, section := range c.sections {
|
||
|
if v, ok := section.GetStringFrom(toml, "debug"); ok {
|
||
|
cfg.DebugFilePath = v
|
||
|
}
|
||
|
|
||
|
if v, ok := section.GetStringFrom(toml, "runtime-path"); ok {
|
||
|
cfg.RuntimePath = v
|
||
|
}
|
||
|
|
||
|
if v, ok := section.GetStringFrom(toml, "root"); ok {
|
||
|
cfg.Root = v
|
||
|
}
|
||
|
|
||
|
if v, ok := section.GetStringFrom(toml, "log-level"); ok {
|
||
|
cfg.Root = v
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c tomlSection) GetStringFrom(toml *toml.Tree, key string) (string, bool) {
|
||
|
value := c.GetFrom(toml, key)
|
||
|
if value != nil {
|
||
|
if v, ok := value.(string); ok {
|
||
|
return v, ok
|
||
|
}
|
||
|
}
|
||
|
return "", false
|
||
|
}
|
||
|
|
||
|
func (c tomlSection) GetFrom(toml *toml.Tree, key string) interface{} {
|
||
|
if !c.validKey(key) {
|
||
|
return nil
|
||
|
}
|
||
|
return toml.Get(c.configKey(key))
|
||
|
}
|
||
|
|
||
|
func (c tomlSection) validKey(key string) bool {
|
||
|
if c.keys == nil {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
_, exists := c.keys[key]
|
||
|
|
||
|
return exists
|
||
|
}
|
||
|
|
||
|
func (c tomlSection) configKey(key string) string {
|
||
|
if c.section == "" {
|
||
|
return key
|
||
|
}
|
||
|
return c.section + "." + key
|
||
|
}
|