public override async Task RunAsync() { var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); ColoredConsole.WriteLine(WarningColor($"Publish {functionAppRoot} contents to an Azure Function App. Locally deleted files are not removed from destination.")); ColoredConsole.WriteLine("Getting site publishing info..."); var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName); using (var client = await GetRemoteZipClient(new Uri($"https://{functionApp.ScmUri}"))) using (var request = new HttpRequestMessage()) { request.Method = HttpMethod.Put; request.RequestUri = new Uri("api/zip/site/wwwroot", UriKind.Relative); request.Headers.IfMatch.Add(EntityTagHeaderValue.Any); ColoredConsole.WriteLine("Creating archive for current directory..."); request.Content = CreateZip(functionAppRoot); ColoredConsole.WriteLine("Uploading archive..."); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); response = await client.PostAsync("api/functions/synctriggers", content : null); response.EnsureSuccessStatusCode(); ColoredConsole.WriteLine("Upload completed successfully."); } }
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)}.zip"); } else { outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath); if (FileSystemHelpers.DirectoryExists(outputPath)) { outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}.zip"); } } if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName))) { throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}"); } var workerRuntime = _secretsManager.GetSecrets().FirstOrDefault(s => s.Key.Equals(Constants.FunctionsWorkerRuntime, StringComparison.OrdinalIgnoreCase)).Value; var workerRuntimeEnum = string.IsNullOrEmpty(workerRuntime) ? WorkerRuntime.None : WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(workerRuntime); var zipStream = await GetAppZipFile(workerRuntimeEnum, functionAppRoot); await FileSystemHelpers.WriteToFile(outputPath, zipStream); }
private static async Task <bool> IsRightServer(Uri server) { try { var hostId = await GetHostId(ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory)); if (string.IsNullOrWhiteSpace(hostId)) { return(true); } using (var client = new HttpClient()) { var response = await client.GetAsync(new Uri(server, "admin/host/status")); response.EnsureSuccessStatusCode(); var hostStatus = await response.Content.ReadAsAsync <HostStatus>(); return(hostStatus.Id.Equals(hostId, StringComparison.OrdinalIgnoreCase)); } } catch { return(false); } }
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)}.zip"); } else { outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath); if (FileSystemHelpers.DirectoryExists(outputPath)) { outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}.zip"); } } if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName))) { throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}"); } var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager); var zipStream = await ZipHelper.GetAppZipFile(workerRuntime, functionAppRoot, BuildNativeDeps); await FileSystemHelpers.WriteToFile(outputPath, zipStream); }
public override async Task RunAsync() { Utilities.PrintLogo(); var traceLevel = await ScriptHostHelpers.GetTraceLevel(ScriptRoot); var settings = SelfHostWebHostSettingsFactory.Create(traceLevel, ScriptRoot); (var baseAddress, var certificate) = Setup(); IWebHost host = await BuildWebHost(settings, baseAddress, certificate); var runTask = host.RunAsync(); var manager = host.Services.GetRequiredService <WebScriptHostManager>(); await manager.DelayUntilHostReady(); ColoredConsole.WriteLine($"Listening on {baseAddress}"); ColoredConsole.WriteLine("Hit CTRL-C to exit..."); DisableCoreLogging(manager); DisplayHttpFunctionsInfo(manager, baseAddress); DisplayDisabledFunctions(manager); await SetupDebuggerAsync(baseAddress); await runTask; }
public override async Task RunAsync() { // Get function app var functionApp = await AzureHelper.GetFunctionApp(FunctionAppName, AccessToken, ManagementURL); // Get the GitIgnoreParser from the functionApp root var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); var ignoreParser = PublishHelper.GetIgnoreParser(functionAppRoot); // Get the WorkerRuntime var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager); // Check for any additional conditions or app settings that need to change // before starting any of the publish activity. var additionalAppSettings = await ValidateFunctionAppPublish(functionApp, workerRuntime); if (workerRuntime == WorkerRuntime.dotnet && !Csx && !NoBuild) { if (DotnetHelpers.CanDotnetBuild()) { var outputPath = Path.Combine("bin", "publish"); await DotnetHelpers.BuildDotnetProject(outputPath, DotnetCliParameters); Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath); } else if (StaticSettings.IsDebug) { ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build."); } } if (workerRuntime != WorkerRuntime.dotnet || Csx) { // Restore all valid extensions var installExtensionAction = new InstallExtensionAction(_secretsManager, false); await installExtensionAction.RunAsync(); } if (ListIncludedFiles) { InternalListIncludedFiles(ignoreParser); } else if (ListIgnoredFiles) { InternalListIgnoredFiles(ignoreParser); } else { if (PublishLocalSettingsOnly) { await PublishLocalAppSettings(functionApp, additionalAppSettings); } else { await PublishFunctionApp(functionApp, ignoreParser, additionalAppSettings); } } }
public override async Task RunAsync() { var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); ColoredConsole.WriteLine(WarningColor($"Publish {functionAppRoot} contents to an Azure Function App. Locally deleted files are not removed from destination.")); ColoredConsole.WriteLine("Getting site publishing info..."); var functionApp = await _armManager.GetFunctionAppAsync(FunctionAppName); if (PublishLocalSettingsOnly) { var isSuccessful = await PublishAppSettings(functionApp); if (!isSuccessful) { return; } } else { await RetryHelper.Retry(async() => { using (var client = await GetRemoteZipClient(new Uri($"https://{functionApp.ScmUri}"))) using (var request = new HttpRequestMessage(HttpMethod.Put, new Uri("api/zip/site/wwwroot", UriKind.Relative))) { request.Headers.IfMatch.Add(EntityTagHeaderValue.Any); ColoredConsole.WriteLine("Creating archive for current directory..."); request.Content = CreateZip(functionAppRoot); ColoredConsole.WriteLine("Uploading archive..."); var response = await client.SendAsync(request); if (!response.IsSuccessStatusCode) { throw new CliException($"Error uploading archive ({response.StatusCode})."); } response = await client.PostAsync("api/functions/synctriggers", content: null); if (!response.IsSuccessStatusCode) { throw new CliException($"Error calling sync triggers ({response.StatusCode})."); } if (PublishLocalSettings) { var isSuccessful = await PublishAppSettings(functionApp); if (!isSuccessful) { return; } } ColoredConsole.WriteLine("Upload completed successfully."); } }, 2); } }
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 if (functionApp.IsLinux && !functionApp.IsDynamic && 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); // If Consumption Linux if (functionApp.IsLinux && (functionApp.IsDynamic || functionApp.IsElasticPremium)) { await PublishRunFromPackage(functionApp, await zipStreamFactory()); } // If Windows default else if (RunFromPackageDeploy) { await PublishRunFromPackageLocal(functionApp, zipStreamFactory); } // If Dedicated Linux or "--no-zip" else { await PublishZipDeploy(functionApp, zipStreamFactory); } if (PublishLocalSettings) { await PublishLocalAppSettings(functionApp, additionalAppSettings); } else if (additionalAppSettings.Any()) { await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings); } // Syncing triggers is not required when using zipdeploy api if ((functionApp.IsLinux && (functionApp.IsDynamic || functionApp.IsElasticPremium)) || RunFromPackageDeploy) { await Task.Delay(TimeSpan.FromSeconds(5)); await SyncTriggers(functionApp); } await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, showKeys : 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); }
public override async Task RunAsync() { Utilities.PrintLogo(); var scriptPath = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); var traceLevel = await ScriptHostHelpers.GetTraceLevel(scriptPath); var settings = SelfHostWebHostSettingsFactory.Create(traceLevel, scriptPath); var baseAddress = Setup(); await ReadSecrets(scriptPath, baseAddress); var config = new HttpSelfHostConfiguration(baseAddress) { IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always, TransferMode = TransferMode.Streamed, HostNameComparisonMode = HostNameComparisonMode.Exact, MaxReceivedMessageSize = 1 * 1024 * 1024 * 100 // 1 byte * 1,024 * 1,024 * 100 = 100 MB (or 104,857,600 bytes) }; if (!string.IsNullOrEmpty(CorsOrigins)) { var cors = new EnableCorsAttribute(CorsOrigins, "*", "*"); config.EnableCors(cors); } config.Formatters.Add(new JsonMediaTypeFormatter()); Environment.SetEnvironmentVariable("EDGE_NODE_PARAMS", $"--debug={NodeDebugPort}", EnvironmentVariableTarget.Process); WebApiConfig.Initialize(config, settings: settings); using (var httpServer = new HttpSelfHostServer(config)) { await httpServer.OpenAsync(); ColoredConsole.WriteLine($"Listening on {baseAddress}"); ColoredConsole.WriteLine("Hit CTRL-C to exit..."); await PostHostStartActions(config); await Task.Delay(-1); await httpServer.CloseAsync(); } }
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)}.zip"); } else { outputPath = Path.Combine(Environment.CurrentDirectory, OutputPath); if (FileSystemHelpers.DirectoryExists(outputPath)) { outputPath = Path.Combine(outputPath, $"{Path.GetFileName(functionAppRoot)}.zip"); } } if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName))) { throw new CliException($"Can't find {Path.Combine(functionAppRoot, ScriptConstants.HostMetadataFileName)}"); } var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager); if (FileSystemHelpers.FileExists(outputPath)) { ColoredConsole.WriteLine($"Deleting the old package {outputPath}"); try { FileSystemHelpers.FileDelete(outputPath); } catch (Exception) { throw new CliException($"Could not delete {outputPath}"); } } var zipStream = await ZipHelper.GetAppZipFile(workerRuntime, functionAppRoot, BuildNativeDeps, NoBundler, additionalPackages : AdditionalPackages); ColoredConsole.WriteLine($"Creating a new package {outputPath}"); await FileSystemHelpers.WriteToFile(outputPath, zipStream); }
private async Task PublishFunctionApp(Site functionApp, GitIgnoreParser ignoreParser, IDictionary <string, string> additionalAppSettings) { ColoredConsole.WriteLine("Getting site publishing info..."); var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); if (functionApp.IsLinux && !functionApp.IsDynamic && RunFromZipDeploy) { throw new CliException("--zip is not supported with dedicated linux apps."); } 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, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true); // if consumption Linux, or --zip, run from zip if ((functionApp.IsLinux && functionApp.IsDynamic) || RunFromZipDeploy) { await PublishRunFromZip(functionApp, await zipStreamFactory()); } else { await PublishZipDeploy(functionApp, zipStreamFactory); } if (PublishLocalSettings) { await PublishLocalAppSettings(functionApp, additionalAppSettings); } else if (additionalAppSettings.Any()) { await PublishAppSettings(functionApp, new Dictionary <string, string>(), additionalAppSettings); } await Task.Delay(TimeSpan.FromSeconds(5)); await SyncTriggers(functionApp); await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, showKeys : true); }
public override async Task RunAsync() { // Get function app var functionApp = await AzureHelper.GetFunctionApp(FunctionAppName, AccessToken); // Get the GitIgnoreParser from the functionApp root var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); var ignoreParser = PublishHelper.GetIgnoreParser(functionAppRoot); // Get the WorkerRuntime var workerRuntime = WorkerRuntimeLanguageHelper.GetCurrentWorkerRuntimeLanguage(_secretsManager); // Check for any additional conditions or app settings that need to change // before starting any of the publish activity. var additionalAppSettings = ValidateFunctionAppPublish(functionApp, workerRuntime); if (workerRuntime == WorkerRuntime.dotnet && !Csx && !NoBuild) { const string outputPath = "bin/publish"; await DotnetHelpers.BuildDotnetProject(outputPath, DotnetCliParameters); Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath); } if (ListIncludedFiles) { InternalListIncludedFiles(ignoreParser); } else if (ListIgnoredFiles) { InternalListIgnoredFiles(ignoreParser); } else { if (PublishLocalSettingsOnly) { await PublishLocalAppSettings(functionApp, additionalAppSettings); } else { await PublishFunctionApp(functionApp, ignoreParser, additionalAppSettings); } } }
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); } }
public override async Task RunAsync() { Utilities.PrintLogo(); var scriptPath = IgnoreHostJsonNotFound ? Environment.CurrentDirectory : ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); var settings = SelfHostWebHostSettingsFactory.Create(ConsoleTraceLevel, scriptPath); ReadSecrets(); CheckHostJsonId(); var baseAddress = Setup(); var config = new HttpSelfHostConfiguration(baseAddress) { IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always, TransferMode = TransferMode.Streamed }; var cors = new EnableCorsAttribute(CorsOrigins, "*", "*"); config.EnableCors(cors); config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); Environment.SetEnvironmentVariable("EDGE_NODE_PARAMS", $"--debug={NodeDebugPort}", EnvironmentVariableTarget.Process); WebApiConfig.Initialize(config, settings: settings); using (var httpServer = new HttpSelfHostServer(config)) { await httpServer.OpenAsync(); ColoredConsole.WriteLine($"Listening on {baseAddress}"); ColoredConsole.WriteLine("Hit CTRL-C to exit..."); await PostHostStartActions(config); await Task.Delay(-1); await httpServer.CloseAsync(); } }
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.IsDynamic && 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; 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"); } var zipStream = await ZipHelper.GetAppZipFile(workerRuntimeEnum, functionAppRoot, BuildNativeDeps, ignoreParser); // if consumption Linux, or --zip, run from zip if ((functionApp.IsLinux && functionApp.IsDynamic) || RunFromZipDeploy) { await PublishRunFromZip(functionApp, zipStream); } else { await PublishZipDeploy(functionApp, zipStream); } await SyncTriggers(functionApp); if (PublishLocalSettings) { await PublishAppSettings(functionApp); } }
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.")); } // if consumption linux, or --zip, run from zip else if (functionApp.IsDynamicLinux || RunFromZipDeploy) { await PublishRunFromZip(functionApp, functionAppRoot, ignoreParser); } else { await PublishZipDeploy(functionApp, functionAppRoot, ignoreParser); } // else same old same old }
public override Task RunAsync() { ScriptHostHelpers.SetIsHelpRunning(); Utilities.PrintLogo(); if (!string.IsNullOrEmpty(_context) || !string.IsNullOrEmpty(_subContext)) { var context = Context.None; var subContext = Context.None; if (!string.IsNullOrEmpty(_context) && !Enum.TryParse(_context, true, out context)) { ColoredConsole.Error.WriteLine(ErrorColor($"Error: unknown argument {_context}")); DisplayGeneralHelp(); return(Task.CompletedTask); } if (!string.IsNullOrEmpty(_subContext) && !Enum.TryParse(_subContext, true, out subContext)) { ColoredConsole.Error.WriteLine(ErrorColor($"Error: unknown argument {_subContext} in {context.ToLowerCaseString()} Context")); DisplayContextHelp(context, Context.None); return(Task.CompletedTask); } DisplayContextHelp(context, subContext); } else if (_action != null && _parseResult != null) { DisplayActionHelp(); } else { DisplayGeneralHelp(); } return(Task.CompletedTask); }
public override async Task RunAsync() { // Get function app var functionApp = await AzureHelper.GetFunctionApp(FunctionAppName, AccessToken, ManagementURL, Slot, Subscription); if (!functionApp.IsLinux && (PublishBuildOption == BuildOption.Container || PublishBuildOption == BuildOption.Remote)) { throw new CliException($"--build {PublishBuildOption} is not supported for Windows Function Apps."); } // Get the GitIgnoreParser from the functionApp root var functionAppRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory); var ignoreParser = PublishHelper.GetIgnoreParser(functionAppRoot); // Get the WorkerRuntime var workerRuntime = GlobalCoreToolsSettings.CurrentWorkerRuntime; // Check for any additional conditions or app settings that need to change // before starting any of the publish activity. var additionalAppSettings = await ValidateFunctionAppPublish(functionApp, workerRuntime); // Update build option PublishBuildOption = PublishHelper.ResolveBuildOption(PublishBuildOption, workerRuntime, functionApp, BuildNativeDeps, NoBuild); if (workerRuntime == WorkerRuntime.dotnet && !Csx && !NoBuild && PublishBuildOption != BuildOption.Remote) { if (DotnetHelpers.CanDotnetBuild()) { var outputPath = Path.Combine("bin", "publish"); await DotnetHelpers.BuildDotnetProject(outputPath, DotnetCliParameters); Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, outputPath); } else if (StaticSettings.IsDebug) { ColoredConsole.WriteLine("Could not find a valid .csproj file. Skipping the build."); } } if (workerRuntime != WorkerRuntime.dotnet || Csx) { // Restore all valid extensions var installExtensionAction = new InstallExtensionAction(_secretsManager, false); await installExtensionAction.RunAsync(); } if (ListIncludedFiles) { InternalListIncludedFiles(ignoreParser); } else if (ListIgnoredFiles) { InternalListIgnoredFiles(ignoreParser); } else { if (PublishLocalSettingsOnly) { await PublishLocalAppSettings(functionApp, additionalAppSettings); } else { await PublishFunctionApp(functionApp, ignoreParser, additionalAppSettings); } } }
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); } }
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 isFunctionAppDedicatedLinux = functionApp.IsLinux && !functionApp.IsDynamic && !functionApp.IsElasticPremium; if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python && !functionApp.IsLinux) { throw new CliException("Publishing Python functions is only supported for Linux FunctionApps"); } // Recommend Linux scm users to use --build remote instead of --build-native-deps if (BuildNativeDeps && functionApp.IsLinux && !string.IsNullOrEmpty(functionApp.ScmUri)) { ColoredConsole.WriteLine(Yellow("Recommend using '--build remote' to resolve project dependencies remotely on Azure")); } Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, PublishBuildOption, NoBuild, ignoreParser, AdditionalPackages, ignoreDotNetCheck: true); bool shouldSyncTriggers = true; if (functionApp.IsLinux && functionApp.IsDynamic) { // Consumption Linux shouldSyncTriggers = await HandleLinuxConsumptionPublish(functionApp, zipStreamFactory); } else if (functionApp.IsLinux && functionApp.IsElasticPremium) { // Elastic Premium Linux shouldSyncTriggers = await HandleElasticPremiumLinuxPublish(functionApp, zipStreamFactory); } else if (isFunctionAppDedicatedLinux) { // Dedicated Linux shouldSyncTriggers = false; await HandleLinuxDedicatedPublish(functionApp, zipStreamFactory); } 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; // "--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. So do Linux Dedicated Function Apps with remote build // 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 // or a Linux Dedicated Function App with remote build if (!(functionApp.IsLinux && functionApp.IsElasticPremium) && !(isFunctionAppDedicatedLinux && PublishBuildOption == BuildOption.Remote)) { await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, ManagementURL, showKeys : true); } }
public override async Task RunAsync() { using (var client = await _scriptServer.ConnectAsync(Timeout, NoInteractive)) { var hostStatusResponse = await client.GetAsync("admin/host/status"); var functionStatusResponse = await client.GetAsync($"admin/functions/{FunctionName}/status"); if (!hostStatusResponse.IsSuccessStatusCode) { ColoredConsole .Error .WriteLine(ErrorColor($"Error calling the functions host: {hostStatusResponse.StatusCode}")); return; } else if (!functionStatusResponse.IsSuccessStatusCode) { ColoredConsole .Error .WriteLine(ErrorColor($"Error calling function {FunctionName}: {functionStatusResponse.StatusCode}")); return; } var functionMetadata = ScriptHostHelpers.GetFunctionMetadata(FunctionName); var hostStatus = await hostStatusResponse.Content.ReadAsAsync <HostStatus>(); Func <IEnumerable <string>, string, bool> printError = (errors, title) => { if (errors?.Any() == true) { ColoredConsole .Error .WriteLine(ErrorColor(title)); foreach (var error in errors) { ColoredConsole .Error .WriteLine(ErrorColor($"\t{error}")); } return(true); } return(false); }; if (printError(hostStatus.Errors, "The function host has the following errors:") || printError(hostStatus.Errors, $"Function {FunctionName} has the following errors:")) { return; } if (Debug) { var scriptType = functionMetadata.ScriptType; if (scriptType != ScriptType.CSharp && scriptType != ScriptType.Javascript) { ColoredConsole .Error .WriteLine(ErrorColor($"Only C# and Javascript functions are currently supported for debugging.")); return; } if (scriptType == ScriptType.CSharp) { ColoredConsole .WriteLine("Debugger launching...") .WriteLine("Setup your break points, and hit continue!"); await DebuggerHelper.AttachManagedAsync(client); } else if (scriptType == ScriptType.Javascript) { var nodeDebugger = await DebuggerHelper.TrySetupNodeDebuggerAsync(); if (nodeDebugger == NodeDebuggerStatus.Error) { ColoredConsole .Error .WriteLine(ErrorColor("Unable to configure node debugger. Check your launch.json.")); return; } else if (!NoInteractive) { ColoredConsole.WriteLine("launch.json configured."); } else { ColoredConsole .Write("launch.json configured. Setup your break points, launch debugger (F5), and press any key to continue..."); Console.ReadKey(); } } } var invocation = string.IsNullOrEmpty(FileName) ? Content : await FileSystemHelpers.ReadAllTextFromFileAsync(FileName); invocation = invocation ?? string.Empty; var adminInvocation = JsonConvert.SerializeObject(new FunctionInvocation { Input = invocation }); if (functionMetadata.IsHttpFunction()) { ColoredConsole.WriteLine(WarningColor("NOTE: the 'func run' command only supports POST for HTTP triggers. For other verbs, consider a REST client like cURL or Postman.")); } var response = functionMetadata.IsHttpFunction() ? await client.PostAsync($"api/{FunctionName}", new StringContent(invocation, Encoding.UTF8, invocation.IsJson() ? "application/json" : "plain/text")) : await client.PostAsync($"admin/functions/{FunctionName}", new StringContent(adminInvocation, Encoding.UTF8, "application/json")); ColoredConsole.WriteLine($"{TitleColor($"Response Status Code:")} {response.StatusCode}"); var contentTask = response.Content?.ReadAsStringAsync(); if (contentTask != null) { var content = await contentTask; if (!response.IsSuccessStatusCode) { try { var exception = JsonConvert.DeserializeObject <JObject>(content); if (exception?["InnerException"]?["ExceptionMessage"]?.ToString() == "Script compilation failed.") { ColoredConsole.Error.WriteLine(ErrorColor("Script compilation failed.")); return; } } catch { } } ColoredConsole.WriteLine(await contentTask); } } }
private async Task <Uri> DiscoverServer(int iteration = 0) { var server = new Uri($"http://localhost:{Port + iteration}"); if (!await server.IsServerRunningAsync()) { // create the server if (_settings.DisplayLaunchingRunServerWarning) { ColoredConsole .WriteLine() .WriteLine("We need to launch a server that will host and run your functions.") .WriteLine("The server will auto load any changes you make to the function."); string answer = null; do { ColoredConsole .Write(QuestionColor("Do you want to always display this warning before launching a new server [yes/no]? [yes] ")); answer = Console.ReadLine()?.Trim()?.ToLowerInvariant(); answer = string.IsNullOrEmpty(answer) ? "yes" : answer; } while (answer != "yes" && answer != "no"); _settings.DisplayLaunchingRunServerWarning = answer == "yes" ? true : false; } //TODO: factor out to PlatformHelper.LaunchInNewConsole and implement for Mac using AppleScript var exeName = System.Reflection.Assembly.GetEntryAssembly().Location; var exe = PlatformHelper.IsWindows ? new Executable(exeName, $"host start -p {Port + iteration}", streamOutput: false, shareConsole: true) : new Executable("mono", $"{exeName} host start -p {Port + iteration}", streamOutput: false, shareConsole: false); exe.RunAsync().Ignore(); await Task.Delay(500); if (PlatformHelper.IsWindows) { ConsoleNativeMethods.GetFocusBack(); } return(server); } else { var hostId = await GetHostId(ScriptHostHelpers.GetFunctionAppRootDirectory(Environment.CurrentDirectory)); using (var client = new HttpClient()) { var response = await client.GetAsync(new Uri(server, "admin/host/status")); response.EnsureSuccessStatusCode(); var hostStatus = await response.Content.ReadAsAsync <HostStatus>(); if (!hostStatus.Id.Equals(hostId, StringComparison.OrdinalIgnoreCase)) { return(await DiscoverServer(iteration + 1)); } else { return(server); } } } }
public override ICommandLineParserResult ParseArgs(string[] args) { var hostSettings = _secretsManager.GetHostStartSettings(); Parser .Setup <int>('p', "port") .WithDescription($"Local port to listen on. Default: {DefaultPort}") .SetDefault(hostSettings.LocalHttpPort == default(int) ? DefaultPort : hostSettings.LocalHttpPort) .Callback(p => Port = p); Parser .Setup <string>("cors") .WithDescription($"A comma separated list of CORS origins with no spaces. Example: https://functions.azure.com,https://functions-staging.azure.com") .SetDefault(hostSettings.Cors ?? string.Empty) .Callback(c => CorsOrigins = c); Parser .Setup <int>('t', "timeout") .WithDescription($"Timeout for on the functions host to start in seconds. Default: {DefaultTimeout} seconds.") .SetDefault(DefaultTimeout) .Callback(t => Timeout = t); Parser .Setup <bool>("useHttps") .WithDescription("Bind to https://localhost:{port} rather than http://localhost:{port}. By default it creates and trusts a certificate.") .SetDefault(false) .Callback(s => UseHttps = s); Parser .Setup <string>("cert") .WithDescription("for use with --useHttps. The path to a pfx file that contains a private key") .Callback(c => CertPath = c); Parser .Setup <string>("password") .WithDescription("to use with --cert. Either the password, or a file that contains the password for the pfx file") .Callback(p => CertPassword = p); Parser .Setup <DebuggerType>("debug") .WithDescription("Default is None. Options are VSCode and VS") .SetDefault(DebuggerType.None) .Callback(d => Debugger = d); Parser .Setup <string>('w', "workers") .WithDescription("Arguments to configure language workers, separated by ','. Example: --workers node:debug=<node-debug-port>,java:path=<path-to-worker-jar>") .Callback(w => { foreach (var arg in w.Split(',')) { var pair = arg.Split('='); var section = pair[0]; var value = pair.Count() == 2 ? pair[1] : string.Empty; IConfigurationArguments[section] = value; } }); Parser .Setup <string>("script-root") .WithDescription($"The path to the root of the function app where the command will be executed.") .SetDefault(".") .Callback(dir => { var fullDirPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, dir)); ScriptRoot = ScriptHostHelpers.GetFunctionAppRootDirectory(fullDirPath); }); return(Parser.Parse(args)); }
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 isFunctionAppDedicatedLinux = functionApp.IsLinux && !functionApp.IsDynamic && !functionApp.IsElasticPremium; // For Python linux apps, we do not support --build remote with --build-native-deps flag if (PublishBuildOption == BuildOption.Remote && BuildNativeDeps) { throw new CliException("Cannot use '--build remote' along with '--build-native-deps'"); } else if (PublishBuildOption == BuildOption.Local || PublishBuildOption == BuildOption.Container || PublishBuildOption == BuildOption.None) { throw new CliException("The --build flag only supports '--build remote'"); } if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.python && !functionApp.IsLinux) { throw new CliException("Publishing Python functions is only supported for Linux FunctionApps"); } Func <Task <Stream> > zipStreamFactory = () => ZipHelper.GetAppZipFile(functionAppRoot, BuildNativeDeps, PublishBuildOption, 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 shouldSyncTriggers = await HandleLinuxConsumptionPublish(functionAppRoot, functionApp, fileNameNoExtension); } else if (functionApp.IsLinux && functionApp.IsElasticPremium) { // Elastic Premium Linux shouldSyncTriggers = await HandleElasticPremiumLinuxPublish(functionApp, zipStreamFactory, $"{fileNameNoExtension}.zip"); } else if (isFunctionAppDedicatedLinux) { // Dedicated Linux shouldSyncTriggers = false; await HandleLinuxDedicatedPublish(zipStreamFactory, functionApp); } 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; // "--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. So do Linux Dedicated Function Apps with remote build // 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 // or a Linux Dedicated Function App with remote build if (!(functionApp.IsLinux && functionApp.IsElasticPremium) && !(isFunctionAppDedicatedLinux && PublishBuildOption == BuildOption.Remote)) { await AzureHelper.PrintFunctionsInfo(functionApp, AccessToken, ManagementURL, showKeys : true); } }