コード例 #1
0
        private static async Task <FunctionOutputBufferHandler> StartFunctionHostProcess(
            int port,
            string provider,
            string workingDirectory,
            FunctionConfiguration?functionConfiguration)
        {
            var startInfo = new ProcessStartInfo(
                await GetToolPath(),
                $"host start --port {port} --{provider}")
            {
                WorkingDirectory       = workingDirectory,
                UseShellExecute        = false,
                CreateNoWindow         = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                RedirectStandardInput  = true,
                WindowStyle            = ProcessWindowStyle.Normal,
            };

            if (functionConfiguration != null)
            {
                foreach (KeyValuePair <string, string> kvp in functionConfiguration.EnvironmentVariables)
                {
                    startInfo.EnvironmentVariables[kvp.Key] = kvp.Value;
                }
            }

            var processHandler = new FunctionOutputBufferHandler(startInfo);

            processHandler.Start();

            return(processHandler);
        }
コード例 #2
0
        /// <summary>
        /// Start a functions instance.
        /// </summary>
        /// <param name="path">The location of the functions project.</param>
        /// <param name="port">The port on which to start the functions instance.</param>
        /// <param name="runtime">The runtime version for use with the function host (e.g. netcoreapp3.1).</param>
        /// <param name="provider">The functions provider. Defaults to csharp.</param>
        /// <param name="configuration">A <see cref="FunctionConfiguration"/> instance, for conveying
        /// configuration values via environment variables to the function host process.</param>
        /// <returns>A task that completes once the function instance has started.</returns>
        public async Task StartFunctionsInstance(string path, int port, string runtime, string provider = "csharp", FunctionConfiguration?configuration = null)
        {
            this.functionLogScope = this.logger.BeginScope(this);
            if (IsSomethingAlreadyListeningOn(port))
            {
                this.logger.LogWarning("Found a process listening on {Port}. Is this a debug instance?", port);
                this.logger.LogWarning("This test run will reuse this process, and so may produce unexpected results.");
                return;
            }

            this.logger.LogInformation("Starting a function instance for project {Path} on port {Port}", path, port);
            this.logger.LogDebug("Starting process");

            FunctionOutputBufferHandler bufferHandler = await StartFunctionHostProcess(
                port,
                provider,
                FunctionProject.ResolvePath(path, runtime, this.logger),
                configuration).ConfigureAwait(false);

            lock (this.sync)
            {
                this.output.Add(bufferHandler);
            }

            this.logger.LogDebug("Process started; waiting for initialisation to complete");

            await Task.WhenAny(
                bufferHandler.JobHostStarted,
                bufferHandler.ExitCode,
                Task.Delay(TimeSpan.FromSeconds(StartupTimeout))).ConfigureAwait(false);

            if (bufferHandler.ExitCode.IsCompleted)
            {
                int exitCode = await bufferHandler.ExitCode.ConfigureAwait(false);

                this.logger.LogError(
                    @"Failed to start function host, process terminated unexpectedly with exit code {ExitCode}.
StdOut: {StdOut}
StdErr: {StdErr}",
                    exitCode,
                    bufferHandler.StandardOutputText,
                    bufferHandler.StandardErrorText);

                throw new FunctionStartupException(
                          $"Function host process terminated unexpectedly with exit code {exitCode}.",
                          stdout: bufferHandler.StandardOutputText,
                          stderr: bufferHandler.StandardErrorText);
            }

            if (!bufferHandler.JobHostStarted.IsCompleted)
            {
                throw new FunctionStartupException("Timed out while starting functions instance.");
            }

            this.logger.LogDebug("Initialisation completed");
            this.logger.LogInformation("Function {Path} now running on port {Port}", path, port);
        }
コード例 #3
0
        /// <summary>
        /// Start a functions instance.
        /// </summary>
        /// <param name="path">The location of the functions project.</param>
        /// <param name="port">The port on which to start the functions instance.</param>
        /// <param name="runtime">The runtime version for use with the function host (e.g. netcoreapp3.1).</param>
        /// <param name="provider">The functions provider. Defaults to csharp.</param>
        /// <param name="configuration">A <see cref="FunctionConfiguration"/> instance, for conveying
        /// configuration values via environment variables to the function host process.</param>
        /// <returns>A task that completes once the function instance has started.</returns>
        public async Task StartFunctionsInstance(string path, int port, string runtime, string provider = "csharp", FunctionConfiguration?configuration = null)
        {
            if (IsSomethingAlreadyListeningOn(port))
            {
                Console.WriteLine($"Found a process listening on {port}. Is this a debug instance?");
                Console.WriteLine("This test run will reuse this process, and so may produce unexpected results.");
                return;
            }

            Console.WriteLine($"Starting a function instance for project {path} on port {port}");
            Console.WriteLine("\tStarting process");

            FunctionOutputBufferHandler bufferHandler = await StartFunctionHostProcess(
                port,
                provider,
                FunctionProject.ResolvePath(path, runtime),
                configuration);

            lock (this.sync)
            {
                this.output.Add(bufferHandler);
            }

            Console.WriteLine("\tProcess started; waiting for initialisation to complete");

            await Task.WhenAny(
                bufferHandler.JobHostStarted,
                bufferHandler.ExitCode,
                Task.Delay(TimeSpan.FromSeconds(StartupTimeout))).ConfigureAwait(false);

            if (bufferHandler.ExitCode.IsCompleted)
            {
                int exitCode = await bufferHandler.ExitCode.ConfigureAwait(false);

                throw new FunctionStartupException(
                          $"Function host process terminated unexpectedly with exit code {exitCode}.",
                          stderr: bufferHandler.StandardErrorText);
            }

            if (!bufferHandler.JobHostStarted.IsCompleted)
            {
                throw new FunctionStartupException("Timed out while starting functions instance.");
            }

            Console.WriteLine();
            Console.WriteLine("\tStarted");
        }
コード例 #4
0
        /// <summary>
        /// Start a functions instance.
        /// </summary>
        /// <param name="path">The location of the functions project.</param>
        /// <param name="port">The port on which to start the functions instance.</param>
        /// <param name="runtime">The runtime version for use with the function host (e.g. netcoreapp3.1).</param>
        /// <param name="provider">The functions provider. Defaults to csharp.</param>
        /// <param name="configuration">A <see cref="FunctionConfiguration"/> instance, for conveying
        /// configuration values via environment variables to the function host process.</param>
        /// <returns>A task that completes once the function instance has started.</returns>
        public async Task StartFunctionsInstance(string path, int port, string runtime, string provider = "csharp", FunctionConfiguration?configuration = null)
        {
            Console.WriteLine($"Starting a function instance for project {path} on port {port}");
            Console.WriteLine("\tStarting process");

            FunctionOutputBufferHandler bufferHandler = StartFunctionHostProcess(
                port,
                provider,
                await GetToolPath(),
                GetWorkingDirectory(path, runtime),
                configuration);

            lock (this.sync)
            {
                this.output.Add(bufferHandler);
            }

            Console.WriteLine("\tProcess started; waiting for initialisation to complete");

            await Task.WhenAny(
                bufferHandler.JobHostStarted,
                bufferHandler.ExitCode,
                Task.Delay(TimeSpan.FromSeconds(StartupTimeout))).ConfigureAwait(false);

            if (bufferHandler.ExitCode.IsCompleted)
            {
                int exitCode = await bufferHandler.ExitCode.ConfigureAwait(false);

                throw new FunctionStartupException(
                          $"Function host process terminated unexpectedly with exit code {exitCode}.",
                          stderr: bufferHandler.StandardErrorText);
            }

            if (!bufferHandler.JobHostStarted.IsCompleted)
            {
                throw new FunctionStartupException("Timed out while starting functions instance.");
            }

            Console.WriteLine();
            Console.WriteLine("\tStarted");
        }
コード例 #5
0
        private static async Task <FunctionOutputBufferHandler> StartFunctionHostProcess(
            int port,
            string provider,
            string workingDirectory,
            FunctionConfiguration?functionConfiguration)
        {
            var startInfo = new ProcessStartInfo(
                await GetToolPath().ConfigureAwait(false),
                $"host start --port {port} --{provider}")
            {
                WorkingDirectory       = workingDirectory,
                UseShellExecute        = false,
                CreateNoWindow         = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                RedirectStandardInput  = true,
                WindowStyle            = ProcessWindowStyle.Normal,
            };

            if (functionConfiguration != null)
            {
                foreach (KeyValuePair <string, string> kvp in functionConfiguration.EnvironmentVariables)
                {
                    startInfo.EnvironmentVariables[kvp.Key] = kvp.Value;
                }
            }

            // Force the logging level to debug to ensure we can pick up the message that tells us the function is
            // ready to go.
            startInfo.EnvironmentVariables["AzureFunctionsJobHost:logging:logLevel:default"] = "Debug";

            var processHandler = new FunctionOutputBufferHandler(startInfo);

            processHandler.Start();

            return(processHandler);
        }
コード例 #6
0
        /// <summary>
        ///     Start a functions instance.
        /// </summary>
        /// <param name="featureContext">The current feature context.</param>
        /// <param name="scenarioContext">The current scenario context. Not required if using this class per-feature.</param>
        /// <param name="path">The location of the functions project.</param>
        /// <param name="port">The port on which to start the functions instance.</param>
        /// <param name="runtime">The runtime version, defaults to netcoreapp2.1.</param>
        /// <param name="provider">The functions provider. Defaults to csharp.</param>
        /// <returns>A task that completes once the function instance has started.</returns>
        public async Task StartFunctionsInstance(
            FeatureContext featureContext,
            ScenarioContext?scenarioContext,
            string path,
            int port,
            string runtime  = "netcoreapp2.1",
            string provider = "csharp")
        {
            Console.WriteLine($"Starting a function instance for project {path} on port {port}");

            string directoryExtension = $"\\bin\\release\\{runtime}";

            string lowerInvariantCurrentDirectory = TestContext.CurrentContext.TestDirectory.ToLowerInvariant();

            if (lowerInvariantCurrentDirectory.Contains("debug"))
            {
                directoryExtension = $"\\bin\\debug\\{runtime}";
            }

            Console.WriteLine($"\tCurrent directory: {lowerInvariantCurrentDirectory}");

            string root = TestContext.CurrentContext.TestDirectory.Substring(
                0,
                TestContext.CurrentContext.TestDirectory.IndexOf(@"\Solutions\") + 11);

            Console.WriteLine($"\tRoot: {root}");

            string npmPrefix = await GetNpmPrefix().ConfigureAwait(false);

            string toolsFolder = Path.Combine(
                npmPrefix,
                @"node_modules\azure-functions-core-tools\bin");

            Assert.IsTrue(
                Directory.Exists(toolsFolder),
                $"Azure Functions runtime not found at {toolsFolder}. Have you run: 'npm install -g azure-functions-core-tools --unsafe-perm true'?");
            string toolPath = Path.Combine(
                toolsFolder,
                "func");

            Console.WriteLine($"\tToolsPath: {toolPath}");

            Console.WriteLine($"\tStarting process");

            var startInfo = new ProcessStartInfo(toolPath, $"host start --port {port} --{provider}")
            {
                WorkingDirectory       = root + path + directoryExtension,
                UseShellExecute        = false,
                CreateNoWindow         = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                RedirectStandardInput  = true,
                WindowStyle            = ProcessWindowStyle.Normal,
            };

            FunctionConfiguration?functionConfiguration = null;

            scenarioContext?.TryGetValue(out functionConfiguration);

            if (functionConfiguration == null)
            {
                featureContext.TryGetValue(out functionConfiguration);
            }

            if (functionConfiguration != null)
            {
                foreach (KeyValuePair <string, string> kvp in functionConfiguration.EnvironmentVariables)
                {
                    startInfo.EnvironmentVariables[kvp.Key] = kvp.Value;
                }
            }

            var bufferHandler = new FunctionOutputBufferHandler(startInfo);

            lock (this.sync)
            {
                this.output[bufferHandler.Process] = bufferHandler;
            }

            Console.WriteLine($"\tProcess started; waiting for initialisation to complete");

            await Task.WhenAny(
                bufferHandler.JobHostStarted,
                bufferHandler.ExitCode,
                Task.Delay(TimeSpan.FromSeconds(StartupTimeout))).ConfigureAwait(false);

            if (bufferHandler.ExitCode.IsCompleted)
            {
                int exitCode = await bufferHandler.ExitCode.ConfigureAwait(false);

                Assert.Fail($"Function host process terminated unexpectedly with exit code {exitCode}. Error output: {bufferHandler.StandardErrorText}");
            }
            else if (!bufferHandler.JobHostStarted.IsCompleted)
            {
                Assert.Fail("Timed out while starting functions instance.");
            }
            else
            {
                Console.WriteLine();
                Console.WriteLine("\tStarted");
            }
        }