// This is only used by build artifact. This isn't a officially supported artifact type in RM public async Task DownloadArtifactAsync(IExecutionContext executionContext, IHostContext hostContext, ArtifactDefinition artifactDefinition, string dropLocation, string localFolderPath) { ArgUtil.NotNull(artifactDefinition, nameof(artifactDefinition)); ArgUtil.NotNull(executionContext, nameof(executionContext)); ArgUtil.NotNullOrEmpty(localFolderPath, nameof(localFolderPath)); ArgUtil.NotNullOrEmpty(dropLocation, nameof(dropLocation)); var trimChars = new[] { '\\', '/' }; var relativePath = artifactDefinition.Details.RelativePath; // If user has specified a relative folder in the drop, change the drop location itself. dropLocation = Path.Combine(dropLocation.TrimEnd(trimChars), relativePath.Trim(trimChars)); var fileSystemManager = hostContext.CreateService<IReleaseFileSystemManager>(); List<string> filePaths = new DirectoryInfo(dropLocation).EnumerateFiles("*", SearchOption.AllDirectories) .Select(path => path.FullName) .ToList(); if (filePaths.Any()) { foreach (var filePath in filePaths) { var filePathRelativeToDrop = filePath.Replace(dropLocation, string.Empty).Trim(trimChars); using (var fileReader = fileSystemManager.GetFileReader(filePath)) { await fileSystemManager.WriteStreamToFile(fileReader.BaseStream, Path.Combine(localFolderPath, filePathRelativeToDrop)); } } } else { executionContext.Warning(StringUtil.Loc("RMNoArtifactsFound", relativePath)); } }
// This is only used by build artifact. This isn't a officially supported artifact type in RM public async Task DownloadArtifactAsync(IExecutionContext executionContext, IHostContext hostContext, ArtifactDefinition artifactDefinition, string dropLocation, string localFolderPath) { ArgUtil.NotNull(artifactDefinition, nameof(artifactDefinition)); ArgUtil.NotNull(executionContext, nameof(executionContext)); ArgUtil.NotNullOrEmpty(localFolderPath, nameof(localFolderPath)); ArgUtil.NotNullOrEmpty(dropLocation, nameof(dropLocation)); var trimChars = new[] { '\\', '/' }; var relativePath = artifactDefinition.Details.RelativePath; // If user has specified a relative folder in the drop, change the drop location itself. dropLocation = Path.Combine(dropLocation.TrimEnd(trimChars), relativePath.Trim(trimChars)); var fileSystemManager = hostContext.CreateService <IReleaseFileSystemManager>(); List <string> filePaths = new DirectoryInfo(dropLocation).EnumerateFiles("*", SearchOption.AllDirectories) .Select(path => path.FullName) .ToList(); if (filePaths.Any()) { foreach (var filePath in filePaths) { var filePathRelativeToDrop = filePath.Replace(dropLocation, string.Empty).Trim(trimChars); using (var fileReader = fileSystemManager.GetFileReader(filePath)) { await fileSystemManager.WriteStreamToFile(fileReader.BaseStream, Path.Combine(localFolderPath, filePathRelativeToDrop)); } } } else { executionContext.Warning(StringUtil.Loc("RMNoArtifactsFound", relativePath)); } }
public RSA CreateKey() { RSA rsa = null; if (!File.Exists(_keyFile)) { Trace.Info("Creating new RSA key using 2048-bit key length"); rsa = RSA.Create(); rsa.KeySize = 2048; // Now write the parameters to disk IOUtil.SaveObject(rsa.ExportParameters(true), _keyFile); Trace.Info("Successfully saved RSA key parameters to file {0}", _keyFile); // Try to lock down the credentials_key file to the owner/group var whichUtil = _context.GetService <IWhichUtil>(); var chmodPath = whichUtil.Which("chmod"); if (!String.IsNullOrEmpty(chmodPath)) { var arguments = $"600 {new FileInfo(_keyFile).FullName}"; using (var invoker = _context.CreateService <IProcessInvoker>()) { var exitCode = invoker.ExecuteAsync(IOUtil.GetRootPath(), chmodPath, arguments, null, default(CancellationToken)).GetAwaiter().GetResult(); if (exitCode == 0) { Trace.Info("Successfully set permissions for RSA key parameters file {0}", _keyFile); } else { Trace.Warning("Unable to succesfully set permissions for RSA key parameters file {0}. Received exit code {1} from {2}", _keyFile, exitCode, chmodPath); } } } else { Trace.Warning("Unable to locate chmod to set permissions for RSA key parameters file {0}.", _keyFile); } } else { Trace.Info("Found existing RSA key parameters file {0}", _keyFile); rsa = RSA.Create(); rsa.ImportParameters(IOUtil.LoadObject <RSAParameters>(_keyFile)); } return(rsa); }
public async Task CheckToolOutputAsync(string name, string fileName, string arguments) { _trace.Entering(); ArgUtil.NotNullOrEmpty(name, nameof(name)); ArgUtil.NotNullOrEmpty(fileName, nameof(fileName)); try { // Attempt to locate the tool. string filePath = _whichUtil.Which(fileName); if (string.IsNullOrEmpty(filePath)) { return; } // Invoke the tool and capture the output. var output = new StringBuilder(); using (var processInvoker = _hostContext.CreateService <IProcessInvoker>()) { processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs args) => { if (!string.IsNullOrEmpty(args.Data)) { output.Append(args.Data); } }; await processInvoker.ExecuteAsync( workingDirectory : string.Empty, fileName : filePath, arguments : arguments ?? string.Empty, environment : null, cancellationToken : _cancellationToken); } // Add the capability. if (output.Length > 0) { string value = output.ToString(); _trace.Info($"Adding '{name}': '{value}'"); _capabilities.Add(new Capability(name, value)); } } catch (Exception ex) when(!(ex is OperationCanceledException)) { _trace.Error(ex); } }
private async Task DownloadArtifactUsingFileSystemManagerAsync(IExecutionContext executionContext, IHostContext hostContext, ArtifactDefinition artifactDefinition, string dropLocation, string localFolderPath) { var trimChars = new[] { '\\', '/' }; var relativePath = artifactDefinition.Details.RelativePath; // If user has specified a relative folder in the drop, change the drop location itself. dropLocation = Path.Combine(dropLocation.TrimEnd(trimChars), relativePath.Trim(trimChars)); var fileSystemManager = hostContext.CreateService <IReleaseFileSystemManager>(); List <string> filePaths = new DirectoryInfo(dropLocation).EnumerateFiles("*", SearchOption.AllDirectories) .Select(path => path.FullName) .ToList(); if (filePaths.Any()) { int bufferSize = executionContext.Variables.Release_Download_BufferSize ?? DefaultBufferSize; foreach (var filePath in filePaths) { string fullPath = Path.GetFullPath(filePath); if (File.Exists(fullPath)) { string filePathRelativeToDrop = filePath.Replace(dropLocation, string.Empty).Trim(trimChars); using (StreamReader fileReader = fileSystemManager.GetFileReader(filePath)) { await fileSystemManager.WriteStreamToFile( fileReader.BaseStream, Path.Combine(localFolderPath, filePathRelativeToDrop), bufferSize, executionContext.CancellationToken); } } else { executionContext.Warning(StringUtil.Loc("FileNotFound", fullPath)); } } } else { executionContext.Warning(StringUtil.Loc("RMArtifactEmpty")); } }
public static async Task SetEncoding(IHostContext hostContext, Tracing trace, CancellationToken cancellationToken) { #if OS_WINDOWS try { if (Console.InputEncoding.CodePage != 65001) { using (var p = hostContext.CreateService <IProcessInvoker>()) { // Use UTF8 code page int exitCode = await p.ExecuteAsync(workingDirectory : hostContext.GetDirectory(WellKnownDirectory.Work), fileName : WhichUtil.Which("chcp", true, trace), arguments : "65001", environment : null, requireExitCodeZero : false, outputEncoding : null, killProcessOnCancel : false, redirectStandardIn : null, inheritConsoleHandler : true, cancellationToken : cancellationToken); if (exitCode == 0) { trace.Info("Successfully returned to code page 65001 (UTF8)"); } else { trace.Warning($"'chcp 65001' failed with exit code {exitCode}"); } } } } catch (Exception ex) { trace.Warning($"'chcp 65001' failed with exception {ex.Message}"); } #endif // Dummy variable to prevent compiler error CS1998: "This async method lacks 'await' operators and will run synchronously..." await Task.CompletedTask; }
private async Task DownloadArtifactUsingRobocopyAsync(IExecutionContext executionContext, IHostContext hostContext, ArtifactDefinition artifactDefinition, string dropLocation, string downloadFolderPath) { int? robocopyMT = executionContext.Variables.GetInt(Constants.Variables.Release.RobocopyMT); bool verbose = executionContext.Variables.GetBoolean(Constants.Variables.System.Debug) ?? false; if (robocopyMT != null) { if (robocopyMT < 1) { robocopyMT = 1; } else if (robocopyMT > 128) { robocopyMT = 128; } } executionContext.Output(StringUtil.Loc("RMDownloadingArtifactUsingRobocopy")); using (var processInvoker = hostContext.CreateService <IProcessInvoker>()) { // Save STDOUT from worker, worker will use STDOUT report unhandle exception. processInvoker.OutputDataReceived += delegate(object sender, ProcessDataReceivedEventArgs stdout) { if (!string.IsNullOrEmpty(stdout.Data)) { executionContext.Output(stdout.Data); } }; // Save STDERR from worker, worker will use STDERR on crash. processInvoker.ErrorDataReceived += delegate(object sender, ProcessDataReceivedEventArgs stderr) { if (!string.IsNullOrEmpty(stderr.Data)) { executionContext.Error(stderr.Data); } }; var trimChars = new[] { '\\', '/' }; var relativePath = artifactDefinition.Details.RelativePath; dropLocation = Path.Combine(dropLocation.TrimEnd(trimChars), relativePath.Trim(trimChars)); downloadFolderPath = downloadFolderPath.TrimEnd(trimChars); string robocopyArguments = "\"" + dropLocation + "\" \"" + downloadFolderPath + "\" /E /Z /NP /R:3"; if (verbose != true) { robocopyArguments = robocopyArguments + " /NDL /NFL"; } if (robocopyMT != null) { robocopyArguments = robocopyArguments + " /MT:" + robocopyMT; } int exitCode = await processInvoker.ExecuteAsync( workingDirectory : "", fileName : "robocopy", arguments : robocopyArguments, environment : null, requireExitCodeZero : false, outputEncoding : null, killProcessOnCancel : true, cancellationToken : executionContext.CancellationToken); executionContext.Output(StringUtil.Loc("RMRobocopyBasedArtifactDownloadExitCode", exitCode)); if (exitCode >= 8) { throw new ArtifactDownloadException(StringUtil.Loc("RMRobocopyBasedArtifactDownloadFailed", exitCode)); } } }
private static string GetEnvironmentVariableUsingPs(Process process, IHostContext hostContext, string variable) { // On OSX, there is no /proc folder for us to read environment for given process, // So we have call `ps e -p <pid> -o command` to print out env to STDOUT, // However, the output env are not format in a parseable way, it's just a string that concatenate all envs with space, // It doesn't escape '=' or ' ', so we can't parse the output into a dictionary of all envs. // So we only look for the env you request, in the format of variable=value. (it won't work if you variable contains = or space) var trace = hostContext.GetTrace(nameof(ProcessExtensions)); trace.Info($"Read env from output of `ps e -p {process.Id} -o command`"); Dictionary <string, string> env = new Dictionary <string, string>(); List <string> psOut = new List <string>(); object outputLock = new object(); using (var p = hostContext.CreateService <IProcessInvoker>()) { p.OutputDataReceived += delegate(object sender, ProcessDataReceivedEventArgs stdout) { if (!string.IsNullOrEmpty(stdout.Data)) { lock (outputLock) { psOut.Add(stdout.Data); } } }; p.ErrorDataReceived += delegate(object sender, ProcessDataReceivedEventArgs stderr) { if (!string.IsNullOrEmpty(stderr.Data)) { lock (outputLock) { trace.Error(stderr.Data); } } }; int exitCode = p.ExecuteAsync(workingDirectory: hostContext.GetDirectory(WellKnownDirectory.Root), fileName: "ps", arguments: $"e -p {process.Id} -o command", environment: null, cancellationToken: CancellationToken.None).GetAwaiter().GetResult(); if (exitCode == 0) { trace.Info($"Successfully dump environment variables for {process.Id}"); if (psOut.Count > 0) { string psOutputString = string.Join(" ", psOut); trace.Verbose($"ps output: '{psOutputString}'"); int varStartIndex = psOutputString.IndexOf(variable, StringComparison.Ordinal); if (varStartIndex >= 0) { string rightPart = psOutputString.Substring(varStartIndex + variable.Length + 1); if (rightPart.IndexOf(' ') > 0) { string value = rightPart.Substring(0, rightPart.IndexOf(' ')); env[variable] = value; } else { env[variable] = rightPart; } trace.Verbose($"PID:{process.Id} ({variable}={env[variable]})"); } } } } if (env.TryGetValue(variable, out string envVariable)) { return(envVariable); } else { return(null); } }
public static async Task <CheckResult> DownloadExtraCA(this IHostContext hostContext, string url, string pat) { var result = new CheckResult(); try { result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** Download SSL Certificate from {url} "); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************"); var uri = new Uri(url); var env = new Dictionary <string, string>() { { "HOSTNAME", uri.Host }, { "PORT", uri.IsDefaultPort ? (uri.Scheme.ToLowerInvariant() == "https" ? "443" : "80") : uri.Port.ToString() }, { "PATH", uri.AbsolutePath }, { "PAT", pat } }; var proxy = hostContext.WebProxy.GetProxy(uri); if (proxy != null) { env["PROXYHOST"] = proxy.Host; env["PROXYPORT"] = proxy.IsDefaultPort ? (proxy.Scheme.ToLowerInvariant() == "https" ? "443" : "80") : proxy.Port.ToString(); if (hostContext.WebProxy.HttpProxyUsername != null || hostContext.WebProxy.HttpsProxyUsername != null) { env["PROXYUSERNAME"] = hostContext.WebProxy.HttpProxyUsername ?? hostContext.WebProxy.HttpsProxyUsername; env["PROXYPASSWORD"] = hostContext.WebProxy.HttpProxyPassword ?? hostContext.WebProxy.HttpsProxyPassword; } else { env["PROXYUSERNAME"] = ""; env["PROXYPASSWORD"] = ""; } } else { env["PROXYHOST"] = ""; env["PROXYPORT"] = ""; env["PROXYUSERNAME"] = ""; env["PROXYPASSWORD"] = ""; } using (var processInvoker = hostContext.CreateService <IProcessInvoker>()) { processInvoker.OutputDataReceived += new EventHandler <ProcessDataReceivedEventArgs>((sender, args) => { if (!string.IsNullOrEmpty(args.Data)) { result.Logs.Add($"{DateTime.UtcNow.ToString("O")} [STDOUT] {args.Data}"); } }); processInvoker.ErrorDataReceived += new EventHandler <ProcessDataReceivedEventArgs>((sender, args) => { if (!string.IsNullOrEmpty(args.Data)) { result.Logs.Add($"{DateTime.UtcNow.ToString("O")} [STDERR] {args.Data}"); } }); var downloadCertScript = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Bin), "checkScripts", "downloadCert"); var node12 = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node12} \"{downloadCertScript}\"' "); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} {StringUtil.ConvertToJson(env)}"); await processInvoker.ExecuteAsync( hostContext.GetDirectory(WellKnownDirectory.Root), node12, $"\"{downloadCertScript}\"", env, true, CancellationToken.None); } result.Pass = true; } catch (Exception ex) { result.Pass = false; result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** Download SSL Certificate from '{url}' failed with error: {ex}"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} **** ****"); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} ***************************************************************************************************************"); } return(result); }
public override void Initialize(IHostContext hostContext) { base.Initialize(hostContext); ActionCommandManager = hostContext.CreateService <IActionCommandManager>(); }