feat: initial implementation of distro interface
This commit is contained in:
parent
c3774714fd
commit
120fcdc56b
@ -2,12 +2,64 @@ package centos
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"code.dumpstack.io/tools/out-of-tree/config"
|
"code.dumpstack.io/tools/out-of-tree/config"
|
||||||
|
"code.dumpstack.io/tools/out-of-tree/container"
|
||||||
|
"code.dumpstack.io/tools/out-of-tree/distro"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
releases := []string{"6", "7", "8"}
|
||||||
|
|
||||||
|
for _, release := range releases {
|
||||||
|
container := "out_of_tree_centos_" + release
|
||||||
|
|
||||||
|
distro.Register(CentOS{
|
||||||
|
release: release,
|
||||||
|
container: container,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type CentOS struct {
|
||||||
|
release string
|
||||||
|
container string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (centos CentOS) ID() distro.ID {
|
||||||
|
return distro.CentOS
|
||||||
|
}
|
||||||
|
|
||||||
|
func (centos CentOS) Equal(d distro.Distro) bool {
|
||||||
|
return centos.release == d.Release && distro.CentOS == d.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (centos CentOS) Packages() (pkgs []string, err error) {
|
||||||
|
c, err := container.New(centos.container, time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := "yum search kernel --showduplicates " +
|
||||||
|
"| grep '^kernel-[0-9]' " +
|
||||||
|
"| grep -v src " +
|
||||||
|
"| cut -d ' ' -f 1"
|
||||||
|
|
||||||
|
output, err := c.Run(config.Dir("tmp"), cmd)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range strings.Fields(output) {
|
||||||
|
pkgs = append(pkgs, pkg)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func Envs(km config.Target) (envs []string) {
|
func Envs(km config.Target) (envs []string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,73 @@ import (
|
|||||||
"code.dumpstack.io/tools/out-of-tree/cache"
|
"code.dumpstack.io/tools/out-of-tree/cache"
|
||||||
"code.dumpstack.io/tools/out-of-tree/config"
|
"code.dumpstack.io/tools/out-of-tree/config"
|
||||||
"code.dumpstack.io/tools/out-of-tree/container"
|
"code.dumpstack.io/tools/out-of-tree/container"
|
||||||
|
"code.dumpstack.io/tools/out-of-tree/distro"
|
||||||
"code.dumpstack.io/tools/out-of-tree/distro/debian/snapshot"
|
"code.dumpstack.io/tools/out-of-tree/distro/debian/snapshot"
|
||||||
"code.dumpstack.io/tools/out-of-tree/fs"
|
"code.dumpstack.io/tools/out-of-tree/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
releases := []Release{
|
||||||
|
Wheezy,
|
||||||
|
Jessie,
|
||||||
|
Stretch,
|
||||||
|
Buster,
|
||||||
|
Bullseye,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, release := range releases {
|
||||||
|
container := fmt.Sprintf("out_of_tree_debian_%d", release)
|
||||||
|
|
||||||
|
distro.Register(Debian{
|
||||||
|
release: release,
|
||||||
|
container: container,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Debian struct {
|
||||||
|
release Release
|
||||||
|
container string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Debian) ID() distro.ID {
|
||||||
|
return distro.Debian
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Debian) Equal(dd distro.Distro) bool {
|
||||||
|
if dd.ID != distro.Debian {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return releaseFromString(dd.Release) == d.release
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Debian) Packages() (packages []string, err error) {
|
||||||
|
kernels, err := GetKernels()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("get kernels")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dk := range kernels {
|
||||||
|
p := strings.Replace(dk.Image.Deb.Name, ".deb", "", -1)
|
||||||
|
|
||||||
|
var kr Release
|
||||||
|
kr, err = kernelRelease(p)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Err(err).Msg("")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if kr != d.release {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
packages = append(packages, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type Release int
|
type Release int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -111,38 +174,6 @@ func kernelRelease(deb string) (r Release, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Match(km config.Target) (pkgs []string, err error) {
|
|
||||||
kernels, err := GetKernels()
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("get kernels")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
release := releaseFromString(km.Distro.Release)
|
|
||||||
|
|
||||||
r := regexp.MustCompile(km.Kernel.Regex)
|
|
||||||
|
|
||||||
for _, dk := range kernels {
|
|
||||||
p := strings.Replace(dk.Image.Deb.Name, ".deb", "", -1)
|
|
||||||
|
|
||||||
var kr Release
|
|
||||||
kr, err = kernelRelease(p)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn().Err(err).Msg("")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if kr != release {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.MatchString(p) {
|
|
||||||
pkgs = append(pkgs, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Envs(km config.Target) (envs []string) {
|
func Envs(km config.Target) (envs []string) {
|
||||||
envs = append(envs, "DEBIAN_FRONTEND=noninteractive")
|
envs = append(envs, "DEBIAN_FRONTEND=noninteractive")
|
||||||
return
|
return
|
||||||
|
@ -1,6 +1,47 @@
|
|||||||
package distro
|
package distro
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mu sync.Mutex
|
||||||
|
var distros []distribution
|
||||||
|
|
||||||
|
type distribution interface {
|
||||||
|
ID() ID
|
||||||
|
Equal(Distro) bool
|
||||||
|
Packages() (packages []string, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Register(d distribution) {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
|
||||||
|
distros = append(distros, d)
|
||||||
|
}
|
||||||
|
|
||||||
type Distro struct {
|
type Distro struct {
|
||||||
ID ID
|
ID ID
|
||||||
Release string
|
Release string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d Distro) Packages() (packages []string, err error) {
|
||||||
|
for _, dd := range distros {
|
||||||
|
if d.ID != None && d.ID != dd.ID() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Release != "" && !dd.Equal(d) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkgs []string
|
||||||
|
pkgs, err = dd.Packages()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
packages = append(packages, pkgs...)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
10
distro/id.go
10
distro/id.go
@ -9,8 +9,9 @@ import (
|
|||||||
type ID int
|
type ID int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
None ID = iota
|
||||||
// Ubuntu https://ubuntu.com/
|
// Ubuntu https://ubuntu.com/
|
||||||
Ubuntu ID = iota
|
Ubuntu
|
||||||
// CentOS https://www.centos.org/
|
// CentOS https://www.centos.org/
|
||||||
CentOS
|
CentOS
|
||||||
// Debian https://www.debian.org/
|
// Debian https://www.debian.org/
|
||||||
@ -20,10 +21,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var IDs = []ID{
|
var IDs = []ID{
|
||||||
Ubuntu, CentOS, Debian, OracleLinux,
|
None, Ubuntu, CentOS, Debian, OracleLinux,
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameStrings = [...]string{
|
var nameStrings = [...]string{
|
||||||
|
"",
|
||||||
"Ubuntu",
|
"Ubuntu",
|
||||||
"CentOS",
|
"CentOS",
|
||||||
"Debian",
|
"Debian",
|
||||||
@ -50,8 +52,10 @@ func (id *ID) UnmarshalTOML(data []byte) (err error) {
|
|||||||
*id = Debian
|
*id = Debian
|
||||||
} else if strings.EqualFold(name, "OracleLinux") {
|
} else if strings.EqualFold(name, "OracleLinux") {
|
||||||
*id = OracleLinux
|
*id = OracleLinux
|
||||||
|
} else if name != "" {
|
||||||
|
err = fmt.Errorf("distro %s is not supported", name)
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("distro %s is unsupported", name)
|
*id = None
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package oraclelinux
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -10,8 +9,58 @@ import (
|
|||||||
|
|
||||||
"code.dumpstack.io/tools/out-of-tree/config"
|
"code.dumpstack.io/tools/out-of-tree/config"
|
||||||
"code.dumpstack.io/tools/out-of-tree/container"
|
"code.dumpstack.io/tools/out-of-tree/container"
|
||||||
|
"code.dumpstack.io/tools/out-of-tree/distro"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
releases := []string{"6", "7", "8", "9"}
|
||||||
|
|
||||||
|
for _, release := range releases {
|
||||||
|
container := "out_of_tree_oraclelinux_" + release
|
||||||
|
|
||||||
|
distro.Register(OracleLinux{
|
||||||
|
release: release,
|
||||||
|
container: container,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type OracleLinux struct {
|
||||||
|
release string
|
||||||
|
container string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ol OracleLinux) ID() distro.ID {
|
||||||
|
return distro.OracleLinux
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ol OracleLinux) Equal(d distro.Distro) bool {
|
||||||
|
return ol.release == d.Release && distro.OracleLinux == d.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ol OracleLinux) Packages() (pkgs []string, err error) {
|
||||||
|
c, err := container.New(ol.container, time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := "yum search kernel --showduplicates " +
|
||||||
|
"| grep '^kernel-[0-9]\\|^kernel-uek-[0-9]' " +
|
||||||
|
"| grep -v src " +
|
||||||
|
"| cut -d ' ' -f 1"
|
||||||
|
|
||||||
|
output, err := c.Run(config.Dir("tmp"), cmd)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range strings.Fields(output) {
|
||||||
|
pkgs = append(pkgs, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func Envs(km config.Target) (envs []string) {
|
func Envs(km config.Target) (envs []string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -40,42 +89,6 @@ func Runs(km config.Target) (commands []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Match(km config.Target) (pkgs []string, err error) {
|
|
||||||
// FIXME timeout should be in global out-of-tree config
|
|
||||||
c, err := container.New(km.DockerName(), time.Hour)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := "yum search kernel --showduplicates " +
|
|
||||||
"| grep '^kernel-[0-9]\\|^kernel-uek-[0-9]' " +
|
|
||||||
"| grep -v src " +
|
|
||||||
"| cut -d ' ' -f 1"
|
|
||||||
|
|
||||||
output, err := c.Run(config.Dir("tmp"), cmd)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := regexp.Compile("kernel-" + km.Kernel.Regex)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pkg := range strings.Fields(output) {
|
|
||||||
if r.MatchString(pkg) || strings.Contains(pkg, km.Kernel.Regex) {
|
|
||||||
log.Trace().Msg(pkg)
|
|
||||||
pkgs = append(pkgs, pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pkgs) == 0 {
|
|
||||||
log.Warn().Msg("no packages matched")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Install(km config.Target, pkgname string, headers bool) (commands []string, err error) {
|
func Install(km config.Target, pkgname string, headers bool) (commands []string, err error) {
|
||||||
var headerspkg string
|
var headerspkg string
|
||||||
if headers {
|
if headers {
|
||||||
|
@ -2,14 +2,70 @@ package ubuntu
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.dumpstack.io/tools/out-of-tree/config"
|
"code.dumpstack.io/tools/out-of-tree/config"
|
||||||
"code.dumpstack.io/tools/out-of-tree/container"
|
"code.dumpstack.io/tools/out-of-tree/container"
|
||||||
|
"code.dumpstack.io/tools/out-of-tree/distro"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
releases := []string{
|
||||||
|
"12.04",
|
||||||
|
"14.04",
|
||||||
|
"16.04",
|
||||||
|
"18.04",
|
||||||
|
"20.04",
|
||||||
|
"22.04",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, release := range releases {
|
||||||
|
container := "out_of_tree_ubuntu_" + release
|
||||||
|
container = strings.Replace(container, ".", "__", -1)
|
||||||
|
|
||||||
|
distro.Register(Ubuntu{
|
||||||
|
release: release,
|
||||||
|
container: container,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ubuntu struct {
|
||||||
|
release string
|
||||||
|
container string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Ubuntu) ID() distro.ID {
|
||||||
|
return distro.Ubuntu
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Ubuntu) Equal(d distro.Distro) bool {
|
||||||
|
return u.release == d.Release && distro.Ubuntu == d.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Ubuntu) Packages() (pkgs []string, err error) {
|
||||||
|
c, err := container.New(u.container, time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := "apt-cache search " +
|
||||||
|
"--names-only '^linux-image-[0-9\\.\\-]*-generic' " +
|
||||||
|
"| awk '{ print $1 }'"
|
||||||
|
|
||||||
|
output, err := c.Run(config.Dir("tmp"), cmd)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range strings.Fields(output) {
|
||||||
|
pkgs = append(pkgs, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func Envs(km config.Target) (envs []string) {
|
func Envs(km config.Target) (envs []string) {
|
||||||
envs = append(envs, "DEBIAN_FRONTEND=noninteractive")
|
envs = append(envs, "DEBIAN_FRONTEND=noninteractive")
|
||||||
return
|
return
|
||||||
@ -53,36 +109,6 @@ func Runs(km config.Target) (commands []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Match(km config.Target) (pkgs []string, err error) {
|
|
||||||
// FIXME timeout should be in global out-of-tree config
|
|
||||||
c, err := container.New(km.DockerName(), time.Hour)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := "apt-cache search " +
|
|
||||||
"--names-only '^linux-image-[0-9\\.\\-]*-generic' " +
|
|
||||||
"| awk '{ print $1 }'"
|
|
||||||
|
|
||||||
output, err := c.Run(config.Dir("tmp"), cmd)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := regexp.Compile("linux-image-" + km.Kernel.Regex)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pkg := range strings.Fields(output) {
|
|
||||||
if r.MatchString(pkg) || strings.Contains(pkg, km.Kernel.Regex) {
|
|
||||||
pkgs = append(pkgs, pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Install(km config.Target, pkgname string, headers bool) (commands []string, err error) {
|
func Install(km config.Target, pkgname string, headers bool) (commands []string, err error) {
|
||||||
|
|
||||||
var headerspkg string
|
var headerspkg string
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -31,18 +32,23 @@ import (
|
|||||||
"code.dumpstack.io/tools/out-of-tree/fs"
|
"code.dumpstack.io/tools/out-of-tree/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MatchPackages(km config.Target) (pkgs []string, err error) {
|
func MatchPackages(km config.Target) (packages []string, err error) {
|
||||||
// TODO interface for kernels match
|
pkgs, err := km.Distro.Packages()
|
||||||
switch km.Distro.ID {
|
if err != nil {
|
||||||
case distro.Ubuntu:
|
return
|
||||||
pkgs, err = ubuntu.Match(km)
|
|
||||||
case distro.OracleLinux, distro.CentOS:
|
|
||||||
pkgs, err = oraclelinux.Match(km)
|
|
||||||
case distro.Debian:
|
|
||||||
pkgs, err = debian.Match(km)
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("%s not yet supported", km.Distro.ID.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r, err := regexp.Compile(km.Kernel.Regex)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
if r.MatchString(pkg) {
|
||||||
|
packages = append(packages, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
main.go
5
main.go
@ -23,6 +23,11 @@ import (
|
|||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
|
|
||||||
|
_ "code.dumpstack.io/tools/out-of-tree/distro/centos"
|
||||||
|
_ "code.dumpstack.io/tools/out-of-tree/distro/debian"
|
||||||
|
_ "code.dumpstack.io/tools/out-of-tree/distro/oraclelinux"
|
||||||
|
_ "code.dumpstack.io/tools/out-of-tree/distro/ubuntu"
|
||||||
|
|
||||||
"code.dumpstack.io/tools/out-of-tree/cache"
|
"code.dumpstack.io/tools/out-of-tree/cache"
|
||||||
"code.dumpstack.io/tools/out-of-tree/config"
|
"code.dumpstack.io/tools/out-of-tree/config"
|
||||||
"code.dumpstack.io/tools/out-of-tree/container"
|
"code.dumpstack.io/tools/out-of-tree/container"
|
||||||
|
Loading…
Reference in New Issue
Block a user