add docker exec as an attach command

This commit is contained in:
Aaron Walker 2020-05-17 16:53:35 -04:00
commit c9b1456759
3 changed files with 46 additions and 21 deletions

View file

@ -394,7 +394,9 @@ and connect to it using debugpy.
The usage pattern is to hit `<F5>`, enter `host` (the host where your app runs),
`account` (the account it runs under), and `port` (a port that will be opened on
the remote host). Vimspector then orchestrates the various tools to set you up.
the remote host). Vimspector also supports exec'ing into Docker run containers
with `container` (the container name or id your app is running in).
Vimspector then orchestrates the various tools to set you up.
```json
@ -403,9 +405,10 @@ the remote host). Vimspector then orchestrates the various tools to set you up.
"python-remote": {
"port": "${port}",
"host": "${host}",
"container": "${container}",
"launch": {
"remote": {
"host": "${host}", // Remote host to ssh to (mandatory)
"host": "${host}", // Remote host to ssh to (mandatory if not using container)
"account": "${account}", // User to connect as (optional)
// Optional.... Manual additional arguments for ssh
@ -432,14 +435,7 @@ the remote host). Vimspector then orchestrates the various tools to set you up.
},
"attach": {
"remote": {
"host": "${host}", // Remote host to ssh to (mandatory)
"account": "${account}", // User to connect as (optional)
// Optional.... Manual additional arguments for ssh
// "ssh": {
// "args": [ "-o", "StrictHostKeyChecking=no" ]
// },
"container": "${container}"
// Command to get the PID of the process to attach (mandatory)
"pidCommand": [
//

View file

@ -78,8 +78,19 @@
"properties": {
"remote": {
"type": "object",
"required": [ "host" ],
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will ssh to 'account'@'host' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
"oneOf": [
{
"required": [
"host"
]
},
{
"required": [
"container"
]
}
],
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
"properties": {
"account": {
"type": "string",
@ -87,7 +98,11 @@
},
"host": {
"type": "string",
"description": "Name of the remote host to connect to (via passwordless SSH). "
"description": "Name of the remote host to connect to (via passwordless SSH)."
},
"container": {
"type": "string",
"description": "Name or container id of the docker run container to connect to (via docker exec -it)."
},
"pidCommand": {
"type": "array",

View file

@ -613,13 +613,13 @@ class DebugSession( object ):
# e.g. expand variables when we use them, not all at once. This would
# remove the whole %PID% hack.
remote = atttach_config[ 'remote' ]
ssh = self._GetSSHCommand( remote )
attach_cmd = self._GetAttachCommand( remote )
# FIXME: Why does this not use self._GetCommands ?
cmd = ssh + remote[ 'pidCommand' ]
pid_cmd = attach_cmd + remote[ 'pidCommand' ]
self._logger.debug( 'Getting PID: %s', cmd )
pid = subprocess.check_output( cmd ).decode( 'utf-8' ).strip()
self._logger.debug( 'Getting PID: %s', pid_cmd )
pid = subprocess.check_output( pid_cmd ).decode( 'utf-8' ).strip()
self._logger.debug( 'Got PID: %s', pid )
if not pid:
@ -628,7 +628,7 @@ class DebugSession( object ):
return
if 'initCompleteCommand' in remote:
initcmd = ssh + remote[ 'initCompleteCommand' ][ : ]
initcmd = attach_cmd + remote[ 'initCompleteCommand' ][ : ]
for index, item in enumerate( initcmd ):
initcmd[ index ] = item.replace( '%PID%', pid )
@ -638,7 +638,7 @@ class DebugSession( object ):
commands = self._GetCommands( remote, 'attach' )
for command in commands:
cmd = ssh + command[ : ]
cmd = attach_cmd + command[ : ]
for index, item in enumerate( cmd ):
cmd[ index ] = item.replace( '%PID%', pid )
@ -665,11 +665,11 @@ class DebugSession( object ):
if 'remote' in run_config:
remote = run_config[ 'remote' ]
ssh = self._GetSSHCommand( remote )
attach_cmd = self._GetAttachCommand( remote )
commands = self._GetCommands( remote, 'run' )
for index, command in enumerate( commands ):
cmd = ssh + command[ : ]
cmd = attach_cmd + command[ : ]
full_cmd = []
for item in cmd:
if isinstance( command_line, list ):
@ -694,6 +694,20 @@ class DebugSession( object ):
return ssh
def _GetDockerCommand( self, remote ):
docker = [ 'docker exec -it' ] + remote.get( 'docker', {} ).get( 'args', [] )
if 'container' not in remote:
raise ValueError( "Invalid container; must be string" )
docker.append( remote[ 'container' ] )
return docker
def _GetAttachCommand( self, remote ):
if any( remote.get( 'ssh' ), remote.get( 'account' ), remote.get( 'host' ) ):
return self._GetSSHCommand( remote )
elif any( remote.get( 'docker' ), remote.get( 'container' ) ):
return self._GetDockerCommand( remote )
raise ValueError( 'Could not determine attach command' )
def _GetCommands( self, remote, pfx ):
commands = remote.get( pfx + 'Commands', None )