92 lines
3.6 KiB
Go
92 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
)
|
|
|
|
func TestTemplateDrain(t *testing.T) {
|
|
for _, purpose := range []string{"build", "qualification"} {
|
|
for _, outcome := range []string{"Succeeded", "Failed", "Error"} {
|
|
t.Run(purpose+"/"+outcome, func(t *testing.T) {
|
|
ctx := context.Background()
|
|
now := time.Date(2026, 10, 2, 0, 0, 0, 0, time.UTC)
|
|
c := testController(t, continuousDelivery(), &mutableRefs{}, &now)
|
|
d, err := decodeProjectDelivery(continuousDelivery())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := c.ensureWorkflow(ctx, &d, "first", "nuthatch-delivery", purpose, nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
old := boundTemplate(t, c, "first").DeepCopy()
|
|
c.config.templateQuiet = time.Minute
|
|
changeImage(t, c, "nuthatch-delivery", "example.invalid/builder:v2")
|
|
if _, err := c.readyTemplate(ctx, "delivery", "nuthatch-delivery"); !errors.Is(err, templatePending) {
|
|
t.Fatalf("first change = %v", err)
|
|
}
|
|
now = now.Add(30 * time.Second)
|
|
changeImage(t, c, "nuthatch-delivery", "example.invalid/builder:v3")
|
|
if _, err := c.readyTemplate(ctx, "delivery", "nuthatch-delivery"); !errors.Is(err, templatePending) {
|
|
t.Fatalf("latest change = %v", err)
|
|
}
|
|
now = now.Add(time.Minute)
|
|
if _, err := c.readyTemplate(ctx, "delivery", "nuthatch-delivery"); !errors.Is(err, templatePending) {
|
|
t.Fatalf("queued drain = %v", err)
|
|
}
|
|
setNamedWorkflowStatus(t, c, "first", "Running", nil)
|
|
if _, err := c.readyTemplate(ctx, "delivery", "nuthatch-delivery"); !errors.Is(err, templatePending) {
|
|
t.Fatalf("running drain = %v", err)
|
|
}
|
|
if err := c.ensureWorkflow(ctx, &d, "first", "nuthatch-delivery", purpose, nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := c.ensureWorkflow(ctx, &d, "second", "nuthatch-delivery", purpose, nil, nil); !errors.Is(err, templatePending) {
|
|
t.Fatalf("new admission = %v", err)
|
|
}
|
|
setNamedWorkflowStatus(t, c, "first", outcome, nil)
|
|
if err := c.ensureWorkflow(ctx, &d, "second", "nuthatch-delivery", purpose, nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
latest := boundTemplate(t, c, "second")
|
|
templates, _, _ := unstructured.NestedSlice(latest.Object, "spec", "templates")
|
|
if image := templates[0].(map[string]any)["container"].(map[string]any)["image"]; image != "example.invalid/builder:v3" {
|
|
t.Fatalf("published image = %v", image)
|
|
}
|
|
if !reflect.DeepEqual(old.Object["spec"], boundTemplate(t, c, "first").Object["spec"]) {
|
|
t.Fatal("terminal Workflow lost its captured specification")
|
|
}
|
|
resource := c.client.Resource(templateGVR).Namespace("delivery")
|
|
alias, err := resource.Get(ctx, "nuthatch-delivery", metav1.GetOptions{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if alias.GetAnnotations()[publishedKey] != latest.GetName() {
|
|
t.Fatal("published selection did not retain the latest revision")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func changeImage(t *testing.T, c *controller, name, image string) {
|
|
t.Helper()
|
|
resource := c.client.Resource(templateGVR).Namespace("delivery")
|
|
object, err := resource.Get(context.Background(), name, metav1.GetOptions{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
object.SetGeneration(object.GetGeneration() + 1)
|
|
if err := unstructured.SetNestedSlice(object.Object, []any{map[string]any{"name": "build", "container": map[string]any{"image": image}}}, "spec", "templates"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := resource.Update(context.Background(), object, metav1.UpdateOptions{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|