88 lines
4.1 KiB
Go
88 lines
4.1 KiB
Go
|
|
package cluster
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"scm.bstein.dev/bstein/ananke/internal/config"
|
||
|
|
)
|
||
|
|
|
||
|
|
// TestImagePullCredentialBlockerReasonsClassifiesHarborAuth runs one
|
||
|
|
// orchestration or CLI step.
|
||
|
|
// Signature: TestImagePullCredentialBlockerReasonsClassifiesHarborAuth(t *testing.T).
|
||
|
|
// Why: Harbor auth failures should drive secret-sync repair instead of pod
|
||
|
|
// recycling or DNS remediation.
|
||
|
|
func TestImagePullCredentialBlockerReasonsClassifiesHarborAuth(t *testing.T) {
|
||
|
|
events := `{"items":[` +
|
||
|
|
`{"involvedObject":{"kind":"Pod","namespace":"veles","name":"veles-backend"},"type":"Warning","reason":"Failed","message":"Failed to pull image \"registry.bstein.dev/veles/veles-backend:0.5.25\": no basic auth credentials"},` +
|
||
|
|
`{"metadata":{"namespace":"veles"},"involvedObject":{"kind":"Pod","name":"veles-frontend"},"type":"Warning","reason":"FailedToRetrieveImagePullSecret","message":"Unable to retrieve some image pull secrets (harbor-regcred); attempting to pull the image may not succeed."},` +
|
||
|
|
`{"involvedObject":{"kind":"Pod","namespace":"logging","name":"oauth2"},"type":"Warning","reason":"Failed","message":"Failed to pull image: lookup registry-1.docker.io: Try again"}` +
|
||
|
|
`]}`
|
||
|
|
orch := buildOrchestratorWithStubs(t, config.Config{}, []commandStub{
|
||
|
|
{match: matchContains("kubectl", "get", "events", "-A", "-o", "json"), out: events},
|
||
|
|
})
|
||
|
|
|
||
|
|
reasons, err := orch.imagePullCredentialBlockerReasons(context.Background())
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("imagePullCredentialBlockerReasons failed: %v", err)
|
||
|
|
}
|
||
|
|
if got := reasons["veles/veles-backend"]; got != "ImagePullCredentialBlocker:no-basic-auth" {
|
||
|
|
t.Fatalf("unexpected backend credential reason %q", got)
|
||
|
|
}
|
||
|
|
if got := reasons["veles/veles-frontend"]; got != "ImagePullCredentialBlocker:missing-pull-secret" {
|
||
|
|
t.Fatalf("unexpected frontend credential reason %q", got)
|
||
|
|
}
|
||
|
|
if _, ok := reasons["logging/oauth2"]; ok {
|
||
|
|
t.Fatalf("DNS image-pull blocker must not be classified as credential failure")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// TestHealImagePullCredentialSyncRestartsVaultSyncDeployment runs one
|
||
|
|
// orchestration or CLI step.
|
||
|
|
// Signature: TestHealImagePullCredentialSyncRestartsVaultSyncDeployment(t *testing.T).
|
||
|
|
// Why: a namespace with registry credential blockers and a Vault CSI sync helper
|
||
|
|
// should get that sync helper rolled instead of application pods deleted.
|
||
|
|
func TestHealImagePullCredentialSyncRestartsVaultSyncDeployment(t *testing.T) {
|
||
|
|
events := `{"items":[{"involvedObject":{"kind":"Pod","namespace":"veles","name":"veles-backend"},"type":"Warning","reason":"Failed","message":"Failed to pull image \"registry.bstein.dev/veles/veles-backend:0.5.25\": no basic auth credentials"}]}`
|
||
|
|
deployments := `{"items":[` +
|
||
|
|
`{"metadata":{"name":"veles-backend","labels":{"app.kubernetes.io/name":"veles-backend"}}},` +
|
||
|
|
`{"metadata":{"name":"veles-vault-sync","labels":{"app.kubernetes.io/component":"vault-sync"}}}` +
|
||
|
|
`]}`
|
||
|
|
restarted := false
|
||
|
|
rolledOut := false
|
||
|
|
orch := buildOrchestratorWithStubs(t, config.Config{}, []commandStub{
|
||
|
|
{match: matchContains("kubectl", "get", "events", "-A", "-o", "json"), out: events},
|
||
|
|
{match: matchContains("kubectl", "-n", "veles", "get", "deployment", "-o", "json"), out: deployments},
|
||
|
|
{
|
||
|
|
match: func(name string, args []string) bool {
|
||
|
|
if !matchContains("kubectl", "-n", "veles", "rollout", "restart", "deployment", "veles-vault-sync")(name, args) {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
restarted = true
|
||
|
|
return true
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
match: func(name string, args []string) bool {
|
||
|
|
if !matchContains("kubectl", "-n", "veles", "rollout", "status", "deployment/veles-vault-sync", "--timeout=60s")(name, args) {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
rolledOut = true
|
||
|
|
return true
|
||
|
|
},
|
||
|
|
},
|
||
|
|
})
|
||
|
|
|
||
|
|
repaired, err := orch.healImagePullCredentialSync(context.Background())
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("healImagePullCredentialSync failed: %v", err)
|
||
|
|
}
|
||
|
|
if strings.Join(repaired, ",") != "veles/deployment/veles-vault-sync" {
|
||
|
|
t.Fatalf("unexpected image-pull credential repair list: %#v", repaired)
|
||
|
|
}
|
||
|
|
if !restarted || !rolledOut {
|
||
|
|
t.Fatalf("expected vault-sync deployment restart and rollout wait, restarted=%v rolledOut=%v", restarted, rolledOut)
|
||
|
|
}
|
||
|
|
}
|