So... stuff is working better and better. What's t...
# general
w
So... stuff is working better and better. What's the best/canonical way to add CRDs? I got ingress and cert-manager helm charts deployed. Now I'd like to deploy various resources defined by each.
c
@wooden-toddler-96888 sadly we do not yet have a well-typed experience for this, but you can use `apiextensions.CustomResource`: https://github.com/pulumi/pulumi-kubernetes/blob/master/pack/nodejs/provider.ts#L1341
w
Aha! That's what I was looking for. Thanks!
c
(Under the covers this is what gets called when we parse a YAML doc or Helm Chart that’s using CRs)
w
I just need a bit of a nudge. I was able to compose this, for instance:
Copy code
const stagingLetsEncryptIssuer = new k8s.apiextensions.CustomResource(
    "staging-lets-encrypt-issuer",
    {
    apiVersion: "<http://certmanager.k8s.io/v1alpha1|certmanager.k8s.io/v1alpha1>",
    kind: "ClusterIssuer",
    },
    {
        provider: ek8s
    });
But I couldn't figure out how to fit this, into that definition:
Copy code
apiVersion: <http://certmanager.k8s.io/v1alpha1|certmanager.k8s.io/v1alpha1>
kind: Issuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: <https://acme-staging.api.letsencrypt.org/directory>
    # Email address used for ACME registration
    email: "<mailto:certificates@example.com|certificates@example.com>"
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    http01: {}
c
@wooden-toddler-96888 ah the types are a little misleading here. Try this:
Copy code
new k8s.apiextensions.CustomResource("staging-lets-encrypt-issuer",
{
  "apiVersion": "<http://certmanager.k8s.io/v1alpha1|certmanager.k8s.io/v1alpha1>",
  "kind": "Issuer",
  "metadata": {
    "name": "letsencrypt-staging"
  },
  "spec": {
    "acme": {
      "server": "<https://acme-staging.api.letsencrypt.org/directory>",
      "email": "<mailto:certificates@example.com|certificates@example.com>",
      "privateKeySecretRef": {
        "name": "letsencrypt-staging"
      },
      "http01": {
      }
    }
  }
}, {provider: ek8s})
The way to think about this is: the only thing we know about the object we’re passing to the
CustomResource
constructor is that it has
apiVersion
and `kind`; but it can also have whatever other properties you need.
👍 1
w
In case anyone else is tracking this, I had to declare this sub-custom resource:
Copy code
import * as k8s from "@pulumi/kubernetes";
import * as pulumi from "@pulumi/pulumi";

export class ExtensibleResource extends k8s.apiextensions.CustomResource {
    /**
     * Create a CustomResource resource with the given unique name, arguments, and options.
     *
     * @param name The _unique_ name of the resource.
     * @param args The arguments to use to populate this resource's properties.
     * @param opts A bag of options that control this resource's behavior.
     */
    constructor(name: string, args: {
        apiVersion: pulumi.Input<string>;
        kind: pulumi.Input<string>;
        [others: string]: any;
    }, opts?: pulumi.CustomResourceOptions) {
        super(name, args, opts)
    }
}
That's so that TypeScript would allow having additional arbitary unchecked K/V pairs in args.
c
Oooo. I should add this.
I'll open a bug