From 6382582090c545a8aae774afd5b19d6471c06ddd Mon Sep 17 00:00:00 2001 From: Andrew Stoltz Date: Tue, 19 May 2026 12:27:47 -0500 Subject: [PATCH] fc-desktop: add remotedesktop warm pool intent --- apps/fc-desktop/fc-desktop.yaml | 9 +- apps/fc-desktop/remotedesktop-pools.yaml | 101 ++++++++++++++++++ .../FleetManifestLintTests.cs | 32 ++++++ 3 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 apps/fc-desktop/remotedesktop-pools.yaml diff --git a/apps/fc-desktop/fc-desktop.yaml b/apps/fc-desktop/fc-desktop.yaml index 6a45b07..712731c 100644 --- a/apps/fc-desktop/fc-desktop.yaml +++ b/apps/fc-desktop/fc-desktop.yaml @@ -1,10 +1,13 @@ # FlowerCore Remote Desktop — TLS + Ingress # # Source-of-truth split: -# - bluejay-infra OWNS: Certificate, IngressRoute, all NetworkPolicies +# - bluejay-infra OWNS: Certificate, IngressRoute, all NetworkPolicies, +# and the explicit RemoteDesktopPoolCrd warm-pool intent in +# remotedesktop-pools.yaml. # (see network-policies.yaml in this directory). -# - FlowerCore.RemoteDesktop scripts/deploy-web.sh OWNS: Deployment + -# Service. Reason: image refs like `localhost/fc-desktop:linux-xfce` +# - FlowerCore.RemoteDesktop OWNS: CRD definition/operator Deployment and +# scripts/deploy-web.sh Deployment + Service. Reason: image refs like +# `localhost/fc-desktop:linux-xfce` # only exist on each node's containerd after a manual import, so a # Deployment manifest in bluejay-infra would race the image-import # step and crash-loop. diff --git a/apps/fc-desktop/remotedesktop-pools.yaml b/apps/fc-desktop/remotedesktop-pools.yaml new file mode 100644 index 0000000..77d0f56 --- /dev/null +++ b/apps/fc-desktop/remotedesktop-pools.yaml @@ -0,0 +1,101 @@ +# FlowerCore RemoteDesktop warm-pool intent. +# +# These CRDs are deliberately explicit. The RemoteDesktop warmup loop no +# longer scans template defaults to decide what to warm; every enabled pool +# here represents operator/GitOps intent and prevents a repeat of the +# orphan-pool leak from 2026-05-08. +--- +apiVersion: flowercore.io/v1 +kind: RemoteDesktopPoolCrd +metadata: + name: browser-lab-pool + namespace: fc-desktop + labels: + app.kubernetes.io/name: remotedesktop-pool + app.kubernetes.io/part-of: flowercore-remotedesktop + app.kubernetes.io/managed-by: bluejay-infra +spec: + templateSlug: browser-only + desiredSize: 1 + enabled: true + reconcileNow: true +--- +apiVersion: flowercore.io/v1 +kind: RemoteDesktopPoolCrd +metadata: + name: opensuse-xfce-pool + namespace: fc-desktop + labels: + app.kubernetes.io/name: remotedesktop-pool + app.kubernetes.io/part-of: flowercore-remotedesktop + app.kubernetes.io/managed-by: bluejay-infra +spec: + templateSlug: opensuse-xfce + desiredSize: 1 + enabled: true + userVolumeMode: LateAttach + reconcileNow: true +--- +apiVersion: flowercore.io/v1 +kind: RemoteDesktopPoolCrd +metadata: + name: dev-workstation-pool + namespace: fc-desktop + labels: + app.kubernetes.io/name: remotedesktop-pool + app.kubernetes.io/part-of: flowercore-remotedesktop + app.kubernetes.io/managed-by: bluejay-infra +spec: + templateSlug: dev-workstation + desiredSize: 1 + enabled: true + userVolumeMode: LateAttach + reconcileNow: true +--- +apiVersion: flowercore.io/v1 +kind: RemoteDesktopPoolCrd +metadata: + name: ai-station-pool + namespace: fc-desktop + labels: + app.kubernetes.io/name: remotedesktop-pool + app.kubernetes.io/part-of: flowercore-remotedesktop + app.kubernetes.io/managed-by: bluejay-infra +spec: + templateSlug: ai-station + desiredSize: 1 + enabled: true + userVolumeMode: LateAttach + reconcileNow: true +--- +apiVersion: flowercore.io/v1 +kind: RemoteDesktopPoolCrd +metadata: + name: linux-xfce-pool + namespace: fc-desktop + labels: + app.kubernetes.io/name: remotedesktop-pool + app.kubernetes.io/part-of: flowercore-remotedesktop + app.kubernetes.io/managed-by: bluejay-infra +spec: + templateSlug: linux-xfce + desiredSize: 1 + enabled: true + userVolumeMode: LateAttach + reconcileNow: true +--- +apiVersion: flowercore.io/v1 +kind: RemoteDesktopPoolCrd +metadata: + name: linux-xfce-rdp-pool + namespace: fc-desktop + labels: + app.kubernetes.io/name: remotedesktop-pool + app.kubernetes.io/part-of: flowercore-remotedesktop + app.kubernetes.io/managed-by: bluejay-infra +spec: + templateSlug: linux-xfce-rdp + desiredSize: 1 + enabled: true + userVolumeMode: LateAttach + reconcileNow: true diff --git a/tests/bluejay-infra-lint/FleetManifestLintTests.cs b/tests/bluejay-infra-lint/FleetManifestLintTests.cs index eb9683d..f1be8ed 100644 --- a/tests/bluejay-infra-lint/FleetManifestLintTests.cs +++ b/tests/bluejay-infra-lint/FleetManifestLintTests.cs @@ -387,6 +387,38 @@ public sealed class FleetManifestLintTests violations.Should().BeEmpty(); } + [Fact] + public void RemoteDesktopPoolCrds_MustExplicitlyOptInHookReadyTemplates() + { + var expectedModes = new Dictionary(StringComparer.Ordinal) + { + ["browser-only"] = null, + ["opensuse-xfce"] = "LateAttach", + ["dev-workstation"] = "LateAttach", + ["ai-station"] = "LateAttach", + ["linux-xfce"] = "LateAttach", + ["linux-xfce-rdp"] = "LateAttach", + }; + + var pools = Inventory.Documents + .Where(document => document.Kind == "RemoteDesktopPoolCrd") + .Where(document => document.RelativePath == "fc-desktop/remotedesktop-pools.yaml") + .ToDictionary( + document => document.Scalar("spec", "templateSlug") ?? string.Empty, + StringComparer.Ordinal); + + pools.Keys.Should().BeEquivalentTo(expectedModes.Keys); + foreach (var expected in expectedModes) + { + var pool = pools[expected.Key]; + pool.Namespace.Should().Be("fc-desktop"); + pool.Scalar("spec", "desiredSize").Should().Be("1"); + pool.Scalar("spec", "enabled").Should().Be("true"); + pool.Scalar("spec", "reconcileNow").Should().Be("true"); + pool.Scalar("spec", "userVolumeMode").Should().Be(expected.Value); + } + } + [Fact] public void PublicEgressDeployments_MustOptOutOfIamworkinLanSearchSuffixes() {