Skip to content

Commit 31c1f45

Browse files
committed
feat: Go implement GetDebugInfo
Signed-off-by: Fred Rolland <[email protected]>
1 parent cd40b4c commit 31c1f45

File tree

3 files changed

+261
-2
lines changed

3 files changed

+261
-2
lines changed

entrypoint/internal/utils/host/host.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ package host
1818

1919
import (
2020
"context"
21+
"fmt"
22+
"strings"
2123

2224
"github.com/Mellanox/doca-driver-build/entrypoint/internal/utils/cmd"
2325
"github.com/Mellanox/doca-driver-build/entrypoint/internal/wrappers"
@@ -57,8 +59,33 @@ func (h *host) GetOSType(ctx context.Context) (string, error) {
5759

5860
// GetDebugInfo is the default implementation of the host.Interface.
5961
func (h *host) GetDebugInfo(ctx context.Context) (string, error) {
60-
// TODO: add implementation
61-
return "", nil
62+
var debugInfo strings.Builder
63+
64+
// Get OS release information
65+
osReleaseContent, err := h.os.ReadFile("/etc/os-release")
66+
if err != nil {
67+
debugInfo.WriteString(fmt.Sprintf("[os-release]: Error reading /etc/os-release: %v\n", err))
68+
} else {
69+
debugInfo.WriteString(fmt.Sprintf("[os-release]: %s\n", string(osReleaseContent)))
70+
}
71+
72+
// Get kernel information
73+
stdout, stderr, err := h.cmd.RunCommand(ctx, "uname", "-a")
74+
if err != nil {
75+
debugInfo.WriteString(fmt.Sprintf("[uname -a]: Error executing uname -a: %v (stderr: %s)\n", err, stderr))
76+
} else {
77+
debugInfo.WriteString(fmt.Sprintf("[uname -a]: %s\n", stdout))
78+
}
79+
80+
// Get memory information
81+
stdout, stderr, err = h.cmd.RunCommand(ctx, "free", "-m")
82+
if err != nil {
83+
debugInfo.WriteString(fmt.Sprintf("[free -m]: Error executing free -m: %v (stderr: %s)\n", err, stderr))
84+
} else {
85+
debugInfo.WriteString(fmt.Sprintf("[free -m]: %s\n", stdout))
86+
}
87+
88+
return debugInfo.String(), nil
6289
}
6390

6491
// LoadedModule contains information about loaded kernel module.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2025, NVIDIA CORPORATION & AFFILIATES
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package host
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
func TestHost(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
RunSpecs(t, "Host Suite")
29+
}
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*
2+
Copyright 2025, NVIDIA CORPORATION & AFFILIATES
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package host
18+
19+
import (
20+
"context"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
"github.com/stretchr/testify/assert"
25+
26+
cmdMockPkg "github.com/Mellanox/doca-driver-build/entrypoint/internal/utils/cmd/mocks"
27+
osMockPkg "github.com/Mellanox/doca-driver-build/entrypoint/internal/wrappers/mocks"
28+
)
29+
30+
var _ = Describe("Host", func() {
31+
Context("GetDebugInfo", func() {
32+
var (
33+
h Interface
34+
cmdMock *cmdMockPkg.Interface
35+
osMock *osMockPkg.OSWrapper
36+
)
37+
38+
BeforeEach(func() {
39+
cmdMock = cmdMockPkg.NewInterface(GinkgoT())
40+
osMock = osMockPkg.NewOSWrapper(GinkgoT())
41+
h = New(cmdMock, osMock)
42+
})
43+
44+
It("should return debug info with all successful operations", func() {
45+
osReleaseContent := `PRETTY_NAME="Ubuntu 22.04.3 LTS"
46+
NAME="Ubuntu"
47+
VERSION_ID="22.04"
48+
ID=ubuntu`
49+
unameOutput := "Linux hostname 5.15.0-91-generic #101-Ubuntu SMP Thu Nov 16 18:13:39 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux"
50+
freeOutput := ` total used free shared buff/cache available
51+
Mem: 15947 1234 5678 123 8901 14000
52+
Swap: 2048 0 2048`
53+
54+
osMock.EXPECT().ReadFile("/etc/os-release").Return([]byte(osReleaseContent), nil)
55+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return(unameOutput, "", nil)
56+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return(freeOutput, "", nil)
57+
58+
debugInfo, err := h.GetDebugInfo(context.Background())
59+
Expect(err).ToNot(HaveOccurred())
60+
Expect(debugInfo).To(ContainSubstring("[os-release]: " + osReleaseContent))
61+
Expect(debugInfo).To(ContainSubstring("[uname -a]: " + unameOutput))
62+
Expect(debugInfo).To(ContainSubstring("[free -m]: " + freeOutput))
63+
})
64+
65+
It("should handle os-release read error gracefully", func() {
66+
unameOutput := "Linux hostname 5.15.0-91-generic #101-Ubuntu SMP Thu Nov 16 18:13:39 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux"
67+
freeOutput := ` total used free shared buff/cache available
68+
Mem: 15947 1234 5678 123 8901 14000
69+
Swap: 2048 0 2048`
70+
71+
osMock.EXPECT().ReadFile("/etc/os-release").Return(nil, assert.AnError)
72+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return(unameOutput, "", nil)
73+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return(freeOutput, "", nil)
74+
75+
debugInfo, err := h.GetDebugInfo(context.Background())
76+
Expect(err).ToNot(HaveOccurred())
77+
Expect(debugInfo).To(ContainSubstring("[os-release]: Error reading /etc/os-release: assert.AnError general error for testing"))
78+
Expect(debugInfo).To(ContainSubstring("[uname -a]: " + unameOutput))
79+
Expect(debugInfo).To(ContainSubstring("[free -m]: " + freeOutput))
80+
})
81+
82+
It("should handle uname command error gracefully", func() {
83+
osReleaseContent := `PRETTY_NAME="Ubuntu 22.04.3 LTS"
84+
NAME="Ubuntu"
85+
ID=ubuntu`
86+
freeOutput := ` total used free shared buff/cache available
87+
Mem: 15947 1234 5678 123 8901 14000
88+
Swap: 2048 0 2048`
89+
90+
osMock.EXPECT().ReadFile("/etc/os-release").Return([]byte(osReleaseContent), nil)
91+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return("", "command not found", assert.AnError)
92+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return(freeOutput, "", nil)
93+
94+
debugInfo, err := h.GetDebugInfo(context.Background())
95+
Expect(err).ToNot(HaveOccurred())
96+
Expect(debugInfo).To(ContainSubstring("[os-release]: " + osReleaseContent))
97+
Expect(debugInfo).To(ContainSubstring("[uname -a]: Error executing uname -a: assert.AnError general error for testing (stderr: command not found)"))
98+
Expect(debugInfo).To(ContainSubstring("[free -m]: " + freeOutput))
99+
})
100+
101+
It("should handle free command error gracefully", func() {
102+
osReleaseContent := `PRETTY_NAME="Ubuntu 22.04.3 LTS"
103+
NAME="Ubuntu"
104+
ID=ubuntu`
105+
unameOutput := "Linux hostname 5.15.0-91-generic #101-Ubuntu SMP Thu Nov 16 18:13:39 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux"
106+
107+
osMock.EXPECT().ReadFile("/etc/os-release").Return([]byte(osReleaseContent), nil)
108+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return(unameOutput, "", nil)
109+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return("", "permission denied", assert.AnError)
110+
111+
debugInfo, err := h.GetDebugInfo(context.Background())
112+
Expect(err).ToNot(HaveOccurred())
113+
Expect(debugInfo).To(ContainSubstring("[os-release]: " + osReleaseContent))
114+
Expect(debugInfo).To(ContainSubstring("[uname -a]: " + unameOutput))
115+
Expect(debugInfo).To(ContainSubstring("[free -m]: Error executing free -m: assert.AnError general error for testing (stderr: permission denied)"))
116+
})
117+
118+
It("should handle all operations failing gracefully", func() {
119+
osMock.EXPECT().ReadFile("/etc/os-release").Return(nil, assert.AnError)
120+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return("", "command not found", assert.AnError)
121+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return("", "permission denied", assert.AnError)
122+
123+
debugInfo, err := h.GetDebugInfo(context.Background())
124+
Expect(err).ToNot(HaveOccurred())
125+
Expect(debugInfo).To(ContainSubstring("[os-release]: Error reading /etc/os-release: assert.AnError general error for testing"))
126+
Expect(debugInfo).To(ContainSubstring("[uname -a]: Error executing uname -a: assert.AnError general error for testing (stderr: command not found)"))
127+
Expect(debugInfo).To(ContainSubstring("[free -m]: Error executing free -m: assert.AnError general error for testing (stderr: permission denied)"))
128+
})
129+
130+
It("should handle empty outputs from commands", func() {
131+
osReleaseContent := `PRETTY_NAME="Ubuntu 22.04.3 LTS"
132+
NAME="Ubuntu"
133+
ID=ubuntu`
134+
135+
osMock.EXPECT().ReadFile("/etc/os-release").Return([]byte(osReleaseContent), nil)
136+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return("", "", nil)
137+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return("", "", nil)
138+
139+
debugInfo, err := h.GetDebugInfo(context.Background())
140+
Expect(err).ToNot(HaveOccurred())
141+
Expect(debugInfo).To(ContainSubstring("[os-release]: " + osReleaseContent))
142+
Expect(debugInfo).To(ContainSubstring("[uname -a]: \n"))
143+
Expect(debugInfo).To(ContainSubstring("[free -m]: \n"))
144+
})
145+
146+
It("should handle multiline os-release content", func() {
147+
osReleaseContent := `PRETTY_NAME="Red Hat Enterprise Linux 9.2 (Plow)"
148+
NAME="Red Hat Enterprise Linux"
149+
VERSION="9.2 (Plow)"
150+
ID="rhel"
151+
ID_LIKE="fedora"
152+
VERSION_ID="9.2"
153+
PLATFORM_ID="platform:el9"
154+
PRETTY_NAME="Red Hat Enterprise Linux 9.2 (Plow)"
155+
ANSI_COLOR="0;31"
156+
LOGO="fedora-logo-icon"
157+
CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos"
158+
HOME_URL="https://www.redhat.com/"
159+
DOCUMENTATION_URL="https://access.redhat.com/documentation/red_hat_enterprise_linux/9/"
160+
SUPPORT_URL="https://access.redhat.com/support"
161+
BUG_REPORT_URL="https://bugzilla.redhat.com/"
162+
REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9"
163+
REDHAT_BUGZILLA_PRODUCT_VERSION=9.2
164+
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
165+
REDHAT_SUPPORT_PRODUCT_VERSION="9.2"`
166+
unameOutput := "Linux rhel-host 5.14.0-284.11.1.el9_2.x86_64 #1 SMP PREEMPT_DYNAMIC Tue May 9 10:23:07 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux"
167+
freeOutput := ` total used free shared buff/cache available
168+
Mem: 32000 8000 12000 500 12000 23000
169+
Swap: 4096 0 4096`
170+
171+
osMock.EXPECT().ReadFile("/etc/os-release").Return([]byte(osReleaseContent), nil)
172+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return(unameOutput, "", nil)
173+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return(freeOutput, "", nil)
174+
175+
debugInfo, err := h.GetDebugInfo(context.Background())
176+
Expect(err).ToNot(HaveOccurred())
177+
Expect(debugInfo).To(ContainSubstring("[os-release]: " + osReleaseContent))
178+
Expect(debugInfo).To(ContainSubstring("[uname -a]: " + unameOutput))
179+
Expect(debugInfo).To(ContainSubstring("[free -m]: " + freeOutput))
180+
})
181+
182+
It("should handle commands with stderr output but no error", func() {
183+
osReleaseContent := `PRETTY_NAME="Ubuntu 22.04.3 LTS"
184+
NAME="Ubuntu"
185+
ID=ubuntu`
186+
unameOutput := "Linux hostname 5.15.0-91-generic #101-Ubuntu SMP Thu Nov 16 18:13:39 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux"
187+
unameStderr := "warning: some warning message"
188+
freeOutput := ` total used free shared buff/cache available
189+
Mem: 15947 1234 5678 123 8901 14000
190+
Swap: 2048 0 2048`
191+
192+
osMock.EXPECT().ReadFile("/etc/os-release").Return([]byte(osReleaseContent), nil)
193+
cmdMock.EXPECT().RunCommand(context.Background(), "uname", "-a").Return(unameOutput, unameStderr, nil)
194+
cmdMock.EXPECT().RunCommand(context.Background(), "free", "-m").Return(freeOutput, "", nil)
195+
196+
debugInfo, err := h.GetDebugInfo(context.Background())
197+
Expect(err).ToNot(HaveOccurred())
198+
Expect(debugInfo).To(ContainSubstring("[os-release]: " + osReleaseContent))
199+
Expect(debugInfo).To(ContainSubstring("[uname -a]: " + unameOutput))
200+
Expect(debugInfo).To(ContainSubstring("[free -m]: " + freeOutput))
201+
})
202+
})
203+
})

0 commit comments

Comments
 (0)