insta 0.1.7 → 0.1.8
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/commands/compute.js +30 -0
- package/dist/index.js +2 -1
- package/dist/telemetry.js +5 -4
- package/package.json +1 -1
package/dist/commands/compute.js
CHANGED
|
@@ -590,9 +590,25 @@ export async function serviceAlwaysOn(type, mode, serviceName, opts) {
|
|
|
590
590
|
info(`${type} ${res.body.service?.name ?? svc.name}: always-on ${on ? 'ENABLED — machines stay warm (no cold starts; idle RAM bills at actual usage)' : 'disabled — scales to zero when idle'}`);
|
|
591
591
|
}
|
|
592
592
|
export const computeAlwaysOn = (mode, serviceName, opts) => serviceAlwaysOn('compute', mode, serviceName, opts);
|
|
593
|
+
const INSTANCE_ID = /^inst-[a-f0-9]{12}$/;
|
|
594
|
+
// A lone positional is the service even when it is all digits: service names may be.
|
|
595
|
+
export function removeTarget(count, service, opts) {
|
|
596
|
+
if (!INSTANCE_ID.test(opts.remove))
|
|
597
|
+
throw new Error(`invalid instance id: ${opts.remove} (expected inst-<12 hex digits>, the \`instance\` field of \`insta compute logs --json\`)`);
|
|
598
|
+
if (opts.region !== undefined)
|
|
599
|
+
throw new Error('--region does not apply to --remove');
|
|
600
|
+
if (service !== undefined) {
|
|
601
|
+
throw new Error(count !== undefined && count.trim() !== '' && Number.isFinite(Number(count)) ? '--remove lowers the replica count by one; pass no count' : `unexpected argument: ${service} (usage: insta compute scale [service] --remove <instance>)`);
|
|
602
|
+
}
|
|
603
|
+
return count;
|
|
604
|
+
}
|
|
593
605
|
// `insta compute scale <count> [service] [--region <r>]` — POST /services/:id/scale. Count is
|
|
594
606
|
// validated locally (1..10); the paid-plan gate is the backend's and its 403 flows verbatim.
|
|
595
607
|
export async function computeScale(count, serviceName, opts) {
|
|
608
|
+
if (opts.remove !== undefined)
|
|
609
|
+
return computeRemoveInstance(removeTarget(count, serviceName, { remove: opts.remove, region: opts.region }), opts.remove, opts);
|
|
610
|
+
if (count === undefined)
|
|
611
|
+
throw new Error('a replica count is required (or --remove <instance> to drop one named instance)');
|
|
596
612
|
const machineCount = parseCount(count);
|
|
597
613
|
const api = await ApiClient.load();
|
|
598
614
|
const p = await requireProject();
|
|
@@ -606,6 +622,20 @@ export async function computeScale(count, serviceName, opts) {
|
|
|
606
622
|
return printJson(res.body.service);
|
|
607
623
|
info(`scaled compute ${svc.name} to ${machineCount} replica(s)${opts.region ? ` in ${opts.region}` : ''}`);
|
|
608
624
|
}
|
|
625
|
+
// `insta compute scale [service] --remove <instance>` — DELETE /services/:id/instances/:instance.
|
|
626
|
+
async function computeRemoveInstance(serviceName, instance, opts) {
|
|
627
|
+
const api = await ApiClient.load();
|
|
628
|
+
const p = await requireProject();
|
|
629
|
+
const branch = opts.branch ?? p.branch;
|
|
630
|
+
const { services } = await api.request('GET', `/projects/${p.projectId}/services${q(branch)}`);
|
|
631
|
+
const svc = resolveSoleService(services, 'compute', serviceName);
|
|
632
|
+
const res = await api.rawRequest('DELETE', `/projects/${p.projectId}/services/${svc.id}/instances/${instance}`);
|
|
633
|
+
if (handleApproval(res, opts.json))
|
|
634
|
+
return;
|
|
635
|
+
if (opts.json)
|
|
636
|
+
return printJson(res.body.service);
|
|
637
|
+
info(`removed ${instance} from compute ${svc.name}; ${res.body.service?.machine_count ?? '?'} replica(s) remain`);
|
|
638
|
+
}
|
|
609
639
|
// ---- limits (the resource ceiling; paid plans) ----
|
|
610
640
|
// Parse a human memory value into MB: "512", "512mb", "1gb", "2g", "1.5gb".
|
|
611
641
|
// Exported for unit tests — this is the only place a user-typed size becomes a number.
|
package/dist/index.js
CHANGED
|
@@ -365,8 +365,9 @@ compute.command('restart [service]').description("Restart a compute service by r
|
|
|
365
365
|
.option('--json').option('--branch <branch>', 'branch (default: current)').action(guard((service, o) => computeCmd.computeRestart(service, o)));
|
|
366
366
|
compute.command('status [service]').description("Show a compute service's desired vs. live state")
|
|
367
367
|
.option('--json').option('--branch <branch>', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStatus(service, o)));
|
|
368
|
-
compute.command('scale
|
|
368
|
+
compute.command('scale [count] [service]').description('Set a compute service same-region replica count, 1 to 10 (paid plans only). --remove <instance> instead drops that one instance and runs one fewer; instance ids are the `instance` field of `insta compute logs --json`. The last instance cannot be removed')
|
|
369
369
|
.option('--region <region>', 'region to scale in (default: the service region)')
|
|
370
|
+
.option('--remove <instance>', 'drop this instance (inst-<12 hex>) and run one fewer replica')
|
|
370
371
|
.option('--json').option('--branch <branch>', 'branch (default: current)')
|
|
371
372
|
.action(guard((count, service, o) => computeCmd.computeScale(count, service, o)));
|
|
372
373
|
compute.command('limits [service]').description("Show or set a compute service's resource ceiling (any plan within the free cap; raising above it needs a paid plan). --memory is the dial; cpu derives from it unless --cpu is given. Billing is actual usage — the ceiling caps what the app may burn, it is not a price")
|
package/dist/telemetry.js
CHANGED
|
@@ -34,7 +34,7 @@ const SAFE_ARGS = {
|
|
|
34
34
|
'env use': { 0: ENV }, 'project link': { 0: ID },
|
|
35
35
|
'service add': { 0: SERVICE }, 'service remove': { 0: SERVICE }, 'service rename': { 0: SERVICE },
|
|
36
36
|
'storage set-access': { 0: oneOf(['public', 'private']) },
|
|
37
|
-
'compute scale': { 0:
|
|
37
|
+
'compute scale': { 0: (v) => /^\d+$/.test(v) },
|
|
38
38
|
'compute always-on': { 0: ON_OFF }, 'postgres always-on': { 0: ON_OFF },
|
|
39
39
|
'redis always-on': { 0: ON_OFF }, 'mysql always-on': { 0: ON_OFF }, 'mongodb always-on': { 0: ON_OFF },
|
|
40
40
|
'template info': { 0: SLUG }, 'billing subscribe': { 0: oneOf(['pro', 'team']) },
|
|
@@ -69,8 +69,9 @@ export function redactOptions(opts) {
|
|
|
69
69
|
}
|
|
70
70
|
return out;
|
|
71
71
|
}
|
|
72
|
-
export function redactArgs(command, args) {
|
|
73
|
-
|
|
72
|
+
export function redactArgs(command, args, options = {}) {
|
|
73
|
+
// with --remove the count's slot holds the service name
|
|
74
|
+
const checks = command === 'compute scale' && options.remove !== undefined ? {} : SAFE_ARGS[command] ?? {};
|
|
74
75
|
return args.map((a, i) => (a === undefined ? null : typeof a === 'string' && checks[i]?.(a) ? a : REDACTED));
|
|
75
76
|
}
|
|
76
77
|
/** The deployment a `login --env|--api-url` targets. It is persisted only when the login succeeds, so
|
|
@@ -125,7 +126,7 @@ export function buildCommandEvent(command, args, options, outcome, ctx) {
|
|
|
125
126
|
timestamp: new Date().toISOString(),
|
|
126
127
|
properties: {
|
|
127
128
|
command,
|
|
128
|
-
args: redactArgs(command, args),
|
|
129
|
+
args: redactArgs(command, args, options),
|
|
129
130
|
options: redactOptions(options),
|
|
130
131
|
success: !cancelled && (outcome.exitCode === 0 || ranChild),
|
|
131
132
|
cancelled,
|