anycloud 0.0.4 → 0.0.5
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/dist/cli/commands/config/edit.js +15 -0
- package/dist/cli/commands/config/edit.js.map +1 -1
- package/dist/cli/commands/config/list.js +53 -18
- package/dist/cli/commands/config/list.js.map +1 -1
- package/dist/cli/commands/config/new.js +21 -0
- package/dist/cli/commands/config/new.js.map +1 -1
- package/dist/cli/commands/config/remove.js +10 -0
- package/dist/cli/commands/config/remove.js.map +1 -1
- package/dist/cli/commands/credentials/delete.js +10 -0
- package/dist/cli/commands/credentials/delete.js.map +1 -1
- package/dist/cli/commands/credentials/edit.js +16 -0
- package/dist/cli/commands/credentials/edit.js.map +1 -1
- package/dist/cli/commands/credentials/list.js +35 -13
- package/dist/cli/commands/credentials/list.js.map +1 -1
- package/dist/cli/commands/credentials/new.js +25 -0
- package/dist/cli/commands/credentials/new.js.map +1 -1
- package/dist/cli/commands/daemon/index.js +5 -3
- package/dist/cli/commands/daemon/index.js.map +1 -1
- package/dist/cli/commands/list.js +64 -14
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/login.js +10 -0
- package/dist/cli/commands/login.js.map +1 -1
- package/dist/cli/commands/logs.js +95 -11
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/{job.js → run.js} +45 -6
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/serve.js +15 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/status.js +113 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/terminate.js +79 -10
- package/dist/cli/commands/terminate.js.map +1 -1
- package/dist/cli/commands/upgrade.js +64 -6
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/index.js +6 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/services/api-client.js +29 -7
- package/dist/cli/services/api-client.js.map +1 -1
- package/dist/cli/services/config.js +2 -0
- package/dist/cli/services/config.js.map +1 -1
- package/dist/cli/services/oauth.js +4 -5
- package/dist/cli/services/oauth.js.map +1 -1
- package/dist/cli/utils/env-parser.js +27 -0
- package/dist/cli/utils/env-parser.js.map +1 -0
- package/dist/cli/utils/output.js +42 -0
- package/dist/cli/utils/output.js.map +1 -1
- package/dist/daemon/cluster.js +113 -8
- package/dist/daemon/cluster.js.map +1 -1
- package/dist/daemon/docker.js +61 -20
- package/dist/daemon/docker.js.map +1 -1
- package/dist/daemon/preemption.js +127 -0
- package/dist/daemon/preemption.js.map +1 -0
- package/dist/daemon/server.js +118 -6
- package/dist/daemon/server.js.map +1 -1
- package/dist/shared/id-generator.js +20 -0
- package/dist/shared/id-generator.js.map +1 -0
- package/dist/shared/types.js +5 -1
- package/dist/shared/types.js.map +1 -1
- package/package.json +9 -3
- package/dist/cli/commands/job.js.map +0 -1
- package/dist/cli/commands/new.js +0 -15
- package/dist/cli/commands/new.js.map +0 -1
|
@@ -1,12 +1,38 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import Table from 'cli-table3';
|
|
3
|
+
import chalk from 'chalk';
|
|
2
4
|
import { getGitHubToken } from '../services/auth.js';
|
|
3
5
|
import { listDeployments } from '../services/api-client.js';
|
|
4
6
|
import { resolveAllDeploymentProfiles } from '../services/config.js';
|
|
5
|
-
import {
|
|
7
|
+
import { printInfo, printError, printCloudConfigsTable, createSpinner, } from '../utils/output.js';
|
|
6
8
|
import packageJson from '../../../package.json' with { type: 'json' };
|
|
7
9
|
export function createListCommand() {
|
|
8
10
|
return new Command('list')
|
|
9
11
|
.description('List all deployments across all profiles')
|
|
12
|
+
.addHelpText('after', `
|
|
13
|
+
Examples:
|
|
14
|
+
$ anycloud list
|
|
15
|
+
|
|
16
|
+
Output format:
|
|
17
|
+
✓ Found 3 deployment(s) | 4 total VMs | 1 spot instance
|
|
18
|
+
|
|
19
|
+
┌─────────────────────┬──────────────┬─────────┬──────┬──────┐
|
|
20
|
+
│ ID │ Config │ Status │ VMs │ Spot │
|
|
21
|
+
├─────────────────────┼──────────────┼─────────┼──────┼──────┤
|
|
22
|
+
│ abc123-def456-ghi7… │ my-app │ active │ 3 │ Yes │
|
|
23
|
+
│ xyz789-abc123-def4… │ api-service │ stopped │ 1 │ No │
|
|
24
|
+
└─────────────────────┴──────────────┴─────────┴──────┴──────┘
|
|
25
|
+
|
|
26
|
+
Cloud Configurations:
|
|
27
|
+
|
|
28
|
+
┌──────────────┬──────────┬──────────────┬────────────────┐
|
|
29
|
+
│ Config │ Provider │ Region │ VM Type │
|
|
30
|
+
├──────────────┼──────────┼──────────────┼────────────────┤
|
|
31
|
+
│ my-app │ aws │ us-east-1 │ t3.medium │
|
|
32
|
+
│ my-app │ gcp │ us-central1 │ e2-medium │
|
|
33
|
+
│ api-service │ azure │ eastus │ Standard_B2s │
|
|
34
|
+
└──────────────┴──────────┴──────────────┴────────────────┘
|
|
35
|
+
`)
|
|
10
36
|
.action(async () => {
|
|
11
37
|
try {
|
|
12
38
|
// Get GitHub token
|
|
@@ -18,26 +44,50 @@ export function createListCommand() {
|
|
|
18
44
|
return;
|
|
19
45
|
}
|
|
20
46
|
// List all deployments
|
|
47
|
+
const spinner = createSpinner('Fetching deployments...').start();
|
|
21
48
|
const deployments = await listDeployments(anycloudConfigs, accessToken, packageJson.version);
|
|
22
49
|
if (deployments.length === 0) {
|
|
50
|
+
spinner.stop();
|
|
23
51
|
printInfo('No deployments found.');
|
|
24
52
|
return;
|
|
25
53
|
}
|
|
26
|
-
|
|
54
|
+
// Calculate summary statistics
|
|
55
|
+
const totalVMs = deployments.reduce((sum, deployment) => sum + deployment.size, 0);
|
|
56
|
+
const spotCount = deployments.filter((deployment) => deployment.cloudConfigs.some((config) => config.spot === true)).length;
|
|
57
|
+
// Display summary
|
|
58
|
+
spinner.succeed(`Found ${deployments.length} deployment(s) | ${totalVMs} total VMs | ${spotCount} spot instance${spotCount !== 1 ? 's' : ''}`);
|
|
27
59
|
console.log('');
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
deployment.cloudConfigs.forEach((config, i) => {
|
|
37
|
-
printInfo(` ${i + 1}. ${config.cloudProvider} - ${config.region || 'default region'} (${config.vmType || 'default VM'})`);
|
|
38
|
-
});
|
|
39
|
-
console.log('');
|
|
60
|
+
// Create deployments table
|
|
61
|
+
const deploymentsTable = new Table({
|
|
62
|
+
head: ['ID', 'Config', 'VMs'].map((h) => chalk.cyan(h)),
|
|
63
|
+
colWidths: [30, 25, 10],
|
|
64
|
+
style: {
|
|
65
|
+
head: [],
|
|
66
|
+
border: ['dim'],
|
|
67
|
+
},
|
|
40
68
|
});
|
|
69
|
+
deployments.forEach((deployment) => {
|
|
70
|
+
const truncatedId = deployment.id.length > 28
|
|
71
|
+
? deployment.id.substring(0, 27) + '…'
|
|
72
|
+
: deployment.id;
|
|
73
|
+
deploymentsTable.push([
|
|
74
|
+
truncatedId,
|
|
75
|
+
deployment.configName,
|
|
76
|
+
deployment.size.toString(),
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
console.log(deploymentsTable.toString());
|
|
80
|
+
console.log('');
|
|
81
|
+
// Create cloud configurations table using shared utility
|
|
82
|
+
const cloudConfigEntries = deployments.flatMap((deployment) => deployment.cloudConfigs.map((config) => ({
|
|
83
|
+
configName: deployment.configName,
|
|
84
|
+
credentialsName: '', // Not used in deployment list
|
|
85
|
+
provider: config.cloudProvider,
|
|
86
|
+
region: config.region,
|
|
87
|
+
vmType: config.vmType,
|
|
88
|
+
spot: config.spot ?? false,
|
|
89
|
+
})));
|
|
90
|
+
printCloudConfigsTable(cloudConfigEntries);
|
|
41
91
|
}
|
|
42
92
|
catch (error) {
|
|
43
93
|
printError(`Failed to list deployments: ${error.message}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,16 @@ import { printError } from '../utils/output.js';
|
|
|
4
4
|
export function createLoginCommand() {
|
|
5
5
|
return new Command('login')
|
|
6
6
|
.description('Authenticate with GitHub using OAuth Device Flow')
|
|
7
|
+
.addHelpText('after', `
|
|
8
|
+
Examples:
|
|
9
|
+
$ anycloud login
|
|
10
|
+
|
|
11
|
+
Output:
|
|
12
|
+
Enter this code: XXXX-YYYY on https://github.com/login/device
|
|
13
|
+
Or visit: https://github.com/login/device?user_code=XXXX-YYYY
|
|
14
|
+
Waiting for authorization...
|
|
15
|
+
✓ Successfully authenticated with GitHub!
|
|
16
|
+
`)
|
|
7
17
|
.action(async () => {
|
|
8
18
|
try {
|
|
9
19
|
await authenticateWithGitHub();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;SACxB,WAAW,CAAC,kDAAkD,CAAC;SAC/D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,sBAAsB,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,UAAU,CAAC,iBAAkB,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;SACxB,WAAW,CAAC,kDAAkD,CAAC;SAC/D,WAAW,CACV,OAAO,EACP;;;;;;;;;CASL,CACI;SACA,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,sBAAsB,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,UAAU,CAAC,iBAAkB,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1,23 +1,107 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import prompts from 'prompts';
|
|
2
3
|
import { getGitHubToken } from '../services/auth.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
4
|
+
import { getDockerLogs, listDeployments } from '../services/api-client.js';
|
|
5
|
+
import { resolveAllDeploymentProfiles } from '../services/config.js';
|
|
6
|
+
import { printInfo, printError, createSpinner } from '../utils/output.js';
|
|
7
|
+
import { isNonInteractive, getEnvOptional, } from '../services/non-interactive.js';
|
|
5
8
|
import packageJson from '../../../package.json' with { type: 'json' };
|
|
6
9
|
export function createLogsCommand() {
|
|
7
10
|
return new Command('logs')
|
|
8
|
-
.description('Get
|
|
9
|
-
.argument('
|
|
10
|
-
.
|
|
11
|
+
.description('Get Docker container logs')
|
|
12
|
+
.argument('[id]', 'Deployment ID (optional - will prompt to select if not provided)')
|
|
13
|
+
.option('--tail <n>', 'Number of log lines to show (default: 100)', '100')
|
|
14
|
+
.addHelpText('after', `
|
|
15
|
+
Examples:
|
|
16
|
+
$ anycloud logs abc123-def456-ghi789
|
|
17
|
+
$ anycloud logs abc123-def456-ghi789 --tail 50
|
|
18
|
+
$ anycloud logs
|
|
19
|
+
|
|
20
|
+
Output:
|
|
21
|
+
Fetching logs for: abc123-def456-ghi789
|
|
22
|
+
|
|
23
|
+
Docker Logs:
|
|
24
|
+
─────────────────────────────────────────────────────
|
|
25
|
+
=== VM 1 (1.2.3.4) ===
|
|
26
|
+
[2024-01-15 10:30:00] Application started
|
|
27
|
+
[2024-01-15 10:30:01] Listening on port 8080
|
|
28
|
+
[2024-01-15 10:30:05] Request received: GET /
|
|
29
|
+
|
|
30
|
+
=== VM 2 (5.6.7.8) ===
|
|
31
|
+
[2024-01-15 10:30:00] Application started
|
|
32
|
+
[2024-01-15 10:30:01] Listening on port 8080
|
|
33
|
+
─────────────────────────────────────────────────────
|
|
34
|
+
`)
|
|
35
|
+
.action(async (id, options) => {
|
|
11
36
|
try {
|
|
12
|
-
|
|
13
|
-
//
|
|
37
|
+
let deploymentId = id;
|
|
38
|
+
// If no ID provided, fetch and prompt for selection
|
|
39
|
+
if (!deploymentId) {
|
|
40
|
+
// Check for environment variable in non-interactive mode
|
|
41
|
+
if (isNonInteractive()) {
|
|
42
|
+
deploymentId = getEnvOptional('ANYCLOUD_DEPLOYMENT_ID');
|
|
43
|
+
if (!deploymentId) {
|
|
44
|
+
printError('Non-interactive mode: Deployment ID required.\n' +
|
|
45
|
+
' Provide ID as argument or set ANYCLOUD_DEPLOYMENT_ID environment variable.');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Get GitHub token
|
|
51
|
+
const accessToken = await getGitHubToken();
|
|
52
|
+
// Get all deployment configs with resolved credentials
|
|
53
|
+
const anycloudConfigs = await resolveAllDeploymentProfiles();
|
|
54
|
+
if (Object.keys(anycloudConfigs).length === 0) {
|
|
55
|
+
printError('No deployment profiles found in anycloud.json');
|
|
56
|
+
printInfo('Please create anycloud.json with deployment profiles.');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
// List all deployments
|
|
60
|
+
const loadingSpinner = createSpinner('Loading deployments...').start();
|
|
61
|
+
const deployments = await listDeployments(anycloudConfigs, accessToken, packageJson.version);
|
|
62
|
+
loadingSpinner.stop();
|
|
63
|
+
if (deployments.length === 0) {
|
|
64
|
+
printError('No deployments found.');
|
|
65
|
+
printInfo('Create a deployment first using: anycloud run --config <config-name>');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
// Prompt for deployment selection
|
|
69
|
+
const selection = await prompts({
|
|
70
|
+
type: 'select',
|
|
71
|
+
name: 'deployment',
|
|
72
|
+
message: 'Select deployment:',
|
|
73
|
+
choices: deployments.map((deployment) => {
|
|
74
|
+
const hasSpot = deployment.cloudConfigs.some((config) => config.spot === true);
|
|
75
|
+
const spotText = hasSpot ? ' | Spot' : '';
|
|
76
|
+
return {
|
|
77
|
+
title: deployment.id,
|
|
78
|
+
value: deployment.id,
|
|
79
|
+
description: `${deployment.configName} | ${deployment.size} VMs${spotText}`,
|
|
80
|
+
};
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
if (!selection.deployment) {
|
|
84
|
+
process.exit(0); // User cancelled
|
|
85
|
+
}
|
|
86
|
+
deploymentId = selection.deployment;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Get GitHub token (if not already fetched)
|
|
14
90
|
const accessToken = await getGitHubToken();
|
|
15
|
-
//
|
|
16
|
-
const
|
|
91
|
+
// Parse tail option
|
|
92
|
+
const tail = parseInt(options?.tail || '100', 10);
|
|
93
|
+
if (isNaN(tail) || tail < 1) {
|
|
94
|
+
printError('Invalid --tail value. Must be a positive number.');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
// Get Docker logs
|
|
98
|
+
const spinner = createSpinner(`Fetching Docker logs for: ${deploymentId}...`).start();
|
|
99
|
+
const response = await getDockerLogs(deploymentId, accessToken, packageJson.version, tail);
|
|
100
|
+
spinner.stop();
|
|
17
101
|
console.log('');
|
|
18
|
-
console.log('Logs:');
|
|
102
|
+
console.log('Docker Logs:');
|
|
19
103
|
console.log('─────────────────────────────────────────────────────');
|
|
20
|
-
console.log(response.
|
|
104
|
+
console.log(response.logs);
|
|
21
105
|
console.log('─────────────────────────────────────────────────────');
|
|
22
106
|
console.log('');
|
|
23
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,12 +5,31 @@ import { resolveDeploymentProfile, loadDeploymentProfiles, } from '../services/c
|
|
|
5
5
|
import { createDeployment } from '../services/api-client.js';
|
|
6
6
|
import { printInfo, printError, createSpinner } from '../utils/output.js';
|
|
7
7
|
import { isNonInteractive, getConfigFromEnv, } from '../services/non-interactive.js';
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import { DeploymentType } from '../../shared/types.js';
|
|
9
|
+
import { generateJobId } from '../../shared/id-generator.js';
|
|
10
|
+
import { parseEnvFile } from '../utils/env-parser.js';
|
|
11
|
+
import packageJson from '../../../package.json' with { type: 'json' };
|
|
12
|
+
export function createRunCommand() {
|
|
13
|
+
return new Command('run')
|
|
10
14
|
.description('Create a new job deployment')
|
|
11
15
|
.argument('<image>', 'Container image (e.g., alpine:latest, ghcr.io/user/job:latest)')
|
|
12
|
-
.option('--config <name>', 'Config name from anycloud.json')
|
|
13
|
-
.
|
|
16
|
+
.option('-c, --config <name>', 'Config name from anycloud.json')
|
|
17
|
+
.option('-i, --id <id>', 'Job identifier')
|
|
18
|
+
.option('-e, --env <file>', 'Environment file (.env format)')
|
|
19
|
+
.addHelpText('after', `
|
|
20
|
+
Examples:
|
|
21
|
+
$ anycloud run alpine:latest
|
|
22
|
+
$ anycloud run alpine:latest --config my-app
|
|
23
|
+
$ anycloud run ghcr.io/myuser/job:v1.0 --config prod --id my-job-123
|
|
24
|
+
$ anycloud run alpine:latest --env prod.env
|
|
25
|
+
|
|
26
|
+
Output:
|
|
27
|
+
Creating job deployment for image: alpine:latest
|
|
28
|
+
Using config: my-app
|
|
29
|
+
✓ Job deployment created!
|
|
30
|
+
|
|
31
|
+
ID: job-abc123-def456-ghi789
|
|
32
|
+
`)
|
|
14
33
|
.action(async (image, options) => {
|
|
15
34
|
try {
|
|
16
35
|
printInfo(`Creating job deployment for image: ${image}`);
|
|
@@ -50,13 +69,33 @@ export function createJobCommand() {
|
|
|
50
69
|
configName = selection.profile;
|
|
51
70
|
}
|
|
52
71
|
printInfo(`Using config: ${configName}`);
|
|
72
|
+
// Parse environment variables from file if provided
|
|
73
|
+
let envVars;
|
|
74
|
+
if (options.env) {
|
|
75
|
+
try {
|
|
76
|
+
envVars = parseEnvFile(options.env);
|
|
77
|
+
const count = Object.keys(envVars).length;
|
|
78
|
+
if (count > 0) {
|
|
79
|
+
printInfo(`Loaded ${count} environment variable(s) from ${options.env}`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
printInfo(`No environment variables found in ${options.env}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
printError(error.message);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
53
90
|
// Get GitHub token
|
|
54
91
|
const accessToken = await getGitHubToken();
|
|
55
92
|
// Resolve deployment profile and credentials
|
|
56
93
|
const cloudConfigs = await resolveDeploymentProfile(configName);
|
|
94
|
+
// Generate job ID if not provided
|
|
95
|
+
const jobId = options.name || generateJobId();
|
|
57
96
|
// Create deployment with hardcoded 'job' type
|
|
58
97
|
const spinner = createSpinner('Creating job deployment...').start();
|
|
59
|
-
const response = await createDeployment(image, cloudConfigs, accessToken, configName,
|
|
98
|
+
const response = await createDeployment(image, cloudConfigs, accessToken, configName, DeploymentType.Job, packageJson.version, jobId, envVars);
|
|
60
99
|
spinner.succeed('Job deployment created!');
|
|
61
100
|
console.log('');
|
|
62
101
|
printInfo(`ID: ${response.id}`);
|
|
@@ -68,4 +107,4 @@ export function createJobCommand() {
|
|
|
68
107
|
}
|
|
69
108
|
});
|
|
70
109
|
}
|
|
71
|
-
//# sourceMappingURL=
|
|
110
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EACL,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,WAAW,MAAM,uBAAuB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAEtE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC;SACtB,WAAW,CAAC,6BAA6B,CAAC;SAC1C,QAAQ,CACP,SAAS,EACT,gEAAgE,CACjE;SACA,MAAM,CAAC,qBAAqB,EAAE,gCAAgC,CAAC;SAC/D,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC;SACzC,MAAM,CAAC,kBAAkB,EAAE,gCAAgC,CAAC;SAC5D,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;CAaL,CACI;SACA,MAAM,CACL,KAAK,EACH,KAAa,EACb,OAAyD,EACzD,EAAE;QACF,IAAI,CAAC;YACH,SAAS,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;YAEzD,wBAAwB;YACxB,IAAI,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;YAEhC,yDAAyD;YACzD,IAAI,CAAC,UAAU,IAAI,gBAAgB,EAAE,EAAE,CAAC;gBACtC,UAAU,GAAG,gBAAgB,EAAE,CAAC;gBAChC,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,UAAU,CACR,+CAA+C;wBAC7C,uEAAuE,CAC1E,CAAC;oBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC;YAED,wFAAwF;YACxF,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,QAAQ,GAAG,MAAM,sBAAsB,EAAE,CAAC;gBAChD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAE3C,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,UAAU,CAAC,+CAA+C,CAAC,CAAC;oBAC5D,SAAS,CACP,uDAAuD,CACxD,CAAC;oBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;gBAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC;oBAC9B,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,gBAAgB;oBACzB,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;wBACnC,KAAK,EAAE,IAAI;wBACX,KAAK,EAAE,IAAI;wBACX,WAAW,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,YAAY;qBAClD,CAAC,CAAC;iBACJ,CAAC,CAAC;gBAEH,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;oBACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;gBACpC,CAAC;gBAED,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC;YACjC,CAAC;YAED,SAAS,CAAC,iBAAiB,UAAU,EAAE,CAAC,CAAC;YAEzC,oDAAoD;YACpD,IAAI,OAA2C,CAAC;YAChD,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBAChB,IAAI,CAAC;oBACH,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;oBACpC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;oBAC1C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;wBACd,SAAS,CACP,UAAU,KAAK,iCAAiC,OAAO,CAAC,GAAG,EAAE,CAC9D,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,SAAS,CAAC,qCAAqC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;oBAChE,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,UAAU,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC;oBACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC;YAED,mBAAmB;YACnB,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;YAE3C,6CAA6C;YAC7C,MAAM,YAAY,GAAG,MAAM,wBAAwB,CAAC,UAAU,CAAC,CAAC;YAEhE,kCAAkC;YAClC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,IAAI,aAAa,EAAE,CAAC;YAE9C,8CAA8C;YAC9C,MAAM,OAAO,GAAG,aAAa,CAAC,4BAA4B,CAAC,CAAC,KAAK,EAAE,CAAC;YACpE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CACrC,KAAK,EACL,YAAY,EACZ,WAAW,EACX,UAAU,EACV,cAAc,CAAC,GAAG,EAClB,WAAW,CAAC,OAAO,EACnB,KAAK,EACL,OAAO,CACR,CAAC;YAEF,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,SAAS,CAAC,OAAO,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,UAAU,CACR,oCAAqC,KAAe,CAAC,OAAO,EAAE,CAC/D,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CACF,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { printError, printInfo } from '../utils/output.js';
|
|
3
|
+
export function createServeCommand() {
|
|
4
|
+
return new Command('serve')
|
|
5
|
+
.description('Create a new server deployment')
|
|
6
|
+
.argument('<image>', 'Container image (e.g., nginx:latest, ghcr.io/user/app:latest)')
|
|
7
|
+
.option('--config <name>', 'Config name from anycloud.json')
|
|
8
|
+
.option('--name <name>', 'Server name')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
printError('Server deployments are not yet supported.');
|
|
11
|
+
printInfo('Use "anycloud run" for job deployments.');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;SACxB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,QAAQ,CACP,SAAS,EACT,+DAA+D,CAChE;SACA,MAAM,CAAC,iBAAiB,EAAE,gCAAgC,CAAC;SAC3D,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC;SACtC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,UAAU,CAAC,2CAA2C,CAAC,CAAC;QACxD,SAAS,CAAC,yCAAyC,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import prompts from 'prompts';
|
|
3
|
+
import { getGitHubToken } from '../services/auth.js';
|
|
4
|
+
import { getDeploymentStatus, listDeployments, } from '../services/api-client.js';
|
|
5
|
+
import { resolveAllDeploymentProfiles } from '../services/config.js';
|
|
6
|
+
import { printInfo, printError, createSpinner } from '../utils/output.js';
|
|
7
|
+
import { isNonInteractive, getEnvOptional, } from '../services/non-interactive.js';
|
|
8
|
+
import packageJson from '../../../package.json' with { type: 'json' };
|
|
9
|
+
export function createStatusCommand() {
|
|
10
|
+
return new Command('status')
|
|
11
|
+
.description('Get deployment status logs')
|
|
12
|
+
.argument('[id]', 'Deployment ID (optional - will prompt to select if not provided)')
|
|
13
|
+
.addHelpText('after', `
|
|
14
|
+
Examples:
|
|
15
|
+
$ anycloud status abc123-def456-ghi789
|
|
16
|
+
$ anycloud status
|
|
17
|
+
|
|
18
|
+
Output:
|
|
19
|
+
Fetching status for: abc123-def456-ghi789
|
|
20
|
+
|
|
21
|
+
Status:
|
|
22
|
+
─────────────────────────────────────────────────────
|
|
23
|
+
Deploying your service...
|
|
24
|
+
Pulling container image...
|
|
25
|
+
Deployment complete!
|
|
26
|
+
─────────────────────────────────────────────────────
|
|
27
|
+
`)
|
|
28
|
+
.action(async (id) => {
|
|
29
|
+
try {
|
|
30
|
+
let deploymentId = id;
|
|
31
|
+
// If no ID provided, fetch and prompt for selection
|
|
32
|
+
if (!deploymentId) {
|
|
33
|
+
// Check for environment variable in non-interactive mode
|
|
34
|
+
if (isNonInteractive()) {
|
|
35
|
+
deploymentId = getEnvOptional('ANYCLOUD_DEPLOYMENT_ID');
|
|
36
|
+
if (!deploymentId) {
|
|
37
|
+
printError('Non-interactive mode: Deployment ID required.\n' +
|
|
38
|
+
' Provide ID as argument or set ANYCLOUD_DEPLOYMENT_ID environment variable.');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Get GitHub token
|
|
44
|
+
const accessToken = await getGitHubToken();
|
|
45
|
+
// Get all deployment configs with resolved credentials
|
|
46
|
+
const anycloudConfigs = await resolveAllDeploymentProfiles();
|
|
47
|
+
if (Object.keys(anycloudConfigs).length === 0) {
|
|
48
|
+
printError('No deployment profiles found in anycloud.json');
|
|
49
|
+
printInfo('Please create anycloud.json with deployment profiles.');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
// List all deployments
|
|
53
|
+
const loadingSpinner = createSpinner('Loading deployments...').start();
|
|
54
|
+
const deployments = await listDeployments(anycloudConfigs, accessToken, packageJson.version);
|
|
55
|
+
loadingSpinner.stop();
|
|
56
|
+
if (deployments.length === 0) {
|
|
57
|
+
printError('No deployments found.');
|
|
58
|
+
printInfo('Create a deployment first using: anycloud run --config <config-name>');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
// Prompt for deployment selection
|
|
62
|
+
const selection = await prompts({
|
|
63
|
+
type: 'select',
|
|
64
|
+
name: 'deployment',
|
|
65
|
+
message: 'Select deployment:',
|
|
66
|
+
choices: deployments.map((deployment) => {
|
|
67
|
+
const hasSpot = deployment.cloudConfigs.some((config) => config.spot === true);
|
|
68
|
+
const spotText = hasSpot ? ' | Spot' : '';
|
|
69
|
+
return {
|
|
70
|
+
title: deployment.id,
|
|
71
|
+
value: deployment.id,
|
|
72
|
+
description: `${deployment.configName} | ${deployment.size} VMs${spotText}`,
|
|
73
|
+
};
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
if (!selection.deployment) {
|
|
77
|
+
process.exit(0); // User cancelled
|
|
78
|
+
}
|
|
79
|
+
deploymentId = selection.deployment;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Get GitHub token (if not already fetched)
|
|
83
|
+
const accessToken = await getGitHubToken();
|
|
84
|
+
// Get status
|
|
85
|
+
const spinner = createSpinner(`Fetching status for: ${deploymentId}...`).start();
|
|
86
|
+
const response = await getDeploymentStatus(deploymentId, accessToken, packageJson.version);
|
|
87
|
+
spinner.stop();
|
|
88
|
+
console.log('');
|
|
89
|
+
console.log(`Deployment Health: ${response.status.toUpperCase()}`);
|
|
90
|
+
console.log('');
|
|
91
|
+
// Show per-VM status if available
|
|
92
|
+
if (response.vmStatuses && response.vmStatuses.length > 0) {
|
|
93
|
+
console.log('VM Health:');
|
|
94
|
+
response.vmStatuses.forEach((vm, index) => {
|
|
95
|
+
const healthIcon = vm.healthy ? '✓' : '✗';
|
|
96
|
+
const healthText = vm.healthy ? 'healthy' : 'unhealthy';
|
|
97
|
+
console.log(` ${healthIcon} VM ${index + 1} (${vm.ip}): ${healthText}`);
|
|
98
|
+
});
|
|
99
|
+
console.log('');
|
|
100
|
+
}
|
|
101
|
+
console.log('Deployment Logs:');
|
|
102
|
+
console.log('─────────────────────────────────────────────────────');
|
|
103
|
+
console.log(response.message);
|
|
104
|
+
console.log('─────────────────────────────────────────────────────');
|
|
105
|
+
console.log('');
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
printError(`Failed to fetch status: ${error.message}`);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,89 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import prompts from 'prompts';
|
|
3
|
-
import { terminateDeployment } from '../services/api-client.js';
|
|
3
|
+
import { terminateDeployment, listDeployments, } from '../services/api-client.js';
|
|
4
4
|
import { getGitHubToken } from '../services/auth.js';
|
|
5
|
-
import { resolveDeploymentProfile, loadDeploymentProfiles, } from '../services/config.js';
|
|
6
|
-
import {
|
|
7
|
-
import { isNonInteractive, getConfigFromEnv, } from '../services/non-interactive.js';
|
|
5
|
+
import { resolveDeploymentProfile, loadDeploymentProfiles, resolveAllDeploymentProfiles, } from '../services/config.js';
|
|
6
|
+
import { printInfo, printError, createSpinner } from '../utils/output.js';
|
|
7
|
+
import { isNonInteractive, getConfigFromEnv, getEnvOptional, } from '../services/non-interactive.js';
|
|
8
8
|
import packageJson from '../../../package.json' with { type: 'json' };
|
|
9
9
|
export function createTerminateCommand() {
|
|
10
10
|
return new Command('terminate')
|
|
11
11
|
.description('Terminate a deployment')
|
|
12
|
-
.argument('
|
|
12
|
+
.argument('[id]', 'Deployment ID (optional - will prompt to select if not provided)')
|
|
13
13
|
.option('--config <name>', 'Config name from anycloud.json')
|
|
14
|
+
.addHelpText('after', `
|
|
15
|
+
Examples:
|
|
16
|
+
$ anycloud terminate abc123-def456-ghi789
|
|
17
|
+
$ anycloud terminate abc123-def456-ghi789 --config my-app
|
|
18
|
+
$ anycloud terminate
|
|
19
|
+
|
|
20
|
+
Output:
|
|
21
|
+
Terminating: abc123-def456-ghi789
|
|
22
|
+
Using config: my-app
|
|
23
|
+
✓ Deployment terminated successfully!
|
|
24
|
+
`)
|
|
14
25
|
.action(async (id, options) => {
|
|
15
26
|
try {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
let deploymentId = id;
|
|
28
|
+
let configName = options?.config;
|
|
29
|
+
// If no ID provided, fetch and prompt for selection
|
|
30
|
+
if (!deploymentId) {
|
|
31
|
+
// Check for environment variable in non-interactive mode
|
|
32
|
+
if (isNonInteractive()) {
|
|
33
|
+
deploymentId = getEnvOptional('ANYCLOUD_DEPLOYMENT_ID');
|
|
34
|
+
if (!deploymentId) {
|
|
35
|
+
printError('Non-interactive mode: Deployment ID required.\n' +
|
|
36
|
+
' Provide ID as argument or set ANYCLOUD_DEPLOYMENT_ID environment variable.');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Get GitHub token
|
|
42
|
+
const accessToken = await getGitHubToken();
|
|
43
|
+
// Get all deployment configs with resolved credentials
|
|
44
|
+
const anycloudConfigs = await resolveAllDeploymentProfiles();
|
|
45
|
+
if (Object.keys(anycloudConfigs).length === 0) {
|
|
46
|
+
printError('No deployment profiles found in anycloud.json');
|
|
47
|
+
printInfo('Please create anycloud.json with deployment profiles.');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
// List all deployments
|
|
51
|
+
const loadingSpinner = createSpinner('Loading deployments...').start();
|
|
52
|
+
const deployments = await listDeployments(anycloudConfigs, accessToken, packageJson.version);
|
|
53
|
+
loadingSpinner.stop();
|
|
54
|
+
if (deployments.length === 0) {
|
|
55
|
+
printError('No deployments found.');
|
|
56
|
+
printInfo('Create a deployment first using: anycloud run --config <config-name>');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
// Prompt for deployment selection
|
|
60
|
+
const selection = await prompts({
|
|
61
|
+
type: 'select',
|
|
62
|
+
name: 'deployment',
|
|
63
|
+
message: 'Select deployment to terminate:',
|
|
64
|
+
choices: deployments.map((deployment) => {
|
|
65
|
+
const hasSpot = deployment.cloudConfigs.some((config) => config.spot === true);
|
|
66
|
+
const spotText = hasSpot ? ' | Spot' : '';
|
|
67
|
+
return {
|
|
68
|
+
title: deployment.id,
|
|
69
|
+
value: deployment.id,
|
|
70
|
+
description: `${deployment.configName} | ${deployment.size} VMs${spotText}`,
|
|
71
|
+
};
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
if (!selection.deployment) {
|
|
75
|
+
process.exit(0); // User cancelled
|
|
76
|
+
}
|
|
77
|
+
deploymentId = selection.deployment;
|
|
78
|
+
// Auto-detect config from the selected deployment if not provided
|
|
79
|
+
const selectedDeployment = deployments.find((d) => d.id === deploymentId);
|
|
80
|
+
if (selectedDeployment && !configName) {
|
|
81
|
+
configName = selectedDeployment.configName;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
printInfo(`Terminating: ${deploymentId}`);
|
|
86
|
+
// Determine config name if not already set
|
|
19
87
|
// Check for environment variable in non-interactive mode
|
|
20
88
|
if (!configName && isNonInteractive()) {
|
|
21
89
|
configName = getConfigFromEnv();
|
|
@@ -55,8 +123,9 @@ export function createTerminateCommand() {
|
|
|
55
123
|
// Resolve deployment profile and credentials
|
|
56
124
|
const cloudConfigs = await resolveDeploymentProfile(configName);
|
|
57
125
|
// Terminate deployment
|
|
58
|
-
const
|
|
59
|
-
|
|
126
|
+
const spinner = createSpinner('Terminating deployment...').start();
|
|
127
|
+
const response = await terminateDeployment(deploymentId, cloudConfigs, accessToken, configName, packageJson.version);
|
|
128
|
+
spinner.succeed('Deployment terminated successfully!');
|
|
60
129
|
if (response.message) {
|
|
61
130
|
printInfo(response.message);
|
|
62
131
|
}
|