Skip to content

Commit

Permalink
Allow transforms to omit objects; ignore Helm lifecycle hooks
Browse files Browse the repository at this point in the history
Resolves half of #665 (still missing docs).
Fixes #486.
  • Loading branch information
hausdorff committed Jul 30, 2019
1 parent d11fdd8 commit 37c20f3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 21 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
(https://github.com/pulumi/pulumi-kubernetes/pull/655).
- Fix unexpected diffs when running against an API server that does not support dry-run.
(https://github.com/pulumi/pulumi-kubernetes/pull/658)
- Remove Helm lifecycle hooks from any Helm deployment
(https://github.com/pulumi/pulumi-kubernetes/pull/666).
- Allow {yaml|helm} `transformations` API to omit/filter out resources by returning `null`.
(https://github.com/pulumi/pulumi-kubernetes/pull/666).


## 0.25.2 (July 11, 2019)

Expand Down
22 changes: 13 additions & 9 deletions pkg/gen/nodejs-templates/yaml.ts.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import fetch from "node-fetch";
import * as k8s from "../index";
import * as outputApi from "../types/output";


export interface ConfigGroupOpts {
/** Set of paths or a URLs that uniquely identify files. */
files?: string[] | string;
Expand All @@ -20,9 +21,9 @@ import * as outputApi from "../types/output";
/**
* A set of transformations to apply to Kubernetes resource definitions before registering
* with engine.
* with engine. If `null` is returned, the resource is removed from
*/
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[];
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[];
/**
* An optional prefix for the auto-generated resource names.
Expand All @@ -37,9 +38,9 @@ import * as outputApi from "../types/output";
/**
* A set of transformations to apply to Kubernetes resource definitions before registering
* with engine.
* with engine. If `null` is returned, the resource is removed from
*/
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[];
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[];
/**
* An optional prefix for the auto-generated resource names.
Expand All @@ -54,9 +55,9 @@ import * as outputApi from "../types/output";
/**
* A set of transformations to apply to Kubernetes resource definitions before registering
* with engine.
* with engine. If `null` is returned, the resource is removed from
*/
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[];
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[];
/**
* An optional prefix for the auto-generated resource names.
Expand Down Expand Up @@ -306,7 +307,7 @@ import * as outputApi from "../types/output";

/** @ignore */ function parseYamlObject(
obj: any,
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[],
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[],
resourcePrefix?: string,
opts?: pulumi.CustomResourceOptions,
): pulumi.Output<{name: string, resource: pulumi.CustomResource}>[] {
Expand All @@ -317,9 +318,12 @@ import * as outputApi from "../types/output";
// Create a copy of opts to pass into potentially mutating transforms that will be applied to this resource.
opts = Object.assign({}, opts);

// Allow users to change API objects before any validation.
// Allow users to change API objects before any validation. Omit any object if any
// transformation returns `null`.
for (const t of transformations || []) {
t(obj, opts);
if (t(obj, opts) === null) {
return [];
}
}

if (!("kind" in obj && "apiVersion" in obj)) {
Expand Down
23 changes: 20 additions & 3 deletions sdk/nodejs/helm/v2/helm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ interface BaseChartOpts {
* Optional array of transformations to apply to resources that will be created by this chart prior to
* creation. Allows customization of the chart behaviour without directly modifying the chart itself.
*/
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[];
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[];

/**
* An optional prefix for the auto-generated resource names.
Expand Down Expand Up @@ -174,7 +174,12 @@ export class Chart extends yaml.CollectionComponentResource {
const yamlStream = execSync(
`helm template ${chart} --name ${release} --values ${defaultValues} --values ${values} ${namespaceArg}`
).toString();
return this.parseTemplate(yamlStream, cfg.transformations, cfg.resourcePrefix, configDeps);
return this.parseTemplate(
yamlStream,
[ignoreHelmTestHook, ...(cfg.transformations || [])],
cfg.resourcePrefix,
configDeps,
);
} catch (e) {
// Shed stack trace, only emit the error.
throw new pulumi.RunError(e.toString());
Expand All @@ -188,7 +193,7 @@ export class Chart extends yaml.CollectionComponentResource {

parseTemplate(
yamlStream: string,
transformations: ((o: any, opts: pulumi.CustomResourceOptions) => void)[] | undefined,
transformations: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[],
resourcePrefix: string | undefined,
dependsOn: pulumi.Resource[],
): pulumi.Output<{ [key: string]: pulumi.CustomResource }> {
Expand All @@ -214,6 +219,18 @@ export class Chart extends yaml.CollectionComponentResource {
}
}

// ignoreHelmTestHook returns `null` if a resource has an annotation that signals it's part of the
// Helm test lifecycle hook. This can be provided to Chart's `transformations` API to have it omit
// all resources that are part of this hook.
function ignoreHelmTestHook(o: any) {
const annotations = (o.metadata && o.metadata.annotations) || {};
const hook = annotations["helm.sh/hook"];
if (hook === "test-success" || hook === "test-failure") {
return null;
}
return o;
}

// helmSort is a JavaScript implementation of the Helm Kind sorter[1]. It provides a
// best-effort topology of Kubernetes kinds, which in most cases should ensure that resources
// that must be created first, are.
Expand Down
22 changes: 13 additions & 9 deletions sdk/nodejs/yaml/yaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import fetch from "node-fetch";
import * as k8s from "../index";
import * as outputApi from "../types/output";


export interface ConfigGroupOpts {
/** Set of paths or a URLs that uniquely identify files. */
files?: string[] | string;
Expand All @@ -20,9 +21,9 @@ import * as outputApi from "../types/output";

/**
* A set of transformations to apply to Kubernetes resource definitions before registering
* with engine.
* with engine. If `null` is returned, the resource is removed from
*/
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[];
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[];

/**
* An optional prefix for the auto-generated resource names.
Expand All @@ -37,9 +38,9 @@ import * as outputApi from "../types/output";

/**
* A set of transformations to apply to Kubernetes resource definitions before registering
* with engine.
* with engine. If `null` is returned, the resource is removed from
*/
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[];
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[];

/**
* An optional prefix for the auto-generated resource names.
Expand All @@ -54,9 +55,9 @@ import * as outputApi from "../types/output";

/**
* A set of transformations to apply to Kubernetes resource definitions before registering
* with engine.
* with engine. If `null` is returned, the resource is removed from
*/
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[];
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[];

/**
* An optional prefix for the auto-generated resource names.
Expand Down Expand Up @@ -2282,7 +2283,7 @@ import * as outputApi from "../types/output";

/** @ignore */ function parseYamlObject(
obj: any,
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void)[],
transformations?: ((o: any, opts: pulumi.CustomResourceOptions) => void | null)[],
resourcePrefix?: string,
opts?: pulumi.CustomResourceOptions,
): pulumi.Output<{name: string, resource: pulumi.CustomResource}>[] {
Expand All @@ -2293,9 +2294,12 @@ import * as outputApi from "../types/output";
// Create a copy of opts to pass into potentially mutating transforms that will be applied to this resource.
opts = Object.assign({}, opts);

// Allow users to change API objects before any validation.
// Allow users to change API objects before any validation. Omit any object if any
// transformation returns `null`.
for (const t of transformations || []) {
t(obj, opts);
if (t(obj, opts) === null) {
return [];
}
}

if (!("kind" in obj && "apiVersion" in obj)) {
Expand Down

0 comments on commit 37c20f3

Please sign in to comment.