1
0

9 Commits

10 changed files with 79 additions and 52 deletions

View File

@ -17,13 +17,13 @@ out-of-tree is for automating some routine actions for creating development envi
$ curl -fsSL https://get.docker.com | sh $ curl -fsSL https://get.docker.com | sh
$ sudo usermod -aG docker user && newgrp docker $ sudo usermod -aG docker user && newgrp docker
$ curl -L https://nixos.org/nix/install | sh $ curl -L https://nixos.org/nix/install | sh
$ nix-env -iA nixpkgs.out-of-tree $ nix-env -iA nixpkgs.out-of-tree # Note: may not be up to date immediately, in this case consider installing from source
Note that adding a user to group *docker* has serious security implications. Check Docker documentation for more information. Note that adding a user to group *docker* has serious security implications. Check Docker documentation for more information.
### macOS ### macOS
$ brew cask install docker $ brew install --cask docker
$ open --background -a Docker && sleep 1m $ open --background -a Docker && sleep 1m
$ brew tap out-of-tree/repo $ brew tap out-of-tree/repo
$ brew install out-of-tree $ brew install out-of-tree

View File

@ -144,7 +144,7 @@ func (cmd *DebugCmd) Run(g *Globals) (err error) {
} }
defer q.Stop() defer q.Stop()
tmp, err := ioutil.TempDir("/tmp/", "out-of-tree_") tmp, err := ioutil.TempDir(tempDirBase, "out-of-tree_")
if err != nil { if err != nil {
return return
} }

2
go.mod
View File

@ -14,7 +14,7 @@ require (
github.com/naoina/toml v0.1.1 github.com/naoina/toml v0.1.1
github.com/natefinch/lumberjack v2.0.0+incompatible github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/olekukonko/tablewriter v0.0.5 github.com/olekukonko/tablewriter v0.0.5
github.com/otiai10/copy v1.9.0 github.com/otiai10/copy v1.10.0
github.com/remeh/sizedwaitgroup v1.0.0 github.com/remeh/sizedwaitgroup v1.0.0
github.com/rs/zerolog v1.29.0 github.com/rs/zerolog v1.29.0
github.com/zcalusic/sysinfo v0.9.5 github.com/zcalusic/sysinfo v0.9.5

11
go.sum
View File

@ -80,13 +80,10 @@ github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6Yf
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4= github.com/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ=
github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI= github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4=
github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=

View File

@ -159,7 +159,7 @@ func unpackTar(archive, destination string) (err error) {
} }
func downloadImage(path, file string) (err error) { func downloadImage(path, file string) (err error) {
tmp, err := ioutil.TempDir("/tmp/", "out-of-tree_") tmp, err := ioutil.TempDir(tempDirBase, "out-of-tree_")
if err != nil { if err != nil {
return return
} }

View File

@ -172,7 +172,7 @@ func matchDebImagePkg(container, mask string) (pkgs []string, err error) {
return return
} }
output, err := c.Run("/tmp", cmd) output, err := c.Run(tempDirBase, cmd)
if err != nil { if err != nil {
return return
} }
@ -203,7 +203,7 @@ func matchCentOSDevelPkg(container, mask string, generic bool) (
return return
} }
output, err := c.Run("/tmp", cmd) output, err := c.Run(tempDirBase, cmd)
if err != nil { if err != nil {
return return
} }
@ -307,7 +307,8 @@ func generateBaseDockerImage(registry string, commands []config.DockerCommand,
d += "RUN apt-get install -y wget git\n" d += "RUN apt-get install -y wget git\n"
// Install a single kernel and headers to ensure all dependencies are cached // Install a single kernel and headers to ensure all dependencies are cached
d += "RUN export PKGNAME=$(apt-cache search --names-only '^linux-headers-[0-9\\.\\-]*-generic' | awk '{ print $1 }' | head -n 1); " + d += "RUN export PKGNAME=$(apt-cache search --names-only '^linux-headers-[0-9\\.\\-]*-generic' | awk '{ print $1 }' | head -n 1); " +
"apt-get install -y $PKGNAME $(echo $PKGNAME | sed 's/headers/image/')\n" "apt-get install -y $PKGNAME $(echo $PKGNAME | sed 's/headers/image/'); " +
"apt-get remove -y $PKGNAME $(echo $PKGNAME | sed 's/headers/image/')\n"
if sk.DistroRelease >= "14.04" { if sk.DistroRelease >= "14.04" {
d += "RUN apt-get install -y libseccomp-dev\n" d += "RUN apt-get install -y libseccomp-dev\n"
} }
@ -388,7 +389,7 @@ func generateBaseDockerImage(registry string, commands []config.DockerCommand,
} }
func installKernel(sk config.KernelMask, pkgname string, force, headers bool) (err error) { func installKernel(sk config.KernelMask, pkgname string, force, headers bool) (err error) {
tmpdir, err := os.MkdirTemp("", "out-of-tree-"+pkgname+"-") tmpdir, err := os.MkdirTemp(tempDirBase, "out-of-tree-"+pkgname+"-")
if err != nil { if err != nil {
log.Fatal().Err(err).Msg("make tmp directory") log.Fatal().Err(err).Msg("make tmp directory")
} }
@ -444,7 +445,7 @@ func installKernel(sk config.KernelMask, pkgname string, force, headers bool) (e
cmd := fmt.Sprintf("apt-get install -y %s %s", pkgname, headerspkg) cmd := fmt.Sprintf("apt-get install -y %s %s", pkgname, headerspkg)
_, err = c.Run("/tmp", cmd) _, err = c.Run(tempDirBase, cmd)
if err != nil { if err != nil {
return return
} }
@ -458,14 +459,14 @@ func installKernel(sk config.KernelMask, pkgname string, force, headers bool) (e
} }
cmd := fmt.Sprintf("yum -y install %s %s\n", imagepkg, cmd := fmt.Sprintf("yum -y install %s %s\n", imagepkg,
pkgname) pkgname)
_, err = c.Run("/tmp", cmd) _, err = c.Run(tempDirBase, cmd)
if err != nil { if err != nil {
return return
} }
cmd = fmt.Sprintf("dracut --add-drivers 'e1000 ext4' -f "+ cmd = fmt.Sprintf("dracut --add-drivers 'e1000 ext4' -f "+
"/boot/initramfs-%s.img %s\n", version, version) "/boot/initramfs-%s.img %s\n", version, version)
_, err = c.Run("/tmp", cmd) _, err = c.Run(tempDirBase, cmd)
if err != nil { if err != nil {
return return
} }
@ -504,7 +505,7 @@ func installKernel(sk config.KernelMask, pkgname string, force, headers bool) (e
cmd += " && cp -r /usr/src/* /target/usr/src/" cmd += " && cp -r /usr/src/* /target/usr/src/"
} }
_, err = c.Run("/tmp", cmd) _, err = c.Run(tempDirBase, cmd)
if err != nil { if err != nil {
return return
} }
@ -513,32 +514,34 @@ func installKernel(sk config.KernelMask, pkgname string, force, headers bool) (e
return return
} }
func genKernelPath(files []os.FileInfo, kname string) string { func findKernelFile(files []os.FileInfo, kname string) (name string, err error) {
for _, file := range files { for _, file := range files {
if strings.HasPrefix(file.Name(), "vmlinuz") { if strings.HasPrefix(file.Name(), "vmlinuz") {
if strings.Contains(file.Name(), kname) { if strings.Contains(file.Name(), kname) {
return file.Name() name = file.Name()
return
} }
} }
} }
log.Fatal().Msgf("cannot find kernel %s", kname) err = errors.New("cannot find kernel")
return "" return
} }
func genInitrdPath(files []os.FileInfo, kname string) string { func findInitrdFile(files []os.FileInfo, kname string) (name string, err error) {
for _, file := range files { for _, file := range files {
if strings.HasPrefix(file.Name(), "initrd") || if strings.HasPrefix(file.Name(), "initrd") ||
strings.HasPrefix(file.Name(), "initramfs") { strings.HasPrefix(file.Name(), "initramfs") {
if strings.Contains(file.Name(), kname) { if strings.Contains(file.Name(), kname) {
return file.Name() name = file.Name()
return
} }
} }
} }
log.Fatal().Msgf("cannot find initrd %s", kname) err = errors.New("cannot find kernel")
return "" return
} }
func genRootfsImage(d containerImageInfo, download bool) (rootfs string, err error) { func genRootfsImage(d containerImageInfo, download bool) (rootfs string, err error) {
@ -640,16 +643,29 @@ func listContainersKernels(dii containerImageInfo, newkcfg *config.KernelConfig,
} }
for _, krel := range moddirs { for _, krel := range moddirs {
log.Debug().Msgf("generate config entry for %s", krel.Name())
var kernelFile, initrdFile string
kernelFile, err = findKernelFile(bootfiles, krel.Name())
if err != nil {
log.Warn().Msgf("cannot find kernel %s", krel.Name())
continue
}
initrdFile, err = findInitrdFile(bootfiles, krel.Name())
if err != nil {
log.Warn().Msgf("cannot find initrd %s", krel.Name())
continue
}
ki := config.KernelInfo{ ki := config.KernelInfo{
DistroType: dii.DistroType, DistroType: dii.DistroType,
DistroRelease: dii.DistroRelease, DistroRelease: dii.DistroRelease,
KernelRelease: krel.Name(), KernelRelease: krel.Name(),
ContainerName: dii.Name, ContainerName: dii.Name,
KernelPath: c.Volumes.Boot + "/" + KernelPath: c.Volumes.Boot + "/" + kernelFile,
genKernelPath(bootfiles, krel.Name()), InitrdPath: c.Volumes.Boot + "/" + initrdFile,
InitrdPath: c.Volumes.Boot + "/" +
genInitrdPath(bootfiles, krel.Name()),
ModulesPath: c.Volumes.LibModules + "/" + krel.Name(), ModulesPath: c.Volumes.LibModules + "/" + krel.Name(),
RootFS: rootfs, RootFS: rootfs,
@ -660,7 +676,7 @@ func listContainersKernels(dii containerImageInfo, newkcfg *config.KernelConfig,
for _, cmd := range []string{ for _, cmd := range []string{
"find /boot -type f -exec chmod a+r {} \\;", "find /boot -type f -exec chmod a+r {} \\;",
} { } {
_, err = c.Run("/tmp", cmd) _, err = c.Run(tempDirBase, cmd)
if err != nil { if err != nil {
return return
} }
@ -738,7 +754,9 @@ func generateKernels(km config.KernelMask, registry string,
max-- max--
break break
} else if attempt >= retries { } else if attempt >= retries {
log.Fatal().Err(err).Msg("install kernel") log.Error().Err(err).Msg("install kernel")
log.Debug().Msg("skip")
break
} else { } else {
log.Warn().Err(err).Msg("install kernel") log.Warn().Err(err).Msg("install kernel")
time.Sleep(time.Second) time.Sleep(time.Second)

View File

@ -37,7 +37,7 @@ func genHostKernels(download bool) (kcfg config.KernelConfig, err error) {
} }
kernelsBase := "/boot/" kernelsBase := "/boot/"
files, err := ioutil.ReadDir(kernelsBase) bootfiles, err := ioutil.ReadDir(kernelsBase)
if err != nil { if err != nil {
return return
} }
@ -55,20 +55,35 @@ func genHostKernels(download bool) (kcfg config.KernelConfig, err error) {
return return
} }
for _, k := range strings.Fields(string(rawOutput)) { for _, krel := range strings.Fields(string(rawOutput)) {
log.Debug().Msgf("generate config entry for %s", krel)
var kernelFile, initrdFile string
kernelFile, err = findKernelFile(bootfiles, krel)
if err != nil {
log.Warn().Msgf("cannot find kernel %s", krel)
continue
}
initrdFile, err = findInitrdFile(bootfiles, krel)
if err != nil {
log.Warn().Msgf("cannot find initrd %s", krel)
continue
}
ki := config.KernelInfo{ ki := config.KernelInfo{
DistroType: distroType, DistroType: distroType,
DistroRelease: si.OS.Version, DistroRelease: si.OS.Version,
KernelRelease: k, KernelRelease: krel,
KernelSource: "/lib/modules/" + k + "/build", KernelSource: "/lib/modules/" + krel + "/build",
KernelPath: kernelsBase + genKernelPath(files, k), KernelPath: kernelsBase + kernelFile,
InitrdPath: kernelsBase + genInitrdPath(files, k), InitrdPath: kernelsBase + initrdFile,
RootFS: rootfs, RootFS: rootfs,
} }
vmlinux := "/usr/lib/debug/boot/vmlinux-" + k vmlinux := "/usr/lib/debug/boot/vmlinux-" + krel
log.Print("vmlinux", vmlinux) log.Print("vmlinux", vmlinux)
if exists(vmlinux) { if exists(vmlinux) {
ki.VmlinuxPath = vmlinux ki.VmlinuxPath = vmlinux

View File

@ -89,6 +89,8 @@ func (lw *LevelWriter) WriteLevel(l zerolog.Level, p []byte) (n int, err error)
return len(p), nil return len(p), nil
} }
var tempDirBase string
func main() { func main() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
@ -101,7 +103,7 @@ func main() {
Compact: true, Compact: true,
}), }),
kong.Vars{ kong.Vars{
"version": "2.0.0", "version": "2.0.6",
}, },
) )
@ -124,6 +126,9 @@ func main() {
return return
} }
tempDirBase = usr.HomeDir + "/.out-of-tree/tmp/"
os.MkdirAll(tempDirBase, os.ModePerm)
log.Logger = log.Output(zerolog.MultiLevelWriter( log.Logger = log.Output(zerolog.MultiLevelWriter(
&LevelWriter{Writer: zerolog.NewConsoleWriter( &LevelWriter{Writer: zerolog.NewConsoleWriter(
func(w *zerolog.ConsoleWriter) { func(w *zerolog.ConsoleWriter) {

10
pew.go
View File

@ -14,7 +14,6 @@ import (
"math/rand" "math/rand"
"os" "os"
"os/exec" "os/exec"
"os/user"
"strings" "strings"
"time" "time"
@ -599,14 +598,7 @@ func (cmd PewCmd) testArtifact(swg *sizedwaitgroup.SizedWaitGroup,
} }
}() }()
usr, err := user.Current() tmp, err := ioutil.TempDir(tempDirBase, "out-of-tree_")
if err != nil {
return
}
tmpdir := usr.HomeDir + "/.out-of-tree/tmp"
os.MkdirAll(tmpdir, os.ModePerm)
tmp, err := ioutil.TempDir(tmpdir, "out-of-tree_")
if err != nil { if err != nil {
slog.Error().Err(err).Msg("making tmp directory") slog.Error().Err(err).Msg("making tmp directory")
return return

View File

@ -61,7 +61,7 @@ func preload(q *qemu.System, ki config.KernelInfo, pm config.PreloadModule,
func buildAndInsmod(workPath string, q *qemu.System, ki config.KernelInfo, func buildAndInsmod(workPath string, q *qemu.System, ki config.KernelInfo,
dockerTimeout time.Duration, cache string) (err error) { dockerTimeout time.Duration, cache string) (err error) {
tmp, err := ioutil.TempDir("", "out-of-tree_") tmp, err := ioutil.TempDir(tempDirBase, "out-of-tree_")
if err != nil { if err != nil {
return return
} }