ModifyConfig takes a Config object, iterates through Clusters, AuthInfos, and Contexts, uses the LocationOfOrigin if specified or uses the default destination file to write the results into. This results in multiple file reads, but it's very easy to follow. Preferences and CurrentContext should alw
(configAccess ConfigAccess, newConfig clientcmdapi.Config, relativizePaths bool)
| 156 | // 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 |
| 157 | // modified element. |
| 158 | func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, relativizePaths bool) error { |
| 159 | possibleSources := configAccess.GetLoadingPrecedence() |
| 160 | // sort the possible kubeconfig files so we always "lock" in the same order |
| 161 | // to avoid deadlock (note: this can fail w/ symlinks, but... come on). |
| 162 | sort.Strings(possibleSources) |
| 163 | for _, filename := range possibleSources { |
| 164 | if err := lockFile(filename); err != nil { |
| 165 | return err |
| 166 | } |
| 167 | defer unlockFile(filename) |
| 168 | } |
| 169 | |
| 170 | startingConfig, err := configAccess.GetStartingConfig() |
| 171 | if err != nil { |
| 172 | return err |
| 173 | } |
| 174 | |
| 175 | // We need to find all differences, locate their original files, read a partial config to modify only that stanza and write out the file. |
| 176 | // Special case the test for current context and preferences since those always write to the default file. |
| 177 | if reflect.DeepEqual(*startingConfig, newConfig) { |
| 178 | // nothing to do |
| 179 | return nil |
| 180 | } |
| 181 | |
| 182 | if startingConfig.CurrentContext != newConfig.CurrentContext { |
| 183 | if err := writeCurrentContext(configAccess, newConfig.CurrentContext); err != nil { |
| 184 | return err |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | if !reflect.DeepEqual(startingConfig.Preferences, newConfig.Preferences) { |
| 189 | if err := writePreferences(configAccess, newConfig.Preferences); err != nil { |
| 190 | return err |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | // Search every cluster, authInfo, and context. First from new to old for differences, then from old to new for deletions |
| 195 | for key, cluster := range newConfig.Clusters { |
| 196 | startingCluster, exists := startingConfig.Clusters[key] |
| 197 | if !reflect.DeepEqual(cluster, startingCluster) || !exists { |
| 198 | destinationFile := cluster.LocationOfOrigin |
| 199 | if len(destinationFile) == 0 { |
| 200 | destinationFile = configAccess.GetDefaultFilename() |
| 201 | } |
| 202 | |
| 203 | configToWrite, err := getConfigFromFile(destinationFile) |
| 204 | if err != nil { |
| 205 | return err |
| 206 | } |
| 207 | t := *cluster |
| 208 | |
| 209 | configToWrite.Clusters[key] = &t |
| 210 | configToWrite.Clusters[key].LocationOfOrigin = destinationFile |
| 211 | if relativizePaths { |
| 212 | if err := RelativizeClusterLocalPaths(configToWrite.Clusters[key]); err != nil { |
| 213 | return err |
| 214 | } |
| 215 | } |