PageRenderTime 89ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Agent.Listener/CommandSettings.cs

https://gitlab.com/srbhgupta/vsts-agent
C# | 310 lines | 247 code | 40 blank | 23 comment | 5 complexity | 9d3d8d31dd3851af16cf6c47ecb1c4e9 MD5 | raw file
  1. using Microsoft.VisualStudio.Services.Agent.Listener.Configuration;
  2. using Microsoft.VisualStudio.Services.Agent.Util;
  3. using System;
  4. using System.Linq;
  5. using System.Collections.Generic;
  6. namespace Microsoft.VisualStudio.Services.Agent.Listener
  7. {
  8. public sealed class CommandSettings
  9. {
  10. private readonly IHostContext _context;
  11. private readonly CommandLineParser _parser;
  12. private readonly IPromptManager _promptManager;
  13. private readonly Tracing _trace;
  14. private readonly string[] validCommands =
  15. {
  16. Constants.Agent.CommandLine.Commands.Configure,
  17. Constants.Agent.CommandLine.Commands.Run,
  18. Constants.Agent.CommandLine.Commands.Unconfigure
  19. };
  20. private readonly string[] validFlags =
  21. {
  22. Constants.Agent.CommandLine.Flags.AcceptTeeEula,
  23. Constants.Agent.CommandLine.Flags.Commit,
  24. Constants.Agent.CommandLine.Flags.Help,
  25. Constants.Agent.CommandLine.Flags.Replace,
  26. Constants.Agent.CommandLine.Flags.RunAsService,
  27. Constants.Agent.CommandLine.Flags.Unattended,
  28. Constants.Agent.CommandLine.Flags.Version
  29. };
  30. private readonly string[] validArgs =
  31. {
  32. Constants.Agent.CommandLine.Args.Agent,
  33. Constants.Agent.CommandLine.Args.Auth,
  34. Constants.Agent.CommandLine.Args.NotificationPipeName,
  35. Constants.Agent.CommandLine.Args.Password,
  36. Constants.Agent.CommandLine.Args.Pool,
  37. Constants.Agent.CommandLine.Args.Token,
  38. Constants.Agent.CommandLine.Args.Url,
  39. Constants.Agent.CommandLine.Args.UserName,
  40. Constants.Agent.CommandLine.Args.WindowsLogonAccount,
  41. Constants.Agent.CommandLine.Args.WindowsLogonPassword,
  42. Constants.Agent.CommandLine.Args.Work
  43. };
  44. // Commands.
  45. public bool Configure => TestCommand(Constants.Agent.CommandLine.Commands.Configure);
  46. public bool Run => TestCommand(Constants.Agent.CommandLine.Commands.Run);
  47. public bool Unconfigure => TestCommand(Constants.Agent.CommandLine.Commands.Unconfigure);
  48. // Flags.
  49. public bool Commit => TestFlag(Constants.Agent.CommandLine.Flags.Commit);
  50. public bool Help => TestFlag(Constants.Agent.CommandLine.Flags.Help);
  51. public bool Unattended => TestFlag(Constants.Agent.CommandLine.Flags.Unattended);
  52. public bool Version => TestFlag(Constants.Agent.CommandLine.Flags.Version);
  53. // Constructor.
  54. public CommandSettings(IHostContext context, string[] args)
  55. {
  56. ArgUtil.NotNull(context, nameof(context));
  57. _context = context;
  58. _promptManager = context.GetService<IPromptManager>();
  59. _trace = context.GetTrace(nameof(CommandSettings));
  60. // Parse the command line args.
  61. _parser = new CommandLineParser(
  62. hostContext: context,
  63. secretArgNames: Constants.Agent.CommandLine.Args.Secrets);
  64. _parser.Parse(args);
  65. }
  66. // Validate commandline parser result
  67. public List<string> Validate()
  68. {
  69. List<string> unknowns = new List<string>();
  70. // detect unknown commands
  71. unknowns.AddRange(_parser.Commands.Where(x => !validCommands.Contains(x)));
  72. // detect unknown flags
  73. unknowns.AddRange(_parser.Flags.Where(x => !validFlags.Contains(x)));
  74. // detect unknown args
  75. unknowns.AddRange(_parser.Args.Keys.Where(x => !validArgs.Contains(x)));
  76. return unknowns;
  77. }
  78. //
  79. // Interactive flags.
  80. //
  81. public bool GetAcceptTeeEula()
  82. {
  83. return TestFlagOrPrompt(
  84. name: Constants.Agent.CommandLine.Flags.AcceptTeeEula,
  85. description: StringUtil.Loc("AcceptTeeEula"),
  86. defaultValue: false);
  87. }
  88. public bool GetReplace()
  89. {
  90. return TestFlagOrPrompt(
  91. name: Constants.Agent.CommandLine.Flags.Replace,
  92. description: StringUtil.Loc("Replace"),
  93. defaultValue: false);
  94. }
  95. public bool GetRunAsService()
  96. {
  97. return TestFlagOrPrompt(
  98. name: Constants.Agent.CommandLine.Flags.RunAsService,
  99. description: StringUtil.Loc("RunAgentAsServiceDescription"),
  100. defaultValue: false);
  101. }
  102. //
  103. // Args.
  104. //
  105. public string GetAgentName()
  106. {
  107. return GetArgOrPrompt(
  108. name: Constants.Agent.CommandLine.Args.Agent,
  109. description: StringUtil.Loc("AgentName"),
  110. defaultValue: Environment.MachineName ?? "myagent",
  111. validator: Validators.NonEmptyValidator);
  112. }
  113. public string GetAuth(string defaultValue)
  114. {
  115. return GetArgOrPrompt(
  116. name: Constants.Agent.CommandLine.Args.Auth,
  117. description: StringUtil.Loc("AuthenticationType"),
  118. defaultValue: defaultValue,
  119. validator: Validators.AuthSchemeValidator);
  120. }
  121. public string GetPassword()
  122. {
  123. return GetArgOrPrompt(
  124. name: Constants.Agent.CommandLine.Args.Password,
  125. description: StringUtil.Loc("Password"),
  126. defaultValue: string.Empty,
  127. validator: Validators.NonEmptyValidator);
  128. }
  129. public string GetPool()
  130. {
  131. return GetArgOrPrompt(
  132. name: Constants.Agent.CommandLine.Args.Pool,
  133. description: StringUtil.Loc("AgentMachinePoolNameLabel"),
  134. defaultValue: "default",
  135. validator: Validators.NonEmptyValidator);
  136. }
  137. public string GetToken()
  138. {
  139. return GetArgOrPrompt(
  140. name: Constants.Agent.CommandLine.Args.Token,
  141. description: StringUtil.Loc("PersonalAccessToken"),
  142. defaultValue: string.Empty,
  143. validator: Validators.NonEmptyValidator);
  144. }
  145. public string GetUrl()
  146. {
  147. return GetArgOrPrompt(
  148. name: Constants.Agent.CommandLine.Args.Url,
  149. description: StringUtil.Loc("ServerUrl"),
  150. defaultValue: string.Empty,
  151. validator: Validators.ServerUrlValidator);
  152. }
  153. public string GetUserName()
  154. {
  155. return GetArgOrPrompt(
  156. name: Constants.Agent.CommandLine.Args.UserName,
  157. description: StringUtil.Loc("UserName"),
  158. defaultValue: string.Empty,
  159. validator: Validators.NonEmptyValidator);
  160. }
  161. public string GetWindowsLogonAccount(string defaultValue)
  162. {
  163. return GetArgOrPrompt(
  164. name: Constants.Agent.CommandLine.Args.WindowsLogonAccount,
  165. description: StringUtil.Loc("WindowsLogonAccountNameDescription"),
  166. defaultValue: defaultValue,
  167. validator: Validators.NTAccountValidator);
  168. }
  169. public string GetWindowsLogonPassword(string accountName)
  170. {
  171. return GetArgOrPrompt(
  172. name: Constants.Agent.CommandLine.Args.WindowsLogonPassword,
  173. description: StringUtil.Loc("WindowsLogonPasswordDescription", accountName),
  174. defaultValue: string.Empty,
  175. validator: Validators.NonEmptyValidator);
  176. }
  177. public string GetWork()
  178. {
  179. return GetArgOrPrompt(
  180. name: Constants.Agent.CommandLine.Args.Work,
  181. description: StringUtil.Loc("WorkFolderDescription"),
  182. defaultValue: Constants.Path.WorkDirectory,
  183. validator: Validators.NonEmptyValidator);
  184. }
  185. public string GetNotificationPipeName()
  186. {
  187. return GetArg(Constants.Agent.CommandLine.Args.NotificationPipeName);
  188. }
  189. //
  190. // Private helpers.
  191. //
  192. private string GetArg(string name)
  193. {
  194. string result;
  195. if (!_parser.Args.TryGetValue(name, out result))
  196. {
  197. result = null;
  198. }
  199. return result;
  200. }
  201. private void RemoveArg(string name)
  202. {
  203. if (_parser.Args.ContainsKey(name))
  204. {
  205. _parser.Args.Remove(name);
  206. }
  207. }
  208. private string GetArgOrPrompt(
  209. string name,
  210. string description,
  211. string defaultValue,
  212. Func<string, bool> validator)
  213. {
  214. // Check for the arg in the command line parser.
  215. ArgUtil.NotNull(validator, nameof(validator));
  216. string result = GetArg(name);
  217. // Return the arg if it is not empty and is valid.
  218. _trace.Info($"Arg '{name}': '{result}'");
  219. if (!string.IsNullOrEmpty(result))
  220. {
  221. // After read the arg from input commandline args, remove it from Arg dictionary,
  222. // This will help if bad arg value passed through CommandLine arg, when ConfigurationManager ask CommandSetting the second time,
  223. // It will prompt for input intead of continue use the bad input.
  224. _trace.Info($"Remove {name} from Arg dictionary.");
  225. RemoveArg(name);
  226. if (validator(result))
  227. {
  228. return result;
  229. }
  230. _trace.Info("Arg is invalid.");
  231. }
  232. // Otherwise prompt for the arg.
  233. return _promptManager.ReadValue(
  234. argName: name,
  235. description: description,
  236. secret: Constants.Agent.CommandLine.Args.Secrets.Any(x => string.Equals(x, name, StringComparison.OrdinalIgnoreCase)),
  237. defaultValue: defaultValue,
  238. validator: validator,
  239. unattended: Unattended);
  240. }
  241. private bool TestCommand(string name)
  242. {
  243. bool result = _parser.IsCommand(name);
  244. _trace.Info($"Command '{name}': '{result}'");
  245. return result;
  246. }
  247. private bool TestFlag(string name)
  248. {
  249. bool result = _parser.Flags.Contains(name);
  250. _trace.Info($"Flag '{name}': '{result}'");
  251. return result;
  252. }
  253. private bool TestFlagOrPrompt(
  254. string name,
  255. string description,
  256. bool defaultValue)
  257. {
  258. bool result = TestFlag(name);
  259. if (!result)
  260. {
  261. result = _promptManager.ReadBool(
  262. argName: name,
  263. description: description,
  264. defaultValue: defaultValue,
  265. unattended: Unattended);
  266. }
  267. return result;
  268. }
  269. }
  270. }