forked from dienianindya/gsi_ess_mobile
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
320 lines
13 KiB
320 lines
13 KiB
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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.isValidMemoryOption = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.endpointTriggerType = void 0;
|
|
const gcf = require("../../gcp/cloudfunctions");
|
|
const gcfV2 = require("../../gcp/cloudfunctionsv2");
|
|
const run = require("../../gcp/run");
|
|
const utils = require("../../utils");
|
|
const error_1 = require("../../error");
|
|
const functional_1 = require("../../functional");
|
|
function endpointTriggerType(endpoint) {
|
|
if (isScheduleTriggered(endpoint)) {
|
|
return "scheduled";
|
|
}
|
|
else if (isHttpsTriggered(endpoint)) {
|
|
return "https";
|
|
}
|
|
else if (isCallableTriggered(endpoint)) {
|
|
return "callable";
|
|
}
|
|
else if (isEventTriggered(endpoint)) {
|
|
return endpoint.eventTrigger.eventType;
|
|
}
|
|
else if (isTaskQueueTriggered(endpoint)) {
|
|
return "taskQueue";
|
|
}
|
|
else if (isBlockingTriggered(endpoint)) {
|
|
return endpoint.blockingTrigger.eventType;
|
|
}
|
|
else {
|
|
throw new Error("Unexpected trigger type for endpoint " + JSON.stringify(endpoint));
|
|
}
|
|
}
|
|
exports.endpointTriggerType = endpointTriggerType;
|
|
exports.AllVpcEgressSettings = ["PRIVATE_RANGES_ONLY", "ALL_TRAFFIC"];
|
|
exports.AllIngressSettings = [
|
|
"ALLOW_ALL",
|
|
"ALLOW_INTERNAL_ONLY",
|
|
"ALLOW_INTERNAL_AND_GCLB",
|
|
];
|
|
const allMemoryOptions = [128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768];
|
|
function isValidMemoryOption(mem) {
|
|
return allMemoryOptions.includes(mem);
|
|
}
|
|
exports.isValidMemoryOption = isValidMemoryOption;
|
|
function memoryOptionDisplayName(option) {
|
|
return {
|
|
128: "128MB",
|
|
256: "256MB",
|
|
512: "512MB",
|
|
1024: "1GB",
|
|
2048: "2GB",
|
|
4096: "4GB",
|
|
8192: "8GB",
|
|
16384: "16GB",
|
|
32768: "32GB",
|
|
}[option];
|
|
}
|
|
exports.memoryOptionDisplayName = memoryOptionDisplayName;
|
|
function memoryToGen1Cpu(memory) {
|
|
return {
|
|
128: 0.0833,
|
|
256: 0.1666,
|
|
512: 0.3333,
|
|
1024: 0.5833,
|
|
2048: 1,
|
|
4096: 2,
|
|
8192: 2,
|
|
16384: 4,
|
|
32768: 8,
|
|
}[memory];
|
|
}
|
|
exports.memoryToGen1Cpu = memoryToGen1Cpu;
|
|
function memoryToGen2Cpu(memory) {
|
|
return {
|
|
128: 1,
|
|
256: 1,
|
|
512: 1,
|
|
1024: 1,
|
|
2048: 1,
|
|
4096: 2,
|
|
8192: 2,
|
|
16384: 4,
|
|
32768: 8,
|
|
}[memory];
|
|
}
|
|
exports.memoryToGen2Cpu = memoryToGen2Cpu;
|
|
exports.DEFAULT_CONCURRENCY = 80;
|
|
exports.DEFAULT_MEMORY = 256;
|
|
exports.MIN_CPU_FOR_CONCURRENCY = 1;
|
|
exports.SCHEDULED_FUNCTION_LABEL = Object.freeze({ deployment: "firebase-schedule" });
|
|
function secretVersionName(s) {
|
|
var _a;
|
|
return `projects/${s.projectId}/secrets/${s.secret}/versions/${(_a = s.version) !== null && _a !== void 0 ? _a : "latest"}`;
|
|
}
|
|
exports.secretVersionName = secretVersionName;
|
|
exports.AllFunctionsPlatforms = ["gcfv1", "gcfv2"];
|
|
function isHttpsTriggered(triggered) {
|
|
return {}.hasOwnProperty.call(triggered, "httpsTrigger");
|
|
}
|
|
exports.isHttpsTriggered = isHttpsTriggered;
|
|
function isCallableTriggered(triggered) {
|
|
return {}.hasOwnProperty.call(triggered, "callableTrigger");
|
|
}
|
|
exports.isCallableTriggered = isCallableTriggered;
|
|
function isEventTriggered(triggered) {
|
|
return {}.hasOwnProperty.call(triggered, "eventTrigger");
|
|
}
|
|
exports.isEventTriggered = isEventTriggered;
|
|
function isScheduleTriggered(triggered) {
|
|
return {}.hasOwnProperty.call(triggered, "scheduleTrigger");
|
|
}
|
|
exports.isScheduleTriggered = isScheduleTriggered;
|
|
function isTaskQueueTriggered(triggered) {
|
|
return {}.hasOwnProperty.call(triggered, "taskQueueTrigger");
|
|
}
|
|
exports.isTaskQueueTriggered = isTaskQueueTriggered;
|
|
function isBlockingTriggered(triggered) {
|
|
return {}.hasOwnProperty.call(triggered, "blockingTrigger");
|
|
}
|
|
exports.isBlockingTriggered = isBlockingTriggered;
|
|
function empty() {
|
|
return {
|
|
requiredAPIs: [],
|
|
endpoints: {},
|
|
environmentVariables: {},
|
|
};
|
|
}
|
|
exports.empty = empty;
|
|
function of(...endpoints) {
|
|
const bkend = Object.assign({}, empty());
|
|
for (const endpoint of endpoints) {
|
|
bkend.endpoints[endpoint.region] = bkend.endpoints[endpoint.region] || {};
|
|
if (bkend.endpoints[endpoint.region][endpoint.id]) {
|
|
throw new Error("Trying to create a backend with the same endpiont twice");
|
|
}
|
|
bkend.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
}
|
|
return bkend;
|
|
}
|
|
exports.of = of;
|
|
function merge(...backends) {
|
|
const merged = of(...(0, functional_1.flattenArray)(backends.map((b) => allEndpoints(b))));
|
|
const apiToReasons = {};
|
|
for (const b of backends) {
|
|
for (const { api, reason } of b.requiredAPIs) {
|
|
const reasons = apiToReasons[api] || new Set();
|
|
if (reason) {
|
|
reasons.add(reason);
|
|
}
|
|
apiToReasons[api] = reasons;
|
|
}
|
|
merged.environmentVariables = Object.assign(Object.assign({}, merged.environmentVariables), b.environmentVariables);
|
|
}
|
|
for (const [api, reasons] of Object.entries(apiToReasons)) {
|
|
merged.requiredAPIs.push({ api, reason: Array.from(reasons).join(" ") });
|
|
}
|
|
return merged;
|
|
}
|
|
exports.merge = merge;
|
|
function isEmptyBackend(backend) {
|
|
return (Object.keys(backend.requiredAPIs).length === 0 && Object.keys(backend.endpoints).length === 0);
|
|
}
|
|
exports.isEmptyBackend = isEmptyBackend;
|
|
function functionName(cloudFunction) {
|
|
return `projects/${cloudFunction.project}/locations/${cloudFunction.region}/functions/${cloudFunction.id}`;
|
|
}
|
|
exports.functionName = functionName;
|
|
function scheduleIdForFunction(cloudFunction) {
|
|
return `firebase-schedule-${cloudFunction.id}-${cloudFunction.region}`;
|
|
}
|
|
exports.scheduleIdForFunction = scheduleIdForFunction;
|
|
async function existingBackend(context, forceRefresh) {
|
|
if (!context.loadedExistingBackend || forceRefresh) {
|
|
await loadExistingBackend(context);
|
|
}
|
|
return context.existingBackend;
|
|
}
|
|
exports.existingBackend = existingBackend;
|
|
async function loadExistingBackend(ctx) {
|
|
var _a;
|
|
ctx.loadedExistingBackend = true;
|
|
ctx.existingBackend = Object.assign({}, empty());
|
|
ctx.unreachableRegions = {
|
|
gcfV1: [],
|
|
gcfV2: [],
|
|
};
|
|
const gcfV1Results = await gcf.listAllFunctions(ctx.projectId);
|
|
for (const apiFunction of gcfV1Results.functions) {
|
|
const endpoint = gcf.endpointFromFunction(apiFunction);
|
|
ctx.existingBackend.endpoints[endpoint.region] =
|
|
ctx.existingBackend.endpoints[endpoint.region] || {};
|
|
ctx.existingBackend.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
}
|
|
ctx.unreachableRegions.gcfV1 = gcfV1Results.unreachable;
|
|
let gcfV2Results;
|
|
try {
|
|
gcfV2Results = await gcfV2.listAllFunctions(ctx.projectId);
|
|
const runResults = await Promise.all(gcfV2Results.functions.map((fn) => run.getService(fn.serviceConfig.service)));
|
|
for (const [apiFunction, runService] of (0, functional_1.zip)(gcfV2Results.functions, runResults)) {
|
|
const endpoint = gcfV2.endpointFromFunction(apiFunction);
|
|
endpoint.concurrency = runService.spec.template.spec.containerConcurrency || 1;
|
|
endpoint.cpu = +runService.spec.template.spec.containers[0].resources.limits.cpu;
|
|
ctx.existingBackend.endpoints[endpoint.region] =
|
|
ctx.existingBackend.endpoints[endpoint.region] || {};
|
|
ctx.existingBackend.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
}
|
|
ctx.unreachableRegions.gcfV2 = gcfV2Results.unreachable;
|
|
}
|
|
catch (err) {
|
|
if (err.status === 404 && ((_a = err.message) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes("method not found"))) {
|
|
return;
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
async function checkAvailability(context, want) {
|
|
var _a, _b, _c, _d;
|
|
if (!context.loadedExistingBackend) {
|
|
await loadExistingBackend(context);
|
|
}
|
|
const gcfV1Regions = new Set();
|
|
const gcfV2Regions = new Set();
|
|
for (const ep of allEndpoints(want)) {
|
|
if (ep.platform === "gcfv1") {
|
|
gcfV1Regions.add(ep.region);
|
|
}
|
|
else {
|
|
gcfV2Regions.add(ep.region);
|
|
}
|
|
}
|
|
const neededUnreachableV1 = (_a = context.unreachableRegions) === null || _a === void 0 ? void 0 : _a.gcfV1.filter((region) => gcfV1Regions.has(region));
|
|
const neededUnreachableV2 = (_b = context.unreachableRegions) === null || _b === void 0 ? void 0 : _b.gcfV2.filter((region) => gcfV2Regions.has(region));
|
|
if (neededUnreachableV1 === null || neededUnreachableV1 === void 0 ? void 0 : neededUnreachableV1.length) {
|
|
throw new error_1.FirebaseError("The following Cloud Functions regions are currently unreachable:\n\t" +
|
|
neededUnreachableV1.join("\n\t") +
|
|
"\nThis deployment contains functions in those regions. Please try again in a few minutes, or exclude these regions from your deployment.");
|
|
}
|
|
if (neededUnreachableV2 === null || neededUnreachableV2 === void 0 ? void 0 : neededUnreachableV2.length) {
|
|
throw new error_1.FirebaseError("The following Cloud Functions V2 regions are currently unreachable:\n\t" +
|
|
neededUnreachableV2.join("\n\t") +
|
|
"\nThis deployment contains functions in those regions. Please try again in a few minutes, or exclude these regions from your deployment.");
|
|
}
|
|
if ((_c = context.unreachableRegions) === null || _c === void 0 ? void 0 : _c.gcfV1.length) {
|
|
utils.logLabeledWarning("functions", "The following Cloud Functions regions are currently unreachable:\n" +
|
|
context.unreachableRegions.gcfV1.join("\n") +
|
|
"\nCloud Functions in these regions won't be deleted.");
|
|
}
|
|
if ((_d = context.unreachableRegions) === null || _d === void 0 ? void 0 : _d.gcfV2.length) {
|
|
utils.logLabeledWarning("functions", "The following Cloud Functions V2 regions are currently unreachable:\n" +
|
|
context.unreachableRegions.gcfV2.join("\n") +
|
|
"\nCloud Functions in these regions won't be deleted.");
|
|
}
|
|
}
|
|
exports.checkAvailability = checkAvailability;
|
|
function allEndpoints(backend) {
|
|
return Object.values(backend.endpoints).reduce((accum, perRegion) => {
|
|
return [...accum, ...Object.values(perRegion)];
|
|
}, []);
|
|
}
|
|
exports.allEndpoints = allEndpoints;
|
|
function someEndpoint(backend, predicate) {
|
|
for (const endpoints of Object.values(backend.endpoints)) {
|
|
if (Object.values(endpoints).some(predicate)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
exports.someEndpoint = someEndpoint;
|
|
function findEndpoint(backend, predicate) {
|
|
for (const endpoints of Object.values(backend.endpoints)) {
|
|
const endpoint = Object.values(endpoints).find(predicate);
|
|
if (endpoint)
|
|
return endpoint;
|
|
}
|
|
}
|
|
exports.findEndpoint = findEndpoint;
|
|
function matchingBackend(backend, predicate) {
|
|
const filtered = Object.assign(Object.assign({}, backend), { endpoints: {} });
|
|
for (const endpoint of allEndpoints(backend)) {
|
|
if (!predicate(endpoint)) {
|
|
continue;
|
|
}
|
|
filtered.endpoints[endpoint.region] = filtered.endpoints[endpoint.region] || {};
|
|
filtered.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
}
|
|
return filtered;
|
|
}
|
|
exports.matchingBackend = matchingBackend;
|
|
function regionalEndpoints(backend, region) {
|
|
return backend.endpoints[region] ? Object.values(backend.endpoints[region]) : [];
|
|
}
|
|
exports.regionalEndpoints = regionalEndpoints;
|
|
const hasEndpoint = (backend) => (endpoint) => {
|
|
return (!!backend.endpoints[endpoint.region] && !!backend.endpoints[endpoint.region][endpoint.id]);
|
|
};
|
|
exports.hasEndpoint = hasEndpoint;
|
|
const missingEndpoint = (backend) => (endpoint) => {
|
|
return !(0, exports.hasEndpoint)(backend)(endpoint);
|
|
};
|
|
exports.missingEndpoint = missingEndpoint;
|
|
function compareFunctions(left, right) {
|
|
if (left.platform !== right.platform) {
|
|
return right.platform < left.platform ? -1 : 1;
|
|
}
|
|
if (left.region < right.region) {
|
|
return -1;
|
|
}
|
|
if (left.region > right.region) {
|
|
return 1;
|
|
}
|
|
if (left.id < right.id) {
|
|
return -1;
|
|
}
|
|
if (left.id > right.id) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
exports.compareFunctions = compareFunctions;
|