94 lines
2.0 KiB
Go
94 lines
2.0 KiB
Go
|
// Copyright 2023 Mikhail Klementev. All rights reserved.
|
||
|
// Use of this source code is governed by a AGPLv3 license
|
||
|
// (or later) that can be found in the LICENSE file.
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"os/user"
|
||
|
"time"
|
||
|
|
||
|
"github.com/rs/zerolog/log"
|
||
|
)
|
||
|
|
||
|
type container struct {
|
||
|
name string
|
||
|
timeout time.Duration
|
||
|
Volumes struct {
|
||
|
LibModules string
|
||
|
UsrSrc string
|
||
|
Boot string
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func NewContainer(name string, timeout time.Duration) (c container, err error) {
|
||
|
c.name = name
|
||
|
c.timeout = timeout
|
||
|
|
||
|
usr, err := user.Current()
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
c.Volumes.LibModules = fmt.Sprintf(
|
||
|
"%s/.out-of-tree/volumes/%s/lib/modules", usr.HomeDir, name)
|
||
|
os.MkdirAll(c.Volumes.LibModules, 0777)
|
||
|
|
||
|
c.Volumes.UsrSrc = fmt.Sprintf(
|
||
|
"%s/.out-of-tree/volumes/%s/usr/src", usr.HomeDir, name)
|
||
|
os.MkdirAll(c.Volumes.UsrSrc, 0777)
|
||
|
|
||
|
c.Volumes.Boot = fmt.Sprintf(
|
||
|
"%s/.out-of-tree/volumes/%s/boot", usr.HomeDir, name)
|
||
|
os.MkdirAll(c.Volumes.Boot, 0777)
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (c container) Build(imagePath string) (output string, err error) {
|
||
|
args := []string{"build"}
|
||
|
args = append(args, "-t", c.name, imagePath)
|
||
|
|
||
|
cmd := exec.Command("docker", args...)
|
||
|
log.Debug().Msgf("%v", cmd)
|
||
|
|
||
|
rawOutput, err := cmd.CombinedOutput()
|
||
|
output = string(rawOutput)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (c container) Run(workdir string, command string) (output string, err error) {
|
||
|
cmd := exec.Command("docker", "run", "--rm",
|
||
|
"-v", workdir+":/work",
|
||
|
"-v", c.Volumes.LibModules+":/lib/modules",
|
||
|
"-v", c.Volumes.UsrSrc+":/usr/src",
|
||
|
"-v", c.Volumes.Boot+":/boot",
|
||
|
c.name, "bash", "-c", "cd /work && "+command)
|
||
|
|
||
|
log.Debug().Msgf("%v", cmd)
|
||
|
|
||
|
timer := time.AfterFunc(c.timeout, func() {
|
||
|
log.Info().Str("container", c.name).
|
||
|
Str("workdir", workdir).
|
||
|
Str("command", command).
|
||
|
Msg("killing container by timeout")
|
||
|
cmd.Process.Kill()
|
||
|
})
|
||
|
defer timer.Stop()
|
||
|
|
||
|
raw, err := cmd.CombinedOutput()
|
||
|
if err != nil {
|
||
|
e := fmt.Sprintf("error `%v` for cmd `%v` with output `%v`",
|
||
|
err, command, string(raw))
|
||
|
err = errors.New(e)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
output = string(raw)
|
||
|
return
|
||
|
}
|