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 }