Skip to content

Commit 9ea2eba

Browse files
authored
providers/linux/os.go - Get OS info from Manjaro Linux (#183)
Manjaro was not working as expected because the `DISTRIB_RELEASE` value was never used to get the OS version. There was no OS distribution family for "arch". So this maps Majaro as part of the "arch" family along with Arch Linux itself and Antergos. Added an additional fallback to use the `ID_LIKE` field in `os-release` to determine the OS distribution family. I replaced the deprecated `io/ioutil` with the `os` package. Fixes #168
1 parent 7185883 commit 9ea2eba

File tree

10 files changed

+120
-22
lines changed

10 files changed

+120
-22
lines changed

.changelog/183.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
linux: Added an `os.Family` mapping for Arch Linux based distributions.
3+
```
4+
5+
```release-note:bug
6+
linux: Fix OS metadata collection for Manjaro Linux.
7+
```

providers/linux/os.go

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"bufio"
2222
"bytes"
2323
"fmt"
24-
"io/ioutil"
2524
"os"
2625
"path/filepath"
2726
"regexp"
@@ -50,12 +49,13 @@ var (
5049

5150
// familyMap contains a mapping of family -> []platforms.
5251
var familyMap = map[string][]string{
52+
"arch": {"arch", "antergos", "manjaro"},
5353
"redhat": {
5454
"redhat", "fedora", "centos", "scientific", "oraclelinux", "ol",
5555
"amzn", "rhel", "almalinux", "openeuler", "rocky",
5656
},
5757
"debian": {"debian", "ubuntu", "raspbian", "linuxmint"},
58-
"suse": {"suse", "sles", "opensuse", "opensuse-leap", "opensuse-tumbleweed"},
58+
"suse": {"suse", "sles", "opensuse"},
5959
}
6060

6161
var platformToFamilyMap map[string]string
@@ -99,9 +99,9 @@ func getOSInfo(baseDir string) (*types.OSInfo, error) {
9999
}
100100

101101
func getOSRelease(baseDir string) (*types.OSInfo, error) {
102-
lsbRel, _ := ioutil.ReadFile(filepath.Join(baseDir, lsbRelease))
102+
lsbRel, _ := os.ReadFile(filepath.Join(baseDir, lsbRelease))
103103

104-
osRel, err := ioutil.ReadFile(filepath.Join(baseDir, osRelease))
104+
osRel, err := os.ReadFile(filepath.Join(baseDir, osRelease))
105105
if err != nil {
106106
return nil, err
107107
}
@@ -150,21 +150,15 @@ func parseOSRelease(content []byte) (*types.OSInfo, error) {
150150
func makeOSInfo(osRelease map[string]string) (*types.OSInfo, error) {
151151
os := &types.OSInfo{
152152
Type: "linux",
153-
Platform: osRelease["ID"],
154-
Name: osRelease["NAME"],
155-
Version: osRelease["VERSION"],
153+
Platform: firstOf(osRelease, "ID", "DISTRIB_ID"),
154+
Name: firstOf(osRelease, "NAME", "PRETTY_NAME"),
155+
Version: firstOf(osRelease, "VERSION", "VERSION_ID", "DISTRIB_RELEASE"),
156156
Build: osRelease["BUILD_ID"],
157-
Codename: osRelease["VERSION_CODENAME"],
158-
}
159-
160-
if os.Version == "" {
161-
// Fallback to VERSION_ID if VERSION is empty.
162-
os.Version = osRelease["VERSION_ID"]
157+
Codename: firstOf(osRelease, "VERSION_CODENAME", "DISTRIB_CODENAME"),
163158
}
164159

165160
if os.Codename == "" {
166-
// Some OSes uses their own CODENAME keys (e.g UBUNTU_CODENAME) or we
167-
// can get the DISTRIB_CODENAME value from the lsb-release data.
161+
// Some OSes use their own CODENAME keys (e.g UBUNTU_CODENAME).
168162
for k, v := range osRelease {
169163
if strings.Contains(k, "CODENAME") {
170164
os.Codename = v
@@ -174,10 +168,19 @@ func makeOSInfo(osRelease map[string]string) (*types.OSInfo, error) {
174168
}
175169

176170
if os.Platform == "" {
177-
// Fallback to the first word of the NAME field.
178-
parts := strings.SplitN(os.Name, " ", 2)
179-
if len(parts) > 0 {
180-
os.Platform = strings.ToLower(parts[0])
171+
// Fallback to the first word of the Name field.
172+
os.Platform, _, _ = strings.Cut(os.Name, " ")
173+
}
174+
175+
os.Family = linuxFamily(os.Platform)
176+
if os.Family == "" {
177+
// ID_LIKE is a space-separated list of OS identifiers that this
178+
// OS is similar to. Use this to figure out the Linux family.
179+
for _, id := range strings.Fields(osRelease["ID_LIKE"]) {
180+
os.Family = linuxFamily(id)
181+
if os.Family != "" {
182+
break
183+
}
181184
}
182185
}
183186

@@ -200,7 +203,6 @@ func makeOSInfo(osRelease map[string]string) (*types.OSInfo, error) {
200203
}
201204
}
202205

203-
os.Family = platformToFamilyMap[strings.ToLower(os.Platform)]
204206
return os, nil
205207
}
206208

@@ -231,7 +233,7 @@ func findDistribRelease(baseDir string) (*types.OSInfo, error) {
231233
}
232234

233235
func getDistribRelease(file string) (*types.OSInfo, error) {
234-
data, err := ioutil.ReadFile(file)
236+
data, err := os.ReadFile(file)
235237
if err != nil {
236238
return nil, err
237239
}
@@ -277,6 +279,40 @@ func parseDistribRelease(platform string, content []byte) (*types.OSInfo, error)
277279
}
278280
}
279281

280-
os.Family = platformToFamilyMap[strings.ToLower(os.Platform)]
282+
os.Family = linuxFamily(os.Platform)
281283
return os, nil
282284
}
285+
286+
// firstOf returns the first non-empty value found in the map while
287+
// iterating over keys.
288+
func firstOf(kv map[string]string, keys ...string) string {
289+
for _, key := range keys {
290+
if v := kv[key]; v != "" {
291+
return v
292+
}
293+
}
294+
return ""
295+
}
296+
297+
// linuxFamily returns the linux distribution family associated to the OS platform.
298+
// If there is no family associated then it returns an empty string.
299+
func linuxFamily(platform string) string {
300+
if platform == "" {
301+
return ""
302+
}
303+
304+
platform = strings.ToLower(platform)
305+
306+
// First try a direct lookup.
307+
if family, found := platformToFamilyMap[platform]; found {
308+
return family
309+
}
310+
311+
// Try prefix matching (e.g. opensuse matches opensuse-tumpleweed).
312+
for platformPrefix, family := range platformToFamilyMap {
313+
if strings.HasPrefix(platform, platformPrefix) {
314+
return family
315+
}
316+
}
317+
return ""
318+
}

providers/linux/os_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,20 @@ func TestOperatingSystem(t *testing.T) {
8080
}, *os)
8181
t.Logf("%#v", os)
8282
})
83+
t.Run("archlinux", func(t *testing.T) {
84+
os, err := getOSInfo("testdata/archlinux")
85+
if err != nil {
86+
t.Fatal(err)
87+
}
88+
assert.Equal(t, types.OSInfo{
89+
Type: "linux",
90+
Family: "arch",
91+
Platform: "archarm",
92+
Name: "Arch Linux ARM",
93+
Build: "rolling",
94+
}, *os)
95+
t.Logf("%#v", os)
96+
})
8397
t.Run("centos6", func(t *testing.T) {
8498
os, err := getOSInfo("testdata/centos6")
8599
if err != nil {
@@ -181,6 +195,22 @@ func TestOperatingSystem(t *testing.T) {
181195
}, *os)
182196
t.Logf("%#v", os)
183197
})
198+
t.Run("manjaro23", func(t *testing.T) {
199+
os, err := getOSInfo("testdata/manjaro23")
200+
if err != nil {
201+
t.Fatal(err)
202+
}
203+
assert.Equal(t, types.OSInfo{
204+
Type: "linux",
205+
Family: "arch",
206+
Platform: "manjaro-arm",
207+
Name: "Manjaro ARM",
208+
Version: "23.02",
209+
Major: 23,
210+
Minor: 2,
211+
}, *os)
212+
t.Logf("%#v", os)
213+
})
184214
t.Run("redhat7", func(t *testing.T) {
185215
os, err := getOSInfo("testdata/redhat7")
186216
if err != nil {

providers/linux/testdata/archlinux/etc/arch-release

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../usr/lib/os-release
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
NAME="Arch Linux ARM"
2+
PRETTY_NAME="Arch Linux ARM"
3+
ID=archarm
4+
ID_LIKE=arch
5+
BUILD_ID=rolling
6+
ANSI_COLOR="38;2;23;147;209"
7+
HOME_URL="https://archlinuxarm.org/"
8+
DOCUMENTATION_URL="https://archlinuxarm.org/wiki"
9+
SUPPORT_URL="https://archlinuxarm.org/forum"
10+
BUG_REPORT_URL="https://github.com/archlinuxarm/PKGBUILDs/issues"
11+
LOGO=archlinux-logo

providers/linux/testdata/manjaro23/etc/arch-release

Whitespace-only changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
DISTRIB_ID=Manjaro-ARM
2+
DISTRIB_RELEASE=23.02
3+
DISTRIB_CODENAME=
4+
DISTRIB_DESCRIPTION="Manjaro ARM Linux"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../usr/lib/os-release
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
NAME="Manjaro ARM"
2+
ID="manjaro-arm"
3+
ID_LIKE="manjaro arch"
4+
PRETTY_NAME="Manjaro ARM"
5+
ANSI_COLOR="1;32"
6+
HOME_URL="https://www.manjaro.org/"
7+
SUPPORT_URL="https://forum.manjaro.org/c/arm/"
8+
LOGO=manjarolinux

0 commit comments

Comments
 (0)