rackmind-cli 0.1.2 → 0.1.4
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/README.md +63 -4
- package/dist/ai/system-prompt.js +2 -2
- package/dist/ai/system-prompt.js.map +1 -1
- package/dist/ai/tool-executor.d.ts.map +1 -1
- package/dist/ai/tool-executor.js +166 -41
- package/dist/ai/tool-executor.js.map +1 -1
- package/dist/ai/tools.js +4 -4
- package/dist/ai/tools.js.map +1 -1
- package/dist/commands/auth.d.ts +4 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +189 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +126 -2
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/containers.d.ts +7 -2
- package/dist/commands/containers.d.ts.map +1 -1
- package/dist/commands/containers.js +30 -11
- package/dist/commands/containers.js.map +1 -1
- package/dist/commands/exec.d.ts +5 -1
- package/dist/commands/exec.d.ts.map +1 -1
- package/dist/commands/exec.js +20 -3
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/lifecycle.d.ts +6 -1
- package/dist/commands/lifecycle.d.ts.map +1 -1
- package/dist/commands/lifecycle.js +118 -25
- package/dist/commands/lifecycle.js.map +1 -1
- package/dist/commands/report.js +3 -3
- package/dist/commands/report.js.map +1 -1
- package/dist/commands/vms.d.ts +7 -2
- package/dist/commands/vms.d.ts.map +1 -1
- package/dist/commands/vms.js +30 -11
- package/dist/commands/vms.js.map +1 -1
- package/dist/config/index.d.ts +8 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +40 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/types.d.ts +12 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -1
- package/dist/index.js +85 -10
- package/dist/index.js.map +1 -1
- package/dist/server/client.d.ts +19 -2
- package/dist/server/client.d.ts.map +1 -1
- package/dist/server/client.js +27 -1
- package/dist/server/client.js.map +1 -1
- package/dist/server/proxmox.d.ts +54 -1
- package/dist/server/proxmox.d.ts.map +1 -1
- package/dist/server/proxmox.js +159 -35
- package/dist/server/proxmox.js.map +1 -1
- package/dist/utils/command-safety.d.ts +11 -0
- package/dist/utils/command-safety.d.ts.map +1 -0
- package/dist/utils/command-safety.js +33 -0
- package/dist/utils/command-safety.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// rackmind login / logout / account
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Handles authentication with the RackMind account system.
|
|
5
|
+
// `login` registers the device with the cloud API and stores the user ID.
|
|
6
|
+
// `logout` clears stored credentials.
|
|
7
|
+
// `account` shows current plan and usage info.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import crypto from 'node:crypto';
|
|
11
|
+
import { setAuthToken, clearAuth, getAuthInfo } from '../config/index.js';
|
|
12
|
+
import { formatError, formatSuccess, formatKeyValue } from '../utils/format.js';
|
|
13
|
+
import { logger } from '../utils/logger.js';
|
|
14
|
+
import { isJsonMode } from '../globals.js';
|
|
15
|
+
/** Base URL for the RackMind cloud API. */
|
|
16
|
+
const CLOUD_API_URL = 'https://rackmind.ai';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// login
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
export async function loginCommand() {
|
|
21
|
+
const json = isJsonMode();
|
|
22
|
+
const { isLoggedIn, email } = getAuthInfo();
|
|
23
|
+
if (isLoggedIn) {
|
|
24
|
+
if (json) {
|
|
25
|
+
process.stdout.write(JSON.stringify({ status: 'already_logged_in', email }) + '\n');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
process.stderr.write(chalk.yellow(`Already logged in as ${chalk.bold(email)}.\n`));
|
|
29
|
+
process.stderr.write(chalk.dim('Run `rackmind logout` first if you want to switch accounts.\n'));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Generate a stable device ID for this CLI installation
|
|
33
|
+
const deviceId = crypto.randomUUID();
|
|
34
|
+
if (!json) {
|
|
35
|
+
process.stderr.write('\n');
|
|
36
|
+
process.stderr.write(chalk.bold('Registering device with RackMind...\n\n'));
|
|
37
|
+
}
|
|
38
|
+
// Register device with the cloud API (auto-grants 30-day Pro trial)
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(`${CLOUD_API_URL}/api/auth/register`, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: { 'Content-Type': 'application/json' },
|
|
43
|
+
body: JSON.stringify({ deviceId }),
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
const body = (await res.json().catch(() => null));
|
|
47
|
+
const msg = body?.error ?? `HTTP ${res.status}`;
|
|
48
|
+
process.stderr.write(formatError(`Registration failed: ${msg}`) + '\n');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const data = (await res.json());
|
|
52
|
+
// Store the device ID as the auth token and the cloud user ID
|
|
53
|
+
setAuthToken(deviceId, data.user.id, data.user.email ?? `${deviceId}@device.rackmind.ai`);
|
|
54
|
+
if (json) {
|
|
55
|
+
process.stdout.write(JSON.stringify({
|
|
56
|
+
status: 'logged_in',
|
|
57
|
+
userId: data.user.id,
|
|
58
|
+
deviceId,
|
|
59
|
+
tier: data.user.subscription_tier,
|
|
60
|
+
}) + '\n');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
process.stderr.write(formatSuccess(`Registered successfully. User ID: ${chalk.bold(data.user.id)}\n`));
|
|
64
|
+
if (data.user.subscription_status === 'trialing') {
|
|
65
|
+
process.stderr.write(chalk.green(' You have a 30-day Pro trial. Enjoy full access!\n'));
|
|
66
|
+
}
|
|
67
|
+
process.stderr.write('\n');
|
|
68
|
+
process.stderr.write(chalk.dim(`Manage your account at ${CLOUD_API_URL}/account\n`));
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
logger.debug('Registration failed', { error: err });
|
|
72
|
+
if (json) {
|
|
73
|
+
process.stdout.write(JSON.stringify({ error: 'Could not reach RackMind cloud API' }) + '\n');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
process.stderr.write(formatError('Could not reach RackMind cloud API. Check your internet connection.') +
|
|
77
|
+
'\n');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// logout
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
export function logoutCommand() {
|
|
84
|
+
const json = isJsonMode();
|
|
85
|
+
const { isLoggedIn } = getAuthInfo();
|
|
86
|
+
if (!isLoggedIn) {
|
|
87
|
+
if (json) {
|
|
88
|
+
process.stdout.write(JSON.stringify({ status: 'not_logged_in' }) + '\n');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
process.stderr.write(chalk.dim('Not currently logged in.\n'));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
clearAuth();
|
|
95
|
+
if (json) {
|
|
96
|
+
process.stdout.write(JSON.stringify({ status: 'logged_out' }) + '\n');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
process.stderr.write(formatSuccess('Logged out successfully.\n'));
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// account
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
export async function accountCommand() {
|
|
105
|
+
const json = isJsonMode();
|
|
106
|
+
const { isLoggedIn, userId, email } = getAuthInfo();
|
|
107
|
+
if (!isLoggedIn) {
|
|
108
|
+
if (json) {
|
|
109
|
+
process.stdout.write(JSON.stringify({
|
|
110
|
+
error: 'Not logged in',
|
|
111
|
+
hint: 'Run: rackmind login',
|
|
112
|
+
}) + '\n');
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
process.stderr.write(chalk.yellow('Not logged in.\n'));
|
|
116
|
+
process.stderr.write(chalk.dim('Run `rackmind login` to authenticate.\n'));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (!json) {
|
|
120
|
+
process.stderr.write('\n');
|
|
121
|
+
process.stderr.write(chalk.bold('RackMind Account\n\n'));
|
|
122
|
+
process.stderr.write(formatKeyValue('Email', email) + '\n');
|
|
123
|
+
process.stderr.write(formatKeyValue('User ID', userId) + '\n\n');
|
|
124
|
+
}
|
|
125
|
+
// Fetch billing status from the cloud API
|
|
126
|
+
try {
|
|
127
|
+
const res = await fetch(`${CLOUD_API_URL}/api/billing/status?userId=${encodeURIComponent(userId)}`);
|
|
128
|
+
if (res.ok) {
|
|
129
|
+
const data = (await res.json());
|
|
130
|
+
if (json) {
|
|
131
|
+
process.stdout.write(JSON.stringify({ email, userId, billing: data }, null, 2) + '\n');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const tierLabel = data.tier === 'pro' ? chalk.green('Pro') : chalk.dim('Free');
|
|
135
|
+
const statusLabel = data.status === 'trialing'
|
|
136
|
+
? chalk.yellow('Trial')
|
|
137
|
+
: data.status === 'active'
|
|
138
|
+
? chalk.green('Active')
|
|
139
|
+
: chalk.red(data.status);
|
|
140
|
+
process.stderr.write(formatKeyValue('Plan', tierLabel) + '\n');
|
|
141
|
+
process.stderr.write(formatKeyValue('Status', statusLabel) + '\n');
|
|
142
|
+
if (data.billing_cycle) {
|
|
143
|
+
process.stderr.write(formatKeyValue('Billing', data.billing_cycle) + '\n');
|
|
144
|
+
}
|
|
145
|
+
if (data.trial_ends_at) {
|
|
146
|
+
const trialEnd = new Date(data.trial_ends_at);
|
|
147
|
+
const daysLeft = Math.max(0, Math.ceil((trialEnd.getTime() - Date.now()) / (1000 * 60 * 60 * 24)));
|
|
148
|
+
process.stderr.write(formatKeyValue('Trial ends', `${trialEnd.toLocaleDateString()} (${daysLeft} days left)`) + '\n');
|
|
149
|
+
}
|
|
150
|
+
if (data.current_period_end) {
|
|
151
|
+
process.stderr.write(formatKeyValue('Renews', new Date(data.current_period_end).toLocaleDateString()) + '\n');
|
|
152
|
+
}
|
|
153
|
+
const usageBar = `${data.managed_interactions_used}/${data.managed_interactions_limit}`;
|
|
154
|
+
const usagePct = data.managed_interactions_limit > 0
|
|
155
|
+
? Math.round((data.managed_interactions_used / data.managed_interactions_limit) * 100)
|
|
156
|
+
: 0;
|
|
157
|
+
const usageColor = usagePct >= 90 ? chalk.red : usagePct >= 70 ? chalk.yellow : chalk.green;
|
|
158
|
+
process.stderr.write(formatKeyValue('AI Usage', usageColor(`${usageBar} (${usagePct}%)`)) + '\n');
|
|
159
|
+
process.stderr.write('\n');
|
|
160
|
+
process.stderr.write(chalk.dim(`Manage your subscription at ${CLOUD_API_URL}/account\n`));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// User not found in billing DB -- show basic info
|
|
164
|
+
if (res.status === 404) {
|
|
165
|
+
if (json) {
|
|
166
|
+
process.stdout.write(JSON.stringify({ email, userId, billing: { tier: 'free', status: 'active' } }, null, 2) + '\n');
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
process.stderr.write(formatKeyValue('Plan', chalk.dim('Free')) + '\n');
|
|
170
|
+
process.stderr.write(chalk.dim(`\nUpgrade at ${CLOUD_API_URL}/pricing\n`));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Cloud API unreachable
|
|
176
|
+
if (json) {
|
|
177
|
+
process.stdout.write(JSON.stringify({
|
|
178
|
+
email,
|
|
179
|
+
userId,
|
|
180
|
+
billing: null,
|
|
181
|
+
error: 'Could not reach RackMind cloud API',
|
|
182
|
+
}, null, 2) + '\n');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
process.stderr.write(chalk.yellow('Could not reach the RackMind cloud API for billing info.\n'));
|
|
186
|
+
process.stderr.write(chalk.dim(`Manage your subscription at ${CLOUD_API_URL}/account\n`));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AA8DA;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BjE"}
|
package/dist/commands/connect.js
CHANGED
|
@@ -3,12 +3,43 @@
|
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
// If the alias already exists, switches to it. Otherwise, runs the
|
|
5
5
|
// interactive setup wizard to create a new server profile.
|
|
6
|
+
// Validates credentials by testing the API connection before saving.
|
|
6
7
|
// ---------------------------------------------------------------------------
|
|
7
8
|
import chalk from 'chalk';
|
|
9
|
+
import ora from 'ora';
|
|
8
10
|
import { getServerProfile, saveServerProfile, setActiveServer, encryptCredential, getDefaultServerProfile, } from '../config/index.js';
|
|
9
11
|
import { promptText, promptNumber, promptSecret, promptSelect, promptConfirm, } from '../utils/prompt.js';
|
|
10
12
|
import { formatError, formatSuccess, formatKeyValue } from '../utils/format.js';
|
|
11
13
|
import { logger } from '../utils/logger.js';
|
|
14
|
+
import { ProxmoxClient, ProxmoxApiError } from '../server/proxmox.js';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// API token format patterns
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Validates that an API token ID follows the Proxmox format: user@realm!tokenid
|
|
20
|
+
* Examples: root@pam!rackmind, admin@pve!monitoring, apiuser@pam!backup
|
|
21
|
+
*/
|
|
22
|
+
function validateTokenId(tokenId) {
|
|
23
|
+
if (!tokenId) {
|
|
24
|
+
return { valid: false, error: 'API token ID is required' };
|
|
25
|
+
}
|
|
26
|
+
// Pattern: user@realm!tokenname
|
|
27
|
+
const tokenPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+![a-zA-Z0-9._-]+$/;
|
|
28
|
+
if (!tokenPattern.test(tokenId)) {
|
|
29
|
+
return {
|
|
30
|
+
valid: false,
|
|
31
|
+
error: `Invalid token format: "${tokenId}"\n` +
|
|
32
|
+
' Expected format: user@realm!tokenid\n' +
|
|
33
|
+
' Examples:\n' +
|
|
34
|
+
' root@pam!rackmind\n' +
|
|
35
|
+
' admin@pve!monitoring\n' +
|
|
36
|
+
' apiuser@pam!backup\n' +
|
|
37
|
+
'\n' +
|
|
38
|
+
' Create a token in Proxmox: Datacenter > Permissions > API Tokens > Add',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return { valid: true };
|
|
42
|
+
}
|
|
12
43
|
/**
|
|
13
44
|
* Main connect command handler.
|
|
14
45
|
* If the alias exists in config, switches to it.
|
|
@@ -61,8 +92,28 @@ async function runSetupWizard(alias) {
|
|
|
61
92
|
// -- Proxmox-specific fields ---------------------------------------------
|
|
62
93
|
if (platform === 'proxmox') {
|
|
63
94
|
profile.port = await promptNumber('Proxmox API port', 8006);
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
// API token ID with format validation
|
|
96
|
+
let tokenId;
|
|
97
|
+
while (true) {
|
|
98
|
+
tokenId = await promptText('API token ID (format: user@realm!tokenid, e.g., root@pam!rackmind)', '');
|
|
99
|
+
if (!tokenId) {
|
|
100
|
+
process.stderr.write(chalk.yellow('Warning: No API token ID provided. API commands will not work.\n'));
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
const validation = validateTokenId(tokenId);
|
|
104
|
+
if (validation.valid) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
process.stderr.write(chalk.red(validation.error ?? 'Invalid token format') + '\n\n');
|
|
108
|
+
}
|
|
109
|
+
profile.apiTokenId = tokenId;
|
|
110
|
+
// Extract user from token ID (user@realm from user@realm!tokenid)
|
|
111
|
+
if (tokenId.includes('!')) {
|
|
112
|
+
profile.apiUser = tokenId.split('!')[0] ?? '';
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
profile.apiUser = await promptText('API user (e.g., root@pam)', 'root@pam');
|
|
116
|
+
}
|
|
66
117
|
const tokenSecret = await promptSecret('API token secret');
|
|
67
118
|
if (tokenSecret) {
|
|
68
119
|
profile.encryptedTokenSecret = encryptCredential(tokenSecret);
|
|
@@ -70,6 +121,10 @@ async function runSetupWizard(alias) {
|
|
|
70
121
|
profile.node =
|
|
71
122
|
(await promptText('Node name (leave empty for auto-detect)', '')) || undefined;
|
|
72
123
|
profile.allowSelfSigned = await promptConfirm('Allow self-signed TLS certificates?', true);
|
|
124
|
+
// -- Connection validation -----------------------------------------------
|
|
125
|
+
if (tokenId && tokenSecret) {
|
|
126
|
+
await validateConnection(profile, tokenSecret);
|
|
127
|
+
}
|
|
73
128
|
}
|
|
74
129
|
// -- SSH connection ------------------------------------------------------
|
|
75
130
|
const configureSSH = platform !== 'proxmox' ? true : await promptConfirm('Configure SSH access?', true);
|
|
@@ -94,6 +149,67 @@ async function runSetupWizard(alias) {
|
|
|
94
149
|
}
|
|
95
150
|
return profile;
|
|
96
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Test the API connection before saving the profile.
|
|
154
|
+
* Shows clear pass/fail and actionable guidance on failure.
|
|
155
|
+
*/
|
|
156
|
+
async function validateConnection(profile, tokenSecret) {
|
|
157
|
+
process.stderr.write('\n');
|
|
158
|
+
const spinner = ora('Testing Proxmox API connection...').start();
|
|
159
|
+
const client = new ProxmoxClient({
|
|
160
|
+
host: profile.host,
|
|
161
|
+
port: profile.port,
|
|
162
|
+
apiTokenId: profile.apiTokenId,
|
|
163
|
+
apiTokenSecret: tokenSecret,
|
|
164
|
+
allowSelfSigned: profile.allowSelfSigned,
|
|
165
|
+
});
|
|
166
|
+
try {
|
|
167
|
+
const version = await client.testConnection();
|
|
168
|
+
spinner.succeed(chalk.green(`Connected to Proxmox VE ${version.version} (release ${version.release})`));
|
|
169
|
+
// If node was specified, validate it exists
|
|
170
|
+
if (profile.node) {
|
|
171
|
+
try {
|
|
172
|
+
const nodes = await client.listNodes();
|
|
173
|
+
const nodeExists = nodes.some((n) => n.node === profile.node);
|
|
174
|
+
if (!nodeExists) {
|
|
175
|
+
const available = nodes.map((n) => n.node).join(', ');
|
|
176
|
+
process.stderr.write(chalk.yellow(` Warning: Node "${profile.node}" not found. Available: ${available}\n`));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// Non-critical — node list might require additional permissions
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Try to detect node name for auto-detect confirmation
|
|
184
|
+
if (!profile.node) {
|
|
185
|
+
try {
|
|
186
|
+
const nodeName = await client.detectNodeName();
|
|
187
|
+
process.stderr.write(chalk.dim(` Auto-detected node: ${nodeName}\n`));
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Non-critical
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
spinner.fail(chalk.red('Connection test failed'));
|
|
196
|
+
if (err instanceof ProxmoxApiError) {
|
|
197
|
+
process.stderr.write('\n' + chalk.red(` ${err.message}\n`));
|
|
198
|
+
if (err.suggestion) {
|
|
199
|
+
process.stderr.write(chalk.yellow(` ${err.suggestion}\n`));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
204
|
+
process.stderr.write('\n' + chalk.red(` ${message}\n`));
|
|
205
|
+
}
|
|
206
|
+
process.stderr.write('\n');
|
|
207
|
+
const saveAnyway = await promptConfirm('Save profile anyway? (You can fix credentials later)', true);
|
|
208
|
+
if (!saveAnyway) {
|
|
209
|
+
throw new Error('Connection validation failed — profile not saved', { cause: err });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
97
213
|
/**
|
|
98
214
|
* Print a summary of the saved profile (masking sensitive values).
|
|
99
215
|
*/
|
|
@@ -113,5 +229,13 @@ function printProfileSummary(profile) {
|
|
|
113
229
|
process.stderr.write(formatKeyValue(' SSH Auth', profile.sshAuthType) + '\n');
|
|
114
230
|
}
|
|
115
231
|
process.stderr.write(chalk.dim('----------------------\n'));
|
|
232
|
+
// Least-privilege documentation hint
|
|
233
|
+
if (profile.platform === 'proxmox' && profile.apiUser === 'root@pam') {
|
|
234
|
+
process.stderr.write('\n');
|
|
235
|
+
process.stderr.write(chalk.yellow(' Tip: For production use, create a least-privilege API token instead of root@pam.\n'));
|
|
236
|
+
process.stderr.write(chalk.dim(' Minimum permissions for read-only monitoring: PVEAuditor role on /\n' +
|
|
237
|
+
' For lifecycle management (start/stop): PVEAdmin role on /vms\n' +
|
|
238
|
+
' Create in: Datacenter > Permissions > API Tokens\n'));
|
|
239
|
+
}
|
|
116
240
|
}
|
|
117
241
|
//# sourceMappingURL=connect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8DAA8D;AAC9D,8EAA8E;AAC9E,mEAAmE;AACnE,2DAA2D;AAC3D,8EAA8E;AAE9E,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,uBAAuB,GAE1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACH,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,aAAa,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
export interface ContainersCommandOptions {
|
|
2
|
+
json: boolean;
|
|
3
|
+
node?: string;
|
|
4
|
+
}
|
|
1
5
|
/**
|
|
2
|
-
* List all LXC containers
|
|
6
|
+
* List all LXC containers across all cluster nodes.
|
|
7
|
+
* Optionally filter by --node.
|
|
3
8
|
*/
|
|
4
|
-
export declare function containersCommand(
|
|
9
|
+
export declare function containersCommand(options: ContainersCommandOptions): Promise<void>;
|
|
5
10
|
//# sourceMappingURL=containers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containers.d.ts","sourceRoot":"","sources":["../../src/commands/containers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"containers.d.ts","sourceRoot":"","sources":["../../src/commands/containers.ts"],"names":[],"mappings":"AA0DA,MAAM,WAAW,wBAAwB;IACrC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgFxF"}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// rackmind containers (alias: ct) — list all LXC containers
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
// Fetches containers from Proxmox API and displays them in a formatted table.
|
|
5
|
-
//
|
|
5
|
+
// Uses /cluster/resources to aggregate containers across ALL cluster nodes.
|
|
6
|
+
// Supports --json for machine-readable output and --node to filter by node.
|
|
6
7
|
// ---------------------------------------------------------------------------
|
|
7
8
|
import chalk from 'chalk';
|
|
8
9
|
import { ServerClient } from '../server/client.js';
|
|
@@ -13,6 +14,7 @@ function toContainerRow(ct) {
|
|
|
13
14
|
return {
|
|
14
15
|
vmid: ct.vmid,
|
|
15
16
|
name: ct.name,
|
|
17
|
+
node: ct.node,
|
|
16
18
|
status: ct.status,
|
|
17
19
|
cpus: ct.cpus,
|
|
18
20
|
memUsed: ct.mem,
|
|
@@ -27,9 +29,10 @@ function toContainerRow(ct) {
|
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
|
-
* List all LXC containers
|
|
32
|
+
* List all LXC containers across all cluster nodes.
|
|
33
|
+
* Optionally filter by --node.
|
|
31
34
|
*/
|
|
32
|
-
export async function containersCommand(
|
|
35
|
+
export async function containersCommand(options) {
|
|
33
36
|
let client = null;
|
|
34
37
|
try {
|
|
35
38
|
client = ServerClient.fromActiveProfile();
|
|
@@ -40,33 +43,49 @@ export async function containersCommand(json) {
|
|
|
40
43
|
process.exit(1);
|
|
41
44
|
}
|
|
42
45
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
// Use cluster-wide listing for multi-node support
|
|
47
|
+
let containers = await client.listAllContainers();
|
|
48
|
+
// Filter by node if specified
|
|
49
|
+
if (options.node) {
|
|
50
|
+
containers = containers.filter((ct) => ct.node === options.node);
|
|
51
|
+
}
|
|
45
52
|
// Sort by VMID
|
|
46
53
|
containers.sort((a, b) => a.vmid - b.vmid);
|
|
47
|
-
if (json) {
|
|
54
|
+
if (options.json) {
|
|
48
55
|
const rows = containers.map(toContainerRow);
|
|
49
56
|
process.stdout.write(JSON.stringify(rows, null, 2) + '\n');
|
|
50
57
|
return;
|
|
51
58
|
}
|
|
52
59
|
if (containers.length === 0) {
|
|
53
|
-
|
|
60
|
+
const nodeLabel = options.node ? ` on node "${options.node}"` : '';
|
|
61
|
+
process.stderr.write(chalk.dim(`No LXC containers found${nodeLabel}.\n`));
|
|
54
62
|
return;
|
|
55
63
|
}
|
|
56
|
-
|
|
57
|
-
const
|
|
64
|
+
// Detect if multi-node (show node column only when there are multiple nodes)
|
|
65
|
+
const nodeNames = new Set(containers.map((ct) => ct.node));
|
|
66
|
+
const isMultiNode = nodeNames.size > 1;
|
|
67
|
+
const headerLabel = options.node
|
|
68
|
+
? `LXC Containers on ${options.node}`
|
|
69
|
+
: 'LXC Containers (all nodes)';
|
|
70
|
+
process.stderr.write(chalk.cyan.bold(`\n${headerLabel}`) + chalk.dim(` (${containers.length})\n\n`));
|
|
71
|
+
const headers = isMultiNode
|
|
72
|
+
? ['VMID', 'Name', 'Node', 'Status', 'CPUs', 'Memory', 'Disk', 'Uptime']
|
|
73
|
+
: ['VMID', 'Name', 'Status', 'CPUs', 'Memory', 'Disk', 'Uptime'];
|
|
74
|
+
const table = createTable(headers);
|
|
58
75
|
for (const ct of containers) {
|
|
59
76
|
const memRatio = ct.maxmem > 0 ? ct.mem / ct.maxmem : 0;
|
|
60
77
|
const diskRatio = ct.maxdisk > 0 ? ct.disk / ct.maxdisk : 0;
|
|
61
|
-
|
|
78
|
+
const row = [
|
|
62
79
|
String(ct.vmid),
|
|
63
80
|
truncate(ct.name || chalk.dim('(unnamed)'), 24),
|
|
81
|
+
...(isMultiNode ? [chalk.dim(ct.node)] : []),
|
|
64
82
|
colorStatus(ct.status),
|
|
65
83
|
String(ct.cpus),
|
|
66
84
|
`${formatBytes(ct.mem)} / ${formatBytes(ct.maxmem)} ${formatPercent(memRatio)}`,
|
|
67
85
|
`${formatBytes(ct.disk)} / ${formatBytes(ct.maxdisk)} ${formatPercent(diskRatio)}`,
|
|
68
86
|
formatUptime(ct.uptime),
|
|
69
|
-
]
|
|
87
|
+
];
|
|
88
|
+
table.push(row);
|
|
70
89
|
}
|
|
71
90
|
process.stderr.write(table.toString() + '\n\n');
|
|
72
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containers.js","sourceRoot":"","sources":["../../src/commands/containers.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAC9E,8EAA8E;AAC9E
|
|
1
|
+
{"version":3,"file":"containers.js","sourceRoot":"","sources":["../../src/commands/containers.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/exec.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
export interface ExecCommandOptions {
|
|
2
|
+
target?: string;
|
|
3
|
+
force?: boolean;
|
|
4
|
+
}
|
|
1
5
|
/**
|
|
2
6
|
* Execute a command on the active server (host or container).
|
|
3
7
|
*/
|
|
4
|
-
export declare function execCommand(cmd: string,
|
|
8
|
+
export declare function execCommand(cmd: string, options?: ExecCommandOptions): Promise<void>;
|
|
5
9
|
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/commands/exec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/commands/exec.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,kBAAkB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiI9F"}
|
package/dist/commands/exec.js
CHANGED
|
@@ -10,13 +10,30 @@
|
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
import chalk from 'chalk';
|
|
12
12
|
import { ServerClient } from '../server/client.js';
|
|
13
|
-
import { formatError, formatDim } from '../utils/format.js';
|
|
13
|
+
import { formatError, formatDim, formatWarning } from '../utils/format.js';
|
|
14
14
|
import { logger } from '../utils/logger.js';
|
|
15
15
|
import { isQuietMode, isJsonMode } from '../globals.js';
|
|
16
|
+
import { matchDangerousPattern } from '../utils/command-safety.js';
|
|
17
|
+
import { readConfig } from '../config/index.js';
|
|
18
|
+
import { promptConfirm } from '../utils/prompt.js';
|
|
16
19
|
/**
|
|
17
20
|
* Execute a command on the active server (host or container).
|
|
18
21
|
*/
|
|
19
|
-
export async function execCommand(cmd,
|
|
22
|
+
export async function execCommand(cmd, options = {}) {
|
|
23
|
+
const { force } = options;
|
|
24
|
+
// Safety check: block dangerous commands unless --force is passed
|
|
25
|
+
const dangerMatch = matchDangerousPattern(cmd);
|
|
26
|
+
if (dangerMatch && !force) {
|
|
27
|
+
const config = readConfig();
|
|
28
|
+
if (config.preferences.confirmDestructive) {
|
|
29
|
+
process.stderr.write(formatWarning(`Dangerous command detected: ${dangerMatch}`) + '\n');
|
|
30
|
+
const confirmed = await promptConfirm(chalk.yellow('Are you sure you want to execute this command?'), false);
|
|
31
|
+
if (!confirmed) {
|
|
32
|
+
process.stderr.write(chalk.dim('Cancelled. Use --force to skip this check.\n'));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
20
37
|
let client = null;
|
|
21
38
|
try {
|
|
22
39
|
client = ServerClient.fromActiveProfile();
|
|
@@ -28,7 +45,7 @@ export async function execCommand(cmd, target) {
|
|
|
28
45
|
}
|
|
29
46
|
try {
|
|
30
47
|
// Determine if targeting a container (numeric vmid) or the host
|
|
31
|
-
const vmid = parseTarget(target);
|
|
48
|
+
const vmid = parseTarget(options.target);
|
|
32
49
|
const quiet = isQuietMode();
|
|
33
50
|
const jsonMode = isJsonMode();
|
|
34
51
|
// In JSON mode, collect output instead of streaming
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/commands/exec.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AACxE,8EAA8E;AAC9E,qEAAqE;AACrE,EAAE;AACF,SAAS;AACT,yEAAyE;AACzE,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAE9E,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/commands/exec.ts"],"names":[],"mappings":"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"}
|