diff --git a/info/lib/displayServiceInfo.js b/info/lib/displayServiceInfo.js index f1cf35a..3658776 100644 --- a/info/lib/displayServiceInfo.js +++ b/info/lib/displayServiceInfo.js @@ -45,12 +45,21 @@ module.exports = { const funcEventConfig = serviceFunc.events[0][eventType]; let funcResource = funcEventConfig.resource || null; + let funcName = serviceFunc.handler; + + if (serviceFunc.prependStage) { + funcName = `${this.options.stage}-${funcName}`; + } + + if (serviceFunc.prependService) { + funcName = `${this.serverless.service.service}-${funcName}`; + } if (eventType === 'http') { const region = this.options.region; const project = this.serverless.service.provider.project; const baseUrl = `https://${region}-${project}.cloudfunctions.net`; - const path = serviceFunc.handler; // NOTE this might change + const path = funcName; // NOTE this might change funcResource = `${baseUrl}/${path}`; } @@ -99,5 +108,6 @@ const getFunctionNameInService = (funcName, service, stage) => { funcNameInService = funcNameInService.replace(service, ''); funcNameInService = funcNameInService.replace(stage, ''); funcNameInService = funcNameInService.slice(2, funcNameInService.length); + return funcNameInService; }; diff --git a/info/lib/displayServiceInfo.test.js b/info/lib/displayServiceInfo.test.js index 984fa05..c02486c 100644 --- a/info/lib/displayServiceInfo.test.js +++ b/info/lib/displayServiceInfo.test.js @@ -34,6 +34,20 @@ describe('DisplayServiceInfo', () => { }, ], }, + func3: { + handler: 'handler', + prependStage: true, + events: [ + { http: 'foo3' }, + ], + }, + func4: { + handler: 'handler', + prependService: true, + events: [ + { http: 'foo4' }, + ], + }, }; serverless.service.provider = { project: 'my-project', @@ -105,6 +119,8 @@ describe('DisplayServiceInfo', () => { { type: 'resource.which.should.be.filterered', name: 'someResource' }, { type: 'cloudfunctions.v1beta2.function', name: 'my-service-dev-func1' }, { type: 'cloudfunctions.v1beta2.function', name: 'my-service-dev-func2' }, + { type: 'cloudfunctions.v1beta2.function', name: 'my-service-dev-func3' }, + { type: 'cloudfunctions.v1beta2.function', name: 'my-service-dev-func4' }, ], }; @@ -123,6 +139,14 @@ describe('DisplayServiceInfo', () => { name: 'func2', resource: 'projects/*/topics/my-test-topic', }, + { + name: 'func3', + resource: 'https://us-central1-my-project.cloudfunctions.net/dev-handler', + }, + { + name: 'func4', + resource: 'https://us-central1-my-project.cloudfunctions.net/my-service-handler', + }, ], }, }; diff --git a/invoke/lib/invokeFunction.js b/invoke/lib/invokeFunction.js index fcd7eff..afa9b8a 100644 --- a/invoke/lib/invokeFunction.js +++ b/invoke/lib/invokeFunction.js @@ -15,10 +15,16 @@ module.exports = { invoke() { const project = this.serverless.service.provider.project; const region = this.options.region; + const stage = this.options.stage ? this.options.stage : 'dev'; let func = this.options.function; const data = this.options.data || ''; - func = getGoogleCloudFunctionName(this.serverless.service.functions, func); + func = getGoogleCloudFunctionName( + this.serverless.service.functions, + func, + stage, + this.serverless.service.service, + ); const params = { name: `projects/${project}/locations/${region}/functions/${func}`, @@ -55,7 +61,7 @@ module.exports = { }; // retrieve the functions name (Google uses our handler property as the function name) -const getGoogleCloudFunctionName = (serviceFunctions, func) => { +const getGoogleCloudFunctionName = (serviceFunctions, func, stage, service) => { if (!serviceFunctions[func]) { const errorMessage = [ `Function "${func}" not found. `, @@ -64,5 +70,15 @@ const getGoogleCloudFunctionName = (serviceFunctions, func) => { throw new Error(errorMessage); } - return serviceFunctions[func].handler; + let funcName = serviceFunctions[func].handler; + + if (serviceFunctions[func].prependStage) { + funcName = `${stage}-${funcName}`; + } + + if (serviceFunctions[func].prependService) { + funcName = `${service}-${funcName}`; + } + + return funcName; }; diff --git a/invoke/lib/invokeFunction.test.js b/invoke/lib/invokeFunction.test.js index dcbc1ca..cf50f7d 100644 --- a/invoke/lib/invokeFunction.test.js +++ b/invoke/lib/invokeFunction.test.js @@ -24,6 +24,19 @@ describe('InvokeFunction', () => { func1: { handler: 'foo', }, + func2: { + handler: 'foo2', + prependService: true, + }, + func3: { + handler: 'foo3', + prependStage: true, + }, + func4: { + handler: 'foo4', + prependStage: true, + prependService: true, + }, }; serverless.setProvider('google', new GoogleProvider(serverless)); const options = { @@ -86,6 +99,63 @@ describe('InvokeFunction', () => { }); }); + it('should invoke the provided function with prependService', () => { + googleInvoke.options.function = 'func2'; + + return googleInvoke.invoke().then(() => { + expect(requestStub.calledWithExactly( + 'cloudfunctions', + 'projects', + 'locations', + 'functions', + 'call', + { + name: 'projects/my-project/locations/us-central1/functions/my-service-foo2', + resource: { + data: '', + }, + })).toEqual(true); + }); + }); + + it('should invoke the provided function with prependStage', () => { + googleInvoke.options.function = 'func3'; + + return googleInvoke.invoke().then(() => { + expect(requestStub.calledWithExactly( + 'cloudfunctions', + 'projects', + 'locations', + 'functions', + 'call', + { + name: 'projects/my-project/locations/us-central1/functions/dev-foo3', + resource: { + data: '', + }, + })).toEqual(true); + }); + }); + + it('should invoke the provided function with all prepend', () => { + googleInvoke.options.function = 'func4'; + + return googleInvoke.invoke().then(() => { + expect(requestStub.calledWithExactly( + 'cloudfunctions', + 'projects', + 'locations', + 'functions', + 'call', + { + name: 'projects/my-project/locations/us-central1/functions/my-service-dev-foo4', + resource: { + data: '', + }, + })).toEqual(true); + }); + }); + it('should invoke the provided function with the data option', () => { googleInvoke.options.function = 'func1'; googleInvoke.options.data = '{ "some": "json" }'; diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index de5034d..5e3c4aa 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -23,13 +23,15 @@ module.exports = { validateHandlerProperty(funcObject, functionName); validateEventsProperty(funcObject, functionName); - const funcTemplate = getFunctionTemplate( funcObject, this.options.region, + this.options.stage, + this.serverless.service.service, `gs://${ - this.serverless.service.provider.deploymentBucketName - }/${this.serverless.service.package.artifactFilePath}`); + this.serverless.service.provider.deploymentBucketName + }/${this.serverless.service.package.artifactFilePath}`, + ); funcTemplate.properties.availableMemoryMb = _.get(funcObject, 'memorySize') || _.get(this, 'serverless.service.provider.memorySize') @@ -109,7 +111,17 @@ const validateEventsProperty = (funcObject, functionName) => { } }; -const getFunctionTemplate = (funcObject, region, sourceArchiveUrl) => { //eslint-disable-line +const getFunctionTemplate = (funcObject, region, stage, service, sourceArchiveUrl) => { //eslint-disable-line + let funcName = funcObject.handler; + + if (funcObject.prependStage) { + funcName = `${stage}-${funcName}`; + } + + if (funcObject.prependService) { + funcName = `${service}-${funcName}`; + } + return { type: 'cloudfunctions.v1beta2.function', name: funcObject.name, @@ -117,7 +129,8 @@ const getFunctionTemplate = (funcObject, region, sourceArchiveUrl) => { //eslint location: region, availableMemoryMb: 256, timeout: '60s', - function: funcObject.handler, + entryPoint: funcObject.handler, + function: funcName, sourceArchiveUrl, }, }; diff --git a/package/lib/compileFunctions.test.js b/package/lib/compileFunctions.test.js index ce2ccb2..5963253 100644 --- a/package/lib/compileFunctions.test.js +++ b/package/lib/compileFunctions.test.js @@ -113,6 +113,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 1024, timeout: '60s', @@ -147,6 +148,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 1024, timeout: '60s', @@ -181,6 +183,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 256, timeout: '120s', @@ -215,6 +218,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 256, timeout: '120s', @@ -251,6 +255,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 256, timeout: '60s', @@ -289,6 +294,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 256, timeout: '60s', @@ -331,6 +337,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 256, timeout: '60s', @@ -367,6 +374,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 256, timeout: '60s', @@ -418,6 +426,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func1', properties: { location: 'us-central1', + entryPoint: 'func1', function: 'func1', availableMemoryMb: 256, timeout: '60s', @@ -435,6 +444,7 @@ describe('CompileFunctions', () => { name: 'my-service-dev-func2', properties: { location: 'us-central1', + entryPoint: 'func2', function: 'func2', availableMemoryMb: 256, timeout: '60s', @@ -454,5 +464,111 @@ describe('CompileFunctions', () => { .toEqual(compiledResources); }); }); + + it('should set stage in function name with prependStage', () => { + googlePackage.serverless.service.functions = { + func1: { + handler: 'func1', + prependStage: true, + events: [ + { http: 'foo' }, + ], + }, + }; + + const compiledResources = [{ + type: 'cloudfunctions.v1beta2.function', + name: 'my-service-dev-func1', + properties: { + location: 'us-central1', + entryPoint: 'func1', + function: 'dev-func1', + availableMemoryMb: 256, + timeout: '60s', + sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', + httpsTrigger: { + url: 'foo', + }, + labels: {}, + }, + }]; + + return googlePackage.compileFunctions().then(() => { + expect(consoleLogStub.calledOnce).toEqual(true); + expect(googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources) + .toEqual(compiledResources); + }); + }); + + it('should set service in function name with prependService', () => { + googlePackage.serverless.service.functions = { + func1: { + handler: 'func1', + prependService: true, + events: [ + { http: 'foo' }, + ], + }, + }; + + const compiledResources = [{ + type: 'cloudfunctions.v1beta2.function', + name: 'my-service-dev-func1', + properties: { + location: 'us-central1', + entryPoint: 'func1', + function: 'my-service-func1', + availableMemoryMb: 256, + timeout: '60s', + sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', + httpsTrigger: { + url: 'foo', + }, + labels: {}, + }, + }]; + + return googlePackage.compileFunctions().then(() => { + expect(consoleLogStub.calledOnce).toEqual(true); + expect(googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources) + .toEqual(compiledResources); + }); + }); + + it('should set service and stage in function name with prependService and prependStage', () => { + googlePackage.serverless.service.functions = { + func1: { + handler: 'func1', + prependStage: true, + prependService: true, + events: [ + { http: 'foo' }, + ], + }, + }; + + const compiledResources = [{ + type: 'cloudfunctions.v1beta2.function', + name: 'my-service-dev-func1', + properties: { + location: 'us-central1', + entryPoint: 'func1', + function: 'my-service-dev-func1', + availableMemoryMb: 256, + timeout: '60s', + sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', + httpsTrigger: { + url: 'foo', + }, + labels: {}, + }, + }]; + + return googlePackage.compileFunctions().then(() => { + expect(consoleLogStub.calledOnce).toEqual(true); + expect(googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources) + .toEqual(compiledResources); + }); + }); }); });