From d4df15057261f9c41997998b339a6397836ef76a Mon Sep 17 00:00:00 2001 From: Patrick Lee Scott Date: Mon, 28 Sep 2026 22:29:58 -0500 Subject: [PATCH] fix: import dynamic CSI snapshot handles [[tasks/harmony-1394]] --- functions/branch/010-state-status.yaml.gotmpl | 6 +- tests/test-branch/main.k | 107 ++++++++++++++++++ .../observed/cross-namespace-ready.yaml | 3 +- .../observed/cross-namespace-staged.yaml | 3 +- 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/functions/branch/010-state-status.yaml.gotmpl b/functions/branch/010-state-status.yaml.gotmpl index 490cc44..ed874ac 100644 --- a/functions/branch/010-state-status.yaml.gotmpl +++ b/functions/branch/010-state-status.yaml.gotmpl @@ -103,7 +103,11 @@ {{- $sourceContentManifest := $sourceContentAtProvider.manifest | default dict }} {{- $sourceContentSpec := $sourceContentManifest.spec | default dict }} {{- $sourceContentSource := $sourceContentSpec.source | default dict }} -{{- $sourceSnapshotHandle := $sourceContentSource.snapshotHandle | default "" }} +{{- $sourceContentStatus := $sourceContentManifest.status | default dict }} +# Dynamic content identifies the source volume in spec.source.volumeHandle; +# the CSI snapshot ID is published in status.snapshotHandle. Pre-provisioned +# content can supply that ID in spec.source.snapshotHandle before status exists. +{{- $sourceSnapshotHandle := $sourceContentStatus.snapshotHandle | default $sourceContentSource.snapshotHandle | default "" }} {{- $sourceSnapshotDriver := $sourceContentSpec.driver | default "" }} {{- $sourceSnapshotVolumeMode := $sourceContentSpec.sourceVolumeMode | default "" }} {{- $sourceSnapshotClassName := $sourceContentSpec.volumeSnapshotClassName | default "" }} diff --git a/tests/test-branch/main.k b/tests/test-branch/main.k index 1d3cbd2..07716dc 100644 --- a/tests/test-branch/main.k +++ b/tests/test-branch/main.k @@ -79,6 +79,36 @@ _ready_source_snapshot_content = lambda namespace, name { } } +_ready_dynamic_source_snapshot_content = lambda namespace, name { + { + apiVersion = "kubernetes.m.crossplane.io/v1alpha1" + kind = "Object" + metadata = { + name = name + namespace = namespace + annotations = { + "crossplane.io/composition-resource-name" = "source-snapshot-content" + "gotemplating.fn.crossplane.io/composition-resource-name" = "source-snapshot-content" + } + } + status = { + conditions = [{type = "Ready", status = "True"}] + atProvider.manifest = { + spec = { + driver = "ebs.csi.eks.amazonaws.com" + source.volumeHandle = "vol-0123456789abcdef0" + sourceVolumeMode = "Filesystem" + volumeSnapshotClassName = "psql" + } + status = { + snapshotHandle = "snap-dynamic0123456789" + readyToUse = True + } + } + } +} +} + _ready_branch_snapshot_content = lambda namespace, name { { apiVersion = "kubernetes.m.crossplane.io/v1alpha1" @@ -367,6 +397,83 @@ _items = [ } } + # Dynamic CSI content stores the source volume in spec and the resulting + # snapshot in status. Import the snapshot ID, never the source volume ID. + metav1alpha1.CompositionTest { + metadata.name = "cross-ns-imports-dynamic-status-snapshot-handle" + spec = { + compositionPath = "apis/psqlbranches/composition.yaml" + xrdPath = "apis/psqlbranches/definition.yaml" + timeoutSeconds = 60 + validate = False + xr = stacksv1alpha1.PSQLBranch { + metadata = {name = "br-x", namespace = "preview-pr-1"} + spec = { + clusterName = "prod" + source = {name = "src-app", namespace = "team-app"} + } + } + observedResources = [ + _ready_source_cluster("preview-pr-1", "br-x-source-cluster"), + { + apiVersion = "kubernetes.m.crossplane.io/v1alpha1" + kind = "Object" + metadata = { + name = "br-x-source-snapshot" + namespace = "preview-pr-1" + annotations = { + "crossplane.io/composition-resource-name" = "source-snapshot" + "gotemplating.fn.crossplane.io/composition-resource-name" = "source-snapshot" + } + } + status = { + conditions = [{type = "Ready", status = "True"}] + atProvider.manifest.status = { + boundVolumeSnapshotContentName = "snapcontent-from-source" + readyToUse = True + } + } + } + _ready_dynamic_source_snapshot_content("preview-pr-1", "br-x-source-snapshot-content") + ] + assertResources = [ + { + apiVersion = "kubernetes.m.crossplane.io/v1alpha1" + kind = "Object" + metadata.name = "br-x-branch-snapshot-content" + spec.forProvider.manifest.spec = { + deletionPolicy = "Retain" + driver = "ebs.csi.eks.amazonaws.com" + source.snapshotHandle = "snap-dynamic0123456789" + volumeSnapshotRef = { + name = "br-x-snap" + namespace = "preview-pr-1" + } + } + } + { + apiVersion = "kubernetes.m.crossplane.io/v1alpha1" + kind = "Object" + metadata.name = "br-x-branch-snapshot" + spec.forProvider.manifest.spec.source.volumeSnapshotContentName = "preview-pr-1-br-x-6a6f418e5232e5cb-content" + } + { + apiVersion = "hops.ops.com.ai/v1alpha1" + kind = "PSQLBranch" + metadata.name = "br-x" + status = { + ready = False + conditions = [ + {type = "Responsive", status = "True"} + {type = "Synced", status = "True"} + {type = "Ready", status = "False"} + ] + } + } + ] + } + } + # ========================================================================== # Cluster-scoped content names include a length-delimited identity hash, so # delimiter-equivalent readable prefixes cannot collide. diff --git a/tests/test-branch/observed/cross-namespace-ready.yaml b/tests/test-branch/observed/cross-namespace-ready.yaml index cd2dc1a..2058cb1 100644 --- a/tests/test-branch/observed/cross-namespace-ready.yaml +++ b/tests/test-branch/observed/cross-namespace-ready.yaml @@ -53,10 +53,11 @@ status: deletionPolicy: Delete driver: ebs.csi.eks.amazonaws.com source: - snapshotHandle: snap-0123456789abcdef0 + volumeHandle: vol-0123456789abcdef0 sourceVolumeMode: Filesystem volumeSnapshotClassName: psql status: + snapshotHandle: snap-0123456789abcdef0 readyToUse: true --- apiVersion: kubernetes.m.crossplane.io/v1alpha1 diff --git a/tests/test-branch/observed/cross-namespace-staged.yaml b/tests/test-branch/observed/cross-namespace-staged.yaml index 14d6baa..5be0306 100644 --- a/tests/test-branch/observed/cross-namespace-staged.yaml +++ b/tests/test-branch/observed/cross-namespace-staged.yaml @@ -52,8 +52,9 @@ status: spec: driver: ebs.csi.eks.amazonaws.com source: - snapshotHandle: snap-0123456789abcdef0 + volumeHandle: vol-0123456789abcdef0 sourceVolumeMode: Filesystem volumeSnapshotClassName: psql status: + snapshotHandle: snap-0123456789abcdef0 readyToUse: true