Skip to content

Commit e08b1e8

Browse files
committed
feat: print diff before confirm prompt
1 parent 1bd58d1 commit e08b1e8

3 files changed

Lines changed: 39 additions & 19 deletions

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ require (
2525
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
2626
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
2727
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
28+
github.com/sergi/go-diff v1.4.0 // indirect
2829
github.com/spf13/pflag v1.0.9 // indirect
2930
github.com/x448/float16 v0.8.4 // indirect
3031
go.yaml.in/yaml/v2 v2.4.3 // indirect

go.sum

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
3939
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
4040
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
4141
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
42+
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
4243
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
4344
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
4445
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -66,6 +67,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
6667
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
6768
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
6869
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
70+
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
71+
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
6972
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
7073
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
7174
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -74,6 +77,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
7477
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
7578
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
7679
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
80+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
7781
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
7882
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
7983
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
@@ -107,12 +111,15 @@ golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs
107111
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
108112
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
109113
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
114+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
110115
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
111116
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
112117
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
113118
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
114119
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
115120
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
121+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
122+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
116123
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
117124
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
118125
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

main.go

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ package main
33
import (
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

1415
var (
@@ -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

Comments
 (0)