mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 20:24:31 +00:00
runtime: Scan drop-in directory, read files and decode them
updateFromDropIn() uses the infrastructure built by previous commits to ensure no contents of 'tomlConfig' are lost during decoding. To do this, we preserve the current contents of our tomlConfig in a clone and decode a drop-in into the original. At this point, the original instance is updated but its Agent and/or Hypervisor fields are potentially damaged. To merge, we update the clone's Agent/Hypervisor from the original instance. Now the clone has the desired Agent/Hypervisor and the original instance has the rest, so to finish, we just need to move the clone's Agent/Hypervisor to the original. Signed-off-by: Pavel Mores <pmores@redhat.com>
This commit is contained in:
parent
2c1efcc697
commit
0f9856c465
@ -10,6 +10,7 @@ package katautils
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@ -177,6 +178,20 @@ type agent struct {
|
||||
DialTimeout uint32 `toml:"dial_timeout"`
|
||||
}
|
||||
|
||||
func (orig *tomlConfig) Clone() tomlConfig {
|
||||
clone := *orig
|
||||
clone.Hypervisor = make(map[string]hypervisor)
|
||||
clone.Agent = make(map[string]agent)
|
||||
|
||||
for key, value := range orig.Hypervisor {
|
||||
clone.Hypervisor[key] = value
|
||||
}
|
||||
for key, value := range orig.Agent {
|
||||
clone.Agent[key] = value
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
func (h hypervisor) path() (string, error) {
|
||||
p := h.Path
|
||||
|
||||
@ -1309,6 +1324,70 @@ func decodeConfig(configPath string) (tomlConfig, string, error) {
|
||||
return tomlConf, resolved, nil
|
||||
}
|
||||
|
||||
func decodeDropIns(mainConfigPath string, tomlConf *tomlConfig) error {
|
||||
configDir := filepath.Dir(mainConfigPath)
|
||||
dropInDir := filepath.Join(configDir, "config.d")
|
||||
|
||||
files, err := ioutil.ReadDir(dropInDir)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("error reading %q directory: %s", dropInDir, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
dropInFpath := filepath.Join(dropInDir, file.Name())
|
||||
|
||||
err = updateFromDropIn(dropInFpath, tomlConf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateFromDropIn(dropInFpath string, tomlConf *tomlConfig) error {
|
||||
configData, err := os.ReadFile(dropInFpath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading file %q: %s", dropInFpath, err)
|
||||
}
|
||||
|
||||
// Ordinarily, BurntSushi only updates fields of tomlConfig that are
|
||||
// changed by the file and leaves the rest alone. This doesn't apply
|
||||
// though to tomlConfig substructures that are stored in maps. Their
|
||||
// previous contents are erased by toml.Decode() and only fields changed by
|
||||
// the file are set. To work around this, a bit of juggling is needed to
|
||||
// preserve the previous contents and merge them manually with the incoming
|
||||
// changes afterwards, using reflection.
|
||||
tomlConfOrig := tomlConf.Clone()
|
||||
|
||||
var md toml.MetaData
|
||||
md, err = toml.Decode(string(configData), &tomlConf)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding file %q: %s", dropInFpath, err)
|
||||
}
|
||||
|
||||
if len(md.Undecoded()) > 0 {
|
||||
msg := fmt.Sprintf("warning: undecoded keys in %q: %+v", dropInFpath, md.Undecoded())
|
||||
kataUtilsLogger.Warn(msg)
|
||||
}
|
||||
|
||||
for _, key := range md.Keys() {
|
||||
err = applyKey(*tomlConf, key, &tomlConfOrig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error applying key '%+v' from drop-in file %q: %s", key, dropInFpath, err)
|
||||
}
|
||||
}
|
||||
|
||||
tomlConf.Hypervisor = tomlConfOrig.Hypervisor
|
||||
tomlConf.Agent = tomlConfOrig.Agent
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyKey(sourceConf tomlConfig, key []string, targetConf *tomlConfig) error {
|
||||
// Any key that might need treatment provided by this function has to have
|
||||
|
Loading…
Reference in New Issue
Block a user