serverless-python-requirements
serverless-python-requirements copied to clipboard
sls deploy function -f <function> does not work - TypeError: Cannot read property 'runtime' of undefined
If you are using the latest serverless (I have tried 2.34 and above) with this plugin and try and update one function you get TypeError: Cannot read property 'runtime' of undefined
Any ideas why this fails if the plugin is enabled? This used to work well in earlier versions. Any help or ideas to solve this would be awesome.
Example output:
$ sls deploy function -f hello --stage ae --region ap-southeast-2
Type Error ----------------------------------------------
TypeError: Cannot read property 'runtime' of undefined
at /Users/demo/test/node_modules/serverless-python-requirements/lib/pip.js:609:15
at Array.filter (<anonymous>)
at ServerlessPythonRequirements.installAllRequirements (/Users/demo/test/node_modules/serverless-python-requirements/lib/pip.js:608:8)
at ServerlessPythonRequirements.tryCatcher (/Users/demo/test/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Users/demo/test/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/Users/demo/test/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/Users/demo/test/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/Users/demo/test/node_modules/bluebird/js/release/promise.js:729:18)
at _drainQueueStep (/Users/demo/test/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/Users/demo/test/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/Users/demo/test/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/Users/demo/test/node_modules/bluebird/js/release/async.js:15:14)
at processImmediate (internal/timers.js:461:21)
For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
Your Environment Information ---------------------------
Operating System: darwin
Node Version: 14.16.1
Framework Version: 2.37.1
Plugin Version: 4.5.3
SDK Version: 4.2.2
Components Version: 3.9.0
You can easily duplicate this using the example api - https://github.com/serverless/examples/tree/master/aws-python-rest-api with few small updates - see example serverless.yaml below.
service: test-api
frameworkVersion: '2'
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
dockerizePip: true
slim: true
layer:
compatibleRuntimes:
- python3.8
provider:
name: aws
runtime: python3.8
lambdaHashingVersion: '20201221'
package:
individually: true
patterns:
- '!*.txt'
- '!*.md'
- '!*.json'
- '!node_modules/**'
functions:
hello:
handler: handler.hello
layers:
- { Ref: PythonRequirementsLambdaLayer }
events:
- http:
path: /
method: get
Example requirements.txt with a module in there.
jsonpickle
Environment Details
serverless-python-requirements version: 5.1.1
Environment overview:
Operating System: darwin
Node Version: 14.16.1
Framework Version: 2.37.1
Plugin Version: 4.5.3
SDK Version: 4.2.2
Components Version: 3.9.0
I did some further testing and investigation and maybe this helps others to help figure out what is going wrong.
If you use:
package:
individually: true
And you have enabled this plugin with Lamdba layers, you cannot deploy an individual function. If you do not set the above then you can deploy individual function but not all at once as you then get
No file matches include / exclude patterns
Looking further at the code, the strange part is this, when an individual function is specified, example:
sls deploy function -f hello --stage ae --region ap-southeast-2
Lets look at index.js specific the targetFuncs() function...
...
get targetFuncs() {
let inputOpt = this.serverless.processedInput.options;
return inputOpt.function
? [inputOpt.functionObj]
: values(this.serverless.service.functions);
}
...
This will return a "String" as the function name if an individual function is specified not an Array if all functions are to be deployed.
Now looking at ./lib/pip.js see the installAllREquirements() extract below where things are failing with the "filter"
function installAllRequirements() {
// fse.ensureDirSync(path.join(this.servicePath, '.serverless'));
// First, check and delete cache versions, if enabled
checkForAndDeleteMaxCacheVersions(this.options, this.serverless);
// Then if we're going to package functions individually...
if (this.serverless.service.package.individually) {
let doneModules = [];
this.targetFuncs
.filter((func) =>
(func.runtime || this.serverless.service.provider.runtime).match(
/^python.*/
)
)
...
...
If you look at this, we can see that if you have set package indiividually to true, this "targetFuncs" is expected to return an "Array" - as "filter" is used, but a string is passed in not an array.
Maybe this helps to solve this issue.
I am also trying to figure out this. Really need to solve this.
It's not that targetFuncs is returning a String, it's that it is returning an array of undefined. I am new to serverless, but I'm guessing that the options object previously had an attribute functionObj which is no longer there. The solution appears to be to replace [inputOpt.functionObj] with [this.serverless.service.functions[inputOpt.function]].
Having hacked that change in to my local version of the plugin, it no longer exhibits this error.
Thank you - I have applied the change and it works!
Is there any plan to bundle this fix into a release?
@pgrzesik are there any plans to merge the PR for this? This has been ongoing for a while and it seems the fix has been ready for over a month now.
Hey @dalecampbell, the PR is not complete as it doesn't include a test case, I've just wrote a comment about that, if we don't hear from the original author then we're open to other contributions.
Any update @pgrzesik ?
Hey @dalecampbell - no updates from the original author - I think at this point we should accept an alternative contributions if anyone would like to solve that problem
hmm ran into the same trap. Thanks for the information.
using
sls deploy -f app
this.targetFuncs returns undefined

this is why :-/
inputOpt.functionObj is undefined....

Sorry you've run into that issue @pharindoko
If anyone interested in taking over the PR that fixes it, we'll be happy to accept the contribution 🙌