@rollupdate/hctl 0.0.0-stage → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1066 -2
  3. package/dist/auction/cache.d.ts +6 -0
  4. package/dist/auction/cache.js +55 -0
  5. package/dist/auction/client.d.ts +24 -0
  6. package/dist/auction/client.js +236 -0
  7. package/dist/auction/commands.d.ts +2 -0
  8. package/dist/auction/commands.js +440 -0
  9. package/dist/auction/diff-formatter.d.ts +3 -0
  10. package/dist/auction/diff-formatter.js +61 -0
  11. package/dist/auction/diff.d.ts +11 -0
  12. package/dist/auction/diff.js +28 -0
  13. package/dist/auction/formatter.d.ts +21 -0
  14. package/dist/auction/formatter.js +182 -0
  15. package/dist/auction/store.d.ts +24 -0
  16. package/dist/auction/store.js +177 -0
  17. package/dist/auction/types.d.ts +74 -0
  18. package/dist/auction/types.js +5 -0
  19. package/dist/cli.d.ts +2 -0
  20. package/dist/cli.js +74 -0
  21. package/dist/client.d.ts +2 -0
  22. package/dist/client.js +4 -0
  23. package/dist/cloud/browser-bootstrap.d.ts +16 -0
  24. package/dist/cloud/browser-bootstrap.js +438 -0
  25. package/dist/cloud/client.d.ts +520 -0
  26. package/dist/cloud/client.js +755 -0
  27. package/dist/cloud/commands/certificate.d.ts +2 -0
  28. package/dist/cloud/commands/certificate.js +108 -0
  29. package/dist/cloud/commands/context.d.ts +2 -0
  30. package/dist/cloud/commands/context.js +133 -0
  31. package/dist/cloud/commands/datacenter.d.ts +2 -0
  32. package/dist/cloud/commands/datacenter.js +24 -0
  33. package/dist/cloud/commands/firewall.d.ts +2 -0
  34. package/dist/cloud/commands/firewall.js +142 -0
  35. package/dist/cloud/commands/floating-ip.d.ts +2 -0
  36. package/dist/cloud/commands/floating-ip.js +138 -0
  37. package/dist/cloud/commands/image.d.ts +2 -0
  38. package/dist/cloud/commands/image.js +98 -0
  39. package/dist/cloud/commands/index.d.ts +2 -0
  40. package/dist/cloud/commands/index.js +47 -0
  41. package/dist/cloud/commands/inventory.d.ts +2 -0
  42. package/dist/cloud/commands/inventory.js +13 -0
  43. package/dist/cloud/commands/iso.d.ts +2 -0
  44. package/dist/cloud/commands/iso.js +27 -0
  45. package/dist/cloud/commands/load-balancer-type.d.ts +2 -0
  46. package/dist/cloud/commands/load-balancer-type.js +24 -0
  47. package/dist/cloud/commands/load-balancer.d.ts +2 -0
  48. package/dist/cloud/commands/load-balancer.js +269 -0
  49. package/dist/cloud/commands/location.d.ts +2 -0
  50. package/dist/cloud/commands/location.js +24 -0
  51. package/dist/cloud/commands/network.d.ts +2 -0
  52. package/dist/cloud/commands/network.js +157 -0
  53. package/dist/cloud/commands/placement-group.d.ts +2 -0
  54. package/dist/cloud/commands/placement-group.js +79 -0
  55. package/dist/cloud/commands/pricing.d.ts +2 -0
  56. package/dist/cloud/commands/pricing.js +15 -0
  57. package/dist/cloud/commands/primary-ip.d.ts +2 -0
  58. package/dist/cloud/commands/primary-ip.js +139 -0
  59. package/dist/cloud/commands/server-type.d.ts +2 -0
  60. package/dist/cloud/commands/server-type.js +24 -0
  61. package/dist/cloud/commands/server.d.ts +2 -0
  62. package/dist/cloud/commands/server.js +346 -0
  63. package/dist/cloud/commands/ssh-key.d.ts +2 -0
  64. package/dist/cloud/commands/ssh-key.js +94 -0
  65. package/dist/cloud/commands/volume.d.ts +2 -0
  66. package/dist/cloud/commands/volume.js +138 -0
  67. package/dist/cloud/context.d.ts +34 -0
  68. package/dist/cloud/context.js +215 -0
  69. package/dist/cloud/formatter.d.ts +40 -0
  70. package/dist/cloud/formatter.js +824 -0
  71. package/dist/cloud/helpers.d.ts +27 -0
  72. package/dist/cloud/helpers.js +67 -0
  73. package/dist/cloud/inventory.d.ts +100 -0
  74. package/dist/cloud/inventory.js +229 -0
  75. package/dist/cloud/pricing.d.ts +27 -0
  76. package/dist/cloud/pricing.js +103 -0
  77. package/dist/cloud/token-instructions.d.ts +2 -0
  78. package/dist/cloud/token-instructions.js +21 -0
  79. package/dist/cloud/types.d.ts +437 -0
  80. package/dist/cloud/types.js +5 -0
  81. package/dist/config.d.ts +1 -0
  82. package/dist/config.js +2 -0
  83. package/dist/formatter.d.ts +3 -0
  84. package/dist/formatter.js +6 -0
  85. package/dist/index.d.ts +12 -0
  86. package/dist/index.js +21 -0
  87. package/dist/robot/client.d.ts +246 -0
  88. package/dist/robot/client.js +719 -0
  89. package/dist/robot/commands/auth.d.ts +2 -0
  90. package/dist/robot/commands/auth.js +54 -0
  91. package/dist/robot/commands/boot.d.ts +2 -0
  92. package/dist/robot/commands/boot.js +76 -0
  93. package/dist/robot/commands/cancel.d.ts +2 -0
  94. package/dist/robot/commands/cancel.js +37 -0
  95. package/dist/robot/commands/failover.d.ts +2 -0
  96. package/dist/robot/commands/failover.js +46 -0
  97. package/dist/robot/commands/firewall.d.ts +2 -0
  98. package/dist/robot/commands/firewall.js +72 -0
  99. package/dist/robot/commands/index.d.ts +2 -0
  100. package/dist/robot/commands/index.js +36 -0
  101. package/dist/robot/commands/interactive.d.ts +2 -0
  102. package/dist/robot/commands/interactive.js +152 -0
  103. package/dist/robot/commands/ip.d.ts +2 -0
  104. package/dist/robot/commands/ip.js +55 -0
  105. package/dist/robot/commands/key.d.ts +2 -0
  106. package/dist/robot/commands/key.js +68 -0
  107. package/dist/robot/commands/order.d.ts +2 -0
  108. package/dist/robot/commands/order.js +33 -0
  109. package/dist/robot/commands/rdns.d.ts +2 -0
  110. package/dist/robot/commands/rdns.js +41 -0
  111. package/dist/robot/commands/reset.d.ts +2 -0
  112. package/dist/robot/commands/reset.js +77 -0
  113. package/dist/robot/commands/server.d.ts +2 -0
  114. package/dist/robot/commands/server.js +32 -0
  115. package/dist/robot/commands/storagebox.d.ts +2 -0
  116. package/dist/robot/commands/storagebox.js +126 -0
  117. package/dist/robot/commands/subnet.d.ts +2 -0
  118. package/dist/robot/commands/subnet.js +24 -0
  119. package/dist/robot/commands/traffic.d.ts +2 -0
  120. package/dist/robot/commands/traffic.js +23 -0
  121. package/dist/robot/commands/vswitch.d.ts +2 -0
  122. package/dist/robot/commands/vswitch.js +65 -0
  123. package/dist/robot/commands/wol.d.ts +2 -0
  124. package/dist/robot/commands/wol.js +20 -0
  125. package/dist/robot/formatter.d.ts +56 -0
  126. package/dist/robot/formatter.js +546 -0
  127. package/dist/robot/types.d.ts +353 -0
  128. package/dist/robot/types.js +5 -0
  129. package/dist/shared/config.d.ts +86 -0
  130. package/dist/shared/config.js +289 -0
  131. package/dist/shared/formatter.d.ts +29 -0
  132. package/dist/shared/formatter.js +121 -0
  133. package/dist/shared/helpers.d.ts +39 -0
  134. package/dist/shared/helpers.js +86 -0
  135. package/dist/shared/init.d.ts +2 -0
  136. package/dist/shared/init.js +107 -0
  137. package/dist/shared/reference.d.ts +5 -0
  138. package/dist/shared/reference.js +688 -0
  139. package/dist/shared/schemas.d.ts +1 -0
  140. package/dist/shared/schemas.js +1022 -0
  141. package/dist/types.d.ts +2 -0
  142. package/dist/types.js +2 -0
  143. package/package.json +131 -4
@@ -0,0 +1,98 @@
1
+ import { success } from "../../shared/formatter.js";
2
+ import { confirmAction, output } from "../../shared/helpers.js";
3
+ import { formatImageDetails, formatImageList } from "../formatter.js";
4
+ import { cloudAction, resolveIdOrName, } from "../helpers.js";
5
+ export function registerImageCommands(parent) {
6
+ const image = parent.command("image").description("Image management");
7
+ image
8
+ .command("list")
9
+ .alias("ls")
10
+ .description("List all images")
11
+ .option("-l, --label-selector <selector>", "Label selector")
12
+ .option("-s, --sort <field>", "Sort by field")
13
+ .option("--type <type>", "Filter by type (system, snapshot, backup, app)")
14
+ .option("--architecture <arch>", "Filter by architecture (x86, arm)")
15
+ .option("--status <status>", "Filter by status")
16
+ .action(cloudAction(async (client, options) => {
17
+ const images = await client.listImages({
18
+ label_selector: options.labelSelector,
19
+ sort: options.sort,
20
+ type: options.type,
21
+ architecture: options.architecture,
22
+ status: options.status,
23
+ });
24
+ output(images, formatImageList, options);
25
+ }));
26
+ image
27
+ .command("describe <id-or-name>")
28
+ .description("Show image details")
29
+ .action(cloudAction(async (client, idOrName, options) => {
30
+ const id = await resolveIdOrName(idOrName, "image", (name) => client.listImages({ name }));
31
+ const img = await client.getImage(id);
32
+ output(img, formatImageDetails, options);
33
+ }));
34
+ image
35
+ .command("update <id-or-name>")
36
+ .description("Update image")
37
+ .option("--description <desc>", "New description")
38
+ .option("--type <type>", "New type (snapshot)")
39
+ .action(cloudAction(async (client, idOrName, options) => {
40
+ const id = await resolveIdOrName(idOrName, "image", (name) => client.listImages({ name }));
41
+ await client.updateImage(id, {
42
+ description: options.description,
43
+ type: options.type,
44
+ });
45
+ console.log(success(`Image ${id} updated.`));
46
+ }));
47
+ image
48
+ .command("delete <id-or-name>")
49
+ .description("Delete an image")
50
+ .option("-y, --yes", "Skip confirmation")
51
+ .action(cloudAction(async (client, idOrName, options) => {
52
+ const id = await resolveIdOrName(idOrName, "image", (name) => client.listImages({ name }));
53
+ const img = await client.getImage(id);
54
+ if (!(await confirmAction(`Delete image '${img.description}' (ID: ${id})?`, options))) {
55
+ return;
56
+ }
57
+ await client.deleteImage(id);
58
+ console.log(success(`Image '${img.description}' (ID: ${id}) deleted.`));
59
+ }));
60
+ image
61
+ .command("enable-protection <id-or-name>")
62
+ .description("Enable delete protection")
63
+ .action(cloudAction(async (client, idOrName) => {
64
+ const id = await resolveIdOrName(idOrName, "image", (name) => client.listImages({ name }));
65
+ await client.changeImageProtection(id, true);
66
+ console.log(success(`Protection enabled for image ${id}.`));
67
+ }));
68
+ image
69
+ .command("disable-protection <id-or-name>")
70
+ .description("Disable delete protection")
71
+ .action(cloudAction(async (client, idOrName) => {
72
+ const id = await resolveIdOrName(idOrName, "image", (name) => client.listImages({ name }));
73
+ await client.changeImageProtection(id, false);
74
+ console.log(success(`Protection disabled for image ${id}.`));
75
+ }));
76
+ image
77
+ .command("add-label <id-or-name> <label>")
78
+ .description("Add a label (key=value)")
79
+ .action(cloudAction(async (client, idOrName, label) => {
80
+ const id = await resolveIdOrName(idOrName, "image", (name) => client.listImages({ name }));
81
+ const img = await client.getImage(id);
82
+ const [key, value] = label.split("=");
83
+ await client.updateImage(id, {
84
+ labels: { ...img.labels, [key]: value || "" },
85
+ });
86
+ console.log(success(`Label '${key}' added.`));
87
+ }));
88
+ image
89
+ .command("remove-label <id-or-name> <key>")
90
+ .description("Remove a label")
91
+ .action(cloudAction(async (client, idOrName, key) => {
92
+ const id = await resolveIdOrName(idOrName, "image", (name) => client.listImages({ name }));
93
+ const img = await client.getImage(id);
94
+ const labels = Object.fromEntries(Object.entries(img.labels).filter(([k]) => k !== key));
95
+ await client.updateImage(id, { labels });
96
+ console.log(success(`Label '${key}' removed.`));
97
+ }));
98
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerCloudCommands(parent: Command): void;
@@ -0,0 +1,47 @@
1
+ import { registerCertificateCommands } from "./certificate.js";
2
+ import { registerContextCommands } from "./context.js";
3
+ import { registerDatacenterCommands } from "./datacenter.js";
4
+ import { registerCloudFirewallCommands } from "./firewall.js";
5
+ import { registerFloatingIpCommands } from "./floating-ip.js";
6
+ import { registerImageCommands } from "./image.js";
7
+ import { registerInventoryCommands } from "./inventory.js";
8
+ import { registerIsoCommands } from "./iso.js";
9
+ import { registerLoadBalancerCommands } from "./load-balancer.js";
10
+ import { registerLoadBalancerTypeCommands } from "./load-balancer-type.js";
11
+ import { registerLocationCommands } from "./location.js";
12
+ import { registerNetworkCommands } from "./network.js";
13
+ import { registerPlacementGroupCommands } from "./placement-group.js";
14
+ import { registerPricingCommands } from "./pricing.js";
15
+ import { registerPrimaryIpCommands } from "./primary-ip.js";
16
+ import { registerCloudServerCommands } from "./server.js";
17
+ import { registerServerTypeCommands } from "./server-type.js";
18
+ import { registerCloudSshKeyCommands } from "./ssh-key.js";
19
+ import { registerVolumeCommands } from "./volume.js";
20
+ export function registerCloudCommands(parent) {
21
+ const cloud = parent
22
+ .command("cloud")
23
+ .description("Hetzner Cloud API management");
24
+ cloud.option("--token <token>", "Cloud API token (overrides context)");
25
+ registerContextCommands(cloud);
26
+ // Read-only resources
27
+ registerDatacenterCommands(cloud);
28
+ registerLocationCommands(cloud);
29
+ registerServerTypeCommands(cloud);
30
+ registerLoadBalancerTypeCommands(cloud);
31
+ registerIsoCommands(cloud);
32
+ registerPricingCommands(cloud);
33
+ registerInventoryCommands(cloud);
34
+ // Core resources
35
+ registerCloudServerCommands(cloud);
36
+ registerNetworkCommands(cloud);
37
+ registerCloudFirewallCommands(cloud);
38
+ registerFloatingIpCommands(cloud);
39
+ registerPrimaryIpCommands(cloud);
40
+ registerVolumeCommands(cloud);
41
+ registerLoadBalancerCommands(cloud);
42
+ registerImageCommands(cloud);
43
+ // Ancillary resources
44
+ registerCloudSshKeyCommands(cloud);
45
+ registerCertificateCommands(cloud);
46
+ registerPlacementGroupCommands(cloud);
47
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerInventoryCommands(parent: Command): void;
@@ -0,0 +1,13 @@
1
+ import { output } from "../../shared/helpers.js";
2
+ import { formatInventoryReport } from "../formatter.js";
3
+ import { cloudAction } from "../helpers.js";
4
+ import { buildInventory } from "../inventory.js";
5
+ export function registerInventoryCommands(parent) {
6
+ parent
7
+ .command("inventory")
8
+ .description("Full fleet inventory with estimated monthly costs (list prices x live resources)")
9
+ .action(cloudAction(async (client, options) => {
10
+ const report = await buildInventory(client);
11
+ output(report, formatInventoryReport, options);
12
+ }));
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerIsoCommands(parent: Command): void;
@@ -0,0 +1,27 @@
1
+ import { output } from "../../shared/helpers.js";
2
+ import { formatIsoDetails, formatIsoList } from "../formatter.js";
3
+ import { cloudAction, resolveIdOrName, } from "../helpers.js";
4
+ export function registerIsoCommands(parent) {
5
+ const iso = parent.command("iso").description("ISO image management");
6
+ iso
7
+ .command("list")
8
+ .alias("ls")
9
+ .description("List all ISOs")
10
+ .option("-n, --name <name>", "Filter by name")
11
+ .option("-a, --architecture <arch>", "Filter by architecture")
12
+ .action(cloudAction(async (client, options) => {
13
+ const isos = await client.listIsos({
14
+ name: options.name,
15
+ architecture: options.architecture,
16
+ });
17
+ output(isos, formatIsoList, options);
18
+ }));
19
+ iso
20
+ .command("describe <id-or-name>")
21
+ .description("Show ISO details")
22
+ .action(cloudAction(async (client, idOrName, options) => {
23
+ const id = await resolveIdOrName(idOrName, "ISO", (name) => client.listIsos({ name }));
24
+ const iso = await client.getIso(id);
25
+ output(iso, formatIsoDetails, options);
26
+ }));
27
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerLoadBalancerTypeCommands(parent: Command): void;
@@ -0,0 +1,24 @@
1
+ import { output } from "../../shared/helpers.js";
2
+ import { formatLoadBalancerTypeDetails, formatLoadBalancerTypeList, } from "../formatter.js";
3
+ import { cloudAction, resolveIdOrName, } from "../helpers.js";
4
+ export function registerLoadBalancerTypeCommands(parent) {
5
+ const lbType = parent
6
+ .command("load-balancer-type")
7
+ .description("Load balancer type information");
8
+ lbType
9
+ .command("list")
10
+ .alias("ls")
11
+ .description("List all load balancer types")
12
+ .action(cloudAction(async (client, options) => {
13
+ const types = await client.listLoadBalancerTypes();
14
+ output(types, formatLoadBalancerTypeList, options);
15
+ }));
16
+ lbType
17
+ .command("describe <id-or-name>")
18
+ .description("Show load balancer type details")
19
+ .action(cloudAction(async (client, idOrName, options) => {
20
+ const id = await resolveIdOrName(idOrName, "load balancer type", (name) => client.listLoadBalancerTypes({ name }));
21
+ const type = await client.getLoadBalancerType(id);
22
+ output(type, formatLoadBalancerTypeDetails, options);
23
+ }));
24
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerLoadBalancerCommands(parent: Command): void;
@@ -0,0 +1,269 @@
1
+ import { success } from "../../shared/formatter.js";
2
+ import { confirmAction, output } from "../../shared/helpers.js";
3
+ import { formatLoadBalancerDetails, formatLoadBalancerList, } from "../formatter.js";
4
+ import { cloudAction, resolveIdOrName, } from "../helpers.js";
5
+ function resolveLbId(client, idOrName) {
6
+ return resolveIdOrName(idOrName, "load balancer", (name) => client.listLoadBalancers({ name }));
7
+ }
8
+ async function handleLbList(client, options) {
9
+ const lbs = await client.listLoadBalancers({
10
+ label_selector: options.labelSelector,
11
+ sort: options.sort,
12
+ });
13
+ output(lbs, formatLoadBalancerList, options);
14
+ }
15
+ async function handleLbDescribe(client, idOrName, options) {
16
+ const id = await resolveLbId(client, idOrName);
17
+ const loadBalancer = await client.getLoadBalancer(id);
18
+ output(loadBalancer, formatLoadBalancerDetails, options);
19
+ }
20
+ async function handleLbCreate(client, options) {
21
+ const { load_balancer: created } = await client.createLoadBalancer({
22
+ name: options.name,
23
+ load_balancer_type: options.type,
24
+ location: options.location,
25
+ network_zone: options.networkZone,
26
+ algorithm: options.algorithm ? { type: options.algorithm } : undefined,
27
+ });
28
+ console.log(success(`Load balancer '${created.name}' created (ID: ${created.id})`));
29
+ }
30
+ async function handleLbDelete(client, idOrName, options) {
31
+ const id = await resolveLbId(client, idOrName);
32
+ const loadBalancer = await client.getLoadBalancer(id);
33
+ if (!(await confirmAction(`Delete load balancer '${loadBalancer.name}' (ID: ${id})?`, options))) {
34
+ return;
35
+ }
36
+ await client.deleteLoadBalancer(id);
37
+ console.log(success(`Load balancer '${loadBalancer.name}' (ID: ${id}) deleted.`));
38
+ }
39
+ async function handleLbUpdate(client, idOrName, options) {
40
+ const id = await resolveLbId(client, idOrName);
41
+ await client.updateLoadBalancer(id, { name: options.name });
42
+ console.log(success(`Load balancer ${id} updated.`));
43
+ }
44
+ async function handleLbAddTarget(client, idOrName, options) {
45
+ const id = await resolveLbId(client, idOrName);
46
+ const target = {
47
+ type: options.type,
48
+ use_private_ip: !!options.usePrivateIp,
49
+ };
50
+ if (options.server) {
51
+ target.server = { id: Number.parseInt(options.server, 10) };
52
+ }
53
+ if (options.labelSelector) {
54
+ target.label_selector = { selector: options.labelSelector };
55
+ }
56
+ if (options.ip) {
57
+ target.ip = { ip: options.ip };
58
+ }
59
+ await client.addTargetToLoadBalancer(id, target);
60
+ console.log(success(`Target added to load balancer ${id}.`));
61
+ }
62
+ async function handleLbRemoveTarget(client, idOrName, options) {
63
+ const id = await resolveLbId(client, idOrName);
64
+ const target = { type: options.type };
65
+ if (options.server) {
66
+ target.server = { id: Number.parseInt(options.server, 10) };
67
+ }
68
+ if (options.labelSelector) {
69
+ target.label_selector = { selector: options.labelSelector };
70
+ }
71
+ if (options.ip) {
72
+ target.ip = { ip: options.ip };
73
+ }
74
+ await client.removeTargetFromLoadBalancer(id, target);
75
+ console.log(success(`Target removed from load balancer ${id}.`));
76
+ }
77
+ async function handleLbAddService(client, idOrName, options) {
78
+ const id = await resolveLbId(client, idOrName);
79
+ await client.addServiceToLoadBalancer(id, {
80
+ protocol: options.protocol,
81
+ listen_port: Number.parseInt(options.listenPort, 10),
82
+ destination_port: Number.parseInt(options.destinationPort, 10),
83
+ proxyprotocol: !!options.proxyprotocol,
84
+ health_check: {
85
+ protocol: options.protocol,
86
+ port: Number.parseInt(options.destinationPort, 10),
87
+ interval: 15,
88
+ timeout: 10,
89
+ retries: 3,
90
+ },
91
+ });
92
+ console.log(success(`Service added to load balancer ${id}.`));
93
+ }
94
+ async function handleLbUpdateService(client, idOrName, options) {
95
+ const id = await resolveLbId(client, idOrName);
96
+ const service = {
97
+ listen_port: Number.parseInt(options.listenPort, 10),
98
+ };
99
+ if (options.protocol) {
100
+ service.protocol = options.protocol;
101
+ }
102
+ if (options.destinationPort) {
103
+ service.destination_port = Number.parseInt(options.destinationPort, 10);
104
+ }
105
+ if (options.proxyprotocol !== undefined) {
106
+ service.proxyprotocol = options.proxyprotocol === "true";
107
+ }
108
+ await client.updateServiceOnLoadBalancer(id, service);
109
+ console.log(success(`Service on load balancer ${id} updated.`));
110
+ }
111
+ async function handleLbDeleteService(client, idOrName, options) {
112
+ const id = await resolveLbId(client, idOrName);
113
+ await client.deleteServiceFromLoadBalancer(id, Number.parseInt(options.listenPort, 10));
114
+ console.log(success(`Service on port ${options.listenPort} deleted from load balancer ${id}.`));
115
+ }
116
+ async function handleLbChangeAlgorithm(client, idOrName, options) {
117
+ const id = await resolveLbId(client, idOrName);
118
+ await client.changeLoadBalancerAlgorithm(id, options.algorithm);
119
+ console.log(success(`Algorithm changed for load balancer ${id}.`));
120
+ }
121
+ async function handleLbChangeType(client, idOrName, options) {
122
+ const id = await resolveLbId(client, idOrName);
123
+ await client.changeLoadBalancerType(id, options.type);
124
+ console.log(success(`Type changed for load balancer ${id}.`));
125
+ }
126
+ async function handleLbAttachToNetwork(client, idOrName, options) {
127
+ const id = await resolveLbId(client, idOrName);
128
+ await client.attachLoadBalancerToNetwork(id, Number.parseInt(options.network, 10), options.ip);
129
+ console.log(success(`Load balancer ${id} attached to network ${options.network}.`));
130
+ }
131
+ async function handleLbDetachFromNetwork(client, idOrName, options) {
132
+ const id = await resolveLbId(client, idOrName);
133
+ await client.detachLoadBalancerFromNetwork(id, Number.parseInt(options.network, 10));
134
+ console.log(success(`Load balancer ${id} detached from network ${options.network}.`));
135
+ }
136
+ async function handleLbEnablePublicInterface(client, idOrName) {
137
+ const id = await resolveLbId(client, idOrName);
138
+ await client.enableLoadBalancerPublicInterface(id);
139
+ console.log(success(`Public interface enabled for load balancer ${id}.`));
140
+ }
141
+ async function handleLbDisablePublicInterface(client, idOrName) {
142
+ const id = await resolveLbId(client, idOrName);
143
+ await client.disableLoadBalancerPublicInterface(id);
144
+ console.log(success(`Public interface disabled for load balancer ${id}.`));
145
+ }
146
+ async function handleLbEnableProtection(client, idOrName) {
147
+ const id = await resolveLbId(client, idOrName);
148
+ await client.changeLoadBalancerProtection(id, true);
149
+ console.log(success(`Protection enabled for load balancer ${id}.`));
150
+ }
151
+ async function handleLbDisableProtection(client, idOrName) {
152
+ const id = await resolveLbId(client, idOrName);
153
+ await client.changeLoadBalancerProtection(id, false);
154
+ console.log(success(`Protection disabled for load balancer ${id}.`));
155
+ }
156
+ async function handleLbAddLabel(client, idOrName, label) {
157
+ const id = await resolveLbId(client, idOrName);
158
+ const loadBalancer = await client.getLoadBalancer(id);
159
+ const [key, value] = label.split("=");
160
+ await client.updateLoadBalancer(id, {
161
+ labels: { ...loadBalancer.labels, [key]: value || "" },
162
+ });
163
+ console.log(success(`Label '${key}' added.`));
164
+ }
165
+ async function handleLbRemoveLabel(client, idOrName, key) {
166
+ const id = await resolveLbId(client, idOrName);
167
+ const loadBalancer = await client.getLoadBalancer(id);
168
+ const labels = Object.fromEntries(Object.entries(loadBalancer.labels).filter(([k]) => k !== key));
169
+ await client.updateLoadBalancer(id, { labels });
170
+ console.log(success(`Label '${key}' removed.`));
171
+ }
172
+ export function registerLoadBalancerCommands(parent) {
173
+ const lb = parent
174
+ .command("load-balancer")
175
+ .description("Load balancer management");
176
+ lb.command("list")
177
+ .alias("ls")
178
+ .description("List all load balancers")
179
+ .option("-l, --label-selector <selector>", "Label selector")
180
+ .option("-s, --sort <field>", "Sort by field")
181
+ .action(cloudAction(handleLbList));
182
+ lb.command("describe <id-or-name>")
183
+ .description("Show load balancer details")
184
+ .action(cloudAction(handleLbDescribe));
185
+ lb.command("create")
186
+ .description("Create a load balancer")
187
+ .requiredOption("--name <name>", "Load balancer name")
188
+ .requiredOption("--type <type>", "Load balancer type")
189
+ .option("--location <loc>", "Location")
190
+ .option("--network-zone <zone>", "Network zone")
191
+ .option("--algorithm <algo>", "Algorithm (round_robin, least_connections)", "round_robin")
192
+ .action(cloudAction(handleLbCreate));
193
+ lb.command("delete <id-or-name>")
194
+ .description("Delete a load balancer")
195
+ .option("-y, --yes", "Skip confirmation")
196
+ .action(cloudAction(handleLbDelete));
197
+ lb.command("update <id-or-name>")
198
+ .description("Update load balancer")
199
+ .option("--name <name>", "New name")
200
+ .action(cloudAction(handleLbUpdate));
201
+ lb.command("add-target <id-or-name>")
202
+ .description("Add target to load balancer")
203
+ .requiredOption("--type <type>", "Target type (server, label_selector, ip)")
204
+ .option("--server <server>", "Server ID")
205
+ .option("--label-selector <selector>", "Label selector")
206
+ .option("--ip <ip>", "IP address")
207
+ .option("--use-private-ip", "Use private IP")
208
+ .action(cloudAction(handleLbAddTarget));
209
+ lb.command("remove-target <id-or-name>")
210
+ .description("Remove target from load balancer")
211
+ .requiredOption("--type <type>", "Target type (server, label_selector, ip)")
212
+ .option("--server <server>", "Server ID")
213
+ .option("--label-selector <selector>", "Label selector")
214
+ .option("--ip <ip>", "IP address")
215
+ .action(cloudAction(handleLbRemoveTarget));
216
+ lb.command("add-service <id-or-name>")
217
+ .description("Add service to load balancer")
218
+ .requiredOption("--protocol <protocol>", "Protocol (tcp, http, https)")
219
+ .requiredOption("--listen-port <port>", "Listen port")
220
+ .requiredOption("--destination-port <port>", "Destination port")
221
+ .option("--proxyprotocol", "Enable proxy protocol")
222
+ .action(cloudAction(handleLbAddService));
223
+ lb.command("update-service <id-or-name>")
224
+ .description("Update a service on load balancer")
225
+ .requiredOption("--listen-port <port>", "Listen port of the service to update")
226
+ .option("--protocol <protocol>", "New protocol")
227
+ .option("--destination-port <port>", "New destination port")
228
+ .option("--proxyprotocol <bool>", "Enable/disable proxy protocol (true/false)")
229
+ .action(cloudAction(handleLbUpdateService));
230
+ lb.command("delete-service <id-or-name>")
231
+ .description("Delete a service from load balancer")
232
+ .requiredOption("--listen-port <port>", "Listen port of the service to delete")
233
+ .action(cloudAction(handleLbDeleteService));
234
+ lb.command("change-algorithm <id-or-name>")
235
+ .description("Change load balancer algorithm")
236
+ .requiredOption("--algorithm <type>", "Algorithm type (round_robin, least_connections)")
237
+ .action(cloudAction(handleLbChangeAlgorithm));
238
+ lb.command("change-type <id-or-name>")
239
+ .description("Change load balancer type")
240
+ .requiredOption("--type <type>", "New load balancer type")
241
+ .action(cloudAction(handleLbChangeType));
242
+ lb.command("attach-to-network <id-or-name>")
243
+ .description("Attach load balancer to network")
244
+ .requiredOption("--network <network>", "Network ID")
245
+ .option("--ip <ip>", "IP address in network")
246
+ .action(cloudAction(handleLbAttachToNetwork));
247
+ lb.command("detach-from-network <id-or-name>")
248
+ .description("Detach load balancer from network")
249
+ .requiredOption("--network <network>", "Network ID")
250
+ .action(cloudAction(handleLbDetachFromNetwork));
251
+ lb.command("enable-public-interface <id-or-name>")
252
+ .description("Enable public interface")
253
+ .action(cloudAction(handleLbEnablePublicInterface));
254
+ lb.command("disable-public-interface <id-or-name>")
255
+ .description("Disable public interface")
256
+ .action(cloudAction(handleLbDisablePublicInterface));
257
+ lb.command("enable-protection <id-or-name>")
258
+ .description("Enable delete protection")
259
+ .action(cloudAction(handleLbEnableProtection));
260
+ lb.command("disable-protection <id-or-name>")
261
+ .description("Disable delete protection")
262
+ .action(cloudAction(handleLbDisableProtection));
263
+ lb.command("add-label <id-or-name> <label>")
264
+ .description("Add a label (key=value)")
265
+ .action(cloudAction(handleLbAddLabel));
266
+ lb.command("remove-label <id-or-name> <key>")
267
+ .description("Remove a label")
268
+ .action(cloudAction(handleLbRemoveLabel));
269
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerLocationCommands(parent: Command): void;
@@ -0,0 +1,24 @@
1
+ import { output } from "../../shared/helpers.js";
2
+ import { formatLocationDetails, formatLocationList } from "../formatter.js";
3
+ import { cloudAction, resolveIdOrName, } from "../helpers.js";
4
+ export function registerLocationCommands(parent) {
5
+ const location = parent
6
+ .command("location")
7
+ .description("Location information");
8
+ location
9
+ .command("list")
10
+ .alias("ls")
11
+ .description("List all locations")
12
+ .action(cloudAction(async (client, options) => {
13
+ const locations = await client.listLocations();
14
+ output(locations, formatLocationList, options);
15
+ }));
16
+ location
17
+ .command("describe <id-or-name>")
18
+ .description("Show location details")
19
+ .action(cloudAction(async (client, idOrName, options) => {
20
+ const id = await resolveIdOrName(idOrName, "location", (name) => client.listLocations({ name }));
21
+ const location = await client.getLocation(id);
22
+ output(location, formatLocationDetails, options);
23
+ }));
24
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerNetworkCommands(parent: Command): void;