/ by

Debug your Python and Pulumi Code

Introduction

This article aims to serve as a guide on how to debug your code where you have implemented Python programming language and Pulumi.

Prerequisites

In order to successfully go through the steps below, you need to have:

  • a new Pulumi scaffold created
  • debugpy installed (a debugger for Python)

Code

In your Python code (in particular, your runnable file), you need to create a variable that will hold the current environment you are using (debug, dev, prod, etc). It will look like this:

It is important to add a check whether the “isDebug” variable is true. If it is true, we attach the debugger and in that way, we will be able to use the same script file without having to change it every time we switch from one environment to another.

Launch.json file

The next thing that we will need is launch.json file.

The launch.json file as well as the tasks.json file (we will talk about it later in this article) should be located in the .vscode folder of your project.

We need to add three more properties in addition to the ones in the default Python attachment file:

  1. “request”: “attach” – this property means that we want to connect to an already existing project and not to start a new one
  2. “justMyCode”: false – when set to false, it allows us to enter library’s code
  3. “preLaunchTask”: “<name_of_task>“ – here we indicate the name of the task that will be called before the start of the debug session for your Python code

Tasks – tasks.json file

The configuration of the tasks is in a separate file called tasks.json. As we pointed out earlier, this file is created in the .vscode folder of your project.

Task One – Wait until Pulumi starts

The properties configured here help us reproduce a functionality where we “wait” for Pulumi to start:

  1. “label” – property for the name of the task
  2. “type”: “shell” – indicates that it will be called within a terminal
  3. “windows”, “linux”, and “osx” (Mac) properties – describe how the code will behave on different OS; the “command” property indicates what exactly will be run within the terminal
  4. “dependsOn” – this is the most important field; it specifies which tasks should be run before the current task
  5. “presentation” – when the “close” property is set to true, that forces the terminal to close (the one that up until this moment runs the sleep commands)

Task Two – Pulumi preview

Here we configure a task where we preview the updates of the existing stack’s resources:

  1. “command” – we call “pulumi preview” and pass a path to a config file
    1. Note: If you want, you can use “pulumi up” instead of “pulumi preview” so that the stack’s resources will be updated
    2. Note: If we pass a raw value as an argument, Pulumi will save the value to the configuration file and this will break the normal runs of Pulumi (it will save the debug key to the normal preview). That is why here we pass the file path so we can use the values that we have configured in our “debug.yaml” file.
  2. “isBackground”- this means that the task will be working in a second thread and won’t force the debugger to wait until Pulumi finishes. This prevents a dead loop such as “Pulumi waits for the debugger, and the debugger waits for the Pulumi”.

Another thing to configure is the “problemMatcher” property for “windows”, “linux”, and “osx”- it specifies when the task should start and end. The “pattern” property is for catching messages in the “Problems” tab of VS code and the “background” property is for messages in the terminal output, so in our case, we will configure and use the “background” property.

On Windows, the terminal outputs the Pulumi messages in real-time, so Pulumi will be counted as a blocker from any symbol input – this is indicated by “activeOnStart” and “beginsPattern” properties. On the other side, for the “endsPattern” property we specify the “Debugging” string because debugpy outputs a message that it is waiting and we catch this message. After a few milliseconds the “Wait until pulumi start” task starts. On Windows, it will wait a few more milliseconds before running the code so that VS code and debugpy are fully ready.

On Linux and Mac, we don’t receive debug messages from Pulumi until it fully stops so here “background” will start and end with any symbol. After that, the operation system will wait 3 seconds as it is described in “Wait until Pulumi start” Linux or OSX section. (After some testing, we discovered that 3 seconds is enough to start and be able to attach. You can change this number according to your system’s needs)

See the three configurations below for comparison (note that the configurations for Linux and OSX are the same):

Debug config file

After going through all the steps above, we are ready to create and configure our “debug.yaml” file. It is mandatory only to specify your project name; the other attributes are of your choice. It will look something like this:

Conclusion

Now you are ready to debug your Python application. Note that in most cases you won’t be able to see the actual network requests because Pulumi splits the logic into three separate threads. In one of the next articles, we will describe how to debug the provider that is responsible for creating, deleting, and updating the resources.

Contact us

Get in touch and ask us anything. We're happy to answer every single one of your questions.

  • 6A Maria Luiza Blvd, Plovdiv
    4000, Bulgaria
  • Ulpia Tech LinkedIn Ulpia Tech Twitter


    To top