Add the ability to pulumi.unsecret an existing output (#6086)
Related: #5653 This will take an existing output and then unwrap the secret, and return a new output ``` import * as pulumi from "@pulumi/pulumi"; const x = pulumi.secret("test") export const xVal = x; const y = pulumi.unsecret(x); export const yVal = y; ``` ``` ▶ pulumi stack output Current stack outputs (3): OUTPUT VALUE xVal [secret] yVal test ``` Also adds the ability to check if an output is as secret: ``` import * as pulumi from "@pulumi/pulumi"; const x = pulumi.secret("test") const isSecret = x.isSecret; export const isSecretDeets = isSecret; ```
This commit is contained in:
parent
dd66d8d2ab
commit
ae9a6db36e
|
@ -17,6 +17,12 @@ CHANGELOG
|
|||
- [sdk/python] Fix python 3.6 support by removing annotations import.
|
||||
[#6109](https://github.com/pulumi/pulumi/pull/6109)
|
||||
|
||||
- [sdk/nodejs] Added `pulumi.unsecret` which will take an existing secret output and
|
||||
create a non-secret variant with an unwrapped secret value. Also adds,
|
||||
`pulumi.isSecret` which will take an existing output and
|
||||
determine if an output has a secret within the output.
|
||||
[#6086](https://github.com/pulumi/pulumi/pull/6086)
|
||||
|
||||
## 2.17.1 (2021-01-13)
|
||||
|
||||
- Fix an issue with go sdk generation where optional strict enum values
|
||||
|
@ -38,7 +44,7 @@ CHANGELOG
|
|||
- [sdk/dotnet] Moved urn value retrieval into if statement
|
||||
for MockMonitor
|
||||
[#6081](https://github.com/pulumi/pulumi/pull/6081)
|
||||
|
||||
|
||||
- [sdk/dotnet] Added `Pulumi.Output.Unsecret` which will
|
||||
take an existing secret output and
|
||||
create a non-secret variant with an unwrapped secret value.
|
||||
|
|
|
@ -388,9 +388,10 @@ async function applyHelperAsync<T, U>(
|
|||
// Returns an promise denoting if the output is a secret or not. This is not the same as just calling `.isSecret`
|
||||
// because in cases where the output does not have a `isSecret` property and it is a Proxy, we need to ignore
|
||||
// the isSecret member that the proxy reports back.
|
||||
// This calls the public implementation so that we only make any calculations in a single place.
|
||||
/** @internal */
|
||||
export function isSecretOutput<T>(o: Output<T>): Promise<boolean> {
|
||||
return Output.isInstance(o.isSecret) ? Promise.resolve(false) : o.isSecret;
|
||||
return isSecret(o);
|
||||
}
|
||||
|
||||
// Helper function for `output`. This function trivially recurses through an object, copying it,
|
||||
|
@ -521,7 +522,7 @@ export function output<T>(val: Input<T | undefined>): Output<Unwrap<T | undefine
|
|||
}
|
||||
|
||||
/**
|
||||
* [secret] behaves the same as [output] except the returned output is marked as contating sensitive data.
|
||||
* [secret] behaves the same as [output] except the returned output is marked as containing sensitive data.
|
||||
*/
|
||||
export function secret<T>(val: Input<T>): Output<Unwrap<T>>;
|
||||
export function secret<T>(val: Input<T> | undefined): Output<Unwrap<T | undefined>>;
|
||||
|
@ -534,6 +535,19 @@ export function secret<T>(val: Input<T | undefined>): Output<Unwrap<T | undefine
|
|||
o.isKnown, Promise.resolve(true), o.allResources!());
|
||||
}
|
||||
|
||||
/**
|
||||
* [unsecret] behaves the same as [output] except the returned output takes the existing output and unwraps the secret
|
||||
*/
|
||||
export function unsecret<T>(val: Output<T>): Output<T> {
|
||||
return new Output(
|
||||
val.resources(), val.promise(/*withUnknowns*/ true),
|
||||
val.isKnown, Promise.resolve(false), val.allResources!());
|
||||
}
|
||||
|
||||
export function isSecret<T>(val: Output<T>): Promise<boolean> {
|
||||
return Output.isInstance(val.isSecret) ? Promise.resolve(false) : val.isSecret;
|
||||
}
|
||||
|
||||
function createSimpleOutput(val: any) {
|
||||
return new Output(
|
||||
new Set(),
|
||||
|
@ -779,7 +793,6 @@ export type UnwrappedObject<T> = {
|
|||
*/
|
||||
export interface OutputInstance<T> {
|
||||
/** @internal */ allResources?: () => Promise<Set<Resource>>;
|
||||
|
||||
/** @internal */ readonly isKnown: Promise<boolean>;
|
||||
/** @internal */ readonly isSecret: Promise<boolean>;
|
||||
/** @internal */ promise(withUnknowns?: boolean): Promise<T>;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// tslint:disable
|
||||
|
||||
import * as assert from "assert";
|
||||
import { Output, all, concat, interpolate, output, unknown } from "../output";
|
||||
import { Output, all, concat, interpolate, output, unknown, secret, unsecret, isSecret } from "../output";
|
||||
import { Resource } from "../resource";
|
||||
import * as runtime from "../runtime";
|
||||
import { asyncTest } from "./util";
|
||||
|
@ -860,6 +860,21 @@ describe("output", () => {
|
|||
}));
|
||||
});
|
||||
|
||||
describe("secret operations", () => {
|
||||
it("ensure secret", asyncTest(async () => {
|
||||
const sec = secret("foo");
|
||||
assert.strictEqual(await sec.isSecret, true)
|
||||
}));
|
||||
it("ensure that a secret can be unwrapped", asyncTest(async () => {
|
||||
const sec = secret("foo");
|
||||
assert.strictEqual(await isSecret(sec), true)
|
||||
|
||||
const unsec = unsecret(sec);
|
||||
assert.strictEqual(await isSecret(unsec), false)
|
||||
assert.strictEqual(await unsec.promise(), "foo")
|
||||
}));
|
||||
});
|
||||
|
||||
describe("lifted operations", () => {
|
||||
it("lifts properties from inner object", asyncTest(async () => {
|
||||
const output1 = output({ a: 1, b: true, c: "str", d: [2], e: { f: 3 }, g: undefined, h: null });
|
||||
|
|
Loading…
Reference in a new issue