Skip to content

Commit

Permalink
Load secrets when emulating functions with --inspect-function flag (#…
Browse files Browse the repository at this point in the history
…5308)

* Load secrets when emulating functions with --inspect-function flag

* add changeloag
  • Loading branch information
joehan committed Dec 7, 2022
1 parent 27def0a commit 97ce550
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
@@ -1 +1,2 @@
- Add support for Firestore TTL (#5267)
- Fix bug where secrets were not loaded when emulating functions with `--inpsect-functions`. (#4605)
2 changes: 1 addition & 1 deletion src/emulator/extensionsEmulator.ts
Expand Up @@ -234,7 +234,7 @@ export class ExtensionsEmulator implements EmulatorInstance {
const emulatableBackend: EmulatableBackend = {
functionsDir,
env: nonSecretEnv,
codebase: "",
codebase: instance.instanceId, // Give each extension its own codebase name so that they don't share workerPools.
secretEnv: secretEnvVariables,
predefinedTriggers: extensionTriggers,
nodeMajorVersion: nodeMajorVersion,
Expand Down
84 changes: 48 additions & 36 deletions src/emulator/functionsEmulator.ts
Expand Up @@ -653,10 +653,22 @@ export class FunctionsEmulator implements EmulatorInstance {
this.logger.logLabeled("SUCCESS", `functions[${definition.id}]`, msg);
}
}

// In debug mode, we eagerly start a runtime process to allow debuggers to attach
// In debug mode, we eagerly start the runtime processes to allow debuggers to attach
// before invoking a function.
if (this.args.debugPort) {
// Since we're about to start a runtime to be shared by all the functions in this codebase,
// we need to make sure it has all the secrets used by any function in the codebase.
emulatableBackend.secretEnv = Object.values(
toSetup.reduce(
(acc: Record<string, backend.SecretEnvVar>, curr: EmulatedTriggerDefinition) => {
for (const secret of curr.secretEnvironmentVariables || []) {
acc[secret.key] = secret;
}
return acc;
},
{}
)
);
await this.startRuntime(emulatableBackend);
}
}
Expand Down Expand Up @@ -1206,42 +1218,42 @@ export class FunctionsEmulator implements EmulatorInstance {
);
}
}
// Note - if trigger is undefined, we are loading in 'sequential' mode.
// In that case, we need to load all secrets for that codebase.
const secrets: backend.SecretEnvVar[] =
trigger?.secretEnvironmentVariables || backend.secretEnv;
const accesses = secrets
.filter((s) => !secretEnvs[s.key])
.map(async (s) => {
this.logger.logLabeled("INFO", "functions", `Trying to access secret ${s.secret}@latest`);
const value = await accessSecretVersion(
this.getProjectId(),
s.secret,
s.version ?? "latest"
);
return [s.key, value];
});
const accessResults = await allSettled(accesses);

if (trigger) {
const secrets: backend.SecretEnvVar[] = trigger.secretEnvironmentVariables || [];
const accesses = secrets
.filter((s) => !secretEnvs[s.key])
.map(async (s) => {
this.logger.logLabeled("INFO", "functions", `Trying to access secret ${s.secret}@latest`);
const value = await accessSecretVersion(
this.getProjectId(),
s.secret,
s.version ?? "latest"
);
return [s.key, value];
});
const accessResults = await allSettled(accesses);

const errs: string[] = [];
for (const result of accessResults) {
if (result.status === "rejected") {
errs.push(result.reason as string);
} else {
const [k, v] = result.value;
secretEnvs[k] = v;
}
const errs: string[] = [];
for (const result of accessResults) {
if (result.status === "rejected") {
errs.push(result.reason as string);
} else {
const [k, v] = result.value;
secretEnvs[k] = v;
}
}

if (errs.length > 0) {
this.logger.logLabeled(
"ERROR",
"functions",
"Unable to access secret environment variables from Google Cloud Secret Manager. " +
"Make sure the credential used for the Functions Emulator have access " +
`or provide override values in ${secretPath}:\n\t` +
errs.join("\n\t")
);
}
if (errs.length > 0) {
this.logger.logLabeled(
"ERROR",
"functions",
"Unable to access secret environment variables from Google Cloud Secret Manager. " +
"Make sure the credential used for the Functions Emulator have access " +
`or provide override values in ${secretPath}:\n\t` +
errs.join("\n\t")
);
}

return secretEnvs;
Expand Down Expand Up @@ -1280,7 +1292,6 @@ export class FunctionsEmulator implements EmulatorInstance {
"See https://yarnpkg.com/getting-started/migration#step-by-step for more information."
);
}

const runtimeEnv = this.getRuntimeEnvs(backend, trigger);
const secretEnvs = await this.resolveSecretEnvs(backend, trigger);
const socketPath = getTemporarySocketPath();
Expand All @@ -1307,6 +1318,7 @@ export class FunctionsEmulator implements EmulatorInstance {
instanceId: backend.extensionInstanceId,
ref: backend.extensionVersion?.ref,
};

const pool = this.workerPools[backend.codebase];
const worker = pool.addWorker(trigger?.id, runtime, extensionLogInfo);
await worker.waitForSocketReady();
Expand Down
2 changes: 1 addition & 1 deletion src/test/emulators/extensionsEmulator.spec.ts
Expand Up @@ -119,7 +119,7 @@ describe("Extensions Emulator", () => {
],
extension: TEST_EXTENSION,
extensionVersion: TEST_EXTENSION_VERSION,
codebase: "",
codebase: "ext-test",
},
},
];
Expand Down

0 comments on commit 97ce550

Please sign in to comment.