mirror of
https://github.com/skoelle/kctl-tui.git
synced 2026-09-18 04:20:25 +00:00
Add pure secret-diff logic (kctl.DiffSecretValues) with unit tests
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
package kctl
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
// SecretDiffEntry represents the comparison of one key between two secret
|
||||||
|
// sources (e.g. AWS Secrets Manager vs. a Kubernetes Secret).
|
||||||
|
type SecretDiffEntry struct {
|
||||||
|
Key string
|
||||||
|
Left string // e.g. the AWS Secrets Manager value
|
||||||
|
Right string // e.g. the decoded Kubernetes secret value
|
||||||
|
Match bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiffSecretValues compares two key/value maps and returns a sorted list of
|
||||||
|
// diff entries covering the union of keys present in either map. A key that
|
||||||
|
// only exists on one side is still reported, with the missing side left as
|
||||||
|
// an empty string and Match set to false (unless both sides happen to be
|
||||||
|
// empty strings).
|
||||||
|
func DiffSecretValues(left, right map[string]string) []SecretDiffEntry {
|
||||||
|
seen := map[string]bool{}
|
||||||
|
for k := range left {
|
||||||
|
seen[k] = true
|
||||||
|
}
|
||||||
|
for k := range right {
|
||||||
|
seen[k] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := make([]string, 0, len(seen))
|
||||||
|
for k := range seen {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
result := make([]SecretDiffEntry, 0, len(keys))
|
||||||
|
for _, k := range keys {
|
||||||
|
l := left[k]
|
||||||
|
r := right[k]
|
||||||
|
result = append(result, SecretDiffEntry{Key: k, Left: l, Right: r, Match: l == r})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyMismatch reports whether at least one diff entry does not match.
|
||||||
|
func AnyMismatch(entries []SecretDiffEntry) bool {
|
||||||
|
for _, e := range entries {
|
||||||
|
if !e.Match {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package kctl
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestDiffSecretValues_AllMatch(t *testing.T) {
|
||||||
|
left := map[string]string{"a": "1", "b": "2"}
|
||||||
|
right := map[string]string{"a": "1", "b": "2"}
|
||||||
|
|
||||||
|
entries := DiffSecretValues(left, right)
|
||||||
|
if len(entries) != 2 {
|
||||||
|
t.Fatalf("expected 2 entries, got %d", len(entries))
|
||||||
|
}
|
||||||
|
if AnyMismatch(entries) {
|
||||||
|
t.Fatalf("expected no mismatch, got %v", entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiffSecretValues_Mismatch(t *testing.T) {
|
||||||
|
left := map[string]string{"a": "1", "b": "2"}
|
||||||
|
right := map[string]string{"a": "1", "b": "different"}
|
||||||
|
|
||||||
|
entries := DiffSecretValues(left, right)
|
||||||
|
if !AnyMismatch(entries) {
|
||||||
|
t.Fatalf("expected a mismatch, got %v", entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
var bEntry *SecretDiffEntry
|
||||||
|
for i := range entries {
|
||||||
|
if entries[i].Key == "b" {
|
||||||
|
bEntry = &entries[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bEntry == nil || bEntry.Match {
|
||||||
|
t.Fatalf("expected key 'b' to be a mismatch, got %v", bEntry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiffSecretValues_KeyOnlyOnOneSide(t *testing.T) {
|
||||||
|
left := map[string]string{"a": "1", "only-left": "x"}
|
||||||
|
right := map[string]string{"a": "1", "only-right": "y"}
|
||||||
|
|
||||||
|
entries := DiffSecretValues(left, right)
|
||||||
|
if len(entries) != 3 {
|
||||||
|
t.Fatalf("expected 3 entries (union of keys), got %d: %v", len(entries), entries)
|
||||||
|
}
|
||||||
|
if !AnyMismatch(entries) {
|
||||||
|
t.Fatalf("expected mismatch due to keys only present on one side")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiffSecretValues_EmptyMaps(t *testing.T) {
|
||||||
|
entries := DiffSecretValues(nil, nil)
|
||||||
|
if len(entries) != 0 {
|
||||||
|
t.Fatalf("expected no entries for empty maps, got %v", entries)
|
||||||
|
}
|
||||||
|
if AnyMismatch(entries) {
|
||||||
|
t.Fatalf("expected no mismatch for empty maps")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user