I have a python_awslambda question: I have a large...
# plugins
b
I have a python_awslambda question: I have a large number of functions with the same third-party dependencies, and prior to using pants was using Lambda Layers to avoid reuploading 100MB of deps for every function. In python_awslambda, the deps get built into the pex so I'm back to repeating lots of large uploads. Is there a way to filter a third-party dep out of the pex being sent to lambda?
c
I donโ€™t have any first hand experience with this, but it looks like it is this you want to use: https://github.com/pantsbuild/pants/pull/13894
Perhaps thereโ€™s some tweaks that needs to be done to support that for aws lambda use? @happy-kitchen-89482
b
ah, yeah I think that's what I need, let me see if it generates the plain pex without the deps I'm trying to avoid
yep that's exactly what I need, just for awslambda in addition to for pex
๐Ÿ‘ 1
and I see now where in the awslambda module it's making that call https://github.com/pantsbuild/pants/blob/main/src/python/pants/backend/awslambda/python/rules.py#L94-L109 so then all I'd need is the new
include_requirements:bool
flag to be available on python_awslambda and passed into the pexrequest. Thanks for the pointer
๐Ÿ™Œ 1
wow, that was extremely easy to add:
e
To point out another possibility, you might be able to create a single lambdex with all your functions and then just alter the
LAMBDEX_ENTRY_POINT
in a tiny layer: https://github.com/pantsbuild/lambdex#controlling-runtime-execution
b
I see - so I would still upload my large deps in the pex, but include that env var to change it around
e
Yes. I re-read though and may have missed the point. You said Lambda Layers and not Docker layers so my mental model is probably wrong. I have no clue what Lambda Layers are.
b
they're fairly close, but you can have lambda layers added to a function after you've deployed it, and reuse the layer using its ARN across many lambdas. In our case we have some fairly hefty C dependencies that change infrequently. To make deploys fast & not reupload the C deps every time we deploy, we put them in a layer
your suggestion of the entry point would reduce the number of uploads from once per function per deploy to once per deploy, but layers reduce it further to once per change to the layer
e
Gotcha.
b
I made a PR of the change to add
include_requirements
as a field on python_awslambda https://github.com/pantsbuild/pants/pull/14469
๐Ÿ™Œ 2
I am not 100% clear on how things get into the docs. Do I need to also make a docs change, or will that description field get picked up automatically?
e
Automatically. Targets and Subsystems get generated docs - everything in the Reference section of https://www.pantsbuild.org/. All the rest of the docs you use the web UI to suggest edits.
b
ah that's so neat
e
Thanks for digging in here!
b
of course ๐Ÿ™‚ I'm not entirely sure how to test this PR without just stubbing everything, since it's just a pass of bool flags through to PexTarget
I know "but it's such a simple change" isn't a good reason not to test, but in this case I feel like the type system is really doing the work for me
e
If you feel inspired, the infrastructure is all there https://github.com/pantsbuild/pants/blob/4b335cdccfebcbd1f92caaa5fef7d5ca161c7226/src/python/pants/backend/awslambda/python/rules_test.py#L76. I think it would be pretty easy to add a single pinned dep (say ansicolors) and check include / exclude.
b
When I try to run that test I get this error (macos, I think it may be that I'm missing python3.7 development headers?):
Copy code
E   ImportError: dlopen(/private/var/folders/_s/q_xksw8943540mqd5vllmmgh0000gn/T/process-executionO6ryWQ/src/python/pants/engine/internals/native_engine.so, 0x0002): symbol not found in flat namespace '_PyObject_VectorcallMethod'
ImportError while importing test module '/private/var/folders/_s/q_xksw8943540mqd5vllmmgh0000gn/T/process-executionO6ryWQ/src/python/pants/backend/awslambda/python/rules_test.py'.
Hint: make sure your test modules/packages have valid Python names.
h
You can force the test to use a different Python version by using
--python-interpreter-constraints=['==3.9.*']
here https://github.com/pantsbuild/pants/blob/4b335cdccfebcbd1f92caaa5fef7d5ca161c7226/src/python/pants/backend/awslambda/python/rules_test.py#L55
btw another way to solve this problem is using transitive excludes with `!!`: https://www.pantsbuild.org/docs/targets#dependencies-field
b
Wouldn't that mean I have to transitive exclude every dependency though, and remember all future ones?
h
indeed, so your PR is a much better solution in the case that you want to leave off every 3rd-party requirement. Whereas
!!
transitive excludes are good if you only want to exclude a few expensive deps, but keep others
b
Gotcha - I'll add that alternative to the PR description
โค๏ธ 1
Added a test as well - https://github.com/pantsbuild/pants/pull/14469/commits/5ea8e9d29043b1c2bb7e9024bd344661d7122530 It does change the scope for the hello_world lambda by adding a third-party dep, but I think that's an ok addition
๐Ÿ™Œ 2
h
This is great, thanks for the PR! Just to clarify though, this is an all-or-nothing proposition: it will omit all 3rd party requirements from the lambda, so you have to provide them all in a layer. As long as this solves the problem, great! A more selective solution would require more work (such as implementing https://docs.google.com/document/d/1r9nCf62lHeaz5NGldhsZwu19_SzRuTCrPEELgn_9l2g/edit?usp=sharing)
b
Correct it does omit all 3rd party requirements
which, for my use case, is exactly what I need and then I do the opposite to generate my layer zip. Using the 3rdparty filter:
./pants dependencies share/deployer/:: | xargs ./pants filter --target-type=python_requirement | xargs ./pants peek | jq -r '.[]["requirements"][]'
so that way I can make my lambda pex light (no 3rdparty) and still make sure I get the exact requirements into my layer when I build it
๐Ÿ’ฏ 1
๐Ÿ’ฅ 1
I uh... don't think I understand nearly enough about pants to comment on that proposal doc
h
Hah, yeah it's a deep cut
But as long as this solves your problem effectively then even better!
No need to go complicated when simple will do
Although, next step, a plugin to generate the layer zip... ๐Ÿ˜‰
b
yeah that's all outside pants right now, I'm just starting to adopt it and I already have a generation step for layers in my CI
h
BTW you can somewhat simplify that invocation with
/pants dependencies share/deployer/:: | xargs ./pants peek | jq -r '.[].requirements|select(.!=null)[]'
So use
jq
itself to filter nulls instead of piping through the target type filter
b
oh. I ripped it from the suggested
build-support
file
cool
h
Yeah I only realized this myself a few days ago
And maybe it's worse in some way, I am not a jq expert
b
neat
maybe the longer one is to prevent non-python deps from coming in, say if you've got a mixed language repo
h
It is probably more future-proof!