Define context for scoped operation across core types

It holds necessary state plus additional information relative to the
context which we are being run to (e.g. if we are in a terminal or not).
Besides in the future we can use it also as a contextual logger to
provide more smart logging capabilities.

This also replace the general global configuration instance that
previously was share between the core components.
This commit is contained in:
Ettore Di Giacinto
2021-10-21 00:13:02 +02:00
parent b9895c9e05
commit a1c669d3ae
89 changed files with 1774 additions and 1849 deletions

View File

@@ -18,14 +18,11 @@ package backend_test
import (
"testing"
. "github.com/mudler/luet/cmd/util"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestSolver(t *testing.T) {
RegisterFailHandler(Fail)
LoadConfig()
RunSpecs(t, "Backend Suite")
}

View File

@@ -18,8 +18,7 @@ package backend
import (
"os/exec"
"github.com/mudler/luet/pkg/config"
. "github.com/mudler/luet/pkg/logger"
"github.com/mudler/luet/pkg/api/core/types"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/pkg/errors"
@@ -44,17 +43,17 @@ type Options struct {
BackendArgs []string
}
func runCommand(cmd *exec.Cmd) error {
func runCommand(ctx *types.Context, cmd *exec.Cmd) error {
output := ""
buffered := !config.LuetCfg.GetGeneral().ShowBuildOutput
writer := NewBackendWriter(buffered)
buffered := !ctx.Config.GetGeneral().ShowBuildOutput
writer := NewBackendWriter(buffered, ctx)
cmd.Stdout = writer
cmd.Stderr = writer
if buffered {
Spinner(32)
defer SpinnerStop()
ctx.Spinner()
defer ctx.SpinnerStop()
}
err := cmd.Start()

View File

@@ -23,64 +23,66 @@ import (
"path/filepath"
"strings"
"github.com/mudler/luet/pkg/api/core/types"
bus "github.com/mudler/luet/pkg/bus"
fileHelper "github.com/mudler/luet/pkg/helpers/file"
capi "github.com/mudler/docker-companion/api"
"github.com/mudler/luet/pkg/helpers"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors"
)
type SimpleDocker struct{}
type SimpleDocker struct {
ctx *types.Context
}
func NewSimpleDockerBackend() *SimpleDocker {
return &SimpleDocker{}
func NewSimpleDockerBackend(ctx *types.Context) *SimpleDocker {
return &SimpleDocker{ctx: ctx}
}
// TODO: Missing still: labels, and build args expansion
func (*SimpleDocker) BuildImage(opts Options) error {
func (s *SimpleDocker) BuildImage(opts Options) error {
name := opts.ImageName
bus.Manager.Publish(bus.EventImagePreBuild, opts)
buildarg := genBuildCommand(opts)
Info(":whale2: Building image " + name)
s.ctx.Info(":whale2: Building image " + name)
cmd := exec.Command("docker", buildarg...)
cmd.Dir = opts.SourcePath
err := runCommand(cmd)
err := runCommand(s.ctx, cmd)
if err != nil {
return err
}
Info(":whale: Building image " + name + " done")
s.ctx.Info(":whale: Building image " + name + " done")
bus.Manager.Publish(bus.EventImagePostBuild, opts)
return nil
}
func (*SimpleDocker) CopyImage(src, dst string) error {
Debug(":whale: Tagging image:", src, "->", dst)
func (s *SimpleDocker) CopyImage(src, dst string) error {
s.ctx.Debug(":whale: Tagging image:", src, "->", dst)
cmd := exec.Command("docker", "tag", src, dst)
out, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed tagging image: "+string(out))
}
Info(":whale: Tagged image:", src, "->", dst)
s.ctx.Info(":whale: Tagged image:", src, "->", dst)
return nil
}
func (*SimpleDocker) DownloadImage(opts Options) error {
func (s *SimpleDocker) DownloadImage(opts Options) error {
name := opts.ImageName
bus.Manager.Publish(bus.EventImagePrePull, opts)
buildarg := []string{"pull", name}
Debug(":whale: Downloading image " + name)
s.ctx.Debug(":whale: Downloading image " + name)
Spinner(22)
defer SpinnerStop()
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
cmd := exec.Command("docker", buildarg...)
out, err := cmd.CombinedOutput()
@@ -88,20 +90,20 @@ func (*SimpleDocker) DownloadImage(opts Options) error {
return errors.Wrap(err, "Failed pulling image: "+string(out))
}
Info(":whale: Downloaded image:", name)
s.ctx.Info(":whale: Downloaded image:", name)
bus.Manager.Publish(bus.EventImagePostPull, opts)
return nil
}
func (*SimpleDocker) ImageExists(imagename string) bool {
func (s *SimpleDocker) ImageExists(imagename string) bool {
buildarg := []string{"inspect", "--type=image", imagename}
Debug(":whale: Checking existance of docker image: " + imagename)
s.ctx.Debug(":whale: Checking existance of docker image: " + imagename)
cmd := exec.Command("docker", buildarg...)
out, err := cmd.CombinedOutput()
if err != nil {
Debug("Image not present")
Debug(string(out))
s.ctx.Debug("Image not present")
s.ctx.Debug(string(out))
return false
}
return true
@@ -111,31 +113,31 @@ func (*SimpleDocker) ImageAvailable(imagename string) bool {
return imageAvailable(imagename)
}
func (*SimpleDocker) RemoveImage(opts Options) error {
func (s *SimpleDocker) RemoveImage(opts Options) error {
name := opts.ImageName
buildarg := []string{"rmi", name}
out, err := exec.Command("docker", buildarg...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed removing image: "+string(out))
}
Info(":whale: Removed image:", name)
s.ctx.Info(":whale: Removed image:", name)
//Info(string(out))
return nil
}
func (*SimpleDocker) Push(opts Options) error {
func (s *SimpleDocker) Push(opts Options) error {
name := opts.ImageName
pusharg := []string{"push", name}
bus.Manager.Publish(bus.EventImagePrePush, opts)
Spinner(22)
defer SpinnerStop()
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
out, err := exec.Command("docker", pusharg...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed pushing image: "+string(out))
}
Info(":whale: Pushed image:", name)
s.ctx.Info(":whale: Pushed image:", name)
bus.Manager.Publish(bus.EventImagePostPush, opts)
//Info(string(out))
@@ -155,22 +157,22 @@ func (s *SimpleDocker) ImageDefinitionToTar(opts Options) error {
return nil
}
func (*SimpleDocker) ExportImage(opts Options) error {
func (s *SimpleDocker) ExportImage(opts Options) error {
name := opts.ImageName
path := opts.Destination
buildarg := []string{"save", name, "-o", path}
Debug(":whale: Saving image " + name)
s.ctx.Debug(":whale: Saving image " + name)
Spinner(22)
defer SpinnerStop()
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
out, err := exec.Command("docker", buildarg...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed exporting image: "+string(out))
}
Debug(":whale: Exported image:", name)
s.ctx.Debug(":whale: Exported image:", name)
return nil
}
@@ -196,15 +198,13 @@ func (b *SimpleDocker) ExtractRootfs(opts Options, keepPerms bool) error {
imageExport := filepath.Join(tempexport, "image.tar")
Spinner(22)
defer SpinnerStop()
b.ctx.Spinner()
defer b.ctx.SpinnerStop()
if err := b.ExportImage(Options{ImageName: name, Destination: imageExport}); err != nil {
return errors.Wrap(err, "failed while extracting rootfs for "+name)
}
SpinnerStop()
src := imageExport
if src == "" && opts.ImageName != "" {

View File

@@ -16,6 +16,7 @@
package backend_test
import (
"github.com/mudler/luet/pkg/api/core/types"
"github.com/mudler/luet/pkg/api/core/types/artifact"
"github.com/mudler/luet/pkg/compiler"
. "github.com/mudler/luet/pkg/compiler"
@@ -35,6 +36,7 @@ import (
var _ = Describe("Docker backend", func() {
Context("Simple Docker backend satisfies main interface functionalities", func() {
ctx := types.NewContext()
It("Builds and generate tars", func() {
generalRecipe := tree.NewGeneralRecipe(pkg.NewInMemoryDatabase(false))
@@ -69,7 +71,7 @@ WORKDIR /luetbuild
ENV PACKAGE_NAME=enman
ENV PACKAGE_VERSION=1.4.0
ENV PACKAGE_CATEGORY=app-admin`))
b := NewSimpleDockerBackend()
b := NewSimpleDockerBackend(ctx)
opts := backend.Options{
ImageName: "luet/base",
SourcePath: tmpdir,
@@ -115,7 +117,7 @@ RUN echo bar > /test2`))
artifacts = append(artifacts, artifact.ArtifactNode{Name: "/test", Size: 4})
artifacts = append(artifacts, artifact.ArtifactNode{Name: "/test2", Size: 4})
Expect(compiler.GenerateChanges(b, opts, opts2)).To(Equal(
Expect(compiler.GenerateChanges(ctx, b, opts, opts2)).To(Equal(
[]artifact.ArtifactLayer{{
FromImage: "luet/base",
ToImage: "test",
@@ -137,7 +139,7 @@ RUN echo bar > /test2`))
})
It("Detects available images", func() {
b := NewSimpleDockerBackend()
b := NewSimpleDockerBackend(ctx)
Expect(b.ImageAvailable("quay.io/mocaccino/extra")).To(BeTrue())
Expect(b.ImageAvailable("ubuntu:20.10")).To(BeTrue())
Expect(b.ImageAvailable("igjo5ijgo25nho52")).To(BeFalse())

View File

@@ -20,64 +20,65 @@ import (
"os/exec"
"strings"
"github.com/mudler/luet/pkg/api/core/types"
bus "github.com/mudler/luet/pkg/bus"
. "github.com/mudler/luet/pkg/logger"
"github.com/pkg/errors"
)
type SimpleImg struct{}
type SimpleImg struct {
ctx *types.Context
}
func NewSimpleImgBackend() *SimpleImg {
return &SimpleImg{}
func NewSimpleImgBackend(ctx *types.Context) *SimpleImg {
return &SimpleImg{ctx: ctx}
}
// TODO: Missing still: labels, and build args expansion
func (*SimpleImg) BuildImage(opts Options) error {
func (s *SimpleImg) BuildImage(opts Options) error {
name := opts.ImageName
bus.Manager.Publish(bus.EventImagePreBuild, opts)
buildarg := genBuildCommand(opts)
Info(":tea: Building image " + name)
s.ctx.Info(":tea: Building image " + name)
cmd := exec.Command("img", buildarg...)
cmd.Dir = opts.SourcePath
err := runCommand(cmd)
err := runCommand(s.ctx, cmd)
if err != nil {
return err
}
bus.Manager.Publish(bus.EventImagePostBuild, opts)
Info(":tea: Building image " + name + " done")
s.ctx.Info(":tea: Building image " + name + " done")
return nil
}
func (*SimpleImg) RemoveImage(opts Options) error {
func (s *SimpleImg) RemoveImage(opts Options) error {
name := opts.ImageName
buildarg := []string{"rm", name}
Spinner(22)
defer SpinnerStop()
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
out, err := exec.Command("img", buildarg...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed removing image: "+string(out))
}
Info(":tea: Image " + name + " removed")
s.ctx.Info(":tea: Image " + name + " removed")
return nil
}
func (*SimpleImg) DownloadImage(opts Options) error {
func (s *SimpleImg) DownloadImage(opts Options) error {
name := opts.ImageName
bus.Manager.Publish(bus.EventImagePrePull, opts)
buildarg := []string{"pull", name}
Debug(":tea: Downloading image " + name)
s.ctx.Debug(":tea: Downloading image " + name)
Spinner(22)
defer SpinnerStop()
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
cmd := exec.Command("img", buildarg...)
out, err := cmd.CombinedOutput()
@@ -85,27 +86,27 @@ func (*SimpleImg) DownloadImage(opts Options) error {
return errors.Wrap(err, "Failed downloading image: "+string(out))
}
Info(":tea: Image " + name + " downloaded")
s.ctx.Info(":tea: Image " + name + " downloaded")
bus.Manager.Publish(bus.EventImagePostPull, opts)
return nil
}
func (*SimpleImg) CopyImage(src, dst string) error {
Spinner(22)
defer SpinnerStop()
func (s *SimpleImg) CopyImage(src, dst string) error {
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
Debug(":tea: Tagging image", src, dst)
s.ctx.Debug(":tea: Tagging image", src, dst)
cmd := exec.Command("img", "tag", src, dst)
out, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed tagging image: "+string(out))
}
Info(":tea: Image " + dst + " tagged")
s.ctx.Info(":tea: Image " + dst + " tagged")
return nil
}
func (*SimpleImg) ImageAvailable(imagename string) bool {
func (s *SimpleImg) ImageAvailable(imagename string) bool {
return imageAvailable(imagename)
}
@@ -135,20 +136,20 @@ func (s *SimpleImg) ImageDefinitionToTar(opts Options) error {
return nil
}
func (*SimpleImg) ExportImage(opts Options) error {
func (s *SimpleImg) ExportImage(opts Options) error {
name := opts.ImageName
path := opts.Destination
buildarg := []string{"save", "-o", path, name}
Debug(":tea: Saving image " + name)
s.ctx.Debug(":tea: Saving image " + name)
Spinner(22)
defer SpinnerStop()
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
out, err := exec.Command("img", buildarg...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed exporting image: "+string(out))
}
Info(":tea: Image " + name + " saved")
s.ctx.Info(":tea: Image " + name + " saved")
return nil
}
@@ -166,20 +167,20 @@ func (s *SimpleImg) ExtractRootfs(opts Options, keepPerms bool) error {
os.RemoveAll(path)
buildarg := []string{"unpack", "-o", path, name}
Debug(":tea: Extracting image " + name)
s.ctx.Debug(":tea: Extracting image " + name)
Spinner(22)
defer SpinnerStop()
s.ctx.Spinner()
defer s.ctx.SpinnerStop()
out, err := exec.Command("img", buildarg...).CombinedOutput()
if err != nil {
return errors.Wrap(err, "Failed extracting image: "+string(out))
}
Debug(":tea: Image " + name + " extracted")
s.ctx.Debug(":tea: Image " + name + " extracted")
return nil
}
func (*SimpleImg) Push(opts Options) error {
func (s *SimpleImg) Push(opts Options) error {
name := opts.ImageName
bus.Manager.Publish(bus.EventImagePrePush, opts)
@@ -188,9 +189,9 @@ func (*SimpleImg) Push(opts Options) error {
if err != nil {
return errors.Wrap(err, "Failed pushing image: "+string(out))
}
Info(":tea: Pushed image:", name)
s.ctx.Info(":tea: Pushed image:", name)
bus.Manager.Publish(bus.EventImagePostPush, opts)
//Info(string(out))
//s.ctx.Info(string(out))
return nil
}

View File

@@ -19,18 +19,20 @@ package backend
import (
"bytes"
. "github.com/mudler/luet/pkg/logger"
"github.com/mudler/luet/pkg/api/core/types"
)
type BackendWriter struct {
BufferedOutput bool
Buffer *bytes.Buffer
ctx *types.Context
}
func NewBackendWriter(buffered bool) *BackendWriter {
func NewBackendWriter(buffered bool, ctx *types.Context) *BackendWriter {
return &BackendWriter{
BufferedOutput: buffered,
Buffer: &bytes.Buffer{},
ctx: ctx,
}
}
@@ -39,7 +41,7 @@ func (b *BackendWriter) Write(p []byte) (int, error) {
return b.Buffer.Write(p)
}
Msg("info", false, false, (string(p)))
b.ctx.Msg("info", false, (string(p)))
return len(p), nil
}