Exemple #1
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);
            }
        }
Exemple #2
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);
        }
Exemple #3
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);
        }
Exemple #4
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);
            }
        }
Exemple #5
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);
            }
        }