Skip to content

Commit c03dc23

Browse files
José Lucas Chociaiedaniszewski
andauthored
feat: Legacy naming and failurePolicy (#1)
* feat: Add support for allowUnauthenticated and custom IAM definitions (PR serverless#219) * feat: preserve function name * added failurePolicy Co-authored-by: Erick Daniszewski <[email protected]>
1 parent ad8cf16 commit c03dc23

File tree

3 files changed

+505
-2
lines changed

3 files changed

+505
-2
lines changed

info/lib/displayServiceInfo.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ module.exports = {
5050
const region = this.options.region;
5151
const project = this.serverless.service.provider.project;
5252
const baseUrl = `https://${region}-${project}.cloudfunctions.net`;
53-
const path = serviceFunc.name; // NOTE this might change
53+
const path = serviceFunc.useLegacyNaming ? serviceFunc.handler : serviceFunc.name;
5454
funcResource = `${baseUrl}/${path}`;
5555
}
5656

package/lib/compileFunctions.js

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = {
2424
validateHandlerProperty(funcObject, functionName);
2525
validateEventsProperty(funcObject, functionName);
2626
validateVpcConnectorProperty(funcObject, functionName);
27+
validateIamProperty(funcObject, functionName);
2728

2829
const funcTemplate = getFunctionTemplate(
2930
funcObject,
@@ -51,6 +52,11 @@ module.exports = {
5152
_.get(this, 'serverless.service.provider.environment'),
5253
funcObject.environment // eslint-disable-line comma-dangle
5354
);
55+
funcTemplate.accessControl.gcpIamPolicy.bindings = _.unionBy(
56+
_.get(funcObject, 'iam.bindings'),
57+
_.get(this, 'serverless.service.provider.iam.bindings'),
58+
'role'
59+
);
5460

5561
if (!funcTemplate.properties.serviceAccountEmail) {
5662
delete funcTemplate.properties.serviceAccountEmail;
@@ -83,16 +89,30 @@ module.exports = {
8389

8490
funcTemplate.properties.httpsTrigger = {};
8591
funcTemplate.properties.httpsTrigger.url = url;
92+
93+
if (funcObject.allowUnauthenticated) {
94+
funcTemplate.accessControl.gcpIamPolicy.bindings = _.unionBy(
95+
[{ role: 'roles/cloudfunctions.invoker', members: ['allUsers'] }],
96+
funcTemplate.accessControl.gcpIamPolicy.bindings,
97+
'role'
98+
);
99+
}
86100
}
87101
if (eventType === 'event') {
88102
const type = funcObject.events[0].event.eventType;
89103
const path = funcObject.events[0].event.path; //eslint-disable-line
90104
const resource = funcObject.events[0].event.resource;
105+
const failurePolicy = funcObject.events[0].event.failurePolicy;
91106

92107
funcTemplate.properties.eventTrigger = {};
93108
funcTemplate.properties.eventTrigger.eventType = type;
94109
if (path) funcTemplate.properties.eventTrigger.path = path;
95110
funcTemplate.properties.eventTrigger.resource = resource;
111+
if (failurePolicy) funcTemplate.properties.eventTrigger.failurePolicy = failurePolicy;
112+
}
113+
114+
if (!funcTemplate.accessControl.gcpIamPolicy.bindings.length) {
115+
delete funcTemplate.accessControl;
96116
}
97117

98118
this.serverless.service.provider.compiledConfigurationTemplate.resources.push(funcTemplate);
@@ -157,6 +177,29 @@ const validateVpcConnectorProperty = (funcObject, functionName) => {
157177
}
158178
};
159179

180+
const validateIamProperty = (funcObject, functionName) => {
181+
if (_.get(funcObject, 'iam.bindings') && funcObject.iam.bindings.length > 0) {
182+
funcObject.iam.bindings.forEach((binding) => {
183+
if (!binding.role) {
184+
const errorMessage = [
185+
`The function "${functionName}" has no role specified for an IAM binding.`,
186+
' Each binding requires a role. For details on supported roles, see the documentation',
187+
' at: https://cloud.google.com/iam/docs/understanding-roles',
188+
].join('');
189+
throw new Error(errorMessage);
190+
}
191+
if (!Array.isArray(binding.members) || !binding.members.length) {
192+
const errorMessage = [
193+
`The function "${functionName}" has no members specified for an IAM binding.`,
194+
' Each binding requires at least one member to be assigned. See the IAM documentation',
195+
' for details on configuring members: https://cloud.google.com/iam/docs/overview',
196+
].join('');
197+
throw new Error(errorMessage);
198+
}
199+
});
200+
}
201+
};
202+
160203
const getFunctionTemplate = (funcObject, projectName, region, sourceArchiveUrl) => {
161204
//eslint-disable-line
162205
return {
@@ -168,8 +211,13 @@ const getFunctionTemplate = (funcObject, projectName, region, sourceArchiveUrl)
168211
runtime: 'nodejs8',
169212
timeout: '60s',
170213
entryPoint: funcObject.handler,
171-
function: funcObject.name,
214+
function: funcObject.useLegacyNaming ? funcObject.handler : funcObject.name,
172215
sourceArchiveUrl,
173216
},
217+
accessControl: {
218+
gcpIamPolicy: {
219+
bindings: [],
220+
},
221+
},
174222
};
175223
};

0 commit comments

Comments
 (0)