Beispiel #1
0
        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);
        }
Beispiel #3
0
        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>();
        }
Beispiel #4
0
        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);
                }
        }
Beispiel #5
0
        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));
            }
        }
Beispiel #6
0
        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);
                }
        }
Beispiel #7
0
        // 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);
            }
        }
Beispiel #8
0
        // 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;
            }
        }