Created
January 30, 2022 13:15
-
-
Save elig-salt/fb63120ed3aa766e1d9053b6ae867517 to your computer and use it in GitHub Desktop.
Configure-telepresence
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cmd | |
import ( | |
"bytes" | |
"errors" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"os" | |
"path/filepath" | |
"strings" | |
"github.com/spf13/cobra" | |
"gopkg.in/yaml.v3" | |
) | |
var current bool | |
var namespace string | |
var clusterName string | |
// configDebugCmd represents the configDebug command | |
var configDebugCmd = &cobra.Command{ | |
Use: "config-debug", | |
Short: "Configure a local environment to work against telepresence", | |
Run: func(cmd *cobra.Command, args []string) { | |
if err := configDebug(); err != nil { | |
log.Fatal(err) | |
} | |
}, | |
} | |
func init() { | |
configDebugCmd.Flags().BoolVar(¤t, "current", false, "Use the currently selected cluster and namespace") | |
configDebugCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "the namespace to set") | |
configDebugCmd.Flags().StringVarP(&clusterName, "cluster", "c", "", "The cluster name to modify") | |
rootCmd.AddCommand(configDebugCmd) | |
} | |
func configDebug() error { | |
if clusterName == "" { | |
return errors.New("Please specify a cluster name") | |
} | |
if namespace == "" { | |
return errors.New("Please specify a namespace") | |
} | |
if namespace == "prod" { | |
return errors.New("Cannot use 'prod' namespace") | |
} | |
fmt.Printf("Pointing Telepresence on cluster \"%v\" to work against namespace \"%v\"\n", clusterName, namespace) | |
home, exists := os.LookupEnv("HOME") | |
if !exists { | |
home = "/root" | |
} | |
configPath := filepath.Join(home, ".kube", "config") | |
m := make(map[interface{}]interface{}) | |
// Read the yaml from kubeconfig into t | |
if err := readConfig(m, configPath); err != nil { | |
return fmt.Errorf("Could not read config: %v", err) | |
} | |
if err := modifyKubeConfig(m, clusterName, namespace); err != nil { | |
return err | |
} | |
if err := writeConfig(m, configPath); err != nil { | |
return fmt.Errorf("Could not write config: %v", err) | |
} | |
fmt.Printf("Config saved to: \"%v\"\n", configPath) | |
return nil | |
} | |
func modifyKubeConfig(m map[interface{}]interface{}, clusterName, namespace string) error { | |
clustersFound := []string{} | |
clusters, ok := m["clusters"] | |
if !ok { | |
return fmt.Errorf("Corrupted kubeconfig file: Missing \"clusters\"") | |
} else { | |
clustersSlice, err := parseSlice(clusters) | |
if err != nil { | |
return fmt.Errorf("%v: clusters", err) | |
} | |
for _, currCluster := range clustersSlice { | |
clusterMap, err := parseMap(currCluster) | |
if err != nil { | |
return fmt.Errorf("%v: clusters", err) | |
} | |
clusterMapName, ok := clusterMap["name"] | |
if !ok { | |
return fmt.Errorf("Corrupted configuration: Missing Name in cluster") | |
} | |
currClusterName, ok := clusterMapName.(string) | |
if !ok { | |
return fmt.Errorf("Cluster name missing") | |
} else { | |
clustersFound = append(clustersFound, currClusterName) | |
if strings.HasSuffix(currClusterName, clusterName) { | |
clusterData, exists := clusterMap["cluster"] | |
if !exists { | |
return fmt.Errorf("Cluser config is corrupted: \"%v\"", currClusterName) | |
} | |
if clusterData := clusterData.(map[string]interface{}); ok { | |
setTelepresenceNamespaceToCluster(clusterData, namespace) | |
return nil | |
} else { | |
return fmt.Errorf("Cluser config is corrupted: \"%v\"", currClusterName) | |
} | |
} | |
} | |
} | |
return fmt.Errorf("Could not find requested cluster: %v\n\nClusters found:\n%v", clusterName, strings.Join(clustersFound, "\n")) | |
} | |
} | |
func readConfig(m map[interface{}]interface{}, configPath string) error { | |
yamlFile, err := ioutil.ReadFile(configPath) | |
if err != nil { | |
return fmt.Errorf("Error reading file: %v", err) | |
} | |
err = yaml.Unmarshal(yamlFile, &m) | |
if err != nil { | |
return fmt.Errorf("Error unmarshalling yaml: %v", err) | |
} | |
return nil | |
} | |
func writeConfig(config map[interface{}]interface{}, newConfigPath string) error { | |
var b bytes.Buffer | |
yamlEncoder := yaml.NewEncoder(&b) | |
yamlEncoder.SetIndent(2) | |
err := yamlEncoder.Encode(&config) | |
if err != nil { | |
return err | |
} | |
ioutil.WriteFile(newConfigPath, b.Bytes(), 600) | |
return nil | |
} | |
func setTelepresenceNamespaceToCluster(m map[string]interface{}, namespace string) { | |
m["extensions"] = []map[string]interface{}{ | |
{ | |
"extension": map[string]interface{}{ | |
"manager": map[string]interface{}{ | |
"namespace": namespace, | |
}, | |
}, | |
"name": "telepresence.io", | |
}, | |
} | |
} | |
func parseMap(val interface{}) (map[string]interface{}, error) { | |
if mapVals, ok := val.(map[string]interface{}); ok { | |
return mapVals, nil | |
} | |
return nil, errors.New("Could not parse map") | |
} | |
func parseSlice(val interface{}) ([]interface{}, error) { | |
if slice, ok := val.([]interface{}); ok { | |
return slice, nil | |
} | |
return nil, errors.New("Could not parse slice") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment