mirror of https://github.com/k3s-io/k3s
Merge pull request #28232 from cjcullen/webhook2
Automatic merge from submit-queue Lock all possible kubecfg files at the beginning of ModifyConfig. Prevent concurrent calls to ModifyConfig on the same (or overlapping) kubeconfig files.pull/6/head
commit
bc9820ce47
|
@ -22,6 +22,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
@ -153,6 +154,17 @@ func NewDefaultPathOptions() *PathOptions {
|
||||||
// that means that this code will only write into a single file. If you want to relativizePaths, you must provide a fully qualified path in any
|
// that means that this code will only write into a single file. If you want to relativizePaths, you must provide a fully qualified path in any
|
||||||
// modified element.
|
// modified element.
|
||||||
func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, relativizePaths bool) error {
|
func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, relativizePaths bool) error {
|
||||||
|
possibleSources := configAccess.GetLoadingPrecedence()
|
||||||
|
// sort the possible kubeconfig files so we always "lock" in the same order
|
||||||
|
// to avoid deadlock (note: this can fail w/ symlinks, but... come on).
|
||||||
|
sort.Strings(possibleSources)
|
||||||
|
for _, filename := range possibleSources {
|
||||||
|
if err := lockFile(filename); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer unlockFile(filename)
|
||||||
|
}
|
||||||
|
|
||||||
startingConfig, err := configAccess.GetStartingConfig()
|
startingConfig, err := configAccess.GetStartingConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -186,7 +198,10 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
|
||||||
destinationFile = configAccess.GetDefaultFilename()
|
destinationFile = configAccess.GetDefaultFilename()
|
||||||
}
|
}
|
||||||
|
|
||||||
configToWrite := GetConfigFromFileOrDie(destinationFile)
|
configToWrite, err := getConfigFromFile(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
t := *cluster
|
t := *cluster
|
||||||
|
|
||||||
configToWrite.Clusters[key] = &t
|
configToWrite.Clusters[key] = &t
|
||||||
|
@ -211,7 +226,10 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
|
||||||
destinationFile = configAccess.GetDefaultFilename()
|
destinationFile = configAccess.GetDefaultFilename()
|
||||||
}
|
}
|
||||||
|
|
||||||
configToWrite := GetConfigFromFileOrDie(destinationFile)
|
configToWrite, err := getConfigFromFile(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
configToWrite.Contexts[key] = context
|
configToWrite.Contexts[key] = context
|
||||||
|
|
||||||
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
||||||
|
@ -228,7 +246,10 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
|
||||||
destinationFile = configAccess.GetDefaultFilename()
|
destinationFile = configAccess.GetDefaultFilename()
|
||||||
}
|
}
|
||||||
|
|
||||||
configToWrite := GetConfigFromFileOrDie(destinationFile)
|
configToWrite, err := getConfigFromFile(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
t := *authInfo
|
t := *authInfo
|
||||||
configToWrite.AuthInfos[key] = &t
|
configToWrite.AuthInfos[key] = &t
|
||||||
configToWrite.AuthInfos[key].LocationOfOrigin = destinationFile
|
configToWrite.AuthInfos[key].LocationOfOrigin = destinationFile
|
||||||
|
@ -251,7 +272,10 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
|
||||||
destinationFile = configAccess.GetDefaultFilename()
|
destinationFile = configAccess.GetDefaultFilename()
|
||||||
}
|
}
|
||||||
|
|
||||||
configToWrite := GetConfigFromFileOrDie(destinationFile)
|
configToWrite, err := getConfigFromFile(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
delete(configToWrite.Clusters, key)
|
delete(configToWrite.Clusters, key)
|
||||||
|
|
||||||
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
||||||
|
@ -267,7 +291,10 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
|
||||||
destinationFile = configAccess.GetDefaultFilename()
|
destinationFile = configAccess.GetDefaultFilename()
|
||||||
}
|
}
|
||||||
|
|
||||||
configToWrite := GetConfigFromFileOrDie(destinationFile)
|
configToWrite, err := getConfigFromFile(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
delete(configToWrite.Contexts, key)
|
delete(configToWrite.Contexts, key)
|
||||||
|
|
||||||
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
||||||
|
@ -283,7 +310,10 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
|
||||||
destinationFile = configAccess.GetDefaultFilename()
|
destinationFile = configAccess.GetDefaultFilename()
|
||||||
}
|
}
|
||||||
|
|
||||||
configToWrite := GetConfigFromFileOrDie(destinationFile)
|
configToWrite, err := getConfigFromFile(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
delete(configToWrite.AuthInfos, key)
|
delete(configToWrite.AuthInfos, key)
|
||||||
|
|
||||||
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
if err := WriteToFile(*configToWrite, destinationFile); err != nil {
|
||||||
|
@ -330,7 +360,10 @@ func writeCurrentContext(configAccess ConfigAccess, newCurrentContext string) er
|
||||||
|
|
||||||
if configAccess.IsExplicitFile() {
|
if configAccess.IsExplicitFile() {
|
||||||
file := configAccess.GetExplicitFile()
|
file := configAccess.GetExplicitFile()
|
||||||
currConfig := GetConfigFromFileOrDie(file)
|
currConfig, err := getConfigFromFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
currConfig.CurrentContext = newCurrentContext
|
currConfig.CurrentContext = newCurrentContext
|
||||||
if err := WriteToFile(*currConfig, file); err != nil {
|
if err := WriteToFile(*currConfig, file); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -341,7 +374,10 @@ func writeCurrentContext(configAccess ConfigAccess, newCurrentContext string) er
|
||||||
|
|
||||||
if len(newCurrentContext) > 0 {
|
if len(newCurrentContext) > 0 {
|
||||||
destinationFile := configAccess.GetDefaultFilename()
|
destinationFile := configAccess.GetDefaultFilename()
|
||||||
config := GetConfigFromFileOrDie(destinationFile)
|
config, err := getConfigFromFile(destinationFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
config.CurrentContext = newCurrentContext
|
config.CurrentContext = newCurrentContext
|
||||||
|
|
||||||
if err := WriteToFile(*config, destinationFile); err != nil {
|
if err := WriteToFile(*config, destinationFile); err != nil {
|
||||||
|
@ -354,7 +390,10 @@ func writeCurrentContext(configAccess ConfigAccess, newCurrentContext string) er
|
||||||
// we're supposed to be clearing the current context. We need to find the first spot in the chain that is setting it and clear it
|
// we're supposed to be clearing the current context. We need to find the first spot in the chain that is setting it and clear it
|
||||||
for _, file := range configAccess.GetLoadingPrecedence() {
|
for _, file := range configAccess.GetLoadingPrecedence() {
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
currConfig := GetConfigFromFileOrDie(file)
|
currConfig, err := getConfigFromFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(currConfig.CurrentContext) > 0 {
|
if len(currConfig.CurrentContext) > 0 {
|
||||||
currConfig.CurrentContext = newCurrentContext
|
currConfig.CurrentContext = newCurrentContext
|
||||||
|
@ -379,7 +418,10 @@ func writePreferences(configAccess ConfigAccess, newPrefs clientcmdapi.Preferenc
|
||||||
|
|
||||||
if configAccess.IsExplicitFile() {
|
if configAccess.IsExplicitFile() {
|
||||||
file := configAccess.GetExplicitFile()
|
file := configAccess.GetExplicitFile()
|
||||||
currConfig := GetConfigFromFileOrDie(file)
|
currConfig, err := getConfigFromFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
currConfig.Preferences = newPrefs
|
currConfig.Preferences = newPrefs
|
||||||
if err := WriteToFile(*currConfig, file); err != nil {
|
if err := WriteToFile(*currConfig, file); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -389,7 +431,10 @@ func writePreferences(configAccess ConfigAccess, newPrefs clientcmdapi.Preferenc
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range configAccess.GetLoadingPrecedence() {
|
for _, file := range configAccess.GetLoadingPrecedence() {
|
||||||
currConfig := GetConfigFromFileOrDie(file)
|
currConfig, err := getConfigFromFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(currConfig.Preferences, newPrefs) {
|
if !reflect.DeepEqual(currConfig.Preferences, newPrefs) {
|
||||||
currConfig.Preferences = newPrefs
|
currConfig.Preferences = newPrefs
|
||||||
|
@ -404,15 +449,23 @@ func writePreferences(configAccess ConfigAccess, newPrefs clientcmdapi.Preferenc
|
||||||
return errors.New("no config found to write preferences")
|
return errors.New("no config found to write preferences")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfigFromFileOrDie tries to read a kubeconfig file and if it can't, it calls exit. One exception, missing files result in empty configs, not an exit
|
// getConfigFromFile tries to read a kubeconfig file and if it can't, returns an error. One exception, missing files result in empty configs, not an error.
|
||||||
func GetConfigFromFileOrDie(filename string) *clientcmdapi.Config {
|
func getConfigFromFile(filename string) (*clientcmdapi.Config, error) {
|
||||||
config, err := LoadFromFile(filename)
|
config, err := LoadFromFile(filename)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
glog.FatalDepth(1, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return clientcmdapi.NewConfig()
|
config = clientcmdapi.NewConfig()
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfigFromFileOrDie tries to read a kubeconfig file and if it can't, it calls exit. One exception, missing files result in empty configs, not an exit
|
||||||
|
func GetConfigFromFileOrDie(filename string) *clientcmdapi.Config {
|
||||||
|
config, err := getConfigFromFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
glog.FatalDepth(1, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
|
@ -382,12 +382,6 @@ func WriteToFile(config clientcmdapi.Config, filename string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lockFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer unlockFile(filename)
|
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filename, content, 0600); err != nil {
|
if err := ioutil.WriteFile(filename, content, 0600); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -397,6 +391,14 @@ func WriteToFile(config clientcmdapi.Config, filename string) error {
|
||||||
func lockFile(filename string) error {
|
func lockFile(filename string) error {
|
||||||
// TODO: find a way to do this with actual file locks. Will
|
// TODO: find a way to do this with actual file locks. Will
|
||||||
// probably need seperate solution for windows and linux.
|
// probably need seperate solution for windows and linux.
|
||||||
|
|
||||||
|
// Make sure the dir exists before we try to create a lock file.
|
||||||
|
dir := filepath.Dir(filename)
|
||||||
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
|
if err = os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
f, err := os.OpenFile(lockName(filename), os.O_CREATE|os.O_EXCL, 0)
|
f, err := os.OpenFile(lockName(filename), os.O_CREATE|os.O_EXCL, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in New Issue