@eve-horizon/cli 0.0.1
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 +275 -0
- package/bin/eve.js +2 -0
- package/dist/commands/api.js +350 -0
- package/dist/commands/auth.js +99 -0
- package/dist/commands/db.js +149 -0
- package/dist/commands/env.js +303 -0
- package/dist/commands/event.js +273 -0
- package/dist/commands/harness.js +96 -0
- package/dist/commands/job.js +2266 -0
- package/dist/commands/org.js +97 -0
- package/dist/commands/pipeline.js +403 -0
- package/dist/commands/profile.js +103 -0
- package/dist/commands/project.js +185 -0
- package/dist/commands/secrets.js +147 -0
- package/dist/commands/system.js +457 -0
- package/dist/commands/workflow.js +337 -0
- package/dist/index.js +97 -0
- package/dist/lib/args.js +57 -0
- package/dist/lib/client.js +116 -0
- package/dist/lib/config.js +76 -0
- package/dist/lib/context.js +45 -0
- package/dist/lib/help.js +938 -0
- package/dist/lib/logs.js +51 -0
- package/dist/lib/output.js +14 -0
- package/package.json +36 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleSystem = handleSystem;
|
|
4
|
+
const args_1 = require("../lib/args");
|
|
5
|
+
const client_1 = require("../lib/client");
|
|
6
|
+
const output_1 = require("../lib/output");
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Main Handler
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* System administration commands.
|
|
12
|
+
*
|
|
13
|
+
* NOTE: When auth is implemented, these commands should be restricted to
|
|
14
|
+
* system administrators only - not regular org users.
|
|
15
|
+
*/
|
|
16
|
+
async function handleSystem(subcommand, positionals, flags, context) {
|
|
17
|
+
const json = Boolean(flags.json);
|
|
18
|
+
switch (subcommand) {
|
|
19
|
+
case 'status':
|
|
20
|
+
return handleStatus(context, json);
|
|
21
|
+
case 'health':
|
|
22
|
+
return handleHealth(context, json);
|
|
23
|
+
case 'jobs':
|
|
24
|
+
return handleJobs(flags, context, json);
|
|
25
|
+
case 'envs':
|
|
26
|
+
return handleEnvs(flags, context, json);
|
|
27
|
+
case 'logs':
|
|
28
|
+
return handleLogs(positionals, flags, context, json);
|
|
29
|
+
case 'pods':
|
|
30
|
+
return handlePods(context, json);
|
|
31
|
+
case 'events':
|
|
32
|
+
return handleEvents(flags, context, json);
|
|
33
|
+
case 'config':
|
|
34
|
+
return handleConfig(context, json);
|
|
35
|
+
default:
|
|
36
|
+
throw new Error('Usage: eve system <status|health|jobs|envs|logs|pods|events|config>');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// Subcommand Handlers
|
|
41
|
+
// ============================================================================
|
|
42
|
+
/**
|
|
43
|
+
* eve system status
|
|
44
|
+
* Show comprehensive system status via API endpoint.
|
|
45
|
+
*
|
|
46
|
+
* Note: This calls GET /system/status on the API. The API is responsible for
|
|
47
|
+
* aggregating health from internal services (orchestrator, worker, etc.).
|
|
48
|
+
* The CLI only talks to the API - never directly to other services.
|
|
49
|
+
*/
|
|
50
|
+
async function handleStatus(context, json) {
|
|
51
|
+
try {
|
|
52
|
+
// Try the full system status endpoint first
|
|
53
|
+
const status = await (0, client_1.requestJson)(context, '/system/status');
|
|
54
|
+
if (json) {
|
|
55
|
+
(0, output_1.outputJson)(status, json);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
formatStatus(status);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// If /system/status doesn't exist yet, fall back to basic health check
|
|
63
|
+
const err = error;
|
|
64
|
+
if (err.message?.includes('HTTP 404')) {
|
|
65
|
+
console.log('Note: Full system status endpoint not yet implemented.');
|
|
66
|
+
console.log('Falling back to basic health check...');
|
|
67
|
+
console.log('');
|
|
68
|
+
return handleHealth(context, json);
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* eve system health
|
|
75
|
+
* Quick health check of the API.
|
|
76
|
+
*
|
|
77
|
+
* Note: This only checks the API's health endpoint. The API is the gateway -
|
|
78
|
+
* if the API is healthy and connected to the database, the system is operational.
|
|
79
|
+
*/
|
|
80
|
+
async function handleHealth(context, json) {
|
|
81
|
+
try {
|
|
82
|
+
const health = await (0, client_1.requestJson)(context, '/health');
|
|
83
|
+
if (json) {
|
|
84
|
+
(0, output_1.outputJson)(health, json);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const isHealthy = health.status === 'ok' || health.status === 'healthy';
|
|
88
|
+
const icon = isHealthy ? '✓' : '✗';
|
|
89
|
+
const status = isHealthy ? 'Healthy' : 'Unhealthy';
|
|
90
|
+
console.log('System Health Check');
|
|
91
|
+
console.log('═══════════════════════════════════════');
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log(` ${icon} API: ${status}`);
|
|
94
|
+
if (health.database) {
|
|
95
|
+
console.log(` Database: ${health.database}`);
|
|
96
|
+
}
|
|
97
|
+
if (health.version) {
|
|
98
|
+
console.log(` Version: ${health.version}`);
|
|
99
|
+
}
|
|
100
|
+
console.log('');
|
|
101
|
+
if (isHealthy) {
|
|
102
|
+
console.log('API is operational.');
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.log('API is not healthy. Check server logs.');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
const err = error;
|
|
111
|
+
if (json) {
|
|
112
|
+
(0, output_1.outputJson)({
|
|
113
|
+
api: { healthy: false, error: err.message },
|
|
114
|
+
}, json);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log('System Health Check');
|
|
118
|
+
console.log('═══════════════════════════════════════');
|
|
119
|
+
console.log('');
|
|
120
|
+
console.log(' ✗ API: Unreachable');
|
|
121
|
+
console.log(` ${err.message}`);
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log(`Make sure the API is running and EVE_API_URL is set correctly.`);
|
|
124
|
+
console.log(`Current: ${context.apiUrl}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// Formatting Helpers
|
|
130
|
+
// ============================================================================
|
|
131
|
+
function formatStatus(status) {
|
|
132
|
+
console.log('╭────────────────────────────────────────────────────────────────╮');
|
|
133
|
+
console.log('│ System Status │');
|
|
134
|
+
console.log('╰────────────────────────────────────────────────────────────────╯');
|
|
135
|
+
console.log('');
|
|
136
|
+
// Services
|
|
137
|
+
console.log('Services:');
|
|
138
|
+
formatServiceHealth(' API', status.api.healthy, status.api.version);
|
|
139
|
+
formatServiceHealth(' Orchestrator', status.orchestrator.healthy);
|
|
140
|
+
formatServiceHealth(' Worker', status.worker.healthy);
|
|
141
|
+
console.log('');
|
|
142
|
+
// Queue
|
|
143
|
+
console.log('Job Queue:');
|
|
144
|
+
console.log(` Ready: ${status.queue.ready}`);
|
|
145
|
+
console.log(` Active: ${status.queue.active}`);
|
|
146
|
+
console.log(` Blocked: ${status.queue.blocked}`);
|
|
147
|
+
console.log('');
|
|
148
|
+
// Overall assessment
|
|
149
|
+
const allHealthy = status.api.healthy && status.orchestrator.healthy && status.worker.healthy;
|
|
150
|
+
if (allHealthy) {
|
|
151
|
+
console.log('Status: All systems operational');
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const unhealthy = [];
|
|
155
|
+
if (!status.api.healthy)
|
|
156
|
+
unhealthy.push('API');
|
|
157
|
+
if (!status.orchestrator.healthy)
|
|
158
|
+
unhealthy.push('Orchestrator');
|
|
159
|
+
if (!status.worker.healthy)
|
|
160
|
+
unhealthy.push('Worker');
|
|
161
|
+
console.log(`Status: Issues detected with: ${unhealthy.join(', ')}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function formatServiceHealth(name, healthy, version) {
|
|
165
|
+
const icon = healthy ? '✓' : '✗';
|
|
166
|
+
const status = healthy ? 'healthy' : 'unhealthy';
|
|
167
|
+
const versionStr = version ? ` (v${version})` : '';
|
|
168
|
+
console.log(`${name}: ${icon} ${status}${versionStr}`);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* eve system jobs [--org=X] [--project=X] [--phase=X] [--limit=50] [--offset=0]
|
|
172
|
+
* Admin view: list all jobs across all projects
|
|
173
|
+
*/
|
|
174
|
+
async function handleJobs(flags, context, json) {
|
|
175
|
+
const query = buildQuery({
|
|
176
|
+
org_id: (0, args_1.getStringFlag)(flags, ['org']),
|
|
177
|
+
project_id: (0, args_1.getStringFlag)(flags, ['project']),
|
|
178
|
+
phase: (0, args_1.getStringFlag)(flags, ['phase']),
|
|
179
|
+
limit: (0, args_1.getStringFlag)(flags, ['limit']) ?? '50',
|
|
180
|
+
offset: (0, args_1.getStringFlag)(flags, ['offset']),
|
|
181
|
+
});
|
|
182
|
+
const response = await (0, client_1.requestJson)(context, `/jobs${query}`);
|
|
183
|
+
if (json) {
|
|
184
|
+
(0, output_1.outputJson)(response, json);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
if (response.jobs.length === 0) {
|
|
188
|
+
console.log('No jobs found.');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
console.log('System Jobs (admin view):');
|
|
192
|
+
console.log('');
|
|
193
|
+
formatJobsTable(response.jobs);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* eve system envs [--org=X] [--project=X] [--limit=50] [--offset=0]
|
|
198
|
+
* Admin view: list all environments across all projects
|
|
199
|
+
*/
|
|
200
|
+
async function handleEnvs(flags, context, json) {
|
|
201
|
+
const query = buildQuery({
|
|
202
|
+
org_id: (0, args_1.getStringFlag)(flags, ['org']),
|
|
203
|
+
project_id: (0, args_1.getStringFlag)(flags, ['project']),
|
|
204
|
+
limit: (0, args_1.getStringFlag)(flags, ['limit']) ?? '50',
|
|
205
|
+
offset: (0, args_1.getStringFlag)(flags, ['offset']),
|
|
206
|
+
});
|
|
207
|
+
try {
|
|
208
|
+
const response = await (0, client_1.requestJson)(context, `/system/envs${query}`);
|
|
209
|
+
if (json) {
|
|
210
|
+
(0, output_1.outputJson)(response, json);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
if (response.environments.length === 0) {
|
|
214
|
+
console.log('No environments found.');
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
console.log('System Environments (admin view):');
|
|
218
|
+
console.log('');
|
|
219
|
+
formatEnvsTable(response.environments);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
const err = error;
|
|
224
|
+
if (err.message?.includes('HTTP 404')) {
|
|
225
|
+
console.error('Error: The /system/envs endpoint is not yet implemented.');
|
|
226
|
+
console.error('Please use "eve env list" within a project context instead.');
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* eve system logs <service> [--tail=100]
|
|
234
|
+
* Fetch recent logs for a service via API.
|
|
235
|
+
*/
|
|
236
|
+
async function handleLogs(positionals, flags, context, json) {
|
|
237
|
+
const service = positionals[0] ?? (0, args_1.getStringFlag)(flags, ['service']);
|
|
238
|
+
if (!service) {
|
|
239
|
+
throw new Error('Usage: eve system logs <api|orchestrator|worker|postgres> [--tail=<n>]');
|
|
240
|
+
}
|
|
241
|
+
const tail = (0, args_1.getStringFlag)(flags, ['tail']);
|
|
242
|
+
const query = buildQuery({ tail: tail ?? '100' });
|
|
243
|
+
const response = await (0, client_1.requestJson)(context, `/system/logs/${service}${query}`);
|
|
244
|
+
if (json) {
|
|
245
|
+
(0, output_1.outputJson)(response, json);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (response.length === 0) {
|
|
249
|
+
console.log('No logs found.');
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
for (const entry of response) {
|
|
253
|
+
console.log(`[${entry.timestamp}] ${entry.line}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* eve system pods
|
|
258
|
+
* List pods via API.
|
|
259
|
+
*/
|
|
260
|
+
async function handlePods(context, json) {
|
|
261
|
+
const response = await (0, client_1.requestJson)(context, '/system/pods');
|
|
262
|
+
if (json) {
|
|
263
|
+
(0, output_1.outputJson)(response, json);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (response.length === 0) {
|
|
267
|
+
console.log('No pods found.');
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
console.log('Pods:');
|
|
271
|
+
console.log('');
|
|
272
|
+
formatPodsTable(response);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* eve system events [--limit=50]
|
|
276
|
+
* List recent cluster events via API.
|
|
277
|
+
*/
|
|
278
|
+
async function handleEvents(flags, context, json) {
|
|
279
|
+
const limit = (0, args_1.getStringFlag)(flags, ['limit']);
|
|
280
|
+
const query = buildQuery({ limit: limit ?? '50' });
|
|
281
|
+
const response = await (0, client_1.requestJson)(context, `/system/events${query}`);
|
|
282
|
+
if (json) {
|
|
283
|
+
(0, output_1.outputJson)(response, json);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (response.length === 0) {
|
|
287
|
+
console.log('No events found.');
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
console.log('Recent Events:');
|
|
291
|
+
for (const event of response) {
|
|
292
|
+
const target = `${event.involvedObject.kind}/${event.involvedObject.name}`;
|
|
293
|
+
console.log(`[${event.timestamp}] ${event.type} ${event.reason} ${target} - ${event.message}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* eve system config
|
|
298
|
+
* Show cluster config summary via API.
|
|
299
|
+
*/
|
|
300
|
+
async function handleConfig(context, json) {
|
|
301
|
+
const response = await (0, client_1.requestJson)(context, '/system/config');
|
|
302
|
+
if (json) {
|
|
303
|
+
(0, output_1.outputJson)(response, json);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
console.log('Cluster Config:');
|
|
307
|
+
console.log(` Namespace: ${response.namespace}`);
|
|
308
|
+
if (response.clusterVersion) {
|
|
309
|
+
console.log(` Cluster Version: ${response.clusterVersion}`);
|
|
310
|
+
}
|
|
311
|
+
if (response.nodeCount !== undefined) {
|
|
312
|
+
console.log(` Node Count: ${response.nodeCount}`);
|
|
313
|
+
}
|
|
314
|
+
if (response.deployments.length > 0) {
|
|
315
|
+
console.log(' Deployments:');
|
|
316
|
+
response.deployments.forEach((deployment) => console.log(` - ${deployment}`));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// ============================================================================
|
|
320
|
+
// Helper Functions
|
|
321
|
+
// ============================================================================
|
|
322
|
+
function buildQuery(params) {
|
|
323
|
+
const search = new URLSearchParams();
|
|
324
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
325
|
+
if (value === undefined || value === '')
|
|
326
|
+
return;
|
|
327
|
+
search.set(key, String(value));
|
|
328
|
+
});
|
|
329
|
+
const query = search.toString();
|
|
330
|
+
return query ? `?${query}` : '';
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Format jobs as a human-readable table
|
|
334
|
+
*/
|
|
335
|
+
function formatJobsTable(jobs) {
|
|
336
|
+
if (jobs.length === 0) {
|
|
337
|
+
console.log('No jobs found.');
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
// Calculate column widths
|
|
341
|
+
const idWidth = Math.max(6, ...jobs.map((j) => j.id.length));
|
|
342
|
+
const projectWidth = Math.max(10, ...jobs.map((j) => j.project_id.length));
|
|
343
|
+
const phaseWidth = Math.max(5, ...jobs.map((j) => j.phase.length));
|
|
344
|
+
const titleWidth = Math.min(40, Math.max(5, ...jobs.map((j) => j.title.length)));
|
|
345
|
+
// Header
|
|
346
|
+
const header = [
|
|
347
|
+
padRight('Job ID', idWidth),
|
|
348
|
+
padRight('Project', projectWidth),
|
|
349
|
+
padRight('Phase', phaseWidth),
|
|
350
|
+
padRight('P', 2),
|
|
351
|
+
padRight('Title', titleWidth),
|
|
352
|
+
'Assignee',
|
|
353
|
+
].join(' ');
|
|
354
|
+
console.log(header);
|
|
355
|
+
console.log('-'.repeat(header.length));
|
|
356
|
+
// Rows
|
|
357
|
+
for (const job of jobs) {
|
|
358
|
+
const title = job.title.length > titleWidth ? job.title.slice(0, titleWidth - 3) + '...' : job.title;
|
|
359
|
+
const row = [
|
|
360
|
+
padRight(job.id, idWidth),
|
|
361
|
+
padRight(job.project_id, projectWidth),
|
|
362
|
+
padRight(job.phase, phaseWidth),
|
|
363
|
+
padRight(`P${job.priority}`, 2),
|
|
364
|
+
padRight(title, titleWidth),
|
|
365
|
+
job.assignee ?? '-',
|
|
366
|
+
].join(' ');
|
|
367
|
+
console.log(row);
|
|
368
|
+
}
|
|
369
|
+
console.log('');
|
|
370
|
+
console.log(`Total: ${jobs.length} job(s)`);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Format environments as a human-readable table
|
|
374
|
+
*/
|
|
375
|
+
function formatEnvsTable(envs) {
|
|
376
|
+
if (envs.length === 0) {
|
|
377
|
+
console.log('No environments found.');
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
// Calculate column widths
|
|
381
|
+
const projectWidth = Math.max(10, ...envs.map((e) => e.project_id.length));
|
|
382
|
+
const nameWidth = Math.max(12, ...envs.map((e) => e.name.length));
|
|
383
|
+
const typeWidth = Math.max(4, ...envs.map((e) => e.type.length));
|
|
384
|
+
const namespaceWidth = Math.max(9, ...envs.map((e) => (e.namespace ?? '-').length));
|
|
385
|
+
const releaseWidth = Math.max(7, ...envs.map((e) => (e.current_release ?? '-').length));
|
|
386
|
+
// Header
|
|
387
|
+
const header = [
|
|
388
|
+
padRight('Project', projectWidth),
|
|
389
|
+
padRight('Environment', nameWidth),
|
|
390
|
+
padRight('Type', typeWidth),
|
|
391
|
+
padRight('Namespace', namespaceWidth),
|
|
392
|
+
padRight('Release', releaseWidth),
|
|
393
|
+
].join(' ');
|
|
394
|
+
console.log(header);
|
|
395
|
+
console.log('-'.repeat(header.length));
|
|
396
|
+
// Rows
|
|
397
|
+
for (const env of envs) {
|
|
398
|
+
const row = [
|
|
399
|
+
padRight(env.project_id, projectWidth),
|
|
400
|
+
padRight(env.name, nameWidth),
|
|
401
|
+
padRight(env.type, typeWidth),
|
|
402
|
+
padRight(env.namespace ?? '-', namespaceWidth),
|
|
403
|
+
padRight(env.current_release ?? '-', releaseWidth),
|
|
404
|
+
].join(' ');
|
|
405
|
+
console.log(row);
|
|
406
|
+
}
|
|
407
|
+
console.log('');
|
|
408
|
+
console.log(`Total: ${envs.length} environment(s)`);
|
|
409
|
+
}
|
|
410
|
+
function formatPodsTable(pods) {
|
|
411
|
+
if (pods.length === 0) {
|
|
412
|
+
console.log('No pods found.');
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const nameWidth = Math.max(8, ...pods.map((p) => p.name.length));
|
|
416
|
+
const nsWidth = Math.max(8, ...pods.map((p) => p.namespace.length));
|
|
417
|
+
const phaseWidth = Math.max(5, ...pods.map((p) => p.phase.length));
|
|
418
|
+
const readyWidth = 5;
|
|
419
|
+
const restartsWidth = Math.max(8, ...pods.map((p) => String(p.restarts).length));
|
|
420
|
+
const ageWidth = Math.max(3, ...pods.map((p) => p.age.length));
|
|
421
|
+
const header = [
|
|
422
|
+
padRight('Name', nameWidth),
|
|
423
|
+
padRight('Namespace', nsWidth),
|
|
424
|
+
padRight('Phase', phaseWidth),
|
|
425
|
+
padRight('Ready', readyWidth),
|
|
426
|
+
padRight('Restarts', restartsWidth),
|
|
427
|
+
padRight('Age', ageWidth),
|
|
428
|
+
'Component',
|
|
429
|
+
'Org',
|
|
430
|
+
'Project',
|
|
431
|
+
'Env',
|
|
432
|
+
].join(' ');
|
|
433
|
+
console.log(header);
|
|
434
|
+
console.log('-'.repeat(header.length));
|
|
435
|
+
for (const pod of pods) {
|
|
436
|
+
console.log([
|
|
437
|
+
padRight(pod.name, nameWidth),
|
|
438
|
+
padRight(pod.namespace, nsWidth),
|
|
439
|
+
padRight(pod.phase, phaseWidth),
|
|
440
|
+
padRight(pod.ready ? 'yes' : 'no', readyWidth),
|
|
441
|
+
padRight(String(pod.restarts), restartsWidth),
|
|
442
|
+
padRight(pod.age, ageWidth),
|
|
443
|
+
padRight(pod.component ?? '-', 10),
|
|
444
|
+
padRight(pod.orgId ?? '-', 10),
|
|
445
|
+
padRight(pod.projectId ?? '-', 10),
|
|
446
|
+
padRight(pod.env ?? '-', 10),
|
|
447
|
+
].join(' '));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Pad a string to the right with spaces
|
|
452
|
+
*/
|
|
453
|
+
function padRight(str, width) {
|
|
454
|
+
if (str.length >= width)
|
|
455
|
+
return str;
|
|
456
|
+
return str + ' '.repeat(width - str.length);
|
|
457
|
+
}
|