From 99eed5d42d946cab3e5405be6fb814989e7f66e1 Mon Sep 17 00:00:00 2001
From: Levi Blackstone <levi@pulumi.com>
Date: Wed, 28 Oct 2020 10:12:51 -0600
Subject: [PATCH 1/6] Add a ready attribute to await Helm Charts

---
 provider/pkg/gen/nodejs-templates/helm/v2/helm.ts | 2 ++
 provider/pkg/gen/nodejs-templates/helm/v3/helm.ts | 2 ++
 provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl  | 1 +
 sdk/nodejs/helm/v2/helm.ts                        | 2 ++
 sdk/nodejs/helm/v3/helm.ts                        | 2 ++
 sdk/nodejs/yaml/yaml.ts                           | 1 +
 6 files changed, 10 insertions(+)

diff --git a/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts b/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
index 9712f4fb26..19e511d8cc 100644
--- a/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
+++ b/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
@@ -254,6 +254,8 @@ export class Chart extends yaml.CollectionComponentResource {
                 overrides.removeCallback();
             }
         });
+
+        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
     }
 
     parseTemplate(
diff --git a/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts b/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
index 4489d896d9..d9c8374b55 100644
--- a/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
+++ b/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
@@ -157,6 +157,8 @@ export class Chart extends yaml.CollectionComponentResource {
         this.resources = allConfig.apply(cfg => {
             return this.parseChart(cfg, releaseName, opts)
         });
+
+        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
     }
 
     parseChart(config: ChartOpts | LocalChartOpts, releaseName: string, opts?: pulumi.ComponentResourceOptions) {
diff --git a/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl b/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl
index 9cec91cbb1..72c097b2e4 100644
--- a/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl
+++ b/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl
@@ -25,6 +25,7 @@ import { getVersion } from "../utilities";
 
 export abstract class CollectionComponentResource extends pulumi.ComponentResource {
     resources!: pulumi.Output<{ [key: string]: pulumi.CustomResource }>;
+    ready!: pulumi.Output<pulumi.Output<pulumi.CustomResource>[]>;
 
     protected constructor(
         resourceType: string, name: string, config: any, opts?: pulumi.ComponentResourceOptions,
diff --git a/sdk/nodejs/helm/v2/helm.ts b/sdk/nodejs/helm/v2/helm.ts
index 9712f4fb26..19e511d8cc 100644
--- a/sdk/nodejs/helm/v2/helm.ts
+++ b/sdk/nodejs/helm/v2/helm.ts
@@ -254,6 +254,8 @@ export class Chart extends yaml.CollectionComponentResource {
                 overrides.removeCallback();
             }
         });
+
+        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
     }
 
     parseTemplate(
diff --git a/sdk/nodejs/helm/v3/helm.ts b/sdk/nodejs/helm/v3/helm.ts
index 4489d896d9..d9c8374b55 100644
--- a/sdk/nodejs/helm/v3/helm.ts
+++ b/sdk/nodejs/helm/v3/helm.ts
@@ -157,6 +157,8 @@ export class Chart extends yaml.CollectionComponentResource {
         this.resources = allConfig.apply(cfg => {
             return this.parseChart(cfg, releaseName, opts)
         });
+
+        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
     }
 
     parseChart(config: ChartOpts | LocalChartOpts, releaseName: string, opts?: pulumi.ComponentResourceOptions) {
diff --git a/sdk/nodejs/yaml/yaml.ts b/sdk/nodejs/yaml/yaml.ts
index 87fa9fb935..5f29e1777d 100644
--- a/sdk/nodejs/yaml/yaml.ts
+++ b/sdk/nodejs/yaml/yaml.ts
@@ -25,6 +25,7 @@ import { getVersion } from "../utilities";
 
 export abstract class CollectionComponentResource extends pulumi.ComponentResource {
     resources!: pulumi.Output<{ [key: string]: pulumi.CustomResource }>;
+    ready!: pulumi.Output<pulumi.Output<pulumi.CustomResource>[]>;
 
     protected constructor(
         resourceType: string, name: string, config: any, opts?: pulumi.ComponentResourceOptions,

From 913299df62efb2352231d2961e18098f5f8df92c Mon Sep 17 00:00:00 2001
From: Levi Blackstone <levi@pulumi.com>
Date: Wed, 11 Nov 2020 11:56:59 -0700
Subject: [PATCH 2/6] Add test

---
 tests/sdk/nodejs/examples/examples_test.go    |  34 +-
 .../nodejs/examples/helm-local/step1/index.ts |  34 +-
 .../helm-local/step1/nginx-lego/Chart.yaml    |  16 -
 .../helm-local/step1/nginx-lego/README.md     |  82 ---
 .../step1/nginx-lego/templates/NOTES.txt      |  37 --
 .../step1/nginx-lego/templates/_helpers.tpl   |  16 -
 .../templates/default-deployment.yaml         |  21 -
 .../nginx-lego/templates/default-service.yaml |  13 -
 .../nginx-lego/templates/lego-configmap.yaml  |  11 -
 .../nginx-lego/templates/lego-deployment.yaml |  40 --
 .../nginx-lego/templates/nginx-configmap.yaml |  12 -
 .../templates/nginx-deployment.yaml           |  38 --
 .../templates/nginx-monitoring.yaml           |  15 -
 .../nginx-lego/templates/nginx-service.yaml   |  15 -
 .../helm-local/step1/nginx-lego/values.yaml   |  73 ---
 .../step1/{nginx-lego => nginx}/.helmignore   |   0
 .../helm-local/step1/nginx/Chart.yaml         |  21 +
 .../examples/helm-local/step1/nginx/README.md | 252 +++++++++
 .../helm-local/step1/nginx/ci/ct-values.yaml  |   2 +
 ...-with-ingress-metrics-and-serverblock.yaml |  26 +
 .../step1/nginx/templates/NOTES.txt           |  39 ++
 .../step1/nginx/templates/_helpers.tpl        | 292 ++++++++++
 .../step1/nginx/templates/deployment.yaml     | 192 +++++++
 .../step1/nginx/templates/health-ingress.yaml |  37 ++
 .../helm-local/step1/nginx/templates/hpa.yaml |  27 +
 .../step1/nginx/templates/ingress.yaml        |  37 ++
 .../nginx/templates/ldap-daemon-secrets.yaml  |  14 +
 .../templates/server-block-configmap.yaml     |  13 +
 .../step1/nginx/templates/servicemonitor.yaml |  28 +
 .../helm-local/step1/nginx/templates/svc.yaml |  41 ++
 .../step1/nginx/templates/tls-secrets.yaml    |  14 +
 .../helm-local/step1/nginx/values.schema.json |  68 +++
 .../helm-local/step1/nginx/values.yaml        | 510 ++++++++++++++++++
 .../nodejs/examples/helm-local/step2/index.ts |  34 +-
 34 files changed, 1674 insertions(+), 430 deletions(-)
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/Chart.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/README.md
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/NOTES.txt
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/_helpers.tpl
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-deployment.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-service.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-configmap.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-deployment.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-configmap.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-deployment.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-monitoring.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-service.yaml
 delete mode 100755 tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/values.yaml
 rename tests/sdk/nodejs/examples/helm-local/step1/{nginx-lego => nginx}/.helmignore (100%)
 mode change 100755 => 100644
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/Chart.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/README.md
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/ct-values.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/values-with-ingress-metrics-and-serverblock.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/NOTES.txt
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/_helpers.tpl
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/deployment.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/health-ingress.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/hpa.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ingress.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ldap-daemon-secrets.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/server-block-configmap.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/servicemonitor.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/svc.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/tls-secrets.yaml
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/values.schema.json
 create mode 100644 tests/sdk/nodejs/examples/helm-local/step1/nginx/values.yaml

diff --git a/tests/sdk/nodejs/examples/examples_test.go b/tests/sdk/nodejs/examples/examples_test.go
index f6a09ccb1c..0a968347ea 100644
--- a/tests/sdk/nodejs/examples/examples_test.go
+++ b/tests/sdk/nodejs/examples/examples_test.go
@@ -18,6 +18,7 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"regexp"
 	"sort"
 	"testing"
 
@@ -189,13 +190,40 @@ func TestAccHelmLocal(t *testing.T) {
 	skipIfShort(t)
 	test := getBaseOptions(t).
 		With(integration.ProgramTestOptions{
-			Dir:         filepath.Join(getCwd(t), "helm-local", "step1"),
-			SkipRefresh: true, // Deployment controller changes object out-of-band.
+			Dir:                  filepath.Join(getCwd(t), "helm-local", "step1"),
+			ExpectRefreshChanges: true,
 			ExtraRuntimeValidation: func(
 				t *testing.T, stackInfo integration.RuntimeValidationStackInfo,
 			) {
 				assert.NotNil(t, stackInfo.Deployment)
-				assert.Equal(t, 15, len(stackInfo.Deployment.Resources))
+				assert.Equal(t, 12, len(stackInfo.Deployment.Resources))
+
+				// Verify resource creation order using the Event stream. The Chart resources must be created
+				// first, followed by the dependent ConfigMap. (The ConfigMap doesn't actually need the Chart, but
+				// it creates almost instantly, so it's a good choice to test creation ordering)
+				cmRegex := regexp.MustCompile(`ConfigMap::test-.*/nginx-server-block`)
+				svcRegex := regexp.MustCompile(`Service::test-.*/nginx`)
+				deployRegex := regexp.MustCompile(`Deployment::test-.*/nginx`)
+				dependentRegex := regexp.MustCompile(`ConfigMap::foo`)
+
+				var configmapFound, serviceFound, deploymentFound, dependentFound bool
+				for _, e := range stackInfo.Events {
+					if e.ResOutputsEvent != nil {
+						switch {
+						case cmRegex.MatchString(e.ResOutputsEvent.Metadata.URN):
+							configmapFound = true
+						case svcRegex.MatchString(e.ResOutputsEvent.Metadata.URN):
+							serviceFound = true
+						case deployRegex.MatchString(e.ResOutputsEvent.Metadata.URN):
+							deploymentFound = true
+						case dependentRegex.MatchString(e.ResOutputsEvent.Metadata.URN):
+							dependentFound = true
+						}
+						assert.Falsef(t, dependentFound && !(configmapFound && serviceFound && deploymentFound),
+							"dependent ConfigMap created before all chart resources were ready")
+						fmt.Println(e.ResOutputsEvent.Metadata.URN)
+					}
+				}
 			},
 			EditDirs: []integration.EditDir{
 				{
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/index.ts b/tests/sdk/nodejs/examples/helm-local/step1/index.ts
index cd900b053d..242ac41a92 100644
--- a/tests/sdk/nodejs/examples/helm-local/step1/index.ts
+++ b/tests/sdk/nodejs/examples/helm-local/step1/index.ts
@@ -1,4 +1,4 @@
-// Copyright 2016-2019, Pulumi Corporation.
+// Copyright 2016-2020, Pulumi Corporation.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -19,30 +19,19 @@ const namespace = new k8s.core.v1.Namespace("test");
 const namespaceName = namespace.metadata.name;
 
 function chart(resourcePrefix?: string): k8s.helm.v2.Chart {
-    return new k8s.helm.v2.Chart("nginx-lego", {
-        // Represents chart `stable/nginx-lego@v0.3.1`.
-        path: "nginx-lego",
-        version: "0.3.1",
+    return new k8s.helm.v2.Chart("nginx", {
+        path: "nginx",
         namespace: namespaceName,
         resourcePrefix: resourcePrefix,
         values: {
-            // Override for the Chart's `values.yml` file. Use `null` to zero out resource requests so it
-            // can be scheduled on our (wimpy) CI cluster. (Setting these values to `null` is the "normal"
-            // way to delete values.)
-            nginx: {resources: null},
-            default: {resources: null},
-            lego: {resources: null}
+            service: { type: "ClusterIP" }
         },
         transformations: [
-            // Make every service private to the cluster, i.e., turn all services into ClusterIP instead of
-            // LoadBalancer.
-            (obj: any) => {
+            (obj: any, opts: pulumi.CustomResourceOptions) => {
                 if (obj.kind == "Service" && obj.apiVersion == "v1") {
-                    if (obj.spec && obj.spec.type && obj.spec.type == "LoadBalancer") {
-                        obj.spec.type = "ClusterIP";
-                    }
+                    opts.additionalSecretOutputs = ["status"];
                 }
-            },
+            }
         ]
     });
 }
@@ -50,9 +39,16 @@ function chart(resourcePrefix?: string): k8s.helm.v2.Chart {
 // Create the first instance of the Chart.
 const nginx = chart();
 
+// Create a ConfigMap depending on the Chart. The ConfigMap should not be created until after all of the Chart
+// resources are ready.
+new k8s.core.v1.ConfigMap("foo", {
+    metadata: { namespace: namespaceName },
+    data: {foo: "bar"}
+}, {dependsOn: nginx})
+
 // Export the (cluster-private) IP address of the Guestbook frontend.
 const frontendServiceSpec = pulumi.all([namespaceName, nginx]).apply(([nsName, nginx]) =>
-    nginx.getResourceProperty("v1/Service", nsName, "nginx-lego-nginx-lego", "spec"));
+    nginx.getResourceProperty("v1/Service", nsName, "nginx", "spec"));
 export const frontendServiceIP = frontendServiceSpec.clusterIP;
 
 // Deploy a duplicate chart with a different resource prefix to verify that multiple instances of the Chart
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/Chart.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/Chart.yaml
deleted file mode 100755
index 04d6690afa..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/Chart.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-deprecated: true
-description: Chart for nginx-ingress-controller and kube-lego
-engine: gotpl
-keywords:
-- kube-lego
-- nginx-ingress-controller
-- nginx
-- letsencrypt
-maintainers:
-- email: jack.zampolin@gmail.com
-  name: Jack Zampolin
-name: nginx-lego
-sources:
-- https://github.com/kubernetes/contrib/tree/master/ingress/controllers/nginx
-- https://github.com/jetstack/kube-lego/tree/master/examples/nginx
-version: 0.3.1
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/README.md b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/README.md
deleted file mode 100755
index e8e3429190..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/README.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# nginx-lego
-
-**This chart has been deprecated as of version 0.2.1 and will not be updated. Please use the nginx-ingress and (optional) kube-lego charts instead.**
-
-[nginx-lego](https://github.com/jetstack/kube-lego/tree/master/examples/nginx) is a chart for an [`nginx` ingress](https://github.com/kubernetes/contrib/tree/master/ingress/controllers/nginx) with optional support for automatically generating `SSL` cert for the managed routes.
-
-To use this ingress contoller add the following annotations to the `ingress` resources you would like to route through it:
-
-```yaml
-apiVersion: extensions/v1beta1
-kind: Ingress
-metadata:
-  namespace: foo
-  annotations:
-    # Add to route through the nginx service
-    kubernetes.io/ingress.class: nginx
-    # Add to generate certificates for this ingress
-    kubernetes.io/tls-acme: "true"
-spec:
-  tls:
-    # With this configuration kube-lego will generate a secret in namespace foo called `example-tls`
-    # for the URL `www.example.com`
-    - hosts:
-      - "www.example.com"
-      secretName: example-tls
-```
-
-## TL;DR;
-
-```bash
-$ helm install stable/kube-lego
-```
-
-## Introduction
-
-This chart bootstraps an nginx-lego deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
-
-## Prerequisites
-
-- Kubernetes 1.4+ with Beta APIs enabled
-
-## Installing the Chart
-
-To install the chart with the release name `my-release`:
-
-```bash
-$ helm install --name my-release stable/nginx-lego
-```
-
-The command deploys nginx-lego on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
-
-> **Tip**: List all releases using `helm list`
-
-## Uninstalling the Chart
-
-To uninstall/delete the `my-release` deployment:
-
-```bash
-$ helm delete my-release
-```
-
-The command removes all the Kubernetes components associated with the chart and deletes the release.
-
-## Configuration
-
-See `values.yaml` for configuration notes. Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
-
-```bash
-$ helm install --name my-release \
-  --set lego.enabled=false \
-    stable/nginx-lego
-```
-
-Installs the chart without kube-lego and the ability to generate certs.
-
-Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
-
-```bash
-$ helm install --name my-release -f values.yaml stable/nginx-lego
-```
-
-> **Tip**: You can use the default [values.yaml](values.yaml)
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/NOTES.txt b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/NOTES.txt
deleted file mode 100755
index 3b57244996..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/NOTES.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-################################################################################
-#### This chart has been deprecated as of version 0.2.1 and will not be updated.
-#### Please use the nginx-ingress and (optional) kube-lego charts instead.
-################################################################################
-
-This chart runs an nginx-ingress-controller  {{- if .Values.lego.enabled }}  and kube-lego  {{- end }}  adding the ability to use ingress resources to route in your cluster  {{- if .Values.lego.enabled -}}  as well as optionally generating SSL certs for you  {{- end -}}.
-
-EXAMPLE INGRESS YAML:
-
-apiVersion: extensions/v1beta1
-kind: Ingress
-metadata:
-  namespace: foo
-  annotations:
-    # Add to route through the nginx service
-    kubernetes.io/ingress.class: nginx
-{{- if .Values.lego.enabled }}
-    # Add to generate certificates for this ingress
-    kubernetes.io/tls-acme: "true"
-{{- end }}
-spec:
-  rules:
-  - host: www.example.com
-    http:
-      paths:
-      - backend:
-          serviceName: exampleService
-          servicePort: 80
-        path: /
-{{- if .Values.lego.enabled }}
-  tls:
-    # With this configuration kube-lego will generate a secret in namespace foo called `example-tls`
-    # for the URL `www.example.com`
-    - hosts:
-      - "www.example.com"
-      secretName: example-tls
-{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/_helpers.tpl b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/_helpers.tpl
deleted file mode 100755
index 895e6444d6..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/_helpers.tpl
+++ /dev/null
@@ -1,16 +0,0 @@
-{{/* vim: set filetype=mustache: */}}
-{{/*
-Expand the name of the chart.
-*/}}
-{{- define "nginx-lego.name" -}}
-{{- default .Chart.Name .Values.nameOverride | trunc 24 -}}
-{{- end -}}
-
-{{/*
-Create a default fully qualified app name.
-We truncate at 24 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
-*/}}
-{{- define "nginx-lego.fullname" -}}
-{{- $name := default .Chart.Name .Values.nameOverride -}}
-{{- printf "%s-%s" .Release.Name $name | trunc 24 -}}
-{{- end -}}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-deployment.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-deployment.yaml
deleted file mode 100755
index e09c011391..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-deployment.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}-default-backend
-  labels:
-    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
-spec:
-  replicas: {{ .Values.default.replicaCount }}
-  template:
-    metadata:
-      labels:
-        app: {{ template "nginx-lego.fullname" . }}-default-backend
-    spec:
-      containers:
-      - name: {{ template "nginx-lego.fullname" . }}-default-backend
-        image: "{{ .Values.default.image.repository }}:{{ .Values.default.image.tag }}"
-        imagePullPolicy: {{ .Values.default.image.pullPolicy | quote }}
-        ports:
-        - containerPort: 8080
-        resources:
-{{ toYaml .Values.default.resources | indent 10 }}
\ No newline at end of file
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-service.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-service.yaml
deleted file mode 100755
index 890d7a51d4..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/default-service.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}-default-backend
-  labels:
-    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
-spec:
-  type: ClusterIP
-  ports:
-  - port: 80
-    targetPort: 8080
-  selector:
-    app: {{ template "nginx-lego.fullname" . }}-default-backend
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-configmap.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-configmap.yaml
deleted file mode 100755
index 98d336c3e8..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-configmap.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-{{- if .Values.lego.enabled }}
-apiVersion: v1
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}-lego
-data:
-  # modify this to specify your address
-  lego.email: {{ .Values.lego.configmap.email | quote }}
-  # configure letencrypt's production api
-  lego.url: {{ .Values.lego.configmap.url | quote }}
-kind: ConfigMap
-{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-deployment.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-deployment.yaml
deleted file mode 100755
index 987360d9bf..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/lego-deployment.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-{{- if .Values.lego.enabled }}
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}-lego
-spec:
-  replicas: {{ .Values.lego.replicaCount }}
-  template:
-    metadata:
-      labels:
-        app: kube-lego
-    spec:
-      containers:
-      - name: {{ .Chart.Name }}-lego
-        image: "{{ .Values.lego.image.repository }}:{{ .Values.lego.image.tag }}"
-        imagePullPolicy: {{ .Values.lego.image.pullPolicy }}
-        ports:
-        - containerPort: 8080
-        env:
-        - name: LEGO_EMAIL
-          valueFrom:
-            configMapKeyRef:
-              name: {{ template "nginx-lego.fullname" . }}-lego
-              key: lego.email
-        - name: LEGO_URL
-          valueFrom:
-            configMapKeyRef:
-              name: {{ template "nginx-lego.fullname" . }}-lego
-              key: lego.url
-        - name: LEGO_NAMESPACE
-          valueFrom:
-            fieldRef:
-              fieldPath: metadata.namespace
-        - name: LEGO_POD_IP
-          valueFrom:
-            fieldRef:
-              fieldPath: status.podIP
-        resources:
-{{ toYaml .Values.nginx.resources | indent 10 }}
-{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-configmap.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-configmap.yaml
deleted file mode 100755
index e0af8c0262..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-configmap.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-apiVersion: v1
-data:
-  proxy-connect-timeout: {{ .Values.nginx.configmap.proxy_connect_timeout | quote }}
-  proxy-read-timeout: {{ .Values.nginx.configmap.proxy_read_timeout | quote }}
-  proxy-send-imeout: {{ .Values.nginx.configmap.proxy_send_imeout | quote }}
-  hsts-include-subdomains: {{ .Values.nginx.configmap.hsts_include_subdomains | quote }}
-  body-size: {{ .Values.nginx.configmap.body_size | quote }}
-  server-name-hash-bucket-size: {{ .Values.nginx.configmap.server_name_hash_bucket_size | quote }}
-  enable-vts-status: {{ .Values.nginx.configmap.enable_vts_status | quote }}
-kind: ConfigMap
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-deployment.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-deployment.yaml
deleted file mode 100755
index e673940dd7..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-deployment.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}
-  labels:
-    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
-spec:
-  replicas: {{ .Values.nginx.replicaCount }}
-  template:
-    metadata:
-      labels:
-        app: {{ template "nginx-lego.fullname" . }}
-    spec:
-      containers:
-      - name: {{ .Chart.Name }}
-        image: "{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.tag }}"
-        imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
-        env:
-          - name: POD_NAME
-            valueFrom:
-              fieldRef:
-                fieldPath: metadata.name
-          - name: POD_NAMESPACE
-            valueFrom:
-              fieldRef:
-                fieldPath: metadata.namespace
-        ports:
-        - containerPort: 80
-        - containerPort: 443
-{{- if .Values.nginx.monitoring }}
-        - containerPort: 8080
-{{- end }}
-        resources:
-{{ toYaml .Values.nginx.resources | indent 10 }}
-        args:
-        - /nginx-ingress-controller
-        - --default-backend-service={{ .Release.Namespace }}/{{ template "nginx-lego.fullname" . }}-default-backend
-        - --nginx-configmap={{ .Release.Namespace }}/{{ template "nginx-lego.fullname" . }}
\ No newline at end of file
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-monitoring.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-monitoring.yaml
deleted file mode 100755
index 2d6b40cb90..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-monitoring.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-{{- if .Values.nginx.monitoring }}
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}-monitoring
-  labels:
-    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
-spec:
-  type: ClusterIP
-  ports:
-  - port: 18080
-    name: vts-stats
-  selector:
-    app: {{ template "nginx-lego.fullname" . }}
-{{- end }}
\ No newline at end of file
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-service.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-service.yaml
deleted file mode 100755
index 07850cd0a9..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/templates/nginx-service.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ template "nginx-lego.fullname" . }}
-  labels:
-    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
-spec:
-  type: {{ .Values.nginx.service.type | quote }}
-  ports:
-  - port: 80
-    name: http
-  - port: 443
-    name: https
-  selector:
-    app: {{ template "nginx-lego.fullname" . }}
\ No newline at end of file
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/values.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/values.yaml
deleted file mode 100755
index 5aebcbf527..0000000000
--- a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/values.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-## nginx-lego spins up a scalable ingress provider that can also provision SSL certs
-## See https://github.com/jetstack/kube-lego/tree/master/examples/nginx for more information on implementation
-
-## Nginx configuration
-## ref: https://github.com/kubernetes/contrib/tree/master/ingress/controllers/nginx#automated-certificate-management-with-kube-lego
-##
-nginx:
-  replicaCount: 1
-  image:
-    repository: k8s.gcr.io/nginx-ingress-controller
-    tag: "0.8.3"
-    pullPolicy: IfNotPresent
-  service:
-    type: LoadBalancer
-  monitoring: false
-  resources:
-    limits:
-      cpu: 1
-      memory: 2Gi
-    requests:
-      cpu: 1
-      memory: 128Mi
-  configmap:
-    proxy_connect_timeout: "30"
-    proxy_read_timeout: "600"
-    proxy_send_imeout: "600"
-    hsts_include_subdomains: "false"
-    body_size: "64m"
-    server_name_hash_bucket_size: "256"
-    # TODO: figure out how to expose `{nginx_addr}:8080/nginx_status`, on existing service or create new one?
-    enable_vts_status: "false"
-
-## Default Backend configuration
-## To run a different 404 page for the managed domains please see the documentation below
-## ref: https://github.com/kubernetes/contrib/tree/master/404-server
-##
-default:
-  replicaCount: 1
-  image:
-    repository: k8s.gcr.io/defaultbackend
-    tag: "1.0"
-    pullPolicy: IfNotPresent
-  resources:
-    limits:
-      cpu: 1
-      memory: 2Gi
-    requests:
-      cpu: 1
-      memory: 128Mi
-
-## kube-lego configuration
-## ref: https://github.com/jetstack/kube-lego
-##
-lego:
-  enabled: false
-  replicaCount: 1
-  image:
-    repository: jetstack/kube-lego
-    tag: "0.1.3"
-    pullPolicy: IfNotPresent
-  configmap:
-    email: "my@email.tld"
-    # Production Let's Encrypt server
-    # url: "https://acme-v01.api.letsencrypt.org/directory"
-    # Test Let's Encrypt server
-    url: "https://acme-staging.api.letsencrypt.org/directory "
-  resources:
-    limits:
-      cpu: 1
-      memory: 2Gi
-    requests:
-      cpu: 1
-      memory: 128Mi
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/.helmignore b/tests/sdk/nodejs/examples/helm-local/step1/nginx/.helmignore
old mode 100755
new mode 100644
similarity index 100%
rename from tests/sdk/nodejs/examples/helm-local/step1/nginx-lego/.helmignore
rename to tests/sdk/nodejs/examples/helm-local/step1/nginx/.helmignore
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/Chart.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/Chart.yaml
new file mode 100644
index 0000000000..06303d71ca
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/Chart.yaml
@@ -0,0 +1,21 @@
+annotations:
+  category: Infrastructure
+apiVersion: v1
+appVersion: 1.19.1
+description: Chart for the nginx server
+engine: gotpl
+home: http://www.nginx.org
+icon: https://bitnami.com/assets/stacks/nginx/img/nginx-stack-220x234.png
+keywords:
+- nginx
+- http
+- web
+- www
+- reverse proxy
+maintainers:
+- email: containers@bitnami.com
+  name: Bitnami
+name: nginx
+sources:
+- https://github.com/bitnami/bitnami-docker-nginx
+version: 6.0.4
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/README.md b/tests/sdk/nodejs/examples/helm-local/step1/nginx/README.md
new file mode 100644
index 0000000000..1df5eeb651
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/README.md
@@ -0,0 +1,252 @@
+# NGINX
+
+[NGINX](https://nginx.org) (pronounced "engine-x") is an open source reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer, HTTP cache, and a web server (origin server).
+
+## TL;DR
+
+```bash
+$ helm repo add bitnami https://charts.bitnami.com/bitnami
+$ helm install my-release bitnami/nginx
+```
+
+## Introduction
+
+Bitnami charts for Helm are carefully engineered, actively maintained and are the quickest and easiest way to deploy containers on a Kubernetes cluster that are ready to handle production workloads.
+
+This chart bootstraps a [NGINX Open Source](https://github.com/bitnami/bitnami-docker-nginx) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
+
+Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications.
+
+## Prerequisites
+
+- Kubernetes 1.12+
+- Helm 2.12+ or Helm 3.0-beta3+
+
+## Installing the Chart
+
+To install the chart with the release name `my-release`:
+
+```bash
+$ helm repo add bitnami https://charts.bitnami.com/bitnami
+$ helm install my-release bitnami/nginx
+```
+
+These commands deploy NGINX Open Source on the Kubernetes cluster in the default configuration.
+
+> **Tip**: List all releases using `helm list`
+
+## Uninstalling the Chart
+
+To uninstall/delete the `my-release` deployment:
+
+```bash
+$ helm delete my-release
+```
+
+The command removes all the Kubernetes components associated with the chart and deletes the release.
+
+## Parameters
+
+The following tables lists the configurable parameters of the NGINX Open Source chart and their default values.
+
+| Parameter                                  | Description                                                                                  | Default                                                      |
+|--------------------------------------------|----------------------------------------------------------------------------------------------|--------------------------------------------------------------|
+| `global.imageRegistry`                     | Global Docker image registry                                                                 | `nil`                                                        |
+| `global.imagePullSecrets`                  | Global Docker registry secret names as an array                                              | `[]` (does not add image pull secrets to deployed pods)      |
+| `image.registry`                           | NGINX image registry                                                                         | `docker.io`                                                  |
+| `image.repository`                         | NGINX Image name                                                                             | `bitnami/nginx`                                              |
+| `image.tag`                                | NGINX Image tag                                                                              | `{TAG_NAME}`                                                 |
+| `image.pullPolicy`                         | NGINX image pull policy                                                                      | `IfNotPresent`                                               |
+| `image.pullSecrets`                        | Specify docker-registry secret names as an array                                             | `[]` (does not add image pull secrets to deployed pods)      |
+| `nameOverride`                             | String to partially override nginx.fullname template                                         | `nil`                                                        |
+| `fullnameOverride`                         | String to fully override nginx.fullname template                                             | `nil`                                                        |
+| `staticSiteConfigmap`                      | Name of existing ConfigMap with the server static content                                    | `nil`                                                        |
+| `staticSitePVC`                            | Name of existing PVC with the server static content                                          | `nil`                                                        |
+| `cloneStaticSiteFromGit.enabled`           | Get the server static content from a git repository                                          | `false`                                                      |
+| `cloneStaticSiteFromGit.image.registry`    | Git image registry                                                                           | `docker.io`                                                  |
+| `cloneStaticSiteFromGit.image.repository`  | Git image name                                                                               | `bitnami/git`                                                |
+| `cloneStaticSiteFromGit.image.tag`         | Git image tag                                                                                | `{TAG_NAME}`                                                 |
+| `cloneStaticSiteFromGit.image.pullPolicy`  | Git image pull policy                                                                        | `Always`                                                     |
+| `cloneStaticSiteFromGit.image.pullSecrets` | Specify docker-registry secret names as an array                                             | `[]` (does not add image pull secrets to deployed pods)      |
+| `cloneStaticSiteFromGit.repository`        | Repository to clone static content from                                                      | `nil`                                                        |
+| `cloneStaticSiteFromGit.branch`            | Branch inside the git repository                                                             | `nil`                                                        |
+| `cloneStaticSiteFromGit.interval`          | Interval for sidecar container pull from the repository                                      | `60`                                                         |
+| `serverBlock`                              | Custom NGINX server block                                                                    | `nil`                                                        |
+| `existingServerBlockConfigmap`             | Name of existing PVC with custom NGINX server block                                          | `nil`                                                        |
+| `replicaCount`                             | Number of replicas to deploy                                                                 | `1`                                                          |
+| `containerPort`                            | Deployment Container Port                                                                    | `8080`                                                       |
+| `containerTlsPort`                         | Deployment Container Tls Port                                                                | `nil`                                                        |
+| `podAnnotations`                           | Pod annotations                                                                              | `{}`                                                         |
+| `affinity`                                 | Map of node/pod affinities                                                                   | `{}` (The value is evaluated as a template)                  |
+| `nodeSelector`                             | Node labels for pod assignment                                                               | `{}` (The value is evaluated as a template)                  |
+| `tolerations`                              | Tolerations for pod assignment                                                               | `[]` (The value is evaluated as a template)                  |
+| `resources`                                | Resource requests/limit                                                                      | `{}`                                                         |
+| `livenessProbe`                            | Deployment Liveness Probe                                                                    | See `values.yaml`                                            |
+| `readinessProbe`                           | Deployment Readiness Probe                                                                   | See `values.yaml`                                            |
+| `service.type`                             | Kubernetes Service type                                                                      | `LoadBalancer`                                               |
+| `service.port`                             | Service HTTP port                                                                            | `80`                                                         |
+| `service.httpsPort`                        | Service HTTPS port                                                                           | `443`                                                        |
+| `service.nodePorts.http`                   | Kubernetes http node port                                                                    | `""`                                                         |
+| `service.nodePorts.https`                  | Kubernetes https node port                                                                   | `""`                                                         |
+| `service.externalTrafficPolicy`            | Enable client source IP preservation                                                         | `Cluster`                                                    |
+| `service.loadBalancerIP`                   | LoadBalancer service IP address                                                              | `""`                                                         |
+| `service.annotations`                      | Service annotations                                                                          | `{}`                                                         |
+| `ldapDaemon.enabled`                       | Enable LDAP Auth Daemon proxy                                                                | `false`                                                      |
+| `ldapDaemon.image.registry`                | LDAP AUth Daemon Image registry                                                              | `docker.io`                                                  |
+| `ldapDaemon.image.repository`              | LDAP Auth Daemon Image name                                                                  | `bitnami/nginx-ldap-auth-daemon`                             |
+| `ldapDaemon.image.tag`                     | LDAP Auth Daemon Image tag                                                                   | `{TAG_NAME}`                                                 |
+| `ldapDaemon.image.pullPolicy`              | LDAP Auth Daemon Image pull policy                                                           | `IfNotPresent`                                               |
+| `ldapDaemon.port`                          | LDAP Auth Daemon port                                                                        | `8888`                                                       |
+| `ldapDaemon.ldapConfig.uri`                | LDAP Server URI, `ldap[s]:/<hostname>:<port>`                                                | `""`                                                         |
+| `ldapDaemon.ldapConfig.baseDN`             | LDAP root DN to begin the search for the user                                                | `""`                                                         |
+| `ldapDaemon.ldapConfig.bindDN`             | DN of user to bind to LDAP                                                                   | `""`                                                         |
+| `ldapDaemon.ldapConfig.bindPassword`       | Password for the user to bind to LDAP                                                        | `""`                                                         |
+| `ldapDaemon.ldapConfig.filter`             | LDAP search filter for search+bind authentication                                            | `""`                                                         |
+| `ldapDaemon.ldapConfig.httpRealm`          | LDAP HTTP auth realm                                                                         | `""`                                                         |
+| `ldapDaemon.ldapConfig.httpCookieName`     | HTTP cookie name to be used in LDAP Auth                                                     | `""`                                                         |
+| `ldapDaemon.nginxServerBlock`              | NGINX server block that configures LDAP communication. Overrides `ldapDaemon.ldapConfig`     | See `values.yaml`                                            |
+| `ldapDaemon.existingNginxServerBlockSecret`| Name of existing Secret with a NGINX server block to use for LDAP communication              | `nil`                                                        |
+| `ldapDaemon.livenessProbe`                 | LDAP Auth Daemon Liveness Probe                                                              | See `values.yaml`                                            |
+| `ldapDaemon.readinessProbe`                | LDAP Auth Daemon Readiness Probe                                                             | See `values.yaml`                                            |
+| `ingress.enabled`                          | Enable ingress controller resource                                                           | `false`                                                      |
+| `ingress.certManager`                      | Add annotations for cert-manager                                                             | `false`                                                      |
+| `ingress.selectors`                        | Ingress selectors for labelSelector option                                                   | `[]`                                                         |
+| `ingress.annotations`                      | Ingress annotations                                                                          | `[]`                                                         |
+| `ingress.hosts[0].name`                    | Hostname to your NGINX installation                                                          | `nginx.local`                                                |
+| `ingress.hosts[0].path`                    | Path within the url structure                                                                | `/`                                                          |
+| `ingress.tls[0].hosts[0]`                  | TLS hosts                                                                                    | `nginx.local`                                                |
+| `ingress.tls[0].secretName`                | TLS Secret (certificates)                                                                    | `nginx.local-tls`                                            |
+| `ingress.secrets[0].name`                  | TLS Secret Name                                                                              | `nil`                                                        |
+| `ingress.secrets[0].certificate`           | TLS Secret Certificate                                                                       | `nil`                                                        |
+| `ingress.secrets[0].key`                   | TLS Secret Key                                                                               | `nil`                                                        |
+| `healthIngress.enabled`                    | Enable health ingress controller resource                                                    | `false`                                                      |
+| `healthIngress.certManager`                | Add annotations for cert-manager                                                             | `false`                                                      |
+| `healthIngress.selectors`                  | Health Ingress selectors for labelSelector option                                            | `[]`                                                         |
+| `healthIngress.annotations`                | Health Ingress annotations                                                                   | `[]`                                                         |
+| `healthIngress.hosts[0].name`              | Hostname to your NGINX installation                                                          | `nginx.local`                                                |
+| `healthIngress.hosts[0].path`              | Path within the url structure                                                                | `/`                                                          |
+| `healthIngress.tls[0].hosts[0]`            | TLS hosts                                                                                    | `nginx.local`                                                |
+| `healthIngress.tls[0].secretName`          | TLS Secret (certificates)                                                                    | `nginx.local-tls`                                            |
+| `healthIngress.secrets[0].name`            | TLS Secret Name                                                                              | `nil`                                                        |
+| `healthIngress.secrets[0].certificate`     | TLS Secret Certificate                                                                       | `nil`                                                        |
+| `healthIngress.secrets[0].key`             | TLS Secret Key                                                                               | `nil`                                                        |
+| `metrics.enabled`                          | Start a side-car prometheus exporter                                                         | `false`                                                      |
+| `metrics.image.registry`                   | NGINX Prometheus exporter image registry                                                     | `docker.io`                                                  |
+| `metrics.image.repository`                 | NGINX Prometheus exporter image name                                                         | `bitnami/nginx-exporter`                                     |
+| `metrics.image.tag`                        | NGINX Prometheus exporter image tag                                                          | `{TAG_NAME}`                                                 |
+| `metrics.image.pullPolicy`                 | NGINX Prometheus exporter image pull policy                                                  | `IfNotPresent`                                               |
+| `metrics.image.pullSecrets`                | Specify docker-registry secret names as an array                                             | `[]` (does not add image pull secrets to deployed pods)      |
+| `metrics.podAnnotations`                   | Additional annotations for NGINX Prometheus exporter pod(s)                                  | `{prometheus.io/scrape: "true", prometheus.io/port: "9113"}` |
+| `metrics.resources`                        | NGINX Prometheus exporter resource requests/limit                                            | `{}`                                                         |
+| `metrics.serviceMonitor.enabled`           | Creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`)  | `false`                                                      |
+| `metrics.serviceMonitor.namespace`         | Namespace in which Prometheus is running                                                     | `nil`                                                        |
+| `metrics.serviceMonitor.interval`          | Interval at which metrics should be scraped.                                                 | `nil` (Prometheus Operator default value)                    |
+| `metrics.serviceMonitor.scrapeTimeout`     | Timeout after which the scrape is ended                                                      | `nil` (Prometheus Operator default value)                    |
+| `metrics.serviceMonitor.selector`          | Prometheus instance selector labels                                                          | `nil`                                                        |
+| `autoscaling.enabled`                      | Enable autoscaling for NGINX deployment                                                      | `false`                                                      |
+| `autoscaling.minReplicas`                  | Minimum number of replicas to scale back                                                     | `nil`                                                        |
+| `autoscaling.maxReplicas`                  | Maximum number of replicas to scale out                                                      | `nil`                                                        |
+| `autoscaling.targetCPU`                    | Target CPU utilization percentage                                                            | `nil`                                                        |
+| `autoscaling.targetMemory`                 | Target Memory utilization percentage                                                         | `nil`                                                        |
+| `extraVolumes`                             | Array to add extra volumes (evaluated as a template)                                         | `[]`                                                         |
+| `extraVolumeMounts`                        | Array to add extra mounts (normally used with extraVolumes, evaluated as a template)         | `[]`                                                         |
+
+Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
+
+```bash
+$ helm install my-release \
+  --set imagePullPolicy=Always \
+    bitnami/nginx
+```
+
+The above command sets the `imagePullPolicy` to `Always`.
+
+Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
+
+```bash
+$ helm install my-release -f values.yaml bitnami/nginx
+```
+
+> **Tip**: You can use the default [values.yaml](values.yaml)
+
+## Configuration and installation details
+
+### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/)
+
+It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image.
+
+Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist.
+
+### Change NGINX version
+
+To modify the NGINX version used in this chart you can specify a [valid image tag](https://hub.docker.com/r/bitnami/nginx/tags/) using the `image.tag` parameter. For example, `image.tag=X.Y.Z`. This approach is also applicable to other images like exporters.
+
+### Deploying your custom web application
+
+The NGINX chart allows you to deploy a custom web application using one of the following methods:
+
+- Cloning from a git repository: Set `cloneStaticSiteFromGit.enabled` to `true` and set the repository and branch using the `cloneStaticSiteFromGit.repository` and  `cloneStaticSiteFromGit.branch` parameters. A sidecar will also pull the latest changes in an interval set by `cloneStaticSitesFromGit.interval`.
+- Providing a ConfigMap: Set the `staticSiteConfigMap` value to mount a ConfigMap in the NGINX html folder.
+- Using an existing PVC: Set the `staticSitePVC` value to mount an PersistentVolumeClaim with the static site content.
+
+You can deploy a example web application using git deploying the chart with the following parameters:
+
+```console
+cloneStaticSiteFromGit.enabled=true
+cloneStaticSiteFromGit.repository=https://github.com/mdn/beginner-html-site-styled.git
+cloneStaticSiteFromGit.branch=master
+```
+
+### Providing a custom server block
+
+This helm chart supports using custom custom server block for NGINX to use.
+
+You can use the `serverBlock` value to provide a custom server block for NGINX to use. To do this, create a values files with your server block and install the chart using it:
+
+```yaml
+serverBlock: |-
+  server {
+    listen 0.0.0.0:8080;
+    location / {
+      return 200 "hello!";
+    }
+  }
+```
+
+> Warning: The above example is not compatible with enabling Prometheus metrics since it affects the `/status` endpoint.
+
+In addition, you can also set an external ConfigMap with the configuration file. This is done by setting the `existingServerBlockConfigmap` parameter. Note that this will override the previous option.
+
+### Enabling LDAP
+
+In some scenarios, you may require users to authenticate in order to gain access to protected resources. By enabling LDAP, NGINX will make use of an Authorization Daemon to proxy those identification requests against a given LDAP Server.
+
+In order to enable LDAP authentication you can set the `ldapDaemon.enabled` property and follow these steps:
+
+1. Use the `ldapDaemon.nginxServerBlock` property to provide with an additional server block that will make NGINX such a proxy (see `values.yaml`). Alternatively, you can provide this configuration using an external Secret and the property `ldapDaemon.existingNginxServerBlockSecret`.
+
+2. Complete the aforementioned server block by specifying your LDAP Server connection details (see `values.yaml`). Alternatively, you can declare them using the property `ldapDaemon.ldapConfig`.
+
+## Upgrading
+
+### 5.6.0
+Added support for the use of LDAP.
+
+### 5.0.0
+
+Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments.
+Use the workaround below to upgrade from versions previous to 5.0.0. The following example assumes that the release name is nginx:
+
+```console
+$ kubectl delete deployment nginx --cascade=false
+$ helm upgrade nginx bitnami/nginx
+```
+
+### To 1.0.0
+
+Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments.
+Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is nginx:
+
+```console
+$ kubectl patch deployment nginx --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]'
+```
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/ct-values.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/ct-values.yaml
new file mode 100644
index 0000000000..b738e2a57a
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/ct-values.yaml
@@ -0,0 +1,2 @@
+service:
+  type: ClusterIP
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/values-with-ingress-metrics-and-serverblock.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/values-with-ingress-metrics-and-serverblock.yaml
new file mode 100644
index 0000000000..0b0a06fb4a
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/ci/values-with-ingress-metrics-and-serverblock.yaml
@@ -0,0 +1,26 @@
+# Test values file for generating all of the yaml and check that
+# the rendering is correct
+
+serverBlock: |-
+  server {
+   listen 0.0.0.0:8080;
+   root /app;
+   location / {
+     index index.html index.php;
+   }
+   location ~ \.php$ {
+     fastcgi_pass phpfpm-server:9000;
+     fastcgi_index index.php;
+     include fastcgi.conf;
+   }
+  }
+
+ingress:
+  enabled: true
+  tls: []
+
+metrics:
+  enabled: true
+  ## Kubeval doesn't recognise ServiceMonitor as a valid K8s object
+  # serviceMonitor:
+  #   enabled: true
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/NOTES.txt b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/NOTES.txt
new file mode 100644
index 0000000000..f411914134
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/NOTES.txt
@@ -0,0 +1,39 @@
+Get the NGINX URL:
+
+{{- if .Values.ingress.enabled }}
+
+  You should be able to access your new NGINX installation through:
+
+  {{- if .Values.ingress.hostname }}
+      - http://{{ .Values.ingress.hostname }}
+  {{- end }}
+  {{- range $host := .Values.ingress.hosts }}
+    {{- range .paths }}
+      - http://{{ $host.name }}{{ . }}
+    {{- end }}
+  {{- end }}
+
+{{- else if contains "LoadBalancer" .Values.service.type }}
+{{- $port:=.Values.service.port | toString }}
+
+  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+        Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "nginx.fullname" . }}'
+
+  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+  echo "NGINX URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.service.port }}{{ end }}/"
+
+{{- else if contains "ClusterIP"  .Values.service.type }}
+
+  echo "NGINX URL: http://127.0.0.1:8080/"
+  kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "nginx.fullname" . }} 8080:{{ .Values.service.port }}
+
+{{- else if contains "NodePort" .Values.service.type }}
+
+  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "nginx.fullname" . }})
+  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+  echo "NGINX URL: http://$NODE_IP:$NODE_PORT/"
+
+{{- end }}
+
+{{- include "nginx.validateValues" . }}
+{{- include "nginx.checkRollingTags" . }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/_helpers.tpl b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/_helpers.tpl
new file mode 100644
index 0000000000..55ef55bd71
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/_helpers.tpl
@@ -0,0 +1,292 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "nginx.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+*/}}
+{{- define "nginx.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "nginx.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "nginx.labels" -}}
+app.kubernetes.io/name: {{ include "nginx.name" . }}
+helm.sh/chart: {{ include "nginx.chart" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
+
+{{/*
+Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector
+*/}}
+{{- define "nginx.matchLabels" -}}
+app.kubernetes.io/name: {{ include "nginx.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Return the proper NGINX image name
+*/}}
+{{- define "nginx.image" -}}
+{{- $registryName := .Values.image.registry -}}
+{{- $repositoryName := .Values.image.repository -}}
+{{- $tag := .Values.image.tag | toString -}}
+{{/*
+Helm 2.11 supports the assignment of a value to a variable defined in a different scope,
+but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic.
+Also, we can't use a single if because lazy evaluation is not an option
+*/}}
+{{- if .Values.global }}
+    {{- if .Values.global.imageRegistry }}
+        {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}}
+    {{- else -}}
+        {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+    {{- end -}}
+{{- else -}}
+    {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the proper Git image name
+*/}}
+{{- define "cloneStaticSiteFromGit.image" -}}
+{{- $registryName := .Values.cloneStaticSiteFromGit.image.registry -}}
+{{- $repositoryName := .Values.cloneStaticSiteFromGit.image.repository -}}
+{{- $tag := .Values.cloneStaticSiteFromGit.image.tag | toString -}}
+{{/*
+Helm 2.11 supports the assignment of a value to a variable defined in a different scope,
+but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic.
+Also, we can't use a single if because lazy evaluation is not an option
+*/}}
+{{- if .Values.global }}
+    {{- if .Values.global.imageRegistry }}
+        {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}}
+    {{- else -}}
+        {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+    {{- end -}}
+{{- else -}}
+    {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the proper image name (for the LDAP Auth Daemon image)
+*/}}
+{{- define "nginx.ldapDaemon.image" -}}
+{{- $registryName := .Values.ldapDaemon.image.registry -}}
+{{- $repositoryName := .Values.ldapDaemon.image.repository -}}
+{{- $tag := .Values.ldapDaemon.image.tag | toString -}}
+{{/*
+Helm 2.11 supports the assignment of a value to a variable defined in a different scope,
+but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic.
+Also, we can't use a single if because lazy evaluation is not an option
+*/}}
+{{- if .Values.global }}
+    {{- if .Values.global.imageRegistry }}
+        {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}}
+    {{- else -}}
+        {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+    {{- end -}}
+{{- else -}}
+    {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the proper image name (for the metrics image)
+*/}}
+{{- define "nginx.metrics.image" -}}
+{{- $registryName := .Values.metrics.image.registry -}}
+{{- $repositoryName := .Values.metrics.image.repository -}}
+{{- $tag := .Values.metrics.image.tag | toString -}}
+{{/*
+Helm 2.11 supports the assignment of a value to a variable defined in a different scope,
+but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic.
+Also, we can't use a single if because lazy evaluation is not an option
+*/}}
+{{- if .Values.global }}
+    {{- if .Values.global.imageRegistry }}
+        {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}}
+    {{- else -}}
+        {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+    {{- end -}}
+{{- else -}}
+    {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the proper Docker Image Registry Secret Names
+*/}}
+{{- define "nginx.imagePullSecrets" -}}
+{{/*
+Helm 2.11 supports the assignment of a value to a variable defined in a different scope,
+but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic.
+Also, we can not use a single if because lazy evaluation is not an option
+*/}}
+{{- if .Values.global }}
+{{- if .Values.global.imagePullSecrets }}
+imagePullSecrets:
+{{- range .Values.global.imagePullSecrets }}
+  - name: {{ . }}
+{{- end }}
+{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.cloneStaticSiteFromGit.image.pullSecrets }}
+imagePullSecrets:
+{{- range .Values.image.pullSecrets }}
+  - name: {{ . }}
+{{- end }}
+{{- range .Values.cloneStaticSiteFromGit.image.pullSecrets }}
+  - name: {{ . }}
+{{- end }}
+{{- range .Values.metrics.image.pullSecrets }}
+  - name: {{ . }}
+{{- end }}
+{{- end -}}
+{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.cloneStaticSiteFromGit.image.pullSecrets }}
+imagePullSecrets:
+{{- range .Values.image.pullSecrets }}
+  - name: {{ . }}
+{{- end }}
+{{- range .Values.cloneStaticSiteFromGit.image.pullSecrets }}
+  - name: {{ . }}
+{{- end }}
+{{- range .Values.metrics.image.pullSecrets }}
+  - name: {{ . }}
+{{- end }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Check if there are rolling tags in the images
+*/}}
+{{- define "nginx.checkRollingTags" -}}
+{{- if and (contains "bitnami/" .Values.image.repository) (not (.Values.image.tag | toString | regexFind "-r\\d+$|sha256:")) }}
+WARNING: Rolling tag detected ({{ .Values.image.repository }}:{{ .Values.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment.
++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/
+{{- end }}
+{{- if and (contains "bitnami/" .Values.cloneStaticSiteFromGit.image.repository) (not (.Values.cloneStaticSiteFromGit.image.tag | toString | regexFind "-r\\d+$|sha256:")) }}
+WARNING: Rolling tag detected ({{ .Values.cloneStaticSiteFromGit.image.repository }}:{{ .Values.cloneStaticSiteFromGit.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment.
++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/
+{{- end }}
+{{- if and (contains "bitnami/" .Values.metrics.image.repository) (not (.Values.metrics.image.tag | toString | regexFind "-r\\d+$|sha256:")) }}
+WARNING: Rolling tag detected ({{ .Values.metrics.image.repository }}:{{ .Values.metrics.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment.
++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/
+{{- end }}
+{{- end -}}
+
+{{/*
+Return true if a static site should be mounted in the NGINX container
+*/}}
+{{- define "nginx.useStaticSite" -}}
+{{- if or .Values.cloneStaticSiteFromGit.enabled .Values.staticSiteConfigmap .Values.staticSitePVC }}
+    {- true -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the volume to use to mount the static site in the NGINX container
+*/}}
+{{- define "nginx.staticSiteVolume" -}}
+{{- if .Values.cloneStaticSiteFromGit.enabled }}
+emptyDir: {}
+{{- else if .Values.staticSiteConfigmap }}
+configMap:
+  name: {{ .Values.staticSiteConfigmap }}
+{{- else if .Values.staticSitePVC }}
+persistentVolumeClaim:
+  claimName: {{ .Values.staticSitePVC }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Return the custom NGINX server block configmap.
+*/}}
+{{- define "nginx.serverBlockConfigmapName" -}}
+{{- if .Values.existingServerBlockConfigmap -}}
+    {{- printf "%s" (tpl .Values.existingServerBlockConfigmap $) -}}
+{{- else -}}
+    {{- printf "%s-server-block" (include "nginx.fullname" .) -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Return the custom NGINX server block secret for LDAP.
+*/}}
+{{- define "ldap.nginxServerBlockSecret" -}}
+{{- if .Values.ldapDaemon.existingNginxServerBlockSecret -}}
+    {{- printf "%s" (tpl .Values.ldapDaemon.existingNginxServerBlockSecret $) -}}
+{{- else -}}
+    {{- printf "%s-ldap-daemon" (include "nginx.fullname" .) -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Renders a value that contains template.
+Usage:
+{{ include "nginx.tplValue" (dict "value" .Values.path.to.the.Value "context" $) }}
+*/}}
+{{- define "nginx.tplValue" -}}
+    {{- if typeIs "string" .value }}
+        {{- tpl .value .context }}
+    {{- else }}
+        {{- tpl (.value | toYaml) .context }}
+    {{- end }}
+{{- end -}}
+
+{{/*
+Compile all warnings into a single message, and call fail.
+*/}}
+{{- define "nginx.validateValues" -}}
+{{- $messages := list -}}
+{{- $messages := append $messages (include "nginx.validateValues.cloneStaticSiteFromGit" .) -}}
+{{- $messages := append $messages (include "nginx.validateValues.extraVolumes" .) -}}
+{{- $messages := without $messages "" -}}
+{{- $message := join "\n" $messages -}}
+
+{{- if $message -}}
+{{-   printf "\nVALUES VALIDATION:\n%s" $message | fail -}}
+{{- end -}}
+{{- end -}}
+
+{{/* Validate values of NGINX - Clone StaticSite from Git configuration */}}
+{{- define "nginx.validateValues.cloneStaticSiteFromGit" -}}
+{{- if and .Values.cloneStaticSiteFromGit.enabled (or (not .Values.cloneStaticSiteFromGit.repository) (not .Values.cloneStaticSiteFromGit.branch)) -}}
+nginx: cloneStaticSiteFromGit
+    When enabling cloing a static site from a Git repository, both the Git repository and the Git branch must be provided.
+    Please provide them by setting the `cloneStaticSiteFromGit.repository` and `cloneStaticSiteFromGit.branch` parameters.
+{{- end -}}
+{{- end -}}
+
+{{/* Validate values of NGINX - Incorrect extra volume settings */}}
+{{- define "nginx.validateValues.extraVolumes" -}}
+{{- if and (.Values.extraVolumes) (not .Values.extraVolumeMounts) -}}
+nginx: missing-extra-volume-mounts
+    You specified extra volumes but not mount points for them. Please set
+    the extraVolumeMounts value
+{{- end -}}
+{{- end -}}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/deployment.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/deployment.yaml
new file mode 100644
index 0000000000..9a4f989435
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/deployment.yaml
@@ -0,0 +1,192 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ template "nginx.fullname" . }}
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+spec:
+  selector:
+    matchLabels: {{- include "nginx.matchLabels" . | nindent 6 }}
+  replicas: {{ .Values.replicaCount }}
+  template:
+    metadata:
+      labels: {{- include "nginx.labels" . | nindent 8 }}
+      {{- if or .Values.podAnnotations (and .Values.metrics.enabled .Values.metrics.podAnnotations) (and .Values.serverBlock (not .Values.existingServerBlockConfigmap)) }}
+      annotations:
+        {{- if .Values.podAnnotations }}
+        {{- include "nginx.tplValue" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }}
+        {{- end }}
+        {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }}
+        {{- include "nginx.tplValue" ( dict "value" .Values.metrics.podAnnotations "context" $) | nindent 8 }}
+        {{- end }}
+        {{- if and .Values.serverBlock (not .Values.existingServerBlockConfigmap) }}
+        checksum/server-block-configuration: {{ include (print $.Template.BasePath "/server-block-configmap.yaml") . | sha256sum }}
+        {{- end }}
+      {{- end }}
+    spec:
+{{- include "nginx.imagePullSecrets" . | indent 6 }}
+      {{- if .Values.affinity }}
+      affinity: {{- include "nginx.tplValue" (dict "value" .Values.affinity "context" $) | nindent 8 }}
+      {{- end }}
+      {{- if .Values.nodeSelector }}
+      nodeSelector: {{- include "nginx.tplValue" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }}
+      {{- end }}
+      {{- if .Values.tolerations }}
+      tolerations: {{- include "nginx.tplValue" (dict "value" .Values.tolerations "context" $) | nindent 8 }}
+      {{- end }}
+      {{- if .Values.cloneStaticSiteFromGit.enabled }}
+      initContainers:
+        - name: git-clone-repository
+          image: {{ include "cloneStaticSiteFromGit.image" . }}
+          imagePullPolicy: {{ .Values.cloneStaticSiteFromGit.image.pullPolicy | quote }}
+          command:
+            - /bin/bash
+            - -ec
+            - |
+              git clone {{ .Values.cloneStaticSiteFromGit.repository }} --branch {{ .Values.cloneStaticSiteFromGit.branch }} /app
+          volumeMounts:
+            - name: staticsite
+              mountPath: /app
+      containers:
+        - name: git-repo-syncer
+          image: {{ include "cloneStaticSiteFromGit.image" . }}
+          imagePullPolicy: {{ .Values.cloneStaticSiteFromGit.image.pullPolicy | quote }}
+          command:
+            - /bin/bash
+            - -ec
+            - |
+              while true; do
+                  cd /app && git pull origin {{ .Values.cloneStaticSiteFromGit.branch }}
+                  sleep {{ .Values.cloneStaticSiteFromGit.interval }}
+              done
+          volumeMounts:
+            - name: staticsite
+              mountPath: /app
+      {{- else }}
+      containers:
+      {{- end }}
+        - name: nginx
+          image: {{ template "nginx.image" . }}
+          imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
+          ports:
+            - name: http
+              containerPort: {{ .Values.containerPort }}
+            {{ if .Values.containerTlsPort }}
+            - name: https
+              containerPort: {{ .Values.containerTlsPort }}
+            {{ end }}
+          {{- if .Values.livenessProbe }}
+          livenessProbe: {{- toYaml .Values.livenessProbe | nindent 12 }}
+          {{- end }}
+          {{- if .Values.readinessProbe }}
+          readinessProbe: {{- toYaml .Values.readinessProbe | nindent 12 }}
+          {{- end }}
+          {{- if .Values.resources }}
+          resources: {{- toYaml .Values.resources | nindent 12 }}
+          {{- end }}
+          volumeMounts:
+            - name: nginx-server-block-paths
+              mountPath: /opt/bitnami/nginx/conf/server_blocks
+            {{- if or .Values.serverBlock .Values.existingServerBlockConfigmap }}
+            - name: nginx-server-block
+              mountPath: /opt/bitnami/nginx/conf/server_blocks/common
+            {{- end }}
+            {{- if .Values.ldapDaemon.enabled }}
+            - name: nginx-server-block-ldap
+              mountPath: /opt/bitnami/nginx/conf/server_blocks/ldap
+            {{- end }}
+            {{- if (include "nginx.useStaticSite" .) }}
+            - name: staticsite
+              mountPath: /app
+            {{- end }}
+            {{- if .Values.extraVolumeMounts }}
+            {{- include "nginx.tplValue" ( dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }}
+            {{- end }}
+        {{- if .Values.ldapDaemon.enabled }}
+        - name: ldap-daemon
+          image: {{ template "nginx.ldapDaemon.image" . }}
+          imagePullPolicy: {{ .Values.ldapDaemon.image.pullPolicy | quote }}
+          ports:
+            - name: ldap-daemon
+              containerPort: {{ .Values.ldapDaemon.port }}
+        {{- if .Values.ldapDaemon.livenessProbe }}
+          livenessProbe: {{- toYaml .Values.ldapDaemon.livenessProbe | nindent 12 }}
+        {{- end }}
+        {{- if .Values.ldapDaemon.readinessProbe }}
+          readinessProbe: {{- toYaml .Values.ldapDaemon.readinessProbe | nindent 12 }}
+        {{- end }}
+          env:
+            - name: NGINXLDAP_PORT_NUMBER
+              value: {{ .Values.ldapDaemon.port | quote}}
+            - name: NGINXLDAP_LDAP_URI
+              value: {{ .Values.ldapDaemon.ldapConfig.uri | quote }}
+            - name: NGINXLDAP_LDAP_BASE_DN
+              value: {{ .Values.ldapDaemon.ldapConfig.baseDN | quote }}
+            - name: NGINXLDAP_LDAP_BIND_DN
+              value: {{ .Values.ldapDaemon.ldapConfig.bindDN | quote }}
+            - name: NGINXLDAP_LDAP_BIND_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ template "nginx.fullname" . }}-ldap-daemon
+                  key: ldap-daemon-ldap-bind-password
+            - name: NGINXLDAP_LDAP_FILTER
+              value: {{ .Values.ldapDaemon.ldapConfig.filter | quote }}
+            - name: NGINXLDAP_HTTP_REALM
+              value: {{ .Values.ldapDaemon.ldapConfig.httpRealm | quote }}
+            - name: NGINXLDAP_HTTP_COOKIE_NAME
+              value: {{ .Values.ldapDaemon.ldapConfig.httpCookieName | quote }}
+        {{- end }}
+        {{- if .Values.metrics.enabled }}
+        - name: metrics
+          image: {{ template "nginx.metrics.image" . }}
+          imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }}
+          command: ['/usr/bin/exporter', '-nginx.scrape-uri', 'http://127.0.0.1:8080/status']
+          ports:
+            - name: metrics
+              containerPort: 9113
+          livenessProbe:
+            httpGet:
+              path: /metrics
+              port: metrics
+            initialDelaySeconds: 15
+            timeoutSeconds: 5
+          readinessProbe:
+            httpGet:
+              path: /metrics
+              port: metrics
+            initialDelaySeconds: 5
+            timeoutSeconds: 1
+          {{- if .Values.metrics.resources }}
+          resources: {{- toYaml .Values.metrics.resources | nindent 12 }}
+          {{- end }}
+        {{- end }}
+      volumes:
+        - name: nginx-server-block-paths
+          configMap:
+            name: {{ template "nginx.fullname" . }}-server-block
+            items:
+              - key: server-blocks-paths.conf
+                path: server-blocks-paths.conf
+      {{- if or .Values.serverBlock .Values.existingServerBlockConfigmap .Values.extraVolumes (include "nginx.useStaticSite" .) }}
+        {{- if or .Values.serverBlock .Values.existingServerBlockConfigmap }}
+        - name: nginx-server-block
+          configMap:
+            name: {{ include "nginx.serverBlockConfigmapName" . }}
+            {{- if or .Values.serverBlock }}
+            items:
+              - key: server-block.conf
+                path: server-block.conf
+            {{- end }}
+        {{- end }}
+        {{- if (include "nginx.useStaticSite" .) }}
+        - name: staticsite
+          {{- include "nginx.staticSiteVolume" . | nindent 10 }}
+        {{- end }}
+      {{- if .Values.extraVolumes }}
+      {{- include "nginx.tplValue" ( dict "value" .Values.extraVolumes "context" $) | nindent 8 }}
+      {{- end }}
+      {{- end }}
+      {{- if .Values.ldapDaemon.enabled }}
+        - name: nginx-server-block-ldap
+          secret:
+            secretName: {{ include "ldap.nginxServerBlockSecret" . }}
+      {{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/health-ingress.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/health-ingress.yaml
new file mode 100644
index 0000000000..a6362a0775
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/health-ingress.yaml
@@ -0,0 +1,37 @@
+{{- if .Values.healthIngress.enabled }}
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  name: {{ include "nginx.fullname" . }}-health
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+  annotations:
+    {{- if .Values.healthIngress.certManager }}
+    kubernetes.io/tls-acme: "true"
+    {{- end }}
+    {{- range $key, $value := .Values.healthIngress.annotations }}
+    {{ $key }}: {{ $value | quote }}
+    {{- end }}
+spec:
+  rules:
+    {{- if .Values.healthIngress.hostname }}
+    - host: {{ .Values.healthIngress.hostname }}
+      http:
+        paths:
+          - path: /
+            backend:
+              serviceName: "{{ template "nginx.fullname" $ }}"
+              servicePort: http
+    {{- end }}
+    {{- range .Values.healthIngress.hosts }}
+    - host: {{ .name }}
+      http:
+        paths:
+          - path: {{ default "/" .path }}
+            backend:
+              serviceName: "{{ template "nginx.fullname" $ }}"
+              servicePort: http
+    {{- end }}
+  {{- if .Values.healthIngress.tls }}
+  tls: {{- toYaml .Values.healthIngress.tls | nindent 4 }}
+  {{- end }}
+{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/hpa.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/hpa.yaml
new file mode 100644
index 0000000000..549eccc529
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/hpa.yaml
@@ -0,0 +1,27 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+  name: {{ template "nginx.fullname" . }}
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+spec:
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: {{ template "nginx.fullname" . }}
+  minReplicas: {{ .Values.autoscaling.minReplicas }}
+  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+  metrics:
+    {{- if .Values.autoscaling.targetCPU }}
+    - type: Resource
+      resource:
+        name: cpu
+        targetAverageUtilization: {{ .Values.autoscaling.targetCPU }}
+    {{- end }}
+    {{- if .Values.autoscaling.targetMemory }}
+    - type: Resource
+      resource:
+        name: memory
+        targetAverageUtilization: {{ .Values.autoscaling.targetMemory  }}
+    {{- end }}
+{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ingress.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ingress.yaml
new file mode 100644
index 0000000000..796935864a
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ingress.yaml
@@ -0,0 +1,37 @@
+{{- if .Values.ingress.enabled }}
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  name: {{ include "nginx.fullname" . }}
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+  annotations:
+    {{- if .Values.ingress.certManager }}
+    kubernetes.io/tls-acme: "true"
+    {{- end }}
+    {{- range $key, $value := .Values.ingress.annotations }}
+    {{ $key }}: {{ $value | quote }}
+    {{- end }}
+spec:
+  rules:
+    {{- if .Values.ingress.hostname }}
+    - host: {{ .Values.ingress.hostname }}
+      http:
+        paths:
+          - path: /
+            backend:
+              serviceName: "{{ template "nginx.fullname" $ }}"
+              servicePort: http
+    {{- end }}
+    {{- range .Values.ingress.hosts }}
+    - host: {{ .name }}
+      http:
+        paths:
+          - path: {{ default "/" .path }}
+            backend:
+              serviceName: "{{ template "nginx.fullname" $ }}"
+              servicePort: http
+    {{- end }}
+  {{- if .Values.ingress.tls }}
+  tls: {{- toYaml .Values.ingress.tls | nindent 4 }}
+  {{- end }}
+{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ldap-daemon-secrets.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ldap-daemon-secrets.yaml
new file mode 100644
index 0000000000..b1b4c76e2d
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/ldap-daemon-secrets.yaml
@@ -0,0 +1,14 @@
+{{- if and .Values.ldapDaemon.enabled }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ template "nginx.fullname" . }}-ldap-daemon
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+type: Opaque
+data:
+  ldap-daemon-ldap-bind-password: {{ .Values.ldapDaemon.ldapConfig.bindPassword | b64enc | quote}}
+{{- if (not .Values.ldapDaemon.existingNginxServerBlockSecret) }}
+  ldap_nginx.conf: |-
+{{ tpl .Values.ldapDaemon.nginxServerBlock . | b64enc | indent 4 }}
+{{- end }}
+{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/server-block-configmap.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/server-block-configmap.yaml
new file mode 100644
index 0000000000..db378b1d40
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/server-block-configmap.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ template "nginx.fullname" . }}-server-block
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+data:
+  server-blocks-paths.conf: |-
+    include  "/opt/bitnami/nginx/conf/server_blocks/ldap/*.conf";
+    include  "/opt/bitnami/nginx/conf/server_blocks/common/*.conf";
+{{- if and .Values.serverBlock (not .Values.existingServerBlockConfigmap) }}
+  server-block.conf: |-
+{{ .Values.serverBlock | indent 4 }}
+{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/servicemonitor.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/servicemonitor.yaml
new file mode 100644
index 0000000000..4b2b5d2275
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/servicemonitor.yaml
@@ -0,0 +1,28 @@
+{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  name: {{ template "nginx.fullname" . }}
+  {{- if .Values.metrics.serviceMonitor.namespace }}
+  namespace: {{ .Values.metrics.serviceMonitor.namespace }}
+  {{- end }}
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+    {{- range $key, $value := .Values.metrics.serviceMonitor.selector }}
+    {{ $key }}: {{ $value | quote }}
+    {{- end }}
+spec:
+  selector:
+    matchLabels: {{ include "nginx.matchLabels" . | nindent 6 }}
+  endpoints:
+    - port: metrics
+      path: /metrics
+      {{- if .Values.metrics.serviceMonitor.interval }}
+      interval: {{ .Values.metrics.serviceMonitor.interval }}
+      {{- end }}
+      {{- if .Values.metrics.serviceMonitor.scrapeTimeout }}
+      scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
+      {{- end }}
+  namespaceSelector:
+    matchNames:
+      - {{ .Release.Namespace }}
+{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/svc.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/svc.yaml
new file mode 100644
index 0000000000..fc40fc3cdb
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/svc.yaml
@@ -0,0 +1,41 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "nginx.fullname" . }}
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+  {{- if or .Values.service.annotations (and .Values.metrics.enabled .Values.metrics.service.annotations) }}
+  annotations:
+    {{- if .Values.service.annotations }}
+    {{- include "nginx.tplValue" ( dict "value" .Values.service.annotations "context" $) | nindent 4 }}
+    {{- end }}
+    {{- if and .Values.metrics.enabled .Values.metrics.service.annotations }}
+    {{- include "nginx.tplValue" ( dict "value" .Values.metrics.service.annotations "context" $) | nindent 4 }}
+    {{- end }}
+  {{- end }}
+spec:
+  type: {{ .Values.service.type }}
+  {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }}
+  externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }}
+  {{- end }}
+  {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }}
+  loadBalancerIP: {{ .Values.service.loadBalancerIP }}
+  {{- end }}
+  ports:
+    - name: http
+      port: {{ .Values.service.port }}
+      targetPort: http
+      {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.http)) }}
+      nodePort: {{ .Values.service.nodePorts.http }}
+      {{- end }}
+    - name: https
+      port: {{ .Values.service.httpsPort }}
+      targetPort: https
+      {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.https)) }}
+      nodePort: {{ .Values.service.nodePorts.https }}
+      {{- end }}
+    {{- if .Values.metrics.enabled }}
+    - name: metrics
+      port: {{ .Values.metrics.service.port }}
+      targetPort: metrics
+    {{- end }}
+  selector: {{- include "nginx.matchLabels" . | nindent 4 }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/tls-secrets.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/tls-secrets.yaml
new file mode 100644
index 0000000000..604ef95e7d
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/templates/tls-secrets.yaml
@@ -0,0 +1,14 @@
+{{- if .Values.ingress.enabled }}
+{{- range .Values.ingress.secrets }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ template "nginx.fullname" . }}
+  labels: {{- include "nginx.labels" . | nindent 4 }}
+type: kubernetes.io/tls
+data:
+  tls.crt: {{ .certificate | b64enc }}
+  tls.key: {{ .key | b64enc }}
+---
+{{- end }}
+{{- end }}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/values.schema.json b/tests/sdk/nodejs/examples/helm-local/step1/nginx/values.schema.json
new file mode 100644
index 0000000000..66b0d072f4
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/values.schema.json
@@ -0,0 +1,68 @@
+{
+  "$schema": "http://json-schema.org/schema#",
+  "type": "object",
+  "properties": {
+    "ingress": {
+      "type": "object",
+      "form": true,
+      "title": "Ingress details",
+      "properties": {
+        "enabled": {
+          "type": "boolean",
+          "form": true,
+          "title": "Use a custom hostname",
+          "description": "Enable the ingress resource that allows you to access the NGINX installation."
+        },
+        "hostname": {
+          "type": "string",
+          "form": true,
+          "title": "Hostname",
+          "hidden": {
+            "value": false,
+            "path": "ingress/enabled"
+          }
+        }
+      }
+    },
+    "replicaCount": {
+      "type": "integer",
+      "form": true,
+      "title": "Number of replicas",
+      "description": "Number of replicas to deploy"
+    },
+    "serverBlock": {
+      "type": "string",
+      "form": true,
+      "title": "Custom server block",
+      "description": "Custom server block to be added to NGINX configuration"
+    },
+    "metrics": {
+      "type": "object",
+      "form": true,
+      "title": "Prometheus metrics details",
+      "properties": {
+        "enabled": {
+          "type": "boolean",
+          "title": "Create Prometheus metrics exporter",
+          "description": "Create a side-car container to expose Prometheus metrics",
+          "form": true
+        },
+        "serviceMonitor": {
+          "type": "object",
+          "properties": {
+            "enabled": {
+              "type": "boolean",
+              "title": "Create Prometheus Operator ServiceMonitor",
+              "description": "Create a ServiceMonitor to track metrics using Prometheus Operator",
+              "form": true,
+              "hidden": {
+                "value": false,
+                "path": "metrics/enabled"
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/tests/sdk/nodejs/examples/helm-local/step1/nginx/values.yaml b/tests/sdk/nodejs/examples/helm-local/step1/nginx/values.yaml
new file mode 100644
index 0000000000..6a1ca23ef5
--- /dev/null
+++ b/tests/sdk/nodejs/examples/helm-local/step1/nginx/values.yaml
@@ -0,0 +1,510 @@
+## Global Docker image parameters
+## Please, note that this will override the image parameters, including dependencies, configured to use the global value
+## Current available global Docker image parameters: imageRegistry and imagePullSecrets
+##
+# global:
+#   imageRegistry: myRegistryName
+#   imagePullSecrets:
+#     - myRegistryKeySecretName
+
+## Bitnami NGINX image version
+## ref: https://hub.docker.com/r/bitnami/nginx/tags/
+##
+image:
+  registry: docker.io
+  repository: bitnami/nginx
+  tag: 1.19.1-debian-10-r22
+  ## Specify a imagePullPolicy
+  ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
+  ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
+  ##
+  pullPolicy: IfNotPresent
+  ## Optionally specify an array of imagePullSecrets.
+  ## Secrets must be manually created in the namespace.
+  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+  ##
+  # pullSecrets:
+  #   - myRegistryKeySecretName
+
+## String to partially override nginx.fullname template (will maintain the release name)
+##
+# nameOverride:
+
+## String to fully override nginx.fullname template
+##
+# fullnameOverride:
+
+## Name of existing ConfigMap with the server static site content
+##
+# staticSiteConfigmap
+
+## Name of existing PVC with the server static site content
+## NOTE: This will override staticSiteConfigmap
+##
+# staticSitePVC
+
+## Get the server static content from a git repository
+## NOTE: This will override staticSiteConfigmap and staticSitePVC
+##
+cloneStaticSiteFromGit:
+  enabled: false
+  ## Bitnami Git image version
+  ## ref: https://hub.docker.com/r/bitnami/git/tags/
+  ##
+  image:
+    registry: docker.io
+    repository: bitnami/git
+    tag: 2.28.0-debian-10-r5
+    ## Specify a imagePullPolicy
+    ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
+    ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
+    ##
+    pullPolicy: IfNotPresent
+    ## Optionally specify an array of imagePullSecrets.
+    ## Secrets must be manually created in the namespace.
+    ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+    ##
+    # pullSecrets:
+    #   - myRegistryKeySecretName
+  ## Repository to clone static content from
+  ##
+  # repository:
+  ## Branch inside the git repository
+  ##
+  # branch:
+  ## Interval for sidecar container pull from the repository
+  ##
+  interval: 60
+
+## Custom server block to be added to NGINX configuration
+## PHP-FPM example server block:
+## serverBlock: |-
+##   server {
+##     listen 0.0.0.0:8080;
+##     root /app;
+##     location / {
+##       index index.html index.php;
+##     }
+##     location ~ \.php$ {
+##       fastcgi_pass phpfpm-server:9000;
+##       fastcgi_index index.php;
+##       include fastcgi.conf;
+##     }
+##   }
+##
+# serverBlock:
+
+## ConfigMap with custom server block to be added to NGINX configuration
+## NOTE: This will override serverBlock
+##
+# existingServerBlockConfigmap:
+
+## Number of replicas to deploy
+##
+replicaCount: 1
+
+## Deployment Container Port
+##
+containerPort: 8080
+
+## If you would like to serve tls in the cluster set containerTlsPort
+##   This is required for extra serverBlocks that serve https.
+##
+## containerTlsPort: 8443
+
+## Pod annotations
+## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
+##
+podAnnotations: {}
+
+## Affinity for pod assignment
+## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
+##
+affinity: {}
+
+## Node labels for pod assignment. Evaluated as a template.
+## Ref: https://kubernetes.io/docs/user-guide/node-selection/
+##
+nodeSelector: {}
+
+## Tolerations for pod assignment. Evaluated as a template.
+## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
+##
+tolerations: {}
+
+## NGINX containers' resource requests and limits
+## ref: http://kubernetes.io/docs/user-guide/compute-resources/
+##
+resources:
+  # We usually recommend not to specify default resources and to leave this as a conscious
+  # choice for the user. This also increases chances charts run on environments with little
+  # resources, such as Minikube. If you do want to specify resources, uncomment the following
+  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+  limits: {}
+  #   cpu: 100m
+  #   memory: 128Mi
+  requests: {}
+  #   cpu: 100m
+  #   memory: 128Mi
+
+## NGINX containers' liveness and readiness probes
+## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
+##
+livenessProbe:
+  tcpSocket:
+    port: http
+  initialDelaySeconds: 30
+  timeoutSeconds: 5
+  failureThreshold: 6
+readinessProbe:
+  tcpSocket:
+    port: http
+  initialDelaySeconds: 5
+  timeoutSeconds: 3
+  periodSeconds: 5
+
+## NGINX Service properties
+##
+service:
+  ## Service type
+  ##
+  type: LoadBalancer
+
+  ## HTTP Port
+  ##
+  port: 80
+
+  ## HTTPS Port
+  ##
+  httpsPort: 443
+
+  ## Specify the nodePort(s) value(s) for the LoadBalancer and NodePort service types.
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
+  ##
+  nodePorts:
+    http: ""
+    https: ""
+
+  ## Set the LoadBalancer service type to internal only.
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer
+  ##
+  # loadBalancerIP:
+
+  ## Provide any additional annotations which may be required. This can be used to
+  ## set the LoadBalancer service type to internal only.
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer
+  ##
+  annotations: {}
+
+  ## Enable client source IP preservation
+  ## ref http://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
+  ##
+  externalTrafficPolicy: Cluster
+
+
+## LDAP Auth Daemon Properties
+##
+## Daemon that will proxy LDAP requests
+## between NGINX and a given LDAP Server
+##
+ldapDaemon:
+
+  enabled: false
+
+  ## Bitnami NGINX LDAP Auth Daemon image
+  ## ref: https://hub.docker.com/r/bitnami/nginx-ldap-auth-daemon/tags/
+  ##
+  image:
+    registry: docker.io
+    repository: bitnami/nginx-ldap-auth-daemon
+    tag: 0.20200116.0-debian-10-r82
+    pullPolicy: IfNotPresent
+
+  ## LDAP Daemon port
+  ##
+  port: 8888
+
+  ## LDAP Auth Daemon Configuration
+  ##
+  ## These different properties define the form of requests performed
+  ## against the given LDAP server
+  ##
+  ## BEWARE THAT THESE VALUES WILL BE IGNORED IF A CUSTOM LDAP SERVER BLOCK
+  ## ALREADY SPECIFIES THEM.
+  ##
+  ##
+  ldapConfig:
+
+    ## LDAP URI where to query the server
+    ## Must follow the pattern -> ldap[s]:/<hostname>:<port>
+    uri: ""
+
+    ## LDAP search base DN
+    baseDN: ""
+
+    ## LDAP bind DN
+    bindDN: ""
+
+    ## LDAP bind Password
+    bindPassword: ""
+
+    ## LDAP search filter
+    filter: ""
+
+    ## LDAP auth realm
+    httpRealm: ""
+
+    ## LDAP cookie name
+    httpCookieName: ""
+
+  ## NGINX Configuration File containing the directives (that define
+  ## how LDAP requests are performed) and tells NGINX to use the LDAP Daemon
+  ## as proxy. Besides, it defines the routes that will require of LDAP auth
+  ## in order to be accessed.
+  ##
+  ## If LDAP directives are provided, they will take precedence over
+  ## the ones specified in ldapConfig.
+  ##
+  ## This will be evaluated as a template.
+  ##
+  ##
+
+  nginxServerBlock: |-
+    server {
+    listen 0.0.0.0:{{ .Values.containerPort }};
+
+    # You can provide a special subPath or the root
+    location = / {
+        auth_request /auth-proxy;
+    }
+
+    location = /auth-proxy {
+        internal;
+
+        proxy_pass http://127.0.0.1:{{ .Values.ldapDaemon.port }};
+
+        ###############################################################
+        # YOU SHOULD CHANGE THE FOLLOWING TO YOUR LDAP CONFIGURATION  #
+        ###############################################################
+
+        # URL and port for connecting to the LDAP server
+        proxy_set_header X-Ldap-URL "ldap://YOUR_LDAP_SERVER_IP:YOUR_LDAP_SERVER_PORT";
+
+        # Base DN
+        proxy_set_header X-Ldap-BaseDN "dc=example,dc=org";
+
+        # Bind DN
+        proxy_set_header X-Ldap-BindDN "cn=admin,dc=example,dc=org";
+
+        # Bind password
+        proxy_set_header X-Ldap-BindPass "adminpassword";
+    }
+    }
+
+  ## Use an existing Secret holding an NGINX Configuration file that
+  ## configures LDAP requests. (will be evaluated as a template)
+  ##
+  ## If provided, both nginxServerBlock and ldapConfig properties are ignored.
+  ##
+  existingNginxServerBlockSecret:
+
+  ## LDAP Auth Daemon's liveness and readiness probes
+  ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
+  ##
+  livenessProbe:
+    tcpSocket:
+      port: ldap-daemon
+    initialDelaySeconds: 30
+    timeoutSeconds: 5
+    failureThreshold: 6
+
+  readinessProbe:
+    tcpSocket:
+      port: ldap-daemon
+    initialDelaySeconds: 5
+    timeoutSeconds: 3
+    periodSeconds: 5
+
+## Ingress paramaters
+##
+ingress:
+  ## Set to true to enable ingress record generation
+  ##
+  enabled: false
+
+  ## Set this to true in order to add the corresponding annotations for cert-manager
+  ##
+  certManager: false
+
+  ## When the ingress is enabled, a host pointing to this will be created
+  ##
+  # hostname: example.local
+
+  ## The list of hosts and paths to be covered into ingress rules if more than one hosts
+  ## or only a host with a path is needed, this is an array
+  ## hosts:
+  ## - name: example.local
+  ##   path: /
+
+  ## Ingress annotations done as key:value pairs
+  ## For a full list of possible ingress annotations, please see
+  ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
+  ##
+  ## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set
+  ## If certManager is set to true, annotation kubernetes.io/tls-acme: "true" will automatically be set
+  annotations: {}
+  #  kubernetes.io/ingress.class: nginx
+
+  ## The tls configuration for the ingress
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls
+  ##
+  tls:
+    - hosts:
+        - example.local
+      secretName: example.local-tls
+
+
+healthIngress:
+  ## Set to true to enable health ingress record generation
+  ##
+  enabled: false
+
+  ## Set this to true in order to add the corresponding annotations for cert-manager
+  ##
+  certManager: false
+
+  ## When the health ingress is enabled, a host pointing to this will be created
+  ##
+  hostname: example.local
+
+  ## Health Ingress annotations done as key:value pairs
+  ## For a full list of possible ingress annotations, please see
+  ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
+  ##
+  ## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set
+  ## If certManager is set to true, annotation kubernetes.io/tls-acme: "true" will automatically be set
+  annotations: {}
+  #  kubernetes.io/ingress.class: nginx
+
+  ## The list of additional hostnames to be covered with this health ingress record.
+  ## Most likely the hostname above will be enough, but in the event more hosts are needed, this is an array
+  ## hosts:
+  ## - name: example.local
+  ##   path: /
+
+  ## The tls configuration for the health ingress
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls
+  ##
+  tls:
+    - hosts:
+        - example.local
+      secretName: example.local-tls
+
+  secrets:
+  ## If you're providing your own certificates, please use this to add the certificates as secrets
+  ## key and certificate should start with -----BEGIN CERTIFICATE----- or
+  ## -----BEGIN RSA PRIVATE KEY-----
+  ##
+  ## name should line up with a tlsSecret set further up
+  ## If you're using cert-manager, this is unneeded, as it will create the secret for you if it is not set
+  ##
+  ## It is also possible to create and manage the certificates outside of this helm chart
+  ## Please see README.md for more information
+  # - name: example.local-tls
+  #   key:
+  #   certificate:
+
+## Prometheus Exporter / Metrics
+##
+metrics:
+  enabled: false
+
+  ## Bitnami NGINX Prometheus Exporter image
+  ## ref: https://hub.docker.com/r/bitnami/nginx-exporter/tags/
+  ##
+  image:
+    registry: docker.io
+    repository: bitnami/nginx-exporter
+    tag: 0.8.0-debian-10-r40
+    pullPolicy: IfNotPresent
+    ## Optionally specify an array of imagePullSecrets.
+    ## Secrets must be manually created in the namespace.
+    ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+    ##
+    # pullSecrets:
+    #   - myRegistryKeySecretName
+
+  ## Prometheus exporter pods' annotation and labels
+  ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
+  ##
+  podAnnotations:
+    prometheus.io/scrape: "true"
+    prometheus.io/port: "9113"
+
+  ## Prometheus exporter service parameters
+  ##
+  service:
+    ## NGINX Prometheus exporter port
+    ##
+    port: 9113
+    ## Annotations for the Prometheus exporter service
+    ##
+    annotations:
+      prometheus.io/scrape: "true"
+      prometheus.io/port: "{{ .Values.metrics.service.port }}"
+
+  ## NGINX Prometheus exporter resource requests and limits
+  ## ref: http://kubernetes.io/docs/user-guide/compute-resources/
+  ##
+  resources:
+    # We usually recommend not to specify default resources and to leave this as a conscious
+    # choice for the user. This also increases chances charts run on environments with little
+    # resources, such as Minikube. If you do want to specify resources, uncomment the following
+    # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+    limits: {}
+    #   cpu: 100m
+    #   memory: 128Mi
+    requests: {}
+    #   cpu: 100m
+    #   memory: 128Mi
+
+  ## Prometheus Operator ServiceMonitor configuration
+  ##
+  serviceMonitor:
+    enabled: false
+    ## Namespace in which Prometheus is running
+    ##
+    # namespace: monitoring
+
+    ## Interval at which metrics should be scraped.
+    ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint
+    ##
+    # interval: 10s
+
+    ## Timeout after which the scrape is ended
+    ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint
+    ##
+    # scrapeTimeout: 10s
+
+    ## ServiceMonitor selector labels
+    ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration
+    ##
+    # selector:
+    #   prometheus: my-prometheus
+
+## Autoscaling parameters
+##
+autoscaling:
+  enabled: false
+  # minReplicas: 1
+  # maxReplicas: 10
+  # targetCPU: 50
+  # targetMemory: 50
+
+## Array to add extra volumes (evaluated as a template)
+##
+extraVolumes: []
+
+## Array to add extra mounts (normally used with extraVolumes, evaluated as a template)
+##
+extraVolumeMounts: []
diff --git a/tests/sdk/nodejs/examples/helm-local/step2/index.ts b/tests/sdk/nodejs/examples/helm-local/step2/index.ts
index 9227cc5bb5..bf330b5c74 100644
--- a/tests/sdk/nodejs/examples/helm-local/step2/index.ts
+++ b/tests/sdk/nodejs/examples/helm-local/step2/index.ts
@@ -1,4 +1,4 @@
-// Copyright 2016-2019, Pulumi Corporation.
+// Copyright 2016-2020, Pulumi Corporation.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -19,30 +19,19 @@ const namespace = new k8s.core.v1.Namespace("test");
 const namespaceName = namespace.metadata.name;
 
 function chart(resourcePrefix?: string): k8s.helm.v3.Chart {
-    return new k8s.helm.v3.Chart("nginx-lego", {
-        // Represents chart `stable/nginx-lego@v0.3.1`.
-        path: "nginx-lego",
-        version: "0.3.1",
+    return new k8s.helm.v3.Chart("nginx", {
+        path: "nginx",
         namespace: namespaceName,
         resourcePrefix: resourcePrefix,
         values: {
-            // Override for the Chart's `values.yml` file. Use `null` to zero out resource requests so it
-            // can be scheduled on our (wimpy) CI cluster. (Setting these values to `null` is the "normal"
-            // way to delete values.)
-            nginx: {resources: null},
-            default: {resources: null},
-            lego: {resources: null}
+            service: { type: "ClusterIP" }
         },
         transformations: [
-            // Make every service private to the cluster, i.e., turn all services into ClusterIP instead of
-            // LoadBalancer.
-            (obj: any) => {
+            (obj: any, opts: pulumi.CustomResourceOptions) => {
                 if (obj.kind == "Service" && obj.apiVersion == "v1") {
-                    if (obj.spec && obj.spec.type && obj.spec.type == "LoadBalancer") {
-                        obj.spec.type = "ClusterIP";
-                    }
+                    opts.additionalSecretOutputs = ["status"];
                 }
-            },
+            }
         ]
     });
 }
@@ -50,9 +39,16 @@ function chart(resourcePrefix?: string): k8s.helm.v3.Chart {
 // Create the first instance of the Chart.
 const nginx = chart();
 
+// Create a ConfigMap depending on the Chart. The ConfigMap should not be created until after all of the Chart
+// resources are ready.
+new k8s.core.v1.ConfigMap("foo", {
+    metadata: { namespace: namespaceName },
+    data: {foo: "bar"}
+}, {dependsOn: nginx})
+
 // Export the (cluster-private) IP address of the Guestbook frontend.
 const frontendServiceSpec = pulumi.all([namespaceName, nginx]).apply(([nsName, nginx]) =>
-    nginx.getResourceProperty("v1/Service", nsName, "nginx-lego-nginx-lego", "spec"));
+    nginx.getResourceProperty("v1/Service", nsName, "nginx", "spec"));
 export const frontendServiceIP = frontendServiceSpec.clusterIP;
 
 // Deploy a duplicate chart with a different resource prefix to verify that multiple instances of the Chart

From cee5cf3cb8d8ff4ab194835e3c52a9828972ed47 Mon Sep 17 00:00:00 2001
From: Levi Blackstone <levi@pulumi.com>
Date: Wed, 11 Nov 2020 12:08:42 -0700
Subject: [PATCH 3/6] Test update

---
 tests/sdk/nodejs/examples/helm-local/step1/index.ts | 2 +-
 tests/sdk/nodejs/examples/helm-local/step2/index.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/sdk/nodejs/examples/helm-local/step1/index.ts b/tests/sdk/nodejs/examples/helm-local/step1/index.ts
index 242ac41a92..91ecd4293f 100644
--- a/tests/sdk/nodejs/examples/helm-local/step1/index.ts
+++ b/tests/sdk/nodejs/examples/helm-local/step1/index.ts
@@ -44,7 +44,7 @@ const nginx = chart();
 new k8s.core.v1.ConfigMap("foo", {
     metadata: { namespace: namespaceName },
     data: {foo: "bar"}
-}, {dependsOn: nginx})
+}, {dependsOn: nginx.ready})
 
 // Export the (cluster-private) IP address of the Guestbook frontend.
 const frontendServiceSpec = pulumi.all([namespaceName, nginx]).apply(([nsName, nginx]) =>
diff --git a/tests/sdk/nodejs/examples/helm-local/step2/index.ts b/tests/sdk/nodejs/examples/helm-local/step2/index.ts
index bf330b5c74..5a64a98be8 100644
--- a/tests/sdk/nodejs/examples/helm-local/step2/index.ts
+++ b/tests/sdk/nodejs/examples/helm-local/step2/index.ts
@@ -44,7 +44,7 @@ const nginx = chart();
 new k8s.core.v1.ConfigMap("foo", {
     metadata: { namespace: namespaceName },
     data: {foo: "bar"}
-}, {dependsOn: nginx})
+}, {dependsOn: nginx.ready})
 
 // Export the (cluster-private) IP address of the Guestbook frontend.
 const frontendServiceSpec = pulumi.all([namespaceName, nginx]).apply(([nsName, nginx]) =>

From e7d952dbfa0ef02cad06c518c821436244f331e5 Mon Sep 17 00:00:00 2001
From: Levi Blackstone <levi@pulumi.com>
Date: Wed, 11 Nov 2020 12:10:02 -0700
Subject: [PATCH 4/6] changelog

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 659e735cfe..cf26233b85 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
 -   Add support for previewing Create and Update operations for API servers that support dry-run (https://github.com/pulumi/pulumi-kubernetes/pull/1355)
 -   Fix panic introduced in #1355 (https://github.com/pulumi/pulumi-kubernetes/pull/1368)
 -   Update Helm to v3.4.0 and client-go to v1.19.2 (https://github.com/pulumi/pulumi-kubernetes/pull/1360)
+-   Add ready attribute to await Helm charts (https://github.com/pulumi/pulumi-kubernetes/pull/1364)
 
 ## 2.6.3 (October 12, 2020)
 

From 703085398e8fb720eb3aaa5a437ead685f6a40db Mon Sep 17 00:00:00 2001
From: Levi Blackstone <levi@pulumi.com>
Date: Thu, 12 Nov 2020 10:27:58 -0700
Subject: [PATCH 5/6] Simplify ready logic

---
 provider/pkg/gen/nodejs-templates/helm/v2/helm.ts | 2 +-
 provider/pkg/gen/nodejs-templates/helm/v3/helm.ts | 2 +-
 sdk/nodejs/helm/v2/helm.ts                        | 2 +-
 sdk/nodejs/helm/v3/helm.ts                        | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts b/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
index 19e511d8cc..0a0723a240 100644
--- a/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
+++ b/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
@@ -255,7 +255,7 @@ export class Chart extends yaml.CollectionComponentResource {
             }
         });
 
-        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
+        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
     }
 
     parseTemplate(
diff --git a/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts b/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
index d9c8374b55..0a7192f6f7 100644
--- a/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
+++ b/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
@@ -158,7 +158,7 @@ export class Chart extends yaml.CollectionComponentResource {
             return this.parseChart(cfg, releaseName, opts)
         });
 
-        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
+        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
     }
 
     parseChart(config: ChartOpts | LocalChartOpts, releaseName: string, opts?: pulumi.ComponentResourceOptions) {
diff --git a/sdk/nodejs/helm/v2/helm.ts b/sdk/nodejs/helm/v2/helm.ts
index 19e511d8cc..0a0723a240 100644
--- a/sdk/nodejs/helm/v2/helm.ts
+++ b/sdk/nodejs/helm/v2/helm.ts
@@ -255,7 +255,7 @@ export class Chart extends yaml.CollectionComponentResource {
             }
         });
 
-        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
+        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
     }
 
     parseTemplate(
diff --git a/sdk/nodejs/helm/v3/helm.ts b/sdk/nodejs/helm/v3/helm.ts
index d9c8374b55..0a7192f6f7 100644
--- a/sdk/nodejs/helm/v3/helm.ts
+++ b/sdk/nodejs/helm/v3/helm.ts
@@ -158,7 +158,7 @@ export class Chart extends yaml.CollectionComponentResource {
             return this.parseChart(cfg, releaseName, opts)
         });
 
-        this.ready = this.resources.apply(m => pulumi.all(m).apply(m => Object.values(m).map(r => pulumi.output(r))));
+        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
     }
 
     parseChart(config: ChartOpts | LocalChartOpts, releaseName: string, opts?: pulumi.ComponentResourceOptions) {

From 974a4c458c827bfc689541f5521c4dc3983ac9f7 Mon Sep 17 00:00:00 2001
From: Levi Blackstone <levi@pulumi.com>
Date: Thu, 12 Nov 2020 10:45:29 -0700
Subject: [PATCH 6/6] Even simpler

---
 provider/pkg/gen/nodejs-templates/helm/v2/helm.ts | 2 +-
 provider/pkg/gen/nodejs-templates/helm/v3/helm.ts | 2 +-
 provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl  | 2 +-
 sdk/nodejs/helm/v2/helm.ts                        | 2 +-
 sdk/nodejs/helm/v3/helm.ts                        | 2 +-
 sdk/nodejs/yaml/yaml.ts                           | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts b/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
index 0a0723a240..504d99599e 100644
--- a/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
+++ b/provider/pkg/gen/nodejs-templates/helm/v2/helm.ts
@@ -255,7 +255,7 @@ export class Chart extends yaml.CollectionComponentResource {
             }
         });
 
-        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
+        this.ready = this.resources.apply(m => Object.values(m));
     }
 
     parseTemplate(
diff --git a/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts b/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
index 0a7192f6f7..fe0220ad96 100644
--- a/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
+++ b/provider/pkg/gen/nodejs-templates/helm/v3/helm.ts
@@ -158,7 +158,7 @@ export class Chart extends yaml.CollectionComponentResource {
             return this.parseChart(cfg, releaseName, opts)
         });
 
-        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
+        this.ready = this.resources.apply(m => Object.values(m));
     }
 
     parseChart(config: ChartOpts | LocalChartOpts, releaseName: string, opts?: pulumi.ComponentResourceOptions) {
diff --git a/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl b/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl
index 72c097b2e4..4c8cad99ec 100644
--- a/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl
+++ b/provider/pkg/gen/nodejs-templates/yaml/yaml.tmpl
@@ -25,7 +25,7 @@ import { getVersion } from "../utilities";
 
 export abstract class CollectionComponentResource extends pulumi.ComponentResource {
     resources!: pulumi.Output<{ [key: string]: pulumi.CustomResource }>;
-    ready!: pulumi.Output<pulumi.Output<pulumi.CustomResource>[]>;
+    ready!: pulumi.Output<pulumi.CustomResource[]>;
 
     protected constructor(
         resourceType: string, name: string, config: any, opts?: pulumi.ComponentResourceOptions,
diff --git a/sdk/nodejs/helm/v2/helm.ts b/sdk/nodejs/helm/v2/helm.ts
index 0a0723a240..504d99599e 100644
--- a/sdk/nodejs/helm/v2/helm.ts
+++ b/sdk/nodejs/helm/v2/helm.ts
@@ -255,7 +255,7 @@ export class Chart extends yaml.CollectionComponentResource {
             }
         });
 
-        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
+        this.ready = this.resources.apply(m => Object.values(m));
     }
 
     parseTemplate(
diff --git a/sdk/nodejs/helm/v3/helm.ts b/sdk/nodejs/helm/v3/helm.ts
index 0a7192f6f7..fe0220ad96 100644
--- a/sdk/nodejs/helm/v3/helm.ts
+++ b/sdk/nodejs/helm/v3/helm.ts
@@ -158,7 +158,7 @@ export class Chart extends yaml.CollectionComponentResource {
             return this.parseChart(cfg, releaseName, opts)
         });
 
-        this.ready = this.resources.apply(m => Object.values(m).map(r => pulumi.output(r)));
+        this.ready = this.resources.apply(m => Object.values(m));
     }
 
     parseChart(config: ChartOpts | LocalChartOpts, releaseName: string, opts?: pulumi.ComponentResourceOptions) {
diff --git a/sdk/nodejs/yaml/yaml.ts b/sdk/nodejs/yaml/yaml.ts
index 5f29e1777d..1704216078 100644
--- a/sdk/nodejs/yaml/yaml.ts
+++ b/sdk/nodejs/yaml/yaml.ts
@@ -25,7 +25,7 @@ import { getVersion } from "../utilities";
 
 export abstract class CollectionComponentResource extends pulumi.ComponentResource {
     resources!: pulumi.Output<{ [key: string]: pulumi.CustomResource }>;
-    ready!: pulumi.Output<pulumi.Output<pulumi.CustomResource>[]>;
+    ready!: pulumi.Output<pulumi.CustomResource[]>;
 
     protected constructor(
         resourceType: string, name: string, config: any, opts?: pulumi.ComponentResourceOptions,