Add the Proxy reconciler state machine with action-table, phase, and envtest suites
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
118
internal/controller/spechash_test.go
Normal file
118
internal/controller/spechash_test.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
crawlv1alpha1 "gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/api/v1alpha1"
|
||||
)
|
||||
|
||||
func hashProxy(mut ...func(*crawlv1alpha1.Proxy)) *crawlv1alpha1.Proxy {
|
||||
p := &crawlv1alpha1.Proxy{
|
||||
Spec: crawlv1alpha1.ProxySpec{
|
||||
Mode: crawlv1alpha1.ModeManaged,
|
||||
Provider: "stub",
|
||||
Port: 3128,
|
||||
Placement: &crawlv1alpha1.PlacementSpec{
|
||||
Zone: "europe-west1-b",
|
||||
MachineType: "e2-micro",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, m := range mut {
|
||||
m(p)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func TestSpecHash_stability(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
p := hashProxy()
|
||||
h1 := specHash(p, "cloud-init-content")
|
||||
h2 := specHash(p.DeepCopy(), "cloud-init-content")
|
||||
if h1 != h2 {
|
||||
t.Errorf("same input hashed differently: %s vs %s", h1, h2)
|
||||
}
|
||||
if !regexp.MustCompile(`^[0-9a-f]{64}$`).MatchString(h1) {
|
||||
t.Errorf("hash %q is not hex SHA-256", h1)
|
||||
}
|
||||
|
||||
// Fields outside the replacement set must not affect the hash — that is
|
||||
// the whole point of an explicit hash-input struct.
|
||||
q := hashProxy(func(p *crawlv1alpha1.Proxy) {
|
||||
p.Spec.Attributes = map[string]string{"geo": "eu"}
|
||||
five := int32(5)
|
||||
p.Spec.MaxLeases = &five
|
||||
p.Spec.HealthCheck = &crawlv1alpha1.HealthCheckSpec{IntervalSeconds: 60}
|
||||
})
|
||||
if specHash(q, "cloud-init-content") != h1 {
|
||||
t.Error("non-replacement spec fields changed the hash")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpecHash_normalization(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nilPlacement := hashProxy(func(p *crawlv1alpha1.Proxy) { p.Spec.Placement = nil })
|
||||
emptyPlacement := hashProxy(func(p *crawlv1alpha1.Proxy) {
|
||||
p.Spec.Placement = &crawlv1alpha1.PlacementSpec{}
|
||||
})
|
||||
if specHash(nilPlacement, "") != specHash(emptyPlacement, "") {
|
||||
t.Error("nil and empty placement hashed differently")
|
||||
}
|
||||
|
||||
// An unset port and an explicit default port mean the same instance.
|
||||
unsetPort := hashProxy(func(p *crawlv1alpha1.Proxy) { p.Spec.Port = 0 })
|
||||
defaultPort := hashProxy(func(p *crawlv1alpha1.Proxy) { p.Spec.Port = crawlv1alpha1.DefaultPort })
|
||||
if specHash(unsetPort, "") != specHash(defaultPort, "") {
|
||||
t.Error("unset port and explicit default port hashed differently")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpecHash_sensitivity(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
base := specHash(hashProxy(), "cloud-init")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
proxy *crawlv1alpha1.Proxy
|
||||
cloudInit string
|
||||
}{
|
||||
{
|
||||
name: "port change",
|
||||
proxy: hashProxy(func(p *crawlv1alpha1.Proxy) { p.Spec.Port = 8080 }),
|
||||
cloudInit: "cloud-init",
|
||||
},
|
||||
{
|
||||
name: "zone change",
|
||||
proxy: hashProxy(func(p *crawlv1alpha1.Proxy) { p.Spec.Placement.Zone = "us-east1-c" }),
|
||||
cloudInit: "cloud-init",
|
||||
},
|
||||
{
|
||||
name: "machine type change",
|
||||
proxy: hashProxy(func(p *crawlv1alpha1.Proxy) { p.Spec.Placement.MachineType = "e2-small" }),
|
||||
cloudInit: "cloud-init",
|
||||
},
|
||||
{
|
||||
name: "image change",
|
||||
proxy: hashProxy(func(p *crawlv1alpha1.Proxy) { p.Spec.Placement.Image = "debian-13" }),
|
||||
cloudInit: "cloud-init",
|
||||
},
|
||||
{
|
||||
name: "resolved cloud-init change (secret rotation)",
|
||||
proxy: hashProxy(),
|
||||
cloudInit: "rotated-cloud-init",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if specHash(tc.proxy, tc.cloudInit) == base {
|
||||
t.Error("hash did not change")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user