Ejemplo n.º 1
0
        public void InvokeBasicFunctionWithTriggerMetadataAndTraceContextWorks()
        {
            string path = Path.Join(s_funcDirectory, "testBasicFunctionWithTriggerMetadata.ps1");

            var(functionInfo, testManager) = PrepareFunction(path, string.Empty);

            Hashtable triggerMetadata = new Hashtable(StringComparer.OrdinalIgnoreCase)
            {
                { TestInputBindingName, TestStringData }
            };

            try
            {
                FunctionMetadata.RegisterFunctionMetadata(testManager.InstanceId, functionInfo);

                Hashtable result = InvokeFunction(testManager, functionInfo, triggerMetadata);

                // The outputBinding hashtable for the runspace should be cleared after 'InvokeFunction'
                Hashtable outputBindings = FunctionMetadata.GetOutputBindingHashtable(testManager.InstanceId);
                Assert.Empty(outputBindings);

                // A PowerShell function should be created fro the Az function.
                string expectedResult = $"{TestStringData},{functionInfo.DeployedPSFuncName}";
                Assert.Equal(expectedResult, result[TestOutputBindingName]);
            }
            finally
            {
                FunctionMetadata.UnregisterFunctionMetadata(testManager.InstanceId);
            }
        }
Ejemplo n.º 2
0
        public void InvokeBasicFunctionWithRequiresWorks()
        {
            string path = Path.Join(s_funcDirectory, "testBasicFunctionWithRequires.ps1");

            var(functionInfo, testManager) = PrepareFunction(path, string.Empty);

            try
            {
                FunctionMetadata.RegisterFunctionMetadata(testManager.InstanceId, functionInfo);
                Hashtable result = InvokeFunction(testManager, functionInfo);

                // The outputBinding hashtable for the runspace should be cleared after 'InvokeFunction'
                Hashtable outputBindings = FunctionMetadata.GetOutputBindingHashtable(testManager.InstanceId);
                Assert.Empty(outputBindings);

                // When function script has #requires, not PowerShell function will be created for the Az function,
                // and the invocation uses the file path directly.
                string expectedResult = $"{TestStringData},ThreadJob,testBasicFunctionWithRequires.ps1";
                Assert.Equal(expectedResult, result[TestOutputBindingName]);
            }
            finally
            {
                FunctionMetadata.UnregisterFunctionMetadata(testManager.InstanceId);
            }
        }
        public Hashtable InvokeFunction(
            AzFunctionInfo functionInfo,
            Hashtable triggerMetadata,
            TraceContext traceContext,
            RetryContext retryContext,
            IList <ParameterBinding> inputData,
            FunctionInvocationPerformanceStopwatch stopwatch)
        {
            var outputBindings = FunctionMetadata.GetOutputBindingHashtable(_pwsh.Runspace.InstanceId);

            var durableController = new DurableController(functionInfo.DurableFunctionInfo, _pwsh);

            try
            {
                durableController.BeforeFunctionInvocation(inputData);

                AddEntryPointInvocationCommand(functionInfo);
                stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.FunctionCodeReady);

                SetInputBindingParameterValues(functionInfo, inputData, durableController, triggerMetadata, traceContext, retryContext);
                stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.InputBindingValuesReady);

                if (!durableController.ShouldSuppressPipelineTraces())
                {
                    _pwsh.AddCommand("Microsoft.Azure.Functions.PowerShellWorker\\Trace-PipelineObject");
                }

                stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.InvokingFunctionCode);
                Logger.Log(isUserOnlyLog: false, LogLevel.Trace, CreateInvocationPerformanceReportMessage(functionInfo.FuncName, stopwatch));

                try
                {
                    return(durableController.TryInvokeOrchestrationFunction(out var result)
                                ? result
                                : InvokeNonOrchestrationFunction(durableController, outputBindings));
                }
                catch (RuntimeException e)
                {
                    ErrorAnalysisLogger.Log(Logger, e.ErrorRecord, isException: true);
                    Logger.Log(isUserOnlyLog: true, LogLevel.Error, GetFunctionExceptionMessage(e));
                    throw;
                }
                catch (OrchestrationFailureException e)
                {
                    if (e.InnerException is IContainsErrorRecord inner)
                    {
                        Logger.Log(isUserOnlyLog: true, LogLevel.Error, GetFunctionExceptionMessage(inner));
                    }
                    throw;
                }
            }
            finally
            {
                durableController.AfterFunctionInvocation();
                outputBindings.Clear();
                ResetRunspace();
            }
        }
Ejemplo n.º 4
0
        public void InvokeFunctionWithEntryPointWorks()
        {
            string path = Path.Join(s_funcDirectory, "testFunctionWithEntryPoint.psm1");

            var(functionInfo, testManager) = PrepareFunction(path, "Run");

            try
            {
                FunctionMetadata.RegisterFunctionMetadata(testManager.InstanceId, functionInfo);
                Hashtable result = InvokeFunction(testManager, functionInfo);

                // The outputBinding hashtable for the runspace should be cleared after 'InvokeFunction'
                Hashtable outputBindings = FunctionMetadata.GetOutputBindingHashtable(testManager.InstanceId);
                Assert.Empty(outputBindings);

                string expectedResult = $"{TestStringData},Run";
                Assert.Equal(expectedResult, result[TestOutputBindingName]);
            }
            finally
            {
                FunctionMetadata.UnregisterFunctionMetadata(testManager.InstanceId);
            }
        }
Ejemplo n.º 5
0
        public void InvokeFunctionWithSpecialVariableWorks()
        {
            string path = Path.Join(s_funcDirectory, "testBasicFunctionSpecialVariables.ps1");

            var(functionInfo, testManager) = PrepareFunction(path, string.Empty);

            try
            {
                FunctionMetadata.RegisterFunctionMetadata(testManager.InstanceId, functionInfo);
                Hashtable result = InvokeFunction(testManager, functionInfo);

                // The outputBinding hashtable for the runspace should be cleared after 'InvokeFunction'
                Hashtable outputBindings = FunctionMetadata.GetOutputBindingHashtable(testManager.InstanceId);
                Assert.Empty(outputBindings);

                // A PowerShell function should be created fro the Az function.
                string expectedResult = $"{s_funcDirectory},{path},{functionInfo.DeployedPSFuncName}";
                Assert.Equal(expectedResult, result[TestOutputBindingName]);
            }
            finally
            {
                FunctionMetadata.UnregisterFunctionMetadata(testManager.InstanceId);
            }
        }
        /// <summary>
        /// Execution a function fired by a trigger or an activity function scheduled by an orchestration.
        /// </summary>
        internal Hashtable InvokeFunction(
            AzFunctionInfo functionInfo,
            Hashtable triggerMetadata,
            TraceContext traceContext,
            IList <ParameterBinding> inputData,
            FunctionInvocationPerformanceStopwatch stopwatch)
        {
            string scriptPath = functionInfo.ScriptPath;
            string entryPoint = functionInfo.EntryPoint;
            var    hasSetInvocationContext = false;

            Hashtable outputBindings = FunctionMetadata.GetOutputBindingHashtable(_pwsh.Runspace.InstanceId);

            try
            {
                if (Utils.AreDurableFunctionsEnabled())
                {
                    // If the function has a output binding of the 'orchestrationClient' type, then we set the binding name
                    // in the module context for the 'Start-NewOrchestration' function to use.
                    if (!string.IsNullOrEmpty(functionInfo.OrchestrationClientBindingName))
                    {
                        _pwsh.AddCommand("Microsoft.Azure.Functions.PowerShellWorker\\Set-FunctionInvocationContext")
                        .AddParameter("OrchestrationStarter", functionInfo.OrchestrationClientBindingName)
                        .InvokeAndClearCommands();
                        hasSetInvocationContext = true;
                    }
                }

                if (string.IsNullOrEmpty(entryPoint))
                {
                    _pwsh.AddCommand(functionInfo.DeployedPSFuncName ?? scriptPath);
                }
                else
                {
                    // If an entry point is defined, we import the script module.
                    _pwsh.AddCommand(Utils.ImportModuleCmdletInfo)
                    .AddParameter("Name", scriptPath)
                    .InvokeAndClearCommands();

                    _pwsh.AddCommand(entryPoint);
                }

                stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.FunctionCodeReady);

                // Set arguments for each input binding parameter
                foreach (ParameterBinding binding in inputData)
                {
                    string bindingName = binding.Name;
                    if (functionInfo.FuncParameters.TryGetValue(bindingName, out PSScriptParamInfo paramInfo))
                    {
                        var bindingInfo = functionInfo.InputBindings[bindingName];
                        var valueToUse  = Utils.TransformInBindingValueAsNeeded(paramInfo, bindingInfo, binding.Data.ToObject());
                        _pwsh.AddParameter(bindingName, valueToUse);
                    }
                }

                stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.InputBindingValuesReady);

                // Gives access to additional Trigger Metadata if the user specifies TriggerMetadata
                if (functionInfo.HasTriggerMetadataParam)
                {
                    _pwsh.AddParameter(AzFunctionInfo.TriggerMetadata, triggerMetadata);
                }
                if (functionInfo.HasTraceContextParam)
                {
                    _pwsh.AddParameter(AzFunctionInfo.TraceContext, traceContext);
                }

                _pwsh.AddCommand("Microsoft.Azure.Functions.PowerShellWorker\\Trace-PipelineObject");

                stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.InvokingFunctionCode);

                Logger.Log(isUserOnlyLog: false, LogLevel.Trace, CreateInvocationPerformanceReportMessage(functionInfo.FuncName, stopwatch));

                Collection <object> pipelineItems = null;

                try
                {
                    pipelineItems = _pwsh.InvokeAndClearCommands <object>();
                }
                catch (RuntimeException e)
                {
                    if (e.ErrorRecord.FullyQualifiedErrorId == "CommandNotFoundException")
                    {
                        Logger.Log(isUserOnlyLog: false, LogLevel.Warning, PowerShellWorkerStrings.CommandNotFoundException_Exception);
                    }

                    Logger.Log(isUserOnlyLog: true, LogLevel.Error, GetFunctionExceptionMessage(e));
                    throw;
                }

                Hashtable result = new Hashtable(outputBindings, StringComparer.OrdinalIgnoreCase);

                if (Utils.AreDurableFunctionsEnabled() && functionInfo.Type == AzFunctionType.ActivityFunction)
                {
                    var returnValue = CreateReturnValueFromFunctionOutput(pipelineItems);
                    result.Add(AzFunctionInfo.DollarReturn, returnValue);
                }

                return(result);
            }
            finally
            {
                if (hasSetInvocationContext)
                {
                    ClearInvocationContext();
                }

                outputBindings.Clear();
                ResetRunspace();
            }
        }
Ejemplo n.º 7
0
 /// <summary>
 /// BeginProcessing override.
 /// </summary>
 protected override void BeginProcessing()
 {
     _retHashtable   = new Hashtable(StringComparer.OrdinalIgnoreCase);
     _outputBindings = FunctionMetadata.GetOutputBindingHashtable(Runspace.DefaultRunspace.InstanceId);
 }
        /// <summary>
        /// Execution a function fired by a trigger or an activity function scheduled by an orchestration.
        /// </summary>
        internal Hashtable InvokeFunction(
            AzFunctionInfo functionInfo,
            Hashtable triggerMetadata,
            IList <ParameterBinding> inputData)
        {
            string scriptPath = functionInfo.ScriptPath;
            string entryPoint = functionInfo.EntryPoint;

            Hashtable outputBindings = FunctionMetadata.GetOutputBindingHashtable(_pwsh.Runspace.InstanceId);

            try
            {
                if (string.IsNullOrEmpty(entryPoint))
                {
                    _pwsh.AddCommand(functionInfo.DeployedPSFuncName ?? scriptPath);
                }
                else
                {
                    // If an entry point is defined, we import the script module.
                    _pwsh.AddCommand(Utils.ImportModuleCmdletInfo)
                    .AddParameter("Name", scriptPath)
                    .InvokeAndClearCommands();

                    _pwsh.AddCommand(entryPoint);
                }

                // Set arguments for each input binding parameter
                foreach (ParameterBinding binding in inputData)
                {
                    string bindingName = binding.Name;
                    if (functionInfo.FuncParameters.TryGetValue(bindingName, out PSScriptParamInfo paramInfo))
                    {
                        var bindingInfo = functionInfo.InputBindings[bindingName];
                        var valueToUse  = Utils.TransformInBindingValueAsNeeded(paramInfo, bindingInfo, binding.Data.ToObject());
                        _pwsh.AddParameter(bindingName, valueToUse);
                    }
                }

                // Gives access to additional Trigger Metadata if the user specifies TriggerMetadata
                if (functionInfo.HasTriggerMetadataParam)
                {
                    _pwsh.AddParameter(AzFunctionInfo.TriggerMetadata, triggerMetadata);
                }

                Collection <object> pipelineItems = _pwsh.AddCommand("Microsoft.Azure.Functions.PowerShellWorker\\Trace-PipelineObject")
                                                    .InvokeAndClearCommands <object>();

                Hashtable result = new Hashtable(outputBindings, StringComparer.OrdinalIgnoreCase);

                /*
                 * TODO: See GitHub issue #82. We are not settled on how to handle the Azure Functions concept of the $returns Output Binding
                 * if (pipelineItems != null && pipelineItems.Count > 0)
                 * {
                 *  // If we would like to support Option 1 from #82, use the following 3 lines of code:
                 *  object[] items = new object[pipelineItems.Count];
                 *  pipelineItems.CopyTo(items, 0);
                 *  result.Add(AzFunctionInfo.DollarReturn, items);
                 *
                 *  // If we would like to support Option 2 from #82, use this line:
                 *  result.Add(AzFunctionInfo.DollarReturn, pipelineItems[pipelineItems.Count - 1]);
                 * }
                 */

                return(result);
            }
            finally
            {
                outputBindings.Clear();
                ResetRunspace();
            }
        }
 /// <summary>
 /// BeginProcessing override.
 /// </summary>
 protected override void BeginProcessing()
 {
     _bindingInfo    = GetBindingInfo(Name);
     _behavior       = GetDataCollectingBehavior(_bindingInfo);
     _outputBindings = FunctionMetadata.GetOutputBindingHashtable(Runspace.DefaultRunspace.InstanceId);
 }