diff --git a/python-pulumi/src/ptd/__init__.py b/python-pulumi/src/ptd/__init__.py index d96d85d..7781939 100644 --- a/python-pulumi/src/ptd/__init__.py +++ b/python-pulumi/src/ptd/__init__.py @@ -428,6 +428,12 @@ class WorkloadClusterConfig: custom_k8s_resources: list[str] | None = None # List of subfolder names from custom_k8s_resources/ to apply # Tolerations for team-operator pods (controller and migration job) team_operator_tolerations: tuple[Toleration, ...] = () + # Skip CRD installation during Helm deployment (for safe migration from kustomize). + # When True, CRDs are not rendered by Helm templates (crd.enable=false) and the + # Helm release skips the crds/ directory. This allows the migration job to patch + # existing CRDs with Helm ownership labels without risk of accidental deletion. + # After migration, set to False to let Helm manage CRDs going forward. + team_operator_skip_crds: bool = False def load_workload_cluster_site_dict( diff --git a/python-pulumi/src/ptd/pulumi_resources/team_operator.py b/python-pulumi/src/ptd/pulumi_resources/team_operator.py index 0b36ff8..0febfcb 100644 --- a/python-pulumi/src/ptd/pulumi_resources/team_operator.py +++ b/python-pulumi/src/ptd/pulumi_resources/team_operator.py @@ -84,7 +84,10 @@ def _define_posit_team_namespace(self): self.posit_team_namespace = kubernetes.core.v1.Namespace( f"{self.workload.compound_name}-{self.release}-{ptd.POSIT_TEAM_NAMESPACE}", metadata={"name": ptd.POSIT_TEAM_NAMESPACE}, - opts=pulumi.ResourceOptions(parent=self), + opts=pulumi.ResourceOptions( + parent=self, + retain_on_delete=True, # Don't delete namespace during migration + ), ) def _define_migration_resources(self): @@ -288,6 +291,15 @@ def _define_helm_release(self): for t in self.cluster_cfg.team_operator_tolerations ], }, + # CRD configuration for safe migration from kustomize to Helm. + # When skip_crds=True: crd.enable=False prevents Helm from rendering CRD templates, + # allowing migration job to patch existing CRDs without risk of deletion. + # When skip_crds=False (default): Helm manages CRDs normally. + # crd.keep=True adds helm.sh/resource-policy: keep as defense-in-depth. + "crd": { + "enable": not self.cluster_cfg.team_operator_skip_crds, + "keep": True, + }, } # OCI Helm chart from public repository @@ -308,6 +320,10 @@ def _define_helm_release(self): namespace=ptd.POSIT_TEAM_SYSTEM_NAMESPACE, create_namespace=True, values=helm_values, + # Skip CRDs at Helm level (belt-and-suspenders with crd.enable in values). + # This tells Helm CLI to skip the crds/ directory if the chart ever moves + # CRDs there. Combined with crd.enable=False, provides complete CRD skip. + skip_crds=self.cluster_cfg.team_operator_skip_crds, ) self.helm_release = kubernetes.helm.v3.Release(