Skip to content

Commit a6c4971

Browse files
authored
Annotate function triggers with __endpoint property (#999)
In addition to annotating function triggers with `__trigger` property, we add `__endpoint` annotation. This property will be used by the to-be-developed functions runtime to generate/declare deployment manifest that the CLI will use to deploy the function. There are lots of code duplication between the utility functions for annotating the `__trigger` and `__endpoint` properties. I didn't try to refactor the common code since I expect that we will favor `__endpoint` property in the future.
1 parent a3f5351 commit a6c4971

15 files changed

+885
-30
lines changed

spec/v1/cloud-functions.spec.ts

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,131 @@ describe('makeCloudFunction', () => {
4141
legacyEventType: 'providers/provider/eventTypes/event',
4242
};
4343

44-
it('should put a __trigger on the returned CloudFunction', () => {
44+
it('should put a __trigger/__endpoint on the returned CloudFunction', () => {
4545
const cf = makeCloudFunction({
4646
provider: 'mock.provider',
4747
eventType: 'mock.event',
4848
service: 'service',
4949
triggerResource: () => 'resource',
5050
handler: () => null,
5151
});
52+
5253
expect(cf.__trigger).to.deep.equal({
5354
eventTrigger: {
5455
eventType: 'mock.provider.mock.event',
5556
resource: 'resource',
5657
service: 'service',
5758
},
5859
});
60+
61+
expect(cf.__endpoint).to.deep.equal({
62+
platform: 'gcfv1',
63+
eventTrigger: {
64+
eventType: 'mock.provider.mock.event',
65+
eventFilters: {
66+
resource: 'resource',
67+
},
68+
retry: false,
69+
},
70+
});
5971
});
6072

61-
it('should have legacy event type in __trigger if provided', () => {
73+
it('should have legacy event type in __trigger/__endpoint if provided', () => {
6274
const cf = makeCloudFunction(cloudFunctionArgs);
75+
6376
expect(cf.__trigger).to.deep.equal({
6477
eventTrigger: {
6578
eventType: 'providers/provider/eventTypes/event',
6679
resource: 'resource',
6780
service: 'service',
6881
},
6982
});
83+
84+
expect(cf.__endpoint).to.deep.equal({
85+
platform: 'gcfv1',
86+
eventTrigger: {
87+
eventType: 'providers/provider/eventTypes/event',
88+
eventFilters: {
89+
resource: 'resource',
90+
},
91+
retry: false,
92+
},
93+
});
94+
});
95+
96+
it('should include converted options in __endpoint', () => {
97+
const cf = makeCloudFunction({
98+
provider: 'mock.provider',
99+
eventType: 'mock.event',
100+
service: 'service',
101+
triggerResource: () => 'resource',
102+
handler: () => null,
103+
options: {
104+
timeoutSeconds: 10,
105+
regions: ['us-central1'],
106+
memory: '128MB',
107+
serviceAccount: '[email protected]',
108+
},
109+
});
110+
111+
expect(cf.__endpoint).to.deep.equal({
112+
platform: 'gcfv1',
113+
timeoutSeconds: 10,
114+
region: ['us-central1'],
115+
availableMemoryMb: 128,
116+
serviceAccountEmail: '[email protected]',
117+
eventTrigger: {
118+
eventType: 'mock.provider.mock.event',
119+
eventFilters: {
120+
resource: 'resource',
121+
},
122+
retry: false,
123+
},
124+
});
125+
});
126+
127+
it('should set retry given failure policy in __endpoint', () => {
128+
const cf = makeCloudFunction({
129+
provider: 'mock.provider',
130+
eventType: 'mock.event',
131+
service: 'service',
132+
triggerResource: () => 'resource',
133+
handler: () => null,
134+
options: { failurePolicy: { retry: {} } },
135+
});
136+
137+
expect(cf.__endpoint).to.deep.equal({
138+
platform: 'gcfv1',
139+
eventTrigger: {
140+
eventType: 'mock.provider.mock.event',
141+
eventFilters: {
142+
resource: 'resource',
143+
},
144+
retry: true,
145+
},
146+
});
147+
});
148+
149+
it('should setup a scheduleTrigger in __endpoint given a schedule', () => {
150+
const schedule = {
151+
schedule: 'every 5 minutes',
152+
retryConfig: { retryCount: 3 },
153+
timeZone: 'America/New_York',
154+
};
155+
const cf = makeCloudFunction({
156+
provider: 'mock.provider',
157+
eventType: 'mock.event',
158+
service: 'service',
159+
triggerResource: () => 'resource',
160+
handler: () => null,
161+
options: {
162+
schedule,
163+
},
164+
});
165+
expect(cf.__endpoint).to.deep.equal({
166+
platform: 'gcfv1',
167+
scheduleTrigger: schedule,
168+
});
70169
});
71170

72171
it('should construct the right context for event', () => {

spec/v1/providers/https.spec.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import { expect } from 'chai';
2424
import * as express from 'express';
25-
import * as _ from 'lodash';
25+
2626
import * as functions from '../../../src/index';
2727
import * as https from '../../../src/providers/https';
2828
import {
@@ -94,11 +94,15 @@ function runHandler(
9494

9595
describe('CloudHttpsBuilder', () => {
9696
describe('#onRequest', () => {
97-
it('should return a Trigger with appropriate values', () => {
97+
it('should return a trigger/endpoint with appropriate values', () => {
9898
const result = https.onRequest((req, resp) => {
9999
resp.send(200);
100100
});
101101
expect(result.__trigger).to.deep.equal({ httpsTrigger: {} });
102+
expect(result.__endpoint).to.deep.equal({
103+
platform: 'gcfv1',
104+
httpsTrigger: {},
105+
});
102106
});
103107

104108
it('should allow both region and runtime options to be set', () => {
@@ -115,37 +119,51 @@ describe('CloudHttpsBuilder', () => {
115119
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
116120
expect(fn.__trigger.timeout).to.deep.equal('90s');
117121
expect(fn.__trigger.httpsTrigger.invoker).to.deep.equal(['private']);
122+
123+
expect(fn.__endpoint.region).to.deep.equal(['us-east1']);
124+
expect(fn.__endpoint.availableMemoryMb).to.deep.equal(256);
125+
expect(fn.__endpoint.timeoutSeconds).to.deep.equal(90);
126+
expect(fn.__endpoint.httpsTrigger.invoker).to.deep.equal(['private']);
118127
});
119128
});
120129
});
121130

122131
describe('handler namespace', () => {
123132
describe('#onRequest', () => {
124-
it('should return an empty trigger', () => {
133+
it('should return an empty trigger and endpoint', () => {
125134
const result = functions.handler.https.onRequest((req, res) => {
126135
res.send(200);
127136
});
128137
expect(result.__trigger).to.deep.equal({});
138+
expect(result.__endpoint).to.deep.equal({});
129139
});
130140
});
131141

132142
describe('#onCall', () => {
133-
it('should return an empty trigger', () => {
143+
it('should return an empty trigger and endpoint', () => {
134144
const result = functions.handler.https.onCall(() => null);
135145
expect(result.__trigger).to.deep.equal({});
146+
expect(result.__endpoint).to.deep.equal({});
136147
});
137148
});
138149
});
139150

140151
describe('#onCall', () => {
141-
it('should return a Trigger with appropriate values', () => {
152+
it('should return a trigger/endpoint with appropriate values', () => {
142153
const result = https.onCall((data) => {
143154
return 'response';
144155
});
156+
145157
expect(result.__trigger).to.deep.equal({
146158
httpsTrigger: {},
147159
labels: { 'deployment-callable': 'true' },
148160
});
161+
162+
expect(result.__endpoint).to.deep.equal({
163+
platform: 'gcfv1',
164+
callableTrigger: {},
165+
labels: {},
166+
});
149167
});
150168

151169
it('should allow both region and runtime options to be set', () => {
@@ -160,6 +178,10 @@ describe('#onCall', () => {
160178
expect(fn.__trigger.regions).to.deep.equal(['us-east1']);
161179
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
162180
expect(fn.__trigger.timeout).to.deep.equal('90s');
181+
182+
expect(fn.__endpoint.region).to.deep.equal(['us-east1']);
183+
expect(fn.__endpoint.availableMemoryMb).to.deep.equal(256);
184+
expect(fn.__endpoint.timeoutSeconds).to.deep.equal(90);
163185
});
164186

165187
it('has a .run method', () => {

spec/v2/providers/helpers.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,22 @@ export const FULL_TRIGGER = {
3333
hello: 'world',
3434
},
3535
};
36+
37+
export const FULL_ENDPOINT = {
38+
platform: 'gcfv2',
39+
region: ['us-west1'],
40+
availableMemoryMb: 512,
41+
timeoutSeconds: 60,
42+
minInstances: 1,
43+
maxInstances: 3,
44+
concurrency: 20,
45+
vpc: {
46+
connector: 'aConnector',
47+
egressSettings: 'ALL_TRAFFIC',
48+
},
49+
serviceAccountEmail: 'root@',
50+
ingressSettings: 'ALLOW_ALL',
51+
labels: {
52+
hello: 'world',
53+
},
54+
};

spec/v2/providers/https.spec.ts

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
expectedResponseHeaders,
88
MockRequest,
99
} from '../../fixtures/mockrequest';
10-
import { FULL_OPTIONS, FULL_TRIGGER } from './helpers';
10+
import { FULL_ENDPOINT, FULL_OPTIONS, FULL_TRIGGER } from './helpers';
1111

1212
/**
1313
* RunHandlerResult contains the data from an express.Response.
@@ -82,10 +82,11 @@ describe('onRequest', () => {
8282
delete process.env.GCLOUD_PROJECT;
8383
});
8484

85-
it('should return a minimal trigger with appropriate values', () => {
85+
it('should return a minimal trigger/endpoint with appropriate values', () => {
8686
const result = https.onRequest((req, res) => {
8787
res.send(200);
8888
});
89+
8990
expect(result.__trigger).to.deep.equal({
9091
apiVersion: 2,
9192
platform: 'gcfv2',
@@ -94,9 +95,15 @@ describe('onRequest', () => {
9495
},
9596
labels: {},
9697
});
98+
99+
expect(result.__endpoint).to.deep.equal({
100+
platform: 'gcfv2',
101+
httpsTrigger: {},
102+
labels: {},
103+
});
97104
});
98105

99-
it('should create a complex trigger with appropriate values', () => {
106+
it('should create a complex trigger/endpoint with appropriate values', () => {
100107
const result = https.onRequest(
101108
{
102109
...FULL_OPTIONS,
@@ -107,6 +114,7 @@ describe('onRequest', () => {
107114
res.send(200);
108115
}
109116
);
117+
110118
expect(result.__trigger).to.deep.equal({
111119
...FULL_TRIGGER,
112120
httpsTrigger: {
@@ -115,6 +123,14 @@ describe('onRequest', () => {
115123
},
116124
regions: ['us-west1', 'us-central1'],
117125
});
126+
127+
expect(result.__endpoint).to.deep.equal({
128+
...FULL_ENDPOINT,
129+
httpsTrigger: {
130+
invoker: ['service-account1@', 'service-account2@'],
131+
},
132+
region: ['us-west1', 'us-central1'],
133+
});
118134
});
119135

120136
it('should merge options and globalOptions', () => {
@@ -148,6 +164,17 @@ describe('onRequest', () => {
148164
regions: ['us-west1', 'us-central1'],
149165
labels: {},
150166
});
167+
168+
expect(result.__endpoint).to.deep.equal({
169+
platform: 'gcfv2',
170+
httpsTrigger: {
171+
invoker: ['private'],
172+
},
173+
concurrency: 20,
174+
minInstances: 3,
175+
region: ['us-west1', 'us-central1'],
176+
labels: {},
177+
});
151178
});
152179

153180
it('should be an express handler', async () => {
@@ -209,8 +236,9 @@ describe('onCall', () => {
209236
delete process.env.GCLOUD_PROJECT;
210237
});
211238

212-
it('should return a minimal trigger with appropriate values', () => {
239+
it('should return a minimal trigger/endpoint with appropriate values', () => {
213240
const result = https.onCall((request) => 42);
241+
214242
expect(result.__trigger).to.deep.equal({
215243
apiVersion: 2,
216244
platform: 'gcfv2',
@@ -221,10 +249,17 @@ describe('onCall', () => {
221249
'deployment-callable': 'true',
222250
},
223251
});
252+
253+
expect(result.__endpoint).to.deep.equal({
254+
platform: 'gcfv2',
255+
labels: {},
256+
callableTrigger: {},
257+
});
224258
});
225259

226-
it('should create a complex trigger with appropriate values', () => {
260+
it('should create a complex trigger/endpoint with appropriate values', () => {
227261
const result = https.onCall(FULL_OPTIONS, (request) => 42);
262+
228263
expect(result.__trigger).to.deep.equal({
229264
...FULL_TRIGGER,
230265
httpsTrigger: {
@@ -235,6 +270,14 @@ describe('onCall', () => {
235270
'deployment-callable': 'true',
236271
},
237272
});
273+
274+
expect(result.__endpoint).to.deep.equal({
275+
...FULL_ENDPOINT,
276+
callableTrigger: {},
277+
labels: {
278+
...FULL_ENDPOINT.labels,
279+
},
280+
});
238281
});
239282

240283
it('should merge options and globalOptions', () => {
@@ -265,6 +308,15 @@ describe('onCall', () => {
265308
'deployment-callable': 'true',
266309
},
267310
});
311+
312+
expect(result.__endpoint).to.deep.equal({
313+
platform: 'gcfv2',
314+
callableTrigger: {},
315+
concurrency: 20,
316+
minInstances: 3,
317+
region: ['us-west1', 'us-central1'],
318+
labels: {},
319+
});
268320
});
269321

270322
it('has a .run method', () => {

0 commit comments

Comments
 (0)