Merge remote-tracking branch 'origin/master' into ctpp
This commit is contained in:
commit
0d9043f6a2
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -2,7 +2,7 @@
|
|||
**/vendor/
|
||||
**/node_modules/
|
||||
**/bin
|
||||
**/.vscode/
|
||||
**/.vscode/**/*
|
||||
**/.vs/
|
||||
**/.ionide/
|
||||
**/.idea/
|
||||
|
@ -17,6 +17,9 @@ coverage.cov
|
|||
# VSCode creates this binary when running tests in the debugger
|
||||
**/debug.test
|
||||
|
||||
# Check in vscode settings for this workspace. This is so we can save common settings like setting go build tags to use by default.
|
||||
!**/.vscode/settings.json
|
||||
|
||||
# Go tests run "in tree" and this folder will linger if they fail (the integration test framework cleans
|
||||
# it up when they pass.)
|
||||
**/command-output/
|
||||
|
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"go.buildTags": "all"
|
||||
}
|
|
@ -8,10 +8,8 @@
|
|||
- [sdk/go] - Respect implicit parents in alias resolution
|
||||
[#8288](https://github.com/pulumi/pulumi/pull/8288)
|
||||
|
||||
- [sdk/dotnet] - Fix a race condition when detecting exceptions in stack creation
|
||||
[#8294](https://github.com/pulumi/pulumi/pull/8294)
|
||||
- Clarify error message string in `sdk/go/common/diag/errors.go`
|
||||
[#8284](https://github.com/pulumi/pulumi/pull/8284)
|
||||
- Clarify error message string in `sdk/go/common/diag/errors.go`
|
||||
[#8284](https://github.com/pulumi/pulumi/pull/8284)
|
||||
|
||||
- [cli] Add `--json` flag to `up`, `destroy` and `refresh`.
|
||||
|
||||
|
@ -20,8 +18,11 @@
|
|||
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.
|
||||
- [codegen/go] - Interaction between the `plain` and `default` tags of a type.
|
||||
[#8254](https://github.com/pulumi/pulumi/pull/8254)
|
||||
|
||||
- [sdk/dotnet] - Fix a race condition when detecting exceptions in stack creation
|
||||
|
@ -30,6 +31,13 @@
|
|||
- [sdk/go] - Fix regression marshaling assets/archives.
|
||||
[#8290](https://github.com/pulumi/pulumi/pull/8290)
|
||||
|
||||
- [sdk/dotnet] - Don't panic on schema mismatches
|
||||
[#8286](https://github.com/pulumi/pulumi/pull/8286)
|
||||
|
||||
- [codegen/python] - Fixes issue with `$fn_output` functions failing in
|
||||
preview when called with unknown arguments
|
||||
[#8320](https://github.com/pulumi/pulumi/pull/8320)
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- [sdk/python] - Drop support for python 3.6
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import pytest
|
||||
|
||||
|
@ -32,8 +33,20 @@ def my_mocks():
|
|||
pulumi.runtime.settings.configure(old_settings)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def my_preview_mocks():
|
||||
old_settings = pulumi.runtime.settings.SETTINGS
|
||||
try:
|
||||
mocks = MyMocks()
|
||||
pulumi.runtime.mocks.set_mocks(mocks, preview=True)
|
||||
yield mocks
|
||||
finally:
|
||||
pulumi.runtime.settings.configure(old_settings)
|
||||
|
||||
|
||||
class MyMocks(pulumi.runtime.Mocks):
|
||||
def call(self, args):
|
||||
|
||||
if args.token in ['mypkg::funcWithAllOptionalInputs',
|
||||
'mypkg::funcWithDefaultValue']:
|
||||
a = args.args.get('a', None)
|
||||
|
@ -49,6 +62,15 @@ class MyMocks(pulumi.runtime.Mocks):
|
|||
'value': [args.args]}
|
||||
|
||||
if args.token == 'mypkg::listStorageAccountKeys':
|
||||
|
||||
if 'accountName' not in args.args or \
|
||||
not args.args['accountName'] or \
|
||||
pulumi.contains_unknowns(args.args['accountName']):
|
||||
raise Exception(
|
||||
'Missing required argument: '
|
||||
'The argument "account_name" is required, '
|
||||
'but no definition was found')
|
||||
|
||||
return {'keys': [
|
||||
dict(creationTime='my-creation-time',
|
||||
keyName='my-key-name',
|
||||
|
@ -193,6 +215,15 @@ def test_list_storage_accounts(my_mocks):
|
|||
)])
|
||||
|
||||
|
||||
@pulumi.runtime.test
|
||||
def test_preview_with_unknowns(my_preview_mocks):
|
||||
|
||||
def check(r):
|
||||
assert False, 'check() should not be called when args contain unknowns'
|
||||
|
||||
return list_storage_account_keys_output(account_name=unknown()).apply(check)
|
||||
|
||||
|
||||
def jstr(x):
|
||||
return json.dumps(x, sort_keys=True)
|
||||
|
||||
|
@ -203,3 +234,14 @@ def r(x):
|
|||
|
||||
def out(x):
|
||||
return pulumi.Output.from_input(x).apply(lambda x: x)
|
||||
|
||||
|
||||
def unknown():
|
||||
is_known_fut: asyncio.Future[bool] = asyncio.Future()
|
||||
is_secret_fut: asyncio.Future[bool] = asyncio.Future()
|
||||
is_known_fut.set_result(False)
|
||||
is_secret_fut.set_result(False)
|
||||
|
||||
value_fut: asyncio.Future[Any] = asyncio.Future()
|
||||
value_fut.set_result(pulumi.UNKNOWN)
|
||||
return pulumi.Output(set(), value_fut, is_known_fut, is_secret_fut)
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -224,9 +224,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -3017,9 +3017,10 @@ def lift_output_func(func: typing.Any) -> typing.Callable[[_F], _F]:
|
|||
|
||||
def lifted_func(*args, opts=None, **kwargs):
|
||||
bound_args = func_sig.bind(*args, **kwargs)
|
||||
|
||||
# Convert tuple to list, see pulumi/pulumi#8172
|
||||
args_list = list(bound_args.args)
|
||||
return pulumi.Output.from_input({
|
||||
'args': bound_args.args,
|
||||
'args': args_list,
|
||||
'kwargs': bound_args.kwargs
|
||||
}).apply(lambda resolved_args: func(*resolved_args['args'],
|
||||
opts=opts,
|
||||
|
|
|
@ -36,6 +36,22 @@ namespace Pulumi.Tests.Mocks
|
|||
public Task<(string? id, object state)> NewResourceAsync(MockResourceArgs args) => throw new Exception("Not used");
|
||||
}
|
||||
|
||||
class MyInvalidMocks : IMocks
|
||||
{
|
||||
public Task<object> CallAsync(MockCallArgs args)
|
||||
{
|
||||
return Task.FromResult<object>(args);
|
||||
}
|
||||
|
||||
public Task<(string? id, object state)> NewResourceAsync(MockResourceArgs args) =>
|
||||
args.Type switch
|
||||
{
|
||||
"aws:ec2/instance:Instance" => Task.FromResult<(string?, object)>(("i-1234567890abcdef0", new Dictionary<string, object> { { "publicIp", unchecked((int)0xcb00710c) }, })),
|
||||
"pkg:index:MyCustom" => Task.FromResult<(string?, object)>((args.Name + "_id", args.Inputs)),
|
||||
_ => throw new Exception($"Unknown resource {args.Type}")
|
||||
};
|
||||
}
|
||||
|
||||
public class MocksTests
|
||||
{
|
||||
[Fact]
|
||||
|
@ -108,6 +124,20 @@ namespace Pulumi.Tests.Mocks
|
|||
Assert.Contains("' failed with an unhandled exception:", exception!.Message);
|
||||
Assert.Contains("Grpc.Core.RpcException: Status(StatusCode=\"Unknown\", Detail=\"error code 404\")", exception!.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestStackWithInvalidSchema()
|
||||
{
|
||||
var resources = await Deployment.TestAsync<MyStack>(new MyInvalidMocks(), new TestOptions { IsPreview = false });
|
||||
|
||||
var stack = resources.OfType<MyStack>().FirstOrDefault();
|
||||
Assert.NotNull(stack);
|
||||
|
||||
var ip = await stack!.PublicIp.GetValueAsync(whenUnknown: default!);
|
||||
Assert.Null(ip);
|
||||
|
||||
// TODO: It would be good to assert that a warning was logged to the engine but getting hold of warnings requires re-plumbing what TestAsync returns.
|
||||
}
|
||||
}
|
||||
|
||||
public static class Testing
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Pulumi.Tests.Serialization
|
|||
private async Task Test(object args, string expected)
|
||||
{
|
||||
var serialized = await SerializeToValueAsync(args);
|
||||
var converted = Converter.ConvertValue<JsonElement>("", serialized);
|
||||
var converted = Converter.ConvertValue<JsonElement>(NoWarn, "", serialized);
|
||||
var value = converted.Value.GetProperty("v").GetProperty("s").GetString();
|
||||
Assert.Equal(expected, value);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void True()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", new Value { BoolValue = true });
|
||||
var data = Converter.ConvertValue<bool>(NoWarn, "", new Value { BoolValue = true });
|
||||
Assert.True(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void False()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", new Value { BoolValue = false });
|
||||
var data = Converter.ConvertValue<bool>(NoWarn, "", new Value { BoolValue = false });
|
||||
|
||||
Assert.False(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -30,7 +30,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void SecretTrue()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", CreateSecretValue(new Value { BoolValue = true }));
|
||||
var data = Converter.ConvertValue<bool>(NoWarn, "", CreateSecretValue(new Value { BoolValue = true }));
|
||||
|
||||
Assert.True(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -40,7 +40,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void SecretFalse()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", CreateSecretValue(new Value { BoolValue = false }));
|
||||
var data = Converter.ConvertValue<bool>(NoWarn, "", CreateSecretValue(new Value { BoolValue = false }));
|
||||
|
||||
Assert.False(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -48,12 +48,16 @@ namespace Pulumi.Tests.Serialization
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void NonBooleanThrows()
|
||||
public void NonBooleanLogs()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
Converter.ConvertValue<bool>("", new Value { StringValue = "" });
|
||||
});
|
||||
string? loggedError = null;
|
||||
Action<string> warn = error => loggedError = error;
|
||||
var data = Converter.ConvertValue<bool>(warn, "", new Value { StringValue = "" });
|
||||
|
||||
Assert.False(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
||||
Assert.Equal("Expected System.Boolean but got System.String deserializing ", loggedError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -61,7 +65,7 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
return RunInPreview(() =>
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", new Value { NullValue = NullValue.NullValue });
|
||||
var data = Converter.ConvertValue<bool>(NoWarn, "", new Value { NullValue = NullValue.NullValue });
|
||||
|
||||
Assert.False(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -73,7 +77,7 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
return RunInNormal(() =>
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", new Value { NullValue = NullValue.NullValue });
|
||||
var data = Converter.ConvertValue<bool>(NoWarn, "", new Value { NullValue = NullValue.NullValue });
|
||||
|
||||
Assert.False(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -83,25 +87,16 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void UnknownProducesFalseUnknown()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", UnknownValue);
|
||||
var data = Converter.ConvertValue<bool>(NoWarn, "", UnknownValue);
|
||||
|
||||
Assert.False(data.Value);
|
||||
Assert.False(data.IsKnown);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StringTest()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
Converter.ConvertValue<bool>("", new Value { StringValue = "" });
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullableTrue()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool?>("", new Value { BoolValue = true });
|
||||
var data = Converter.ConvertValue<bool?>(NoWarn, "", new Value { BoolValue = true });
|
||||
Assert.True(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
}
|
||||
|
@ -109,7 +104,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void NullableFalse()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool?>("", new Value { BoolValue = false });
|
||||
var data = Converter.ConvertValue<bool?>(NoWarn, "", new Value { BoolValue = false });
|
||||
|
||||
Assert.False(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -118,7 +113,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void NullableNull()
|
||||
{
|
||||
var data = Converter.ConvertValue<bool?>("", new Value { NullValue = NullValue.NullValue });
|
||||
var data = Converter.ConvertValue<bool?>(NoWarn, "", new Value { NullValue = NullValue.NullValue });
|
||||
|
||||
Assert.Null(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task TestComplexType1()
|
||||
{
|
||||
var data = Converter.ConvertValue<ComplexType1>("", await SerializeToValueAsync(new Dictionary<string, object>
|
||||
var data = Converter.ConvertValue<ComplexType1>(NoWarn, "", await SerializeToValueAsync(new Dictionary<string, object>
|
||||
{
|
||||
{ "s", "str" },
|
||||
{ "b", true },
|
||||
|
@ -133,10 +133,10 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task TestComplexType2()
|
||||
{
|
||||
var data = Converter.ConvertValue<ComplexType2>("", await SerializeToValueAsync(new Dictionary<string, object>
|
||||
var data = Converter.ConvertValue<ComplexType2>(NoWarn, "", await SerializeToValueAsync(new Dictionary<string, object>
|
||||
{
|
||||
{
|
||||
"c",
|
||||
"c",
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "s", "str1" },
|
||||
|
@ -168,7 +168,7 @@ namespace Pulumi.Tests.Serialization
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
"c2Map",
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
|
@ -231,5 +231,48 @@ namespace Pulumi.Tests.Serialization
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[Fact]
|
||||
public async Task TestComplexTypeTypeMismatches()
|
||||
{
|
||||
var warnings = new List<string>();
|
||||
|
||||
var data = Converter.ConvertValue<ComplexType1>(warnings.Add, "", await SerializeToValueAsync(new Dictionary<string, object>
|
||||
{
|
||||
{ "s", 24 },
|
||||
{ "b", "hi" },
|
||||
{ "i", "string" },
|
||||
{ "d", true },
|
||||
{ "array", new List<object> { false, 99, true, "hello" } },
|
||||
{ "dict", new Dictionary<object, object> { { "k", 10 }, { "v", "hello" } } },
|
||||
{ "obj", "test" },
|
||||
{ "size", "bigger" },
|
||||
{ "color", true },
|
||||
}));
|
||||
|
||||
Assert.Null(data.Value.S);
|
||||
Assert.False(data.Value.B);
|
||||
Assert.Equal(0, data.Value.I);
|
||||
Assert.Equal(0.0, data.Value.D);
|
||||
AssertEx.SequenceEqual(ImmutableArray<bool>.Empty.Add(false).Add(false).Add(true).Add(false), data.Value.Array);
|
||||
AssertEx.MapEqual(ImmutableDictionary<string, int>.Empty.Add("k", 10).Add("v", 0), data.Value.Dict);
|
||||
Assert.Equal("test", data.Value.Obj);
|
||||
Assert.Equal(default(ContainerSize), data.Value.Size);
|
||||
Assert.Equal(default(ContainerColor), data.Value.Color);
|
||||
|
||||
Assert.True(data.IsKnown);
|
||||
|
||||
AssertEx.SequenceEqual(new string[] {
|
||||
"Expected System.String but got System.Double deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(s)",
|
||||
"Expected System.Boolean but got System.String deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(b)",
|
||||
"Expected System.Double but got System.String deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(i)",
|
||||
"Expected System.Double but got System.Boolean deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(d)",
|
||||
"Expected System.Boolean but got System.Double deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(array)",
|
||||
"Expected System.Boolean but got System.String deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(array)",
|
||||
"Expected System.Double but got System.String deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(dict)",
|
||||
"Expected System.Double but got System.String deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(size)",
|
||||
"Expected System.String or System.Double but got System.Boolean deserializing Pulumi.Tests.Serialization.ComplexTypeConverterTests+ComplexType1(color)",
|
||||
}, warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Pulumi.Serialization;
|
||||
|
@ -35,5 +36,10 @@ namespace Pulumi.Tests.Serialization
|
|||
var v = Deserializer.Deserialize(value).Value;
|
||||
return v == null ? default! : (T)v;
|
||||
}
|
||||
|
||||
protected static void NoWarn(string error)
|
||||
{
|
||||
throw new Exception("Test did not expect warn to be called");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[MemberData(nameof(StringEnums))]
|
||||
public async Task StringEnum(ContainerColor input)
|
||||
{
|
||||
var data = Converter.ConvertValue<ContainerColor>("", await SerializeToValueAsync(input));
|
||||
var data = Converter.ConvertValue<ContainerColor>(NoWarn, "", await SerializeToValueAsync(input));
|
||||
|
||||
Assert.Equal(input, data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -108,7 +108,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[MemberData(nameof(DoubleEnums))]
|
||||
public async Task DoubleEnum(ContainerBrightness input)
|
||||
{
|
||||
var data = Converter.ConvertValue<ContainerBrightness>("", await SerializeToValueAsync(input));
|
||||
var data = Converter.ConvertValue<ContainerBrightness>(NoWarn, "", await SerializeToValueAsync(input));
|
||||
|
||||
Assert.Equal(input, data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -123,7 +123,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[InlineData((ContainerSize)int.MaxValue)]
|
||||
public async Task Int32Enum(ContainerSize input)
|
||||
{
|
||||
var data = Converter.ConvertValue<ContainerSize>("", await SerializeToValueAsync(input));
|
||||
var data = Converter.ConvertValue<ContainerSize>(NoWarn, "", await SerializeToValueAsync(input));
|
||||
|
||||
Assert.Equal(input, data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -200,19 +200,23 @@ namespace Pulumi.Tests.Serialization
|
|||
public static IEnumerable<object[]> EnumsWithUnconvertibleValues()
|
||||
=> new[]
|
||||
{
|
||||
new object[] { typeof(ContainerColor), new Value { NumberValue = 1.0 } },
|
||||
new object[] { typeof(ContainerBrightness), new Value { StringValue = "hello" } },
|
||||
new object[] { typeof(ContainerSize), new Value { StringValue = "hello" } },
|
||||
new object[] { typeof(ContainerColor), new Value { NumberValue = 1.0 }, "Expected target type Pulumi.Tests.Serialization.EnumConverterTests+ContainerColor to have a constructor with a single System.Double parameter." },
|
||||
new object[] { typeof(ContainerBrightness), new Value { StringValue = "hello" }, "Expected target type Pulumi.Tests.Serialization.EnumConverterTests+ContainerBrightness to have a constructor with a single System.String parameter." },
|
||||
new object[] { typeof(ContainerSize), new Value { StringValue = "hello" }, "Expected System.Double but got System.String deserializing " },
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(EnumsWithUnconvertibleValues))]
|
||||
public void ConvertingUnconvertibleValuesThrows(Type targetType, Value value)
|
||||
public void ConvertingUnconvertibleValuesLogs(Type targetType, Value value, string expectedError)
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
Converter.ConvertValue("", value, targetType);
|
||||
});
|
||||
string? loggedError = null;
|
||||
Action<string> warn = error => loggedError = error;
|
||||
var data = Converter.ConvertValue(warn, "", value, targetType);
|
||||
|
||||
Assert.Null(data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
||||
Assert.Equal(expectedError, loggedError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void IgnoreInternalProperty()
|
||||
{
|
||||
var data = Converter.ConvertValue<ImmutableDictionary<string, string>>("", new Value
|
||||
var data = Converter.ConvertValue<ImmutableDictionary<string, string>>(NoWarn, "", new Value
|
||||
{
|
||||
StructValue = new Struct
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
var element = JsonDocument.Parse(json).RootElement;
|
||||
var serialized = await SerializeToValueAsync(element);
|
||||
var converted = Converter.ConvertValue<JsonElement>("", serialized);
|
||||
var converted = Converter.ConvertValue<JsonElement>(NoWarn, "", serialized);
|
||||
|
||||
Assert.Equal(expected, converted.Value.ToString());
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task EmptyList()
|
||||
{
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>("", await SerializeToValueAsync(new List<bool>()));
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>(NoWarn, "", await SerializeToValueAsync(new List<bool>()));
|
||||
|
||||
Assert.Equal(ImmutableArray<bool>.Empty, data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -22,7 +22,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task ListWithElement()
|
||||
{
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>("", await SerializeToValueAsync(new List<bool> { true }));
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>(NoWarn, "", await SerializeToValueAsync(new List<bool> { true }));
|
||||
|
||||
AssertEx.SequenceEqual(ImmutableArray<bool>.Empty.Add(true), data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -31,7 +31,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task SecretListWithElement()
|
||||
{
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>("", await SerializeToValueAsync(Output.CreateSecret(new List<object> { true })));
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>(NoWarn, "", await SerializeToValueAsync(Output.CreateSecret(new List<object> { true })));
|
||||
|
||||
AssertEx.SequenceEqual(ImmutableArray<bool>.Empty.Add(true), data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -41,7 +41,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task ListWithSecretElement()
|
||||
{
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>("", await SerializeToValueAsync(new List<object> { Output.CreateSecret(true) }));
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>(NoWarn, "", await SerializeToValueAsync(new List<object> { Output.CreateSecret(true) }));
|
||||
|
||||
AssertEx.SequenceEqual(ImmutableArray<bool>.Empty.Add(true), data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
@ -51,7 +51,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task ListWithUnknownElement()
|
||||
{
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>("", await SerializeToValueAsync(new List<object> { Output<bool>.CreateUnknown(true) }));
|
||||
var data = Converter.ConvertValue<ImmutableArray<bool>>(NoWarn, "", await SerializeToValueAsync(new List<object> { Output<bool>.CreateUnknown(true) }));
|
||||
|
||||
AssertEx.SequenceEqual(ImmutableArray<bool>.Empty.Add(false), data.Value);
|
||||
Assert.False(data.IsKnown);
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void SimpleCase()
|
||||
{
|
||||
var data = Converter.ConvertValue<RecursiveType>("", new Value
|
||||
var data = Converter.ConvertValue<RecursiveType>(NoWarn, "", new Value
|
||||
{
|
||||
StructValue = new Struct
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void T0()
|
||||
{
|
||||
var data = Converter.ConvertValue<Union<int, string>>("", new Value { NumberValue = 1 });
|
||||
var data = Converter.ConvertValue<Union<int, string>>(NoWarn, "", new Value { NumberValue = 1 });
|
||||
Assert.True(data.Value.IsT0);
|
||||
Assert.True(data.IsKnown);
|
||||
Assert.Equal(1, data.Value.AsT0);
|
||||
|
@ -24,7 +24,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public void T1()
|
||||
{
|
||||
var data = Converter.ConvertValue<Union<int, string>>("", new Value { StringValue = "foo" });
|
||||
var data = Converter.ConvertValue<Union<int, string>>(NoWarn, "", new Value { StringValue = "foo" });
|
||||
Assert.True(data.Value.IsT1);
|
||||
Assert.True(data.IsKnown);
|
||||
Assert.Equal("foo", data.Value.AsT1);
|
||||
|
@ -33,7 +33,7 @@ namespace Pulumi.Tests.Serialization
|
|||
[Fact]
|
||||
public async Task MixedList()
|
||||
{
|
||||
var data = Converter.ConvertValue<ImmutableArray<Union<int, string>>>("",
|
||||
var data = Converter.ConvertValue<ImmutableArray<Union<int, string>>>(NoWarn, "",
|
||||
await SerializeToValueAsync(new List<object> { 1, "foo" }));
|
||||
Assert.True(data.IsKnown);
|
||||
Assert.Equal(2, data.Value.Length);
|
||||
|
@ -46,12 +46,16 @@ namespace Pulumi.Tests.Serialization
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void WrongTypeThrows()
|
||||
public void WrongTypeLogs()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
Converter.ConvertValue<Union<int, string>>("", new Value { BoolValue = true });
|
||||
});
|
||||
string? loggedError = null;
|
||||
Action<string> warn = error => loggedError = error;
|
||||
var data = Converter.ConvertValue<Union<int, string>>(warn, "", new Value { BoolValue = true });
|
||||
|
||||
Assert.Equal(default(Union<int, string>), data.Value);
|
||||
Assert.True(data.IsKnown);
|
||||
|
||||
Assert.Equal("Expected System.Int32 or System.String but got System.Boolean deserializing ", loggedError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Pulumi
|
|||
var (result, deps) = await CallRawAsync(token, args, self, options).ConfigureAwait(false);
|
||||
if (convertResult)
|
||||
{
|
||||
var converted = Converter.ConvertValue<T>($"{token} result", new Value { StructValue = result });
|
||||
var converted = Converter.ConvertValue<T>(err => Log.Warn(err, self), $"{token} result", new Value { StructValue = result });
|
||||
return new OutputData<T>(deps, converted.Value, converted.IsKnown, converted.IsSecret);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace Pulumi
|
|||
// tracking, which is a good future direction also for
|
||||
// `Invoke`.
|
||||
var result = await InvokeRawAsync(token, args, options).ConfigureAwait(false);
|
||||
var data = Converter.ConvertValue<T>($"{token} result",
|
||||
var data = Converter.ConvertValue<T>(err => Log.Warn(err), $"{token} result",
|
||||
new Value { StructValue = result.Serialized });
|
||||
var resources = ImmutableHashSet.CreateRange(
|
||||
result.PropertyToDependentResources.Values.SelectMany(r => r)
|
||||
|
@ -77,7 +77,7 @@ namespace Pulumi
|
|||
return default!;
|
||||
}
|
||||
|
||||
var data = Converter.ConvertValue<T>($"{token} result", new Value { StructValue = result.Serialized });
|
||||
var data = Converter.ConvertValue<T>(err => Log.Warn(err), $"{token} result", new Value { StructValue = result.Serialized });
|
||||
return data.Value;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace Pulumi
|
|||
dependencies = ImmutableHashSet<Resource>.Empty;
|
||||
}
|
||||
|
||||
var converted = Converter.ConvertValue($"{resource.GetType().FullName}.{fieldName}", value,
|
||||
var converted = Converter.ConvertValue(err => Log.Warn(err, resource), $"{resource.GetType().FullName}.{fieldName}", value,
|
||||
completionSource.TargetType, dependencies);
|
||||
completionSource.SetValue(converted);
|
||||
}
|
||||
|
|
|
@ -17,38 +17,41 @@ namespace Pulumi.Serialization
|
|||
{
|
||||
internal static class Converter
|
||||
{
|
||||
public static OutputData<T> ConvertValue<T>(string context, Value value)
|
||||
public static OutputData<T> ConvertValue<T>(Action<string> warn, string context, Value value)
|
||||
{
|
||||
var (data, isKnown, isSecret) = ConvertValue(context, value, typeof(T));
|
||||
return new OutputData<T>(ImmutableHashSet<Resource>.Empty, (T)data!, isKnown, isSecret);
|
||||
var (data, isKnown, isSecret) = ConvertValue(warn, context, value, typeof(T));
|
||||
var result = data == null ? default(T)! : (T)data;
|
||||
return new OutputData<T>(ImmutableHashSet<Resource>.Empty, result!, isKnown, isSecret);
|
||||
}
|
||||
|
||||
public static OutputData<object?> ConvertValue(string context, Value value, Type targetType)
|
||||
public static OutputData<object?> ConvertValue(Action<string> warn, string context, Value value, Type targetType)
|
||||
{
|
||||
return ConvertValue(context, value, targetType, ImmutableHashSet<Resource>.Empty);
|
||||
return ConvertValue(warn, context, value, targetType, ImmutableHashSet<Resource>.Empty);
|
||||
}
|
||||
|
||||
public static OutputData<object?> ConvertValue(
|
||||
string context, Value value, Type targetType, ImmutableHashSet<Resource> resources)
|
||||
Action<string> warn, string context, Value value, Type targetType, ImmutableHashSet<Resource> resources)
|
||||
{
|
||||
CheckTargetType(context, targetType, new HashSet<Type>());
|
||||
|
||||
var (deserialized, isKnown, isSecret) = Deserializer.Deserialize(value);
|
||||
var converted = ConvertObject(context, deserialized, targetType);
|
||||
var converted = ConvertObject(warn, context, deserialized, targetType);
|
||||
|
||||
return new OutputData<object?>(resources, converted, isKnown, isSecret);
|
||||
}
|
||||
|
||||
private static object? ConvertObject(string context, object? val, Type targetType)
|
||||
private static object? ConvertObject(Action<string> warn, string context, object? val, Type targetType)
|
||||
{
|
||||
var (result, exception) = TryConvertObject(context, val, targetType);
|
||||
if (exception != null)
|
||||
throw exception;
|
||||
var (result, error) = TryConvertObject(warn, context, val, targetType);
|
||||
if (error != null)
|
||||
{
|
||||
warn(error);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertObject(string context, object? val, Type targetType)
|
||||
private static (object?, string?) TryConvertObject(Action<string> warn, string context, object? val, Type targetType)
|
||||
{
|
||||
var targetIsNullable = targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
|
||||
|
@ -75,7 +78,7 @@ namespace Pulumi.Serialization
|
|||
|
||||
// We're not null and we're converting to Nullable<T>, just convert our value to be a T.
|
||||
if (targetIsNullable)
|
||||
return TryConvertObject(context, val, targetType.GenericTypeArguments.Single());
|
||||
return TryConvertObject(warn, context, val, targetType.GenericTypeArguments.Single());
|
||||
|
||||
if (targetType == typeof(string))
|
||||
return TryEnsureType<string>(context, val);
|
||||
|
@ -131,7 +134,7 @@ namespace Pulumi.Serialization
|
|||
if (targetType.IsEnum)
|
||||
{
|
||||
var underlyingType = targetType.GetEnumUnderlyingType();
|
||||
var (value, exception) = TryConvertObject(context, val, underlyingType);
|
||||
var (value, exception) = TryConvertObject(warn, context, val, underlyingType);
|
||||
if (exception != null || value is null)
|
||||
return (null, exception);
|
||||
|
||||
|
@ -144,16 +147,16 @@ namespace Pulumi.Serialization
|
|||
if (valType != typeof(string) &&
|
||||
valType != typeof(double))
|
||||
{
|
||||
return (null, new InvalidOperationException(
|
||||
$"Expected {typeof(string).FullName} or {typeof(double).FullName} but got {valType.FullName} deserializing {context}"));
|
||||
return (null,
|
||||
$"Expected {typeof(string).FullName} or {typeof(double).FullName} but got {valType.FullName} deserializing {context}");
|
||||
}
|
||||
|
||||
var enumTypeConstructor = targetType.GetConstructor(
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { valType }, null);
|
||||
if (enumTypeConstructor == null)
|
||||
{
|
||||
return (null, new InvalidOperationException(
|
||||
$"Expected target type {targetType.FullName} to have a constructor with a single {valType.FullName} parameter."));
|
||||
return (null,
|
||||
$"Expected target type {targetType.FullName} to have a constructor with a single {valType.FullName} parameter.");
|
||||
}
|
||||
return (enumTypeConstructor.Invoke(new[] { val }), null);
|
||||
}
|
||||
|
@ -161,26 +164,25 @@ namespace Pulumi.Serialization
|
|||
if (targetType.IsConstructedGenericType)
|
||||
{
|
||||
if (targetType.GetGenericTypeDefinition() == typeof(Union<,>))
|
||||
return TryConvertOneOf(context, val, targetType);
|
||||
return TryConvertOneOf(warn, context, val, targetType);
|
||||
|
||||
if (targetType.GetGenericTypeDefinition() == typeof(ImmutableArray<>))
|
||||
return TryConvertArray(context, val, targetType);
|
||||
|
||||
return TryConvertArray(warn, context, val, targetType);
|
||||
|
||||
if (targetType.GetGenericTypeDefinition() == typeof(ImmutableDictionary<,>))
|
||||
return TryConvertDictionary(context, val, targetType);
|
||||
|
||||
return TryConvertDictionary(warn, context, val, targetType);
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"Unexpected generic target type {targetType.FullName} when deserializing {context}");
|
||||
}
|
||||
|
||||
if (targetType.GetCustomAttribute<OutputTypeAttribute>() == null)
|
||||
return (null, new InvalidOperationException(
|
||||
$"Unexpected target type {targetType.FullName} when deserializing {context}"));
|
||||
return (null, $"Unexpected target type {targetType.FullName} when deserializing {context}");
|
||||
|
||||
var constructor = GetPropertyConstructor(targetType);
|
||||
if (constructor == null)
|
||||
return (null, new InvalidOperationException(
|
||||
$"Expected target type {targetType.FullName} to have [{nameof(OutputConstructorAttribute)}] constructor when deserializing {context}"));
|
||||
return (null,
|
||||
$"Expected target type {targetType.FullName} to have [{nameof(OutputConstructorAttribute)}] constructor when deserializing {context}");
|
||||
|
||||
var (dictionary, tempException) = TryEnsureType<ImmutableDictionary<string, object>>(context, val);
|
||||
if (tempException != null)
|
||||
|
@ -197,25 +199,22 @@ namespace Pulumi.Serialization
|
|||
// unknown vals. That's ok. We'll pass that through to 'Convert' and will get the
|
||||
// default value needed for the parameter type.
|
||||
dictionary!.TryGetValue(parameter.Name!, out var argValue);
|
||||
var (temp, tempException1) = TryConvertObject($"{targetType.FullName}({parameter.Name})", argValue, parameter.ParameterType);
|
||||
if (tempException1 != null)
|
||||
return (null, tempException1);
|
||||
|
||||
arguments[i] = temp;
|
||||
arguments[i] = ConvertObject(warn, $"{targetType.FullName}({parameter.Name})", argValue, parameter.ParameterType);
|
||||
}
|
||||
|
||||
return (constructor.Invoke(arguments), null);
|
||||
}
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertJsonElement(
|
||||
private static (object?, string?) TryConvertJsonElement(
|
||||
string context, object val)
|
||||
{
|
||||
using var stream = new MemoryStream();
|
||||
using (var writer = new Utf8JsonWriter(stream))
|
||||
{
|
||||
var exception = TryWriteJson(context, writer, val);
|
||||
if (exception != null)
|
||||
return (null, exception);
|
||||
var error = TryWriteJson(context, writer, val);
|
||||
if (error != null)
|
||||
return (null, error);
|
||||
}
|
||||
|
||||
stream.Position = 0;
|
||||
|
@ -224,7 +223,7 @@ namespace Pulumi.Serialization
|
|||
return (element, null);
|
||||
}
|
||||
|
||||
private static InvalidOperationException? TryWriteJson(string context, Utf8JsonWriter writer, object? val)
|
||||
private static string? TryWriteJson(string context, Utf8JsonWriter writer, object? val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
|
@ -262,41 +261,42 @@ namespace Pulumi.Serialization
|
|||
writer.WriteEndObject();
|
||||
return null;
|
||||
default:
|
||||
return new InvalidOperationException($"Unexpected type {val.GetType().FullName} when converting {context} to {nameof(JsonElement)}");
|
||||
return $"Unexpected type {val.GetType().FullName} when converting {context} to {nameof(JsonElement)}";
|
||||
}
|
||||
}
|
||||
|
||||
private static (T, InvalidOperationException?) TryEnsureType<T>(string context, object val)
|
||||
=> val is T t ? (t, null) : (default(T)!, new InvalidOperationException($"Expected {typeof(T).FullName} but got {val.GetType().FullName} deserializing {context}"));
|
||||
private static (T, string?) TryEnsureType<T>(string context, object val)
|
||||
=> val is T t ? (t, null) : (default(T)!, $"Expected {typeof(T).FullName} but got {val.GetType().FullName} deserializing {context}");
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertOneOf(string context, object val, Type oneOfType)
|
||||
private static (object?, string?) TryConvertOneOf(Action<string> warn, string context, object val, Type oneOfType)
|
||||
{
|
||||
var firstType = oneOfType.GenericTypeArguments[0];
|
||||
var secondType = oneOfType.GenericTypeArguments[1];
|
||||
|
||||
var (val1, exception1) = TryConvertObject($"{context}.AsT0", val, firstType);
|
||||
var (val1, exception1) = TryConvertObject(warn, $"{context}.AsT0", val, firstType);
|
||||
if (exception1 == null)
|
||||
{
|
||||
var fromT0Method = oneOfType.GetMethod(nameof(Union<int, int>.FromT0), BindingFlags.Public | BindingFlags.Static);
|
||||
return (fromT0Method?.Invoke(null, new[] { val1 }), null);
|
||||
}
|
||||
|
||||
var (val2, exception2) = TryConvertObject($"{context}.AsT1", val, secondType);
|
||||
var (val2, exception2) = TryConvertObject(warn, $"{context}.AsT1", val, secondType);
|
||||
if (exception2 == null)
|
||||
{
|
||||
var fromT1Method = oneOfType.GetMethod(nameof(Union<int, int>.FromT1), BindingFlags.Public | BindingFlags.Static);
|
||||
return (fromT1Method?.Invoke(null, new[] { val2 }), null);
|
||||
}
|
||||
|
||||
return (null, new InvalidOperationException($"Expected {firstType.FullName} or {secondType.FullName} but got {val.GetType().FullName} deserializing {context}"));
|
||||
return (null, $"Expected {firstType.FullName} or {secondType.FullName} but got {val.GetType().FullName} deserializing {context}");
|
||||
}
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertArray(
|
||||
private static (object?, string?) TryConvertArray(
|
||||
Action<string> warn,
|
||||
string fieldName, object val, Type targetType)
|
||||
{
|
||||
if (!(val is ImmutableArray<object> array))
|
||||
return (null, new InvalidOperationException(
|
||||
$"Expected {typeof(ImmutableArray<object>).FullName} but got {val.GetType().FullName} deserializing {fieldName}"));
|
||||
return (null,
|
||||
$"Expected {typeof(ImmutableArray<object>).FullName} but got {val.GetType().FullName} deserializing {fieldName}");
|
||||
|
||||
var builder =
|
||||
typeof(ImmutableArray).GetMethod(nameof(ImmutableArray.CreateBuilder), Array.Empty<Type>())!
|
||||
|
@ -309,9 +309,7 @@ namespace Pulumi.Serialization
|
|||
var elementType = targetType.GenericTypeArguments.Single();
|
||||
foreach (var element in array)
|
||||
{
|
||||
var (e, exception) = TryConvertObject(fieldName, element, elementType);
|
||||
if (exception != null)
|
||||
return (null, exception);
|
||||
var e = ConvertObject(warn, fieldName, element, elementType);
|
||||
|
||||
builderAdd.Invoke(builder, new[] { e });
|
||||
}
|
||||
|
@ -319,12 +317,13 @@ namespace Pulumi.Serialization
|
|||
return (builderToImmutable.Invoke(builder, null), null);
|
||||
}
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertDictionary(
|
||||
private static (object?, string?) TryConvertDictionary(
|
||||
Action<string> warn,
|
||||
string fieldName, object val, Type targetType)
|
||||
{
|
||||
if (!(val is ImmutableDictionary<string, object> dictionary))
|
||||
return (null, new InvalidOperationException(
|
||||
$"Expected {typeof(ImmutableDictionary<string, object>).FullName} but got {val.GetType().FullName} deserializing {fieldName}"));
|
||||
return (null,
|
||||
$"Expected {typeof(ImmutableDictionary<string, object>).FullName} but got {val.GetType().FullName} deserializing {fieldName}");
|
||||
|
||||
// check if already in the form we need. no need to convert anything.
|
||||
if (targetType == typeof(ImmutableDictionary<string, object>))
|
||||
|
@ -332,25 +331,21 @@ namespace Pulumi.Serialization
|
|||
|
||||
var keyType = targetType.GenericTypeArguments[0];
|
||||
if (keyType != typeof(string))
|
||||
return (null, new InvalidOperationException(
|
||||
$"Unexpected type {targetType.FullName} when deserializing {fieldName}. ImmutableDictionary's TKey type was not {typeof(string).FullName}"));
|
||||
return (null,
|
||||
$"Unexpected type {targetType.FullName} when deserializing {fieldName}. ImmutableDictionary's TKey type was not {typeof(string).FullName}");
|
||||
|
||||
var builder =
|
||||
typeof(ImmutableDictionary).GetMethod(nameof(ImmutableDictionary.CreateBuilder), Array.Empty<Type>())!
|
||||
.MakeGenericMethod(targetType.GenericTypeArguments)
|
||||
.Invoke(obj: null, parameters: null)!;
|
||||
|
||||
// var b = ImmutableDictionary.CreateBuilder<string, object>().Add()
|
||||
|
||||
var builderAdd = builder.GetType().GetMethod(nameof(ImmutableDictionary<string, object>.Builder.Add), targetType.GenericTypeArguments)!;
|
||||
var builderToImmutable = builder.GetType().GetMethod(nameof(ImmutableDictionary<string, object>.Builder.ToImmutable))!;
|
||||
|
||||
var elementType = targetType.GenericTypeArguments[1];
|
||||
foreach (var (key, element) in dictionary)
|
||||
{
|
||||
var (e, exception) = TryConvertObject(fieldName, element, elementType);
|
||||
if (exception != null)
|
||||
return (null, exception);
|
||||
var e = ConvertObject(warn, fieldName, element, elementType);
|
||||
|
||||
builderAdd.Invoke(builder, new[] { key, e });
|
||||
}
|
||||
|
|
|
@ -624,7 +624,7 @@ export async function getAllTransitivelyReferencedResourceURNs(resources: Set<Re
|
|||
// Then the transitively reachable resources of Comp1 will be [Cust1, Cust2, Cust3, Remote1].
|
||||
// It will *not* include:
|
||||
// * Cust4 because it is a child of a custom resource
|
||||
// * Comp2 because it is a non-remote component resoruce
|
||||
// * Comp2 because it is a non-remote component resource
|
||||
// * Comp3 and Cust5 because Comp3 is a child of a remote component resource
|
||||
|
||||
// To do this, first we just get the transitively reachable set of resources (not diving
|
||||
|
|
|
@ -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.
|
||||
|
@ -69,7 +69,7 @@ def is_custom_timeouts(obj: Any) -> 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)
|
||||
|
|
|
@ -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.
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue