import * as path from "path" ; import * as vscode from "vscode" ; import { IDebugProvider , PortInfo , Cancellable } from "./debugProvider" ; import * as debugUtils from "./debugUtils" ; import * as extensionUtils from "../extensionUtils" ; import { Kubectl } from "../kubectl" ; import { IDockerfile } from "../docker/parser" ; const defaultGoDebuggerExtensionId = "golang.go" ; const defaultGoDebuggerExtension = "Debugger for Go" ; const defaultGoDebuggerConfigType = "go" ; const defaultGoAppPort = "8080" ; const defaultGoDebugPort = "32768" ; const fullGoDebugOptsRegExp = /^dlv debug\s+.*(--listen[\s=][^\s]+)\S*/i ; export class GoDebugProvider implements IDebugProvider { public getDebuggerType ( ) { return defaultGoDebuggerConfigType ; } public async isDebuggerInstalled ( ) { if ( vscode . extensions . getExtension ( defaultGoDebuggerExtensionId ) ) { return true ; } const answer = await vscode . window . showInformationMessage ( `Go debugging requires the '${ defaultGoDebuggerExtension }' extension. Would you like to install it now?` , "Install Now" ) ; if ( answer === "Install Now" ) { return await extensionUtils . installVscodeExtension ( defaultGoDebuggerExtensionId ) ; } return false ; } public async startDebugging ( workspaceFolder , sessionName , port , _pod , _pidToDebug ) { const debugConfiguration = { type : "go" , request : "attach" , mode : "remote" , name : sessionName , hostName : "localhost" , remotePath : "${inputs.remotePath}" , port , inputs : [ { id : "remotePath" , type : "promptString" , description : "What is the remote dirpath for your app?" , default : "/go/src/${workspaceFolderBasename}" } ] } ; const currentFolder = ( vscode . workspace . workspaceFolders || [ ] ) . find ( ( folder ) => folder . name === path . basename ( workspaceFolder ) ) ; if ( ! currentFolder ) { return false ; } return await vscode . debug . startDebugging ( currentFolder , debugConfiguration ) ; } public isSupportedImage ( baseImage ) { if ( ! baseImage ) { return false ; } return baseImage . indexOf ( "golang" ) >= 0 ; } public async resolvePortsFromFile ( dockerfile , env ) { const rawDebugPortInfo = await debugUtils . promptForDebugPort ( defaultGoDebugPort ) ; const exposedPorts = dockerfile . getExposedPorts ( ) ; const possiblePorts = exposedPorts . length ? exposedPorts . filter ( ( port ) => port !== rawDebugPortInfo ) : [ ] ; const rawAppPortInfo = await debugUtils . promptForAppPort ( possiblePorts , defaultGoAppPort , env ) ; return { debugPort : Number ( rawDebugPortInfo ) , appPort : Number ( rawAppPortInfo ) } ; } public async resolvePortsFromContainer ( kubectl , pod , podNamespace , container ) { let rawDebugPortInfo ; const processes = await debugUtils . getProcesses ( kubectl , pod , podNamespace , container ) ; const commandLines = processes ? processes . map ( ( { command } ) => command ) : undefined ; if ( commandLines ) { for ( const commandLine of commandLines ) { const matches = commandLine . match ( fullGoDebugOptsRegExp ) ; if ( matches && matches . length > 0 ) { const addresses = matches [ 1 ] . split ( ":" ) ; rawDebugPortInfo = addresses [ addresses . length - 1 ] ; break ; } } } if ( ! rawDebugPortInfo || rawDebugPortInfo === "0" ) { rawDebugPortInfo = await debugUtils . promptForDebugPort ( defaultGoDebugPort ) ; } if ( ! rawDebugPortInfo ) { return undefined ; } return { debugPort : Number ( rawDebugPortInfo ) } ; } public filterSupportedProcesses ( processes ) { return processes . filter ( ( processInfo ) => ( processInfo . command . toLowerCase ( ) . startsWith ( 'dlv ' ) || processInfo . command . indexOf ( '/dlv ' ) >= 0 ) ) ; } public isPortRequired ( ) { return true ; } public async getDebugArgs ( ) { return { cancelled : false } ; } }