-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
0 parents
commit e5f0891
Showing
18 changed files
with
3,110 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
PROJECT := github.com/pulumi/crd2pulumi | ||
VERSION := 1.0.3 | ||
LDFLAGS := "-X 'github.com/pulumi/crd2pulumi/gen.Version=$(VERSION)'" | ||
|
||
GO ?= go | ||
GOMODULE = GO111MODULE=on | ||
|
||
ensure:: | ||
$(GOMODULE) $(GO) mod tidy | ||
|
||
build:: | ||
$(GOMODULE) $(GO) build $(PROJECT) | ||
|
||
release: rel-darwin rel-linux rel-windows | ||
|
||
rel-darwin:: | ||
GOOS=darwin GOARCH=amd64 $(GO) build -ldflags=$(LDFLAGS) -o releases/crd2pulumi-darwin-amd64/crd2pulumi $(PROJECT) | ||
tar -zcvf releases/crd2pulumi-darwin-amd64.tar.gz -C releases/crd2pulumi-darwin-amd64 . | ||
|
||
rel-linux:: | ||
GOOS=linux GOARCH=386 $(GO) build -ldflags=$(LDFLAGS) -o releases/crd2pulumi-linux-386/crd2pulumi $(PROJECT) | ||
tar -zcvf releases/crd2pulumi-linux-386.tar.gz -C releases/crd2pulumi-linux-386 . | ||
GOOS=linux GOARCH=amd64 $(GO) build -ldflags=$(LDFLAGS) -o releases/crd2pulumi-linux-amd64/crd2pulumi $(PROJECT) | ||
tar -zcvf releases/crd2pulumi-linux-amd64.tar.gz -C releases/crd2pulumi-linux-amd64 . | ||
|
||
rel-windows:: | ||
GOOS=windows GOARCH=386 $(GO) build -ldflags=$(LDFLAGS) -o releases/crd2pulumi-windows-386/crd2pulumi.exe $(PROJECT) | ||
zip -j releases/crd2pulumi-windows-386.zip releases/crd2pulumi-windows-386/crd2pulumi.exe | ||
GOOS=windows GOARCH=amd64 $(GO) build -ldflags=$(LDFLAGS) -o releases/crd2pulumi-windows-amd64/crd2pulumi.exe $(PROJECT) | ||
zip -j releases/crd2pulumi-windows-amd64.zip releases/crd2pulumi-windows-amd64/crd2pulumi.exe | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
# crd2pulumi | ||
Generate typed CustomResources based on Kubernetes CustomResourceDefinitions. | ||
|
||
## Goals | ||
|
||
`crd2pulumi` is a CLI tool that generates typed CustomResources based on Kubernetes CustomResourceDefinition (CRDs). CRDs allow you to extend the Kubernetes API by defining your own schemas for custom objects. While Pulumi lets you create [CustomResources](https://www.pulumi.com/docs/reference/pkg/kubernetes/apiextensions/customresource/), there was previously no strong-typing for these objects since every schema was, well, custom. This can be a massive headache for popular CRDs such as [cert-manager](https://github.com/jetstack/cert-manager/tree/master/deploy/crds) or [istio](https://github.com/istio/istio/tree/0321da58ca86fc786fb03a68afd29d082477e4f2/manifests/charts/base/crds), which contain thousands of lines of complex YAML schemas. By generating typed versions of CustomResources, `crd2pulumi` makes filling out their arguments more convenient by allowing you to leverage existing IDE type checking and autocomplete features. | ||
|
||
## Building and Installation | ||
If you wish to use `crd2pulumi` without developing the tool itself, you can use one of the [binary releases](https://github.com/pulumi/pulumi-kubernetes/releases/tag/crd2pulumi/v1.0.0) hosted on GitHub. | ||
|
||
`crd2pulumi` uses Go modules to manage dependencies. If you want to develop `crd2pulumi` itself, you'll need to have Go installed in order to build. Once you install this prerequisite, run the following to build the `crd2pulumi` binary and install it into `$GOPATH/bin`: | ||
|
||
```bash | ||
$ go build -ldflags="-X 'github.com/pulumi/crd2pulumi/gen.Version=1.0.0'" -o $GOPATH/bin/crd2pulumi main.go | ||
``` | ||
The `ldflags` argument is necessary to dynamically set the `crd2pulumi` version at build time. However, the version | ||
itself can be anything, so you don't have to set it to `1.0.0`. | ||
|
||
Go should then automatically handle pulling the dependencies for you. If `$GOPATH/bin` is not on your path, you may want to move the `crd2pulumi` binary from `$GOPATH/bin` into a directory that is on your path. | ||
|
||
## Usage | ||
```bash | ||
crd2pulumi [-dgnp] [--nodejsPath path] [--pythonPath path] [--dotnetPath path] [--goPath path] <crd1.yaml> [crd2.yaml ...] [--force] | ||
|
||
Example usage: | ||
$ crd2pulumi --nodejs crontabs.yaml | ||
$ crd2pulumi -dgnp crd-certificates.yaml crd-issuers.yaml crd-challenges.yaml | ||
$ crd2pulumi --pythonPath=crds/python/istio --nodejsPath=crds/nodejs/istio crd-all.gen.yaml crd-mixer.yaml crd-operator.yaml | ||
|
||
Flags: | ||
-d, --dotnet generate .NET | ||
--dotnetPath string optional .NET output dir | ||
-g, --go generate Go | ||
--goPath string optional Go output dir | ||
-n, --nodejs generate NodeJS | ||
--nodejsPath string optional NodeJS output dir | ||
-p, --python generate Python | ||
--pythonPath string optional Python output dir | ||
|
||
-f, --force overwrite existing files | ||
-v, --version version for crd2pulumi | ||
-h, --help help for crd2pulumi | ||
``` | ||
Setting only a language-specific flag will output the generated code in the default directory; so `-d` will output to `crds/dotnet`, `-g` will output to `crds/go`, `-n` will output to `crds/nodejs`, and `-p` will output to `crds/python`. You can also specify a language-specific path (`--pythonPath`, `--nodejsPath`, etc) to control where the code will be outputted, in which case setting `-p`, `-n`, etc becomes unnecessary. | ||
|
||
## Examples | ||
Let's use the example CronTab CRD specified in `resourcedefinition.yaml` from the [Kubernetes Documentation](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/). | ||
|
||
### TypeScript | ||
To generate a strongly-typed CronTab CustomResource in TypeScript, we can run this command: | ||
```bash | ||
$ crd2pulumi --nodejsPath ./crontabs resourcedefinition.yaml | ||
``` | ||
Now let's import the generated code into a Pulumi program that provisions the CRD and creates an instance of it. | ||
```typescript | ||
import * as crontabs from "./crontabs" | ||
import * as pulumi from "@pulumi/pulumi" | ||
|
||
// Register the CronTab CRD. | ||
const cronTabDefinition = new crontabs.stable.CronTabDefinition("my-crontab-definition") | ||
|
||
// Instantiate a CronTab resource. | ||
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", | ||
} | ||
}) | ||
|
||
``` | ||
As you can see, the `CronTab` object is typed! For example, if you try to set | ||
`cronSpec` to a non-string or add an extra field, your IDE should immediately warn you. | ||
|
||
### Python | ||
```bash | ||
$ crd2pulumi --pythonPath ./crontabs resourcedefinition.yaml | ||
``` | ||
```python | ||
import pulumi_kubernetes as k8s | ||
import pulumi_kubernetes.apiextensions.v1 as v1 | ||
|
||
import crontabs.pulumi_crds as crontabs | ||
|
||
|
||
# Register the CronTab CRD. | ||
crontab_definition = k8s.yaml.ConfigFile("my-crontab-definition", file="resourcedefinition.yaml") | ||
|
||
# Instantiate a CronTab resource. | ||
crontab_instance = crontabs.stable.v1.CronTab( | ||
"my-new-cron-object", | ||
metadata=k8s.meta.v1.ObjectMetaArgs( | ||
name="my-new-cron-object" | ||
), | ||
spec=crontabs.stable.v1.CronTabSpecArgs( | ||
cron_spec="* * * */5", | ||
image="my-awesome-cron-image", | ||
) | ||
) | ||
|
||
``` | ||
|
||
### Go | ||
```bash | ||
$ crd2pulumi --goPath ./crontabs resourcedefinition.yaml | ||
``` | ||
Now we can access the `NewCronTab()` constructor. Create a `main.go` file with the following code. In this example, the Pulumi project's module is named `crds-go-final`, so the import path is `crds-go-final/crontabs/stable/v1`. Make sure to swap this out with your own module's name. | ||
```go | ||
package main | ||
|
||
import ( | ||
crontabs_v1 "crds-go-final/crontabs/stable/v1" | ||
|
||
meta_v1 "github.com/pulumi/pulumi-kubernetes/sdk/v2/go/kubernetes/meta/v1" | ||
"github.com/pulumi/pulumi/sdk/v2/go/pulumi" | ||
) | ||
|
||
func main() { | ||
pulumi.Run(func(ctx *pulumi.Context) error { | ||
// Register the CronTab CRD. | ||
_, err := yaml.NewConfigFile(ctx, "my-crontab-definition", | ||
&yaml.ConfigFileArgs{ | ||
File: "resourcedefinition.yaml", | ||
}, | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Instantiate a CronTab resource. | ||
_, err := crontabs_v1.NewCronTab(ctx, "cronTabInstance", &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"), | ||
Replicas: pulumi.IntPtr(3), | ||
}, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
``` | ||
|
||
### C\# | ||
```bash | ||
$ crd2pulumi --dotnetPath ./crontabs resourcedefinition.yaml | ||
``` | ||
```csharp | ||
using Pulumi; | ||
using Pulumi.Kubernetes.Yaml; | ||
using Pulumi.Kubernetes.Types.Inputs.Meta.V1; | ||
|
||
class MyStack : Stack | ||
{ | ||
public MyStack() | ||
{ | ||
// Register a CronTab CRD. | ||
var cronTabDefinition = new Pulumi.Kubernetes.Yaml.ConfigFile("my-crontab-definition", | ||
new ConfigFileArgs{ | ||
File = "resourcedefinition.yaml" | ||
} | ||
); | ||
|
||
// Instantiate a CronTab resource. | ||
var cronTabInstance = new Pulumi.Crds.Stable.V1.CronTab("cronTabInstance", | ||
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 get an `Duplicate 'global::System.Runtime.Versioning.TargetFrameworkAttribute' attribute` error when trying to run `pulumi up`, then try deleting the `crontabs/bin` and `crontabs/obj` folders. | ||
Now let's run the program and perform the update. | ||
```bash | ||
$ pulumi up | ||
Previewing update (dev): | ||
Type Name Plan | ||
pulumi:pulumi:Stack examples-dev | ||
+ ├─ kubernetes:stable.example.com:CronTab my-new-cron-object create | ||
+ └─ kubernetes:apiextensions.k8s.io:CustomResourceDefinition my-crontab-definition create | ||
Resources: | ||
+ 2 to create | ||
1 unchanged | ||
Do you want to perform this update? yes | ||
Updating (dev): | ||
Type Name Status | ||
pulumi:pulumi:Stack examples-dev | ||
+ ├─ kubernetes:stable.example.com:CronTab my-new-cron-object created | ||
+ └─ kubernetes:apiextensions.k8s.io:CustomResourceDefinition my-crontab-definition created | ||
Outputs: | ||
urn: "urn:pulumi:dev::examples::kubernetes:stable.example.com/v1:CronTab::my-new-cron-object" | ||
Resources: | ||
+ 2 created | ||
1 unchanged | ||
Duration: 17s | ||
Permalink: https://app.pulumi.com/albert-zhong/examples/dev/updates/4 | ||
``` | ||
It looks like both the CronTab definition and instance were both created! Finally, let's verify that they were created | ||
by manually viewing the raw YAML data: | ||
```bash | ||
$ kubectl get ct -o yaml | ||
``` | ||
```yaml | ||
- apiVersion: stable.example.com/v1 | ||
kind: CronTab | ||
metadata: | ||
annotations: | ||
kubectl.kubernetes.io/last-applied-configuration: | | ||
{"apiVersion":"stable.example.com/v1","kind":"CronTab","metadata":{"labels":{"app.kubernetes.io/managed-by":"pulumi"},"name":"my-new-cron-object"},"spec":{"cronSpec":"* * * * */5","image":"my-awesome-cron-image"}} | ||
creationTimestamp: "2020-08-10T09:50:38Z" | ||
generation: 1 | ||
labels: | ||
app.kubernetes.io/managed-by: pulumi | ||
name: my-new-cron-object | ||
namespace: default | ||
resourceVersion: "1658962" | ||
selfLink: /apis/stable.example.com/v1/namespaces/default/crontabs/my-new-cron-object | ||
uid: 5e2c56a2-7332-49cf-b0fc-211a0892c3d5 | ||
spec: | ||
cronSpec: '* * * * */5' | ||
image: my-awesome-cron-image | ||
kind: List | ||
metadata: | ||
resourceVersion: "" | ||
selfLink: "" | ||
``` |
Oops, something went wrong.