311 lines
11 KiB
ReStructuredText
311 lines
11 KiB
ReStructuredText
=========
|
|
Debugging
|
|
=========
|
|
|
|
Whether developing a new feature or fixing a bug, using the automated
|
|
test suite together with a debugger is a potent combination. This
|
|
guide here can't substitute for full documentation on a given
|
|
debugger; but it might help you get started debugging Warewulf.
|
|
|
|
Validating the code with vet
|
|
============================
|
|
|
|
The Warewulf ``Makefile`` includes a ``vet`` target which runs ``go
|
|
vet`` on the full codebase.
|
|
|
|
.. code-block:: console
|
|
|
|
$ make vet
|
|
|
|
|
|
Running the full test suite
|
|
===========================
|
|
|
|
The Warewulf ``Makefile`` includes a ``test`` target which runs the
|
|
full test suite.
|
|
|
|
.. code-block:: console
|
|
|
|
$ make test
|
|
|
|
|
|
Using delve
|
|
===========
|
|
|
|
If you have a failing test but you're having trouble tracking down
|
|
why, try using a debugger to step through the test. These instructions
|
|
use delve.
|
|
|
|
|
|
Installing delve
|
|
----------------
|
|
|
|
You can install delve as a regular user directly with Go.
|
|
|
|
.. code-block:: console
|
|
|
|
$ go install github.com/go-delve/delve/cmd/dlv@latest
|
|
|
|
The ``dlv`` binary will be installed by default at
|
|
``$HOME/go/bin/dlv``. You can, of course, add ``$HOME/go/bin`` to your
|
|
path if you prefer.
|
|
|
|
.. code-block:: console
|
|
|
|
$ PATH=$HOME/go/bin:$PATH
|
|
|
|
|
|
Running delve against a specific test
|
|
-------------------------------------
|
|
|
|
You can use delve to specifically run the test suite and, even more
|
|
specifically, a single failing test. In this example delve is
|
|
instructed to run the tests for Warewulf's ``node`` package, and
|
|
specifically the ``Test_GetAllNodeInfoDefaults`` test.
|
|
|
|
.. code-block:: console
|
|
|
|
$ dlv test github.com/warewulf/warewulf/internal/pkg/node -- -test.v -test.run Test_GetAllNodeInfoDefaults
|
|
Type 'help' for list of commands.
|
|
(dlv) break node.Test_GetAllNodeInfoDefaults
|
|
Breakpoint 1 set at 0x26c0d0 for github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51
|
|
|
|
Setting a breakpoint at ``node.Test_GetAllNodeInfoDefaults`` pauses
|
|
execution once the test starts, and allows us to ``continue`` through
|
|
all the setup prior to that point.
|
|
|
|
.. code-block:: console
|
|
|
|
(dlv) continue
|
|
=== RUN Test_GetAllNodeInfoDefaults
|
|
> github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 (hits goroutine(35):1 total:1) (PC: 0x26c0d0)
|
|
46: assert.Contains(t, nodeYaml.Nodes, "test_node")
|
|
47: assert.Equal(t, "A single node", nodeYaml.Nodes["test_node"].Comment)
|
|
48: }
|
|
49:
|
|
50:
|
|
=> 51: func Test_GetAllNodeInfoDefaults(t *testing.T) {
|
|
52: file, writeErr := writeTestConfigFile(`
|
|
53: nodes:
|
|
54: test_node: {}`)
|
|
55: if file != nil {
|
|
56: defer os.Remove(file.Name())
|
|
|
|
Helpful commands from here include
|
|
|
|
``next``
|
|
|
|
Execute the current line (marked by ``=>``) and proceed to the next
|
|
line.
|
|
|
|
``step``
|
|
|
|
Execute the current line (marked by ``=>``) and proceed to the next
|
|
line, potentially moving into a function call.
|
|
|
|
``list``
|
|
|
|
Display a contextual Go code listing, marking the next instruction.
|
|
|
|
``locals``
|
|
|
|
Display all local variables in the current scope.
|
|
|
|
``print``
|
|
|
|
Display (in detail) the value of a single variable from the current
|
|
scope.
|
|
|
|
Read about other commands available within delve using the ``help``
|
|
command.
|
|
|
|
|
|
Example debugging session
|
|
-------------------------
|
|
|
|
.. code-block:: console
|
|
|
|
$ ~/go/bin/dlv test github.com/warewulf/warewulf/internal/pkg/node -- -test.v -test.run Test_GetAllNodeInfoDefaults
|
|
Type 'help' for list of commands.
|
|
|
|
(dlv) break node.Test_GetAllNodeInfoDefaults
|
|
Breakpoint 1 set at 0x26c0d0 for github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51
|
|
|
|
(dlv) break nodeinfo.go:417
|
|
Breakpoint 2 set at 0x267f18 for github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:417
|
|
|
|
(dlv) continue
|
|
=== RUN Test_GetAllNodeInfoDefaults
|
|
> github.com/warewulf/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 (hits goroutine(19):1 total:1) (PC: 0x26c0d0)
|
|
46: assert.Contains(t, nodeYaml.Nodes, "test_node")
|
|
47: assert.Equal(t, "A single node", nodeYaml.Nodes["test_node"].Comment)
|
|
48: }
|
|
49:
|
|
50:
|
|
=> 51: func Test_GetAllNodeInfoDefaults(t *testing.T) {
|
|
52: file, writeErr := writeTestConfigFile(`
|
|
53: nodes:
|
|
54: test_node: {}`)
|
|
55: if file != nil {
|
|
56: defer os.Remove(file.Name())
|
|
|
|
(dlv) continue
|
|
WARN : Error reading UNDEF/warewulf/defaults.conf: open UNDEF/warewulf/defaults.conf: no such file or directory
|
|
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:417 (hits goroutine(19):1 total:1) (PC: 0x267f18)
|
|
412: defaultNodeConf.NetDevs = nil
|
|
413: nodeInfo.SetDefFrom(defaultNodeConf)
|
|
414: }
|
|
415:
|
|
416: // Load normal attributes
|
|
=> 417: if nodeConf != nil {
|
|
418: // If no profiles are included, automatically include the
|
|
419: // default profile.
|
|
420: if len(nodeConf.Profiles) == 0 {
|
|
421: nodeInfo.Profiles.SetSlice([]string{"default"})
|
|
422: } else {
|
|
|
|
(dlv) next
|
|
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:420 (PC: 0x267f24)
|
|
415:
|
|
416: // Load normal attributes
|
|
417: if nodeConf != nil {
|
|
418: // If no profiles are included, automatically include the
|
|
419: // default profile.
|
|
=> 420: if len(nodeConf.Profiles) == 0 {
|
|
421: nodeInfo.Profiles.SetSlice([]string{"default"})
|
|
422: } else {
|
|
423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles)
|
|
424: }
|
|
425:
|
|
|
|
(dlv) next
|
|
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:421 (PC: 0x267f3c)
|
|
416: // Load normal attributes
|
|
417: if nodeConf != nil {
|
|
418: // If no profiles are included, automatically include the
|
|
419: // default profile.
|
|
420: if len(nodeConf.Profiles) == 0 {
|
|
=> 421: nodeInfo.Profiles.SetSlice([]string{"default"})
|
|
422: } else {
|
|
423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles)
|
|
424: }
|
|
425:
|
|
426: nodeInfo.SetFrom(nodeConf)
|
|
|
|
(dlv) next
|
|
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:426 (PC: 0x267fec)
|
|
421: nodeInfo.Profiles.SetSlice([]string{"default"})
|
|
422: } else {
|
|
423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles)
|
|
424: }
|
|
425:
|
|
=> 426: nodeInfo.SetFrom(nodeConf)
|
|
427: }
|
|
428:
|
|
429: // Load default attributes for each NetDev
|
|
430: if defaultNetDevConf != nil {
|
|
431: for _, netdev := range nodeInfo.NetDevs {
|
|
|
|
(dlv) next
|
|
> github.com/warewulf/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:430 (PC: 0x268000)
|
|
425:
|
|
426: nodeInfo.SetFrom(nodeConf)
|
|
427: }
|
|
428:
|
|
429: // Load default attributes for each NetDev
|
|
=> 430: if defaultNetDevConf != nil {
|
|
431: for _, netdev := range nodeInfo.NetDevs {
|
|
432: netdev.SetDefFrom(defaultNetDevConf)
|
|
433: }
|
|
434: }
|
|
435:
|
|
|
|
(dlv) print nodeInfo
|
|
github.com/warewulf/warewulf/internal/pkg/node.NodeInfo {
|
|
Id: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 1, cap: 1, [
|
|
"test_node",
|
|
],
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 0, cap: 0, nil,},
|
|
Comment: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 0, cap: 0, nil,},
|
|
ClusterName: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 0, cap: 0, nil,},
|
|
ContainerName: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 0, cap: 0, nil,},
|
|
Ipxe: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 1, cap: 1, ["default"],},
|
|
RuntimeOverlay: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 1, cap: 1, ["generic"],},
|
|
SystemOverlay: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 1, cap: 1, ["wwinit"],},
|
|
Root: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 1, cap: 1, [
|
|
"initramfs",
|
|
],},
|
|
Discoverable: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 0, cap: 0, nil,},
|
|
Init: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 1, cap: 1, [
|
|
"/sbin/init",
|
|
],},
|
|
AssetKey: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 0, cap: 0, nil,},
|
|
Kernel: *github.com/warewulf/warewulf/internal/pkg/node.KernelEntry {
|
|
Override: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x4000158370),
|
|
Args: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001583c8),},
|
|
Ipmi: *github.com/warewulf/warewulf/internal/pkg/node.IpmiEntry {
|
|
Ipaddr: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6600),
|
|
Netmask: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6658),
|
|
Port: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b66b0),
|
|
Gateway: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6708),
|
|
UserName: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6760),
|
|
Password: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b67b8),
|
|
Interface: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6810),
|
|
Write: (*"github.com/warewulf/warewulf/internal/pkg/node.Entry")(0x40001b6868),
|
|
Tags: map[string]*github.com/warewulf/warewulf/internal/pkg/node.Entry [],},
|
|
Profiles: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 1, cap: 1, ["default"],
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 1, cap: 1, ["default"],},
|
|
PrimaryNetDev: github.com/warewulf/warewulf/internal/pkg/node.Entry {
|
|
value: []string len: 0, cap: 0, nil,
|
|
altvalue: []string len: 0, cap: 0, nil,
|
|
from: "",
|
|
def: []string len: 0, cap: 0, nil,},
|
|
NetDevs: map[string]*github.com/warewulf/warewulf/internal/pkg/node.NetDevEntry [],
|
|
Tags: map[string]*github.com/warewulf/warewulf/internal/pkg/node.Entry [],}
|