github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/os/os_linux.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the LGPLv3, see LICENCE file for details.
     3  
     4  package os
     5  
     6  import (
     7  	"errors"
     8  	stdos "os"
     9  	"strings"
    10  	"sync"
    11  
    12  	"github.com/juju/juju/core/os/ostype"
    13  )
    14  
    15  var (
    16  	// osReleaseFile is the name of the file that is read in order to determine
    17  	// the linux type release version.
    18  	osReleaseFile = "/etc/os-release"
    19  	osOnce        sync.Once
    20  	os            ostype.OSType // filled in by the first call to hostOS
    21  )
    22  
    23  func hostOS() ostype.OSType {
    24  	osOnce.Do(func() {
    25  		var err error
    26  		os, err = updateOS(osReleaseFile)
    27  		if err != nil {
    28  			panic("unable to read " + osReleaseFile + ": " + err.Error())
    29  		}
    30  	})
    31  	return os
    32  }
    33  
    34  func updateOS(f string) (ostype.OSType, error) {
    35  	values, err := ReadOSRelease(f)
    36  	if err != nil {
    37  		return ostype.Unknown, err
    38  	}
    39  	switch values["ID"] {
    40  	case strings.ToLower(ostype.Ubuntu.String()):
    41  		return ostype.Ubuntu, nil
    42  	case strings.ToLower(ostype.CentOS.String()):
    43  		return ostype.CentOS, nil
    44  	default:
    45  		return ostype.GenericLinux, nil
    46  	}
    47  }
    48  
    49  // ReadOSRelease parses the information in the os-release file.
    50  //
    51  // See http://www.freedesktop.org/software/systemd/man/os-release.html.
    52  func ReadOSRelease(f string) (map[string]string, error) {
    53  	contents, err := stdos.ReadFile(f)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	values := make(map[string]string)
    58  	releaseDetails := strings.Split(string(contents), "\n")
    59  	for _, val := range releaseDetails {
    60  		c := strings.SplitN(val, "=", 2)
    61  		if len(c) != 2 {
    62  			continue
    63  		}
    64  		values[c[0]] = strings.Trim(c[1], "\t '\"")
    65  	}
    66  	if _, ok := values["ID"]; !ok {
    67  		return nil, errors.New("OS release file is missing ID")
    68  	}
    69  	if _, ok := values["VERSION_ID"]; !ok {
    70  		return nil, errors.New("OS release file is missing VERSION_ID")
    71  	}
    72  	return values, nil
    73  }