Skip to content

Commit 64b3572

Browse files
committed
Backend is stack, extract APIs.
1 parent 208dc23 commit 64b3572

File tree

4 files changed

+68
-38
lines changed

4 files changed

+68
-38
lines changed

spec/runtime/loader.spec.ts

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import * as path from 'path';
33
import * as semver from 'semver';
44

55
import * as loader from '../../src/runtime/loader';
6-
import { ManifestBackend, ManifestEndpoint } from '../../src/runtime/manifest';
6+
import {
7+
ManifestStack,
8+
ManifestEndpoint,
9+
ManifestRequiredAPI,
10+
} from '../../src/runtime/manifest';
711

812
function annotatedFn(
913
endpoint: ManifestEndpoint
@@ -27,15 +31,16 @@ const EVENT_ENDPOINT = {
2731
},
2832
};
2933

30-
describe('extractEndpoints', () => {
31-
it('extracts endpoints from a simple module', () => {
34+
describe('extractStack', () => {
35+
it('extracts stack from a simple module', () => {
3236
const module = {
3337
fn1: annotatedFn(HTTP_ENDPOINT),
3438
fn2: annotatedFn(EVENT_ENDPOINT),
3539
};
3640

3741
const endpoints: Record<string, ManifestEndpoint> = {};
38-
loader.extractEndpoints(module, endpoints);
42+
const requiredAPIs: Record<string, ManifestRequiredAPI> = {};
43+
loader.extractStack(module, endpoints, requiredAPIs);
3944
expect(endpoints).to.be.deep.equal({
4045
fn1: {
4146
entryPoint: 'fn1',
@@ -48,7 +53,7 @@ describe('extractEndpoints', () => {
4853
});
4954
});
5055

51-
it('extracts endpoints from a module with group functions', () => {
56+
it('extracts stack from a module with group functions', () => {
5257
const module = {
5358
fn1: annotatedFn(HTTP_ENDPOINT),
5459
g1: {
@@ -57,7 +62,8 @@ describe('extractEndpoints', () => {
5762
};
5863

5964
const endpoints: Record<string, ManifestEndpoint> = {};
60-
loader.extractEndpoints(module, endpoints);
65+
const requiredAPIs: Record<string, ManifestRequiredAPI> = {};
66+
loader.extractStack(module, endpoints, requiredAPIs);
6167
expect(endpoints).to.be.deep.equal({
6268
fn1: {
6369
entryPoint: 'fn1',
@@ -71,8 +77,8 @@ describe('extractEndpoints', () => {
7177
});
7278
});
7379

74-
describe('loadBackend', () => {
75-
const expected: ManifestBackend = {
80+
describe('loadStack', () => {
81+
const expected: ManifestStack = {
7682
endpoints: {
7783
v1http: {
7884
platform: 'gcfv1',
@@ -86,31 +92,32 @@ describe('loadBackend', () => {
8692
callableTrigger: {},
8793
},
8894
},
89-
requiredAPIs: {},
95+
requiredAPIs: [],
9096
specVersion: 'v1alpha1',
9197
};
9298

9399
type Testcase = {
94100
name: string;
95101
modulePath: string;
96-
expected: ManifestBackend;
102+
expected: ManifestStack;
97103
};
98104

99105
function runTests(tc: Testcase) {
100106
it('loads backend given relative path', async () => {
101-
await expect(loader.loadBackend(tc.modulePath)).to.eventually.deep.equal(
107+
await expect(loader.loadStack(tc.modulePath)).to.eventually.deep.equal(
102108
tc.expected
103109
);
104110
});
105111

106112
it('loads backend given absolute path', async () => {
107113
await expect(
108-
loader.loadBackend(path.join(process.cwd(), tc.modulePath))
114+
loader.loadStack(path.join(process.cwd(), tc.modulePath))
109115
).to.eventually.deep.equal(tc.expected);
110116
});
111117
}
112118

113119
let prev;
120+
114121
beforeEach(() => {
115122
// TODO: When __trigger annotation is removed and GCLOUD_PROJECT is not required at runtime, remove this.
116123
prev = process.env.GCLOUD_PROJECT;
@@ -150,7 +157,7 @@ describe('loadBackend', () => {
150157
callableTrigger: {},
151158
},
152159
},
153-
requiredAPIs: {},
160+
requiredAPIs: [],
154161
specVersion: 'v1alpha1',
155162
},
156163
},
@@ -170,10 +177,16 @@ describe('loadBackend', () => {
170177
},
171178
},
172179
},
173-
requiredAPIs: {
174-
pubsub: 'pubsub.googleapis.com',
175-
scheduler: 'cloudscheduler.googleapis.com',
176-
},
180+
requiredAPIs: [
181+
{
182+
api: 'pubsub.googleapis.com',
183+
reason: 'Needed for v1 scheduled functions.',
184+
},
185+
{
186+
api: 'cloudscheduler.googleapis.com',
187+
reason: 'Needed for v1 scheduled functions.',
188+
},
189+
],
177190
specVersion: 'v1alpha1',
178191
},
179192
},

src/bin/firebase-functions.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env node
22

33
import * as express from 'express';
4-
import { loadBackend } from '../runtime/loader';
4+
import { loadStack } from '../runtime/loader';
55

66
function printUsage() {
77
console.error(
@@ -24,9 +24,9 @@ const functionsDir = args[0];
2424
let server;
2525
const app = express();
2626

27-
app.get('/backend.yaml', async (req, res) => {
27+
app.get('/stack.yaml', async (req, res) => {
2828
try {
29-
const backend = await loadBackend(functionsDir);
29+
const backend = await loadStack(functionsDir);
3030
res.setHeader('content-type', 'text/yaml');
3131
res.send(JSON.stringify(backend));
3232
} catch (e) {
@@ -36,14 +36,14 @@ app.get('/backend.yaml', async (req, res) => {
3636
}
3737
});
3838

39-
app.get('/quitquitquit', async (req, res) => {
39+
app.get('/__/quitquitquit', async (req, res) => {
4040
res.send('ok');
4141
server.close(() => console.log('shutdown requested via /quitquitquit'));
4242
});
4343

4444
let port = 8080;
45-
if (process.env.ADMIN_PORT) {
46-
port = Number.parseInt(process.env.ADMIN_PORT);
45+
if (process.env.STACK_CONTROL_API_PORT) {
46+
port = Number.parseInt(process.env.STACK_CONTROL_API_PORT);
4747
}
4848

4949
console.log('Serving at port', port);

src/runtime/loader.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222
import * as url from 'url';
2323
import * as path from 'path';
2424

25-
import { ManifestBackend, ManifestEndpoint } from './manifest';
25+
import {
26+
ManifestStack,
27+
ManifestEndpoint,
28+
ManifestRequiredAPI,
29+
} from './manifest';
2630

2731
/**
2832
* Dynamically load import function to prevent TypeScript from
@@ -54,9 +58,10 @@ async function loadModule(functionsDir: string) {
5458
}
5559

5660
/* @internal */
57-
export function extractEndpoints(
61+
export function extractStack(
5862
module,
5963
endpoints: Record<string, ManifestEndpoint>,
64+
requiredAPIs: Record<string, ManifestRequiredAPI>,
6065
prefix = ''
6166
) {
6267
for (const [name, val] of Object.entries(module)) {
@@ -70,29 +75,35 @@ export function extractEndpoints(
7075
...val['__endpoint'],
7176
entryPoint: funcName.replace(/-/g, '.'),
7277
};
78+
if (val['__requiredAPIs'] && Array.isArray(val['__requiredAPIs'])) {
79+
for (const { api, reason } of val['__requiredAPIs']) {
80+
const reasons = [reason];
81+
if (requiredAPIs[api]?.reason) {
82+
reasons.push(requiredAPIs[api].reason);
83+
}
84+
requiredAPIs[api] = { api, reason: reasons.join(' ') };
85+
}
86+
}
7387
} else if (typeof val === 'object' && val !== null) {
74-
extractEndpoints(val, endpoints, prefix + name + '-');
88+
extractStack(val, endpoints, requiredAPIs, prefix + name + '-');
7589
}
7690
}
7791
}
7892

7993
/* @internal */
80-
export async function loadBackend(
94+
export async function loadStack(
8195
functionsDir: string
82-
): Promise<ManifestBackend> {
96+
): Promise<ManifestStack> {
8397
const endpoints: Record<string, ManifestEndpoint> = {};
98+
const requiredAPIs: Record<string, ManifestRequiredAPI> = {};
8499
const mod = await loadModule(functionsDir);
85100

86-
extractEndpoints(mod, endpoints);
101+
extractStack(mod, endpoints, requiredAPIs);
87102

88-
const backend: ManifestBackend = {
103+
const stack: ManifestStack = {
89104
endpoints,
90105
specVersion: 'v1alpha1',
91-
requiredAPIs: {},
106+
requiredAPIs: Object.values(requiredAPIs),
92107
};
93-
if (Object.values(endpoints).find((ep) => ep.scheduleTrigger)) {
94-
backend.requiredAPIs['pubsub'] = 'pubsub.googleapis.com';
95-
backend.requiredAPIs['scheduler'] = 'cloudscheduler.googleapis.com';
96-
}
97-
return backend;
108+
return stack;
98109
}

src/runtime/manifest.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,18 @@ export interface ManifestEndpoint {
6868
};
6969
}
7070

71+
/* @internal */
72+
export interface ManifestRequiredAPI {
73+
api: string;
74+
reason: string;
75+
}
76+
7177
/**
7278
* @internal
7379
* An definition of a function deployment as appears in the Manifest.
7480
**/
75-
export interface ManifestBackend {
81+
export interface ManifestStack {
7682
specVersion: 'v1alpha1';
77-
requiredAPIs: Record<string, string>;
83+
requiredAPIs: ManifestRequiredAPI[];
7884
endpoints: Record<string, ManifestEndpoint>;
7985
}

0 commit comments

Comments
 (0)