Skip to content

Commit

Permalink
distro: add ReadOSReleaseFromTree
Browse files Browse the repository at this point in the history
This new method supports reading os-release from an arbitrary tree,
and it also correctly handles multiple os-release locations (see
os-release(5)). It's public so we can reuse it in multiple places.
  • Loading branch information
ondrejbudai authored and achilleas-k committed Apr 10, 2024
1 parent 4657fbd commit 26899f8
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
24 changes: 24 additions & 0 deletions pkg/distro/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package distro
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"path"
"strings"
)

Expand Down Expand Up @@ -48,3 +50,25 @@ func readOSRelease(r io.Reader) (map[string]string, error) {

return osrelease, nil
}

// ReadOSReleaseFromTree reads the os-release file from the given root directory.
//
// According to os-release(5), the os-release file should be located in either /etc/os-release or /usr/lib/os-release,
// so both locations are tried, with the former taking precedence.
func ReadOSReleaseFromTree(root string) (map[string]string, error) {
locations := []string{
"etc/os-release",
"usr/lib/os-release",
}
var errs []string
for _, location := range locations {
f, err := os.Open(path.Join(root, location))
if err == nil {
defer f.Close()
return readOSRelease(f)
}
errs = append(errs, fmt.Sprintf("cannot read %s: %v", location, err))
}

return nil, fmt.Errorf("failed to read os-release:\n%s", strings.Join(errs, "\n"))
}
37 changes: 37 additions & 0 deletions pkg/distro/host_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package distro

import (
"os"
"path"
"reflect"
"strings"
"testing"

"github.com/stretchr/testify/require"
)

func TestOSRelease(t *testing.T) {
Expand Down Expand Up @@ -52,3 +56,36 @@ VARIANT_ID=workstation`,
}
}
}

func TestReadOSReleaseFromTree(t *testing.T) {
tree := t.TempDir()

// initialize dirs
require.NoError(t, os.MkdirAll(path.Join(tree, "usr/lib"), 0755))
require.NoError(t, os.MkdirAll(path.Join(tree, "etc"), 0755))

// firstly, let's write a simple /usr/lib/os-release
require.NoError(t,
os.WriteFile(path.Join(tree, "usr/lib/os-release"), []byte("ID=toucan\n"), 0600),
)

osRelease, err := ReadOSReleaseFromTree(tree)
require.NoError(t, err)
require.Equal(t, "toucan", osRelease["ID"])

// secondly, let's override it with /etc/os-release
require.NoError(t,
os.WriteFile(path.Join(tree, "etc/os-release"), []byte("ID=kingfisher\n"), 0600),
)

osRelease, err = ReadOSReleaseFromTree(tree)
require.NoError(t, err)
require.Equal(t, "kingfisher", osRelease["ID"])
}

func TestReadOSReleaseFromTreeUnhappy(t *testing.T) {
tree := t.TempDir()

_, err := ReadOSReleaseFromTree(tree)
require.ErrorContains(t, err, "failed to read os-release")
}

0 comments on commit 26899f8

Please sign in to comment.