/// <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); } }
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); }
/// <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); }
/// <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); } }
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); } }