Debugging#
Generic debugging capabilities first introduced in 25.4.1
EDA script apps run in a remote execution environment (config or state engine, depending on the script type) and this makes the usual debugging techniques not easy to apply. Adding print
statements to the script files and fish for a printed message in a potentially very crowded stream of logs messages is not a great developer experience.
Yet, it is crucial to give developers a way to introspect the data their scripts operate on or produce. And EDA has a built-in mechanism to help with that.
edactl
debug#
If you look at the demo banners
application scaffolded by edabuilder
, you will notice that both configuration and state scripts1 have the log_msg
2 function; it is used to log debug messages in such a way that can be intercepted by the edactl
tool and printed out for you on demand. During the normal application operation no debug messages are being printed, they are only printed when a developer uses edactl intent debug
command.
To start debugging a state or a configuration script, use the following command:
Let's see how this debugging workflow works.
Logging and monitoring#
To get us a clean start, let's remove any instances of the Banner resource from your cluster:
We will start with a basic task of seeing what exactly happens within our Banner application when we create the Banner resource. We can use the edactl intent config debug <config resource kind>
command to start monitoring the logs of this app.
Split the shell in two panes, and start the debug monitor in the left pane:
This starts a debug monitor for the configuration intent of the banners
app. The associated intent script is going to run when we create the Banner resource that triggers the script to run in the config engine pod. Let's create one in the right panel:
cat << 'EOF' | kubectl -n eda apply -f -
apiVersion: banners.eda.local/v1alpha1
kind: Banner
metadata:
name: demo-banner
namespace: eda
spec:
nodes:
- leaf11
loginBanner: Hello EDA!
EOF
Immediately after creating the Banner resource you should see the debug messages appear in the left pane:
The debug monitor will show the Input CR
that triggered the intent script to run as well as every log_msg
function call. For instance, the following output that you find in the output:
Banner CR:
{"metadata": {"name": "demo-banner", "namespace": "eda"}, "kind": "Banner", "spec": {"loginBanner": "Hello EDA!", "nodes": ["leaf11"]}}
comes from the log_msg
function defined in the config_intent.py
script of the Banner app:
from utils.log import log_msg
def process_cr(cr):
"""Process Banner CR."""
log_msg("Banner CR:", dict=cr) #(1)!
- This log message is rudimentary, since the Input CR is printed by default by the debug monitor.
You can also see that the debug output outputs any Errors raised during the script execution, and we happen to have one in the script:
Error:
Traceback (most recent call last):
File "banners/intents/banner/config_intent.py", line 40, in process_cr
Having a look at the line 40 in our config_intent.py
file we can spot what raises that:
- The error is raised using the utility module
import utils.exceptions as e
which has different classes for different types of errors.
Since our input CR provided a node name in the nodes
field of the spec, the script went up querying the TopoNode resources for the one with the name leaf11
, but our topology does not have such a node. This raised an error and our script execution stopped. Thanks to edactl intent debug
we can clearly find the error in the logs.
Let's fix our typo in the node name by passing a corrected Banner resource that references the leaf-1
node that we have in our topology:
cat << 'EOF' | kubectl -n eda apply -f -
apiVersion: banners.eda.local/v1alpha1
kind: Banner
metadata:
name: demo-banner
namespace: eda
spec:
nodes:
- leaf-1
loginBanner: Hello EDA!
EOF
With the corrected resource our debug monitor shows that the script completes and displays the resources the script generated and written to the EDB:
The config script for the Banner app generated two custom resources during its run:
BannerState
resource to trigger the state scriptNodeConfig
resource that contains the configuration snippets for the nodes matching our node selection.
Similarly, you can debug state scripts by changing the command to edactl -n <namespace> intent state debug <state resource kind>
Triggering your resource#
In the previous section we triggered the configuration script execution by creating or changing the Banner
resource. But during the development cycle it is not convenient to delete+add or modify the resource whenever you want the config or state script to run.
To assist with this workflow, the debug
subcommand is equipped with the --trigger | -t
flag that can be used to trigger the associated script to run as if the resource was created or changed. Here is a demonstration of this in action.
If we were to start the debug monitor for the bannerstate resource just like before, we would not see anything in the output, because the BannerState resource has been created once the config script finished execution.
If we want to run our state script again without republishing BannerState CR, we could add the -t
flag to the command, and this would trigger the script execution with the same BannerState CR passed to it as was recorded before:
The trigger flag can be added to both config and state intents.