106 lines
3.7 KiB
Go
106 lines
3.7 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
"github.com/novox/mesh-controller/internal/conditions"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
)
|
|
|
|
func TestAProviderFailingAConsumerBreaksAllWellUntilItRecovers(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
register(t, open, catalogue.Manifest{Module: "idp", Version: "1",
|
|
Receives: map[string]string{"oidc-client": "/var/lib/mesh/idp/mesh.json"}})
|
|
if _, err := assign(ctx, open, "anchor", "idp"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
kept := standings{keeper: func() *conditions.Keeper { return conditionsFrom }}
|
|
since := time.Now().Add(-23 * time.Hour)
|
|
failing := link.Standing{Module: "idp", Failing: true, Provider: "oidc-client", ProviderNode: "anchor",
|
|
Consumer: "mesh_laptop_dashboard", Node: "laptop", Class: "credentials-rejected",
|
|
Error: `Keycloak token request failed: 401 {"error":"invalid_grant"}`, Since: since, Attempts: 31000}
|
|
if _, err := kept.Stood(ctx, failing); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
asked, err := theThreeQuestions(ctx, open)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if asked.well() {
|
|
t.Fatal("a mesh whose identity provider fails a consumer reads as well")
|
|
}
|
|
said := printed(t, func() error { return printStatus(asked) })
|
|
for _, want := range []string{"1 open condition(s)", "provider.idp.anchor.mesh_laptop_dashboard.failing",
|
|
"idp on anchor keeps failing mesh_laptop_dashboard on laptop", "credentials-rejected", "31000 attempt(s)"} {
|
|
if !strings.Contains(said, want) {
|
|
t.Fatalf("status does not say %q:\n%s", want, said)
|
|
}
|
|
}
|
|
if strings.Contains(said, "all doing what they were told") {
|
|
t.Fatalf("status said all well beside a failing provider:\n%s", said)
|
|
}
|
|
if !strings.HasPrefix(said, "1 open condition(s)") {
|
|
t.Fatalf("status does not lead with what is open:\n%s", said)
|
|
}
|
|
body, err := statusAsJSON(asked)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var doc struct {
|
|
Conditions []conditions.Condition `json:"conditions"`
|
|
Failing []conditions.Condition `json:"failing"`
|
|
}
|
|
if err := json.Unmarshal(body, &doc); err != nil || len(doc.Failing) != 1 || len(doc.Conditions) != 1 ||
|
|
!strings.Contains(doc.Failing[0].Evidence[0].Said, "invalid_grant") {
|
|
t.Fatalf("the document does not carry it: %v\n%s", err, body)
|
|
}
|
|
// Both machines' `node show` name it: where the provider runs, and where the consumer is.
|
|
for _, node := range []string{"anchor", "laptop"} {
|
|
shown := printed(t, func() error { return showNode(ctx, open, node) })
|
|
if !strings.Contains(shown, "open condition(s) about this machine") || !strings.Contains(shown, "mesh_laptop_dashboard") {
|
|
t.Fatalf("node show %s does not name it:\n%s", node, shown)
|
|
}
|
|
}
|
|
|
|
// Recovered: gone, and the mesh may be well again as far as this is concerned.
|
|
failing.Failing = false
|
|
if cleared, err := kept.Stood(ctx, failing); err != nil || !cleared {
|
|
t.Fatalf("%v %v", cleared, err)
|
|
}
|
|
asked, err = theThreeQuestions(ctx, open)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(asked.conditions) != 0 {
|
|
t.Fatalf("a recovered consumer is still named: %+v", asked.conditions)
|
|
}
|
|
}
|
|
|
|
func TestAnUnassignedProvidersLastWordIsCleared(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
kept := standings{keeper: func() *conditions.Keeper { return conditionsFrom }}
|
|
if _, err := kept.Stood(ctx, link.Standing{Module: "gone", Failing: true,
|
|
ProviderNode: "anchor", Consumer: "x", Since: time.Now()}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
all, err := conditionsFrom.Open(ctx)
|
|
if err != nil || len(all) != 1 {
|
|
t.Fatalf("%+v %v", all, err)
|
|
}
|
|
if err := unassignedProviders(ctx, open.inventory, conditionsFrom, all); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if all, _ := conditionsFrom.Open(ctx); len(all) != 0 {
|
|
t.Fatalf("%+v", all)
|
|
}
|
|
}
|