public static async Task <int> MainAsync( string[] args) { //ITerminal registers a CTRL-C handler, which keeps the Agent.Worker process running //and lets the Agent.Listener handle gracefully the exit. using (var hc = new HostContext("Worker")) using (var term = hc.GetService <ITerminal>()) { Tracing trace = hc.GetTrace(nameof(Program)); try { trace.Info($"Version: {Constants.Agent.Version}"); trace.Info($"Commit: {BuildConstants.Source.CommitHash}"); trace.Info($"Culture: {CultureInfo.CurrentCulture.Name}"); trace.Info($"UI Culture: {CultureInfo.CurrentUICulture.Name}"); // Validate args. ArgUtil.NotNull(args, nameof(args)); ArgUtil.Equal(3, args.Length, nameof(args.Length)); ArgUtil.NotNullOrEmpty(args[0], $"{nameof(args)}[0]"); ArgUtil.Equal("spawnclient", args[0].ToLowerInvariant(), $"{nameof(args)}[0]"); ArgUtil.NotNullOrEmpty(args[1], $"{nameof(args)}[1]"); ArgUtil.NotNullOrEmpty(args[2], $"{nameof(args)}[2]"); var worker = hc.GetService <IWorker>(); // Run the worker. return(await worker.RunAsync( pipeIn : args[1], pipeOut : args[2])); } catch (Exception ex) { // Populate any exception that cause worker failure back to agent. Console.WriteLine(ex.ToString()); try { trace.Error(ex); } catch (Exception e) { // make sure we don't crash the app on trace error. // since IOException will throw when we run out of disk space. Console.WriteLine(e.ToString()); } } finally { hc.Dispose(); } return(1); } }
public string GetEndpointData(ServiceEndpoint endpoint, string name) { var trace = HostContext.GetTrace(nameof(SourceProvider)); string value; if (endpoint.Data.TryGetValue(name, out value)) { trace.Info($"Get '{name}': '{value}'"); return(value); } trace.Info($"Get '{name}' (not found)"); return(null); }
public override void Initialize(IHostContext hostContext) { base.Initialize(hostContext); _trace = HostContext.GetTrace(nameof(FileCommandManager)); _fileCommandDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Temp), _folderName); if (!Directory.Exists(_fileCommandDirectory)) { Directory.CreateDirectory(_fileCommandDirectory); } var extensionManager = hostContext.GetService <IExtensionManager>(); _commandExtensions = extensionManager.GetExtensions <IFileCommandExtension>() ?? new List <IFileCommandExtension>(); }
public static async Task <int> MainAsync( string[] args) { //ITerminal registers a CTRL-C handler, which keeps the Agent.Worker process running //and lets the Agent.Listener handle gracefully the exit. using (var hc = new HostContext("Worker")) using (var term = hc.GetService <ITerminal>()) { Tracing trace = hc.GetTrace(nameof(Program)); try { trace.Info($"Version: {Constants.Agent.Version}"); trace.Info($"Commit: {BuildConstants.Source.CommitHash}"); // Validate args. ArgUtil.NotNull(args, nameof(args)); ArgUtil.Equal(3, args.Length, nameof(args.Length)); ArgUtil.NotNullOrEmpty(args[0], $"{nameof(args)}[0]"); ArgUtil.Equal("spawnclient", args[0].ToLowerInvariant(), $"{nameof(args)}[0]"); ArgUtil.NotNullOrEmpty(args[1], $"{nameof(args)}[1]"); ArgUtil.NotNullOrEmpty(args[2], $"{nameof(args)}[2]"); var worker = hc.GetService <IWorker>(); // Run the worker. return(await worker.RunAsync( pipeIn : args[1], pipeOut : args[2])); } catch (Exception ex) { trace.Error(ex); } finally { hc.Dispose(); } return(1); } }
public async Task <int> ExecuteAsync(string workingDirectory, string fileName, string arguments, IDictionary <string, string> environment, bool requireExitCodeZero, Encoding outputEncoding, bool killProcessOnCancel, bool inheritConsoleHandler, CancellationToken cancellationToken) { // make sure container exist. ArgUtil.NotNull(Container, nameof(Container)); ArgUtil.NotNullOrEmpty(Container.ContainerId, nameof(Container.ContainerId)); var dockerManger = HostContext.GetService <IDockerCommandManager>(); string containerEnginePath = dockerManger.DockerPath; ContainerStandardInPayload payload = new ContainerStandardInPayload() { ExecutionHandler = fileName, ExecutionHandlerWorkingDirectory = workingDirectory, ExecutionHandlerArguments = arguments, ExecutionHandlerEnvironment = environment, ExecutionHandlerPrependPath = PrependPath }; // copy the intermediate script (containerHandlerInvoker.js) into Agent_TempDirectory // Background: // We rely on environment variables to send task execution information from agent to task execution engine (node/powershell) // Those task execution information will include all the variables and secrets customer has. // The only way to pass environment variables to `docker exec` is through command line arguments, ex: `docker exec -e myenv=myvalue -e mysecert=mysecretvalue ...` // Since command execution may get log into system event log which might cause secret leaking. // We use this intermediate script to read everything from STDIN, then launch the task execution engine (node/powershell) and redirect STDOUT/STDERR string tempDir = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), Constants.Path.TempDirectory); string targetEntryScript = Path.Combine(tempDir, "containerHandlerInvoker.js"); HostContext.GetTrace(nameof(ContainerStepHost)).Info($"Copying containerHandlerInvoker.js to {tempDir}"); File.Copy(Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "containerHandlerInvoker.js.template"), targetEntryScript, true); string node; if (!string.IsNullOrEmpty(Container.CustomNodePath)) { node = Container.CustomNodePath; } else { node = Container.TranslateToContainerPath(Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node", "bin", $"node{IOUtil.ExeExtension}")); } string entryScript = Container.TranslateContainerPathForImageOS(PlatformUtil.HostOS, Container.TranslateToContainerPath(targetEntryScript)); string userArgs = ""; if (!PlatformUtil.RunningOnWindows) { userArgs = $"-u {Container.CurrentUserId}"; } string containerExecutionArgs = $"exec -i {userArgs} {Container.ContainerId} {node} {entryScript}"; using (var processInvoker = HostContext.CreateService <IProcessInvoker>()) { processInvoker.OutputDataReceived += OutputDataReceived; processInvoker.ErrorDataReceived += ErrorDataReceived; outputEncoding = null; // Let .NET choose the default. if (PlatformUtil.RunningOnWindows) { // It appears that node.exe outputs UTF8 when not in TTY mode. outputEncoding = Encoding.UTF8; } var redirectStandardIn = new InputQueue <string>(); var payloadJson = JsonUtility.ToString(payload); redirectStandardIn.Enqueue(payloadJson); HostContext.GetTrace(nameof(ContainerStepHost)).Info($"Payload: {payloadJson}"); return(await processInvoker.ExecuteAsync(workingDirectory : HostContext.GetDirectory(WellKnownDirectory.Work), fileName : containerEnginePath, arguments : containerExecutionArgs, environment : null, requireExitCodeZero : requireExitCodeZero, outputEncoding : outputEncoding, killProcessOnCancel : killProcessOnCancel, redirectStandardIn : redirectStandardIn, inheritConsoleHandler : inheritConsoleHandler, cancellationToken : cancellationToken)); } }
public async static Task <int> MainAsync(string[] args) { switch (Constants.Agent.Platform) { case Constants.OSPlatform.Linux: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { Console.WriteLine(StringUtil.Loc("NotLinux")); return(1); } break; case Constants.OSPlatform.OSX: if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { Console.WriteLine(StringUtil.Loc("NotOSX")); return(1); } break; case Constants.OSPlatform.Windows: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Console.WriteLine(StringUtil.Loc("NotWindows")); return(1); } break; } using (HostContext context = new HostContext("Agent")) using (var term = context.GetService <ITerminal>()) { int rc = 0; try { s_trace = context.GetTrace("AgentProcess"); s_trace.Info($"Version: {Constants.Agent.Version}"); s_trace.Info($"Commit: {BuildConstants.Source.CommitHash}"); // // TODO (bryanmac): Need VsoAgent.exe compat shim for SCM // That shim will also provide a compat arg parse // and translate / to -- etc... // CommandLineParser parser = new CommandLineParser(context); parser.Parse(args); s_trace.Info("Arguments parsed"); IAgent agent = context.GetService <IAgent>(); using (agent.TokenSource = new CancellationTokenSource()) { rc = await agent.ExecuteCommand(parser); } } catch (Exception e) { if (!(e is OperationCanceledException)) { Console.Error.WriteLine(StringUtil.Format("An error occured. {0}", e.Message)); } s_trace.Error(e); rc = 1; } return(rc); } }
// Return code definition: (this will be used by service host to determine whether it will re-launch agent.listener) // 0: Agent exit // 1: Terminate failure // 2: Retriable failure // 3: Exit for self update public async static Task <int> MainAsync(string[] args) { using (HostContext context = new HostContext("Agent")) { s_trace = context.GetTrace("AgentProcess"); s_trace.Info($"Agent is built for {Constants.Agent.Platform} - {BuildConstants.AgentPackage.PackageName}."); s_trace.Info($"RuntimeInformation: {RuntimeInformation.OSDescription}."); // Validate the binaries intended for one OS are not running on a different OS. switch (Constants.Agent.Platform) { case Constants.OSPlatform.Linux: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { Console.WriteLine(StringUtil.Loc("NotLinux")); return(Constants.Agent.ReturnCode.TerminatedError); } break; case Constants.OSPlatform.OSX: if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { Console.WriteLine(StringUtil.Loc("NotOSX")); return(Constants.Agent.ReturnCode.TerminatedError); } break; case Constants.OSPlatform.Windows: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Console.WriteLine(StringUtil.Loc("NotWindows")); return(Constants.Agent.ReturnCode.TerminatedError); } break; default: Console.WriteLine(StringUtil.Loc("PlatformNotSupport", RuntimeInformation.OSDescription, Constants.Agent.Platform.ToString())); return(Constants.Agent.ReturnCode.TerminatedError); } int rc = Constants.Agent.ReturnCode.Success; try { s_trace.Info($"Version: {Constants.Agent.Version}"); s_trace.Info($"Commit: {BuildConstants.Source.CommitHash}"); // // TODO (bryanmac): Need VsoAgent.exe compat shim for SCM // That shim will also provide a compat arg parse // and translate / to -- etc... // // Parse the command line args. var command = new CommandSettings(context, args); s_trace.Info("Arguments parsed"); // Defer to the Agent class to execute the command. IAgent agent = context.GetService <IAgent>(); using (agent.TokenSource = new CancellationTokenSource()) { try { rc = await agent.ExecuteCommand(command); } catch (OperationCanceledException) when(agent.TokenSource.IsCancellationRequested) { s_trace.Info("Agent execution been cancelled."); } } } catch (Exception e) { Console.Error.WriteLine(StringUtil.Format("An error occured. {0}", e.Message)); s_trace.Error(e); rc = Constants.Agent.ReturnCode.RetryableError; } return(rc); } }
// Return code definition: (this will be used by service host to determine whether it will re-launch agent.listener) // 0: Agent exit // 1: Terminate failure // 2: Retriable failure // 3: Exit for self update public async static Task<int> MainAsync(string[] args) { using (HostContext context = new HostContext("Agent")) { s_trace = context.GetTrace("AgentProcess"); s_trace.Info($"Agent is built for {Constants.Agent.Platform} - {BuildConstants.AgentPackage.PackageName}."); s_trace.Info($"RuntimeInformation: {RuntimeInformation.OSDescription}."); // Validate the binaries intended for one OS are not running on a different OS. switch (Constants.Agent.Platform) { case Constants.OSPlatform.Linux: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { Console.WriteLine(StringUtil.Loc("NotLinux")); return Constants.Agent.ReturnCode.TerminatedError; } break; case Constants.OSPlatform.OSX: if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { Console.WriteLine(StringUtil.Loc("NotOSX")); return Constants.Agent.ReturnCode.TerminatedError; } break; case Constants.OSPlatform.Windows: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Console.WriteLine(StringUtil.Loc("NotWindows")); return Constants.Agent.ReturnCode.TerminatedError; } break; default: Console.WriteLine(StringUtil.Loc("PlatformNotSupport", RuntimeInformation.OSDescription, Constants.Agent.Platform.ToString())); return Constants.Agent.ReturnCode.TerminatedError; } int rc = Constants.Agent.ReturnCode.Success; try { s_trace.Info($"Version: {Constants.Agent.Version}"); s_trace.Info($"Commit: {BuildConstants.Source.CommitHash}"); s_trace.Info($"Culture: {CultureInfo.CurrentCulture.Name}"); s_trace.Info($"UI Culture: {CultureInfo.CurrentUICulture.Name}"); // // TODO (bryanmac): Need VsoAgent.exe compat shim for SCM // That shim will also provide a compat arg parse // and translate / to -- etc... // // Parse the command line args. var command = new CommandSettings(context, args); s_trace.Info("Arguments parsed"); // Defer to the Agent class to execute the command. IAgent agent = context.GetService<IAgent>(); using (agent.TokenSource = new CancellationTokenSource()) { try { rc = await agent.ExecuteCommand(command); } catch (OperationCanceledException) when (agent.TokenSource.IsCancellationRequested) { s_trace.Info("Agent execution been cancelled."); } } } catch (Exception e) { Console.Error.WriteLine(StringUtil.Format("An error occured. {0}", e.Message)); s_trace.Error(e); rc = Constants.Agent.ReturnCode.RetryableError; } return rc; } }