@@ -3,12 +3,13 @@ package main
33import (
44 "context"
55 "fmt"
6- "log "
6+ "os "
77 "slices"
88 "strings"
99 "time"
1010
1111 "github.com/manifoldco/promptui"
12+ "github.com/sergi/go-diff/diffmatchpatch"
1213)
1314
1415var (
@@ -26,71 +27,77 @@ func main() {
2627 fmt .Printf ("k8s-secret-editor version %s (" +
2728 "commit: %s, built at: %s, built by: %s" +
2829 ")\n " , version , commit , date , builtBy )
30+ return
2931 }
3032
3133 k8sClient , err := NewK8SClient (cfg .KubeConfig )
3234 if err != nil {
33- log . Fatalf ("Error creating Kubernetes client: %v" , err )
35+ fatalf ("Error creating Kubernetes client: %v" , err )
3436 }
3537
3638 editor , err := NewEditor (cfg .EditorPath )
3739 if err != nil {
38- log . Fatalf ("Error initializing editor: %v" , err )
40+ fatalf ("Error initializing editor: %v" , err )
3941 }
4042
41- fmt .Printf ("Loading namespaces...\n " )
4243 namespaces , err := withTimeoutCtx (func (ctx context.Context ) ([]string , error ) {
4344 return k8sClient .ListNamespaces (ctx )
4445 })
4546 if err != nil {
46- log . Fatalf ("Error loading namespaces: %v" , err )
47+ fatalf ("Error loading namespaces: %v" , err )
4748 }
4849 selectedNamespace := runPrompt ("Select namespace" , namespaces )
4950
50- fmt .Printf ("Loading secrets in namespace '%s'...\n " , selectedNamespace )
5151 secrets , err := withTimeoutCtx (func (ctx context.Context ) ([]string , error ) {
5252 return k8sClient .ListSecrets (ctx , selectedNamespace )
5353 })
5454 if err != nil {
55- log . Fatalf ("Error loading secrets: %v" , err )
55+ fatalf ("Error loading secrets: %v" , err )
5656 }
5757 selectedSecret := runPrompt (fmt .Sprintf ("Select secret in '%s'" , selectedNamespace ), secrets )
5858
59- fmt .Printf ("Loading secret '%s' in namespace '%s'...\n " , selectedSecret , selectedNamespace )
6059 secret , err := withTimeoutCtx (func (ctx context.Context ) (SecretData , error ) {
6160 return k8sClient .GetSecret (ctx , selectedNamespace , selectedSecret )
6261 })
6362 if err != nil {
64- log . Fatalf ("Error loading secret: %v" , err )
63+ fatalf ("Error loading secret: %v" , err )
6564 }
6665 keys := make ([]string , 0 , len (secret ))
6766 for k := range secret {
6867 keys = append (keys , k )
6968 }
7069 selectedKey := runPrompt (fmt .Sprintf ("Select key in secret '%s'" , selectedSecret ), keys )
71- data , ok := secret [selectedKey ]
70+ originData , ok := secret [selectedKey ]
7271 if ! ok {
73- log . Fatalf ("Key '%s' not found in secret '%s' in namespace '%s'" , selectedKey , selectedSecret , selectedNamespace )
72+ fatalf ("Key '%s' not found in secret '%s' in namespace '%s'" , selectedKey , selectedSecret , selectedNamespace )
7473 }
7574
7675 tmpFile , err := NewTmpFile ()
7776 if err != nil {
78- log . Fatalf ("Error creating temp file: %v" , err )
77+ fatalf ("Error creating temp file: %v" , err )
7978 }
8079 defer tmpFile .Close ()
81- if err := tmpFile .Write (data ); err != nil {
82- log . Fatalf ("Error writing secret data to temp file: %v" , err )
80+ if err := tmpFile .Write (originData ); err != nil {
81+ fatalf ("Error writing secret data to temp file: %v" , err )
8382 }
8483 if err := tmpFile .OpenEditor (editor ); err != nil {
85- log . Fatalf ("Error opening editor: %v" , err )
84+ fatalf ("Error opening editor: %v" , err )
8685 }
8786 editedData , err := tmpFile .Read ()
8887 if err != nil {
89- log .Fatalf ("Error reading edited data from temp file: %v" , err )
88+ fatalf ("Error reading edited data from temp file: %v" , err )
89+ }
90+
91+ if slices .Equal (originData , editedData ) {
92+ fmt .Println ("No changes detected, exiting." )
9093 }
9194
95+ dmp := diffmatchpatch .New ()
96+ diffs := dmp .DiffMain (string (originData ), string (editedData ), false )
97+ fmt .Println (dmp .DiffPrettyText (diffs ))
98+
9299 confirmPrompt := promptui.Prompt {
93- Label : fmt .Sprintf ("Save changes to secret '%s/%s' key '%s'" , selectedNamespace , selectedSecret , selectedKey ),
100+ Label : fmt .Sprintf ("Apply changes to secret '%s/%s' key '%s'" , selectedNamespace , selectedSecret , selectedKey ),
94101 IsConfirm : true ,
95102 }
96103 _ , err = confirmPrompt .Run ()
@@ -104,7 +111,7 @@ func main() {
104111 return struct {}{}, err
105112 })
106113 if err != nil {
107- log . Fatalf ("Error saving secret '%s' in namespace '%s': %v" , selectedSecret , selectedNamespace , err )
114+ fatalf ("Error saving secret '%s' in namespace '%s': %v" , selectedSecret , selectedNamespace , err )
108115 }
109116
110117 fmt .Printf ("Secret '%s' in namespace '%s' updated successfully.\n " , selectedSecret , selectedNamespace )
@@ -129,7 +136,7 @@ func runPrompt(title string, items []string) string {
129136 }
130137 _ , result , err := prompt .Run ()
131138 if err != nil {
132- log . Fatalf ("Prompt failed: %v" , err )
139+ fatalf ("Prompt failed: %v" , err )
133140 }
134141 return result
135142}
@@ -139,3 +146,8 @@ func withTimeoutCtx[T any](f func(context.Context) (T, error)) (T, error) {
139146 defer cancel ()
140147 return f (ctx )
141148}
149+
150+ func fatalf (format string , args ... interface {}) {
151+ fmt .Fprintln (os .Stderr , fmt .Sprintf (format , args ... ))
152+ os .Exit (1 )
153+ }
0 commit comments