Skip to content

Commit

Permalink
feat: function level entry overrides (#1220)
Browse files Browse the repository at this point in the history
* chore(deps-dev): bump eslint from 8.21.0 to 8.22.0

Bumps [eslint](https://github.com/eslint/eslint) from 8.21.0 to 8.22.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](eslint/eslint@v8.21.0...v8.22.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>

* feat: added support for layer-provided lambda handlers

refs #548

* chore: switched to functionDefinition entrypoint

* chore: fixed docs

* chore: entrypoint

* test: added test

* chore: fixed lint

* chore: lint fix

* chore: docs placement

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Vicary <[email protected]>
  • Loading branch information
3 people authored Aug 22, 2022
1 parent 8e42e13 commit 3984c3d
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 14 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,23 @@ module.exports = {
};
```

##### Optional entry overrides

`serverless-webpack` generates Webpack entries from the `handler` value by default.

If your handler is different from the webpack entry, e.g. provided by a layer,
you may override the generated entry at function level via the `entrypoint`
option in `serverless.yml`.

```yaml
functions:
my-function:
layers:
- LAYER-ARN
handler: layer.handler
entrypoint: src/index.handler
```
#### Full customization (for experts)
The lib export also provides the `serverless` and `options` properties, through
Expand Down
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const prepareStepOfflineInvoke = require('./lib/prepareStepOfflineInvoke');
const packExternalModules = require('./lib/packExternalModules');
const packageModules = require('./lib/packageModules');
const { isNodeRuntime } = require('./lib/utils');
const { extendFunctionProperties } = require('./lib/extendServerless');
const lib = require('./lib');

class ServerlessWebpack {
Expand All @@ -24,6 +25,8 @@ class ServerlessWebpack {

constructor(serverless, options, v3Utils) {
this.serverless = serverless;
extendFunctionProperties(this.serverless);

this.options = options;

if (v3Utils) {
Expand Down
15 changes: 15 additions & 0 deletions lib/extendServerless.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const _ = require('lodash');

const extendFunctionProperties = serverless => {
if (_.isFunction(serverless.configSchemaHandler.defineFunctionProperties)) {
serverless.configSchemaHandler.defineFunctionProperties('aws', {
properties: {
entrypoint: { type: 'string' }
}
});
}
};

module.exports = {
extendFunctionProperties
};
6 changes: 5 additions & 1 deletion lib/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ const preferredExtensions = ['.js', '.ts', '.jsx', '.tsx'];
module.exports = {
validate() {
const getHandlerFileAndFunctionName = functionDefinition => {
const { handler: handlerProp, image: imageProp } = functionDefinition;
const { handler: handlerProp, image: imageProp, entrypoint: entryPoint } = functionDefinition;

// CASE: The lambda handler is inside lambda layer. Use functionDefinition `entrypoint`
// to define the original handler.
if (entryPoint) return entryPoint;

if (handlerProp) {
return handlerProp;
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,23 @@ describe('ServerlessWebpack', () => {
};
serverless.pluginManager.spawn = jest.fn().mockReturnValue(BbPromise.resolve());
serverless.service.getFunction = jest.fn().mockReturnValue({ runtime: 'nodejs12.x' });
serverless.configSchemaHandler.defineFunctionProperties = jest.fn();
});

it('should expose a lib object', () => {
const lib = ServerlessWebpack.lib;
expect(lib).toEqual({ entries: {}, webpack: { isLocal: false } });
});

it('should extend serverless', () => {
new ServerlessWebpack(serverless, {});
expect(serverless.configSchemaHandler.defineFunctionProperties).toHaveBeenCalledWith('aws', {
properties: {
entrypoint: { type: 'string' }
}
});
});

describe('with a TS webpack configuration', () => {
it('should support old config and register ts-node', () => {
jest.setMock('ts-node/register', null, { virtual: true });
Expand Down
32 changes: 25 additions & 7 deletions tests/validate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,10 @@ describe('validate', () => {
}
}
]
},
layerFunc: {
handler: 'layer.handler',
entrypoint: 'module1.func1handler'
}
};

Expand Down Expand Up @@ -547,7 +551,7 @@ describe('validate', () => {
};

expect(lib.entries).toEqual(expectedLibEntries);
expect(globMock.sync).toHaveBeenCalledTimes(5);
expect(globMock.sync).toHaveBeenCalledTimes(6);
expect(serverless.cli.log).toHaveBeenCalledTimes(0);
return null;
});
Expand Down Expand Up @@ -804,6 +808,7 @@ describe('validate', () => {
_.set(module.serverless.service, 'custom.webpack.config', testConfig);
module.serverless.service.functions = testFunctionsConfig;
globMock.sync.mockImplementation(filename => [_.replace(filename, '*', 'js')]);

return expect(module.validate())
.resolves.toBeUndefined()
.then(() => {
Expand Down Expand Up @@ -915,6 +920,12 @@ describe('validate', () => {
func: testFunctionsConfig.func1,
entry: { key: 'module1', value: './module1.js' }
},
{
handlerFile: 'module1',
funcName: 'layerFunc',
func: { handler: 'layer.handler', entrypoint: 'module1.func1handler' },
entry: { key: 'module1', value: './module1.js' }
},
{
handlerFile: 'module2',
funcName: 'func2',
Expand Down Expand Up @@ -960,12 +971,13 @@ describe('validate', () => {
return expect(module.validate())
.resolves.toBeUndefined()
.then(() => {
expect(module.webpackConfig).toHaveLength(5);
expect(module.webpackConfig).toHaveLength(6);
expect(module.webpackConfig[0].output.path).toEqual(path.join('output', 'func1'));
expect(module.webpackConfig[1].output.path).toEqual(path.join('output', 'func2'));
expect(module.webpackConfig[2].output.path).toEqual(path.join('output', 'func3'));
expect(module.webpackConfig[3].output.path).toEqual(path.join('output', 'func4'));
expect(module.webpackConfig[4].output.path).toEqual(path.join('output', 'dockerfunc'));
expect(module.webpackConfig[1].output.path).toEqual(path.join('output', 'layerFunc'));
expect(module.webpackConfig[2].output.path).toEqual(path.join('output', 'func2'));
expect(module.webpackConfig[3].output.path).toEqual(path.join('output', 'func3'));
expect(module.webpackConfig[4].output.path).toEqual(path.join('output', 'func4'));
expect(module.webpackConfig[5].output.path).toEqual(path.join('output', 'dockerfunc'));

return null;
});
Expand All @@ -988,22 +1000,28 @@ describe('validate', () => {
return expect(module.validate())
.resolves.toBeUndefined()
.then(() => {
expect(module.webpackConfig).toHaveLength(5);
expect(module.webpackConfig).toHaveLength(6);
expect(module.webpackConfig[0].devtool).toEqual('source-map');
expect(module.webpackConfig[1].devtool).toEqual('source-map');
expect(module.webpackConfig[2].devtool).toEqual('source-map');
expect(module.webpackConfig[3].devtool).toEqual('source-map');
expect(module.webpackConfig[4].devtool).toEqual('source-map');
expect(module.webpackConfig[5].devtool).toEqual('source-map');

expect(module.webpackConfig[0].context).toEqual('some context');
expect(module.webpackConfig[1].context).toEqual('some context');
expect(module.webpackConfig[2].context).toEqual('some context');
expect(module.webpackConfig[3].context).toEqual('some context');
expect(module.webpackConfig[4].context).toEqual('some context');
expect(module.webpackConfig[5].context).toEqual('some context');

expect(module.webpackConfig[0].output.libraryTarget).toEqual('commonjs');
expect(module.webpackConfig[1].output.libraryTarget).toEqual('commonjs');
expect(module.webpackConfig[2].output.libraryTarget).toEqual('commonjs');
expect(module.webpackConfig[3].output.libraryTarget).toEqual('commonjs');
expect(module.webpackConfig[4].output.libraryTarget).toEqual('commonjs');
expect(module.webpackConfig[5].output.libraryTarget).toEqual('commonjs');

return null;
});
});
Expand Down

0 comments on commit 3984c3d

Please sign in to comment.