Skip to content

Commit 8000d67

Browse files
committed
feat: Go support for OS discovery
Signed-off-by: Fred Rolland <[email protected]>
1 parent dd44d4e commit 8000d67

File tree

12 files changed

+706
-11
lines changed

12 files changed

+706
-11
lines changed

entrypoint/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
3838
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
3939
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
4040
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
41-
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
42-
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
4341
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
4442
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
4543
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
4644
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
4745
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
4846
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
47+
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
48+
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
4949
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
5050
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
5151
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

entrypoint/internal/constants/constants.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,13 @@ const (
2121

2222
DriverContainerModeSources = "sources"
2323
DriverContainerModePrecompiled = "precompiled"
24+
25+
// OS Types
26+
OSTypeUbuntu = "ubuntu"
27+
OSTypeSLES = "sles"
28+
OSTypeRedHat = "redhat"
29+
30+
// Default versions
31+
DefaultRHELVersion = "8.4"
32+
DefaultOpenShiftVersion = "4.9"
2433
)

entrypoint/internal/driver/mocks/Interface.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

entrypoint/internal/netconfig/mocks/Interface.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

entrypoint/internal/utils/cmd/mocks/Interface.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

entrypoint/internal/utils/host/host.go

Lines changed: 154 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ package host
1818

1919
import (
2020
"context"
21+
"fmt"
22+
"regexp"
23+
"strconv"
24+
"strings"
25+
"sync"
2126

27+
"github.com/Mellanox/doca-driver-build/entrypoint/internal/constants"
2228
"github.com/Mellanox/doca-driver-build/entrypoint/internal/utils/cmd"
2329
"github.com/Mellanox/doca-driver-build/entrypoint/internal/wrappers"
2430
)
@@ -31,6 +37,17 @@ func New(c cmd.Interface, osWrapper wrappers.OSWrapper) Interface {
3137
}
3238
}
3339

40+
// RedhatVersionInfo contains version information for RedHat-based distributions
41+
type RedhatVersionInfo struct {
42+
// MajorVersion is the major version number (e.g., 8, 9)
43+
MajorVersion int
44+
// FullVersion is the complete version string (e.g., "8.4", "9.2")
45+
FullVersion string
46+
// OpenShiftVersion is the OpenShift version if running on RHCOS (e.g., "4.9")
47+
// If empty, this is not RHCOS
48+
OpenShiftVersion string
49+
}
50+
3451
// Interface is the interface exposed by the host package.
3552
type Interface interface {
3653
// GetOSType returns the name of the operating system as a string.
@@ -42,17 +59,60 @@ type Interface interface {
4259
LsMod(ctx context.Context) (map[string]LoadedModule, error)
4360
// RmMod unload the kernel module.
4461
RmMod(ctx context.Context, module string) error
62+
// GetRedHatVersionInfo parses RedHat version information from /host/etc/os-release
63+
// and returns version details. Should only be called for RedHat-based distributions.
64+
GetRedHatVersionInfo(ctx context.Context) (*RedhatVersionInfo, error)
4565
}
4666

4767
type host struct {
4868
cmd cmd.Interface
4969
os wrappers.OSWrapper
70+
71+
// Cache for OS type
72+
osTypeCache struct {
73+
value string
74+
err error
75+
once sync.Once
76+
}
77+
78+
// Cache for RedHat version info
79+
redhatVersionCache struct {
80+
value *RedhatVersionInfo
81+
err error
82+
once sync.Once
83+
}
5084
}
5185

5286
// GetOSType is the default implementation of the host.Interface.
5387
func (h *host) GetOSType(ctx context.Context) (string, error) {
54-
// TODO: add implementation
55-
return "", nil
88+
h.osTypeCache.once.Do(func() {
89+
// Read /etc/os-release file to determine OS type
90+
osReleaseContent, err := h.os.ReadFile("/etc/os-release")
91+
if err != nil {
92+
h.osTypeCache.err = err
93+
return
94+
}
95+
96+
osReleaseStr := string(osReleaseContent)
97+
osReleaseStr = strings.ToLower(osReleaseStr)
98+
99+
// Check for Ubuntu (case insensitive)
100+
if strings.Contains(osReleaseStr, "ubuntu") {
101+
h.osTypeCache.value = constants.OSTypeUbuntu
102+
return
103+
}
104+
105+
// Check for SLES (case insensitive)
106+
if strings.Contains(osReleaseStr, "sles") {
107+
h.osTypeCache.value = constants.OSTypeSLES
108+
return
109+
}
110+
111+
// Default to redhat for other distributions (RHEL, CentOS, Fedora, etc.)
112+
h.osTypeCache.value = constants.OSTypeRedHat
113+
})
114+
115+
return h.osTypeCache.value, h.osTypeCache.err
56116
}
57117

58118
// GetDebugInfo is the default implementation of the host.Interface.
@@ -83,3 +143,95 @@ func (h *host) RmMod(ctx context.Context, module string) error {
83143
// TODO: add implementation
84144
return nil
85145
}
146+
147+
// GetRedHatVersionInfo is the default implementation of the host.Interface.
148+
func (h *host) GetRedHatVersionInfo(ctx context.Context) (*RedhatVersionInfo, error) {
149+
h.redhatVersionCache.once.Do(func() {
150+
// First check if this is a RedHat-based system
151+
osType, err := h.GetOSType(ctx)
152+
if err != nil {
153+
h.redhatVersionCache.err = fmt.Errorf("failed to get OS type: %w", err)
154+
return
155+
}
156+
157+
if osType != constants.OSTypeRedHat {
158+
h.redhatVersionCache.err = fmt.Errorf("GetRedHatVersionInfo should only be called for RedHat-based distributions, got: %s", osType)
159+
return
160+
}
161+
162+
// Read /host/etc/os-release file
163+
osReleaseContent, err := h.os.ReadFile("/host/etc/os-release")
164+
if err != nil {
165+
h.redhatVersionCache.err = fmt.Errorf("failed to read /host/etc/os-release: %w", err)
166+
return
167+
}
168+
169+
osReleaseStr := string(osReleaseContent)
170+
171+
// Parse the os-release content
172+
versionInfo := &RedhatVersionInfo{}
173+
174+
// Extract ID, VERSION_ID, RHEL_VERSION, and OPENSHIFT_VERSION
175+
var id, versionID, rhelVersion, openshiftVersion string
176+
177+
idMatch := regexp.MustCompile(`(?m)^ID=(.+)$`).FindStringSubmatch(osReleaseStr)
178+
if len(idMatch) > 1 {
179+
id = strings.Trim(idMatch[1], `"`)
180+
}
181+
182+
versionIDMatch := regexp.MustCompile(`(?m)^VERSION_ID=(.+)$`).FindStringSubmatch(osReleaseStr)
183+
if len(versionIDMatch) > 1 {
184+
versionID = strings.Trim(versionIDMatch[1], `"`)
185+
}
186+
187+
rhelVersionMatch := regexp.MustCompile(`(?m)^RHEL_VERSION=(.+)$`).FindStringSubmatch(osReleaseStr)
188+
if len(rhelVersionMatch) > 1 {
189+
rhelVersion = strings.Trim(rhelVersionMatch[1], `"`)
190+
}
191+
192+
openshiftVersionMatch := regexp.MustCompile(`(?m)^OPENSHIFT_VERSION=(.+)$`).FindStringSubmatch(osReleaseStr)
193+
if len(openshiftVersionMatch) > 1 {
194+
openshiftVersion = strings.Trim(openshiftVersionMatch[1], `"`)
195+
}
196+
197+
if id == "rhcos" {
198+
// This is RHCOS - use OpenShift version logic
199+
if openshiftVersion != "" {
200+
versionInfo.OpenShiftVersion = openshiftVersion
201+
} else {
202+
versionInfo.OpenShiftVersion = versionID
203+
}
204+
if versionInfo.OpenShiftVersion == "" {
205+
versionInfo.OpenShiftVersion = constants.DefaultOpenShiftVersion
206+
}
207+
versionInfo.FullVersion = versionInfo.OpenShiftVersion
208+
} else {
209+
// For RHEL and other RedHat-based distros (CentOS, Fedora, etc.)
210+
versionInfo.FullVersion = rhelVersion
211+
if versionInfo.FullVersion == "" {
212+
versionInfo.FullVersion = versionID
213+
}
214+
if versionInfo.FullVersion == "" {
215+
versionInfo.FullVersion = constants.DefaultRHELVersion
216+
}
217+
218+
// If OPENSHIFT_VERSION is present, this might be RHCOS with ID=rhel
219+
if openshiftVersion != "" {
220+
versionInfo.OpenShiftVersion = openshiftVersion
221+
}
222+
}
223+
224+
// Extract major version from full version
225+
majorVersionStr := strings.Split(versionInfo.FullVersion, ".")[0]
226+
majorVersion, err := strconv.Atoi(majorVersionStr)
227+
if err != nil {
228+
h.redhatVersionCache.err = fmt.Errorf("failed to parse major version from '%s': %w", versionInfo.FullVersion, err)
229+
return
230+
}
231+
versionInfo.MajorVersion = majorVersion
232+
233+
h.redhatVersionCache.value = versionInfo
234+
})
235+
236+
return h.redhatVersionCache.value, h.redhatVersionCache.err
237+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package host
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestHost(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Host Suite")
13+
}

0 commit comments

Comments
 (0)