From e629bc32d5afe9615869060235b907fe6e92f0b2 Mon Sep 17 00:00:00 2001 From: Ian Wahbe Date: Mon, 1 Nov 2021 11:10:27 -0700 Subject: [PATCH] Expand dependencies when marshaling output values (#8301) * Expand dependencies when marshaling output values [sdk/python] * Update CHANGELOG_PENDING.md * Use existing code * Fix lint --- CHANGELOG_PENDING.md | 3 +++ sdk/nodejs/runtime/resource.ts | 2 +- sdk/python/lib/pulumi/runtime/known_types.py | 4 ++-- sdk/python/lib/pulumi/runtime/resource.py | 10 ++++++---- sdk/python/lib/pulumi/runtime/rpc.py | 20 +++++++++++++------- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 2de19e30a..3ddae0758 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -18,6 +18,9 @@ However, the streaming output can be extended to `preview` by using the `PULUMI_ENABLE_STREAMING_JSON_PREVIEW` environment variable. [#8275](https://github.com/pulumi/pulumi/pull/8275) + +- [sdk/python] - Expand dependencies when marshaling output values + [#8301](https://github.com/pulumi/pulumi/pull/8301) - [codegen/go] - Interaction between the `plain` and `default` tags of a type. [#8254](https://github.com/pulumi/pulumi/pull/8254) diff --git a/sdk/nodejs/runtime/resource.ts b/sdk/nodejs/runtime/resource.ts index 6a70b9eac..8a0356348 100644 --- a/sdk/nodejs/runtime/resource.ts +++ b/sdk/nodejs/runtime/resource.ts @@ -624,7 +624,7 @@ export async function getAllTransitivelyReferencedResourceURNs(resources: Set bool: def is_stack(obj: Any) -> bool: """ - Returns true if the given type is an Output, false otherwise. + Returns true if the given type is a Stack, false otherwise. """ from .stack import Stack # pylint: disable=import-outside-toplevel return isinstance(obj, Stack) diff --git a/sdk/python/lib/pulumi/runtime/resource.py b/sdk/python/lib/pulumi/runtime/resource.py index 202a5daf7..b7c329eac 100644 --- a/sdk/python/lib/pulumi/runtime/resource.py +++ b/sdk/python/lib/pulumi/runtime/resource.py @@ -640,11 +640,13 @@ class RegisterResponse: self.propertyDependencies = propertyDependencies -# Merge all providers opts (opts.provider and both list and dict forms of opts.providers) into a single dict. def convert_providers( provider: Optional['ProviderResource'], providers: Optional[Union[Mapping[str, 'ProviderResource'], Sequence['ProviderResource']]]) -> Mapping[str, 'ProviderResource']: + """ + Merge all providers opts (opts.provider and both list and dict forms of opts.providers) into a single dict. + """ if provider is not None: return convert_providers(None, [provider]) @@ -661,7 +663,7 @@ def convert_providers( return result -async def _add_dependency(deps: Set[str], res: 'Resource', from_resource: 'Resource'): +async def _add_dependency(deps: Set[str], res: 'Resource', from_resource: Optional['Resource']): """ _add_dependency adds a dependency on the given resource to the set of deps. @@ -700,14 +702,14 @@ async def _add_dependency(deps: Set[str], res: 'Resource', from_resource: 'Resou if not res._remote: return - no_cycles = declare_dependency(from_resource, res) + no_cycles = declare_dependency(from_resource, res) if from_resource else True if no_cycles: urn = await res.urn.future() if urn: deps.add(urn) -async def _expand_dependencies(deps: Iterable['Resource'], from_resource: 'Resource') -> Set[str]: +async def _expand_dependencies(deps: Iterable['Resource'], from_resource: Optional['Resource']) -> Set[str]: """ _expand_dependencies expands the given iterable of Resources into a set of URNs. """ diff --git a/sdk/python/lib/pulumi/runtime/rpc.py b/sdk/python/lib/pulumi/runtime/rpc.py index 1c9950676..c6ee58875 100644 --- a/sdk/python/lib/pulumi/runtime/rpc.py +++ b/sdk/python/lib/pulumi/runtime/rpc.py @@ -1,4 +1,4 @@ -# Copyright 2016-2018, Pulumi Corporation. +# Copyright 2016-2021, Pulumi Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ from google.protobuf import struct_pb2 from semver import VersionInfo as Version import six from . import known_types, settings +from .resource import _expand_dependencies from .. import log from .. import _types from .. import urn as urn_util @@ -278,7 +279,7 @@ async def serialize_property(value: 'Input[Any]', if known_types.is_output(value): output = cast('Output', value) - value_resources = await output.resources() + value_resources: Set['Resource'] = await output.resources() deps.extend(value_resources) # When serializing an Output, we will either serialize it as its resolved value or the @@ -287,14 +288,19 @@ async def serialize_property(value: 'Input[Any]', # resolved with known values. is_known = await output._is_known is_secret = await output._is_secret - value = await serialize_property(output.future(), deps, input_transformer, typ, keep_output_values=False) + promise_deps: List['Resource'] = [] + value = await serialize_property(output.future(), promise_deps, input_transformer, typ, keep_output_values=False) + deps.extend(promise_deps) + value_resources.update(promise_deps) if keep_output_values and await settings.monitor_supports_output_values(): - # TODO[pulumi/pulumi#7977]: Expand dependencies - dependencies: Set[str] = set() + urn_deps: List['Resource'] = [] for resource in value_resources: - urn = await serialize_property(resource.urn, deps, input_transformer, keep_output_values=False) - dependencies.add(cast(str, urn)) + await serialize_property(resource.urn, urn_deps, input_transformer, keep_output_values=False) + promise_deps.extend(set(urn_deps)) + value_resources.update(urn_deps) + + dependencies = await _expand_dependencies(value_resources, None) output_value: Dict[str, Any] = { _special_sig_key: _special_output_value_sig