From 63b2076e6fac791397931a79344c5a4df18a00a6 Mon Sep 17 00:00:00 2001 From: arei Date: Tue, 16 Mar 2021 11:51:15 -0400 Subject: [PATCH 1/7] "Update compile to allow for short names in vpcConnector, and to allow egress settings to be provided." --- package/lib/compileFunctions.js | 54 +++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index c9dd256..1aea9a7 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -61,6 +61,18 @@ module.exports = { vpcConnector: _.get(funcObject, 'vpc') || _.get(this, 'serverless.service.provider.vpc'), }); } + + if (funcObject.vpcEgress) { + const egress = (_.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); + if (egress) { + egress = egress.toUpperCase(); + if (egress==='all') egrees = 'ALL_TRAFFIC'; + if (egress==='private') egrees = 'PRIVATE_RANGES_ONLY'; + } + _.assign(funcTemplate.properties, { + vpcConnectorEgressSettings: egress, + }); + } if (funcObject.maxInstances) { funcTemplate.properties.maxInstances = funcObject.maxInstances; @@ -145,15 +157,39 @@ const validateEventsProperty = (funcObject, functionName) => { const validateVpcConnectorProperty = (funcObject, functionName) => { if (funcObject.vpc && typeof funcObject.vpc === 'string') { - const vpcNamePattern = /projects\/[\s\S]*\/locations\/[\s\S]*\/connectors\/[\s\S]*/i; - if (!vpcNamePattern.test(funcObject.vpc)) { - const errorMessage = [ - `The function "${functionName}" has invalid vpc connection name`, - ' VPC Connector name should follow projects/{project_id}/locations/{region}/connectors/{connector_name}', - ' Please check the docs for more info.', - ].join(''); - throw new Error(errorMessage); - } + + // vpcConnector argument can be one of two possible formats as described here: + // https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction + if (funcObject.vpc.indexOf('/')) { + const vpcNamePattern = /projects\/[\s\S]*\/locations\/[\s\S]*\/connectors\/[\s\S]*/i; + if (!vpcNamePattern.test(funcObject.vpc)) { + const errorMessage = [ + `The function "${functionName}" has invalid vpc connection name`, + ' VPC Connector name should follow projects/{project_id}/locations/{region}/connectors/{connector_name}', + ' or just {connector_name} if within the same project.', + ' Please check the docs for more info at ', + ' https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction', + ].join(''); + throw new Error(errorMessage); + } + } + } +}; + +const validateVpcConnectorEgressProperty = (funcObject, functionName) => { + if (funcObject.vpcEgress && typeof funcObject.vpcEgress === 'string') { + const egress = funcObject.vpcEgress.toUpperCase(); + if (egress!=='ALL' && egress!=='ALL_TRAFFIC' && egress!=='PRIVATE' && egress!=='PRIVATE_RANGES_ONLY') { + const errorMessage = [ + `The function "${functionName}" has invalid vpc connection name`, + ' VPC Connector Egress Setting be either ALL_TRAFFIC or PRIVATE_RANGES_ONLY. ', + ' You may shorten these to ALL or PRIVATE optionally.', + ' Please check the docs for more info at', + ' https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction', + ].join(''); + throw new Error(errorMessage); + + } } }; From 3bdd9c0ccce1a53f1ffcaa6eb73cd635f90e1f43 Mon Sep 17 00:00:00 2001 From: arei Date: Tue, 16 Mar 2021 11:55:17 -0400 Subject: [PATCH 2/7] "Update compile to allow for short names in vpcConnector, and to allow egress settings to be provided." --- package/lib/compileFunctions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index 1aea9a7..ed7d95f 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -63,7 +63,7 @@ module.exports = { } if (funcObject.vpcEgress) { - const egress = (_.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); + const egress = _.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); if (egress) { egress = egress.toUpperCase(); if (egress==='all') egrees = 'ALL_TRAFFIC'; From 18c2cc80aa5e9cc75daaa8c467aaed2baa3f56e6 Mon Sep 17 00:00:00 2001 From: arei Date: Tue, 16 Mar 2021 11:58:24 -0400 Subject: [PATCH 3/7] "Update compile to allow for short names in vpcConnector, and to allow egress settings to be provided." --- package/lib/compileFunctions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index ed7d95f..b68894d 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -160,7 +160,7 @@ const validateVpcConnectorProperty = (funcObject, functionName) => { // vpcConnector argument can be one of two possible formats as described here: // https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction - if (funcObject.vpc.indexOf('/')) { + if (funcObject.vpc.indexOf('/')>-1) { const vpcNamePattern = /projects\/[\s\S]*\/locations\/[\s\S]*\/connectors\/[\s\S]*/i; if (!vpcNamePattern.test(funcObject.vpc)) { const errorMessage = [ From cb3181fa3c77a355fad9fef84ba0cb8cbf67d386 Mon Sep 17 00:00:00 2001 From: arei Date: Tue, 16 Mar 2021 12:00:37 -0400 Subject: [PATCH 4/7] "Update compile to allow for short names in vpcConnector, and to allow egress settings to be provided." --- package/lib/compileFunctions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index b68894d..ed105be 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -63,7 +63,7 @@ module.exports = { } if (funcObject.vpcEgress) { - const egress = _.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); + let egress = _.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); if (egress) { egress = egress.toUpperCase(); if (egress==='all') egrees = 'ALL_TRAFFIC'; From 5cb86613a6ebbcabc5916ca11e5090512e7582da Mon Sep 17 00:00:00 2001 From: arei Date: Tue, 16 Mar 2021 12:01:45 -0400 Subject: [PATCH 5/7] "Update compile to allow for short names in vpcConnector, and to allow egress settings to be provided." --- package/lib/compileFunctions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index ed105be..f1b403b 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -66,8 +66,8 @@ module.exports = { let egress = _.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); if (egress) { egress = egress.toUpperCase(); - if (egress==='all') egrees = 'ALL_TRAFFIC'; - if (egress==='private') egrees = 'PRIVATE_RANGES_ONLY'; + if (egress==='all') egress = 'ALL_TRAFFIC'; + if (egress==='private') egress = 'PRIVATE_RANGES_ONLY'; } _.assign(funcTemplate.properties, { vpcConnectorEgressSettings: egress, From 6e189433f26083e9eae951cd0a8f5ae5eb89413e Mon Sep 17 00:00:00 2001 From: arei Date: Tue, 16 Mar 2021 12:02:46 -0400 Subject: [PATCH 6/7] "Update compile to allow for short names in vpcConnector, and to allow egress settings to be provided." --- package/lib/compileFunctions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index f1b403b..57e211b 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -66,8 +66,8 @@ module.exports = { let egress = _.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); if (egress) { egress = egress.toUpperCase(); - if (egress==='all') egress = 'ALL_TRAFFIC'; - if (egress==='private') egress = 'PRIVATE_RANGES_ONLY'; + if (egress==='ALL') egress = 'ALL_TRAFFIC'; + if (egress==='PRIVATE') egress = 'PRIVATE_RANGES_ONLY'; } _.assign(funcTemplate.properties, { vpcConnectorEgressSettings: egress, From 938c1cdc414d6ad64d15317444823462011ca62e Mon Sep 17 00:00:00 2001 From: arei Date: Tue, 16 Mar 2021 12:16:31 -0400 Subject: [PATCH 7/7] "Update compile to allow for short names in vpcConnector, and to allow egress settings to be provided." --- package/lib/compileFunctions.js | 77 +++++++++-------- package/lib/compileFunctions.test.js | 124 +++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 36 deletions(-) diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index 57e211b..51efbcc 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -24,6 +24,7 @@ module.exports = { validateHandlerProperty(funcObject, functionName); validateEventsProperty(funcObject, functionName); validateVpcConnectorProperty(funcObject, functionName); + validateVpcConnectorEgressProperty(funcObject, functionName); const funcTemplate = getFunctionTemplate( funcObject, @@ -61,14 +62,15 @@ module.exports = { vpcConnector: _.get(funcObject, 'vpc') || _.get(this, 'serverless.service.provider.vpc'), }); } - - if (funcObject.vpcEgress) { - let egress = _.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); - if (egress) { - egress = egress.toUpperCase(); - if (egress==='ALL') egress = 'ALL_TRAFFIC'; - if (egress==='PRIVATE') egress = 'PRIVATE_RANGES_ONLY'; - } + + if (funcObject.vpcEgress) { + let egress = + _.get(funcObject, 'vpcEgress') || _.get(this, 'serverless.service.provider.vpcEgress'); + if (egress) { + egress = egress.toUpperCase(); + if (egress === 'ALL') egress = 'ALL_TRAFFIC'; + if (egress === 'PRIVATE') egress = 'PRIVATE_RANGES_ONLY'; + } _.assign(funcTemplate.properties, { vpcConnectorEgressSettings: egress, }); @@ -157,39 +159,42 @@ const validateEventsProperty = (funcObject, functionName) => { const validateVpcConnectorProperty = (funcObject, functionName) => { if (funcObject.vpc && typeof funcObject.vpc === 'string') { - - // vpcConnector argument can be one of two possible formats as described here: - // https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction - if (funcObject.vpc.indexOf('/')>-1) { - const vpcNamePattern = /projects\/[\s\S]*\/locations\/[\s\S]*\/connectors\/[\s\S]*/i; - if (!vpcNamePattern.test(funcObject.vpc)) { - const errorMessage = [ - `The function "${functionName}" has invalid vpc connection name`, - ' VPC Connector name should follow projects/{project_id}/locations/{region}/connectors/{connector_name}', - ' or just {connector_name} if within the same project.', - ' Please check the docs for more info at ', - ' https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction', - ].join(''); - throw new Error(errorMessage); - } - } + // vpcConnector argument can be one of two possible formats as described here: + // https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction + if (funcObject.vpc.indexOf('/') > -1) { + const vpcNamePattern = /projects\/[\s\S]*\/locations\/[\s\S]*\/connectors\/[\s\S]*/i; + if (!vpcNamePattern.test(funcObject.vpc)) { + const errorMessage = [ + `The function "${functionName}" has invalid vpc connection name`, + ' VPC Connector name should follow projects/{project_id}/locations/{region}/connectors/{connector_name}', + ' or just {connector_name} if within the same project.', + ' Please check the docs for more info at ', + ' https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction', + ].join(''); + throw new Error(errorMessage); + } + } } }; const validateVpcConnectorEgressProperty = (funcObject, functionName) => { if (funcObject.vpcEgress && typeof funcObject.vpcEgress === 'string') { - const egress = funcObject.vpcEgress.toUpperCase(); - if (egress!=='ALL' && egress!=='ALL_TRAFFIC' && egress!=='PRIVATE' && egress!=='PRIVATE_RANGES_ONLY') { - const errorMessage = [ - `The function "${functionName}" has invalid vpc connection name`, - ' VPC Connector Egress Setting be either ALL_TRAFFIC or PRIVATE_RANGES_ONLY. ', - ' You may shorten these to ALL or PRIVATE optionally.', - ' Please check the docs for more info at', - ' https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction', - ].join(''); - throw new Error(errorMessage); - - } + const egress = funcObject.vpcEgress.toUpperCase(); + if ( + egress !== 'ALL' && + egress !== 'ALL_TRAFFIC' && + egress !== 'PRIVATE' && + egress !== 'PRIVATE_RANGES_ONLY' + ) { + const errorMessage = [ + `The function "${functionName}" has invalid vpc connection name`, + ' VPC Connector Egress Setting be either ALL_TRAFFIC or PRIVATE_RANGES_ONLY. ', + ' You may shorten these to ALL or PRIVATE optionally.', + ' Please check the docs for more info at', + ' https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions#resource:-cloudfunction', + ].join(''); + throw new Error(errorMessage); + } } }; diff --git a/package/lib/compileFunctions.test.js b/package/lib/compileFunctions.test.js index a33e771..4ef78e1 100644 --- a/package/lib/compileFunctions.test.js +++ b/package/lib/compileFunctions.test.js @@ -767,4 +767,128 @@ describe('CompileFunctions', () => { }); }); }); + + it('should allow vpc as short name', () => { + googlePackage.serverless.service.functions = { + func1: { + handler: 'func1', + memorySize: 128, + runtime: 'nodejs10', + vpc: 'my-vpc', + events: [{ http: 'foo' }], + }, + }; + + const compiledResources = [ + { + type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', + name: 'my-service-dev-func1', + properties: { + parent: 'projects/myProject/locations/us-central1', + runtime: 'nodejs10', + function: 'my-service-dev-func1', + entryPoint: 'func1', + availableMemoryMb: 128, + timeout: '60s', + sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', + httpsTrigger: { + url: 'foo', + }, + labels: {}, + vpcConnector: 'my-vpc', + }, + }, + ]; + + return googlePackage.compileFunctions().then(() => { + expect(consoleLogStub.called).toEqual(true); + expect( + googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources + ).toEqual(compiledResources); + }); + }); + + it('should allow vpc egress all', () => { + googlePackage.serverless.service.functions = { + func1: { + handler: 'func1', + memorySize: 128, + runtime: 'nodejs10', + vpc: 'my-vpc', + vpcEgress: 'all', + events: [{ http: 'foo' }], + }, + }; + + const compiledResources = [ + { + type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', + name: 'my-service-dev-func1', + properties: { + parent: 'projects/myProject/locations/us-central1', + runtime: 'nodejs10', + function: 'my-service-dev-func1', + entryPoint: 'func1', + availableMemoryMb: 128, + timeout: '60s', + sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', + httpsTrigger: { + url: 'foo', + }, + labels: {}, + vpcConnector: 'my-vpc', + vpcConnectorEgressSettings: 'ALL_TRAFFIC', + }, + }, + ]; + + return googlePackage.compileFunctions().then(() => { + expect(consoleLogStub.called).toEqual(true); + expect( + googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources + ).toEqual(compiledResources); + }); + }); + + it('should allow vpc egress private', () => { + googlePackage.serverless.service.functions = { + func1: { + handler: 'func1', + memorySize: 128, + runtime: 'nodejs10', + vpc: 'my-vpc', + vpcEgress: 'private', + events: [{ http: 'foo' }], + }, + }; + + const compiledResources = [ + { + type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', + name: 'my-service-dev-func1', + properties: { + parent: 'projects/myProject/locations/us-central1', + runtime: 'nodejs10', + function: 'my-service-dev-func1', + entryPoint: 'func1', + availableMemoryMb: 128, + timeout: '60s', + sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', + httpsTrigger: { + url: 'foo', + }, + labels: {}, + vpcConnector: 'my-vpc', + vpcConnectorEgressSettings: 'PRIVATE_RANGES_ONLY', + }, + }, + ]; + + return googlePackage.compileFunctions().then(() => { + expect(consoleLogStub.called).toEqual(true); + expect( + googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources + ).toEqual(compiledResources); + }); + }); });