hetzner-cli 2.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.
- package/LICENSE +21 -0
- package/README.md +907 -0
- package/dist/auction/client.d.ts +4 -0
- package/dist/auction/client.js +103 -0
- package/dist/auction/commands.d.ts +2 -0
- package/dist/auction/commands.js +138 -0
- package/dist/auction/formatter.d.ts +3 -0
- package/dist/auction/formatter.js +87 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +39 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +4 -0
- package/dist/cloud/client.d.ts +511 -0
- package/dist/cloud/client.js +706 -0
- package/dist/cloud/commands/certificate.d.ts +2 -0
- package/dist/cloud/commands/certificate.js +77 -0
- package/dist/cloud/commands/context.d.ts +2 -0
- package/dist/cloud/commands/context.js +78 -0
- package/dist/cloud/commands/datacenter.d.ts +2 -0
- package/dist/cloud/commands/datacenter.js +20 -0
- package/dist/cloud/commands/firewall.d.ts +2 -0
- package/dist/cloud/commands/firewall.js +77 -0
- package/dist/cloud/commands/floating-ip.d.ts +2 -0
- package/dist/cloud/commands/floating-ip.js +83 -0
- package/dist/cloud/commands/image.d.ts +2 -0
- package/dist/cloud/commands/image.js +60 -0
- package/dist/cloud/commands/index.d.ts +2 -0
- package/dist/cloud/commands/index.js +41 -0
- package/dist/cloud/commands/iso.d.ts +2 -0
- package/dist/cloud/commands/iso.js +22 -0
- package/dist/cloud/commands/load-balancer-type.d.ts +2 -0
- package/dist/cloud/commands/load-balancer-type.js +20 -0
- package/dist/cloud/commands/load-balancer.d.ts +2 -0
- package/dist/cloud/commands/load-balancer.js +177 -0
- package/dist/cloud/commands/location.d.ts +2 -0
- package/dist/cloud/commands/location.js +20 -0
- package/dist/cloud/commands/network.d.ts +2 -0
- package/dist/cloud/commands/network.js +96 -0
- package/dist/cloud/commands/placement-group.d.ts +2 -0
- package/dist/cloud/commands/placement-group.js +53 -0
- package/dist/cloud/commands/primary-ip.d.ts +2 -0
- package/dist/cloud/commands/primary-ip.js +83 -0
- package/dist/cloud/commands/server-type.d.ts +2 -0
- package/dist/cloud/commands/server-type.js +20 -0
- package/dist/cloud/commands/server.d.ts +2 -0
- package/dist/cloud/commands/server.js +260 -0
- package/dist/cloud/commands/ssh-key.d.ts +2 -0
- package/dist/cloud/commands/ssh-key.js +63 -0
- package/dist/cloud/commands/volume.d.ts +2 -0
- package/dist/cloud/commands/volume.js +92 -0
- package/dist/cloud/context.d.ts +28 -0
- package/dist/cloud/context.js +172 -0
- package/dist/cloud/formatter.d.ts +37 -0
- package/dist/cloud/formatter.js +413 -0
- package/dist/cloud/helpers.d.ts +18 -0
- package/dist/cloud/helpers.js +48 -0
- package/dist/cloud/types.d.ts +398 -0
- package/dist/cloud/types.js +5 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -0
- package/dist/formatter.d.ts +3 -0
- package/dist/formatter.js +6 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +17 -0
- package/dist/robot/client.d.ts +256 -0
- package/dist/robot/client.js +656 -0
- package/dist/robot/commands/auth.d.ts +2 -0
- package/dist/robot/commands/auth.js +54 -0
- package/dist/robot/commands/boot.d.ts +2 -0
- package/dist/robot/commands/boot.js +72 -0
- package/dist/robot/commands/cancel.d.ts +2 -0
- package/dist/robot/commands/cancel.js +36 -0
- package/dist/robot/commands/failover.d.ts +2 -0
- package/dist/robot/commands/failover.js +42 -0
- package/dist/robot/commands/firewall.d.ts +2 -0
- package/dist/robot/commands/firewall.js +66 -0
- package/dist/robot/commands/index.d.ts +2 -0
- package/dist/robot/commands/index.js +36 -0
- package/dist/robot/commands/interactive.d.ts +2 -0
- package/dist/robot/commands/interactive.js +134 -0
- package/dist/robot/commands/ip.d.ts +2 -0
- package/dist/robot/commands/ip.js +52 -0
- package/dist/robot/commands/key.d.ts +2 -0
- package/dist/robot/commands/key.js +64 -0
- package/dist/robot/commands/order.d.ts +2 -0
- package/dist/robot/commands/order.js +33 -0
- package/dist/robot/commands/rdns.d.ts +2 -0
- package/dist/robot/commands/rdns.js +41 -0
- package/dist/robot/commands/reset.d.ts +2 -0
- package/dist/robot/commands/reset.js +77 -0
- package/dist/robot/commands/server.d.ts +2 -0
- package/dist/robot/commands/server.js +29 -0
- package/dist/robot/commands/storagebox.d.ts +2 -0
- package/dist/robot/commands/storagebox.js +116 -0
- package/dist/robot/commands/subnet.d.ts +2 -0
- package/dist/robot/commands/subnet.js +21 -0
- package/dist/robot/commands/traffic.d.ts +2 -0
- package/dist/robot/commands/traffic.js +20 -0
- package/dist/robot/commands/vswitch.d.ts +2 -0
- package/dist/robot/commands/vswitch.js +64 -0
- package/dist/robot/commands/wol.d.ts +2 -0
- package/dist/robot/commands/wol.js +20 -0
- package/dist/robot/formatter.d.ts +58 -0
- package/dist/robot/formatter.js +500 -0
- package/dist/robot/types.d.ts +352 -0
- package/dist/robot/types.js +5 -0
- package/dist/shared/config.d.ts +86 -0
- package/dist/shared/config.js +273 -0
- package/dist/shared/formatter.d.ts +29 -0
- package/dist/shared/formatter.js +118 -0
- package/dist/shared/helpers.d.ts +17 -0
- package/dist/shared/helpers.js +72 -0
- package/dist/shared/reference.d.ts +2 -0
- package/dist/shared/reference.js +626 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.js +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { asyncAction, output } from '../../shared/helpers.js';
|
|
2
|
+
import * as fmt from '../../shared/formatter.js';
|
|
3
|
+
import * as robotFmt from '../formatter.js';
|
|
4
|
+
export function registerRdnsCommands(parent) {
|
|
5
|
+
const rdns = parent.command('rdns').description('Reverse DNS management');
|
|
6
|
+
rdns
|
|
7
|
+
.command('list')
|
|
8
|
+
.alias('ls')
|
|
9
|
+
.description('List all reverse DNS entries')
|
|
10
|
+
.action(asyncAction(async (client, options) => {
|
|
11
|
+
const entries = await client.listRdns();
|
|
12
|
+
output(entries, robotFmt.formatRdnsList, options);
|
|
13
|
+
}));
|
|
14
|
+
rdns
|
|
15
|
+
.command('get <ip>')
|
|
16
|
+
.alias('show')
|
|
17
|
+
.description('Get reverse DNS entry for IP')
|
|
18
|
+
.action(asyncAction(async (client, ipAddr, options) => {
|
|
19
|
+
const { rdns: entry } = await client.getRdns(ipAddr);
|
|
20
|
+
output(entry, (e) => `IP: ${e.ip}\nPTR: ${e.ptr}`, options);
|
|
21
|
+
}));
|
|
22
|
+
rdns
|
|
23
|
+
.command('set <ip> <ptr>')
|
|
24
|
+
.description('Create or update reverse DNS entry')
|
|
25
|
+
.action(asyncAction(async (client, ipAddr, ptr) => {
|
|
26
|
+
try {
|
|
27
|
+
await client.createRdns(ipAddr, ptr);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
await client.updateRdns(ipAddr, ptr);
|
|
31
|
+
}
|
|
32
|
+
console.log(fmt.success(`rDNS set: ${ipAddr} -> ${ptr}`));
|
|
33
|
+
}));
|
|
34
|
+
rdns
|
|
35
|
+
.command('delete <ip>')
|
|
36
|
+
.description('Delete reverse DNS entry')
|
|
37
|
+
.action(asyncAction(async (client, ipAddr) => {
|
|
38
|
+
await client.deleteRdns(ipAddr);
|
|
39
|
+
console.log(fmt.success('rDNS entry deleted.'));
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Option } from 'commander';
|
|
2
|
+
import { select, confirm } from '@inquirer/prompts';
|
|
3
|
+
import { asyncAction, output } from '../../shared/helpers.js';
|
|
4
|
+
import * as fmt from '../../shared/formatter.js';
|
|
5
|
+
import * as robotFmt from '../formatter.js';
|
|
6
|
+
export function registerResetCommands(parent) {
|
|
7
|
+
const reset = parent.command('reset').description('Server reset operations');
|
|
8
|
+
reset
|
|
9
|
+
.command('options [server]')
|
|
10
|
+
.description('Show reset options for server(s)')
|
|
11
|
+
.action(asyncAction(async (client, serverIdOrIp, options) => {
|
|
12
|
+
if (serverIdOrIp) {
|
|
13
|
+
const { reset: rst } = await client.getResetOptions(serverIdOrIp);
|
|
14
|
+
output(rst, robotFmt.formatResetOptions, options);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
const resets = await client.listResetOptions();
|
|
18
|
+
if (options.json) {
|
|
19
|
+
console.log(fmt.formatJson(resets));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
for (const { reset: rst } of resets) {
|
|
23
|
+
console.log(robotFmt.formatResetOptions(rst));
|
|
24
|
+
console.log('');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
reset
|
|
30
|
+
.command('execute <servers...>')
|
|
31
|
+
.alias('run')
|
|
32
|
+
.description('Reset one or more servers')
|
|
33
|
+
.addOption(new Option('-t, --type <type>', 'Reset type')
|
|
34
|
+
.choices(['sw', 'hw', 'man', 'power', 'power_long'])
|
|
35
|
+
.default('sw'))
|
|
36
|
+
.option('-i, --interactive', 'Interactively select reset type')
|
|
37
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
38
|
+
.action(asyncAction(async (client, servers, options) => {
|
|
39
|
+
let resetType = options.type;
|
|
40
|
+
if (options.interactive) {
|
|
41
|
+
resetType = (await select({
|
|
42
|
+
message: 'Select reset type:',
|
|
43
|
+
choices: [
|
|
44
|
+
{ value: 'sw', name: 'Software reset (ACPI) - Recommended' },
|
|
45
|
+
{ value: 'hw', name: 'Hardware reset (forced)' },
|
|
46
|
+
{ value: 'power', name: 'Power cycle' },
|
|
47
|
+
{ value: 'power_long', name: 'Long power cycle (10+ seconds)' },
|
|
48
|
+
{ value: 'man', name: 'Manual reset (technician)' },
|
|
49
|
+
],
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
if (!options.yes) {
|
|
53
|
+
console.log('');
|
|
54
|
+
console.log(fmt.warning(`About to reset ${servers.length} server(s) with type: ${resetType}`));
|
|
55
|
+
console.log(`Servers: ${servers.join(', ')}`);
|
|
56
|
+
console.log('');
|
|
57
|
+
const confirmed = await confirm({
|
|
58
|
+
message: 'Are you sure you want to proceed?',
|
|
59
|
+
default: false,
|
|
60
|
+
});
|
|
61
|
+
if (!confirmed) {
|
|
62
|
+
console.log('Aborted.');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
console.log('');
|
|
67
|
+
for (const srv of servers) {
|
|
68
|
+
try {
|
|
69
|
+
const { reset: rst } = await client.resetServer(srv, resetType);
|
|
70
|
+
console.log(robotFmt.formatResetResult(rst, resetType));
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.log(fmt.error(`Failed to reset ${srv}: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { asyncAction, output } from '../../shared/helpers.js';
|
|
2
|
+
import * as fmt from '../../shared/formatter.js';
|
|
3
|
+
import * as robotFmt from '../formatter.js';
|
|
4
|
+
export function registerServerCommands(parent) {
|
|
5
|
+
const server = parent.command('server').alias('servers').description('Server management');
|
|
6
|
+
server
|
|
7
|
+
.command('list')
|
|
8
|
+
.alias('ls')
|
|
9
|
+
.description('List all servers')
|
|
10
|
+
.action(asyncAction(async (client, options) => {
|
|
11
|
+
const servers = await client.listServers();
|
|
12
|
+
output(servers, robotFmt.formatServerList, options);
|
|
13
|
+
}));
|
|
14
|
+
server
|
|
15
|
+
.command('get <server>')
|
|
16
|
+
.alias('show')
|
|
17
|
+
.description('Get server details')
|
|
18
|
+
.action(asyncAction(async (client, serverIdOrIp, options) => {
|
|
19
|
+
const { server: srv } = await client.getServer(serverIdOrIp);
|
|
20
|
+
output(srv, robotFmt.formatServerDetails, options);
|
|
21
|
+
}));
|
|
22
|
+
server
|
|
23
|
+
.command('rename <server> <name>')
|
|
24
|
+
.description('Rename a server')
|
|
25
|
+
.action(asyncAction(async (client, serverIdOrIp, name) => {
|
|
26
|
+
await client.updateServerName(serverIdOrIp, name);
|
|
27
|
+
console.log(fmt.success(`Server renamed to: ${name}`));
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { asyncAction, output, confirmAction } from '../../shared/helpers.js';
|
|
2
|
+
import * as fmt from '../../shared/formatter.js';
|
|
3
|
+
import * as robotFmt from '../formatter.js';
|
|
4
|
+
export function registerStorageBoxCommands(parent) {
|
|
5
|
+
const storagebox = parent.command('storagebox').alias('storage').description('Storage Box management');
|
|
6
|
+
storagebox
|
|
7
|
+
.command('list')
|
|
8
|
+
.alias('ls')
|
|
9
|
+
.description('List all storage boxes')
|
|
10
|
+
.action(asyncAction(async (client, options) => {
|
|
11
|
+
const boxes = await client.listStorageBoxes();
|
|
12
|
+
output(boxes, robotFmt.formatStorageBoxList, options);
|
|
13
|
+
}));
|
|
14
|
+
storagebox
|
|
15
|
+
.command('get <id>')
|
|
16
|
+
.alias('show')
|
|
17
|
+
.description('Get storage box details')
|
|
18
|
+
.action(asyncAction(async (client, boxId, options) => {
|
|
19
|
+
const { storagebox: box } = await client.getStorageBox(parseInt(boxId));
|
|
20
|
+
output(box, robotFmt.formatStorageBoxDetails, options);
|
|
21
|
+
}));
|
|
22
|
+
storagebox
|
|
23
|
+
.command('update <id>')
|
|
24
|
+
.description('Update storage box settings')
|
|
25
|
+
.option('-n, --name <name>', 'Storage box name')
|
|
26
|
+
.option('--webdav <enabled>', 'Enable/disable WebDAV')
|
|
27
|
+
.option('--samba <enabled>', 'Enable/disable Samba/CIFS')
|
|
28
|
+
.option('--ssh <enabled>', 'Enable/disable SSH/SFTP')
|
|
29
|
+
.option('--external <enabled>', 'Enable/disable external reachability')
|
|
30
|
+
.option('--zfs <enabled>', 'Enable/disable ZFS')
|
|
31
|
+
.action(asyncAction(async (client, boxId, options) => {
|
|
32
|
+
await client.updateStorageBox(parseInt(boxId), options.name, options.webdav ? options.webdav === 'true' : undefined, options.samba ? options.samba === 'true' : undefined, options.ssh ? options.ssh === 'true' : undefined, options.external ? options.external === 'true' : undefined, options.zfs ? options.zfs === 'true' : undefined);
|
|
33
|
+
console.log(fmt.success('Storage box updated.'));
|
|
34
|
+
}));
|
|
35
|
+
storagebox
|
|
36
|
+
.command('reset-password <id>')
|
|
37
|
+
.description('Reset storage box password')
|
|
38
|
+
.action(asyncAction(async (client, boxId) => {
|
|
39
|
+
const { password } = await client.resetStorageBoxPassword(parseInt(boxId));
|
|
40
|
+
console.log(fmt.success('Password reset.'));
|
|
41
|
+
console.log(`New password: ${fmt.colorize(password, 'yellow')}`);
|
|
42
|
+
}));
|
|
43
|
+
const snapshot = storagebox.command('snapshot').description('Storage box snapshot management');
|
|
44
|
+
snapshot
|
|
45
|
+
.command('list <box-id>')
|
|
46
|
+
.alias('ls')
|
|
47
|
+
.description('List storage box snapshots')
|
|
48
|
+
.action(asyncAction(async (client, boxId, options) => {
|
|
49
|
+
const snapshots = await client.listStorageBoxSnapshots(parseInt(boxId));
|
|
50
|
+
output(snapshots, robotFmt.formatStorageBoxSnapshots, options);
|
|
51
|
+
}));
|
|
52
|
+
snapshot
|
|
53
|
+
.command('create <box-id>')
|
|
54
|
+
.description('Create a new snapshot')
|
|
55
|
+
.action(asyncAction(async (client, boxId) => {
|
|
56
|
+
const { snapshot: snap } = await client.createStorageBoxSnapshot(parseInt(boxId));
|
|
57
|
+
console.log(fmt.success(`Snapshot created: ${snap.name}`));
|
|
58
|
+
}));
|
|
59
|
+
snapshot
|
|
60
|
+
.command('delete <box-id> <name>')
|
|
61
|
+
.alias('rm')
|
|
62
|
+
.description('Delete a snapshot')
|
|
63
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
64
|
+
.action(asyncAction(async (client, boxId, snapshotName, options) => {
|
|
65
|
+
if (!await confirmAction(`Delete snapshot ${snapshotName}?`, options))
|
|
66
|
+
return;
|
|
67
|
+
await client.deleteStorageBoxSnapshot(parseInt(boxId), snapshotName);
|
|
68
|
+
console.log(fmt.success('Snapshot deleted.'));
|
|
69
|
+
}));
|
|
70
|
+
snapshot
|
|
71
|
+
.command('revert <box-id> <name>')
|
|
72
|
+
.description('Revert to a snapshot')
|
|
73
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
74
|
+
.action(asyncAction(async (client, boxId, snapshotName, options) => {
|
|
75
|
+
if (!options.yes) {
|
|
76
|
+
console.log(fmt.warning('This will revert your storage box to the snapshot state.'));
|
|
77
|
+
}
|
|
78
|
+
if (!await confirmAction(`Revert to snapshot ${snapshotName}?`, options))
|
|
79
|
+
return;
|
|
80
|
+
await client.revertStorageBoxSnapshot(parseInt(boxId), snapshotName);
|
|
81
|
+
console.log(fmt.success('Reverted to snapshot.'));
|
|
82
|
+
}));
|
|
83
|
+
const subaccount = storagebox.command('subaccount').description('Storage box subaccount management');
|
|
84
|
+
subaccount
|
|
85
|
+
.command('list <box-id>')
|
|
86
|
+
.alias('ls')
|
|
87
|
+
.description('List storage box subaccounts')
|
|
88
|
+
.action(asyncAction(async (client, boxId, options) => {
|
|
89
|
+
const subaccounts = await client.listStorageBoxSubaccounts(parseInt(boxId));
|
|
90
|
+
output(subaccounts, robotFmt.formatStorageBoxSubaccounts, options);
|
|
91
|
+
}));
|
|
92
|
+
subaccount
|
|
93
|
+
.command('create <box-id> <home-directory>')
|
|
94
|
+
.description('Create a new subaccount')
|
|
95
|
+
.option('--samba <enabled>', 'Enable Samba')
|
|
96
|
+
.option('--ssh <enabled>', 'Enable SSH')
|
|
97
|
+
.option('--webdav <enabled>', 'Enable WebDAV')
|
|
98
|
+
.option('--external <enabled>', 'Enable external reachability')
|
|
99
|
+
.option('--readonly <enabled>', 'Read-only access')
|
|
100
|
+
.option('--comment <comment>', 'Comment')
|
|
101
|
+
.action(asyncAction(async (client, boxId, homeDir, options) => {
|
|
102
|
+
const { subaccount: sub } = await client.createStorageBoxSubaccount(parseInt(boxId), homeDir, options.samba ? options.samba === 'true' : undefined, options.ssh ? options.ssh === 'true' : undefined, options.external ? options.external === 'true' : undefined, options.webdav ? options.webdav === 'true' : undefined, options.readonly ? options.readonly === 'true' : undefined, options.comment);
|
|
103
|
+
console.log(fmt.success(`Subaccount created: ${sub.username}`));
|
|
104
|
+
}));
|
|
105
|
+
subaccount
|
|
106
|
+
.command('delete <box-id> <username>')
|
|
107
|
+
.alias('rm')
|
|
108
|
+
.description('Delete a subaccount')
|
|
109
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
110
|
+
.action(asyncAction(async (client, boxId, username, options) => {
|
|
111
|
+
if (!await confirmAction(`Delete subaccount ${username}?`, options))
|
|
112
|
+
return;
|
|
113
|
+
await client.deleteStorageBoxSubaccount(parseInt(boxId), username);
|
|
114
|
+
console.log(fmt.success('Subaccount deleted.'));
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { asyncAction, output } from '../../shared/helpers.js';
|
|
2
|
+
import * as robotFmt from '../formatter.js';
|
|
3
|
+
export function registerSubnetCommands(parent) {
|
|
4
|
+
const subnet = parent.command('subnet').alias('subnets').description('Subnet management');
|
|
5
|
+
subnet
|
|
6
|
+
.command('list')
|
|
7
|
+
.alias('ls')
|
|
8
|
+
.description('List all subnets')
|
|
9
|
+
.action(asyncAction(async (client, options) => {
|
|
10
|
+
const subnets = await client.listSubnets();
|
|
11
|
+
output(subnets, robotFmt.formatSubnetList, options);
|
|
12
|
+
}));
|
|
13
|
+
subnet
|
|
14
|
+
.command('get <subnet>')
|
|
15
|
+
.alias('show')
|
|
16
|
+
.description('Get subnet details')
|
|
17
|
+
.action(asyncAction(async (client, netIp, options) => {
|
|
18
|
+
const { subnet: subnetData } = await client.getSubnet(netIp);
|
|
19
|
+
output(subnetData, (s) => robotFmt.formatSubnetList([{ subnet: s }]), options);
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { asyncAction, output } from '../../shared/helpers.js';
|
|
2
|
+
import * as robotFmt from '../formatter.js';
|
|
3
|
+
export function registerTrafficCommands(parent) {
|
|
4
|
+
const traffic = parent.command('traffic').description('Traffic analytics');
|
|
5
|
+
traffic
|
|
6
|
+
.command('query')
|
|
7
|
+
.description('Query traffic data')
|
|
8
|
+
.option('-i, --ip <ips...>', 'IP addresses to query')
|
|
9
|
+
.option('-s, --subnet <subnets...>', 'Subnets to query')
|
|
10
|
+
.option('--from <date>', 'Start date (YYYY-MM-DD)')
|
|
11
|
+
.option('--to <date>', 'End date (YYYY-MM-DD)')
|
|
12
|
+
.option('-t, --type <type>', 'Query type (day, month, year)', 'month')
|
|
13
|
+
.action(asyncAction(async (client, options) => {
|
|
14
|
+
const now = new Date();
|
|
15
|
+
const from = options.from || new Date(now.getFullYear(), now.getMonth(), 1).toISOString().split('T')[0];
|
|
16
|
+
const to = options.to || now.toISOString().split('T')[0];
|
|
17
|
+
const { traffic: trafficData } = await client.getTraffic(options.ip || [], options.subnet || [], from, to, options.type);
|
|
18
|
+
output(trafficData, robotFmt.formatTraffic, options);
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { asyncAction, output, confirmAction } from '../../shared/helpers.js';
|
|
2
|
+
import * as fmt from '../../shared/formatter.js';
|
|
3
|
+
import * as robotFmt from '../formatter.js';
|
|
4
|
+
export function registerVSwitchCommands(parent) {
|
|
5
|
+
const vswitch = parent.command('vswitch').description('vSwitch management');
|
|
6
|
+
vswitch
|
|
7
|
+
.command('list')
|
|
8
|
+
.alias('ls')
|
|
9
|
+
.description('List all vSwitches')
|
|
10
|
+
.action(asyncAction(async (client, options) => {
|
|
11
|
+
const vswitches = await client.listVSwitches();
|
|
12
|
+
output(vswitches, robotFmt.formatVSwitchList, options);
|
|
13
|
+
}));
|
|
14
|
+
vswitch
|
|
15
|
+
.command('get <id>')
|
|
16
|
+
.alias('show')
|
|
17
|
+
.description('Get vSwitch details')
|
|
18
|
+
.action(asyncAction(async (client, vswitchId, options) => {
|
|
19
|
+
const { vswitch: vs } = await client.getVSwitch(parseInt(vswitchId));
|
|
20
|
+
output(vs, robotFmt.formatVSwitchDetails, options);
|
|
21
|
+
}));
|
|
22
|
+
vswitch
|
|
23
|
+
.command('create <name> <vlan>')
|
|
24
|
+
.description('Create a new vSwitch')
|
|
25
|
+
.action(asyncAction(async (client, name, vlan) => {
|
|
26
|
+
const { vswitch: vs } = await client.createVSwitch(name, parseInt(vlan));
|
|
27
|
+
console.log(fmt.success(`vSwitch created: ID ${vs.id}`));
|
|
28
|
+
}));
|
|
29
|
+
vswitch
|
|
30
|
+
.command('update <id>')
|
|
31
|
+
.description('Update vSwitch')
|
|
32
|
+
.option('-n, --name <name>', 'New name')
|
|
33
|
+
.option('-v, --vlan <vlan>', 'New VLAN ID')
|
|
34
|
+
.action(asyncAction(async (client, vswitchId, options) => {
|
|
35
|
+
await client.updateVSwitch(parseInt(vswitchId), options.name, options.vlan ? parseInt(options.vlan) : undefined);
|
|
36
|
+
console.log(fmt.success('vSwitch updated.'));
|
|
37
|
+
}));
|
|
38
|
+
vswitch
|
|
39
|
+
.command('delete <id>')
|
|
40
|
+
.alias('rm')
|
|
41
|
+
.description('Delete vSwitch')
|
|
42
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
43
|
+
.option('--date <date>', 'Cancellation date (YYYY-MM-DD)')
|
|
44
|
+
.action(asyncAction(async (client, vswitchId, options) => {
|
|
45
|
+
if (!await confirmAction(`Delete vSwitch ${vswitchId}?`, options))
|
|
46
|
+
return;
|
|
47
|
+
await client.deleteVSwitch(parseInt(vswitchId), options.date);
|
|
48
|
+
console.log(fmt.success('vSwitch deleted.'));
|
|
49
|
+
}));
|
|
50
|
+
vswitch
|
|
51
|
+
.command('add-server <vswitch-id> <server>')
|
|
52
|
+
.description('Add server to vSwitch')
|
|
53
|
+
.action(asyncAction(async (client, vswitchId, serverIdOrIp) => {
|
|
54
|
+
await client.addServerToVSwitch(parseInt(vswitchId), serverIdOrIp);
|
|
55
|
+
console.log(fmt.success('Server added to vSwitch.'));
|
|
56
|
+
}));
|
|
57
|
+
vswitch
|
|
58
|
+
.command('remove-server <vswitch-id> <server>')
|
|
59
|
+
.description('Remove server from vSwitch')
|
|
60
|
+
.action(asyncAction(async (client, vswitchId, serverIdOrIp) => {
|
|
61
|
+
await client.removeServerFromVSwitch(parseInt(vswitchId), serverIdOrIp);
|
|
62
|
+
console.log(fmt.success('Server removed from vSwitch.'));
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { asyncAction, output } from '../../shared/helpers.js';
|
|
2
|
+
import * as fmt from '../../shared/formatter.js';
|
|
3
|
+
import * as robotFmt from '../formatter.js';
|
|
4
|
+
export function registerWolCommands(parent) {
|
|
5
|
+
const wol = parent.command('wol').description('Wake on LAN');
|
|
6
|
+
wol
|
|
7
|
+
.command('status <server>')
|
|
8
|
+
.description('Check WoL status for server')
|
|
9
|
+
.action(asyncAction(async (client, serverIdOrIp, options) => {
|
|
10
|
+
const { wol: wolData } = await client.getWol(serverIdOrIp);
|
|
11
|
+
output(wolData, (w) => `Server: ${w.server_number} (${w.server_ip})\n${fmt.info('Wake on LAN is available for this server.')}`, options);
|
|
12
|
+
}));
|
|
13
|
+
wol
|
|
14
|
+
.command('send <server>')
|
|
15
|
+
.description('Send Wake on LAN packet')
|
|
16
|
+
.action(asyncAction(async (client, serverIdOrIp) => {
|
|
17
|
+
const { wol: wolData } = await client.sendWol(serverIdOrIp);
|
|
18
|
+
console.log(robotFmt.formatWolResult(wolData));
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Server, ServerDetails, Reset, IP, Subnet, Failover, Rdns, SshKey, Firewall, FirewallTemplate, VSwitch, StorageBox, StorageBoxSnapshot, StorageBoxSubaccount, Traffic, Wol, ServerProduct, ServerMarketProduct, ServerTransaction, RescueConfig, LinuxConfig, BootConfig, Cancellation } from './types.js';
|
|
2
|
+
export declare function formatServerList(servers: {
|
|
3
|
+
server: Server;
|
|
4
|
+
}[]): string;
|
|
5
|
+
export declare function formatServerDetails(server: ServerDetails): string;
|
|
6
|
+
export declare function formatResetOptions(reset: Reset): string;
|
|
7
|
+
export declare function formatResetResult(reset: Reset, type: string): string;
|
|
8
|
+
export declare function formatBootConfig(config: BootConfig, serverNumber: number): string;
|
|
9
|
+
export declare function formatRescueActivation(rescue: RescueConfig): string;
|
|
10
|
+
export declare function formatLinuxActivation(linux: LinuxConfig): string;
|
|
11
|
+
export declare function formatIpList(ips: {
|
|
12
|
+
ip: IP;
|
|
13
|
+
}[]): string;
|
|
14
|
+
export declare function formatIpDetails(ip: IP): string;
|
|
15
|
+
export declare function formatSubnetList(subnets: {
|
|
16
|
+
subnet: Subnet;
|
|
17
|
+
}[]): string;
|
|
18
|
+
export declare function formatFailoverList(failovers: {
|
|
19
|
+
failover: Failover;
|
|
20
|
+
}[]): string;
|
|
21
|
+
export declare function formatFailoverSwitch(failover: Failover): string;
|
|
22
|
+
export declare function formatRdnsList(entries: {
|
|
23
|
+
rdns: Rdns;
|
|
24
|
+
}[]): string;
|
|
25
|
+
export declare function formatSshKeyList(keys: {
|
|
26
|
+
key: SshKey;
|
|
27
|
+
}[]): string;
|
|
28
|
+
export declare function formatSshKeyDetails(key: SshKey): string;
|
|
29
|
+
export declare function formatFirewall(firewall: Firewall): string;
|
|
30
|
+
export declare function formatFirewallTemplateList(templates: {
|
|
31
|
+
firewall_template: FirewallTemplate;
|
|
32
|
+
}[]): string;
|
|
33
|
+
export declare function formatVSwitchList(vswitches: {
|
|
34
|
+
vswitch: VSwitch;
|
|
35
|
+
}[]): string;
|
|
36
|
+
export declare function formatVSwitchDetails(vswitch: VSwitch): string;
|
|
37
|
+
export declare function formatStorageBoxList(boxes: {
|
|
38
|
+
storagebox: StorageBox;
|
|
39
|
+
}[]): string;
|
|
40
|
+
export declare function formatStorageBoxDetails(box: StorageBox): string;
|
|
41
|
+
export declare function formatStorageBoxSnapshots(snapshots: {
|
|
42
|
+
snapshot: StorageBoxSnapshot;
|
|
43
|
+
}[]): string;
|
|
44
|
+
export declare function formatStorageBoxSubaccounts(subaccounts: {
|
|
45
|
+
subaccount: StorageBoxSubaccount;
|
|
46
|
+
}[]): string;
|
|
47
|
+
export declare function formatTraffic(traffic: Traffic): string;
|
|
48
|
+
export declare function formatWolResult(wol: Wol): string;
|
|
49
|
+
export declare function formatServerProductList(products: {
|
|
50
|
+
product: ServerProduct;
|
|
51
|
+
}[]): string;
|
|
52
|
+
export declare function formatServerMarketProductList(products: {
|
|
53
|
+
product: ServerMarketProduct;
|
|
54
|
+
}[]): string;
|
|
55
|
+
export declare function formatTransactionList(transactions: {
|
|
56
|
+
transaction: ServerTransaction;
|
|
57
|
+
}[]): string;
|
|
58
|
+
export declare function formatCancellation(cancellation: Cancellation): string;
|