@fluid-app/fluid-cli-mist 0.1.62 → 0.1.64
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 +2 -2
- package/dist/index.mjs +38 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -33,9 +33,9 @@ fluid mist droplet egress-proxy on # ask for egress for the attached
|
|
|
33
33
|
fluid mist droplet egress-proxy off # withdraw the request (and any grant)
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
Fluid's egress proxy lets a Droplet's installations reach external systems such as Exigo from Fluid's fixed outbound IPs.
|
|
36
|
+
Fluid's egress proxy lets a Droplet's installations reach external systems such as Exigo from Fluid's fixed outbound IPs. These commands set the Droplet's `egress_proxy_requested`. Fluid accepts it only on a company it has enabled for egress, and the proxy then admits the Droplet with no further approval, wherever the proxy honours Fluid's answer. Withdrawing the request also clears any grant a Fluid admin recorded (`egress_proxy_enabled`).
|
|
37
37
|
|
|
38
|
-
`--egress-proxy` works on `create --droplet`, `create --kind droplet`, `create --hostable`, `attach --kind droplet` and `attach-droplet`. On a Droplet that already exists it updates the request rather than ignoring the flag. Fluid accepts an egress request only from a company admin
|
|
38
|
+
`--egress-proxy` works on `create --droplet`, `create --kind droplet`, `create --hostable`, `attach --kind droplet` and `attach-droplet`. On a Droplet that already exists it updates the request rather than ignoring the flag. Fluid accepts an egress request only from a company admin, and only on a company Fluid has enabled for egress. Otherwise it refuses the request: `--egress-proxy` then sets the droplet up without it and warns, and `droplet egress-proxy` fails with Fluid's reason without writing. A Fluid that predates the fields ignores them, and the commands warn or fail the same way. `droplet egress-proxy off` also clears a grant a Fluid admin gave without a request. Mist Desktop's Safe Mode treats `droplet egress-proxy` as a write.
|
|
39
39
|
|
|
40
40
|
## Repairing the attached Droplet
|
|
41
41
|
|
package/dist/index.mjs
CHANGED
|
@@ -2557,23 +2557,39 @@ function planReceiptMessage(code) {
|
|
|
2557
2557
|
/**
|
|
2558
2558
|
* Ask Fluid for, or withdraw, egress through its egress proxy for the Mist's
|
|
2559
2559
|
* attached Droplet (`fluid mist droplet egress-proxy`). The owner's ask is the
|
|
2560
|
-
* droplet's `egress_proxy_requested
|
|
2561
|
-
*
|
|
2562
|
-
*
|
|
2560
|
+
* droplet's `egress_proxy_requested`, and the proxy admits the droplet on it
|
|
2561
|
+
* alone. A Fluid root admin's grant (`egress_proxy_enabled`) is now only a
|
|
2562
|
+
* record; withdrawing the request also clears it.
|
|
2563
2563
|
*/
|
|
2564
2564
|
/** Why a droplet response can lack the egress fields. Fluid returns them only
|
|
2565
2565
|
* to company admins (and root admins), and older Fluids not at all. */
|
|
2566
2566
|
const EGRESS_NOT_RETURNED = "Fluid did not return the droplet's egress fields: only a company admin can see or ask for egress, or this Fluid predates it.";
|
|
2567
|
-
/** Fluid refused the egress request outright
|
|
2568
|
-
*
|
|
2569
|
-
* field and omits it from
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2567
|
+
/** Fluid refused the egress request outright: it accepts one only from a
|
|
2568
|
+
* company admin (401), and only on a company Fluid enabled for egress (403).
|
|
2569
|
+
* Distinct from an older Fluid, which ignores the field and omits it from
|
|
2570
|
+
* the response. */
|
|
2571
|
+
const EGRESS_REFUSED = "Fluid refused the egress request: only a company admin can ask for egress, and only once Fluid enables egress for the company. The droplet was set up without it.";
|
|
2572
|
+
/** Whether an API error is Fluid refusing the egress request: a 401 or 403
|
|
2573
|
+
* whose `errors` names `egress_proxy_requested`. Matched exactly, so a real
|
|
2573
2574
|
* authentication failure is reported as one rather than as a refusal. */
|
|
2574
2575
|
function isEgressRefusal(error) {
|
|
2575
|
-
return error instanceof MistApiError && error.status === 401 && error.fieldErrors?.egress_proxy_requested !== void 0;
|
|
2576
|
-
}
|
|
2576
|
+
return error instanceof MistApiError && (error.status === 401 || error.status === 403) && error.fieldErrors?.egress_proxy_requested !== void 0;
|
|
2577
|
+
}
|
|
2578
|
+
/** Fluid's own words for an egress refusal, falling back to EGRESS_REFUSED. */
|
|
2579
|
+
function egressRefusalMessage(error) {
|
|
2580
|
+
const reasons = error.fieldErrors?.egress_proxy_requested;
|
|
2581
|
+
const reason = Array.isArray(reasons) ? reasons[0] : reasons;
|
|
2582
|
+
return typeof reason === "string" ? `Fluid refused the egress request: ${reason}.` : EGRESS_REFUSED;
|
|
2583
|
+
}
|
|
2584
|
+
/** Fluid refused to turn egress on for the droplet. Still an API error, so
|
|
2585
|
+
* it keeps the response's status and the 4xx exit code; only the message
|
|
2586
|
+
* is Fluid's reason instead of a bare status. */
|
|
2587
|
+
var EgressRequestRefusedError = class extends MistApiError {
|
|
2588
|
+
constructor(message, refused) {
|
|
2589
|
+
super(message, refused.status, refused.details, refused.fieldErrors);
|
|
2590
|
+
this.name = "EgressRequestRefusedError";
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2577
2593
|
/** The API answered without the egress fields. */
|
|
2578
2594
|
var EgressProxyUnsupportedError = class extends Error {
|
|
2579
2595
|
constructor() {
|
|
@@ -2602,7 +2618,10 @@ async function setDropletEgressProxy(client, input) {
|
|
|
2602
2618
|
granted: current.egress_proxy_enabled === true,
|
|
2603
2619
|
changed: false
|
|
2604
2620
|
};
|
|
2605
|
-
const updated = (await updateDroplet(client, dropletUuid, { egress_proxy_requested: input.requested }))
|
|
2621
|
+
const updated = (await updateDroplet(client, dropletUuid, { egress_proxy_requested: input.requested }).catch((error) => {
|
|
2622
|
+
if (error instanceof MistApiError && isEgressRefusal(error)) throw new EgressRequestRefusedError(egressRefusalMessage(error), error);
|
|
2623
|
+
throw error;
|
|
2624
|
+
})).droplet;
|
|
2606
2625
|
if (updated.egress_proxy_requested === void 0) throw new EgressProxyUnsupportedError();
|
|
2607
2626
|
return {
|
|
2608
2627
|
mistSlug,
|
|
@@ -2883,8 +2902,7 @@ async function ensureEgressProxy(client, args) {
|
|
|
2883
2902
|
}
|
|
2884
2903
|
const requested = record?.egress_proxy_requested === true;
|
|
2885
2904
|
const granted = record?.egress_proxy_enabled === true;
|
|
2886
|
-
if (
|
|
2887
|
-
else if (requested) reporter.succeed("Egress requested — a Fluid admin must approve it before the proxy admits the droplet");
|
|
2905
|
+
if (requested) reporter.succeed("Egress requested — Fluid's proxy admits requested droplets where egress is enabled");
|
|
2888
2906
|
else reporter.warn(`${EGRESS_NOT_RETURNED} Re-run \`fluid mist droplet egress-proxy on\` as a company admin.`);
|
|
2889
2907
|
return {
|
|
2890
2908
|
requested,
|
|
@@ -3044,7 +3062,7 @@ async function verifyManagedEnv(client, args) {
|
|
|
3044
3062
|
}
|
|
3045
3063
|
//#endregion
|
|
3046
3064
|
//#region src/lib/surface-flags.ts
|
|
3047
|
-
const EGRESS_PROXY_FLAG_DESCRIPTION = "Ask Fluid to let the droplet reach external systems such as Exigo through its egress proxy
|
|
3065
|
+
const EGRESS_PROXY_FLAG_DESCRIPTION = "Ask Fluid to let the droplet reach external systems such as Exigo through its egress proxy";
|
|
3048
3066
|
/**
|
|
3049
3067
|
* `--egress-proxy` only means something for a droplet: only a droplet's
|
|
3050
3068
|
* installation token authenticates to the proxy. Refuse it on other kinds
|
|
@@ -3123,7 +3141,7 @@ function printSurfaceSummary(result) {
|
|
|
3123
3141
|
}
|
|
3124
3142
|
if (result.kind === "droplet" && result.managedEnv) if (result.managedEnv.ready) console.log(chalk.dim(" env: managed keys provisioned ✓"));
|
|
3125
3143
|
else console.log(chalk.yellow(" env: redeploy in progress — run `fluid mist env list` shortly to confirm managed keys"));
|
|
3126
|
-
if (result.kind === "droplet" && result.egressProxy) console.log(result.egressProxy.
|
|
3144
|
+
if (result.kind === "droplet" && result.egressProxy) console.log(result.egressProxy.requested ? chalk.dim(" egress proxy: requested ✓") : chalk.yellow(" egress proxy: not requested — only a company admin can ask for it, or this Fluid predates it"));
|
|
3127
3145
|
}
|
|
3128
3146
|
//#endregion
|
|
3129
3147
|
//#region src/commands/create.ts
|
|
@@ -4061,8 +4079,8 @@ const envCommand = new Command("env").description("Manage a mist's environment v
|
|
|
4061
4079
|
* `fluid mist droplet egress-proxy <on|off> [slug] [--json]`
|
|
4062
4080
|
*
|
|
4063
4081
|
* Ask Fluid (on) to let the Mist's attached Droplet reach external systems
|
|
4064
|
-
* such as Exigo through its egress proxy, or withdraw the request (off).
|
|
4065
|
-
*
|
|
4082
|
+
* such as Exigo through its egress proxy, or withdraw the request (off). The
|
|
4083
|
+
* proxy admits the droplet on the request alone; no Fluid admin approves it.
|
|
4066
4084
|
* Leaves an already-correct droplet untouched. Safe Mode treats this as a
|
|
4067
4085
|
* write (apps/mist-desktop fluid-cli-policy).
|
|
4068
4086
|
*/
|
|
@@ -4072,7 +4090,7 @@ function parseEgressProxyState(value) {
|
|
|
4072
4090
|
if (normalized === "off") return false;
|
|
4073
4091
|
throw new InvalidArgumentError("Use \"on\" or \"off\".");
|
|
4074
4092
|
}
|
|
4075
|
-
const dropletEgressProxyCommand = new Command("egress-proxy").description("Ask Fluid (on) or stop asking (off) to let the attached Droplet reach external systems such as Exigo through its egress proxy
|
|
4093
|
+
const dropletEgressProxyCommand = new Command("egress-proxy").description("Ask Fluid (on) or stop asking (off) to let the attached Droplet reach external systems such as Exigo through its egress proxy").argument("<state>", "on | off", parseEgressProxyState).argument("[slug]", "Mist slug (defaults to the .mist file in CWD)").option("--json", "Emit JSON").action((requested, slug, opts) => runAction(async () => {
|
|
4076
4094
|
const result = await setDropletEgressProxy(createMistClient(), {
|
|
4077
4095
|
slug,
|
|
4078
4096
|
cwd: process.cwd(),
|
|
@@ -4081,8 +4099,7 @@ const dropletEgressProxyCommand = new Command("egress-proxy").description("Ask F
|
|
|
4081
4099
|
if (opts.json) return printJson(result);
|
|
4082
4100
|
const target = `droplet ${result.dropletUuid} (${result.mistSlug})`;
|
|
4083
4101
|
if (!result.requested) console.log(result.changed ? `${chalk.green("✓")} Egress request withdrawn for ${target}` : chalk.dim(`No egress request for ${target}`));
|
|
4084
|
-
else
|
|
4085
|
-
else console.log(`${chalk.green("✓")} Egress requested for ${target}. A Fluid admin must approve it before the proxy admits the droplet.`);
|
|
4102
|
+
else console.log(result.changed ? `${chalk.green("✓")} Egress requested for ${target}. Fluid's proxy admits requested droplets where egress is enabled.` : chalk.dim(`Egress already requested for ${target}`));
|
|
4086
4103
|
}));
|
|
4087
4104
|
//#endregion
|
|
4088
4105
|
//#region src/commands/droplet/reinstall.ts
|