Skip to content

Commit

Permalink
helpers/osinfo: export functions to access internal fields
Browse files Browse the repository at this point in the history
Reference: #60
Reference: #61
  • Loading branch information
rafaeldtinoco authored and Rafael David Tinoco committed Sep 2, 2021
1 parent a453321 commit 0ccd53e
Showing 1 changed file with 49 additions and 59 deletions.
108 changes: 49 additions & 59 deletions helpers/osinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)

Expand Down Expand Up @@ -47,7 +46,7 @@ var osReleaseIDToString = map[OSReleaseID]string{
}

const (
OS_NAME osReleaseField = iota + 0
OS_NAME OSReleaseField = iota + 0
OS_ID
OS_ID_LIKE
OS_PRETTY_NAME
Expand All @@ -62,14 +61,14 @@ const (
OS_KERNEL_RELEASE // not part of default os-release, but we can use it here to facilitate things
)

type osReleaseField uint32
type OSReleaseField uint32

func (o osReleaseField) String() string {
func (o OSReleaseField) String() string {
return osReleaseFieldToString[o]
}

// StringToOSReleaseField is a map of os-release file fields
var stringToOSReleaseField = map[string]osReleaseField{
// stringToOSReleaseField is a map of os-release file fields
var stringToOSReleaseField = map[string]OSReleaseField{
"NAME": OS_NAME,
"ID": OS_ID,
"ID_LIKE": OS_ID_LIKE,
Expand All @@ -85,8 +84,8 @@ var stringToOSReleaseField = map[string]osReleaseField{
"KERNEL_RELEASE": OS_KERNEL_RELEASE,
}

// OSReleaseFieldToString is a map of os-release file fields
var osReleaseFieldToString = map[osReleaseField]string{
// osReleaseFieldToString is a map of os-release file fields
var osReleaseFieldToString = map[OSReleaseField]string{
OS_NAME: "NAME",
OS_ID: "ID",
OS_ID_LIKE: "ID_LIKE",
Expand All @@ -102,42 +101,6 @@ var osReleaseFieldToString = map[osReleaseField]string{
OS_KERNEL_RELEASE: "KERNEL_RELEASE",
}

// CompareOSBaseKernelRelease will compare two given kernel version/release
// strings and return -1, 0 or 1 if given version is less, equal or bigger,
// respectively, than the given one
//
// Examples of $(uname -r):
//
// 5.11.0-31-generic (ubuntu)
// 4.18.0-305.12.1.el8_4.x86_64 (alma)
// 4.18.0-338.el8.x86_64 (stream8)
// 4.18.0-305.7.1.el8_4.centos.x86_64 (centos)
// 4.18.0-305.7.1.el8_4.centos.plus.x86_64 (centos + plus repo)
// 5.13.13-arch1-1 (archlinux)
//
func CompareOSBaseKernelRelease(base, given string) int {
b := strings.Split(base, "-") // [base]-xxx
b = strings.Split(b[0], ".") // [major][minor][patch]

g := strings.Split(given, "-")
g = strings.Split(g[0], ".")

for n := 0; n <= 2; n++ {
i, _ := strconv.Atoi(g[n])
j, _ := strconv.Atoi(b[n])

if i > j {
return 1 // given is bigger
} else if i < j {
return -1 // given is less
} else {
continue // equal
}
}

return 0 // equal
}

// OSBTFEnabled checks if kernel has embedded BTF vmlinux file
func OSBTFEnabled() bool {
_, err := os.Stat("/sys/kernel/btf/vmlinux") // TODO: accept a KernelConfig param and check for CONFIG_DEBUG_INFO_BTF=y, or similar
Expand All @@ -150,20 +113,20 @@ func GetOSInfo() (*OSInfo, error) {
info := OSInfo{}
var err error

if info.OSReleaseInfo == nil {
info.OSReleaseInfo = make(map[osReleaseField]string)
if info.osReleaseFieldValues == nil {
info.osReleaseFieldValues = make(map[OSReleaseField]string)
}

info.OSReleaseInfo[OS_KERNEL_RELEASE], err = UnameRelease()
info.osReleaseFieldValues[OS_KERNEL_RELEASE], err = UnameRelease()
if err != nil {
return &info, fmt.Errorf("could not determine uname release: %w", err)
}

info.OSReleaseFilePath, err = checkEnvPath("LIBBPFGO_OSRELEASE_FILE") // useful if users wants to mount host os-release in a container
info.osReleaseFilePath, err = checkEnvPath("LIBBPFGO_OSRELEASE_FILE") // useful if users wants to mount host os-release in a container
if err != nil {
return &info, err
} else if info.OSReleaseFilePath == "" {
info.OSReleaseFilePath = "/etc/os-release"
} else if info.osReleaseFilePath == "" {
info.osReleaseFilePath = "/etc/os-release"
}

if err = info.discoverOSDistro(); err != nil {
Expand All @@ -177,12 +140,39 @@ func GetOSInfo() (*OSInfo, error) {
//
// OSRelease is relevant to examples such as:
// 1) OSInfo.OSReleaseInfo[helpers.OS_KERNEL_RELEASE]) => will provide $(uname -r) string
// 2) if OSInfo.OSRelease == helpers.UBUNTU => {} will allow to run code in specific distros
// 2) if OSInfo.GetReleaseID() == helpers.UBUNTU => {} will allow to run code in specific distribution
//
type OSInfo struct {
OSReleaseInfo map[osReleaseField]string
OSRelease OSReleaseID
OSReleaseFilePath string
osReleaseFieldValues map[OSReleaseField]string
osReleaseID OSReleaseID
osReleaseFilePath string
}

// GetOSReleaseFieldValue provides access to internal OSInfo OSReleaseField's
func (btfi *OSInfo) GetOSReleaseFieldValue(value OSReleaseField) string {
return btfi.osReleaseFieldValues[value]
}

// GetOSReleaseFilePath provides the path for the used os-release file as it might
// not necessarily be /etc/os-release, depending on the environment variable
func (btfi *OSInfo) GetOSReleaseFilePath() string {
return btfi.osReleaseFilePath
}

// GetOSReleaseFilePath provides the ID of current Linux distribution
func (btfi *OSInfo) GetOSReleaseID() OSReleaseID {
return btfi.osReleaseID
}

// GetOSReleaseAllFieldValues allows user to dump, as strings, the existing OSReleaseField's and its values
func (btfi *OSInfo) GetOSReleaseAllFieldValues() map[OSReleaseField]string {
summary := make(map[OSReleaseField]string)

for k, v := range btfi.osReleaseFieldValues {
summary[k] = v // create a copy so consumer can read internal data (e.g. debugging)
}

return summary
}

// CompareOSBaseKernelRelease will compare a given kernel version/release string
Expand All @@ -192,19 +182,19 @@ type OSInfo struct {
// OSInfo.CompareOSBaseKernelRelease("5.11.0"))
//
func (btfi *OSInfo) CompareOSBaseKernelRelease(version string) int {
return CompareOSBaseKernelRelease(btfi.OSReleaseInfo[OS_KERNEL_RELEASE], version)
return CompareKernelRelease(btfi.osReleaseFieldValues[OS_KERNEL_RELEASE], version)
}

// discoverOSDistro discover running Linux distribution information by reading UTS and
// the /etc/os-releases file (https://man7.org/linux/man-pages/man5/os-release.5.html)
func (btfi *OSInfo) discoverOSDistro() error {
var err error

if btfi.OSReleaseFilePath == "" {
if btfi.osReleaseFilePath == "" {
return fmt.Errorf("should specify os-release filepath")
}

file, err := os.Open(btfi.OSReleaseFilePath)
file, err := os.Open(btfi.osReleaseFilePath)
if err != nil {
return err
}
Expand All @@ -221,9 +211,9 @@ func (btfi *OSInfo) discoverOSDistro() error {
if keyID == 0 { // could not find KEY= from os-release in consts
continue
}
btfi.OSReleaseInfo[keyID] = val[1]
btfi.osReleaseFieldValues[keyID] = val[1]
if keyID == OS_ID {
btfi.OSRelease = stringToOSReleaseID[strings.ToLower(val[1])]
btfi.osReleaseID = stringToOSReleaseID[strings.ToLower(val[1])]
}
}

Expand Down

0 comments on commit 0ccd53e

Please sign in to comment.