예제 #1
0
        private async Task <T> InvokeAsync <T>(
            string token, InvokeArgs args, InvokeOptions?options, bool convertResult)
        {
            var result = await InvokeRawAsync(token, args, options);

            if (!convertResult)
            {
                return(default !);
예제 #2
0
        private async Task <OutputData <T> > RawInvoke <T>(string token, InvokeArgs args, InvokeOptions?options)
        {
            // This method backs all `Fn.Invoke()` calls that generate
            // `Output<T>` and may include `Input<T>` values in the
            // `args`. It needs to decide which control-flow tracking
            // features are supported in the SDK and which ones in the
            // provider implementing the invoke logic.
            //
            // Current choices are:
            //
            // - any resource dependency found by a recursive
            //   traversal of `args` that awaits and inspects every
            //   `Input<T>` will always be propagated into the
            //   `Output<T>`; the provider cannot "swallow"
            //   dependencies
            //
            // - the provider is responsible for deciding whether the
            //   `Output<T>` is secret and known, and may add
            //   additional dependencies
            //
            // This means that presence of secrets or unknowns in the
            // `args` does not guarantee the result is secret or
            // unknown, which differs from Pulumi SDKs that choose to
            // implement these invokes via `Apply` (currently Go and
            // Python).
            //
            // Differences from `Call`: the `Invoke` gRPC protocol
            // does not yet support passing or returning out-of-band
            // dependencies to the provider, and in-band `Resource`
            // value support is subject to feature negotiation (see
            // `MonitorSupportsResourceReferences`). So `Call` makes
            // the provider fully responsible for depdendency
            // 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",
                                                  new Value {
                StructValue = result.Serialized
            });
            var resources = ImmutableHashSet.CreateRange(
                result.PropertyToDependentResources.Values.SelectMany(r => r)
                .Union(data.Resources));

            return(new OutputData <T>(resources: resources,
                                      value: data.Value,
                                      isKnown: data.IsKnown,
                                      isSecret: data.IsSecret));
        }
예제 #3
0
        private async Task <T> InvokeAsync <T>(
            string token, InvokeArgs args, InvokeOptions?options, bool convertResult)
        {
            var label = $"Invoking function: token={token} asynchronously";

            Log.Debug(label);

            // Be resilient to misbehaving callers.
            args ??= InvokeArgs.Empty;

            // Wait for all values to be available, and then perform the RPC.
            var argsDict = await args.ToDictionaryAsync().ConfigureAwait(false);

            var serialized = await SerializeAllPropertiesAsync(
                $"invoke:{token}",
                argsDict, await this.MonitorSupportsResourceReferences().ConfigureAwait(false)).ConfigureAwait(false);

            Log.Debug($"Invoke RPC prepared: token={token}" +
                      (_excessiveDebugOutput ? $", obj={serialized}" : ""));

            var provider = await ProviderResource.RegisterAsync(GetProvider(token, options)).ConfigureAwait(false);

            var result = await this.Monitor.InvokeAsync(new InvokeRequest
            {
                Tok      = token,
                Provider = provider ?? "",
                Version  = options?.Version ?? "",
                Args     = serialized,
            });

            if (result.Failures.Count > 0)
            {
                var reasons = "";
                foreach (var reason in result.Failures)
                {
                    if (reasons != "")
                    {
                        reasons += "; ";
                    }

                    reasons += $"{reason.Reason} ({reason.Property})";
                }

                throw new InvokeException($"Invoke of '{token}' failed: {reasons}");
            }

            if (!convertResult)
            {
                return(default !);
예제 #4
0
        private async Task <OutputData <T> > RawInvoke <T>(string token, InvokeArgs args, InvokeOptions?options)
        {
            // This method backs all `Fn.Invoke()` calls that generate
            // `Output<T>` and may include `Input<T>` values in the
            // `args`. It needs to decide which control-flow tracking
            // features are supported in the SDK and which ones in the
            // provider implementing the invoke logic.
            //
            // Current choices are:
            //
            // - any resource dependency found by a recursive
            //   traversal of `args` that awaits and inspects every
            //   `Input<T>` will always be propagated into the
            //   `Output<T>`; the provider cannot "swallow"
            //   dependencies
            //
            // - the provider is responsible for deciding whether the
            //   `Output<T>` is secret and known, and may add
            //   additional dependencies
            //
            // This means that presence of secrets or unknowns in the
            // `args` does not guarantee the result is secret or
            // unknown, which differs from Pulumi SDKs that choose to
            // implement these invokes via `Apply` (currently Go and
            // Python).
            //
            // Differences from `Call`: the `Invoke` gRPC protocol
            // does not yet support passing or returning out-of-band
            // dependencies to the provider, and in-band `Resource`
            // value support is subject to feature negotiation (see
            // `MonitorSupportsResourceReferences`). So `Call` makes
            // the provider fully responsible for depdendency
            // tracking, which is a good future direction also for
            // `Invoke`.

            var keepResources = await this.MonitorSupportsResourceReferences().ConfigureAwait(false);

            var serializedArgs = await SerializeInvokeArgs(token, args, keepResources);

            // Short-circuit actually invoking if `Unknowns` are
            // present in `args`, otherwise preview can break.
            if (Serializer.ContainsUnknowns(serializedArgs.PropertyValues))
            {
                return(new OutputData <T>(resources: ImmutableHashSet <Resource> .Empty,
                                          value: default !,
예제 #5
0
 Task <T> IDeployment.InvokeAsync <T>(string token, InvokeArgs args, InvokeOptions?options)
 => InvokeAsync <T>(token, args, options, convertResult: true);
예제 #6
0
 Task IDeployment.InvokeAsync(string token, InvokeArgs args, InvokeOptions?options)
 => InvokeAsync <object>(token, args, options, convertResult: false);
예제 #7
0
 Output <T> IDeployment.Invoke <T>(string token, InvokeArgs args, InvokeOptions?options)
 => new Output <T>(RawInvoke <T>(token, args, options));
예제 #8
0
 /// <summary>
 /// Same as <see cref="InvokeAsync{T}(string, InvokeArgs, InvokeOptions)"/>, however the
 /// return value is ignored.
 /// </summary>
 public Task InvokeAsync(string token, InvokeArgs args, InvokeOptions?options = null)
 => _deployment.InvokeAsync(token, args, options);
예제 #9
0
 /// <summary>
 /// Dynamically invokes the function '<paramref name="token"/>', which is offered by a
 /// provider plugin.
 /// <para/>
 /// The result of <see cref="Invoke"/> will be a <see cref="Output"/> resolved to the
 /// result value of the provider plugin.
 /// <para/>
 /// Similar to the earlier <see cref="InvokeAsync"/>, but supports passing input values
 /// and returns an Output value.
 /// <para/>
 /// The <paramref name="args"/> inputs can be a bag of computed values(including, `T`s,
 /// <see cref="Task{TResult}"/>s, <see cref="Output{T}"/>s etc.).
 /// </summary>
 public Output <T> Invoke <T>(string token, InvokeArgs args, InvokeOptions?options = null)
 => _deployment.Invoke <T>(token, args, options);