示例#1
0
        private async Task PreRunConditions()
        {
            if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python)
            {
                var pythonVersion = await PythonHelpers.GetEnvironmentPythonVersion();

                PythonHelpers.AssertPythonVersion(pythonVersion, errorIfNotSupported: true, errorIfNoVersion: true);
                PythonHelpers.SetWorkerPath(pythonVersion?.ExecutablePath, overwrite: false);
                PythonHelpers.SetWorkerRuntimeVersionPython(pythonVersion);
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.dotnet && !NoBuild)
            {
                if (DotnetHelpers.CanDotnetBuild())
                {
                    var outputPath = Path.Combine("bin", "output");
                    await DotnetHelpers.BuildDotnetProject(outputPath, string.Empty);

                    Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
                }
                else if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build.");
                }
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.powershell && !CommandChecker.CommandExists("dotnet"))
            {
                throw new CliException("Dotnet is required for PowerShell Functions. Please install dotnet (.NET Core SDK) for your system from https://www.microsoft.com/net/download");
            }

            if (!NetworkHelpers.IsPortAvailable(Port))
            {
                throw new CliException($"Port {Port} is unavailable. Close the process using that port, or specify another port using --port [-p].");
            }
        }
 private async Task InitLanguageSpecificArtifacts(WorkerRuntime workerRuntime)
 {
     if (workerRuntime == Helpers.WorkerRuntime.python)
     {
         await PythonHelpers.InstallPackage();
     }
 }
 private void PreRunConditions()
 {
     if (_secretsManager.GetSecrets().Any(p => p.Key == Constants.FunctionsWorkerRuntime && p.Value == "Python"))
     {
         PythonHelpers.VerifyVirtualEnvironment();
     }
 }
示例#4
0
        private async Task PreRunConditions(WorkerRuntime workerRuntime)
        {
            if (workerRuntime == WorkerRuntime.python)
            {
                PythonHelpers.VerifyVirtualEnvironment();
            }
            else if (workerRuntime == WorkerRuntime.dotnet && !NoBuild)
            {
                if (DotnetHelpers.CanDotnetBuild())
                {
                    var outputPath = Path.Combine("bin", "output");
                    await DotnetHelpers.BuildDotnetProject(outputPath, string.Empty);

                    Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
                }
                else if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build.");
                }
            }

            if (!NetworkHelpers.IsPortAvailable(Port))
            {
                throw new CliException($"Port {Port} is unavailable. Close the process using that port, or specify another port using --port [-p].");
            }
        }
 private async Task InitLanguageSpecificArtifacts(string language)
 {
     if (language == "Python")
     {
         await PythonHelpers.InstallPackage();
     }
 }
示例#6
0
        /// <summary>
        /// Handler for Linux Consumption publish event
        /// </summary>
        /// <param name="functionApp">Function App in Azure</param>
        /// <param name="zipFileFactory">Factory for local project zipper</param>
        /// <returns>ShouldSyncTrigger value</returns>
        private async Task <bool> HandleLinuxConsumptionPublish(Site functionApp, Func <Task <Stream> > zipFileFactory)
        {
            string fileNameNoExtension = string.Format("{0}-{1}", DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmss"), Guid.NewGuid());

            // Consumption Linux, try squashfs as a package format.
            if (PublishBuildOption == BuildOption.Remote)
            {
                await EnsureRemoteBuildIsSupported(functionApp);
                await RemoveFunctionAppAppSetting(functionApp, Constants.WebsiteRunFromPackage, Constants.WebsiteContentAzureFileConnectionString, Constants.WebsiteContentShared);
                Task <DeployStatus> pollConsumptionBuild(HttpClient client) => KuduLiteDeploymentHelpers.WaitForRemoteBuild(client, functionApp);

                var deployStatus = await PerformServerSideBuild(functionApp, zipFileFactory, pollConsumptionBuild);

                return(deployStatus == DeployStatus.Success);
            }
            else if (PublishBuildOption == BuildOption.Local)
            {
                await PublishRunFromPackage(functionApp, await zipFileFactory(), $"{fileNameNoExtension}.zip");

                return(true);
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntimeOrNone == WorkerRuntime.python && !NoBuild && BuildNativeDeps)
            {
                await PublishRunFromPackage(functionApp, await PythonHelpers.ZipToSquashfsStream(await zipFileFactory()), $"{fileNameNoExtension}.squashfs");

                return(true);
            }
            else
            {
                await PublishRunFromPackage(functionApp, await zipFileFactory(), $"{fileNameNoExtension}.zip");

                return(true);
            }
        }
示例#7
0
        private static async Task InitLanguageSpecificArtifacts(WorkerRuntime workerRuntime, string language, bool managedDependenciesOption)
        {
            if (workerRuntime == Helpers.WorkerRuntime.python)
            {
                await PythonHelpers.SetupPythonProject();
            }
            else if (workerRuntime == Helpers.WorkerRuntime.powershell)
            {
                await WriteFiles("profile.ps1", await StaticResources.PowerShellProfilePs1);

                if (managedDependenciesOption)
                {
                    string majorVersion = await PowerShellHelper.GetLatestAzModuleMajorVersion();

                    var requirementsContent = await StaticResources.PowerShellRequirementsPsd1;
                    requirementsContent = requirementsContent.Replace("MAJOR_VERSION", majorVersion);

                    await WriteFiles("requirements.psd1", requirementsContent);
                }
            }
            else if (workerRuntime == Helpers.WorkerRuntime.node)
            {
                if (language == Constants.Languages.TypeScript)
                {
                    await WriteFiles(".funcignore", await StaticResources.FuncIgnore);
                    await WriteFiles("package.json", await StaticResources.PackageJson);
                    await WriteFiles("tsconfig.json", await StaticResources.TsConfig);
                }
                else
                {
                    await WriteFiles("package.json", await StaticResources.JavascriptPackageJson);
                }
            }
        }
        private static async Task InitLanguageSpecificArtifacts(WorkerRuntime workerRuntime, string language, bool managedDependenciesOption)
        {
            if (workerRuntime == Helpers.WorkerRuntime.python)
            {
                await PythonHelpers.SetupPythonProject();
            }
            else if (workerRuntime == Helpers.WorkerRuntime.powershell)
            {
                await WriteFiles("profile.ps1", await StaticResources.PowerShellProfilePs1);

                if (managedDependenciesOption)
                {
                    string majorVersion = null;

                    bool failedToGetModuleVersion = false;
                    try
                    {
                        majorVersion = await PowerShellHelper.GetLatestAzModuleMajorVersion();
                    }
                    catch
                    {
                        failedToGetModuleVersion = true;
                    }

                    string guidance            = null;
                    var    requirementsContent = await StaticResources.PowerShellRequirementsPsd1;

                    if (failedToGetModuleVersion)
                    {
                        guidance = "Uncomment the next line and replace the MAJOR_VERSION, e.g., 'Az' = '2.*'";

                        var warningMsg = "Failed to get Az module version. Edit the requirements.psd1 file when the powershellgallery.com is accessible.";
                        ColoredConsole.WriteLine(WarningColor(warningMsg));
                    }
                    else
                    {
                        guidance            = string.Empty;
                        requirementsContent = requirementsContent.Replace("# 'Az'", "'Az'");
                        requirementsContent = requirementsContent.Replace("MAJOR_VERSION", majorVersion);
                    }

                    requirementsContent = requirementsContent.Replace("[GUIDANCE]", guidance);
                    await WriteFiles("requirements.psd1", requirementsContent);
                }
            }
            else if (workerRuntime == Helpers.WorkerRuntime.node)
            {
                if (language == Constants.Languages.TypeScript)
                {
                    await WriteFiles(".funcignore", await StaticResources.FuncIgnore);
                    await WriteFiles("package.json", await StaticResources.PackageJson);
                    await WriteFiles("tsconfig.json", await StaticResources.TsConfig);
                }
                else
                {
                    await WriteFiles("package.json", await StaticResources.JavascriptPackageJson);
                }
            }
        }
示例#9
0
        public async void WorkerInfoRuntimeShouldBePython()
        {
            WorkerLanguageVersionInfo worker = await PythonHelpers.GetEnvironmentPythonVersion();

            if (worker.Runtime != WorkerRuntime.python)
            {
                throw new Exception("Worker runtime should always be python");
            }
        }
示例#10
0
        public async void InterpreterShouldHaveExecutablePath()
        {
            WorkerLanguageVersionInfo worker = await PythonHelpers.GetEnvironmentPythonVersion();

            if (worker.ExecutablePath == null)
            {
                throw new Exception("Python executable path should not be empty");
            }
        }
示例#11
0
        public async void InterpreterShouldHaveMajorVersion()
        {
            WorkerLanguageVersionInfo worker = await PythonHelpers.GetEnvironmentPythonVersion();

            if (worker.Major != 2 && worker.Major != 3)
            {
                throw new Exception("Python major version should be 2 or 3");
            }
        }
示例#12
0
        public override async Task RunAsync()
        {
            var functionAppRoot = string.IsNullOrEmpty(FolderName)
                ? Path.Combine(Environment.CurrentDirectory, FolderName)
                : ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            string outputPath;

            if (string.IsNullOrEmpty(OutputPath))
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, $"{Path.GetFileName(functionAppRoot)}");
            }
            else
            {
                outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath);
                if (FileSystemHelpers.DirectoryExists(outputPath))
                {
                    outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}");
                }
            }

            if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)))
            {
                throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}");
            }

            var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager);

            outputPath += Squashfs ? ".squashfs" : ".zip";
            if (FileSystemHelpers.FileExists(outputPath))
            {
                ColoredConsole.WriteLine($"Deleting the old package {outputPath}");
                try
                {
                    FileSystemHelpers.FileDelete(outputPath);
                }
                catch (Exception)
                {
                    throw new CliException($"Could not delete {outputPath}");
                }
            }

            // Restore all valid extensions
            var installExtensionAction = new InstallExtensionAction(_secretsManager, false);
            await installExtensionAction.RunAsync();

            var stream = await ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, noBuild : false, buildOption : BuildOption.Default, additionalPackages : AdditionalPackages);

            if (Squashfs)
            {
                stream = await PythonHelpers.ZipToSquashfsStream(stream);
            }

            ColoredConsole.WriteLine($"Creating a new package {outputPath}");
            await FileSystemHelpers.WriteToFile(outputPath, stream);
        }
示例#13
0
 private async Task InitLanguageSpecificArtifacts(WorkerRuntime workerRuntime)
 {
     if (workerRuntime == Helpers.WorkerRuntime.python)
     {
         await PythonHelpers.InstallPackage();
     }
     else if (workerRuntime == Helpers.WorkerRuntime.powershell)
     {
         await WriteFiles("profile.ps1", await StaticResources.PowerShellProfilePs1);
     }
 }
示例#14
0
        private static async Task WritePythonDockerFile()
        {
            WorkerLanguageVersionInfo worker = await PythonHelpers.GetEnvironmentPythonVersion();

            if (worker?.Major == 3 && worker?.Minor == 7)
            {
                await WriteFiles("Dockerfile", await StaticResources.DockerfilePython37);
            }
            else
            {
                await WriteFiles("Dockerfile", await StaticResources.DockerfilePython36);
            }
        }
        private async Task PreRunConditions(WorkerRuntime workerRuntime)
        {
            if (workerRuntime == WorkerRuntime.python)
            {
                PythonHelpers.VerifyVirtualEnvironment();
            }
            else if (workerRuntime == WorkerRuntime.dotnet && Build)
            {
                const string outputPath = "bin/output";
                await DotnetHelpers.BuildDotnetProject(outputPath);

                Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
            }
        }
示例#16
0
 private async Task InitLanguageSpecificArtifacts(WorkerRuntime workerRuntime)
 {
     if (workerRuntime == Helpers.WorkerRuntime.python)
     {
         await PythonHelpers.InstallPackage();
     }
     else if (workerRuntime == Helpers.WorkerRuntime.powershell)
     {
         await WriteFiles("profile.ps1", await StaticResources.PowerShellProfilePs1);
     }
     if (Language == Constants.Languages.TypeScript)
     {
         await WriteFiles(".funcignore", await StaticResources.FuncIgnore);
         await WriteFiles("package.json", await StaticResources.PackageJson);
         await WriteFiles("tsconfig.json", await StaticResources.TsConfig);
     }
 }
示例#17
0
        public static async Task <Stream> GetAppZipFile(WorkerRuntime workerRuntime, string functionAppRoot, GitIgnoreParser ignoreParser = null)
        {
            var gitIgnorePath = Path.Combine(functionAppRoot, Constants.FuncIgnoreFile);

            if (ignoreParser == null && FileSystemHelpers.FileExists(gitIgnorePath))
            {
                ignoreParser = new GitIgnoreParser(await FileSystemHelpers.ReadAllTextFromFileAsync(gitIgnorePath));
            }

            if (workerRuntime == WorkerRuntime.python)
            {
                return(await PythonHelpers.GetPythonDeploymentPackage(GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot));
            }
            else
            {
                return(CreateZip(GetLocalFiles(functionAppRoot, ignoreParser), functionAppRoot));
            }
        }
        private async Task InternalPublishFunctionApp(GitIgnoreParser ignoreParser)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName);

            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            if (functionApp.IsLinux && !functionApp.IsDynamicLinux && RunFromZipDeploy)
            {
                ColoredConsole
                .WriteLine(ErrorColor("--zip is not supported with dedicated linux apps."));
                return;
            }

            var workerRuntime = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;

            if (!string.IsNullOrWhiteSpace(workerRuntime))
            {
                var worker = WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);
                if (worker == WorkerRuntime.python)
                {
                    if (!SkipWheelRestore)
                    {
                        await PythonHelpers.InstallPipWheel();

                        await PythonHelpers.DownloadWheels();
                    }
                    else
                    {
                        ColoredConsole.WriteLine("Skipping wheels download");
                    }
                }
            }

            // if consumption linux, or --zip, run from zip
            if (functionApp.IsDynamicLinux || RunFromZipDeploy)
            {
                await PublishRunFromZip(functionApp, functionAppRoot, ignoreParser);
            }
            else
            {
                await PublishZipDeploy(functionApp, functionAppRoot, ignoreParser);
            }
        }
示例#19
0
        private async Task PreRunConditions(WorkerRuntime workerRuntime)
        {
            if (workerRuntime == WorkerRuntime.python)
            {
                PythonHelpers.VerifyVirtualEnvironment();
            }
            else if (workerRuntime == WorkerRuntime.dotnet && Build)
            {
                const string outputPath = "bin/output";
                await DotnetHelpers.BuildDotnetProject(outputPath, string.Empty);

                Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
            }

            if (!NetworkHelpers.IsPortAvailable(Port))
            {
                throw new CliException($"Port {Port} is unavailable. Close the process using that port, or specify another port using --port [-p].");
            }
        }
        private async Task PreRunConditions()
        {
            if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python)
            {
                await PythonHelpers.ValidatePythonVersion(setWorkerExecutable : true, errorIfNoExactMatch : true, errorOutIfOld : true);

                // We need to update the PYTHONPATH to add worker's dependencies
                var pythonPath       = Environment.GetEnvironmentVariable("PYTHONPATH") ?? string.Empty;
                var pythonWorkerDeps = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "workers", "python", "deps");
                if (!pythonPath.Contains(pythonWorkerDeps))
                {
                    Environment.SetEnvironmentVariable("PYTHONPATH", $"{pythonPath}{Path.PathSeparator}{pythonWorkerDeps}", EnvironmentVariableTarget.Process);
                }
                if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine($"PYTHONPATH for the process is: {Environment.GetEnvironmentVariable("PYTHONPATH")}");
                }
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.dotnet && !NoBuild)
            {
                if (DotnetHelpers.CanDotnetBuild())
                {
                    var outputPath = Path.Combine("bin", "output");
                    await DotnetHelpers.BuildDotnetProject(outputPath, string.Empty);

                    Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
                }
                else if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build.");
                }
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.powershell && !CommandChecker.CommandExists("dotnet"))
            {
                throw new CliException("Dotnet is required for PowerShell Functions. Please install dotnet (.NET Core SDK) for your system from https://www.microsoft.com/net/download");
            }

            if (!NetworkHelpers.IsPortAvailable(Port))
            {
                throw new CliException($"Port {Port} is unavailable. Close the process using that port, or specify another port using --port [-p].");
            }
        }
        public async Task init_with_python_Dockerfile()
        {
            WorkerLanguageVersionInfo worker = await PythonHelpers.GetEnvironmentPythonVersion();

            Skip.If(worker == null);

            await CliTester.Run(new RunConfiguration
            {
                Commands   = new[] { $"init . --worker-runtime python --docker" },
                CheckFiles = new[]
                {
                    new FileResult
                    {
                        Name            = "Dockerfile",
                        ContentContains = new[] { $"FROM mcr.microsoft.com/azure-functions/python:2.0-python{worker.Major}.{worker.Minor}" }
                    }
                },
                OutputContains = new[] { "Dockerfile" }
            }, _output);
        }
示例#22
0
        /// <summary>
        /// Handler for Linux Consumption publish event
        /// </summary>
        /// <param name="functionAppRoot">Function App project path in local machine</param>
        /// <param name="functionApp">Function App in Azure</param>
        /// <param name="fileNameNoExtension">Name of the file to be uploaded</param>
        /// <returns>ShouldSyncTrigger value</returns>
        private async Task <bool> HandleLinuxConsumptionPublish(string functionAppRoot, Site functionApp, string fileNameNoExtension)
        {
            // Choose if the content need to use remote build
            BuildOption     buildOption  = PublishHelper.UpdateLinuxConsumptionBuildOption(PublishBuildOption);
            GitIgnoreParser ignoreParser = PublishHelper.GetIgnoreParser(functionAppRoot);

            // We update the buildOption, so we need to update the zipFileStream factory as well
            Func <Task <Stream> > zipFileStreamTask = () => ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, buildOption, NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            // Consumption Linux, try squashfs as a package format.
            if (GlobalCoreToolsSettings.CurrentWorkerRuntimeOrNone == WorkerRuntime.python && !NoBuild && (BuildNativeDeps || buildOption == BuildOption.Remote))
            {
                if (BuildNativeDeps)
                {
                    await PublishRunFromPackage(functionApp, await PythonHelpers.ZipToSquashfsStream(await zipFileStreamTask()), $"{fileNameNoExtension}.squashfs");

                    return(true);
                }

                // Remote build don't need sync trigger, container will be deallocated once the build is finished
                if (buildOption == BuildOption.Remote)
                {
                    await RemoveFunctionAppAppSetting(functionApp,
                                                      "WEBSITE_RUN_FROM_PACKAGE",
                                                      "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                                                      "WEBSITE_CONTENTSHARE");
                    Task <DeployStatus> pollConsumptionBuild(HttpClient client) => KuduLiteDeploymentHelpers.WaitForConsumptionServerSideBuild(client, functionApp, AccessToken, ManagementURL);

                    var deployStatus = await PerformServerSideBuild(functionApp, zipFileStreamTask, pollConsumptionBuild);

                    return(deployStatus == DeployStatus.Success);
                }
            }
            else
            {
                await PublishRunFromPackage(functionApp, await zipFileStreamTask(), $"{fileNameNoExtension}.zip");

                return(true);
            }
            return(true);
        }
示例#23
0
        private async Task PreRunConditions(WorkerRuntime workerRuntime)
        {
            if (workerRuntime == WorkerRuntime.python)
            {
                await PythonHelpers.VerifyPythonVersions(setWorkerExecutable : true);

                // We need to update the PYTHONPATH to add worker's dependencies
                var pythonPath       = Environment.GetEnvironmentVariable("PYTHONPATH") ?? string.Empty;
                var pythonWorkerDeps = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "workers", "python", "deps");
                if (!pythonPath.Contains(pythonWorkerDeps))
                {
                    Environment.SetEnvironmentVariable("PYTHONPATH", $"{pythonWorkerDeps}{Path.PathSeparator}{pythonPath}", EnvironmentVariableTarget.Process);
                }
                if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine($"PYTHONPATH for the process is: {Environment.GetEnvironmentVariable("PYTHONPATH")}");
                }
            }
            else if (workerRuntime == WorkerRuntime.dotnet && !NoBuild)
            {
                if (DotnetHelpers.CanDotnetBuild())
                {
                    var outputPath = Path.Combine("bin", "output");
                    await DotnetHelpers.BuildDotnetProject(outputPath, string.Empty);

                    Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath);
                }
                else if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build.");
                }
            }

            if (!NetworkHelpers.IsPortAvailable(Port))
            {
                throw new CliException($"Port {Port} is unavailable. Close the process using that port, or specify another port using --port [-p].");
            }
        }
示例#24
0
        /// <summary>
        /// Handler for Linux Consumption publish event
        /// </summary>
        /// <param name="functionApp">Function App in Azure</param>
        /// <param name="zipFileFactory">Factory for local project zipper</param>
        /// <returns>ShouldSyncTrigger value</returns>
        private async Task <bool> HandleLinuxConsumptionPublish(Site functionApp, Func <Task <Stream> > zipFileFactory)
        {
            string fileNameNoExtension = string.Format("{0}-{1}", DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmss"), Guid.NewGuid());

            // Consumption Linux, try squashfs as a package format.
            if (PublishBuildOption == BuildOption.Remote)
            {
                await RemoveFunctionAppAppSetting(functionApp,
                                                  "WEBSITE_RUN_FROM_PACKAGE",
                                                  "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                                                  "WEBSITE_CONTENTSHARE");
                Task <DeployStatus> pollConsumptionBuild(HttpClient client) => KuduLiteDeploymentHelpers.WaitForConsumptionServerSideBuild(client, functionApp, AccessToken, ManagementURL);

                var deployStatus = await PerformServerSideBuild(functionApp, zipFileFactory, pollConsumptionBuild);

                return(deployStatus == DeployStatus.Success);
            }
            else if (PublishBuildOption == BuildOption.Local)
            {
                await PublishRunFromPackage(functionApp, await zipFileFactory(), $"{fileNameNoExtension}.zip");

                return(true);
            }
            else if (GlobalCoreToolsSettings.CurrentWorkerRuntimeOrNone == WorkerRuntime.python && !NoBuild && BuildNativeDeps)
            {
                await PublishRunFromPackage(functionApp, await PythonHelpers.ZipToSquashfsStream(await zipFileFactory()), $"{fileNameNoExtension}.squashfs");

                return(true);
            }
            else
            {
                await PublishRunFromPackage(functionApp, await zipFileFactory(), $"{fileNameNoExtension}.zip");

                return(true);
            }
        }
示例#25
0
        private async Task PublishFunctionApp(Site functionApp, GitIgnoreParser ignoreParser, IDictionary <string, string> additionalAppSettings)
        {
            ColoredConsole.WriteLine("Getting site publishing info...");
            var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory);

            // For dedicated linux apps, we do not support run from package right now
            var isFunctionAppDedicated = !functionApp.IsDynamic && !functionApp.IsElasticPremium;

            if (functionApp.IsLinux && isFunctionAppDedicated && RunFromPackageDeploy)
            {
                ColoredConsole.WriteLine("Assuming --nozip (do not run from package) for publishing to Linux dedicated plan.");
                RunFromPackageDeploy = false;
            }

            var workerRuntime     = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value;
            var workerRuntimeEnum = string.IsNullOrEmpty(workerRuntime) ? WorkerRuntime.None : WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime);

            if (workerRuntimeEnum == WorkerRuntime.python && !functionApp.IsLinux)
            {
                throw new CliException("Publishing Python functions is only supported for Linux FunctionApps");
            }

            Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(workerRuntimeEnum, functionAppRoot, BuildNativeDeps, NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true);

            bool shouldSyncTriggers  = true;
            var  fileNameNoExtension = string.Format("{0}-{1}", DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmss"), Guid.NewGuid());

            if (functionApp.IsLinux && functionApp.IsDynamic)
            {
                // Consumption Linux, try squashfs as a package format.
                if (workerRuntimeEnum == WorkerRuntime.python && !NoBuild && BuildNativeDeps)
                {
                    await PublishRunFromPackage(functionApp, await PythonHelpers.ZipToSquashfsStream(await zipStreamFactory()), $"{fileNameNoExtension}.squashfs");
                }
                else
                {
                    await PublishRunFromPackage(functionApp, await zipStreamFactory(), $"{fileNameNoExtension}.zip");
                }
            }
            else if (functionApp.IsLinux && functionApp.IsElasticPremium)
            {
                // Elastic Premium Linux
                await PublishRunFromPackage(functionApp, await zipStreamFactory(), $"{fileNameNoExtension}.zip");
            }
            else if (RunFromPackageDeploy)
            {
                // Windows default
                await PublishRunFromPackageLocal(functionApp, zipStreamFactory);
            }
            else
            {
                // ZipDeploy takes care of the SyncTriggers operation so we don't
                // need to perform one
                shouldSyncTriggers = false;

                // Dedicated Linux or "--no-zip"
                await PublishZipDeploy(functionApp, zipStreamFactory);
            }

            if (PublishLocalSettings)
            {
                await PublishLocalAppSettings(functionApp, additionalAppSettings);
            }
            else if (additionalAppSettings.Any())
            {
                await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings);
            }

            if (shouldSyncTriggers)
            {
                await Task.Delay(TimeSpan.FromSeconds(5));
                await SyncTriggers(functionApp);
            }

            // Linux Elastic Premium functions take longer to deploy. Right now, we cannot guarantee that functions info will be most up to date.
            // So, we only show the info, if Function App is not Linux Elastic Premium
            if (!(functionApp.IsLinux && functionApp.IsElasticPremium))
            {
                await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, ManagementURL, showKeys : true);
            }
        }
示例#26
0
        private async Task <IDictionary <string, string> > ValidateFunctionAppPublish(Site functionApp, WorkerRuntime workerRuntime)
        {
            var result = new Dictionary <string, string>();

            // Check version
            if (!functionApp.IsLinux)
            {
                if (functionApp.AzureAppSettings.TryGetValue(Constants.FunctionsExtensionVersion, out string version))
                {
                    // v2 can be either "~2", "beta", or an exact match like "2.0.11961-alpha"
                    if (!version.Equals("~2") &&
                        !version.StartsWith("2.0") &&
                        !version.Equals("beta", StringComparison.OrdinalIgnoreCase))
                    {
                        if (Force)
                        {
                            result.Add(Constants.FunctionsExtensionVersion, "~2");
                        }
                        else
                        {
                            throw new CliException("You're trying to publish to a non-v2 function app from v2 tooling.\n" +
                                                   "You can pass --force to force update the app to v2, or switch to v1 or v3 tooling for publishing");
                        }
                    }
                }
            }

            if (functionApp.AzureAppSettings.TryGetValue(Constants.FunctionsWorkerRuntime, out string workerRuntimeStr))
            {
                var resolution = $"You can pass --force to update your Azure app with '{workerRuntime}' as a '{Constants.FunctionsWorkerRuntime}'";
                try
                {
                    var azureWorkerRuntime = WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntimeStr);
                    if (azureWorkerRuntime != workerRuntime)
                    {
                        if (Force)
                        {
                            ColoredConsole.WriteLine(WarningColor($"Setting '{Constants.FunctionsWorkerRuntime}' to '{workerRuntime}' because --force was passed"));
                            result[Constants.FunctionsWorkerRuntime] = workerRuntime.ToString();
                        }
                        else
                        {
                            throw new CliException($"Your Azure Function App has '{Constants.FunctionsWorkerRuntime}' set to '{azureWorkerRuntime}' while your local project is set to '{workerRuntime}'.\n"
                                                   + resolution);
                        }
                    }
                }
                catch (ArgumentException) when(Force)
                {
                    result[Constants.FunctionsWorkerRuntime] = workerRuntime.ToString();
                }
                catch (ArgumentException) when(!Force)
                {
                    throw new CliException($"Your app has an unknown {Constants.FunctionsWorkerRuntime} defined '{workerRuntimeStr}'. Only {WorkerRuntimeLanguageHelper.AvailableWorkersRuntimeString} are supported.\n" +
                                           resolution);
                }
            }

            if (!functionApp.AzureAppSettings.ContainsKey("AzureWebJobsStorage") && functionApp.IsDynamic)
            {
                throw new CliException($"'{FunctionAppName}' app is missing AzureWebJobsStorage app setting. That setting is required for publishing consumption linux apps.");
            }

            if (functionApp.IsLinux && !functionApp.IsDynamic && !string.IsNullOrEmpty(functionApp.LinuxFxVersion))
            {
                // If linuxFxVersion does not match any of our images
                if (PublishHelper.IsLinuxFxVersionUsingCustomImage(functionApp.LinuxFxVersion))
                {
                    ColoredConsole.WriteLine($"Your functionapp is using a custom image {functionApp.LinuxFxVersion}.\nAssuming that the image contains the correct framework.\n");
                }
                // If there the functionapp is our image but does not match the worker runtime image, we either fail or force update
                else if (!PublishHelper.IsLinuxFxVersionRuntimeMatched(functionApp.LinuxFxVersion, workerRuntime))
                {
                    if (Force)
                    {
                        var updatedSettings = new Dictionary <string, string>
                        {
                            [Constants.LinuxFxVersion] = $"DOCKER|{Constants.WorkerRuntimeImages.GetValueOrDefault(workerRuntime).FirstOrDefault()}"
                        };
                        var settingsResult = await AzureHelper.UpdateWebSettings(functionApp, updatedSettings, AccessToken, ManagementURL);

                        if (!settingsResult.IsSuccessful)
                        {
                            ColoredConsole.Error
                            .WriteLine(ErrorColor("Error updating linux image version:"))
                            .WriteLine(ErrorColor(settingsResult.ErrorResult));
                        }
                    }
                    else
                    {
                        throw new CliException($"Your Linux dedicated app has the container image version (LinuxFxVersion) set to {functionApp.LinuxFxVersion} which is not expected for the worker runtime {workerRuntime}. " +
                                               $"To force publish use --force. This will update your app to the expected image for worker runtime {workerRuntime}\n");
                    }
                }
            }

            // Check if azure-functions-worker exists in requirements.txt for Python function app
            if (workerRuntime == WorkerRuntime.python)
            {
                await PythonHelpers.WarnIfAzureFunctionsWorkerInRequirementsTxt();
            }

            return(result);
        }