Last active
March 29, 2022 14:26
-
-
Save mniak/79dfc8d590552c3312ea35926bac33ef to your computer and use it in GitHub Desktop.
This file contains hidden or 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 main | |
import ( | |
"bytes" | |
"errors" | |
"fmt" | |
"log" | |
"os" | |
"os/exec" | |
"path/filepath" | |
"strings" | |
"github.com/manifoldco/promptui" | |
"github.com/samber/lo" | |
"github.com/spf13/cobra" | |
"golang.org/x/exp/slices" | |
appsv1 "k8s.io/api/apps/v1" | |
corev1 "k8s.io/api/core/v1" | |
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |
"k8s.io/client-go/kubernetes" | |
"k8s.io/client-go/tools/clientcmd" | |
"k8s.io/client-go/util/homedir" | |
) | |
func main() { | |
if home := homedir.HomeDir(); home != "" { | |
rootCmd.Flags().String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") | |
} else { | |
rootCmd.Flags().String("kubeconfig", "", "absolute path to the kubeconfig file") | |
} | |
rootCmd.Flags().StringP("output", "p", ".env", "output file") | |
rootCmd.Execute() | |
} | |
func handle(err error) { | |
if err != nil { | |
log.Fatalln("Fatal:", err) | |
} | |
} | |
func execSimple(program string, args ...string) (string, error) { | |
cmd := exec.Command(program, args...) | |
var stdoutBuffer bytes.Buffer | |
var stderrBuffer bytes.Buffer | |
cmd.Stdout = &stdoutBuffer | |
cmd.Stderr = &stderrBuffer | |
err := cmd.Run() | |
if err != nil { | |
return stdoutBuffer.String(), err | |
} | |
return stdoutBuffer.String(), err | |
} | |
func selectItem[T any](prompt string, items map[string]T) (T, error) { | |
if len(items) == 0 { | |
var zero T | |
return zero, errors.New("the list has no items") | |
} | |
if len(items) == 1 { | |
for _, v := range items { | |
return v, nil | |
} | |
} | |
keys := lo.Keys(items) | |
slices.Sort(keys) | |
_, selectedKey, err := (&promptui.Select{ | |
Label: "Select Pod", | |
Items: keys, | |
}).Run() | |
if err != nil { | |
var zero T | |
return zero, err | |
} | |
return items[selectedKey], nil | |
} | |
var rootCmd = cobra.Command{ | |
Use: "export-env", | |
Run: func(cmd *cobra.Command, args []string) { | |
kubeconfig, err := cmd.Flags().GetString("kubeconfig") | |
handle(err) | |
outputFile, err := cmd.Flags().GetString("output") | |
handle(err) | |
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) | |
handle(err) | |
clientset, err := kubernetes.NewForConfig(config) | |
handle(err) | |
ns, err := execSimple("kubens", "-c") | |
handle(err) | |
ns = strings.Trim(ns, "\n") | |
deployments, err := clientset.AppsV1().Deployments(ns).List(cmd.Context(), metav1.ListOptions{}) | |
handle(err) | |
gApp := lo.GroupBy(deployments.Items, func(p appsv1.Deployment) string { | |
return p.Labels["app"] | |
}) | |
deploymentsList, err := selectItem("Select the Application", gApp) | |
handle(err) | |
gDeployment := lo.KeyBy(deploymentsList, func(p appsv1.Deployment) string { | |
return p.Labels["fullname"] | |
}) | |
deployment, err := selectItem("Select the Deployment", gDeployment) | |
handle(err) | |
gContainer := lo.KeyBy(deployment.Spec.Template.Spec.Containers, func(c corev1.Container) string { | |
return c.Name | |
}) | |
container, err := selectItem("Select the Container", gContainer) | |
envmap := lo.MapValues( | |
lo.KeyBy(container.Env, func(x corev1.EnvVar) string { | |
return x.Name | |
}), | |
func(v corev1.EnvVar, k string) string { | |
return v.Value | |
}, | |
) | |
for _, envFrom := range container.EnvFrom { | |
if envFrom.ConfigMapRef != nil { | |
configmap, err := clientset.CoreV1().ConfigMaps(ns).Get(cmd.Context(), envFrom.ConfigMapRef.Name, metav1.GetOptions{}) | |
handle(err) | |
for k, v := range configmap.Data { | |
envmap[k] = v | |
} | |
} else if envFrom.SecretRef != nil { | |
secret, err := clientset.CoreV1().Secrets(ns).Get(cmd.Context(), envFrom.SecretRef.Name, metav1.GetOptions{}) | |
handle(err) | |
for k, v := range secret.Data { | |
envmap[k] = string(v) | |
} | |
for k, v := range secret.StringData { | |
envmap[k] = v | |
} | |
} | |
} | |
os.WriteFile(outputFile, []byte(buildDotEnv(envmap)), 0o755) | |
}, | |
} | |
func quote(text string) string { | |
replacer := strings.NewReplacer( | |
"\n", "\\n", | |
) | |
return fmt.Sprintf(`"%s"`, replacer.Replace(text)) | |
} | |
func buildDotEnv(envmap map[string]string) string { | |
var sb strings.Builder | |
for k, v := range envmap { | |
sb.WriteString(fmt.Sprintf("%s=%s\n", k, quote(v))) | |
} | |
return sb.String() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment