kairos-sdk/sysext/sysext_test.go

176 lines
5.3 KiB
Go

package sysext
import (
"bytes"
"context"
"fmt"
dockerImage "github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/daemon"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/kairos-io/kairos-sdk/types"
"github.com/kairos-io/kairos-sdk/utils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"math/rand"
"os"
"path/filepath"
"regexp"
"testing"
)
func TestSuite(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "sysext Test Suite")
}
var _ = Describe("sysext", Label("sysext"), Ordered, func() {
var dest string
var image v1.Image
var imageTag string
var buf bytes.Buffer
var log types.KairosLogger
var err error
BeforeEach(func() {
buf = bytes.Buffer{}
log = types.NewBufferLogger(&buf)
dest, err = os.MkdirTemp("", "")
Expect(err).ToNot(HaveOccurred())
})
AfterEach(func() {
if CurrentSpecReport().Failed() {
_, _ = GinkgoWriter.Write(buf.Bytes())
}
Expect(os.RemoveAll(dest)).To(Succeed())
})
When("Using a normal image", func() {
BeforeEach(func() {
imageTag = createTestDockerImage()
By(fmt.Sprintf("Created image %s", imageTag))
image, err = utils.GetImage(imageTag, utils.GetCurrentPlatform(), nil, nil)
Expect(err).ToNot(HaveOccurred())
})
AfterEach(func() {
cli, _ := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
_, _ = cli.ImageRemove(context.Background(), imageTag, dockerImage.RemoveOptions{Force: true})
By(fmt.Sprintf("Removed image %s", imageTag))
})
It("should extract the files into the dir", func() {
err = ExtractFilesFromLastLayer(image, dest, log, DefaultAllowListRegex)
Expect(err).ToNot(HaveOccurred())
_, err := os.Stat(filepath.Join(dest, "usr", "yes"))
Expect(err).ToNot(HaveOccurred())
_, err = os.Stat(filepath.Join(dest, "etc", "yes"))
Expect(err).ToNot(HaveOccurred())
_, err = os.Stat(filepath.Join(dest, "opt", "nope"))
Expect(err).To(HaveOccurred())
_, err = os.Stat(filepath.Join(dest, "var", "nope"))
Expect(err).To(HaveOccurred())
})
It("properly uses the allowList", func() {
allowList := regexp.MustCompile(`^var|^/var`)
err = ExtractFilesFromLastLayer(image, dest, log, allowList)
Expect(err).ToNot(HaveOccurred())
_, err := os.Stat(filepath.Join(dest, "usr", "yes"))
Expect(err).To(HaveOccurred())
_, err = os.Stat(filepath.Join(dest, "etc", "yes"))
Expect(err).To(HaveOccurred())
_, err = os.Stat(filepath.Join(dest, "opt", "nope"))
Expect(err).To(HaveOccurred())
_, err = os.Stat(filepath.Join(dest, "var", "nope"))
Expect(err).ToNot(HaveOccurred())
})
})
When("Using an empty image", func() {
BeforeEach(func() {
imageTag = createEmptyDockerImage()
By(fmt.Sprintf("Created image %s", imageTag))
image, err = utils.GetImage(imageTag, utils.GetCurrentPlatform(), nil, nil)
Expect(err).ToNot(HaveOccurred())
})
AfterEach(func() {
cli, _ := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
_, _ = cli.ImageRemove(context.Background(), imageTag, dockerImage.RemoveOptions{Force: true})
By(fmt.Sprintf("Removed image %s", imageTag))
})
It("Fails with no layers image", func() {
// Cleanup existing image before creating a new one
err = ExtractFilesFromLastLayer(image, dest, log, DefaultAllowListRegex)
Expect(err).To(HaveOccurred())
Expect(err).To(Equal(ErrorImageNoLayers))
})
})
})
func createEmptyDockerImage() string {
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
b := make([]rune, 8)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
img, err := mutate.AppendLayers(empty.Image)
Expect(err).ToNot(HaveOccurred())
// Set the platform to AMD64
cfg, err := img.ConfigFile()
Expect(err).ToNot(HaveOccurred())
cfg.Architecture = "amd64"
cfg.OS = "linux"
img, err = mutate.ConfigFile(img, cfg)
Expect(err).ToNot(HaveOccurred())
tag, err := name.NewTag(fmt.Sprintf("kairos-empty-%s:latest", string(b)))
Expect(err).ToNot(HaveOccurred())
_, err = daemon.Write(tag, img)
Expect(err).ToNot(HaveOccurred())
return tag.String()
}
func createTestDockerImage() string {
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
b := make([]rune, 8)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
// We don't care about this layer so make it a bit fake
fistLayer, _ := crane.Layer(map[string][]byte{
"/etc/one": []byte("hello"),
"/etc/another": []byte("world"),
})
secondLayer, err := tarball.LayerFromFile("testdata/test.tar")
Expect(err).ToNot(HaveOccurred())
img, err := mutate.AppendLayers(empty.Image, fistLayer, secondLayer)
Expect(err).ToNot(HaveOccurred())
// Set the platform to AMD64
cfg, err := img.ConfigFile()
Expect(err).ToNot(HaveOccurred())
cfg.Architecture = "amd64"
cfg.OS = "linux"
img, err = mutate.ConfigFile(img, cfg)
Expect(err).ToNot(HaveOccurred())
tag, err := name.NewTag(fmt.Sprintf("kairos-test-%s:latest", string(b)))
Expect(err).ToNot(HaveOccurred())
_, err = daemon.Write(tag, img)
Expect(err).ToNot(HaveOccurred())
return tag.String()
}