quorate/services/project-delivery/controller/bundle_test.go

164 lines
6.8 KiB
Go
Raw Permalink Normal View History

package main
import (
"context"
"encoding/json"
"reflect"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/yaml"
)
func TestCapturedSpec(t *testing.T) {
instance, template := bundleFixture(t)
ctx := context.Background()
delivery, err := decodeProjectDelivery(continuousDelivery())
if err != nil {
t.Fatal(err)
}
if err := instance.ensureWorkflow(ctx, &delivery, "first", template.GetName(), "build", nil, nil); err != nil {
t.Fatal(err)
}
bound := boundTemplate(t, instance, "first")
stored, _, _ := unstructured.NestedMap(bound.Object, "spec")
if err := unstructured.SetNestedSlice(template.Object, []any{map[string]any{"name": "build", "container": map[string]any{"image": "example.invalid/builder:v2"}}}, "spec", "templates"); err != nil {
t.Fatal(err)
}
gvr := schema.GroupVersionResource{Group: "argoproj.io", Version: "v1alpha1", Resource: "workflowtemplates"}
if _, err := instance.client.Resource(gvr).Namespace("delivery").Update(ctx, template, metav1.UpdateOptions{}); err != nil {
t.Fatal(err)
}
live, _, _ := unstructured.NestedMap(boundTemplate(t, instance, "first").Object, "spec")
if !reflect.DeepEqual(stored, live) {
t.Fatal("captured Workflow spec changed through its live template reference")
}
}
func TestCapturedActions(t *testing.T) {
instance, template := bundleFixture(t)
ctx := context.Background()
delivery, err := decodeProjectDelivery(continuousDelivery())
if err != nil {
t.Fatal(err)
}
if err := instance.ensureWorkflow(ctx, &delivery, "first", template.GetName(), "build", nil, nil); err != nil {
t.Fatal(err)
}
gvr := schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}
config, err := instance.client.Resource(gvr).Namespace("delivery").Get(ctx, "actions", metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
config.Object["data"] = map[string]any{"build.fsx": "printfn \"new action\""}
if _, err := instance.client.Resource(gvr).Namespace("delivery").Update(ctx, config, metav1.UpdateOptions{}); err != nil {
t.Fatal(err)
}
volumes, _, _ := unstructured.NestedSlice(boundTemplate(t, instance, "first").Object, "spec", "volumes")
name := volumes[0].(map[string]any)["configMap"].(map[string]any)["name"].(string)
captured, err := instance.client.Resource(gvr).Namespace("delivery").Get(ctx, name, metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
value, _, _ := unstructured.NestedString(captured.Object, "data", "build.fsx")
if value != "printfn \"old action\"" {
t.Fatalf("a later Pod resolves changed action content: %q", value)
}
}
func bundleFixture(t *testing.T) (*controller, *unstructured.Unstructured) {
t.Helper()
now := time.Date(2026, 10, 2, 0, 0, 0, 0, time.UTC)
instance := testController(t, continuousDelivery(), &mutableRefs{}, &now)
ctx := context.Background()
config := &unstructured.Unstructured{Object: map[string]any{
"apiVersion": "v1", "kind": "ConfigMap",
"metadata": map[string]any{"name": "actions", "namespace": "delivery", "labels": map[string]any{"app.kubernetes.io/name": "project-delivery"}},
"data": map[string]any{"build.fsx": "printfn \"old action\""},
}}
if _, err := instance.client.Resource(schema.GroupVersionResource{Version: "v1", Resource: "configmaps"}).Namespace("delivery").Create(ctx, config, metav1.CreateOptions{}); err != nil {
t.Fatal(err)
}
template := &unstructured.Unstructured{Object: map[string]any{
"apiVersion": "argoproj.io/v1alpha1", "kind": "WorkflowTemplate",
"metadata": map[string]any{"name": "nuthatch-delivery", "namespace": "delivery"},
"spec": map[string]any{
"entrypoint": "build",
"templates": []any{map[string]any{"name": "build", "container": map[string]any{"image": "example.invalid/builder:v1"}}},
"volumes": []any{map[string]any{"name": "actions", "configMap": map[string]any{"name": "actions"}}},
},
}}
gvr := schema.GroupVersionResource{Group: "argoproj.io", Version: "v1alpha1", Resource: "workflowtemplates"}
if _, err := instance.client.Resource(gvr).Namespace("delivery").Update(ctx, template, metav1.UpdateOptions{}); err != nil {
t.Fatal(err)
}
return instance, template
}
func boundTemplate(t *testing.T, instance *controller, name string) *unstructured.Unstructured {
t.Helper()
ctx := context.Background()
workflow, err := instance.client.Resource(workflowGVR).Namespace("delivery").Get(ctx, name, metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
ref, _, _ := unstructured.NestedString(workflow.Object, "spec", "workflowTemplateRef", "name")
gvr := schema.GroupVersionResource{Group: "argoproj.io", Version: "v1alpha1", Resource: "workflowtemplates"}
template, err := instance.client.Resource(gvr).Namespace("delivery").Get(ctx, ref, metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
return template
}
func TestCapturedPatch(t *testing.T) {
instance, template := bundleFixture(t)
ctx := context.Background()
unstructured.RemoveNestedField(template.Object, "spec", "volumes")
if err := unstructured.SetNestedSlice(template.Object, []any{map[string]any{
"name": "build", "container": map[string]any{"image": "example.invalid/builder:v1"},
"podSpecPatch": "volumes:\n- name: actions\n configMap:\n name: actions\n",
}}, "spec", "templates"); err != nil {
t.Fatal(err)
}
if _, err := instance.client.Resource(templateGVR).Namespace("delivery").Update(ctx, template, metav1.UpdateOptions{}); err != nil {
t.Fatal(err)
}
delivery, err := decodeProjectDelivery(continuousDelivery())
if err != nil {
t.Fatal(err)
}
if err := instance.ensureWorkflow(ctx, &delivery, "first", template.GetName(), "build", nil, nil); err != nil {
t.Fatal(err)
}
config, err := instance.client.Resource(configMapGVR).Namespace("delivery").Get(ctx, "actions", metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
config.Object["data"] = map[string]any{"build.fsx": "printfn \"new action\""}
if _, err := instance.client.Resource(configMapGVR).Namespace("delivery").Update(ctx, config, metav1.UpdateOptions{}); err != nil {
t.Fatal(err)
}
templates, _, _ := unstructured.NestedSlice(boundTemplate(t, instance, "first").Object, "spec", "templates")
patch := templates[0].(map[string]any)["podSpecPatch"].(string)
data, err := yaml.YAMLToJSON([]byte(patch))
if err != nil {
t.Fatal(err)
}
var body map[string]any
if err := json.Unmarshal(data, &body); err != nil {
t.Fatal(err)
}
name := body["volumes"].([]any)[0].(map[string]any)["configMap"].(map[string]any)["name"].(string)
captured, err := instance.client.Resource(configMapGVR).Namespace("delivery").Get(ctx, name, metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
value, _, _ := unstructured.NestedString(captured.Object, "data", "build.fsx")
if value != "printfn \"old action\"" {
t.Fatalf("nested podSpecPatch resolves changed actions: %q", value)
}
}