-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(debugging): Support debugging Golang functions. #565
Conversation
Golang Debugging was initally implemented in aws#495, but reverted in aws#526 due to functional and integration tests failures. This commit reverts aws#526 and adds in the testing gaps. The specific differences are: * _get_debug_context method was replaces with the __bool__/__nonzero (py2) * Added additional unit tests for lambda_container to cover added methods * Updated Functional tests * Added debug_context support in start-lambda
* Added the command for building a Go binary for debugging * Added notes being explict about <output path> for dlv and --debugger-path
I have successfully debugged my first Go application. I update the README.rst for the Golang Debugging section to include extra steps I needed to do to get debugging working in VSCode. I am considering updating the README in the Golang example we generate from Also, shout out to @austinlparker for helping me get debugging working and test everything :) |
README.rst
Outdated
as the debugger, and wrap your function with it at runtime. The debugger | ||
is run in headless mode, listening on the debug port. | ||
|
||
When debugging, you must compile you function in debug mode: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small typo; Second you
should be your
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
I think some updates to the Golang example might be useful, yeah. I wouldn't say it's blocking a release though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall. Two questions: why get_debug_context
still exists, and why requests
library is version pinned?
README.rst
Outdated
You must compile `delve` to run in the container and provide its local path | ||
via the `--debugger-path` argument. Build delve locally as follows: | ||
|
||
`GOARCH=amd64 GOOS=linux go build -o <output path>/dlv github.com/derekparker/delve/cmd/dlv` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change <output path>
to something like <delve folder path>
to be more descriptive?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can. I still want to keep the /dlv at the end since it needs to be that name (right now).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah /dlv is fine..
README.rst
Outdated
The following is an example launch configuration for Visual Studio Code to | ||
attach to a debug session. | ||
|
||
.. code:: bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
json
language not bash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -8,7 +8,7 @@ pylint==1.7.2 | |||
pytest==3.0.7 | |||
py==1.4.33 | |||
mock==2.0.0 | |||
requests>=2.19.0 | |||
requests==2.19.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No! why!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are test requirements and without pinning we fail some tests because the request version is in the user-agent headers: https://github.com/awslabs/aws-sam-cli/blob/develop/tests/functional/local/apigw/test_local_apigw_service.py#L629
"headers": {"Host": "0.0.0.0:33651", "User-Agent": "python-requests/2.19.0", ...
Requests library adds these headers. I had different versions of requests in my local Py3 vs Py2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed this too. We should fix the tests to ignore these headers and not pin the versions here. Pip installation will break if we pin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather handle this outside of this PR. Pip should not break for pinning (we already do this for pytest, py, mock, etc) in the dev.txt requirements. For developing with the cli, we recommend pyenv to allow multiple python versions for testing. Devs should not be installing this into an existing pyenv. I think the concern here is valid but very low for 'break if we pin'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh my bad, I thought this was the base requirements.txt. Dev requirements are okay to be pinned
samcli/commands/local/invoke/cli.py
Outdated
:param string debugger_path: Path to debugger on host | ||
:return DebugContext: | ||
""" | ||
if not debug_port or debug_args or debugger_path: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need this method anymore, do you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not.
|
||
return { | ||
debug_options.debugger_path: { | ||
"bind": "/tmp/lambci_debug_files", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this static string to a class member? Also add comments explaining if this is the path in local file system or inside docker container
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call!
event_data = "data" | ||
get_event_mock.return_value = event_data | ||
|
||
debug_context_data = DebugContext(debug_port=self.debug_port, debug_args=self.debug_args, | ||
debugger_path=self.debugger_path) | ||
get_debug_context_mock.return_value = debug_context_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to change because get_debug_context
method won't exist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will update the test where needed.
self.assertEquals(context.debug_args, 'debug_args') | ||
|
||
@parameterized.expand([ | ||
('1000', 'debuggerpath', 'debug_args'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good thought to test with port number as strings :)
|
||
self.assertIsNotNone(result) | ||
|
||
|
||
class TestLambdaContainer_get_additional_options(TestCase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
return None | ||
|
||
return { | ||
debug_options.debugger_path: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other thing I ran into is if the debugger_path is a relative path, this breaks.
Command:
sam local start-api -d 5858 --debugger-path ./sam-app
Failure (start-api works but when invoking I get):
docker.errors.APIError: 400 Client Error: Bad Request ("create ./sam-app: "./sam-app" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path")
The right approach here is to use pathlib.Path(debug_options.debugger_path).resolve()
(encapsulate this inside the DebugContext of course). This will resolve the path to the absolute path. My only concern here is windows and docker integrations. We are already running into path issues with Windows and Docker Toolbox and adding this Path resolving will only make that issue more complex. Short term resolving the path is right but we should really bring all these path resolving through some common library to make our lives a little easier long term.
What are your thoughts here @sanathkr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using pathlib is fine for now. If you want to be future proof, create a separate helper method to resolve Docker paths in Windows that is a no-op today. We can implement this method in a separate PR
* Removed unneeded methods * Refactored some constants in lambda_container * README updates/corrections
In the Go runtime Container (might be others as well), the container handles the timeout of the function. For debug sessions that last longer than the timeout, the container will halt. Now, we set the timeout to 10 hours when we are in a debug session.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except for one readme comment.
Also, can you handle relative paths to dlv file in this PR before I approve it?
README.rst
Outdated
|
||
`GOARCH=amd64 GOOS=linux go build -o <delve folder path>/dlv github.com/derekparker/delve/cmd/dlv` | ||
|
||
NOTE: The output path needs to end in `/dlv`. The docker container will expect the dlv binary to be in the <output path> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to replace here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missed one :(
Yup, already working on it :) |
Adding some additional validation on the debugger_path to make for a better experience and fail fast. Hoping to have a new revision here soon |
debugger = Path(debugger_path).resolve(strict=True) | ||
except OSError as error: | ||
if error.errno == errno.ENOENT: | ||
raise DebugContextException("'debugger_path' could not be found.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor comment: Instead of the string 'debugger_path', can you add the actual value of variable debugger_path to the message? like '/usr/loca/ is not found'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor cchanges. Otherwise looks good
|
||
# We turn off pylint here due to https://github.com/PyCQA/pylint/issues/1660 | ||
if not debugger.is_dir(): # pylint: disable=no-member | ||
raise DebugContextException("'debugger_path' should be a directory with the debugger in it.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have the actual value of debugger path in error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! Thanks for all the iterations :)
@austinlparker Did all the heavy lifting :) |
Y’all too kind. 😛
…Sent from my iPhone
On Jul 25, 2018, at 3:51 PM, Jacob Fuss ***@***.***> wrote:
@austinlparker Did all the heavy lifting :)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
* fix: Functional tests must run on localhost to work in Windows (#552) * fix: spacing typo in Log statement in start-lambda (#559) * docs: Fix syntax highlighting in README.md (#561) * docs: Change jest to mocha in Nodejs init README (#564) * docs: Fix @mhart link in README (#562) * docs(README): removed cloudtrail, added SNS to generate-event (#569) * docs: Update repo name references (#577) * feat(debugging): Fixing issues around debugging Golang functions. (#565) * fix(init): Improve current init samples around docs and fixes (#558) * docs(README): Update launch config to SAM CLI from SAM Local (#587) * docs(README): Update sample code for calling Local Lambda Invoke (#584) * refactor(init): renamed handler for camel case, moved callback call up (#586) * chore: aws-lambda-java-core 1.1.0 -> 1.2.0 for java sam init (#578) * feat(validate): Add profile and region options (#582) Currently, `sam validate` requires AWS Creds (due to the SAM Translator). This commits adds the ability to pass in the credientials through a profile that is configured through `aws configure`. * docs(README): Update README prerequisites to include awscli (#596) * fix(start-lambda): Remove Content-Type Header check (#594) * docs: Disambiguation "Amazon Kinesis" (#599) * docs: Adding instructions for how to add pyenv to your PATH for Windows (#600) * docs: Update README with small grammar fix (#601) * fix: Update link in NodeJS package.json (#603) * docs: Creating instructions for Windows users to install sam (#605) * docs: Adding a note directing Windows users to use pipenv (#606) * fix: Fix stringifying λ environment variables when using Python2 (#579) * feat(generate-event): Added support for 50+ events (#612) * feat(invoke): Add region parameter to all invoke related commands (#608) * docs: Breaking up README into separate files to make it easier to read (#607) * chore: Update JVM size params to match docker-lambda (#615) * feat(invoke): Invoke Function Without Parameters through --no-event (#604) * docs: Update advanced_usage.rst with clarification on --env-vars usage (#610) * docs: Remove an extra word in the sam packaging command (#618) * UX: Improves event names to reflect Lambda Event Sources (#619) * docs: Fix git clone typo in installation docs (#630) * docs(README): Callout go1.x runtime support (#631) * docs(installation): Update sam --version command (#634) * chore(0.6.0): SAM CLI Version bump (#635)
Golang Debugging was initally implemented in #495, but reverted in #526
due to functional and integration tests failures. This commit reverts #526
and adds in the testing gaps. The specific differences are:
Issue #, if available:
#281
Description of changes:
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.