Example #1
0
        internal static FunctionLoadResponse FunctionLoadRequestHandler(FunctionLoadRequest request, IFunctionsApplication application, IMethodInfoLocator methodInfoLocator)
        {
            var response = new FunctionLoadResponse
            {
                FunctionId = request.FunctionId,
                Result     = StatusResult.Success
            };

            if (!request.Metadata.IsProxy)
            {
                try
                {
                    FunctionDefinition definition = request.ToFunctionDefinition(methodInfoLocator);
                    application.LoadFunction(definition);
                }
                catch (Exception ex)
                {
                    response.Result = new StatusResult
                    {
                        Status    = StatusResult.Types.Status.Failure,
                        Exception = ex.ToRpcException()
                    };
                }
            }

            return(response);
        }
        internal StreamingMessage ProcessFunctionLoadRequest(StreamingMessage request)
        {
            FunctionLoadRequest functionLoadRequest = request.FunctionLoadRequest;

            StreamingMessage response = NewStreamingMessageTemplate(
                request.RequestId,
                StreamingMessage.ContentOneofCase.FunctionLoadResponse,
                out StatusResult status);

            response.FunctionLoadResponse.FunctionId = functionLoadRequest.FunctionId;

            try
            {
                // Try loading the metadata of the function
                _functionLoader.Load(functionLoadRequest);

                // if we haven't yet, add the well-known Function App module path to the PSModulePath
                // The location of this module path is in a folder called "Modules" in the root of the Function App.
                if (!_prependedPath)
                {
                    string functionAppModulesPath = Path.GetFullPath(
                        Path.Combine(functionLoadRequest.Metadata.Directory, "..", "Modules"));
                    _powerShellManager.PrependToPSModulePath(functionAppModulesPath);
                    _prependedPath = true;
                }
            }
            catch (Exception e)
            {
                status.Status    = StatusResult.Types.Status.Failure;
                status.Exception = e.ToRpcException();
            }

            return(response);
        }
Example #3
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
            };
        }
Example #4
0
        internal void SendFunctionLoadRequest(FunctionRegistrationContext context)
        {
            FunctionMetadata metadata = context.Metadata;

            // associate the invocation input buffer with the function
            _functionInputBuffers[context.Metadata.FunctionId] = context.InputBuffer;

            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }

            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
Example #5
0
        internal StreamingMessage ProcessFunctionLoadRequest(StreamingMessage request)
        {
            FunctionLoadRequest functionLoadRequest = request.FunctionLoadRequest;

            // Assume success unless something bad happens
            StatusResult status = new StatusResult()
            {
                Status = StatusResult.Types.Status.Success
            };

            // Try to load the functions
            try
            {
                _functionLoader.Load(functionLoadRequest);
            }
            catch (Exception e)
            {
                status.Status    = StatusResult.Types.Status.Failure;
                status.Exception = e.ToRpcException();
            }

            return(new StreamingMessage()
            {
                RequestId = request.RequestId,
                FunctionLoadResponse = new FunctionLoadResponse()
                {
                    FunctionId = functionLoadRequest.FunctionId,
                    Result = status
                }
            });
        }
Example #6
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);
        }
        /// <summary>
        /// Setup the well known paths about the FunctionApp.
        /// This method is called only once during the code start.
        /// </summary>
        internal static void SetupWellKnownPaths(FunctionLoadRequest request)
        {
            // Resolve the FunctionApp root path
            FunctionAppRootPath = Path.GetFullPath(Path.Join(request.Metadata.Directory, ".."));

            // Resolve module paths
            var appLevelModulesPath    = Path.Join(FunctionAppRootPath, "Modules");
            var workerLevelModulesPath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Modules");

            FunctionModulePath = $"{appLevelModulesPath}{Path.PathSeparator}{workerLevelModulesPath}";

            // Add the managed dependencies folder path
            if (DependencyManager.DependenciesPath != null)
            {
                FunctionModulePath = $"{DependencyManager.DependenciesPath}{Path.PathSeparator}{FunctionModulePath}";
            }

            // Resolve the FunctionApp profile path
            var options = new EnumerationOptions {
                MatchCasing = MatchCasing.CaseInsensitive
            };
            var profiles = Directory.EnumerateFiles(FunctionAppRootPath, "profile.ps1", options);

            FunctionAppProfilePath = profiles.FirstOrDefault();
        }
        internal FunctionLoadRequest GetFunctionLoadRequest(FunctionMetadata metadata, ManagedDependencyOptions managedDependencyOptions)
        {
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty,
                    IsProxy    = metadata.IsProxy
                }
            };

            if (managedDependencyOptions != null && managedDependencyOptions.Enabled)
            {
                _workerChannelLogger?.LogDebug($"Adding dependency download request to {_workerConfig.Description.Language} language worker");
                request.ManagedDependencyEnabled = managedDependencyOptions.Enabled;
            }

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }
            return(request);
        }
Example #9
0
 public GrpcFunctionMetadata(FunctionLoadRequest loadRequest)
 {
     EntryPoint     = loadRequest.Metadata.EntryPoint;
     Name           = loadRequest.Metadata.Name;
     PathToAssembly = Path.GetFullPath(loadRequest.Metadata.ScriptFile);
     FunctionId     = loadRequest.FunctionId;
 }
        internal void SendFunctionLoadRequest(FunctionMetadata metadata)
        {
            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            if (_managedDependencyOptions?.Value != null && _managedDependencyOptions.Value.Enabled)
            {
                _workerChannelLogger?.LogDebug($"Adding dependency download request to {_workerConfig.Language} language worker");
                request.ManagedDependencyEnabled = _managedDependencyOptions.Value.Enabled;
            }

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }

            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
        public void Register(FunctionRegistrationContext context)
        {
            FunctionMetadata metadata = context.Metadata;

            // associate the invocation input buffer with the function
            _functionInputBuffers[context.Metadata.FunctionId] = context.InputBuffer;

            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            foreach (var binding in metadata.Bindings)
            {
                request.Metadata.Bindings.Add(binding.Name, new BindingInfo
                {
                    Direction = (BindingInfo.Types.Direction)binding.Direction,
                    Type      = binding.Type
                });
            }

            Send(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
        /// <summary>
        /// Method to process a FunctionLoadRequest.
        /// FunctionLoadRequest should be processed sequentially. There is no point to process FunctionLoadRequest
        /// concurrently as a FunctionApp doesn't include a lot functions in general. Having this step sequential
        /// will make the Runspace-level initialization easier and more predictable.
        /// </summary>
        internal StreamingMessage ProcessFunctionLoadRequest(StreamingMessage request)
        {
            FunctionLoadRequest functionLoadRequest = request.FunctionLoadRequest;

            StreamingMessage response = NewStreamingMessageTemplate(
                request.RequestId,
                StreamingMessage.ContentOneofCase.FunctionLoadResponse,
                out StatusResult status);

            response.FunctionLoadResponse.FunctionId = functionLoadRequest.FunctionId;

            try
            {
                // Ideally, the initialization should happen when processing 'WorkerInitRequest', however, the 'WorkerInitRequest'
                // message doesn't provide the file path of the FunctionApp. That information is not available until the first
                // 'FunctionLoadRequest' comes in. Therefore, we run initialization here.
                if (!_isFunctionAppInitialized)
                {
                    FunctionLoader.SetupWellKnownPaths(functionLoadRequest);
                    _powershellPool.Initialize(request.RequestId);
                    _isFunctionAppInitialized = true;
                }

                // Load the metadata of the function.
                _functionLoader.LoadFunction(functionLoadRequest);
            }
            catch (Exception e)
            {
                status.Status    = StatusResult.Types.Status.Failure;
                status.Exception = e.ToRpcException();
            }

            return(response);
        }
Example #13
0
        public void Creates()
        {
            var bindingInfoProvider = new DefaultOutputBindingsInfoProvider();
            var methodInfoLocator   = new DefaultMethodInfoLocator();

            string fullPathToThisAssembly = GetType().Assembly.Location;
            var    functionLoadRequest    = new FunctionLoadRequest
            {
                FunctionId = "abc",
                Metadata   = new RpcFunctionMetadata
                {
                    EntryPoint = $"Microsoft.Azure.Functions.Worker.Tests.{nameof(GrpcFunctionDefinitionTests)}+{nameof(MyFunctionClass)}.{nameof(MyFunctionClass.Run)}",
                    ScriptFile = Path.GetFileName(fullPathToThisAssembly),
                    Name       = "myfunction"
                }
            };

            // We base this on the request exclusively, not the binding attributes.
            functionLoadRequest.Metadata.Bindings.Add("req", new BindingInfo {
                Type = "HttpTrigger", Direction = Direction.In
            });
            functionLoadRequest.Metadata.Bindings.Add("$return", new BindingInfo {
                Type = "Http", Direction = Direction.Out
            });

            FunctionDefinition definition = functionLoadRequest.ToFunctionDefinition(methodInfoLocator);

            Assert.Equal(functionLoadRequest.FunctionId, definition.Id);
            Assert.Equal(functionLoadRequest.Metadata.EntryPoint, definition.EntryPoint);
            Assert.Equal(functionLoadRequest.Metadata.Name, definition.Name);
            Assert.Equal(fullPathToThisAssembly, definition.PathToAssembly);

            // Parameters
            Assert.Collection(definition.Parameters,
                              p =>
            {
                Assert.Equal("req", p.Name);
                Assert.Equal(typeof(HttpRequestData), p.Type);
            });

            // InputBindings
            Assert.Collection(definition.InputBindings,
                              p =>
            {
                Assert.Equal("req", p.Key);
                Assert.Equal(BindingDirection.In, p.Value.Direction);
                Assert.Equal("HttpTrigger", p.Value.Type);
            });

            // OutputBindings
            Assert.Collection(definition.OutputBindings,
                              p =>
            {
                Assert.Equal("$return", p.Key);
                Assert.Equal(BindingDirection.Out, p.Value.Direction);
                Assert.Equal("Http", p.Value.Type);
            });
        }
Example #14
0
        /// <summary>
        /// Method to process a FunctionLoadRequest.
        /// FunctionLoadRequest should be processed sequentially. There is no point to process FunctionLoadRequest
        /// concurrently as a FunctionApp doesn't include a lot functions in general. Having this step sequential
        /// will make the Runspace-level initialization easier and more predictable.
        /// </summary>
        internal StreamingMessage ProcessFunctionLoadRequest(StreamingMessage request)
        {
            FunctionLoadRequest functionLoadRequest = request.FunctionLoadRequest;

            StreamingMessage response = NewStreamingMessageTemplate(
                request.RequestId,
                StreamingMessage.ContentOneofCase.FunctionLoadResponse,
                out StatusResult status);

            response.FunctionLoadResponse.FunctionId = functionLoadRequest.FunctionId;

            // When a functionLoadRequest comes in, we check to see if a dependency download has failed in a previous call
            // or if PowerShell could not be initialized. If this is the case, mark this as a failed request
            // and submit the exception to the Host (runtime).
            if (_initTerminatingError != null)
            {
                status.Status    = StatusResult.Types.Status.Failure;
                status.Exception = _initTerminatingError.ToRpcException();
                return(response);
            }

            // Ideally, the initialization should happen when processing 'WorkerInitRequest', however, the 'WorkerInitRequest'
            // message doesn't provide information about the FunctionApp. That information is not available until the first
            // 'FunctionLoadRequest' comes in. Therefore, we run initialization here.
            if (!_isFunctionAppInitialized)
            {
                try
                {
                    _isFunctionAppInitialized = true;
                    InitializeForFunctionApp(request, response);
                }
                catch (Exception e)
                {
                    // Failure that happens during this step is terminating and we will need to return a failure response to
                    // all subsequent 'FunctionLoadRequest'. Cache the exception so we can reuse it in future calls.
                    _initTerminatingError = e;

                    status.Status    = StatusResult.Types.Status.Failure;
                    status.Exception = e.ToRpcException();
                    return(response);
                }
            }

            try
            {
                // Load the metadata of the function.
                _functionLoader.LoadFunction(functionLoadRequest);
            }
            catch (Exception e)
            {
                status.Status    = StatusResult.Types.Status.Failure;
                status.Exception = e.ToRpcException();
            }

            return(response);
        }
        public void AddFunction(FunctionLoadRequest functionLoadRequest)
        {
            FunctionDefinition functionDefinition = _functionDescriptorFactory.Create(functionLoadRequest);

            if (functionDefinition.Metadata.FunctionId is null)
            {
                throw new InvalidOperationException("The function ID for the current load request is invalid");
            }

            _functionMap.TryAdd(functionDefinition.Metadata.FunctionId, functionDefinition);
        }
Example #16
0
        /// <summary>
        /// Initializes the dependency manger and performs the following:
        /// - Parse functionAppRoot\requirements.psd1 file and create a list of dependencies to install.
        /// - Set the DependenciesPath which gets used in 'SetupWellKnownPaths'.
        /// - Determines if the dependency module needs to be installed by checking the latest available version
        ///   in the PSGallery and the destination path (to see if it is already installed).
        /// - Set the destination path (if running in Azure vs local) where the function app dependencies will be installed.
        /// </summary>
        internal void Initialize(FunctionLoadRequest request)
        {
            if (!request.ManagedDependencyEnabled)
            {
                return;
            }

            try
            {
                // Resolve the FunctionApp root path.
                var functionAppRootPath = Path.GetFullPath(Path.Join(request.Metadata.Directory, ".."));

                // Resolve the managed dependencies installation path.
                DependenciesPath = GetManagedDependenciesPath(functionAppRootPath);

                // Parse and process the function app dependencies defined in requirements.psd1.
                Hashtable entries = ParsePowerShellDataFile(functionAppRootPath, RequirementsPsd1FileName);
                foreach (DictionaryEntry entry in entries)
                {
                    // A valid entry is of the form: 'ModuleName'='MajorVersion.*"
                    string name    = (string)entry.Key;
                    string version = (string)entry.Value;

                    // Validates that the module name is a supported dependency.
                    ValidateModuleName(name);

                    // Validate the module version.
                    string majorVersion  = GetMajorVersion(version);
                    string latestVersion = DependencyManagementUtils.GetModuleLatestSupportedVersion(name, majorVersion);
                    ValidateModuleMajorVersion(name, majorVersion, latestVersion);

                    // Before installing the module, check the path to see if it is already installed.
                    var moduleVersionFolderPath = Path.Combine(DependenciesPath, name, latestVersion);
                    if (!Directory.Exists(moduleVersionFolderPath))
                    {
                        _shouldUpdateFunctionAppDependencies = true;
                    }

                    // Create a DependencyInfo object and add it to the list of dependencies to install.
                    var dependencyInfo = new DependencyInfo(name, majorVersion, latestVersion);
                    Dependencies.Add(dependencyInfo);
                }
            }
            catch (Exception e)
            {
                // Reset DependenciesPath and Dependencies.
                DependenciesPath = null;
                Dependencies.Clear();

                var errorMsg = string.Format(PowerShellWorkerStrings.FailToInstallFuncAppDependencies, e.Message);
                throw new DependencyInstallationException(errorMsg, e);
            }
        }
Example #17
0
        /// <summary>
        /// Setup the well known paths about the FunctionApp.
        /// This method is called only once during the code start.
        /// </summary>
        internal static void SetupWellKnownPaths(FunctionLoadRequest request)
        {
            FunctionAppRootPath    = Path.GetFullPath(Path.Join(request.Metadata.Directory, ".."));
            FunctionAppModulesPath = Path.Join(FunctionAppRootPath, "Modules");

            var options = new EnumerationOptions {
                MatchCasing = MatchCasing.CaseInsensitive
            };
            var profiles = Directory.EnumerateFiles(FunctionAppRootPath, "profile.ps1", options);

            FunctionAppProfilePath = profiles.FirstOrDefault();
        }
Example #18
0
        internal void FunctionLoadRequestHandler(StreamingMessage request)
        {
            FunctionLoadRequest functionLoadRequest = request.FunctionLoadRequest;

            StreamingMessage response = NewStreamingMessageTemplate(
                request.RequestId,
                StreamingMessage.ContentOneofCase.FunctionLoadResponse,
                out StatusResult status);

            response.FunctionLoadResponse.FunctionId = functionLoadRequest.FunctionId;
            _blockingCollectionQueue.Add(response);
        }
Example #19
0
        private void SetupAppRootPathAndModulePath(FunctionLoadRequest functionLoadRequest, string managedDependenciesPath)
        {
            FunctionLoader.SetupWellKnownPaths(functionLoadRequest, managedDependenciesPath);

            if (FunctionLoader.FunctionAppRootPath == null)
            {
                throw new InvalidOperationException(PowerShellWorkerStrings.FunctionAppRootNotResolved);
            }

            _firstPwshInstance.AddCommand("Microsoft.PowerShell.Management\\Set-Content")
            .AddParameter("Path", "env:PSModulePath")
            .AddParameter("Value", FunctionLoader.FunctionModulePath)
            .InvokeAndClearCommands();
        }
Example #20
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);
        }
Example #22
0
 private static async Task HandleFunctionLoadRequest(FunctionLoadRequest loadRequest)
 {
     s_loadedFunctions.TryAdd(loadRequest.FunctionId, loadRequest.Metadata);
     var response = new StreamingMessage()
     {
         RequestId            = s_requestId,
         FunctionLoadResponse = new FunctionLoadResponse()
         {
             FunctionId = loadRequest.FunctionId,
             Result     = new StatusResult()
             {
                 Status = StatusResult.Types.Status.Success
             }
         }
     };
     await s_call.RequestStream.WriteAsync(response);
 }
Example #23
0
        public Task <FunctionLoadResponse> LoadFunctionAsync(FunctionLoadRequest request)
        {
            // instead, use request.Metadata.IsProxy
            if (!string.IsNullOrEmpty(request.Metadata?.ScriptFile))
            {
                _functionBroker.AddFunction(request);
            }

            var response = new FunctionLoadResponse
            {
                FunctionId = request.FunctionId,
                Result     = new StatusResult {
                    Status = Status.Success
                }
            };

            return(Task.FromResult(response));
        }
Example #24
0
        public FunctionDefinition Create(FunctionLoadRequest request)
        {
            FunctionMetadata metadata = request.ToFunctionMetadata();

            if (metadata.PathToAssembly == null)
            {
                throw new InvalidOperationException("The path to the function assembly is null.");
            }

            if (metadata.EntryPoint == null)
            {
                throw new InvalidOperationException("The entry point is null.");
            }

            var entryPointMatch = _entryPointRegex.Match(metadata.EntryPoint);

            if (!entryPointMatch.Success)
            {
                throw new InvalidOperationException("Invalid entry point configuration. The function entry point must be defined in the format <fulltypename>.<methodname>");
            }

            string typeName   = entryPointMatch.Groups["typename"].Value;
            string methodName = entryPointMatch.Groups["methodname"].Value;

            Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(metadata.PathToAssembly);

            Type?functionType = assembly.GetType(typeName);

            MethodInfo?methodInfo = functionType?.GetMethod(methodName);

            if (methodInfo == null)
            {
                throw new InvalidOperationException($"Method '{methodName}' specified in {nameof(FunctionMetadata.EntryPoint)} was not found. This function cannot be created.");
            }

            IFunctionInvoker invoker = _functionInvokerFactory.Create(methodInfo);

            IEnumerable <FunctionParameter> parameters = methodInfo.GetParameters()
                                                         .Where(p => p.Name != null)
                                                         .Select(p => new FunctionParameter(p.Name !, p.ParameterType));

            return(new DefaultFunctionDefinition(metadata, invoker, parameters));
        }
Example #25
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);
        }
        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);
        }
        internal void SendFunctionLoadRequest(FunctionRegistrationContext context)
        {
            FunctionMetadata metadata = context.Metadata;

            // associate the invocation input buffer with the function
            _functionInputBuffers[context.Metadata.FunctionId] = context.InputBuffer;

            // send a load request for the registered function
            FunctionLoadRequest request = new FunctionLoadRequest()
            {
                FunctionId = metadata.FunctionId,
                Metadata   = new RpcFunctionMetadata()
                {
                    Name       = metadata.Name,
                    Directory  = metadata.FunctionDirectory ?? string.Empty,
                    EntryPoint = metadata.EntryPoint ?? string.Empty,
                    ScriptFile = metadata.ScriptFile ?? string.Empty
                }
            };

            if (_managedDependencyOptions?.Value != null)
            {
                _workerChannelLogger?.LogInformation($"Adding dependency download request to {_workerConfig.Language} language worker");
                request.ManagedDependencyEnabled = _managedDependencyOptions.Value.Enabled;
            }

            foreach (var binding in metadata.Bindings)
            {
                BindingInfo bindingInfo = binding.ToBindingInfo();

                request.Metadata.Bindings.Add(binding.Name, bindingInfo);
            }

            SendStreamingMessage(new StreamingMessage
            {
                FunctionLoadRequest = request
            });
        }
        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
                    }
                }
            };
        }
        public GrpcFunctionDefinition(FunctionLoadRequest loadRequest, IMethodInfoLocator methodInfoLocator)
        {
            EntryPoint     = loadRequest.Metadata.EntryPoint;
            Name           = loadRequest.Metadata.Name;
            PathToAssembly = Path.GetFullPath(loadRequest.Metadata.ScriptFile);
            Id             = loadRequest.FunctionId;

            var grpcBindingsGroup    = loadRequest.Metadata.Bindings.GroupBy(kv => kv.Value.Direction);
            var grpcInputBindings    = grpcBindingsGroup.Where(kv => kv.Key == BindingInfo.Types.Direction.In).FirstOrDefault();
            var grpcOutputBindings   = grpcBindingsGroup.Where(kv => kv.Key != BindingInfo.Types.Direction.In).FirstOrDefault();
            var infoToMetadataLambda = new Func <KeyValuePair <string, BindingInfo>, BindingMetadata>(kv => new GrpcBindingMetadata(kv.Value));

            InputBindings = grpcInputBindings?.ToImmutableDictionary(kv => kv.Key, infoToMetadataLambda)
                            ?? ImmutableDictionary <string, BindingMetadata> .Empty;

            OutputBindings = grpcOutputBindings?.ToImmutableDictionary(kv => kv.Key, infoToMetadataLambda)
                             ?? ImmutableDictionary <string, BindingMetadata> .Empty;

            Parameters = methodInfoLocator.GetMethod(PathToAssembly, EntryPoint)
                         .GetParameters()
                         .Where(p => p.Name != null)
                         .Select(p => new FunctionParameter(p.Name !, p.ParameterType))
                         .ToImmutableArray();
        }