示例#1
0
        public FunctionLoaderTests()
        {
            _functionDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestScripts", "Function");

            var functionId = Guid.NewGuid().ToString();
            var metadata   = new RpcFunctionMetadata
            {
                Name      = "MyHttpTrigger",
                Directory = _functionDirectory,
                Bindings  =
                {
                    { "req",       new BindingInfo {
                          Direction = BindingInfo.Types.Direction.In, Type = "httpTrigger"
                      } },
                    { "inputBlob", new BindingInfo {
                          Direction = BindingInfo.Types.Direction.In, Type = "blobTrigger"
                      } },
                    { "res",       new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "http"
                      } }
                }
            };

            _functionLoadRequest = new FunctionLoadRequest
            {
                FunctionId = functionId,
                Metadata   = metadata
            };
        }
示例#2
0
        static PowerShellManagerTests()
        {
            s_funcDirectory = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "TestScripts", "PowerShell");
            s_testLogger    = new ConsoleLogger();
            s_testInputData = new List <ParameterBinding>
            {
                new ParameterBinding
                {
                    Name = TestInputBindingName,
                    Data = new TypedData {
                        String = TestStringData
                    }
                }
            };

            var rpcFunctionMetadata = new RpcFunctionMetadata()
            {
                Name      = "TestFuncApp",
                Directory = s_funcDirectory,
                Bindings  =
                {
                    { TestInputBindingName,  new BindingInfo {
                          Direction = BindingInfo.Types.Direction.In, Type = "httpTrigger"
                      } },
                    { TestOutputBindingName, new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "http"
                      } }
                }
            };

            s_functionLoadRequest = new FunctionLoadRequest {
                FunctionId = "FunctionId", Metadata = rpcFunctionMetadata
            };
            FunctionLoader.SetupWellKnownPaths(s_functionLoadRequest, managedDependenciesPath: null);
        }
示例#3
0
        private FunctionLoadRequest GetFuncLoadRequest(string functionAppRoot, bool managedDependencyEnabled)
        {
            var metadata = new RpcFunctionMetadata
            {
                Name      = "MyHttpTrigger",
                Directory = functionAppRoot
            };

            var functionLoadRequest = new FunctionLoadRequest
            {
                FunctionId = _functionId,
                Metadata   = metadata
            };

            functionLoadRequest.ManagedDependencyEnabled = managedDependencyEnabled;
            return(functionLoadRequest);
        }
        static TestUtils()
        {
            FunctionDirectory = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "TestScripts", "PowerShell");
            RpcFunctionMetadata = new RpcFunctionMetadata()
            {
                Name = "TestFuncApp",
                Directory = FunctionDirectory,
                Bindings =
                {
                    { TestInputBindingName , new BindingInfo { Direction = BindingInfo.Types.Direction.In, Type = "httpTrigger" } },
                    { TestOutputBindingName, new BindingInfo { Direction = BindingInfo.Types.Direction.Out, Type = "http" } }
                }
            };

            FunctionLoadRequest = new FunctionLoadRequest {FunctionId = "FunctionId", Metadata = RpcFunctionMetadata};
            FunctionLoader.SetupWellKnownPaths(FunctionLoadRequest);
        }
示例#5
0
        public void PublishWorkerMetadataResponse(string workerId, string functionId, IEnumerable <FunctionMetadata> functionMetadata, bool successful, bool useDefaultMetadataIndexing = false, bool overallStatus = true)
        {
            StatusResult statusResult = new StatusResult();

            if (successful)
            {
                statusResult.Status = StatusResult.Types.Status.Success;
            }
            else
            {
                statusResult.Status = StatusResult.Types.Status.Failure;
            }

            FunctionMetadataResponse overallResponse = new FunctionMetadataResponse();

            overallResponse.UseDefaultMetadataIndexing = useDefaultMetadataIndexing;

            if (functionMetadata != null)
            {
                foreach (FunctionMetadata response in functionMetadata)
                {
                    RpcFunctionMetadata indexingResponse = new RpcFunctionMetadata()
                    {
                        Name       = response.Name,
                        Language   = response.Language,
                        Status     = statusResult,
                        FunctionId = functionId
                    };

                    overallResponse.FunctionMetadataResults.Add(indexingResponse);
                }
            }

            overallResponse.Result = new StatusResult()
            {
                Status = overallStatus == true ? StatusResult.Types.Status.Success : StatusResult.Types.Status.Failure
            };

            StreamingMessage responseMessage = new StreamingMessage()
            {
                FunctionMetadataResponse = overallResponse
            };

            _eventManager.Publish(new InboundGrpcEvent(_workerId, responseMessage));
        }
        internal AzFunctionInfo(RpcFunctionMetadata metadata)
        {
            FunctionName = metadata.Name;
            Directory    = metadata.Directory;
            EntryPoint   = metadata.EntryPoint;
            ScriptPath   = metadata.ScriptFile;

            AllBindings    = new MapField <string, BindingInfo>();
            OutputBindings = new MapField <string, BindingInfo>();

            foreach (var binding in metadata.Bindings)
            {
                string      bindingName = binding.Key;
                BindingInfo bindingInfo = binding.Value;

                AllBindings.Add(bindingName, bindingInfo);

                // PowerShell doesn't support the 'InOut' type binding
                if (bindingInfo.Direction == BindingInfo.Types.Direction.In)
                {
                    switch (bindingInfo.Type)
                    {
                    case OrchestrationTrigger:
                        Type = AzFunctionType.OrchestrationFunction;
                        break;

                    case ActivityTrigger:
                        Type = AzFunctionType.ActivityFunction;
                        break;

                    default:
                        Type = AzFunctionType.RegularFunction;
                        break;
                    }
                    continue;
                }

                if (bindingInfo.Direction == BindingInfo.Types.Direction.Out)
                {
                    OutputBindings.Add(bindingName, bindingInfo);
                }
            }
        }
示例#7
0
        public void TestFunctionLoaderGetInfo()
        {
            var functionId         = Guid.NewGuid().ToString();
            var directory          = "/Users/tylerleonhardt/Desktop/Tech/PowerShell/AzureFunctions/azure-functions-powershell-worker/examples/PSCoreApp/MyHttpTrigger";
            var scriptPathExpected = $"{directory}/run.ps1";
            var name     = "MyHttpTrigger";
            var metadata = new RpcFunctionMetadata
            {
                Name       = name,
                EntryPoint = "",
                Directory  = directory,
                ScriptFile = scriptPathExpected
            };

            metadata.Bindings.Add("req", new BindingInfo
            {
                Direction = BindingInfo.Types.Direction.In,
                Type      = "httpTrigger"
            });
            metadata.Bindings.Add("res", new BindingInfo
            {
                Direction = BindingInfo.Types.Direction.Out,
                Type      = "http"
            });

            var functionLoadRequest = new FunctionLoadRequest {
                FunctionId = functionId,
                Metadata   = metadata
            };

            var functionLoader = new FunctionLoader();

            functionLoader.Load(functionLoadRequest);

            var funcInfo = functionLoader.GetFunctionInfo(functionId);

            Assert.Equal(directory, funcInfo.Directory);
            Assert.Equal(name, funcInfo.FunctionName);
            Assert.Equal(2, funcInfo.AllBindings.Count);
            Assert.Single(funcInfo.OutputBindings);
        }
        public FunctionInfo(RpcFunctionMetadata metadata)
        {
            FunctionName = metadata.Name;
            Directory    = metadata.Directory;
            EntryPoint   = metadata.EntryPoint;
            ScriptPath   = metadata.ScriptFile;

            AllBindings    = new MapField <string, BindingInfo>();
            OutputBindings = new MapField <string, BindingInfo>();

            foreach (var binding in metadata.Bindings)
            {
                AllBindings.Add(binding.Key, binding.Value);

                // PowerShell doesn't support the 'InOut' type binding
                if (binding.Value.Direction == BindingInfo.Types.Direction.Out)
                {
                    OutputBindings.Add(binding.Key, binding.Value);
                }
            }
        }
        static HelperModuleTests()
        {
            var funcDirectory   = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "TestScripts", "PowerShell");
            var rpcFuncMetadata = new RpcFunctionMetadata()
            {
                Name       = "TestFuncApp",
                Directory  = funcDirectory,
                ScriptFile = Path.Join(funcDirectory, "testBasicFunction.ps1"),
                EntryPoint = string.Empty,
                Bindings   =
                {
                    { "req",    new BindingInfo {
                          Direction = BindingInfo.Types.Direction.In, Type = "httpTrigger"
                      } },
                    { Response, new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "http"
                      } },
                    { Queue,    new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "queue"
                      } },
                    { Foo,      new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "new"
                      } },
                    { Bar,      new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "new"
                      } },
                    { Food,     new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "new"
                      } }
                }
            };

            var funcLoadReq = new FunctionLoadRequest {
                FunctionId = "FunctionId", Metadata = rpcFuncMetadata
            };

            FunctionLoader.SetupWellKnownPaths(funcLoadReq);
            s_pwsh     = Utils.NewPwshInstance();
            s_funcInfo = new AzFunctionInfo(rpcFuncMetadata);
        }
        public void TestFunctionLoaderGetFuncWithEntryPoint()
        {
            var functionId         = Guid.NewGuid().ToString();
            var directory          = "/Users/azure/PSCoreApp/MyHttpTrigger";
            var scriptPathExpected = $"{directory}/run.ps1";
            var entryPointExpected = "Foo";
            var metadata           = new RpcFunctionMetadata
            {
                Name       = "MyHttpTrigger",
                EntryPoint = entryPointExpected,
                Directory  = directory,
                ScriptFile = scriptPathExpected
            };

            metadata.Bindings.Add("req", new BindingInfo
            {
                Direction = BindingInfo.Types.Direction.In,
                Type      = "httpTrigger"
            });
            metadata.Bindings.Add("res", new BindingInfo
            {
                Direction = BindingInfo.Types.Direction.Out,
                Type      = "http"
            });

            var functionLoadRequest = new FunctionLoadRequest {
                FunctionId = functionId,
                Metadata   = metadata
            };

            var functionLoader = new FunctionLoader();

            functionLoader.Load(functionLoadRequest);

            var funcInfo = functionLoader.GetFunctionInfo(functionId);

            Assert.Equal(scriptPathExpected, funcInfo.ScriptPath);
            Assert.Equal(entryPointExpected, funcInfo.EntryPoint);
        }
        public PowerShellManagerTests()
        {
            _functionDirectory   = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "TestScripts", "PowerShell");
            _rpcFunctionMetadata = new RpcFunctionMetadata()
            {
                Name      = "TestFuncApp",
                Directory = _functionDirectory,
                Bindings  =
                {
                    { TestInputBindingName,  new BindingInfo {
                          Direction = BindingInfo.Types.Direction.In, Type = "httpTrigger"
                      } },
                    { TestOutputBindingName, new BindingInfo {
                          Direction = BindingInfo.Types.Direction.Out, Type = "http"
                      } }
                }
            };
            _functionLoadRequest = new FunctionLoadRequest {
                FunctionId = "FunctionId", Metadata = _rpcFunctionMetadata
            };
            FunctionLoader.SetupWellKnownPaths(_functionLoadRequest);

            _testLogger  = new ConsoleLogger();
            _testManager = new PowerShellManager(_testLogger);
            _testManager.PerformWorkerLevelInitialization();

            _testInputData = new List <ParameterBinding>
            {
                new ParameterBinding
                {
                    Name = TestInputBindingName,
                    Data = new TypedData
                    {
                        String = TestStringData
                    }
                }
            };
        }
示例#12
0
        /// <summary>
        /// Construct an object of AzFunctionInfo from the 'RpcFunctionMetadata'.
        /// Necessary validations are done on the metadata and script.
        /// </summary>
        internal AzFunctionInfo(RpcFunctionMetadata metadata)
        {
            FuncName      = metadata.Name;
            FuncDirectory = metadata.Directory;
            EntryPoint    = metadata.EntryPoint;
            ScriptPath    = metadata.ScriptFile;

            // Support 'entryPoint' only if 'scriptFile' is a .psm1 file;
            // Support .psm1 'scriptFile' only if 'entryPoint' is specified.
            bool isScriptFilePsm1     = ScriptPath.EndsWith(".psm1", StringComparison.OrdinalIgnoreCase);
            bool entryPointNotDefined = string.IsNullOrEmpty(EntryPoint);

            if (entryPointNotDefined)
            {
                if (isScriptFilePsm1)
                {
                    throw new ArgumentException(PowerShellWorkerStrings.RequireEntryPointForScriptModule);
                }
            }
            else if (!isScriptFilePsm1)
            {
                throw new ArgumentException(PowerShellWorkerStrings.InvalidEntryPointForScriptFile);
            }

            // Get the parameter names of the script or function.
            var psScriptParams = GetParameters(ScriptPath, EntryPoint, out ScriptBlockAst scriptAst);

            FuncParameters = new ReadOnlyDictionary <string, PSScriptParamInfo>(psScriptParams);

            var parametersCopy = new Dictionary <string, PSScriptParamInfo>(psScriptParams, StringComparer.OrdinalIgnoreCase);

            HasTriggerMetadataParam = parametersCopy.Remove(TriggerMetadata);
            HasTraceContextParam    = parametersCopy.Remove(TraceContext);

            var allBindings    = new Dictionary <string, ReadOnlyBindingInfo>(StringComparer.OrdinalIgnoreCase);
            var inputBindings  = new Dictionary <string, ReadOnlyBindingInfo>(StringComparer.OrdinalIgnoreCase);
            var outputBindings = new Dictionary <string, ReadOnlyBindingInfo>(StringComparer.OrdinalIgnoreCase);

            var inputsMissingFromParams = new List <string>();

            foreach (var binding in metadata.Bindings)
            {
                string bindingName = binding.Key;
                var    bindingInfo = new ReadOnlyBindingInfo(binding.Value);

                allBindings.Add(bindingName, bindingInfo);

                if (bindingInfo.Direction == BindingInfo.Types.Direction.In)
                {
                    Type = GetAzFunctionType(bindingInfo);
                    inputBindings.Add(bindingName, bindingInfo);

                    // If the input binding name is in the set, we remove it;
                    // otherwise, the binding name is missing from the params.
                    if (!parametersCopy.Remove(bindingName))
                    {
                        inputsMissingFromParams.Add(bindingName);
                    }
                }
                else if (bindingInfo.Direction == BindingInfo.Types.Direction.Out)
                {
                    if (bindingInfo.Type == OrchestrationClient)
                    {
                        OrchestrationClientBindingName = bindingName;
                    }

                    outputBindings.Add(bindingName, bindingInfo);
                }
                else
                {
                    // PowerShell doesn't support the 'InOut' type binding
                    throw new InvalidOperationException(string.Format(PowerShellWorkerStrings.InOutBindingNotSupported, bindingName));
                }
            }

            if (inputsMissingFromParams.Count != 0 || parametersCopy.Count != 0)
            {
                StringBuilder stringBuilder = new StringBuilder();
                foreach (string inputBindingName in inputsMissingFromParams)
                {
                    stringBuilder.AppendFormat(PowerShellWorkerStrings.MissingParameter, inputBindingName).AppendLine();
                }

                foreach (string param in parametersCopy.Keys)
                {
                    stringBuilder.AppendFormat(PowerShellWorkerStrings.UnknownParameter, param).AppendLine();
                }

                string errorMsg = stringBuilder.ToString();
                throw new InvalidOperationException(errorMsg);
            }

            if (entryPointNotDefined && scriptAst.ScriptRequirements == null)
            {
                // If the function script is a '.ps1' file that doesn't have '#requires' defined,
                // then we get the script block and will deploy it as a PowerShell function in the
                // global scope of each Runspace, so as to avoid hitting the disk every invocation.
                FuncScriptBlock    = scriptAst.GetScriptBlock();
                DeployedPSFuncName = $"_{FuncName}_";
            }

            AllBindings    = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(allBindings);
            InputBindings  = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(inputBindings);
            OutputBindings = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(outputBindings);
        }
示例#13
0
        /// <summary>
        /// Construct an object of AzFunctionInfo from the 'RpcFunctionMetadata'.
        /// Necessary validations are done on the metadata and script.
        /// </summary>
        internal AzFunctionInfo(RpcFunctionMetadata metadata)
        {
            FuncName      = metadata.Name;
            FuncDirectory = metadata.Directory;
            EntryPoint    = metadata.EntryPoint;
            ScriptPath    = metadata.ScriptFile;

            // Support 'entryPoint' only if 'scriptFile' is a .psm1 file;
            // Support .psm1 'scriptFile' only if 'entryPoint' is specified.
            bool isScriptFilePsm1 = ScriptPath.EndsWith(".psm1", StringComparison.OrdinalIgnoreCase);

            if (string.IsNullOrEmpty(EntryPoint))
            {
                if (isScriptFilePsm1)
                {
                    throw new ArgumentException(PowerShellWorkerStrings.RequireEntryPointForScriptModule);
                }
            }
            else if (!isScriptFilePsm1)
            {
                throw new ArgumentException(PowerShellWorkerStrings.InvalidEntryPointForScriptFile);
            }

            // Get the parameter names of the script or function.
            var psScriptParams = GetParameters(ScriptPath, EntryPoint);

            FuncParameters = new ReadOnlyDictionary <string, PSScriptParamInfo>(psScriptParams);

            var parametersCopy = new Dictionary <string, PSScriptParamInfo>(psScriptParams, StringComparer.OrdinalIgnoreCase);

            HasTriggerMetadataParam = parametersCopy.Remove(TriggerMetadata);

            var allBindings    = new Dictionary <string, ReadOnlyBindingInfo>(StringComparer.OrdinalIgnoreCase);
            var inputBindings  = new Dictionary <string, ReadOnlyBindingInfo>(StringComparer.OrdinalIgnoreCase);
            var outputBindings = new Dictionary <string, ReadOnlyBindingInfo>(StringComparer.OrdinalIgnoreCase);

            var inputsMissingFromParams = new List <string>();

            foreach (var binding in metadata.Bindings)
            {
                string bindingName = binding.Key;
                var    bindingInfo = new ReadOnlyBindingInfo(binding.Value);

                allBindings.Add(bindingName, bindingInfo);

                if (bindingInfo.Direction == BindingInfo.Types.Direction.In)
                {
                    Type = GetAzFunctionType(bindingInfo);
                    inputBindings.Add(bindingName, bindingInfo);

                    // If the input binding name is in the set, we remove it;
                    // otherwise, the binding name is missing from the params.
                    if (!parametersCopy.Remove(bindingName))
                    {
                        inputsMissingFromParams.Add(bindingName);
                    }
                }
                else if (bindingInfo.Direction == BindingInfo.Types.Direction.Out)
                {
                    outputBindings.Add(bindingName, bindingInfo);
                }
                else
                {
                    // PowerShell doesn't support the 'InOut' type binding
                    throw new InvalidOperationException(string.Format(PowerShellWorkerStrings.InOutBindingNotSupported, bindingName));
                }
            }

            if (inputsMissingFromParams.Count != 0 || parametersCopy.Count != 0)
            {
                StringBuilder stringBuilder = new StringBuilder();
                foreach (string inputBindingName in inputsMissingFromParams)
                {
                    stringBuilder.AppendFormat(PowerShellWorkerStrings.MissingParameter, inputBindingName).AppendLine();
                }

                foreach (string param in parametersCopy.Keys)
                {
                    stringBuilder.AppendFormat(PowerShellWorkerStrings.UnknownParameter, param).AppendLine();
                }

                string errorMsg = stringBuilder.ToString();
                throw new InvalidOperationException(errorMsg);
            }

            AllBindings    = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(allBindings);
            InputBindings  = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(inputBindings);
            OutputBindings = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(outputBindings);
        }
        /// <summary>
        /// Construct an object of AzFunctionInfo from the 'RpcFunctionMetadata'.
        /// Necessary validations are done on the metadata and script.
        /// </summary>
        internal AzFunctionInfo(RpcFunctionMetadata metadata)
        {
            FuncName      = metadata.Name;
            FuncDirectory = metadata.Directory;
            EntryPoint    = metadata.EntryPoint;
            ScriptPath    = metadata.ScriptFile;

            // Support 'entryPoint' only if 'scriptFile' is a .psm1 file;
            // Support .psm1 'scriptFile' only if 'entryPoint' is specified.
            bool isScriptFilePsm1 = ScriptPath.EndsWith(".psm1", StringComparison.OrdinalIgnoreCase);

            if (string.IsNullOrEmpty(EntryPoint))
            {
                if (isScriptFilePsm1)
                {
                    throw new ArgumentException($"The 'entryPoint' property needs to be specified when 'scriptFile' points to a PowerShell module script file (.psm1).");
                }
            }
            else if (!isScriptFilePsm1)
            {
                throw new ArgumentException($"The 'entryPoint' property is supported only if 'scriptFile' points to a PowerShell module script file (.psm1).");
            }

            // Get the parameter names of the script or function.
            FuncParameters = GetParameters(ScriptPath, EntryPoint);
            var parametersCopy = new HashSet <string>(FuncParameters, StringComparer.OrdinalIgnoreCase);

            parametersCopy.Remove(TriggerMetadata);

            var allBindings    = new Dictionary <string, ReadOnlyBindingInfo>();
            var inputBindings  = new Dictionary <string, ReadOnlyBindingInfo>();
            var outputBindings = new Dictionary <string, ReadOnlyBindingInfo>();

            var inputsMissingFromParams = new List <string>();

            foreach (var binding in metadata.Bindings)
            {
                string bindingName = binding.Key;
                var    bindingInfo = new ReadOnlyBindingInfo(binding.Value);

                allBindings.Add(bindingName, bindingInfo);

                if (bindingInfo.Direction == BindingInfo.Types.Direction.In)
                {
                    Type = GetAzFunctionType(bindingInfo);
                    inputBindings.Add(bindingName, bindingInfo);

                    // If the input binding name is in the set, we remove it;
                    // otherwise, the binding name is missing from the params.
                    if (!parametersCopy.Remove(bindingName))
                    {
                        inputsMissingFromParams.Add(bindingName);
                    }
                }
                else if (bindingInfo.Direction == BindingInfo.Types.Direction.Out)
                {
                    outputBindings.Add(bindingName, bindingInfo);
                }
                else
                {
                    // PowerShell doesn't support the 'InOut' type binding
                    throw new InvalidOperationException($"The binding '{bindingName}' is declared with 'InOut' direction, which is not supported by PowerShell functions.");
                }
            }

            if (inputsMissingFromParams.Count != 0 || parametersCopy.Count != 0)
            {
                StringBuilder stringBuilder = new StringBuilder();
                foreach (string inputBindingName in inputsMissingFromParams)
                {
                    stringBuilder.AppendLine($"No parameter defined in the script or function for the input binding '{inputBindingName}'.");
                }

                foreach (string param in parametersCopy)
                {
                    stringBuilder.AppendLine($"No input binding defined for the parameter '{param}' that is declared in the script or function.");
                }

                string errorMsg = stringBuilder.ToString();
                throw new InvalidOperationException(errorMsg);
            }

            AllBindings    = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(allBindings);
            InputBindings  = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(inputBindings);
            OutputBindings = new ReadOnlyDictionary <string, ReadOnlyBindingInfo>(outputBindings);
        }