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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
	caData := []byte("ca-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 {
 | 
			
		||||
		startingContext, exists := startingConfig.Contexts[key]
 | 
			
		||||
		if !reflect.DeepEqual(context, startingContext) || !exists {
 | 
			
		||||
@@ -228,15 +231,28 @@ func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, rela
 | 
			
		||||
				destinationFile = configAccess.GetDefaultFilename()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			configToWrite, err := getConfigFromFile(destinationFile)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			// 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 {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				seenConfigs[destinationFile] = configToWrite
 | 
			
		||||
			}
 | 
			
		||||
			configToWrite.Contexts[key] = context
 | 
			
		||||
 | 
			
		||||
			if err := WriteToFile(*configToWrite, destinationFile); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			configToWrite.Contexts[key] = context
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// actually persist config object changes
 | 
			
		||||
	for destinationFile, configToWrite := range seenConfigs {
 | 
			
		||||
		if err := WriteToFile(*configToWrite, destinationFile); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user