go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/packages/packages.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package packages
     5  
     6  import (
     7  	"github.com/cockroachdb/errors"
     8  	"go.mondoo.com/cnquery/providers/os/connection/shared"
     9  )
    10  
    11  type Package struct {
    12  	Name        string `json:"name"`
    13  	Version     string `json:"version"`
    14  	Arch        string `json:"arch"`
    15  	Status      string `json:"status,omitempty"`
    16  	Description string `json:"description"`
    17  
    18  	// this may be the source package or an origin
    19  	// e.g. on alpine it is used for parent  packages
    20  	// o 	Package Origin - https://wiki.alpinelinux.org/wiki/Apk_spec
    21  	Origin string `json:"origin"`
    22  	Format string `json:"format"`
    23  }
    24  
    25  // extends Package to store available version
    26  type PackageUpdate struct {
    27  	Name      string `json:"name"`
    28  	Version   string `json:"version"`
    29  	Arch      string `json:"arch"`
    30  	Available string `json:"available"`
    31  	Repo      string `json:"repo"`
    32  }
    33  
    34  type OperatingSystemPkgManager interface {
    35  	Name() string
    36  	List() ([]Package, error)
    37  	Available() (map[string]PackageUpdate, error)
    38  }
    39  
    40  // this will find the right package manager for the operating system
    41  func ResolveSystemPkgManager(conn shared.Connection) (OperatingSystemPkgManager, error) {
    42  	var pm OperatingSystemPkgManager
    43  
    44  	asset := conn.Asset()
    45  	if asset == nil || asset.Platform == nil {
    46  		return nil, errors.New("cannot find OS information for package detection")
    47  	}
    48  
    49  	switch {
    50  	case asset.Platform.IsFamily("arch"): // arch family
    51  		pm = &PacmanPkgManager{conn: conn}
    52  	case asset.Platform.IsFamily("debian"): // debian family
    53  		pm = &DebPkgManager{conn: conn}
    54  	case asset.Platform.Name == "amazonlinux" || asset.Platform.Name == "photon" || asset.Platform.Name == "wrlinux":
    55  		fallthrough
    56  	case asset.Platform.IsFamily("redhat"): // rhel family
    57  		pm = &RpmPkgManager{conn: conn, platform: asset.Platform}
    58  	case asset.Platform.IsFamily("suse"): // suse handling
    59  		pm = &SusePkgManager{RpmPkgManager{conn: conn, platform: asset.Platform}}
    60  	case asset.Platform.Name == "alpine": // alpine
    61  		pm = &AlpinePkgManager{conn: conn}
    62  	case asset.Platform.Name == "macos": // mac os family
    63  		pm = &MacOSPkgManager{conn: conn}
    64  	case asset.Platform.Name == "windows":
    65  		pm = &WinPkgManager{conn: conn, platform: asset.Platform}
    66  	case asset.Platform.Name == "scratch" || asset.Platform.Name == "coreos":
    67  		pm = &ScratchPkgManager{conn: conn}
    68  	case asset.Platform.Name == "openwrt":
    69  		pm = &OpkgPkgManager{conn: conn}
    70  	case asset.Platform.Name == "solaris":
    71  		pm = &SolarisPkgManager{conn: conn}
    72  	case asset.Platform.Name == "cos":
    73  		pm = &CosPkgManager{conn: conn}
    74  	case asset.Platform.Name == "freebsd":
    75  		pm = &FreeBSDPkgManager{conn: conn}
    76  	case asset.Platform.Name == "aix":
    77  		pm = &AixPkgManager{conn: conn}
    78  	case asset.Platform.IsFamily("linux"):
    79  		// no clear package manager for linux platform found
    80  		// most likely we land here if we have a yocto-based system
    81  		opkgPaths := []string{"/bin/opkg", "/usr/bin/opkg"}
    82  		for i := range opkgPaths {
    83  			if _, err := conn.FileSystem().Stat(opkgPaths[i]); err == nil {
    84  				pm = &OpkgPkgManager{conn: conn}
    85  				break
    86  			}
    87  		}
    88  	}
    89  
    90  	if pm == nil {
    91  		return nil, errors.New("could not detect suitable package manager for platform: " + asset.Platform.Name)
    92  	}
    93  
    94  	return pm, nil
    95  }