internal static async Task <Stream> GetPythonDeploymentPackage(IEnumerable <string> files, string functionAppRoot, bool buildNativeDeps, bool noBundler, string additionalPackages)
        {
            if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, Constants.RequirementsTxt)))
            {
                throw new CliException($"{Constants.RequirementsTxt} is not found. " +
                                       $"{Constants.RequirementsTxt} is required for python function apps. Please make sure to generate one before publishing.");
            }
            var externalPythonPackages = Path.Combine(functionAppRoot, Constants.ExternalPythonPackages);

            if (FileSystemHelpers.DirectoryExists(externalPythonPackages))
            {
                ColoredConsole.WriteLine($"Deleting the old {Constants.ExternalPythonPackages} directory");
                FileSystemHelpers.DeleteDirectorySafe(Path.Combine(functionAppRoot, Constants.ExternalPythonPackages));
            }

            if (buildNativeDeps)
            {
                if (CommandChecker.CommandExists("docker") && await DockerHelpers.VerifyDockerAccess())
                {
                    return(await InternalPreparePythonDeploymentInDocker(files, functionAppRoot, additionalPackages, noBundler));
                }
                else
                {
                    throw new CliException("Docker is required to build native dependencies for python function apps");
                }
            }
            else
            {
                return(await InternalPreparePythonDeployment(files, functionAppRoot));
            }
        }
예제 #2
0
 public static void EnsureDotNetForExtensions(Template template)
 {
     if (template.Metadata.Extensions != null && !CommandChecker.CommandExists("dotnet"))
     {
         throw new CliException($"The {template.Metadata.Name} template has extensions. {Constants.Errors.ExtensionsNeedDotnet}");
     }
 }
예제 #3
0
        private async Task <string> RunAzCLICommand(string param)
        {
            if (!CommandChecker.CommandExists("az"))
            {
                throw new CliException("az CLI not found");
            }
            var az = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
                ? new Executable("cmd", $"/c az {param}")
                : new Executable("az", param);

            var stdout   = new StringBuilder();
            var stderr   = new StringBuilder();
            var exitCode = await az.RunAsync(o => stdout.AppendLine(o), e => stderr.AppendLine(e));

            if (exitCode == 0)
            {
                return(stdout.ToString().Trim(' ', '\n', '\r', '"'));
            }
            else
            {
                if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine(VerboseColor($"Unable to run az CLI command `az {param}`. Error: {stderr.ToString().Trim(' ', '\n', '\r')}"));
                }
                throw new CliException("Error running Az CLI command");
            }
        }
예제 #4
0
        private async Task <(bool succeeded, string token)> TryGetAzCliToken()
        {
            if (CommandChecker.CommandExists("az"))
            {
                var az = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
                    ? new Executable("cmd", "/c az account get-access-token --query \"accessToken\" --output json")
                    : new Executable("az", "account get-access-token --query \"accessToken\" --output json");

                var stdout   = new StringBuilder();
                var stderr   = new StringBuilder();
                var exitCode = await az.RunAsync(o => stdout.AppendLine(o), e => stderr.AppendLine(e));

                if (exitCode == 0)
                {
                    return(true, stdout.ToString().Trim(' ', '\n', '\r', '"'));
                }
                else
                {
                    if (StaticSettings.IsDebug)
                    {
                        ColoredConsole.WriteLine(VerboseColor($"Unable to fetch access token from az cli. Error: {stderr.ToString().Trim(' ', '\n', '\r')}"));
                    }
                }
            }
            return(false, null);
        }
예제 #5
0
 public void ValidateParametersCount(CommandChecker command, int count)
 {
     if (command.Parameters.Length != count)
     {
         throw new InvalidOperationException(OutputMessages.INVALIDCOMMAND);
     }
 }
예제 #6
0
        private void btnRoverNext_Click(object sender, EventArgs e)
        {
            if (CommandChecker.IsValidCommand(txtCommands.Text) && cBoxDirection.Text != string.Empty && int.TryParse(txtXCoord.Text, out int xCoord) && int.TryParse(txtYCoord.Text, out int yCoord))
            {
                Direction direction = (Direction)Enum.Parse(typeof(Direction), cBoxDirection.Text, true);
                SendRover sendRover = new SendRover(new Data.Rover {
                    X = xCoord, Y = yCoord, Direction = direction
                }, txtCommands.Text);
                Data.Rover result = sendRover.GetRover();
                string     status = string.Empty;
                if (result.X <= plateau.LowerLeft && result.Y <= plateau.UpperRight)
                {
                    status = "Rover moved.";
                }
                else
                {
                    status = "Rover left the plateau field.";
                }

                listRovers.Items.Add($"{status} || X: {result.X.ToString()} || Y: {result.Y.ToString()} || Direction: {result.Direction.ToString()}");
            }
            else
            {
                MessageBox.Show("Please valid entries.");
            }
        }
예제 #7
0
        public async override Task RunAsync()
        {
            var extensionBundleManager = ExtensionBundleHelper.GetExtensionBundleManager();

            if (extensionBundleManager.IsExtensionBundleConfigured())
            {
                var hostFilePath = Path.Combine(Environment.CurrentDirectory, ScriptConstants.HostMetadataFileName);
                if (_showExtensionBundleWarning)
                {
                    ColoredConsole.WriteLine(WarningColor($"No action performed. Extension bundle is configured in {hostFilePath}"));
                }
                return;
            }

            if (CommandChecker.CommandExists("dotnet"))
            {
                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync(_secretsManager, Csx, ConfigPath);

                var installExtensions = new Executable("dotnet", $"build \"{extensionsProj}\" -o \"{OutputPath}\"");
                await installExtensions.RunAsync(output => ColoredConsole.WriteLine(output), error => ColoredConsole.WriteLine(ErrorColor(error)));
            }
            else
            {
                ColoredConsole.Error.WriteLine(ErrorColor(Constants.Errors.ExtensionsNeedDotnet));
            }
        }
예제 #8
0
 public static void EnsureDotnet()
 {
     if (!CommandChecker.CommandExists("dotnet"))
     {
         throw new CliException("dotnet sdk is required for dotnet based functions. Please install https://microsoft.com/net");
     }
 }
예제 #9
0
        private async Task <string> AzureCliGetToken()
        {
            if (CommandChecker.CommandExists("az"))
            {
                var az = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
                    ? new Executable("cmd", "/c az account get-access-token --query \"accessToken\"")
                    : new Executable("az", "account get-access-token --query \"accessToken\"");

                var stdout   = new StringBuilder();
                var stderr   = new StringBuilder();
                var exitCode = await az.RunAsync(o => stdout.AppendLine(o), e => stderr.AppendLine(e));

                if (exitCode != 0)
                {
                    throw new CliException(stderr.ToString().Trim(' ', '\n', '\r'));
                }
                else
                {
                    return(stdout.ToString().Trim(' ', '\n', '\r', '"'));
                }
            }
            else
            {
                throw new FileNotFoundException("Cannot find az cli. Please make sure to install az cli.");
            }
        }
예제 #10
0
        public async override Task RunAsync()
        {
            if (CommandChecker.CommandExists("dotnet"))
            {
                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync();

                var args = $"add {extensionsProj} package {Package} --version {Version}";
                if (!string.IsNullOrEmpty(Source))
                {
                    args += $" --source {Source}";
                }

                var addPackage = new Executable("dotnet", args);
                await addPackage.RunAsync(output => ColoredConsole.WriteLine(output), error => ColoredConsole.WriteLine(ErrorColor(error)));

                var syncAction = new SyncExtensionsAction()
                {
                    OutputPath = OutputPath
                };

                await syncAction.RunAsync();
            }
            else
            {
                ColoredConsole.Error.WriteLine(ErrorColor("Extensions command require dotnet on your path. Please make sure to install dotnet for your system from https://www.microsoft.com/net/download"));
            }
        }
예제 #11
0
 public static void EnsureDotNetForExtensions(Template template)
 {
     if (template.Metadata.Extensions != null && !CommandChecker.CommandExists("dotnet"))
     {
         throw new CliException($"The {template.Metadata.Name} template has extensions which require dotnet on your path. " +
                                $"Please make sure to install dotnet for your system from https://www.microsoft.com/net/download");
     }
 }
예제 #12
0
        internal static async Task <Stream> GetPythonDeploymentPackage(IEnumerable <string> files, string functionAppRoot, bool buildNativeDeps, BuildOption buildOption, string additionalPackages)
        {
            var reqTxtFile = Path.Combine(functionAppRoot, Constants.RequirementsTxt);

            if (!FileSystemHelpers.FileExists(reqTxtFile))
            {
                throw new CliException($"{Constants.RequirementsTxt} is not found. " +
                                       $"{Constants.RequirementsTxt} is required for python function apps. Please make sure to generate one before publishing.");
            }
            var packagesLocation = Path.Combine(functionAppRoot, Constants.ExternalPythonPackages);

            if (FileSystemHelpers.DirectoryExists(packagesLocation))
            {
                // Only update packages if checksum of requirements.txt does not match
                // If build option is remote, we don't need to verify if packages are in sync, as we need to delete them regardless
                if (buildOption != BuildOption.Remote && await ArePackagesInSync(reqTxtFile, packagesLocation))
                {
                    ColoredConsole.WriteLine(Yellow($"Directory {Constants.ExternalPythonPackages} already in sync with {Constants.RequirementsTxt}. Skipping restoring dependencies..."));
                    return(await ZipHelper.CreateZip(files.Union(FileSystemHelpers.GetFiles(packagesLocation)), functionAppRoot));
                }
                ColoredConsole.WriteLine($"Deleting the old {Constants.ExternalPythonPackages} directory");
                FileSystemHelpers.DeleteDirectorySafe(packagesLocation);
            }

            FileSystemHelpers.EnsureDirectory(packagesLocation);

            // Only one of the remote build or build-native-deps flag can be chosen
            if (buildNativeDeps)
            {
                if (CommandChecker.CommandExists("docker") && await DockerHelpers.VerifyDockerAccess())
                {
                    await RestorePythonRequirementsDocker(functionAppRoot, packagesLocation, additionalPackages);
                }
                else
                {
                    throw new CliException("Docker is required to build native dependencies for python function apps");
                }
            }
            else if (buildOption == BuildOption.Remote)
            {
                // No-ops, python packages will be resolved on the server side
            }
            else
            {
                await RestorePythonRequirementsPackapp(functionAppRoot, packagesLocation);
            }

            // No need to generate and compare .md5 when using remote build
            if (buildOption != BuildOption.Remote)
            {
                // Store a checksum of requirements.txt
                var md5FilePath = Path.Combine(packagesLocation, $"{Constants.RequirementsTxt}.md5");
                await FileSystemHelpers.WriteAllTextToFileAsync(md5FilePath, SecurityHelpers.CalculateMd5(reqTxtFile));
            }

            return(await ZipHelper.CreateZip(files.Union(FileSystemHelpers.GetFiles(packagesLocation)), functionAppRoot));
        }
 internal static async Task <Stream> GetPythonDeploymentPackage(IEnumerable <string> files, string functionAppRoot)
 {
     if (CommandChecker.CommandExists("docker") && await DockerHelpers.VerifyDockerAccess())
     {
         return(await InternalPreparePythonDeployment(files, functionAppRoot));
     }
     else
     {
         throw new CliException("Docker is required to publish python function apps");
     }
 }
        public async override Task RunAsync()
        {
            if (CommandChecker.CommandExists("dotnet"))
            {
                if (!string.IsNullOrEmpty(ConfigPath) && !FileSystemHelpers.DirectoryExists(ConfigPath))
                {
                    throw new CliArgumentsException("Invalid config path, please verify directory exists");
                }

                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync(_secretsManager, Csx, ConfigPath);

                if (string.IsNullOrEmpty(Package) && string.IsNullOrEmpty(Version))
                {
                    var project = ProjectHelpers.GetProject(extensionsProj);
                    foreach (var extensionPackage in ExtensionsHelper.GetExtensionPackages())
                    {
                        // Only add / update package referece if it does not exist or forced update is enabled
                        if (!ProjectHelpers.PackageReferenceExists(project, extensionPackage.Name) || Force)
                        {
                            await AddPackage(extensionsProj, extensionPackage.Name, extensionPackage.Version);
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(Package) && !string.IsNullOrEmpty(Version))
                {
                    await AddPackage(extensionsProj, Package, Version);
                }
                else
                {
                    throw new CliArgumentsException("Must specify extension package name and version",
                                                    new CliArgument {
                        Name = nameof(Package), Description = "Extension package name"
                    },
                                                    new CliArgument {
                        Name = nameof(Version), Description = "Extension package version"
                    }
                                                    );
                }

                var syncAction = new SyncExtensionsAction(_secretsManager)
                {
                    OutputPath = OutputPath,
                    ConfigPath = ConfigPath
                };

                await syncAction.RunAsync();
            }
            else
            {
                ColoredConsole.Error.WriteLine(ErrorColor(Constants.Errors.ExtensionsNeedDotnet));
            }
        }
        public async override Task RunAsync()
        {
            if (CommandChecker.CommandExists("dotnet"))
            {
                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync(_secretsManager, Csx, ConfigPath);

                var installExtensions = new Executable("dotnet", $"build \"{extensionsProj}\" -o \"{OutputPath}\"");
                await installExtensions.RunAsync(output => ColoredConsole.WriteLine(output), error => ColoredConsole.WriteLine(ErrorColor(error)));
            }
            else
            {
                ColoredConsole.Error.WriteLine(ErrorColor("Extensions command require dotnet on your path. Please make sure to install dotnet for your system from https://www.microsoft.com/net/download"));
            }
        }
        public async override Task RunAsync()
        {
            if (CommandChecker.CommandExists("dotnet"))
            {
                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync(_secretsManager, Csx, ConfigPath);

                var installExtensions = new Executable("dotnet", $"build \"{extensionsProj}\" -o \"{OutputPath}\"");
                await installExtensions.RunAsync(output => ColoredConsole.WriteLine(output), error => ColoredConsole.WriteLine(ErrorColor(error)));
            }
            else
            {
                ColoredConsole.Error.WriteLine(ErrorColor(Constants.Errors.ExtensionsNeedDotnet));
            }
        }
예제 #17
0
        public async override Task RunAsync()
        {
            if (CommandChecker.CommandExists("dotnet"))
            {
                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync();

                var runtimeId = GetRuntimeIdentifierParameter();

                var installExtensions = new Executable("dotnet", $"build {extensionsProj} -o {OutputPath} {runtimeId}");
                await installExtensions.RunAsync(output => ColoredConsole.WriteLine(output), error => ColoredConsole.WriteLine(ErrorColor(error)));
            }
            else
            {
                ColoredConsole.Error.WriteLine(ErrorColor("Extensions command require dotnet on your path. Please make sure to install dotnet for your system from https://www.microsoft.com/net/download"));
            }
        }
        public override async Task RunAsync()
        {
            if (!string.IsNullOrEmpty(FolderName))
            {
                var folderPath = Path.Combine(Environment.CurrentDirectory, FolderName);
                FileSystemHelpers.EnsureDirectory(folderPath);
                Environment.CurrentDirectory = folderPath;
            }

            if (!Platforms.Contains(Platform))
            {
                ColoredConsole.Error.WriteLine(ErrorColor($"platform {Platform} is not supported. Valid options are: {String.Join(",", Platforms)}"));
                return;
            }

            if (!CommandChecker.CommandExists("kubectl"))
            {
                ColoredConsole.Error.WriteLine(ErrorColor($"kubectl is required for deploying to kubernetes. Please make sure to install kubectl and try again."));
                return;
            }

            var dockerFilePath = Path.Combine(Environment.CurrentDirectory, "Dockerfile");

            if (!FileSystemHelpers.FileExists(dockerFilePath))
            {
                ColoredConsole.Error.WriteLine(ErrorColor($"Dockerfile not found in directory {Environment.CurrentDirectory}"));
                return;
            }

            var image = $"{Registry}/{Name.SanitizeImageName()}";

            ColoredConsole.WriteLine("Building Docker image...");
            await DockerHelpers.DockerBuild(image, Environment.CurrentDirectory);

            ColoredConsole.WriteLine("Pushing function image to registry...");
            await DockerHelpers.DockerPush(image);

            var platform = PlatformFactory.CreatePlatform(Platform, ConfigPath);

            if (platform == null)
            {
                ColoredConsole.Error.WriteLine(ErrorColor($"Platform {Platform} is not supported"));
                return;
            }

            await platform.DeployContainerizedFunction(Name, image, MinInstances, MaxInstances);
        }
예제 #19
0
        public async override Task RunAsync()
        {
            if (CommandChecker.CommandExists("dotnet"))
            {
                if (!string.IsNullOrEmpty(ConfigPath) && !FileSystemHelpers.DirectoryExists(ConfigPath))
                {
                    throw new CliArgumentsException("Invalid config path, please verify directory exists");
                }

                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync(_secretsManager, Csx, ConfigPath);

                if (string.IsNullOrEmpty(Package) && string.IsNullOrEmpty(Version))
                {
                    foreach (var extensionPackage in ExtensionsHelper.GetExtensionPackages())
                    {
                        await AddPackage(extensionsProj, extensionPackage.Name, extensionPackage.Version);
                    }
                }
                else if (!string.IsNullOrEmpty(Package) && !string.IsNullOrEmpty(Version))
                {
                    await AddPackage(extensionsProj, Package, Version);
                }
                else
                {
                    throw new CliArgumentsException("Must specify extension package name and version",
                                                    new CliArgument {
                        Name = nameof(Package), Description = "Extension package name"
                    },
                                                    new CliArgument {
                        Name = nameof(Version), Description = "Extension package version"
                    }
                                                    );
                }

                var syncAction = new SyncExtensionsAction(_secretsManager)
                {
                    OutputPath = OutputPath,
                    ConfigPath = ConfigPath
                };

                await syncAction.RunAsync();
            }
            else
            {
                ColoredConsole.Error.WriteLine(ErrorColor("Extensions command require dotnet on your path. Please make sure to install dotnet for your system from https://www.microsoft.com/net/download"));
            }
        }
예제 #20
0
        internal static async Task <Stream> GetPythonDeploymentPackage(IEnumerable <string> files, string functionAppRoot, bool buildNativeDeps, string additionalPackages)
        {
            var reqTxtFile = Path.Combine(functionAppRoot, Constants.RequirementsTxt);

            if (!FileSystemHelpers.FileExists(reqTxtFile))
            {
                throw new CliException($"{Constants.RequirementsTxt} is not found. " +
                                       $"{Constants.RequirementsTxt} is required for python function apps. Please make sure to generate one before publishing.");
            }
            var packagesLocation = Path.Combine(functionAppRoot, Constants.ExternalPythonPackages);

            if (FileSystemHelpers.DirectoryExists(packagesLocation))
            {
                // Only update packages if checksum of requirements.txt does not match or a sync is forced
                if (await ArePackagesInSync(reqTxtFile, packagesLocation))
                {
                    ColoredConsole.WriteLine(Yellow($"Directory {Constants.ExternalPythonPackages} already in sync with {Constants.RequirementsTxt}. Skipping restoring dependencies..."));
                    return(ZipHelper.CreateZip(files.Union(FileSystemHelpers.GetFiles(packagesLocation)), functionAppRoot));
                }
                ColoredConsole.WriteLine($"Deleting the old {Constants.ExternalPythonPackages} directory");
                FileSystemHelpers.DeleteDirectorySafe(Path.Combine(functionAppRoot, Constants.ExternalPythonPackages));
            }

            FileSystemHelpers.EnsureDirectory(packagesLocation);

            if (buildNativeDeps)
            {
                if (CommandChecker.CommandExists("docker") && await DockerHelpers.VerifyDockerAccess())
                {
                    await RestorePythonRequirementsDocker(functionAppRoot, packagesLocation, additionalPackages);
                }
                else
                {
                    throw new CliException("Docker is required to build native dependencies for python function apps");
                }
            }
            else
            {
                await RestorePythonRequirementsPackapp(functionAppRoot, packagesLocation);
            }
            // Store a checksum of requirements.txt
            var md5FilePath = Path.Combine(packagesLocation, $"{Constants.RequirementsTxt}.md5");
            await FileSystemHelpers.WriteAllTextToFileAsync(md5FilePath, SecurityHelpers.CalculateMd5(reqTxtFile));

            return(ZipHelper.CreateZip(files.Union(FileSystemHelpers.GetFiles(packagesLocation)), functionAppRoot));
        }
예제 #21
0
        internal static async Task <X509Certificate2> GetOrCreateCertificate(string certPath, string certPassword)
        {
            if (!string.IsNullOrEmpty(certPath) && !string.IsNullOrEmpty(certPassword))
            {
                certPassword = File.Exists(certPassword)
                    ? File.ReadAllText(certPassword).Trim()
                    : certPassword;
                return(new X509Certificate2(certPath, certPassword));
            }
            else if (CommandChecker.CommandExists("openssl"))
            {
                return(await CreateCertificateOpenSSL());
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                ColoredConsole
                .WriteLine("Auto cert generation is currently not working on the .NET Core build.")
                .WriteLine("On Windows you can run:")
                .WriteLine()
                .Write(DarkCyan("PS> "))
                .WriteLine($"$cert = {Yellow("New-SelfSignedCertificate")} -Subject localhost -DnsName localhost -FriendlyName \"Functions Development\" -KeyUsage DigitalSignature -TextExtension @(\"2.5.29.37={{text}}1.3.6.1.5.5.7.3.1\")")
                .Write(DarkCyan("PS> "))
                .WriteLine($"{Yellow("Export-PfxCertificate")} -Cert $cert -FilePath certificate.pfx -Password (ConvertTo-SecureString -String {Red("<password>")} -Force -AsPlainText)")
                .WriteLine()
                .WriteLine("For more checkout https://docs.microsoft.com/en-us/aspnet/core/security/https")
                .WriteLine();
            }
            else
            {
                ColoredConsole
                .WriteLine("Auto cert generation is currently not working on the .NET Core build.")
                .WriteLine("On Unix you can run:")
                .WriteLine()
                .Write(DarkGreen("sh> "))
                .WriteLine("openssl req -new -x509 -newkey rsa:2048 -keyout localhost.key -out localhost.cer -days 365 -subj /CN=localhost")
                .Write(DarkGreen("sh> "))
                .WriteLine("openssl pkcs12 -export -out certificate.pfx -inkey localhost.key -in localhost.cer")
                .WriteLine()
                .WriteLine("For more checkout https://docs.microsoft.com/en-us/aspnet/core/security/https")
                .WriteLine();
            }

            throw new CliException("Auto cert generation is currently not working on the .NET Core build.");
        }
예제 #22
0
        public void CommandCheckerShouldWork()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                var exists      = CommandChecker.CommandExists("cmd");
                var doesntExist = CommandChecker.CommandExists("fooo");

                exists.Should().BeTrue(because: "checking if cmd command exists should always be true on Windows");
                doesntExist.Should().BeFalse(because: "checking if fooo command exists on windows should be false");
            }
            else
            {
                var exists      = CommandChecker.CommandExists("bash");
                var doesntExist = CommandChecker.CommandExists("fooo");

                exists.Should().BeTrue(because: "checking if sh command exists should always be true on Unix-like");
                doesntExist.Should().BeFalse(because: "checking if fooo command exists on Unix-like should be false");
            }
        }
        private async Task PreRunConditions(WorkerRuntime workerRuntime)
        {
            if (workerRuntime == 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 (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.");
                }
            }
            else if (workerRuntime == 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].");
            }
        }
예제 #24
0
        public void Run()
        {
            while (true)
            {
                string line = this.ui.ReadLine();
                if (string.IsNullOrWhiteSpace(line))
                {
                    break;
                }

                line = line.Trim();
                try
                {
                    magic = new CommandChecker(line);
                    this.ac.DoMagic();
                }
                catch (InvalidOperationException ex)
                {
                    this.ui.WriteLine(ex.Message);
                }
            }
        }
        internal static async Task <Stream> GetPythonDeploymentPackage(IEnumerable <string> files, string functionAppRoot, bool buildNativeDeps)
        {
            if (!FileSystemHelpers.FileExists(Path.Combine(functionAppRoot, Constants.RequirementsTxt)))
            {
                throw new CliException($"{Constants.RequirementsTxt} is not found. " +
                                       $"{Constants.RequirementsTxt} is required for python function apps. Please make sure to generate one before publishing.");
            }

            if (buildNativeDeps)
            {
                if (CommandChecker.CommandExists("docker") && await DockerHelpers.VerifyDockerAccess())
                {
                    return(await InternalPreparePythonDeploymentInDocker(files, functionAppRoot));
                }
                else
                {
                    throw new CliException("Docker is required to build native dependencies for python function apps");
                }
            }
            else
            {
                return(await InternalPreparePythonDeployment(files, functionAppRoot));
            }
        }
예제 #26
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].");
            }
        }
        public async override Task RunAsync()
        {
            var extensionBundleManager = ExtensionBundleHelper.GetExtensionBundleManager();

            if (extensionBundleManager.IsExtensionBundleConfigured())
            {
                var hostFilePath = Path.Combine(Environment.CurrentDirectory, ScriptConstants.HostMetadataFileName);
                if (_showNoActionWarning)
                {
                    ColoredConsole.WriteLine(WarningColor($"No action performed. Extension bundle is configured in {hostFilePath}."));
                }
                return;
            }

            if (!string.IsNullOrEmpty(ConfigPath) && !FileSystemHelpers.DirectoryExists(ConfigPath))
            {
                throw new CliArgumentsException("Invalid config path, please verify directory exists");
            }

            if (!NeedsExtensionsInstall())
            {
                return;
            }

            if (CommandChecker.CommandExists("dotnet"))
            {
                var extensionsProj = await ExtensionsHelper.EnsureExtensionsProjectExistsAsync(_secretsManager, Csx, ConfigPath);

                if (string.IsNullOrEmpty(Package) && string.IsNullOrEmpty(Version))
                {
                    var project = ProjectHelpers.GetProject(extensionsProj);
                    foreach (var extensionPackage in ExtensionsHelper.GetExtensionPackages())
                    {
                        // Only add / update package referece if it does not exist or forced update is enabled
                        if (!ProjectHelpers.PackageReferenceExists(project, extensionPackage.Name) || Force)
                        {
                            await AddPackage(extensionsProj, extensionPackage.Name, extensionPackage.Version);
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(Package) && !string.IsNullOrEmpty(Version))
                {
                    await AddPackage(extensionsProj, Package, Version);
                }
                else
                {
                    throw new CliArgumentsException("Must specify extension package name and version",
                                                    new CliArgument {
                        Name = nameof(Package), Description = "Extension package name"
                    },
                                                    new CliArgument {
                        Name = nameof(Version), Description = "Extension package version"
                    }
                                                    );
                }

                var syncAction = new SyncExtensionsAction(_secretsManager, false)
                {
                    OutputPath = OutputPath,
                    ConfigPath = ConfigPath
                };

                await syncAction.RunAsync();
            }
            else
            {
                throw new CliException(Constants.Errors.ExtensionsNeedDotnet);
            }
        }
예제 #28
0
        private async Task <(bool succeeded, string token)> TryGetAzPowerShellToken()
        {
            // PowerShell Core can only use Az so we can check that it exists and that the Az module exists
            if (CommandChecker.CommandExists(_powerShellCoreExecutable) &&
                await CommandChecker.PowerShellModuleExistsAsync(_powerShellCoreExecutable, _azProfileModuleName))
            {
                var az = new Executable(_powerShellCoreExecutable,
                                        $"-NonInteractive -o Text -NoProfile -c {GetPowerShellAccessTokenScript(_azProfileModuleName)}");

                var stdout   = new StringBuilder();
                var stderr   = new StringBuilder();
                var exitCode = await az.RunAsync(o => stdout.AppendLine(o), e => stderr.AppendLine(e));

                if (exitCode == 0)
                {
                    return(true, stdout.ToString().Trim(' ', '\n', '\r', '"'));
                }
                else
                {
                    if (StaticSettings.IsDebug)
                    {
                        ColoredConsole.WriteLine(VerboseColor($"Unable to fetch access token from Az.Profile in PowerShell Core. Error: {stderr.ToString().Trim(' ', '\n', '\r')}"));
                    }
                }
            }

            // Windows PowerShell can use Az or AzureRM so first we check if powershell.exe is available
            if (CommandChecker.CommandExists(_windowsPowerShellExecutable))
            {
                string moduleToUse;

                // depending on if Az.Profile or AzureRM.Profile is available, we need to change the prefix
                if (await CommandChecker.PowerShellModuleExistsAsync(_windowsPowerShellExecutable, _azProfileModuleName))
                {
                    moduleToUse = _azProfileModuleName;
                }
                else if (await CommandChecker.PowerShellModuleExistsAsync(_windowsPowerShellExecutable, _azureRmProfileModuleName))
                {
                    moduleToUse = _azureRmProfileModuleName;
                }
                else
                {
                    // User doesn't have either Az.Profile or AzureRM.Profile
                    if (StaticSettings.IsDebug)
                    {
                        ColoredConsole.WriteLine(VerboseColor("Unable to find Az.Profile or AzureRM.Profile."));
                    }
                    return(false, null);
                }

                var az = new Executable("powershell", $"-NonInteractive -o Text -NoProfile -c {GetPowerShellAccessTokenScript(moduleToUse)}");

                var stdout   = new StringBuilder();
                var stderr   = new StringBuilder();
                var exitCode = await az.RunAsync(o => stdout.AppendLine(o), e => stderr.AppendLine(e));

                if (exitCode == 0)
                {
                    return(true, stdout.ToString().Trim(' ', '\n', '\r', '"'));
                }
                else
                {
                    if (StaticSettings.IsDebug)
                    {
                        ColoredConsole.WriteLine(VerboseColor($"Unable to fetch access token from '{moduleToUse}'. Error: {stderr.ToString().Trim(' ', '\n', '\r')}"));
                    }
                }
            }
            return(false, null);
        }
예제 #29
0
        public async override Task RunAsync()
        {
            if (Console.IsOutputRedirected || Console.IsInputRedirected)
            {
                if (string.IsNullOrEmpty(TemplateName) ||
                    string.IsNullOrEmpty(FunctionName))
                {
                    ColoredConsole
                    .Error
                    .WriteLine(ErrorColor("Running with stdin\\stdout redirected. Command must specify --template, and --name explicitly."))
                    .WriteLine(ErrorColor("See 'func help function' for more details"));
                    return;
                }
            }

            var workerRuntime = GlobalCoreToolsSettings.CurrentWorkerRuntimeOrNone;
            var templates     = await _templatesManager.Templates;

            if (workerRuntime != WorkerRuntime.None && !string.IsNullOrWhiteSpace(Language))
            {
                // validate
                var workerRuntimeSelected = WorkerRuntimeLanguageHelper.NormalizeWorkerRuntime(Language);
                if (workerRuntime != workerRuntimeSelected)
                {
                    throw new CliException("Selected language doesn't match worker set in local.settings.json." +
                                           $"Selected worker is: {workerRuntime} and selected language is: {workerRuntimeSelected}");
                }
            }
            else if (string.IsNullOrWhiteSpace(Language))
            {
                if (workerRuntime == WorkerRuntime.None)
                {
                    SelectionMenuHelper.DisplaySelectionWizardPrompt("language");
                    Language      = SelectionMenuHelper.DisplaySelectionWizard(templates.Select(t => t.Metadata.Language).Where(l => !l.Equals("python", StringComparison.OrdinalIgnoreCase)).Distinct());
                    workerRuntime = WorkerRuntimeLanguageHelper.SetWorkerRuntime(_secretsManager, Language);
                }
                else if (workerRuntime != WorkerRuntime.dotnet || Csx)
                {
                    var languages   = WorkerRuntimeLanguageHelper.LanguagesForWorker(workerRuntime);
                    var displayList = templates
                                      .Select(t => t.Metadata.Language)
                                      .Where(l => languages.Contains(l, StringComparer.OrdinalIgnoreCase))
                                      .Distinct()
                                      .ToArray();
                    if (displayList.Length == 1)
                    {
                        Language = displayList.First();
                    }
                    else if (!InferAndUpdateLanguage(workerRuntime))
                    {
                        SelectionMenuHelper.DisplaySelectionWizardPrompt("language");
                        Language = SelectionMenuHelper.DisplaySelectionWizard(displayList);
                    }
                }
            }
            else if (!string.IsNullOrWhiteSpace(Language))
            {
                workerRuntime = WorkerRuntimeLanguageHelper.SetWorkerRuntime(_secretsManager, Language);
            }

            if (workerRuntime == WorkerRuntime.dotnet && !Csx)
            {
                SelectionMenuHelper.DisplaySelectionWizardPrompt("template");
                TemplateName = TemplateName ?? SelectionMenuHelper.DisplaySelectionWizard(DotnetHelpers.GetTemplates());
                ColoredConsole.Write("Function name: ");
                FunctionName = FunctionName ?? Console.ReadLine();
                ColoredConsole.WriteLine(FunctionName);
                var namespaceStr = Path.GetFileName(Environment.CurrentDirectory);
                await DotnetHelpers.DeployDotnetFunction(TemplateName.Replace(" ", string.Empty), Utilities.SanitizeClassName(FunctionName), Utilities.SanitizeNameSpace(namespaceStr));
            }
            else
            {
                SelectionMenuHelper.DisplaySelectionWizardPrompt("template");
                string templateLanguage;
                try
                {
                    templateLanguage = WorkerRuntimeLanguageHelper.NormalizeLanguage(Language);
                }
                catch (Exception)
                {
                    // Ideally this should never happen.
                    templateLanguage = WorkerRuntimeLanguageHelper.GetDefaultTemplateLanguageFromWorker(workerRuntime);
                }

                TelemetryHelpers.AddCommandEventToDictionary(TelemetryCommandEvents, "language", templateLanguage);
                TemplateName = TemplateName ?? SelectionMenuHelper.DisplaySelectionWizard(templates.Where(t => t.Metadata.Language.Equals(templateLanguage, StringComparison.OrdinalIgnoreCase)).Select(t => t.Metadata.Name).Distinct());
                ColoredConsole.WriteLine(TitleColor(TemplateName));

                var template = templates.FirstOrDefault(t => Utilities.EqualsIgnoreCaseAndSpace(t.Metadata.Name, TemplateName) && t.Metadata.Language.Equals(templateLanguage, StringComparison.OrdinalIgnoreCase));

                if (template == null)
                {
                    TelemetryHelpers.AddCommandEventToDictionary(TelemetryCommandEvents, "template", "N/A");
                    throw new CliException($"Can't find template \"{TemplateName}\" in \"{Language}\"");
                }
                else
                {
                    TelemetryHelpers.AddCommandEventToDictionary(TelemetryCommandEvents, "template", TemplateName);

                    var extensionBundleManager = ExtensionBundleHelper.GetExtensionBundleManager();
                    if (template.Metadata.Extensions != null && !extensionBundleManager.IsExtensionBundleConfigured() && !CommandChecker.CommandExists("dotnet"))
                    {
                        throw new CliException($"The {template.Metadata.Name} template has extensions. {Constants.Errors.ExtensionsNeedDotnet}");
                    }

                    ColoredConsole.Write($"Function name: [{template.Metadata.DefaultFunctionName}] ");
                    FunctionName = FunctionName ?? Console.ReadLine();
                    FunctionName = string.IsNullOrEmpty(FunctionName) ? template.Metadata.DefaultFunctionName : FunctionName;
                    await _templatesManager.Deploy(FunctionName, template);

                    PerformPostDeployTasks(FunctionName, Language);
                }
            }
            ColoredConsole.WriteLine($"The function \"{FunctionName}\" was created successfully from the \"{TemplateName}\" template.");
        }