firebase-tools 10.7.1 → 10.9.0
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/lib/commands/ext-configure.js +26 -15
- package/lib/commands/ext-export.js +14 -5
- package/lib/commands/ext-install.js +31 -2
- package/lib/commands/ext-update.js +17 -10
- package/lib/commands/functions-list.js +12 -20
- package/lib/commands/functions-secrets-set.js +1 -13
- package/lib/deploy/extensions/planner.js +12 -0
- package/lib/deploy/extensions/tasks.js +13 -0
- package/lib/deploy/functions/backend.js +47 -14
- package/lib/deploy/functions/build.js +28 -9
- package/lib/deploy/functions/checkIam.js +65 -53
- package/lib/deploy/functions/containerCleaner.js +8 -7
- package/lib/deploy/functions/functionsDeployHelper.js +1 -1
- package/lib/deploy/functions/prepare.js +42 -15
- package/lib/deploy/functions/pricing.js +2 -2
- package/lib/deploy/functions/release/executor.js +1 -1
- package/lib/deploy/functions/release/fabricator.js +66 -11
- package/lib/deploy/functions/release/index.js +0 -21
- package/lib/deploy/functions/runtimes/discovery/index.js +2 -1
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +13 -1
- package/lib/deploy/functions/runtimes/golang/index.js +3 -0
- package/lib/deploy/functions/runtimes/node/index.js +23 -20
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +108 -1
- package/lib/deploy/functions/services/storage.js +6 -12
- package/lib/deploy/functions/validate.js +80 -16
- package/lib/deploy/index.js +2 -1
- package/lib/emulator/auth/cloudFunctions.js +6 -2
- package/lib/emulator/auth/operations.js +0 -1
- package/lib/emulator/auth/server.js +8 -1
- package/lib/emulator/auth/state.js +27 -24
- package/lib/emulator/controller.js +10 -5
- package/lib/emulator/databaseEmulator.js +36 -3
- package/lib/emulator/downloadableEmulators.js +18 -34
- package/lib/emulator/extensionsEmulator.js +4 -1
- package/lib/emulator/functionsEmulator.js +6 -7
- package/lib/emulator/functionsEmulatorRuntime.js +1 -1
- package/lib/emulator/functionsEmulatorShared.js +3 -0
- package/lib/emulator/functionsEmulatorUtils.js +5 -1
- package/lib/emulator/storage/apis/firebase.js +26 -4
- package/lib/extensions/askUserForEventsConfig.js +97 -0
- package/lib/extensions/export.js +7 -0
- package/lib/extensions/extensionsApi.js +47 -7
- package/lib/extensions/manifest.js +1 -1
- package/lib/extensions/paramHelper.js +2 -0
- package/lib/extensions/updateHelper.js +7 -1
- package/lib/extensions/warnings.js +11 -4
- package/lib/frameworks/index.js +111 -0
- package/lib/functions/functionslog.js +4 -9
- package/lib/gcp/cloudfunctions.js +1 -1
- package/lib/gcp/cloudfunctionsv2.js +14 -9
- package/lib/gcp/serviceusage.js +24 -0
- package/lib/hosting/normalizedHostingConfigs.js +3 -0
- package/lib/previews.js +1 -1
- package/lib/serve/index.js +2 -1
- package/lib/throttler/throttler.js +2 -1
- package/npm-shrinkwrap.json +315 -534
- package/package.json +4 -4
- package/templates/extensions/javascript/package.lint.json +5 -5
- package/templates/extensions/javascript/package.nolint.json +3 -3
- package/templates/extensions/typescript/package.lint.json +8 -7
- package/templates/extensions/typescript/package.nolint.json +2 -1
- package/templates/init/functions/typescript/package.lint.json +1 -0
- package/templates/init/functions/typescript/package.nolint.json +5 -5
|
@@ -19,6 +19,7 @@ const refs = require("../extensions/refs");
|
|
|
19
19
|
const manifest = require("../extensions/manifest");
|
|
20
20
|
const functional_1 = require("../functional");
|
|
21
21
|
const paramHelper_1 = require("../extensions/paramHelper");
|
|
22
|
+
const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
|
|
22
23
|
marked.setOptions({
|
|
23
24
|
renderer: new TerminalRenderer(),
|
|
24
25
|
});
|
|
@@ -67,6 +68,15 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
|
|
|
67
68
|
instanceId,
|
|
68
69
|
reconfiguring: true,
|
|
69
70
|
});
|
|
71
|
+
const eventsConfig = spec.events
|
|
72
|
+
? await askUserForEventsConfig.askForEventsConfig(spec.events, "${param:PROJECT_ID}", instanceId)
|
|
73
|
+
: undefined;
|
|
74
|
+
if (eventsConfig) {
|
|
75
|
+
mutableParamsBindingOptions.EVENTARC_CHANNEL = { baseValue: eventsConfig.channel };
|
|
76
|
+
mutableParamsBindingOptions.ALLOWED_EVENT_TYPES = {
|
|
77
|
+
baseValue: eventsConfig.allowedEventTypes.join(","),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
70
80
|
const newParamOptions = Object.assign(Object.assign({}, (0, paramHelper_1.buildBindingOptionsWithBaseValue)(oldParamValues)), mutableParamsBindingOptions);
|
|
71
81
|
await manifest.writeToManifest([
|
|
72
82
|
{
|
|
@@ -83,20 +93,12 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
|
|
|
83
93
|
manifest.showPreviewWarning();
|
|
84
94
|
return;
|
|
85
95
|
}
|
|
96
|
+
if (!projectId) {
|
|
97
|
+
throw new error_1.FirebaseError(`Project ID must be provided when re-configuring an instance outside of local mode.`);
|
|
98
|
+
}
|
|
86
99
|
const spinner = ora(`Configuring ${clc.bold(instanceId)}. This usually takes 3 to 5 minutes...`);
|
|
87
100
|
try {
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
existingInstance = await extensionsApi.getInstance((0, projectUtils_1.needProjectId)({ projectId }), instanceId);
|
|
91
|
-
}
|
|
92
|
-
catch (err) {
|
|
93
|
-
if (err.status === 404) {
|
|
94
|
-
return utils.reject(`No extension instance ${instanceId} found in project ${projectId}.`, {
|
|
95
|
-
exit: 1,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
throw err;
|
|
99
|
-
}
|
|
101
|
+
const existingInstance = await extensionsApi.getInstance((0, projectUtils_1.needProjectId)({ projectId }), instanceId);
|
|
100
102
|
const paramSpecWithNewDefaults = paramHelper.getParamsWithCurrentValuesAsDefaults(existingInstance);
|
|
101
103
|
const immutableParams = _.remove(paramSpecWithNewDefaults, (param) => param.immutable);
|
|
102
104
|
const paramBindingOptions = await paramHelper.getParams({
|
|
@@ -121,12 +123,21 @@ exports.default = new command_1.Command("ext:configure <extensionInstanceId>")
|
|
|
121
123
|
: "To set a different value for this param") +
|
|
122
124
|
", uninstall the extension, then install a new instance of this extension.");
|
|
123
125
|
}
|
|
126
|
+
const pId = (0, projectUtils_1.needProjectId)({ projectId });
|
|
127
|
+
const spec = existingInstance ? existingInstance.config.source.spec : undefined;
|
|
128
|
+
const eventsConfig = spec.events
|
|
129
|
+
? await askUserForEventsConfig.askForEventsConfig(spec.events, pId, instanceId)
|
|
130
|
+
: undefined;
|
|
124
131
|
spinner.start();
|
|
125
|
-
const
|
|
126
|
-
projectId:
|
|
132
|
+
const configureOptions = {
|
|
133
|
+
projectId: pId,
|
|
127
134
|
instanceId,
|
|
128
135
|
params: paramBindings,
|
|
129
|
-
|
|
136
|
+
canEmitEvents: eventsConfig ? true : false,
|
|
137
|
+
eventarcChannel: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.channel,
|
|
138
|
+
allowedEventTypes: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.allowedEventTypes,
|
|
139
|
+
};
|
|
140
|
+
const res = await extensionsApi.configureInstance(configureOptions);
|
|
130
141
|
spinner.stop();
|
|
131
142
|
utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `successfully configured ${clc.bold(instanceId)}.`);
|
|
132
143
|
utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`You can view your reconfigured instance in the Firebase console: ${utils.consoleUrl((0, projectUtils_1.needProjectId)({ projectId }), `/extensions/instances/${instanceId}?tab=config`)}`));
|
|
@@ -43,11 +43,20 @@ module.exports = new command_1.Command("ext:export")
|
|
|
43
43
|
logger_1.logger.info("Exiting. No changes made.");
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
const manifestSpecs =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
const manifestSpecs = withRefSubbed.map((spec) => {
|
|
47
|
+
const paramCopy = Object.assign({}, spec.params);
|
|
48
|
+
if (spec.eventarcChannel) {
|
|
49
|
+
paramCopy.EVENTARC_CHANNEL = spec.eventarcChannel;
|
|
50
|
+
}
|
|
51
|
+
if (spec.allowedEventTypes) {
|
|
52
|
+
paramCopy.ALLOWED_EVENT_TYPES = spec.allowedEventTypes.join(",");
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
instanceId: spec.instanceId,
|
|
56
|
+
ref: spec.ref,
|
|
57
|
+
params: (0, paramHelper_1.buildBindingOptionsWithBaseValue)(paramCopy),
|
|
58
|
+
};
|
|
59
|
+
});
|
|
51
60
|
const existingConfig = manifest.loadConfig(options);
|
|
52
61
|
await manifest.writeToManifest(manifestSpecs, existingConfig, {
|
|
53
62
|
nonInteractive: options.nonInteractive,
|
|
@@ -6,6 +6,7 @@ const ora = require("ora");
|
|
|
6
6
|
const TerminalRenderer = require("marked-terminal");
|
|
7
7
|
const askUserForConsent = require("../extensions/askUserForConsent");
|
|
8
8
|
const displayExtensionInfo_1 = require("../extensions/displayExtensionInfo");
|
|
9
|
+
const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
|
|
9
10
|
const billingMigrationHelper_1 = require("../extensions/billingMigrationHelper");
|
|
10
11
|
const checkProjectBilling_1 = require("../extensions/checkProjectBilling");
|
|
11
12
|
const cloudbilling_1 = require("../gcp/cloudbilling");
|
|
@@ -166,6 +167,15 @@ async function installToManifest(options) {
|
|
|
166
167
|
paramsEnvPath,
|
|
167
168
|
instanceId,
|
|
168
169
|
});
|
|
170
|
+
const eventsConfig = spec.events
|
|
171
|
+
? await askUserForEventsConfig.askForEventsConfig(spec.events, "${param:PROJECT_ID}", instanceId)
|
|
172
|
+
: undefined;
|
|
173
|
+
if (eventsConfig) {
|
|
174
|
+
paramBindingOptions.EVENTARC_CHANNEL = { baseValue: eventsConfig.channel };
|
|
175
|
+
paramBindingOptions.ALLOWED_EVENT_TYPES = {
|
|
176
|
+
baseValue: eventsConfig.allowedEventTypes.join(","),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
169
179
|
const ref = extVersion ? refs.parse(extVersion.ref) : undefined;
|
|
170
180
|
await manifest.writeToManifest([
|
|
171
181
|
{
|
|
@@ -210,6 +220,12 @@ async function installExtension(options) {
|
|
|
210
220
|
reason: `To access and manage secrets which are used by this extension. By using this product you agree to the terms and conditions of the following license: https://console.cloud.google.com/tos?id=cloud&project=${projectId}`,
|
|
211
221
|
});
|
|
212
222
|
}
|
|
223
|
+
if (spec.events && spec.events.length > 0) {
|
|
224
|
+
apis.push({
|
|
225
|
+
apiName: "eventarc.googleapis.com",
|
|
226
|
+
reason: `When events are enabled, the Eventarc API is required to provision an event channel and publish events.`,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
213
229
|
if (apis.length) {
|
|
214
230
|
askUserForConsent.displayApis(spec.displayName || spec.name, projectId, apis);
|
|
215
231
|
const consented = await (0, extensionsHelper_1.confirm)({ nonInteractive, force, default: true });
|
|
@@ -248,6 +264,7 @@ async function installExtension(options) {
|
|
|
248
264
|
}
|
|
249
265
|
let paramBindingOptions;
|
|
250
266
|
let paramBindings;
|
|
267
|
+
let eventsConfig;
|
|
251
268
|
switch (choice) {
|
|
252
269
|
case "installNew":
|
|
253
270
|
instanceId = await (0, extensionsHelper_1.promptForValidInstanceId)(`${instanceId}-${(0, utils_1.getRandomString)(4)}`);
|
|
@@ -258,6 +275,9 @@ async function installExtension(options) {
|
|
|
258
275
|
paramsEnvPath,
|
|
259
276
|
instanceId,
|
|
260
277
|
});
|
|
278
|
+
eventsConfig = spec.events
|
|
279
|
+
? await askUserForEventsConfig.askForEventsConfig(spec.events, projectId, instanceId)
|
|
280
|
+
: undefined;
|
|
261
281
|
paramBindings = (0, paramHelper_1.getBaseParamBindings)(paramBindingOptions);
|
|
262
282
|
spinner.text = "Installing your extension instance. This usually takes 3 to 5 minutes...";
|
|
263
283
|
spinner.start();
|
|
@@ -267,6 +287,8 @@ async function installExtension(options) {
|
|
|
267
287
|
extensionSource: source,
|
|
268
288
|
extensionVersionRef: extVersion === null || extVersion === void 0 ? void 0 : extVersion.ref,
|
|
269
289
|
params: paramBindings,
|
|
290
|
+
allowedEventTypes: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.allowedEventTypes,
|
|
291
|
+
eventarcChannel: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.channel,
|
|
270
292
|
});
|
|
271
293
|
spinner.stop();
|
|
272
294
|
utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `Successfully installed your instance of ${clc.bold(spec.displayName || spec.name)}! ` +
|
|
@@ -280,16 +302,23 @@ async function installExtension(options) {
|
|
|
280
302
|
paramsEnvPath,
|
|
281
303
|
instanceId,
|
|
282
304
|
});
|
|
305
|
+
eventsConfig = spec.events
|
|
306
|
+
? await askUserForEventsConfig.askForEventsConfig(spec.events, projectId, instanceId)
|
|
307
|
+
: undefined;
|
|
283
308
|
paramBindings = (0, paramHelper_1.getBaseParamBindings)(paramBindingOptions);
|
|
284
309
|
spinner.text = "Updating your extension instance. This usually takes 3 to 5 minutes...";
|
|
285
310
|
spinner.start();
|
|
286
|
-
|
|
311
|
+
const updateOptions = {
|
|
287
312
|
projectId,
|
|
288
313
|
instanceId,
|
|
289
314
|
source,
|
|
315
|
+
canEmitEvents: eventsConfig ? true : false,
|
|
316
|
+
eventarcChannel: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.channel,
|
|
317
|
+
allowedEventTypes: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.allowedEventTypes,
|
|
290
318
|
extRef: extVersion === null || extVersion === void 0 ? void 0 : extVersion.ref,
|
|
291
319
|
params: paramBindings,
|
|
292
|
-
}
|
|
320
|
+
};
|
|
321
|
+
await (0, updateHelper_1.update)(updateOptions);
|
|
293
322
|
spinner.stop();
|
|
294
323
|
utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `Successfully updated your instance of ${clc.bold(spec.displayName || spec.name)}! ` +
|
|
295
324
|
`Its Instance ID is ${clc.bold(instanceId)}.`);
|
|
@@ -23,6 +23,7 @@ const requirePermissions_1 = require("../requirePermissions");
|
|
|
23
23
|
const utils = require("../utils");
|
|
24
24
|
const previews_1 = require("../previews");
|
|
25
25
|
const manifest = require("../extensions/manifest");
|
|
26
|
+
const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
|
|
26
27
|
marked.setOptions({
|
|
27
28
|
renderer: new TerminalRenderer(),
|
|
28
29
|
});
|
|
@@ -86,6 +87,15 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
86
87
|
nonInteractive: options.nonInteractive,
|
|
87
88
|
instanceId,
|
|
88
89
|
});
|
|
90
|
+
const eventsConfig = newExtensionVersion.spec.events
|
|
91
|
+
? await askUserForEventsConfig.askForEventsConfig(newExtensionVersion.spec.events, "${param:PROJECT_ID}", instanceId)
|
|
92
|
+
: undefined;
|
|
93
|
+
if (eventsConfig) {
|
|
94
|
+
newParamBindingOptions.EVENTARC_CHANNEL = { baseValue: eventsConfig.channel };
|
|
95
|
+
newParamBindingOptions.ALLOWED_EVENT_TYPES = {
|
|
96
|
+
baseValue: eventsConfig.allowedEventTypes.join(","),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
89
99
|
await manifest.writeToManifest([
|
|
90
100
|
{
|
|
91
101
|
instanceId,
|
|
@@ -104,16 +114,7 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
104
114
|
const spinner = ora(`Updating ${clc.bold(instanceId)}. This usually takes 3 to 5 minutes...`);
|
|
105
115
|
try {
|
|
106
116
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
existingInstance = await extensionsApi.getInstance(projectId, instanceId);
|
|
110
|
-
}
|
|
111
|
-
catch (err) {
|
|
112
|
-
if (err.status === 404) {
|
|
113
|
-
throw new error_1.FirebaseError(`Extension instance '${clc.bold(instanceId)}' not found in project '${clc.bold(projectId)}'.`);
|
|
114
|
-
}
|
|
115
|
-
throw err;
|
|
116
|
-
}
|
|
117
|
+
const existingInstance = await extensionsApi.getInstance(projectId, instanceId);
|
|
117
118
|
const existingSpec = existingInstance.config.source.spec;
|
|
118
119
|
if (existingInstance.config.source.state === "DELETED") {
|
|
119
120
|
throw new error_1.FirebaseError(`Instance '${clc.bold(instanceId)}' cannot be updated anymore because the underlying extension was unpublished from Firebase's registry of extensions. Going forward, you will only be able to re-configure or uninstall this instance.`);
|
|
@@ -214,11 +215,17 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
214
215
|
nonInteractive: options.nonInteractive,
|
|
215
216
|
instanceId,
|
|
216
217
|
});
|
|
218
|
+
const eventsConfig = newSpec.events
|
|
219
|
+
? await askUserForEventsConfig.askForEventsConfig(newSpec.events, projectId, instanceId)
|
|
220
|
+
: undefined;
|
|
217
221
|
const newParams = paramHelper.getBaseParamBindings(newParamBindings);
|
|
218
222
|
spinner.start();
|
|
219
223
|
const updateOptions = {
|
|
220
224
|
projectId,
|
|
221
225
|
instanceId,
|
|
226
|
+
canEmitEvents: eventsConfig ? true : false,
|
|
227
|
+
eventarcChannel: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.channel,
|
|
228
|
+
allowedEventTypes: eventsConfig === null || eventsConfig === void 0 ? void 0 : eventsConfig.allowedEventTypes,
|
|
222
229
|
};
|
|
223
230
|
if (newSourceName.includes("publisher")) {
|
|
224
231
|
updateOptions.extRef = refs.toExtensionVersionRef(refs.parse(newSourceName));
|
|
@@ -5,7 +5,6 @@ const error_1 = require("../error");
|
|
|
5
5
|
const projectUtils_1 = require("../projectUtils");
|
|
6
6
|
const requirePermissions_1 = require("../requirePermissions");
|
|
7
7
|
const backend = require("../deploy/functions/backend");
|
|
8
|
-
const previews_1 = require("../previews");
|
|
9
8
|
const logger_1 = require("../logger");
|
|
10
9
|
const Table = require("cli-table");
|
|
11
10
|
exports.default = new command_1.Command("functions:list")
|
|
@@ -18,28 +17,21 @@ exports.default = new command_1.Command("functions:list")
|
|
|
18
17
|
};
|
|
19
18
|
const existing = await backend.existingBackend(context);
|
|
20
19
|
const endpointsList = backend.allEndpoints(existing).sort(backend.compareFunctions);
|
|
21
|
-
const table =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
})
|
|
26
|
-
: new Table({
|
|
27
|
-
head: ["Function", "Trigger", "Location", "Memory", "Runtime"],
|
|
28
|
-
style: { head: ["yellow"] },
|
|
29
|
-
});
|
|
20
|
+
const table = new Table({
|
|
21
|
+
head: ["Function", "Version", "Trigger", "Location", "Memory", "Runtime"],
|
|
22
|
+
style: { head: ["yellow"] },
|
|
23
|
+
});
|
|
30
24
|
for (const endpoint of endpointsList) {
|
|
31
25
|
const trigger = backend.endpointTriggerType(endpoint);
|
|
32
26
|
const availableMemoryMb = endpoint.availableMemoryMb || "---";
|
|
33
|
-
const entry =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
]
|
|
42
|
-
: [endpoint.id, trigger, endpoint.region, availableMemoryMb, endpoint.runtime];
|
|
27
|
+
const entry = [
|
|
28
|
+
endpoint.id,
|
|
29
|
+
endpoint.platform === "gcfv2" ? "v2" : "v1",
|
|
30
|
+
trigger,
|
|
31
|
+
endpoint.region,
|
|
32
|
+
availableMemoryMb,
|
|
33
|
+
endpoint.runtime,
|
|
34
|
+
];
|
|
43
35
|
table.push(entry);
|
|
44
36
|
}
|
|
45
37
|
logger_1.logger.info(table.toString());
|
|
@@ -77,17 +77,5 @@ exports.default = new command_1.Command("functions:secrets:set <KEY>")
|
|
|
77
77
|
(0, utils_1.logBullet)(`Updated function ${e.id}(${e.region}).`);
|
|
78
78
|
return updated;
|
|
79
79
|
});
|
|
80
|
-
|
|
81
|
-
(0, utils_1.logBullet)(`Pruning stale secrets...`);
|
|
82
|
-
const prunedResult = await (0, secrets_1.pruneAndDestroySecrets)({ projectId, projectNumber }, updatedEndpoints);
|
|
83
|
-
if (prunedResult.destroyed.length > 0) {
|
|
84
|
-
(0, utils_1.logBullet)(`Detroyed unused secret versions: ${prunedResult.destroyed
|
|
85
|
-
.map((s) => `${s.secret}@${s.version}`)
|
|
86
|
-
.join(", ")}`);
|
|
87
|
-
}
|
|
88
|
-
if (prunedResult.erred.length > 0) {
|
|
89
|
-
(0, utils_1.logWarning)(`Failed to destroy unused secret versions:\n\t${prunedResult.erred
|
|
90
|
-
.map((err) => err.message)
|
|
91
|
-
.join("\n\t")}`);
|
|
92
|
-
}
|
|
80
|
+
await Promise.all(updateOps);
|
|
93
81
|
});
|
|
@@ -52,6 +52,8 @@ async function have(projectId) {
|
|
|
52
52
|
const dep = {
|
|
53
53
|
instanceId: i.name.split("/").pop(),
|
|
54
54
|
params: i.config.params,
|
|
55
|
+
allowedEventTypes: i.config.allowedEventTypes,
|
|
56
|
+
eventarcChannel: i.config.eventarcChannel,
|
|
55
57
|
};
|
|
56
58
|
if (i.config.extensionRef) {
|
|
57
59
|
const ref = refs.parse(i.config.extensionRef);
|
|
@@ -78,11 +80,19 @@ async function want(args) {
|
|
|
78
80
|
});
|
|
79
81
|
const autoPopulatedParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId, args.emulatorMode);
|
|
80
82
|
const subbedParams = (0, extensionsHelper_1.substituteParams)(params, autoPopulatedParams);
|
|
83
|
+
const allowedEventTypes = subbedParams.ALLOWED_EVENT_TYPES !== undefined
|
|
84
|
+
? subbedParams.ALLOWED_EVENT_TYPES.split(",").filter((e) => e !== "")
|
|
85
|
+
: undefined;
|
|
86
|
+
const eventarcChannel = subbedParams.EVENTARC_CHANNEL;
|
|
87
|
+
delete subbedParams["EVENTARC_CHANNEL"];
|
|
88
|
+
delete subbedParams["ALLOWED_EVENT_TYPES"];
|
|
81
89
|
if ((0, extensionsHelper_1.isLocalPath)(e[1])) {
|
|
82
90
|
instanceSpecs.push({
|
|
83
91
|
instanceId,
|
|
84
92
|
localPath: e[1],
|
|
85
93
|
params: subbedParams,
|
|
94
|
+
allowedEventTypes: allowedEventTypes,
|
|
95
|
+
eventarcChannel: eventarcChannel,
|
|
86
96
|
});
|
|
87
97
|
}
|
|
88
98
|
else {
|
|
@@ -92,6 +102,8 @@ async function want(args) {
|
|
|
92
102
|
instanceId,
|
|
93
103
|
ref,
|
|
94
104
|
params: subbedParams,
|
|
105
|
+
allowedEventTypes: allowedEventTypes,
|
|
106
|
+
eventarcChannel: eventarcChannel,
|
|
95
107
|
});
|
|
96
108
|
}
|
|
97
109
|
}
|
|
@@ -33,6 +33,8 @@ function createExtensionInstanceTask(projectId, instanceSpec, validateOnly = fal
|
|
|
33
33
|
instanceId: instanceSpec.instanceId,
|
|
34
34
|
params: instanceSpec.params,
|
|
35
35
|
extensionVersionRef: refs.toExtensionVersionRef(instanceSpec.ref),
|
|
36
|
+
allowedEventTypes: instanceSpec.allowedEventTypes,
|
|
37
|
+
eventarcChannel: instanceSpec.eventarcChannel,
|
|
36
38
|
validateOnly,
|
|
37
39
|
});
|
|
38
40
|
}
|
|
@@ -43,6 +45,8 @@ function createExtensionInstanceTask(projectId, instanceSpec, validateOnly = fal
|
|
|
43
45
|
instanceId: instanceSpec.instanceId,
|
|
44
46
|
params: instanceSpec.params,
|
|
45
47
|
extensionSource,
|
|
48
|
+
allowedEventTypes: instanceSpec.allowedEventTypes,
|
|
49
|
+
eventarcChannel: instanceSpec.eventarcChannel,
|
|
46
50
|
validateOnly,
|
|
47
51
|
});
|
|
48
52
|
}
|
|
@@ -67,6 +71,9 @@ function updateExtensionInstanceTask(projectId, instanceSpec, validateOnly = fal
|
|
|
67
71
|
instanceId: instanceSpec.instanceId,
|
|
68
72
|
extRef: refs.toExtensionVersionRef(instanceSpec.ref),
|
|
69
73
|
params: instanceSpec.params,
|
|
74
|
+
canEmitEvents: !!instanceSpec.allowedEventTypes,
|
|
75
|
+
allowedEventTypes: instanceSpec.allowedEventTypes,
|
|
76
|
+
eventarcChannel: instanceSpec.eventarcChannel,
|
|
70
77
|
validateOnly,
|
|
71
78
|
});
|
|
72
79
|
}
|
|
@@ -77,6 +84,9 @@ function updateExtensionInstanceTask(projectId, instanceSpec, validateOnly = fal
|
|
|
77
84
|
instanceId: instanceSpec.instanceId,
|
|
78
85
|
extensionSource,
|
|
79
86
|
validateOnly,
|
|
87
|
+
canEmitEvents: !!instanceSpec.allowedEventTypes,
|
|
88
|
+
allowedEventTypes: instanceSpec.allowedEventTypes,
|
|
89
|
+
eventarcChannel: instanceSpec.eventarcChannel,
|
|
80
90
|
});
|
|
81
91
|
}
|
|
82
92
|
else {
|
|
@@ -99,6 +109,9 @@ function configureExtensionInstanceTask(projectId, instanceSpec, validateOnly =
|
|
|
99
109
|
projectId,
|
|
100
110
|
instanceId: instanceSpec.instanceId,
|
|
101
111
|
params: instanceSpec.params,
|
|
112
|
+
canEmitEvents: !!instanceSpec.allowedEventTypes,
|
|
113
|
+
allowedEventTypes: instanceSpec.allowedEventTypes,
|
|
114
|
+
eventarcChannel: instanceSpec.eventarcChannel,
|
|
102
115
|
validateOnly,
|
|
103
116
|
});
|
|
104
117
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.compareFunctions = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.merge = exports.of = exports.empty = exports.isBlockingTriggered = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.AllFunctionsPlatforms = exports.secretVersionName = exports.SCHEDULED_FUNCTION_LABEL = exports.
|
|
3
|
+
exports.compareFunctions = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.merge = exports.of = exports.empty = exports.isBlockingTriggered = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.AllFunctionsPlatforms = exports.secretVersionName = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_CPU_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.DEFAULT_CONCURRENCY = exports.memoryToGen2Cpu = exports.memoryToGen1Cpu = exports.memoryOptionDisplayName = exports.AllMemoryOptions = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.endpointTriggerType = void 0;
|
|
4
4
|
const gcf = require("../../gcp/cloudfunctions");
|
|
5
5
|
const gcfV2 = require("../../gcp/cloudfunctionsv2");
|
|
6
|
+
const run = require("../../gcp/run");
|
|
6
7
|
const utils = require("../../utils");
|
|
7
8
|
const error_1 = require("../../error");
|
|
8
|
-
const previews_1 = require("../../previews");
|
|
9
9
|
const functional_1 = require("../../functional");
|
|
10
10
|
function endpointTriggerType(endpoint) {
|
|
11
11
|
if (isScheduleTriggered(endpoint)) {
|
|
@@ -37,7 +37,9 @@ exports.AllIngressSettings = [
|
|
|
37
37
|
"ALLOW_INTERNAL_ONLY",
|
|
38
38
|
"ALLOW_INTERNAL_AND_GCLB",
|
|
39
39
|
];
|
|
40
|
-
exports.AllMemoryOptions = [
|
|
40
|
+
exports.AllMemoryOptions = [
|
|
41
|
+
128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
|
|
42
|
+
];
|
|
41
43
|
function memoryOptionDisplayName(option) {
|
|
42
44
|
return {
|
|
43
45
|
128: "128MB",
|
|
@@ -47,11 +49,42 @@ function memoryOptionDisplayName(option) {
|
|
|
47
49
|
2048: "2GB",
|
|
48
50
|
4096: "4GB",
|
|
49
51
|
8192: "8GB",
|
|
52
|
+
16384: "16GB",
|
|
53
|
+
32768: "32GB",
|
|
50
54
|
}[option];
|
|
51
55
|
}
|
|
52
56
|
exports.memoryOptionDisplayName = memoryOptionDisplayName;
|
|
57
|
+
function memoryToGen1Cpu(memory) {
|
|
58
|
+
return {
|
|
59
|
+
128: 0.0833,
|
|
60
|
+
256: 0.1666,
|
|
61
|
+
512: 0.3333,
|
|
62
|
+
1024: 0.5833,
|
|
63
|
+
2048: 1,
|
|
64
|
+
4096: 2,
|
|
65
|
+
8192: 2,
|
|
66
|
+
16384: 3,
|
|
67
|
+
32768: 4,
|
|
68
|
+
}[memory];
|
|
69
|
+
}
|
|
70
|
+
exports.memoryToGen1Cpu = memoryToGen1Cpu;
|
|
71
|
+
function memoryToGen2Cpu(memory) {
|
|
72
|
+
return {
|
|
73
|
+
128: 1,
|
|
74
|
+
256: 1,
|
|
75
|
+
512: 1,
|
|
76
|
+
1024: 1,
|
|
77
|
+
2048: 1,
|
|
78
|
+
4096: 2,
|
|
79
|
+
8192: 2,
|
|
80
|
+
16384: 3,
|
|
81
|
+
32768: 4,
|
|
82
|
+
}[memory];
|
|
83
|
+
}
|
|
84
|
+
exports.memoryToGen2Cpu = memoryToGen2Cpu;
|
|
85
|
+
exports.DEFAULT_CONCURRENCY = 80;
|
|
53
86
|
exports.DEFAULT_MEMORY = 256;
|
|
54
|
-
exports.
|
|
87
|
+
exports.MIN_CPU_FOR_CONCURRENCY = 1;
|
|
55
88
|
exports.SCHEDULED_FUNCTION_LABEL = Object.freeze({ deployment: "firebase-schedule" });
|
|
56
89
|
function secretVersionName(s) {
|
|
57
90
|
var _a;
|
|
@@ -158,12 +191,19 @@ async function loadExistingBackend(ctx) {
|
|
|
158
191
|
ctx.existingBackend.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
159
192
|
}
|
|
160
193
|
ctx.unreachableRegions.gcfV1 = gcfV1Results.unreachable;
|
|
161
|
-
if (!previews_1.previews.functionsv2) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
194
|
let gcfV2Results;
|
|
165
195
|
try {
|
|
166
196
|
gcfV2Results = await gcfV2.listAllFunctions(ctx.projectId);
|
|
197
|
+
const runResults = await Promise.all(gcfV2Results.functions.map((fn) => run.getService(fn.serviceConfig.service)));
|
|
198
|
+
for (const [apiFunction, runService] of (0, functional_1.zip)(gcfV2Results.functions, runResults)) {
|
|
199
|
+
const endpoint = gcfV2.endpointFromFunction(apiFunction);
|
|
200
|
+
endpoint.concurrency = runService.spec.template.spec.containerConcurrency || 1;
|
|
201
|
+
endpoint.cpu = +runService.spec.template.spec.containers[0].resources.limits.cpu;
|
|
202
|
+
ctx.existingBackend.endpoints[endpoint.region] =
|
|
203
|
+
ctx.existingBackend.endpoints[endpoint.region] || {};
|
|
204
|
+
ctx.existingBackend.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
205
|
+
}
|
|
206
|
+
ctx.unreachableRegions.gcfV2 = gcfV2Results.unreachable;
|
|
167
207
|
}
|
|
168
208
|
catch (err) {
|
|
169
209
|
if (err.status === 404 && ((_a = err.message) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes("method not found"))) {
|
|
@@ -171,13 +211,6 @@ async function loadExistingBackend(ctx) {
|
|
|
171
211
|
}
|
|
172
212
|
throw err;
|
|
173
213
|
}
|
|
174
|
-
for (const apiFunction of gcfV2Results.functions) {
|
|
175
|
-
const endpoint = gcfV2.endpointFromFunction(apiFunction);
|
|
176
|
-
ctx.existingBackend.endpoints[endpoint.region] =
|
|
177
|
-
ctx.existingBackend.endpoints[endpoint.region] || {};
|
|
178
|
-
ctx.existingBackend.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
179
|
-
}
|
|
180
|
-
ctx.unreachableRegions.gcfV2 = gcfV2Results.unreachable;
|
|
181
214
|
}
|
|
182
215
|
async function checkAvailability(context, want) {
|
|
183
216
|
const ctx = context;
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveBackend = void 0;
|
|
3
|
+
exports.resolveBackend = exports.of = exports.empty = void 0;
|
|
4
4
|
const backend = require("./backend");
|
|
5
5
|
const proto = require("../../gcp/proto");
|
|
6
6
|
const api = require("../../.../../api");
|
|
7
7
|
const error_1 = require("../../error");
|
|
8
8
|
const functional_1 = require("../../functional");
|
|
9
|
+
function empty() {
|
|
10
|
+
return {
|
|
11
|
+
requiredAPIs: [],
|
|
12
|
+
endpoints: {},
|
|
13
|
+
params: [],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
exports.empty = empty;
|
|
17
|
+
function of(endpoints) {
|
|
18
|
+
const build = empty();
|
|
19
|
+
build.endpoints = endpoints;
|
|
20
|
+
return build;
|
|
21
|
+
}
|
|
22
|
+
exports.of = of;
|
|
9
23
|
function resolveInt(from) {
|
|
10
24
|
if (from == null) {
|
|
11
25
|
return 0;
|
|
@@ -36,7 +50,15 @@ function resolveBoolean(from) {
|
|
|
36
50
|
function isMemoryOption(value) {
|
|
37
51
|
return value == null || [128, 256, 512, 1024, 2048, 4096, 8192].includes(value);
|
|
38
52
|
}
|
|
39
|
-
function resolveBackend(build) {
|
|
53
|
+
function resolveBackend(build, userEnvs) {
|
|
54
|
+
for (const param of build.params) {
|
|
55
|
+
const expectedEnv = param.param;
|
|
56
|
+
if (!userEnvs.hasOwnProperty(expectedEnv)) {
|
|
57
|
+
throw new error_1.FirebaseError("Build specified parameter " +
|
|
58
|
+
expectedEnv +
|
|
59
|
+
" but it was not present in the user dotenv files");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
40
62
|
const bkEndpoints = [];
|
|
41
63
|
for (const endpointId of Object.keys(build.endpoints)) {
|
|
42
64
|
const endpoint = build.endpoints[endpointId];
|
|
@@ -59,23 +81,20 @@ function resolveBackend(build) {
|
|
|
59
81
|
else {
|
|
60
82
|
timeout = 60;
|
|
61
83
|
}
|
|
62
|
-
const bkEndpoint = Object.assign({ id: endpointId, project:
|
|
84
|
+
const bkEndpoint = Object.assign({ id: endpointId, project: endpoint.project, region: region, entryPoint: endpoint.entryPoint, platform: endpoint.platform, runtime: endpoint.runtime, timeoutSeconds: timeout }, trigger);
|
|
63
85
|
proto.renameIfPresent(bkEndpoint, endpoint, "maxInstances", "maxInstances", resolveInt);
|
|
64
86
|
proto.renameIfPresent(bkEndpoint, endpoint, "minInstances", "minInstances", resolveInt);
|
|
65
87
|
proto.renameIfPresent(bkEndpoint, endpoint, "concurrency", "concurrency", resolveInt);
|
|
66
|
-
proto.copyIfPresent(bkEndpoint, endpoint, "ingressSettings");
|
|
88
|
+
proto.copyIfPresent(bkEndpoint, endpoint, "ingressSettings", "availableMemoryMb", "environmentVariables", "labels");
|
|
67
89
|
if (endpoint.vpc) {
|
|
68
90
|
bkEndpoint.vpc = {
|
|
69
|
-
connector: resolveString(endpoint.vpc.connector),
|
|
70
|
-
egressSettings: endpoint.vpc.egressSettings,
|
|
91
|
+
connector: resolveString(endpoint.vpc.connector).replace("$REGION", region),
|
|
71
92
|
};
|
|
93
|
+
proto.copyIfPresent(bkEndpoint.vpc, endpoint.vpc, "egressSettings");
|
|
72
94
|
}
|
|
73
95
|
if (endpoint.serviceAccount) {
|
|
74
96
|
bkEndpoint.serviceAccountEmail = endpoint.serviceAccount;
|
|
75
97
|
}
|
|
76
|
-
else {
|
|
77
|
-
bkEndpoint.serviceAccountEmail = "default";
|
|
78
|
-
}
|
|
79
98
|
bkEndpoints.push(bkEndpoint);
|
|
80
99
|
}
|
|
81
100
|
}
|