CliCommandsWorkflowTests.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. using Tests.EndToEnd.Infra;
  2. using Xunit.Abstractions;
  3. namespace Tests.EndToEnd;
  4. /// <summary>
  5. /// Comprehensive E2E test covering all CLI commands with varied input data.
  6. /// Tests happy paths for CRUD operations, components, labels, and exporters.
  7. /// </summary>
  8. [Collection("Yaml CLI tests")]
  9. public class CliCommandsWorkflowTests(TempYamlCliFixture fs, ITestOutputHelper outputHelper)
  10. : IClassFixture<TempYamlCliFixture> {
  11. private async Task<(string, string)> ExecuteAsync(params string[] args) {
  12. outputHelper.WriteLine($"rpk {string.Join(" ", args)}");
  13. var output = await YamlCliTestHost.RunAsync(
  14. args,
  15. fs.Root,
  16. outputHelper,
  17. "config.yaml"
  18. );
  19. outputHelper.WriteLine(output);
  20. var yaml = await File.ReadAllTextAsync(Path.Combine(fs.Root, "config.yaml"));
  21. return (output, yaml);
  22. }
  23. [Fact]
  24. public async Task comprehensive_cli_workflow_test() {
  25. await File.WriteAllTextAsync(Path.Combine(fs.Root, "config.yaml"), "");
  26. // ============================================================
  27. // GLOBAL: Summary command
  28. // ============================================================
  29. (var output, _) = await ExecuteAsync("summary");
  30. Assert.Contains("Breakdown", output);
  31. // ============================================================
  32. // SERVERS: Full CRUD with components and labels
  33. // ============================================================
  34. // Add server with various naming conventions
  35. (output, _) = await ExecuteAsync("servers", "add", "srv-prod-web01");
  36. // Set server properties with varied data
  37. (output, _) = await ExecuteAsync(
  38. "servers", "set", "srv-prod-web01",
  39. "--ram", "64",
  40. "--ram_mts", "3200",
  41. "--ipmi", "True"
  42. );
  43. Assert.Contains("updated", output);
  44. // Add CPU with bracket format model name
  45. (output, _) = await ExecuteAsync(
  46. "servers", "cpu", "add", "srv-prod-web01",
  47. "--model", "AMD EPYC 7763 [64c]",
  48. "--cores", "64",
  49. "--threads", "128"
  50. );
  51. Assert.Contains("added", output);
  52. // Add drive
  53. (output, _) = await ExecuteAsync(
  54. "servers", "drive", "add", "srv-prod-web01",
  55. "--type", "nvme",
  56. "--size", "4096"
  57. );
  58. Assert.Contains("added", output);
  59. // Add GPU with dash format
  60. (output, _) = await ExecuteAsync(
  61. "servers", "gpu", "add", "srv-prod-web01",
  62. "--model", "NVIDIA-RTX-4090",
  63. "--vram", "24"
  64. );
  65. Assert.Contains("added", output);
  66. // Add NIC
  67. (output, _) = await ExecuteAsync(
  68. "servers", "nic", "add", "srv-prod-web01",
  69. "--type", "RJ45",
  70. "--speed", "10",
  71. "--ports", "2"
  72. );
  73. Assert.Contains("added", output);
  74. // Add label
  75. (output, _) = await ExecuteAsync(
  76. "servers", "label", "add", "srv-prod-web01",
  77. "--key", "env", "--value", "production"
  78. );
  79. Assert.Contains("Label", output);
  80. // Get server
  81. (output, _) = await ExecuteAsync("servers", "get", "srv-prod-web01");
  82. Assert.Contains("srv-prod-web01", output);
  83. Assert.Contains("64 GB", output);
  84. // Get server
  85. (output, _) = await ExecuteAsync("servers", "get", "srv-prod-web01");
  86. Assert.Contains("srv-prod-web01", output);
  87. // Describe
  88. (output, _) = await ExecuteAsync("servers", "describe", "srv-prod-web01");
  89. Assert.Contains("srv-prod-web01", output);
  90. Assert.Contains("EPYC", output);
  91. // Tree
  92. (output, _) = await ExecuteAsync("servers", "tree", "srv-prod-web01");
  93. Assert.Contains("srv-prod-web01", output);
  94. // ============================================================
  95. // SWITCHES: Full workflow
  96. // ============================================================
  97. (output, _) = await ExecuteAsync("switches", "add", "sw-core-01");
  98. Assert.Contains("added", output);
  99. (output, _) = await ExecuteAsync(
  100. "switches", "set", "sw-core-01",
  101. "--model", "Cisco-C9300-48P",
  102. "--managed", "true",
  103. "--poe", "true"
  104. );
  105. Assert.Contains("updated", output);
  106. (output, _) = await ExecuteAsync("switches", "port", "add", "sw-core-01", "--type", "SFP+", "--speed", "25", "--ports", "4");
  107. Assert.Contains("added", output);
  108. (output, _) = await ExecuteAsync(
  109. "switches", "label", "add", "sw-core-01",
  110. "--key", "zone", "--value", "core"
  111. );
  112. Assert.Contains("added", output);
  113. (output, _) = await ExecuteAsync("switches", "get", "sw-core-01");
  114. Assert.Contains("sw-core-01", output);
  115. (output, _) = await ExecuteAsync("switches", "list");
  116. Assert.Contains("sw-core-01", output);
  117. (output, _) = await ExecuteAsync("switches", "summary");
  118. Assert.Contains("Name", output);
  119. (output, _) = await ExecuteAsync("switches", "describe", "sw-core-01");
  120. Assert.Contains("sw-core-01", output);
  121. // ============================================================
  122. // ROUTERS: Full workflow
  123. // ============================================================
  124. (output, _) = await ExecuteAsync("routers", "add", "rt-edge-01");
  125. Assert.Contains("added", output);
  126. (output, _) = await ExecuteAsync(
  127. "routers", "set", "rt-edge-01",
  128. "--Model", "MikroTik-CCR2004",
  129. "--managed", "true",
  130. "--poe", "false"
  131. );
  132. Assert.Contains("updated", output);
  133. (output, _) = await ExecuteAsync("routers", "port", "add", "rt-edge-01", "--type", "SFP", "--speed", "10", "--ports", "8");
  134. Assert.Contains("added", output);
  135. (output, _) = await ExecuteAsync(
  136. "routers", "label", "add", "rt-edge-01",
  137. "--key", "tier", "--value", "edge"
  138. );
  139. Assert.Contains("added", output);
  140. (output, _) = await ExecuteAsync("routers", "get", "rt-edge-01");
  141. Assert.Contains("rt-edge-01", output);
  142. (output, _) = await ExecuteAsync("routers", "list");
  143. Assert.Contains("rt-edge-01", output);
  144. (output, _) = await ExecuteAsync("routers", "summary");
  145. Assert.Contains("Name", output);
  146. (output, _) = await ExecuteAsync("routers", "describe", "rt-edge-01");
  147. Assert.Contains("rt-edge-01", output);
  148. // ============================================================
  149. // FIREWALLS: Full workflow
  150. // ============================================================
  151. (output, _) = await ExecuteAsync("firewalls", "add", "fw-perimeter-01");
  152. Assert.Contains("added", output);
  153. (output, _) = await ExecuteAsync(
  154. "firewalls", "set", "fw-perimeter-01",
  155. "--Model", "PaloAlto-PA-5220",
  156. "--managed", "true",
  157. "--poe", "false"
  158. );
  159. Assert.Contains("updated", output);
  160. (output, _) = await ExecuteAsync("firewalls", "port", "add", "fw-perimeter-01", "--type", "RJ45", "--speed", "1", "--ports", "10");
  161. Assert.Contains("added", output);
  162. (output, _) = await ExecuteAsync(
  163. "firewalls", "label", "add", "fw-perimeter-01",
  164. "--key", "security", "--value", "dmz"
  165. );
  166. Assert.Contains("added", output);
  167. (output, _) = await ExecuteAsync("firewalls", "get", "fw-perimeter-01");
  168. Assert.Contains("fw-perimeter-01", output);
  169. (output, _) = await ExecuteAsync("firewalls", "list");
  170. Assert.Contains("fw-perimeter-01", output);
  171. (output, _) = await ExecuteAsync("firewalls", "summary");
  172. Assert.Contains("Name", output);
  173. (output, _) = await ExecuteAsync("firewalls", "describe", "fw-perimeter-01");
  174. Assert.Contains("fw-perimeter-01", output);
  175. // ============================================================
  176. // SYSTEMS: Full workflow with tree
  177. // ============================================================
  178. (output, _) = await ExecuteAsync("systems", "add", "sys-app-web-01");
  179. Assert.Contains("added", output);
  180. (output, _) = await ExecuteAsync(
  181. "systems", "set", "sys-app-web-01",
  182. "--type", "container",
  183. "--os", "ubuntu-22.04",
  184. "--cores", "4",
  185. "--ram", "16",
  186. "--ip", "10.0.1.50",
  187. "--runs-on", "srv-prod-web01"
  188. );
  189. Assert.Contains("updated", output);
  190. (output, _) = await ExecuteAsync(
  191. "systems", "label", "add", "sys-app-web-01",
  192. "--key", "app", "--value", "web-frontend"
  193. );
  194. Assert.Contains("added", output);
  195. (output, _) = await ExecuteAsync("systems", "get", "sys-app-web-01");
  196. Assert.Contains("sys-app-web-01", output);
  197. (output, _) = await ExecuteAsync("systems", "list");
  198. Assert.Contains("Name", output);
  199. (output, _) = await ExecuteAsync("systems", "summary");
  200. Assert.Contains("Name", output);
  201. (output, _) = await ExecuteAsync("systems", "describe", "sys-app-web-01");
  202. Assert.Contains("container", output);
  203. (output, _) = await ExecuteAsync("systems", "tree", "sys-app-web-01");
  204. Assert.Contains("sys-app-web-01", output);
  205. // ============================================================
  206. // ACCESS POINTS: Full workflow
  207. // ============================================================
  208. (output, _) = await ExecuteAsync("accesspoints", "add", "ap-floor2-01");
  209. Assert.Contains("added", output);
  210. (output, _) = await ExecuteAsync(
  211. "accesspoints", "set", "ap-floor2-01",
  212. "--model", "Ubiquiti-U6-Pro",
  213. "--speed", "2.5"
  214. );
  215. Assert.Contains("updated", output);
  216. (output, _) = await ExecuteAsync(
  217. "accesspoints", "label", "add", "ap-floor2-01",
  218. "--key", "location", "--value", "floor-2"
  219. );
  220. Assert.Contains("added", output);
  221. (output, _) = await ExecuteAsync("accesspoints", "get", "ap-floor2-01");
  222. Assert.Contains("ap-floor2-01", output);
  223. Assert.Contains("Ubiquiti", output);
  224. (output, _) = await ExecuteAsync("accesspoints", "list");
  225. Assert.Contains("ap-floor2-01", output);
  226. (output, _) = await ExecuteAsync("accesspoints", "summary");
  227. Assert.Contains("Name", output);
  228. (output, _) = await ExecuteAsync("accesspoints", "describe", "ap-floor2-01");
  229. Assert.Contains("ap-floor2-01", output);
  230. // ============================================================
  231. // UPS: Full workflow
  232. // ============================================================
  233. (output, _) = await ExecuteAsync("ups", "add", "ups-rack-a-01");
  234. Assert.Contains("added", output);
  235. (output, _) = await ExecuteAsync(
  236. "ups", "set", "ups-rack-a-01",
  237. "--model", "APC-SmartUPS-3000",
  238. "--va", "3000"
  239. );
  240. Assert.Contains("updated", output);
  241. (output, _) = await ExecuteAsync(
  242. "ups", "label", "add", "ups-rack-a-01",
  243. "--key", "rack", "--value", "a"
  244. );
  245. Assert.Contains("added", output);
  246. (output, _) = await ExecuteAsync("ups", "get", "ups-rack-a-01");
  247. Assert.Contains("ups-rack-a-01", output);
  248. Assert.Contains("3000", output);
  249. (output, _) = await ExecuteAsync("ups", "list");
  250. Assert.Contains("ups-rack-a-01", output);
  251. (output, _) = await ExecuteAsync("ups", "summary");
  252. Assert.Contains("Name", output);
  253. (output, _) = await ExecuteAsync("ups", "describe", "ups-rack-a-01");
  254. Assert.Contains("ups-rack-a-01", output);
  255. // ============================================================
  256. // DESKTOPS: Full workflow with components
  257. // ============================================================
  258. (output, _) = await ExecuteAsync("desktops", "add", "dtp-workstation-01");
  259. Assert.Contains("added", output);
  260. (output, _) = await ExecuteAsync(
  261. "desktops", "set", "dtp-workstation-01",
  262. "--model", "Dell-Precision-7865"
  263. );
  264. Assert.Contains("updated", output);
  265. (output, _) = await ExecuteAsync(
  266. "desktops", "cpu", "add", "dtp-workstation-01",
  267. "--model", "AMD-Ryzen-9-7950X",
  268. "--cores", "16",
  269. "--threads", "32"
  270. );
  271. Assert.Contains("added", output);
  272. (output, _) = await ExecuteAsync(
  273. "desktops", "drive", "add", "dtp-workstation-01",
  274. "--type", "ssd",
  275. "--size", "2048"
  276. );
  277. Assert.Contains("added", output);
  278. (output, _) = await ExecuteAsync(
  279. "desktops", "gpu", "add", "dtp-workstation-01",
  280. "--model", "NVIDIA-RTX-3090",
  281. "--vram", "24"
  282. );
  283. Assert.Contains("added", output);
  284. (output, _) = await ExecuteAsync(
  285. "desktops", "nic", "add", "dtp-workstation-01",
  286. "--type", "RJ45",
  287. "--speed", "10",
  288. "--ports", "2"
  289. );
  290. Assert.Contains("added", output);
  291. (output, _) = await ExecuteAsync("desktops", "get", "dtp-workstation-01");
  292. Assert.Contains("dtp-workstation-01", output);
  293. (output, _) = await ExecuteAsync("desktops", "list");
  294. Assert.Contains("dtp-workstation-01", output);
  295. (output, _) = await ExecuteAsync("desktops", "summary");
  296. Assert.Contains("Name", output);
  297. (output, _) = await ExecuteAsync("desktops", "describe", "dtp-workstation-01");
  298. Assert.Contains("dtp-workstation-01", output);
  299. // ============================================================
  300. // LAPTOPS: Full workflow with components
  301. // ============================================================
  302. (output, _) = await ExecuteAsync("laptops", "add", "ltp-dev-01");
  303. Assert.Contains("added", output);
  304. (output, _) = await ExecuteAsync(
  305. "laptops", "set", "ltp-dev-01",
  306. "--model", "Lenovo-ThinkPad-X1"
  307. );
  308. Assert.Contains("updated", output);
  309. (output, _) = await ExecuteAsync(
  310. "laptops", "cpu", "add", "ltp-dev-01",
  311. "--model", "Intel-i9-12900H",
  312. "--cores", "14",
  313. "--threads", "20"
  314. );
  315. Assert.Contains("added", output);
  316. (output, _) = await ExecuteAsync(
  317. "laptops", "drives", "add", "ltp-dev-01",
  318. "--type", "ssd",
  319. "--size", "1024"
  320. );
  321. Assert.Contains("added", output);
  322. (output, _) = await ExecuteAsync(
  323. "laptops", "gpu", "add", "ltp-dev-01",
  324. "--model", "Intel-Iris-Xe",
  325. "--vram", "2"
  326. );
  327. Assert.Contains("added", output);
  328. (output, _) = await ExecuteAsync("laptops", "get", "ltp-dev-01");
  329. Assert.Contains("ltp-dev-01", output);
  330. (output, _) = await ExecuteAsync("laptops", "list");
  331. Assert.Contains("ltp-dev-01", output);
  332. (output, _) = await ExecuteAsync("laptops", "summary");
  333. Assert.Contains("Name", output);
  334. (output, _) = await ExecuteAsync("laptops", "describe", "ltp-dev-01");
  335. Assert.Contains("ltp-dev-01", output);
  336. // ============================================================
  337. // SERVICES: Full workflow
  338. // ============================================================
  339. (output, _) = await ExecuteAsync("services", "add", "svc-postgres-primary");
  340. Assert.Contains("added", output);
  341. (output, _) = await ExecuteAsync(
  342. "services", "set", "svc-postgres-primary",
  343. "--ip", "10.0.0.100",
  344. "--port", "5432",
  345. "--protocol", "tcp",
  346. "--url", "postgresql://10.0.0.100:5432",
  347. "--runs-on", "sys-app-web-01"
  348. );
  349. Assert.Contains("updated", output);
  350. (output, _) = await ExecuteAsync(
  351. "services", "label", "add", "svc-postgres-primary",
  352. "--key", "db-type", "--value", "postgresql"
  353. );
  354. Assert.Contains("added", output);
  355. (output, _) = await ExecuteAsync("services", "get", "svc-postgres-primary");
  356. Assert.Contains("svc-postgres-primary", output);
  357. (output, _) = await ExecuteAsync("services", "list");
  358. Assert.Contains("Name", output);
  359. (output, _) = await ExecuteAsync("services", "summary");
  360. Assert.Contains("Name", output);
  361. (output, _) = await ExecuteAsync("services", "describe", "svc-postgres-primary");
  362. Assert.Contains("svc-postgres-primary", output);
  363. (output, _) = await ExecuteAsync("services", "subnets");
  364. Assert.Contains("Services", output);
  365. // ============================================================
  366. // EXPORTERS: Full workflow
  367. // ============================================================
  368. // Ansible inventory export
  369. (output, _) = await ExecuteAsync("ansible", "inventory");
  370. Assert.Contains("Generated Inventory", output);
  371. // SSH export
  372. (output, _) = await ExecuteAsync("ssh", "export");
  373. Assert.Contains("Generated SSH Config", output);
  374. // Hosts export
  375. (output, _) = await ExecuteAsync("hosts", "export");
  376. Assert.Contains("Generated Hosts File", output);
  377. // ============================================================
  378. // CONNECTIONS: Full workflow
  379. // ============================================================
  380. (output, _) = await ExecuteAsync(
  381. "connections", "add",
  382. "--resource-a", "sw-core-01",
  383. "--port-a", "1",
  384. "--resource-b", "fw-perimeter-01",
  385. "--port-b", "1"
  386. );
  387. if (!output.Contains("added")) {
  388. Assert.Contains("Error", output);
  389. }
  390. else {
  391. Assert.Contains("added", output);
  392. }
  393. (output, _) = await ExecuteAsync(
  394. "connections", "remove",
  395. "--resource", "sw-core-01",
  396. "--port", "1"
  397. );
  398. if (!output.Contains("removed")) {
  399. Assert.Contains("Error", output);
  400. }
  401. else {
  402. Assert.Contains("removed", output);
  403. }
  404. // ============================================================
  405. // DELETE resources to verify cleanup
  406. // ============================================================
  407. (output, _) = await ExecuteAsync("servers", "del", "srv-prod-web01");
  408. Assert.Contains("deleted", output);
  409. (output, _) = await ExecuteAsync("switches", "del", "sw-core-01");
  410. Assert.Contains("deleted", output);
  411. (output, _) = await ExecuteAsync("routers", "del", "rt-edge-01");
  412. Assert.Contains("deleted", output);
  413. (output, _) = await ExecuteAsync("firewalls", "del", "fw-perimeter-01");
  414. Assert.Contains("deleted", output);
  415. (output, _) = await ExecuteAsync("systems", "del", "sys-app-web-01");
  416. Assert.Contains("deleted", output);
  417. (output, _) = await ExecuteAsync("accesspoints", "del", "ap-floor2-01");
  418. Assert.Contains("deleted", output);
  419. (output, _) = await ExecuteAsync("ups", "del", "ups-rack-a-01");
  420. Assert.Contains("deleted", output);
  421. (output, _) = await ExecuteAsync("desktops", "del", "dtp-workstation-01");
  422. Assert.Contains("deleted", output);
  423. (output, _) = await ExecuteAsync("laptops", "del", "ltp-dev-01");
  424. Assert.Contains("deleted", output);
  425. (output, _) = await ExecuteAsync("services", "del", "svc-postgres-primary");
  426. Assert.Contains("deleted", output);
  427. // Verify all resources are gone
  428. (output, _) = await ExecuteAsync("summary");
  429. }
  430. }