Is there currently an officially-recommended way t...
# typescript
l
Is there currently an officially-recommended way to handle 'migrations' for when changes require multiple deployments? For example, I have a
k8s.helm.v3.Release
containing CRDs that I'd like to move to
v4.Chart
(why yes I do have CRDs that are almost a year out of date now, how did you know?). To avoid deleting the CRDs I want to add
retainOnDelete: true
to the v3 release, then replace it with a v4.Chart, but afaik this would require two deployments, so I'd have to ensure that all dependent projects are upgraded to the version that has
retainOnDelete
before I can actually do the v4.Chart replacement. If not, I'm somewhat curious if a dynamic provider based on umzug could work...
Alternatively, if there's a way to do "prevent creation/deletion/update, continue without failing deployment" with hooks, that might also allow for similar multi-stage change behaviour
for this specific case I was able to cheat by using a null resource to hold the `retainOnDelete`:
Copy code
const oldV3Chart = new NullResource(name, {}, {
      parent: this,
      retainOnDelete: true,
      aliases: [{
        type: 'kubernetes:<http://helm.sh/v3:Release|helm.sh/v3:Release>',
      }],
    })

    this.chart = this.helmV4Chart(name, {
      name: props.releaseName ?? 'kube-prometheus-stack-crds',
      chart: 'prometheus-operator-crds',
      namespace: 'default',
      version: props.chart?.version,
      repositoryOpts: {
        repo: '<https://prometheus-community.github.io/helm-charts>',
      },
      values: this.getOverriddenChartValues(props.chart, {
        crds: {
          annotations: {
            '<http://pulumi.com/patchForce|pulumi.com/patchForce>': 'true'
          }
        }
      }),
    }, pulumi.mergeOptions(opts, {
      aliases: [{
        parent: opts?.parent,
      }],
      parent: this,
      dependsOn: [oldV3Chart],
    }))
But I think the desire for a multi-step 'migration' type thing that's a bit more advanced than aliases might still be a relevant discussion
m
That's clever
😁 1
l
I haven't had much of a chance to battle-test it yet, but I think I just stumbled across a generic safe way to migrate v3.Release to v4.Chart?
Copy code
migrateV3ToV4Chart(...args: ConstructorParameters<typeof k8s.helm.v4.Chart>): k8s.helm.v4.Chart {
    const [name, props, opts] = args
    const oldV3Chart = new NullResource(name, {}, pulumi.mergeOptions(opts ?? {}, {
      retainOnDelete: true,
      aliases: [{
        type: 'kubernetes:helm.sh/v3:Release',
      }],
    }))
    
    return this.helmV4Chart(name, props, pulumi.mergeOptions(opts ?? {}, {
      dependsOn: [oldV3Chart],
      transforms: [args => {
        if (isTransformType<pulumi.Unwrap<k8s.apiextensions.v1.CustomResourceDefinitionArgs>>(args, 'kubernetes:apiextensions.k8s.io/v1:CustomResourceDefinition')) {
          args.props.metadata ??= {}
          args.props.metadata.annotations = {
            ...args.props.metadata.annotations,
            'pulumi.com/patchForce': 'true'
          }
        }
        return args
      }]
    }))
  }
(some custom stuff going on in there but you get the gist) I'm not sure what will happen if the inputs change though, I feel like that null resource replacement has to have some sort of ramification somewhere. I think patchForce might be needed on all resources too so maybe just a single deploy with the env var rather than transforming the annotations would be better, not sure yet
m
#CRFURDVQB may have more expertise in this area. Not sure
l
are you sure the CRD's get deleted upon deletion of the
v3.Release
resource? I'm pretty sure pulumi just does "helm uninstall" under the hood, and Helm generally does not clean up its crds
l
Oh that's a good point, I'm actually even switching to v4 because of Helm being too safe with CRDs so I should have realised that. I'm curious if that method above works on other resources managed by v3 though