Skip to content
Open
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adds the ext:inspect command to retrieve currently running extension configuration.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ Detailed doc is [here](https://firebase.google.com/docs/cli/auth).
| **ext** | Display information on how to use ext commands and extensions installed to your project. |
| **ext:configure** | Configure an existing extension instance. |
| **ext:info** | Display information about an extension by name (extensionName@x.y.z for a specific version) |
| **ext:inspect** | Display the configuration of the currently running instances of installed extensions. |
| **ext:install** | Install an extension. |
| **ext:sdk:install** | Install and SDK for an extension so you can define the extension in a functions codebase. |
| **ext:list** | List all the extensions that are installed in your Firebase project. |
Expand Down
90 changes: 90 additions & 0 deletions src/commands/ext-inspect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { checkMinRequiredVersion } from "../checkMinRequiredVersion";
import { Command } from "../command";
import { needProjectId } from "../projectUtils";
import { ensureExtensionsApiEnabled } from "../extensions/extensionsHelper";
import { requirePermissions } from "../requirePermissions";
import { listInstances } from "../extensions/extensionsApi";
import { last, logLabeledBullet } from "../utils";
import { logPrefix } from "../extensions/extensionsHelper";
import { FirebaseError } from "../error";

import * as clc from "colorette";

export const command = new Command("ext:inspect [extensionInstanceId]")
Comment thread
Berlioz marked this conversation as resolved.
Outdated
.description("shows the current configuration for a currently installed Extension")
.option("--with-secrets", "shows the parameter name (but not value) of SECRET-type params")
.before(requirePermissions, ["firebaseextensions.instances.list"])
.before(requirePermissions, ["firebaseextensions.instances.get"])
.before(ensureExtensionsApiEnabled)
.before(checkMinRequiredVersion, "extMinVersion")
.action(async (wantInstanceId: string, options: any) => {
const listAll = !wantInstanceId;
const projectId = needProjectId(options);
const instances = await listInstances(projectId);
if (instances.length < 1) {
logLabeledBullet(
logPrefix,
`there are no extensions installed on project ${clc.bold(projectId)}.`,
);
return;
}

let found = false;
instances.forEach((instance) => {
const instanceId = last(instance.name.split("/")) ?? "";
if (!listAll && instanceId !== wantInstanceId) {
return;
}

found = true;
const liveParams = instance.config.params || [];
const liveSystemParams = instance.config.systemParams || [];
const specParams = instance.config.source.spec.params || [];
const specSystemParams = instance.config.source.spec.systemParams || [];

if (listAll) {
console.log("# " + instanceId);
}

// Every user param must be available, so we replicate the spec's default behavior if not present
specParams.forEach((specParam) => {
if (specParam.type === "SECRET") {
if (options.withSecrets) {
console.log("# " + specParam.param + " stored in Cloud Secret Manager");
}
} else if (specParam.param in liveParams) {
console.log(specParam.param + "=" + liveParams[specParam.param]);
} else if ("default" in specParam) {
console.log(specParam.param + "=" + specParam.default);
} else {
console.log(specParam.param + '=""');
}
});

// System params aren't necessarily defined in the spec, but we do respect any defaults
Object.entries(liveSystemParams).forEach(([sysParamName, sysParamValue]) => {
const renamed = sysParamName.replace(
"firebaseextensions.v1beta.function/",
"extensions_system_",
);
console.log(renamed + "=" + sysParamValue);
});
specSystemParams.forEach((specSystemParam) => {
if (specSystemParam.param in liveSystemParams) {
return;
}
if ("default" in specSystemParam) {
const renamed = specSystemParam.param.replace(
"firebaseextensions.v1beta.function/",
"extensions_system_",
);
console.log(renamed + "=" + specSystemParam.default);
}
});
});
if (!found) {
throw new FirebaseError(
`Could not find extension instance ${wantInstanceId} in active extensions`,
);
}
});
1 change: 1 addition & 0 deletions src/commands/ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const command = new Command("ext")
utils.logLabeledBullet(logPrefix, "list of extensions commands:");
const firebaseTools = require("../"); // eslint-disable-line @typescript-eslint/no-var-requires
const commandNames = [
"ext:inspect",
"ext:install",
"ext:info",
"ext:list",
Expand Down
1 change: 1 addition & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function load(client: CLIClient): CLIClient {
client.ext.configure = loadCommand("ext-configure");
client.ext.info = loadCommand("ext-info");
client.ext.export = loadCommand("ext-export");
client.ext.inspect = loadCommand("ext-inspect");
client.ext.install = loadCommand("ext-install");
client.ext.list = loadCommand("ext-list");
client.ext.uninstall = loadCommand("ext-uninstall");
Expand Down
Loading