diff --git a/lib/Serverless.js b/lib/Serverless.js index fd25eab20..4b61b125a 100644 --- a/lib/Serverless.js +++ b/lib/Serverless.js @@ -84,6 +84,10 @@ class Serverless { // (https://github.com/serverless/serverless/issues/2041) this.variables.populateService(this.pluginManager.cliOptions); + // populate function names after variables are loaded in case functions were externalized + // (https://github.com/serverless/serverless/issues/2997) + this.service.setFunctionNames(this.processedInput.options); + // validate the service configuration, now that variables are loaded this.service.validate(); diff --git a/lib/classes/Service.js b/lib/classes/Service.js index fe5550d1e..1a1679e80 100644 --- a/lib/classes/Service.js +++ b/lib/classes/Service.js @@ -108,23 +108,30 @@ class Service { that.package.include = serverlessFile.package.include; } - // setup function.name property - const stageNameForFunction = options.stage || this.provider.stage; - _.forEach(that.functions, (functionObj, functionName) => { - if (!functionObj.events) { - that.functions[functionName].events = []; - } - - if (!functionObj.name) { - that.functions[functionName].name = - `${that.service}-${stageNameForFunction}-${functionName}`; - } - }); - return this; }); } + setFunctionNames(rawOptions) { + const that = this; + const options = rawOptions || {}; + options.stage = options.stage || options.s; + options.region = options.region || options.r; + + // setup function.name property + const stageNameForFunction = options.stage || this.provider.stage; + _.forEach(that.functions, (functionObj, functionName) => { + if (!functionObj.events) { + that.functions[functionName].events = []; + } + + if (!functionObj.name) { + that.functions[functionName].name = + `${that.service}-${stageNameForFunction}-${functionName}`; + } + }); + } + validate() { _.forEach(this.functions, (functionObj, functionName) => { if (!_.isArray(functionObj.events)) { diff --git a/lib/classes/Service.test.js b/lib/classes/Service.test.js index 67d044e7e..74e56f741 100644 --- a/lib/classes/Service.test.js +++ b/lib/classes/Service.test.js @@ -199,47 +199,6 @@ describe('Service', () => { }); }); - it('should make sure function name contains the default stage', () => { - const SUtils = new Utils(); - const serverlessYml = { - service: 'new-service', - provider: { - name: 'aws', - stage: 'dev', - region: 'us-east-1', - variableSyntax: '\\${{([\\s\\S]+?)}}', - }, - plugins: ['testPlugin'], - functions: { - functionA: {}, - }, - resources: { - aws: { - resourcesProp: 'value', - }, - azure: {}, - google: {}, - }, - package: { - exclude: ['exclude-me'], - include: ['include-me'], - artifact: 'some/path/foo.zip', - }, - }; - - SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), - YAML.dump(serverlessYml)); - - const serverless = new Serverless(); - serverless.init(); - serverless.config.update({ servicePath: tmpDirPath }); - serviceInstance = new Service(serverless); - - return serviceInstance.load().then(() => { - expect(serviceInstance.functions.functionA.name).to.be.equal('new-service-dev-functionA'); - }); - }); - it('should support Serverless file with a non-aws provider', () => { const SUtils = new Utils(); const serverlessYaml = { @@ -259,6 +218,7 @@ describe('Service', () => { serviceInstance = new Service(serverless); return serviceInstance.load().then(() => { + serviceInstance.setFunctionNames(); const expectedFunc = { functionA: { name: 'customFunctionName', @@ -290,6 +250,7 @@ describe('Service', () => { serviceInstance = new Service(serverless); return serviceInstance.load().then(() => { + serviceInstance.setFunctionNames(); const expectedFunc = { functionA: { name: 'customFunctionName', @@ -319,6 +280,7 @@ describe('Service', () => { serviceInstance = new Service(serverless); return serviceInstance.load({ stage: 'dev' }).then(() => { + serviceInstance.setFunctionNames(); const expectedFunc = { functionA: { name: 'my-service-dev-functionA', @@ -503,6 +465,57 @@ describe('Service', () => { }); }); + describe('#setFunctionNames()', () => { + let serviceInstance; + let tmpDirPath; + + beforeEach(() => { + tmpDirPath = testUtils.getTmpDirPath(); + }); + + it('should make sure function name contains the default stage', () => { + const SUtils = new Utils(); + const serverlessYml = { + service: 'new-service', + provider: { + name: 'aws', + stage: 'dev', + region: 'us-east-1', + variableSyntax: '\\${{([\\s\\S]+?)}}', + }, + plugins: ['testPlugin'], + functions: { + functionA: {}, + }, + resources: { + aws: { + resourcesProp: 'value', + }, + azure: {}, + google: {}, + }, + package: { + exclude: ['exclude-me'], + include: ['include-me'], + artifact: 'some/path/foo.zip', + }, + }; + + SUtils.writeFileSync(path.join(tmpDirPath, 'serverless.yml'), + YAML.dump(serverlessYml)); + + const serverless = new Serverless(); + serverless.init(); + serverless.config.update({ servicePath: tmpDirPath }); + serviceInstance = new Service(serverless); + + return serviceInstance.load().then(() => { + serviceInstance.setFunctionNames(); + expect(serviceInstance.functions.functionA.name).to.be.equal('new-service-dev-functionA'); + }); + }); + }); + describe('#update()', () => { it('should update service instance data', () => { const serverless = new Serverless();