Skip to content

Commit fe04913

Browse files
committed
feat: Updating chart to support CRD struct, Fixes #419
1. Added support for the new crds.enabled and crds.keep options in the CertManager component 2. Added proper backward compatibility with the deprecated installCRDs option 3. Updated the schema.json to include the new type definition 4. Created an example to showcase how to use the new options 5. Added a new deleteOnDestroy boolean field to the CertManagerCrds struct in schema.json 6. Updated the CertManagerCrds struct in chart.go to include the new field 7. Implemented the functionality in provider.go to handle CRD deletion on resource destruction
1 parent 5bf1615 commit fe04913

File tree

18 files changed

+817
-15
lines changed

18 files changed

+817
-15
lines changed

examples/examples_ts_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,30 @@ func TestTsCertManagerPreview(t *testing.T) {
4949
p.Preview(t)
5050
})
5151
}
52+
53+
// TestCertManagerWithCrdsUpDestroyUp verifies that CRDs can be deployed, destroyed, and deployed again
54+
// without conflicts. This is especially important for ensuring that the crds.enabled functionality
55+
// works correctly through complete lifecycle operations.
56+
func TestCertManagerWithCrdsUpDestroyUp(t *testing.T) {
57+
t.Run("TestSimpleCertManagerWithCrdsTs", func(t *testing.T) {
58+
p := pulumitest.NewPulumiTest(t, "simple-cert-manager-with-crds-ts",
59+
opttest.LocalProviderPath("pulumi-kubernetes-cert-manager", filepath.Join(getCwd(t), "..", "bin")),
60+
opttest.YarnLink("@pulumi/kubernetes-cert-manager"),
61+
)
62+
p.SetConfig(t, "repository", "public.ecr.aws/eks-anywhere-dev/cert-manager/cert-manager-controller")
63+
64+
// First deployment
65+
p.Up(t)
66+
p.Preview(t, optpreview.ExpectNoChanges())
67+
68+
// Destroy the stack
69+
p.Destroy(t)
70+
71+
// Re-deploy to verify there are no CRD conflicts
72+
p.Up(t)
73+
p.Preview(t, optpreview.ExpectNoChanges())
74+
75+
// Clean up
76+
p.Destroy(t)
77+
})
78+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: simple-cert-manager-with-crds-ts
2+
description: A minimal TypeScript Pulumi program showcasing cert-manager deployment with new CRDs configuration
3+
runtime: nodejs
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import * as k8s from "@pulumi/kubernetes";
2+
import * as certmanager from "@pulumi/kubernetes-cert-manager";
3+
import * as random from "@pulumi/random";
4+
import * as pulumi from "@pulumi/pulumi"
5+
6+
const randomString = new random.RandomString("random", {
7+
length: 16,
8+
special: false,
9+
})
10+
11+
const conf = new pulumi.Config()
12+
const confRepo = conf.get("repository")
13+
let repository = randomString.result
14+
if (confRepo) {
15+
repository = pulumi.output(confRepo)
16+
}
17+
18+
// Create a sandbox namespace.
19+
const ns = new k8s.core.v1.Namespace("sandbox-ns");
20+
21+
// Install a cert manager into our cluster with CRD deletion configuration
22+
const manager = new certmanager.CertManager("cert-manager", {
23+
// Using the new CRDs structure instead of installCRDs
24+
crds: {
25+
enabled: true,
26+
keep: false,
27+
deleteOnDestroy: true // This will ensure CRDs are deleted on destroy
28+
},
29+
helmOptions: {
30+
namespace: ns.metadata.name,
31+
version: "v1.15.3",
32+
},
33+
image: pulumi.all([repository, "v1.15.3-eks-a-v0.21.3-dev-build.0"]).apply(([repository, tag]) => {
34+
return {
35+
repository,
36+
tag: tag,
37+
}
38+
}),
39+
cainjector: {
40+
"image": {
41+
repository: "public.ecr.aws/eks-anywhere-dev/cert-manager/cert-manager-cainjector",
42+
tag: "v1.15.3-eks-a-v0.21.3-dev-build.0",
43+
},
44+
},
45+
startupapicheck: {
46+
"image": {
47+
repository: "public.ecr.aws/eks-anywhere-dev/cert-manager/cert-manager-startupapicheck",
48+
tag: "v1.15.3-eks-a-v0.21.3-dev-build.0",
49+
}
50+
},
51+
webhook: {
52+
image: {
53+
repository: "public.ecr.aws/eks-anywhere-dev/cert-manager/cert-manager-webhook",
54+
tag: "v1.15.3-eks-a-v0.21.3-dev-build.0"
55+
}
56+
}
57+
});
58+
59+
// Create a cluster issuer that uses self-signed certificates.
60+
const issuer = new k8s.apiextensions.CustomResource(
61+
"issuer",
62+
{
63+
apiVersion: "cert-manager.io/v1",
64+
kind: "Issuer",
65+
metadata: {
66+
name: "selfsigned-issuer",
67+
namespace: ns.metadata.name,
68+
},
69+
spec: {
70+
selfSigned: {},
71+
},
72+
},
73+
{ dependsOn: manager }
74+
);
75+
76+
export const certManagerStatus = manager.status;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "simple-cert-manager-with-crds-ts",
3+
"devDependencies": {
4+
"@types/node": "^18"
5+
},
6+
"dependencies": {
7+
"@pulumi/kubernetes": "^4.5.5",
8+
"@pulumi/kubernetes-cert-manager": "latest",
9+
"@pulumi/pulumi": "^3.0.0"
10+
}
11+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"compilerOptions": {
3+
"strict": true,
4+
"outDir": "bin",
5+
"target": "es2016",
6+
"module": "commonjs",
7+
"moduleResolution": "node",
8+
"sourceMap": true,
9+
"experimentalDecorators": true,
10+
"pretty": true,
11+
"noFallthroughCasesInSwitch": true,
12+
"noImplicitReturns": true,
13+
"forceConsistentCasingInFileNames": true
14+
},
15+
"files": [
16+
"index.ts"
17+
]
18+
}

provider/cmd/pulumi-resource-kubernetes-cert-manager/schema.json

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@
8989
"$ref": "#/types/kubernetes-cert-manager:index:CertManagerIngressShim"
9090
},
9191
"installCRDs": {
92-
"type": "boolean"
92+
"type": "boolean",
93+
"description": "Deprecated: Use crds.enabled and crds.keep instead"
94+
},
95+
"crds": {
96+
"$ref": "#/types/kubernetes-cert-manager:index:CertManagerCrds"
9397
},
9498
"no_proxy": {
9599
"items": {
@@ -178,6 +182,24 @@
178182
}
179183
},
180184
"types": {
185+
"kubernetes-cert-manager:index:CertManagerCrds": {
186+
"properties": {
187+
"enabled": {
188+
"type": "boolean",
189+
"description": "Specifies whether the CRDs should be installed as part of the Helm installation"
190+
},
191+
"keep": {
192+
"type": "boolean",
193+
"description": "Specifies whether the CRDs should be kept when the Helm release is uninstalled"
194+
},
195+
"deleteOnDestroy": {
196+
"type": "boolean",
197+
"description": "Specifies whether the CRDs should be explicitly deleted when the resource is destroyed, regardless of the keep setting"
198+
}
199+
},
200+
"type": "object",
201+
"description": "Custom Resource Definitions installation configuration"
202+
},
181203
"kubernetes-cert-manager:index:Release": {
182204
"description": "A Release is an instance of a chart running in a Kubernetes cluster.\nA Chart is a Helm package. It contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster.\nNote - Helm Release is currently in BETA and may change. Use in production environment is discouraged.",
183205
"properties": {

provider/pkg/provider/chart.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func (c *CertManager) DefaultRepoURL() string { return "https
3838
type CertManagerArgs struct {
3939
Global kcm.CertManagerGlobalPtrInput `pulumi:"global"`
4040
InstallCRDs *bool `pulumi:"installCRDs"`
41+
Crds kcm.CertManagerCrdsPtrInput `pulumi:"crds"`
4142
ReplicaCount *int `pulumi:"replicaCount"`
4243
Strategy *appsv1.DeploymentStrategy `pulumi:"strategy" pschema:"ref=/kubernetes/v4.21.0/schema.json#/types/kubernetes:apps/v1:DeploymentStrategy"`
4344
// Comma separated list of feature gates that should be enabled on the controller pod.
@@ -302,3 +303,12 @@ type CertManagerStartupAPICheckRBAC struct {
302303
// annotations for the startup API Check job RBAC and PSP resources
303304
Annotations *map[string]string `pulumi:"annotations"`
304305
}
306+
307+
type CertManagerCrds struct {
308+
// Specifies whether the CRDs should be installed as part of the Helm installation
309+
Enabled *bool `pulumi:"enabled"`
310+
// Specifies whether the CRDs should be kept when the Helm release is uninstalled
311+
Keep *bool `pulumi:"keep"`
312+
// Specifies whether the CRDs should be explicitly deleted when the resource is destroyed, regardless of the keep setting
313+
DeleteOnDestroy *bool `pulumi:"deleteOnDestroy"`
314+
}

provider/pkg/provider/provider.go

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,87 @@ func Serve(version string, schema []byte) {
3939
// creates, registers, and returns the resulting object.
4040
func Construct(ctx *pulumi.Context, typ, name string, inputs pp.ConstructInputs,
4141
opts pulumi.ResourceOption) (*pp.ConstructResult, error) {
42-
return helmbase.Construct(ctx, &CertManager{}, typ, name, &CertManagerArgs{}, inputs, opts)
42+
args := &CertManagerArgs{}
43+
if err := inputs.CopyTo(args); err != nil {
44+
return nil, err
45+
}
46+
47+
// Handle backward compatibility for installCRDs (deprecated)
48+
// When installCRDs is true, set crds.enabled=true and crds.keep=true
49+
if args.InstallCRDs != nil && *args.InstallCRDs {
50+
// For backwards compatibility, set values in the Helm chart
51+
if args.HelmOptions == nil {
52+
args.HelmOptions = &helmbase.ReleaseType{}
53+
}
54+
if args.HelmOptions.Values == nil {
55+
args.HelmOptions.Values = map[string]interface{}{}
56+
}
57+
58+
// Only set crds values if not already explicitly set by user
59+
if _, ok := args.HelmOptions.Values["crds"]; !ok {
60+
args.HelmOptions.Values["crds"] = map[string]interface{}{
61+
"enabled": true,
62+
"keep": true,
63+
}
64+
}
65+
}
66+
67+
// Handle DeleteOnDestroy for CRDs
68+
if args.Crds != nil && ctx.IsPreview() == false {
69+
// Extract crds from the input or create default
70+
var deleteOnDestroy bool
71+
if args.Crds.DeleteOnDestroy != nil && *args.Crds.DeleteOnDestroy {
72+
deleteOnDestroy = true
73+
}
74+
75+
// If DeleteOnDestroy is set to true, register a delete function to remove CRDs
76+
if deleteOnDestroy {
77+
ctx.RegisterResourceDeletedCallback(ctx.NewResource(&CertManager{}), func(id string) error {
78+
// List of cert-manager CRDs to delete
79+
crds := []string{
80+
"certificaterequests.cert-manager.io",
81+
"certificates.cert-manager.io",
82+
"challenges.acme.cert-manager.io",
83+
"clusterissuers.cert-manager.io",
84+
"issuers.cert-manager.io",
85+
"orders.acme.cert-manager.io",
86+
}
87+
88+
// Create a Pulumi provider to execute kubernetes operations
89+
provider := ctx.NewResource("kubernetes:providers:kubeconfig", "cert-manager-crds-cleanup-provider", nil, nil)
90+
91+
// For each CRD, create a dynamic resource to delete it
92+
for _, crd := range crds {
93+
// Log that we're deleting the CRD
94+
ctx.Log.Info(pulumi.Sprintf("Deleting CRD %s as requested by deleteOnDestroy setting", crd), nil)
95+
96+
// Create a dynamic resource that deletes the CRD
97+
deleteOpts := &pulumi.ResourceOptions{
98+
Provider: provider,
99+
DeleteBeforeReplace: true,
100+
Protect: false,
101+
}
102+
103+
// Create a dynamic resource that represents the deletion action
104+
_, err := ctx.RegisterResource("kubernetes:apiextensions.k8s.io/v1:CustomResourceDefinition",
105+
crd,
106+
&map[string]interface{}{
107+
"metadata": map[string]interface{}{
108+
"name": crd,
109+
},
110+
},
111+
deleteOpts)
112+
113+
if err != nil {
114+
ctx.Log.Error(pulumi.Sprintf("Failed to delete CRD %s: %v", crd, err), nil)
115+
return err
116+
}
117+
}
118+
119+
return nil
120+
})
121+
}
122+
}
123+
124+
return helmbase.Construct(ctx, &CertManager{}, typ, name, args, inputs, opts)
43125
}

sdk/dotnet/CertManager.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public sealed class CertManagerArgs : global::Pulumi.ResourceArgs
6767
[Input("containerSecurityContext")]
6868
public Input<Pulumi.Kubernetes.Types.Inputs.Core.V1.SecurityContextArgs>? ContainerSecurityContext { get; set; }
6969

70+
[Input("crds")]
71+
public Input<Inputs.CertManagerCrdsArgs>? Crds { get; set; }
72+
7073
[Input("deploymentAnnotations")]
7174
private InputMap<string>? _deploymentAnnotations;
7275

@@ -142,6 +145,9 @@ public InputList<Pulumi.Kubernetes.Types.Inputs.Core.V1.VolumeArgs> ExtraVolumes
142145
[Input("ingressShim")]
143146
public Input<Inputs.CertManagerIngressShimArgs>? IngressShim { get; set; }
144147

148+
/// <summary>
149+
/// Deprecated: Use crds.enabled and crds.keep instead
150+
/// </summary>
145151
[Input("installCRDs")]
146152
public Input<bool>? InstallCRDs { get; set; }
147153

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// *** WARNING: this file was generated by pulumi-language-dotnet. ***
2+
// *** Do not edit by hand unless you're certain you know what you are doing! ***
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Collections.Immutable;
7+
using System.Threading.Tasks;
8+
using Pulumi.Serialization;
9+
10+
namespace Pulumi.KubernetesCertManager.Inputs
11+
{
12+
13+
/// <summary>
14+
/// Custom Resource Definitions installation configuration
15+
/// </summary>
16+
public sealed class CertManagerCrdsArgs : global::Pulumi.ResourceArgs
17+
{
18+
/// <summary>
19+
/// Specifies whether the CRDs should be explicitly deleted when the resource is destroyed, regardless of the keep setting
20+
/// </summary>
21+
[Input("deleteOnDestroy")]
22+
public Input<bool>? DeleteOnDestroy { get; set; }
23+
24+
/// <summary>
25+
/// Specifies whether the CRDs should be installed as part of the Helm installation
26+
/// </summary>
27+
[Input("enabled")]
28+
public Input<bool>? Enabled { get; set; }
29+
30+
/// <summary>
31+
/// Specifies whether the CRDs should be kept when the Helm release is uninstalled
32+
/// </summary>
33+
[Input("keep")]
34+
public Input<bool>? Keep { get; set; }
35+
36+
public CertManagerCrdsArgs()
37+
{
38+
}
39+
public static new CertManagerCrdsArgs Empty => new CertManagerCrdsArgs();
40+
}
41+
}

0 commit comments

Comments
 (0)