crd2pulumi
crd2pulumi is a CLI tool that generates typed Pulumi SDK classes from Kubernetes CustomResourceDefinition (CRD) YAML schemas. While Pulumi lets you manage Kubernetes CustomResources directly, those resources are untyped by default because every CRD schema is different. crd2pulumi solves this by reading a CRD’s OpenAPI schema and generating strongly typed classes for your language of choice, enabling IDE autocompletion and compile-time type checking.
This is particularly useful for complex CRDs with large schemas, such as cert-manager or Istio, where manually constructing resource arguments is error-prone.
Installation
Install crd2pulumi via Homebrew:
brew install pulumi/tap/crd2pulumi
Alternatively, download a binary from the GitHub releases page.
Usage
The following example uses the CronTab CRD from the Kubernetes documentation. Generate typed SDK classes with crd2pulumi, then use them alongside ConfigFile to register the CRD and instantiate a typed resource.
Generate TypeScript types:
crd2pulumi --nodejsPath ./crontabs resourcedefinition.yaml
Import the generated types into your Pulumi program:
import * as crontabs from "./crontabs";
import * as k8s from "@pulumi/kubernetes";
const cronTabDefinition = new k8s.yaml.v2.ConfigFile("my-crontab-definition", {
file: "resourcedefinition.yaml",
});
const myCronTab = new crontabs.stable.v1.CronTab("my-new-cron-object", {
metadata: {
name: "my-new-cron-object",
},
spec: {
cronSpec: "* * * * */5",
image: "my-awesome-cron-image",
},
});
Generate Python types:
crd2pulumi --pythonPath ./crontabs resourcedefinition.yaml
Import the generated types into your Pulumi program:
from pulumi_kubernetes.yaml.v2 import ConfigFile
import crontabs.pulumi_crds as crontabs
crontab_definition = ConfigFile("my-crontab-definition", file="resourcedefinition.yaml")
crontab_instance = crontabs.stable.v1.CronTab(
"my-new-cron-object",
metadata={"name": "my-new-cron-object"},
spec=crontabs.stable.v1.CronTabSpecArgs(
cron_spec="* * * * */5",
image="my-awesome-cron-image",
),
)
Generate Go types:
crd2pulumi --goPath ./crontabs resourcedefinition.yaml
Import the generated types into your Pulumi program. In this example the Go module is named crds-go-final, so the import path is crds-go-final/crontabs/stable/v1 — replace this with your own module name:
package main
import (
crontabs_v1 "crds-go-final/crontabs/stable/v1"
yamlv2 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/yaml/v2"
meta_v1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := yamlv2.NewConfigFile(ctx, "my-crontab-definition",
&yamlv2.ConfigFileArgs{
File: pulumi.String("resourcedefinition.yaml"),
},
)
if err != nil {
return err
}
_, err = crontabs_v1.NewCronTab(ctx, "my-new-cron-object", &crontabs_v1.CronTabArgs{
Metadata: &meta_v1.ObjectMetaArgs{
Name: pulumi.String("my-new-cron-object"),
},
Spec: crontabs_v1.CronTabSpecArgs{
CronSpec: pulumi.String("* * * * */5"),
Image: pulumi.String("my-awesome-cron-image"),
},
})
if err != nil {
return err
}
return nil
})
}
Generate .NET types:
crd2pulumi --dotnetPath ./crontabs resourcedefinition.yaml
Import the generated types into your Pulumi program:
using Pulumi;
using Pulumi.Kubernetes.Yaml.V2;
using Pulumi.Kubernetes.Types.Inputs.Meta.V1;
class MyStack : Stack
{
public MyStack()
{
var cronTabDefinition = new ConfigFile("my-crontab-definition",
new ConfigFileArgs
{
File = "resourcedefinition.yaml",
}
);
var cronTabInstance = new Pulumi.Crds.Stable.V1.CronTab("my-new-cron-object",
new Pulumi.Kubernetes.Types.Inputs.Stable.V1.CronTabArgs
{
Metadata = new ObjectMetaArgs
{
Name = "my-new-cron-object",
},
Spec = new Pulumi.Kubernetes.Types.Inputs.Stable.V1.CronTabSpecArgs
{
CronSpec = "* * * * */5",
Image = "my-awesome-cron-image",
},
}
);
}
}
If you see a Duplicate 'global::System.Runtime.Versioning.TargetFrameworkAttribute' attribute error when running pulumi up, delete the crontabs/bin and crontabs/obj folders and try again.
Generate Java types:
crd2pulumi --javaPath ./crontabs resourcedefinition.yaml
Import the generated types into your Pulumi program:
package com.example;
import com.pulumi.Pulumi;
import com.pulumi.kubernetes.yaml.v2.ConfigFile;
import com.pulumi.kubernetes.yaml.v2.ConfigFileArgs;
public class MyStack {
public static void main(String[] args) {
Pulumi.run(ctx -> {
var cronTabDefinition = new ConfigFile("my-crontab-definition",
ConfigFileArgs.builder()
.file("resourcedefinition.yaml")
.build());
var cronTabInstance = new com.pulumi.crds.stable.v1.CronTab("my-new-cron-object",
com.pulumi.crds.stable.v1.CronTabArgs.builder()
.metadata(com.pulumi.kubernetes.meta.v1.inputs.ObjectMetaArgs.builder()
.name("my-new-cron-object")
.build())
.spec(com.pulumi.kubernetes.stable.v1.inputs.CronTabSpecArgs.builder()
.cronSpec("* * * * */5")
.image("my-awesome-cron-image")
.build())
.build());
});
}
}
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.