These changes add support for distinguishing an output property with an unknown value from an output property with a known value that is undefined. In a broad sense, the Pulumi property type system is just JSON with the addition of unknown values. Notably absent, however, are undefined values. As it stands, our marshalers between JavaScript and Pulumi property values treat all undefined JavaScript values as unknown Pulumi values. Unfortunately, this conflates two very different concepts: unknown Pulumi values are intended to represent values of output properties that are unknown at time of preview, _not_ values that are known but undefined. This results in difficulty reasoning about when transforms are run on output properties as well as confusing output in the `diff` view of Pulumi preview (user-specifed undefined values are rendered as unknown values). As it turns out, we already have a way to decide whether or not an Output value is known or not: Output.performApply. These changes rename this property to `isKnown`, clarify its meaning, and take advantage of the result to decide whether or not an Output value should marshal as an unknown Pulumi value. This also allowed these changes to improve the serialization of undefined object keys and array elements s.t. we better match JavaScript to JSON serialization behavior (undefined object keys are omitted; undefined array elements are marshaled as `null`). Fixes https://github.com/pulumi/pulumi-cloud/issues/483.
45 lines
1.8 KiB
TypeScript
45 lines
1.8 KiB
TypeScript
// Copyright 2016-2018, Pulumi Corporation.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import * as assert from "assert";
|
|
import { Inputs, runtime } from "../../index";
|
|
import { asyncTest } from "../util";
|
|
|
|
const gstruct = require("google-protobuf/google/protobuf/struct_pb.js");
|
|
|
|
describe("runtime", () => {
|
|
describe("transferProperties", () => {
|
|
it("marshals basic properties correctly", asyncTest(async () => {
|
|
const inputs: Inputs = {
|
|
"aNum": 42,
|
|
"bStr": "a string",
|
|
"cUnd": undefined,
|
|
"dArr": Promise.resolve([ "x", 42, Promise.resolve(true), Promise.resolve(undefined) ]),
|
|
"id": "foo",
|
|
"urn": "bar",
|
|
};
|
|
// Serialize and then deserialize all the properties, checking that they round-trip as expected.
|
|
const transfer = gstruct.Struct.fromJavaScript(
|
|
await runtime.serializeProperties("test", inputs));
|
|
const result = runtime.deserializeProperties(transfer);
|
|
assert.equal(result.aNum, 42);
|
|
assert.equal(result.bStr, "a string");
|
|
assert.equal(result.cUnd, undefined);
|
|
assert.deepEqual(result.dArr, [ "x", 42, true, null ]);
|
|
assert.equal(result.id, "foo");
|
|
assert.equal(result.urn, "bar");
|
|
}));
|
|
});
|
|
});
|
|
|