Debugging Apps Background: Port Forwarding and Debugging Just as we did before with remote shelling into our pods, we can also set up a port-forward between our local machine and our pod. The is useful for operations like connecting to a database running in a pod, viewing an administrative web interface we don’t want to expose to the public, or, in our case, attaching a debugger to the JVM running our application server. You can read more about port-forwarding from the developer documentation. By port forwarding the debugging port for the application server, we can attach the debugger from our IDE and actually step through the code in the pod as it is running in real time. By default EAP is not in debug mode, therefore we first need to turn on the debug ports Exercise: Enabling Debugging in EAP on OpenShift It is very simple to turn on debugging. The EAP S2I container we are using is looking for an environment variable to control whether or not to enable the debug port. All we need to do is set an environment variable for the deployment. oc set env dc/mlbparks DEBUG=true This will force a redeploy of our MLBparks pod, this time with the JDWT transport enabled and serving on port 8787. Whilst we can connect to a Pod directly to debug it, when there is only one instance of a Pod running it can be convenient to setup port-forwarding through a Service (since Pod names change but the name of the Service is static). See Exercise: Port-Forwarding from the pod to our local machine Port-Forwarding through a Service to our local machine Let’s take a closer look at the service in question: oc describe svc/mlbparks Name: mlbparks Namespace: workshop Labels: app=workshop component=mlbparks createdBy=mlbparks-template role=backend type=parksmap-backend Annotations: openshift.io/generated-by: OpenShiftNewApp service.alpha.openshift.io/dependencies: [{"name":"mongodb-mlbparks","namespace":"","kind":"Service"}] Selector: deploymentConfig=mlbparks Type: ClusterIP IP Families: <none> IP: 172.21.206.162 IPs: <none> Port: 8080-tcp 8080/TCP TargetPort: 8080/TCP Endpoints: 172.30.18.203:8080 Port: 8787-tcp 8787/TCP TargetPort: 8787/TCP Endpoints: 172.30.18.203:8787 Session Affinity: None Events: <none> Now that our deployment is setup for debugging, it will be listening on port 8787. We’ll setup port-forwarding to that port on the service (which will in turn forward on to the pod) oc port-forward svc/mlbparks 8787:8787 So now when we connect on localhost:8787 it will get forwarded to the mlbparks instance running in the pod. port-forwarding is only active as long as the oc port-forward command is allowed to run. Since we run it in the foreground, we are able to stop port-forwarding by hitting CTRL+c (or CMD+c on a Mac) Now all we need to do is find a debugger to connect on that port Attaching a Remote Debugger In order to debug the source code you can either use your IDE of choice (instructions for IntelliJ below) or you can debug from the Console. Pick the appropriate tab for your situation. Console IntelliJ NOTE This assumes you have jdb the Java command line debugger installed. If you don’t, you can see these instructions for running a docker container that has Maven AND the jdb installed. Once you have completed those instructions, from within the container setup port-forwarding as discussed above. Then follow the instructions below from within the container. From the root of the mlbparks git repo that you cloned locally, run the following command: jdb -sourcepath $(pwd)/src/main/java -attach localhost:8787 Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > Next, set a breakpoint in the BackendController class by issuing this command in the debugger: stop in com.openshift.evg.roadshow.rest.BackendController.get Set breakpoint com.openshift.evg.roadshow.rest.BackendController.get Navigate to the mlbparks url (you can use curl from a shell or just paste the url in your browser) curl http://mlbparks-workshop.%CLUSTER_SUBDOMAIN%/ws/info Your debugger should now be "breaked" at the first line of the BackendController.get method Breakpoint hit: "thread=default task-4", com.openshift.evg.roadshow.rest.BackendController.get(), line=23 bci=0 23 return new Backend("mlbparks", "AMAZING MLB Parks", new Coordinates("39.82", "-98.57"), 5); Feel free to play around a bit with the jdb commands. Some examples include: list: To see fuller view of source around the breakpoint where: To dump the thread’s current stack print: Print value of variables, such as print this to see the BackendController as string cont: Continue execution of the program Setting up remote debugging is quite easy in IntelliJ. First edit the run/debug configurations. Under the Run menu (ALT+u), choose edit configurations. This will bring up the new configuration dialog. Click the plus in the top left corner, scroll down, and choose remote. On the resulting dialog page, change the name at the top to "on OpenShift" or whatever is informative to you. Then towards the bottom right, change the port number to 8787. When you have done that click "OK". Now when you click the Debug icon in IntelliJ, it will open the debugger and attach to JVM in the pod on OpenShift. Go ahead and set a break point in any class you want and it will do normal debugging - just like you know and love! Exercise: Port-Forwarding from the pod to our local machine It is quite simple to do port-forwarding. First get the pods: oc get pods NAME READY STATUS RESTARTS AGE mlbparks-1-build 0/1 Completed 0 4d mlbparks-1-deploy 0/1 Completed 0 4d mlbparks-1-hook-post 0/1 Completed 0 4d mlbparks-2-build 0/1 Completed 0 10m mlbparks-2-deploy 0/1 Completed 0 9m49s mlbparks-2-hook-post 0/1 Completed 0 8m59s mlbparks-3-deploy 1/1 Running 0 25s mlbparks-3-hcd8g 0/1 Running 0 10s ... Now we can set to set up the port-forward: oc port-forward mlbparks-3-hcd8g 8787:8787 We said to port-forward from port 8787 on the pod to 8787 on the local machine. Now we can attach a remote debugger as outlined here. Binary Builds Further Resources