improve kubeconfig file modification time
Trades runtime complexity for spacial complexity when modifying large amounts of contexts on a kubeconfig. In cases where there are few destination filenames for a given amount of contexts, but a large amount of contexts, this patch prevents reading and writing to the same file (or small number of files) over and over again needlessly.
This commit is contained in:
		@@ -126,6 +126,46 @@ func TestMergeContext(t *testing.T) {
 | 
				
			|||||||
	matchStringArg(namespace, actual, t)
 | 
						matchStringArg(namespace, actual, t)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestModifyContext(t *testing.T) {
 | 
				
			||||||
 | 
						expectedCtx := map[string]bool{
 | 
				
			||||||
 | 
							"updated": true,
 | 
				
			||||||
 | 
							"clean":   true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pathOptions := NewDefaultPathOptions()
 | 
				
			||||||
 | 
						config := createValidTestConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// define new context and assign it - our path options config
 | 
				
			||||||
 | 
						config.Contexts["updated"] = &clientcmdapi.Context{
 | 
				
			||||||
 | 
							Cluster:  "updated",
 | 
				
			||||||
 | 
							AuthInfo: "updated",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config.CurrentContext = "updated"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := ModifyConfig(pathOptions, *config, true); err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						startingConfig, err := pathOptions.GetStartingConfig()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// make sure the current context was updated
 | 
				
			||||||
 | 
						matchStringArg("updated", startingConfig.CurrentContext, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// there should now be two contexts
 | 
				
			||||||
 | 
						if len(startingConfig.Contexts) != len(expectedCtx) {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected nuber of contexts, expecting %v, but found %v", len(expectedCtx), len(startingConfig.Contexts))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for key := range startingConfig.Contexts {
 | 
				
			||||||
 | 
							if !expectedCtx[key] {
 | 
				
			||||||
 | 
								t.Fatalf("expected context %q to exist", key)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestCertificateData(t *testing.T) {
 | 
					func TestCertificateData(t *testing.T) {
 | 
				
			||||||
	caData := []byte("ca-data")
 | 
						caData := []byte("ca-data")
 | 
				
			||||||
	certData := []byte("cert-data")
 | 
						certData := []byte("cert-data")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -220,6 +220,9 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// seenConfigs stores a map of config source filenames to computed config objects
 | 
				
			||||||
 | 
						seenConfigs := map[string]*clientcmdapi.Config{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for key, context := range newConfig.Contexts {
 | 
						for key, context := range newConfig.Contexts {
 | 
				
			||||||
		startingContext, exists := startingConfig.Contexts[key]
 | 
							startingContext, exists := startingConfig.Contexts[key]
 | 
				
			||||||
		if !reflect.DeepEqual(context, startingContext) || !exists {
 | 
							if !reflect.DeepEqual(context, startingContext) || !exists {
 | 
				
			||||||
@@ -228,17 +231,30 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
 | 
				
			|||||||
				destinationFile = configAccess.GetDefaultFilename()
 | 
									destinationFile = configAccess.GetDefaultFilename()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			configToWrite, err := getConfigFromFile(destinationFile)
 | 
								// we only obtain a fresh config object from its source file
 | 
				
			||||||
 | 
								// if we have not seen it already - this prevents us from
 | 
				
			||||||
 | 
								// reading and writing to the same number of files repeatedly
 | 
				
			||||||
 | 
								// when multiple / all contexts share the same destination file.
 | 
				
			||||||
 | 
								configToWrite, seen := seenConfigs[destinationFile]
 | 
				
			||||||
 | 
								if !seen {
 | 
				
			||||||
 | 
									var err error
 | 
				
			||||||
 | 
									configToWrite, err = getConfigFromFile(destinationFile)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			configToWrite.Contexts[key] = context
 | 
									seenConfigs[destinationFile] = configToWrite
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								configToWrite.Contexts[key] = context
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// actually persist config object changes
 | 
				
			||||||
 | 
						for destinationFile, configToWrite := range seenConfigs {
 | 
				
			||||||
		if err := WriteToFile(*configToWrite, destinationFile); err != nil {
 | 
							if err := WriteToFile(*configToWrite, destinationFile); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for key, authInfo := range newConfig.AuthInfos {
 | 
						for key, authInfo := range newConfig.AuthInfos {
 | 
				
			||||||
		startingAuthInfo, exists := startingConfig.AuthInfos[key]
 | 
							startingAuthInfo, exists := startingConfig.AuthInfos[key]
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user