dev-tools/mage/pkgdeps.go (118 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License 2.0; // you may not use this file except in compliance with the Elastic License 2.0. package mage import ( "fmt" "github.com/magefile/mage/sh" ) // PackageInstaller contains package dependency type PackageInstaller struct { table map[PlatformDescription][]PackageDependency } // PlatformDescription contains platform description type PlatformDescription struct { Name string Arch string DefaultTag string } // PackageDependency contains package dependency details type PackageDependency struct { archTag string dependencies []string } var ( // Linux386 platform description for Linux386 Linux386 = PlatformDescription{Name: "linux/386", Arch: "i386", DefaultTag: "i386"} // LinuxAMD64 platform description for LinuxAMD64 LinuxAMD64 = PlatformDescription{Name: "linux/amd64", Arch: "", DefaultTag: ""} // builders run on amd64 platform // LinuxARM64 platform description for LinuxARM64 LinuxARM64 = PlatformDescription{Name: "linux/arm64", Arch: "arm64", DefaultTag: "arm64"} // LinuxARM5 platform description for LinuxARM5 LinuxARM5 = PlatformDescription{Name: "linux/arm5", Arch: "armel", DefaultTag: "armel"} // LinuxARM6 platform description for LinuxARM6 LinuxARM6 = PlatformDescription{Name: "linux/arm6", Arch: "armel", DefaultTag: "armel"} // LinuxARM7 platform description for LinuxARM7 LinuxARM7 = PlatformDescription{Name: "linux/arm7", Arch: "armhf", DefaultTag: "armhf"} // LinuxMIPS platform description for LinuxMIPS LinuxMIPS = PlatformDescription{Name: "linux/mips", Arch: "mips", DefaultTag: "mips"} // LinuxMIPSLE platform description for LinuxMIPSLE LinuxMIPSLE = PlatformDescription{Name: "linux/mipsle", Arch: "mipsel", DefaultTag: "mipsel"} // LinuxMIPS64LE platform description for LinuxMIPS64LE LinuxMIPS64LE = PlatformDescription{Name: "linux/mips64le", Arch: "mips64el", DefaultTag: "mips64el"} // LinuxPPC64LE platform description for LinuxPPC64LE LinuxPPC64LE = PlatformDescription{Name: "linux/ppc64le", Arch: "ppc64el", DefaultTag: "ppc64el"} // LinuxS390x platform description for LinuxS390x LinuxS390x = PlatformDescription{Name: "linux/s390x", Arch: "s390x", DefaultTag: "s390x"} ) // NewPackageInstaller instantiates the package func NewPackageInstaller() *PackageInstaller { return &PackageInstaller{} } // AddEach function adds new package installer step func (i *PackageInstaller) AddEach(ps []PlatformDescription, names ...string) *PackageInstaller { for _, p := range ps { i.Add(p, names...) } return i } // Add function adds new package func (i *PackageInstaller) Add(p PlatformDescription, names ...string) *PackageInstaller { i.AddPackages(p, p.Packages(names...)) return i } // AddPackages function adds a list of packages func (i *PackageInstaller) AddPackages(p PlatformDescription, details ...PackageDependency) *PackageInstaller { if i.table == nil { i.table = map[PlatformDescription][]PackageDependency{} } i.table[p] = append(i.table[p], details...) return i } // Installer installs the package func (i *PackageInstaller) Installer(name string) func() error { var platform PlatformDescription for p := range i.table { if p.Name == name { platform = p } } if platform.Name == "" { return func() error { return nil } } return func() error { return i.Install(platform) } } // Install function installs the package func (i *PackageInstaller) Install(p PlatformDescription) error { packages := map[string]struct{}{} for _, details := range i.table[p] { for _, name := range details.List() { packages[name] = struct{}{} } } j, lst := 0, make([]string, len(packages)) for name := range packages { lst[j], j = name, j+1 } return installDependencies(p.Arch, lst...) } func installDependencies(arch string, pkgs ...string) error { if arch != "" { err := sh.Run("dpkg", "--add-architecture", arch) if err != nil { return fmt.Errorf("error while adding architecture: %w", err) } } if err := sh.Run("apt-get", "update"); err != nil { return err } params := append([]string{"install", "-y", "--no-install-recommends", // Journalbeat is built with old versions of Debian that don't update // their repositories, so they have expired keys. // Allow unauthenticated packages. // This was not enough: "-o", "Acquire::Check-Valid-Until=false", "--allow-unauthenticated", }, pkgs...) return sh.Run("apt-get", params...) } // Packages adds package dependencies func (p PlatformDescription) Packages(names ...string) PackageDependency { return PackageDependency{}.WithTag(p.DefaultTag).Add(names...) } // Add adds package dependency func (p PackageDependency) Add(deps ...string) PackageDependency { if len(deps) == 0 { return p } // always copy to ensure that we never share or overwrite slices due to capacity being too large p.dependencies = append(make([]string, 0, len(p.dependencies)+len(deps)), p.dependencies...) p.dependencies = append(p.dependencies, deps...) return p } // WithTag adds tag func (p PackageDependency) WithTag(tag string) PackageDependency { p.archTag = tag return p } // List function lists dependencies func (p PackageDependency) List() []string { if p.archTag == "" { return p.dependencies } names := make([]string, len(p.dependencies)) for i, name := range p.dependencies { names[i] = fmt.Sprintf("%v:%v", name, p.archTag) } return names }