Skip to content

Commit

Permalink
Merge pull request #9 from siemens/feature/morbyd
Browse files Browse the repository at this point in the history
Feature/morbyd
  • Loading branch information
thediveo authored Feb 2, 2024
2 parents 41c00dc + 371c2d3 commit f21b669
Show file tree
Hide file tree
Showing 13 changed files with 352 additions and 378 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
![goroutines](https://img.shields.io/badge/go%20routines-not%20leaking-success)
![file descriptors](https://img.shields.io/badge/file%20descriptors-not%20leaking-success)
[![Go Report Card](https://goreportcard.com/badge/github.com/siemens/turtlefinder)](https://goreportcard.com/report/github.com/siemens/turtlefinder)
![Coverage](https://img.shields.io/badge/Coverage-87.8%25-brightgreen)
![Coverage](https://img.shields.io/badge/Coverage-87.4%25-brightgreen)

> 🐢🐘 ["Turtles all the way down"
> (Wikipedia)](https://en.wikipedia.org/wiki/Turtles_all_the_way_down)
Expand Down Expand Up @@ -160,6 +160,6 @@ Please see [CONTRIBUTING.md](CONTRIBUTING.md).

## License and Copyright

(c) Siemens AG 2023
(c) Siemens AG 2023‒24

[SPDX-License-Identifier: MIT](LICENSE)
1 change: 1 addition & 0 deletions _test/pind/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ RUN dnf -y install \
--exclude container-selinux && \
dnf clean all && \
rm -rf /var/cache /var/log/dnf* /var/log/yum.* && \
systemctl mask systemd-logind.service getty.service getty.target && \
systemctl enable podman.socket
CMD [ "/usr/sbin/init" ]
3 changes: 2 additions & 1 deletion daemonfinder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import (
"strings"
"time"

"github.com/thediveo/lxkns/model"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/thediveo/lxkns/model"
. "github.com/thediveo/success"
)

Expand Down
129 changes: 66 additions & 63 deletions detector/containerd/containerd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ package containerd
import (
"context"
"fmt"
"io"
"os"
"time"

"github.com/containerd/containerd"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
detect "github.com/siemens/turtlefinder/detector"
"github.com/thediveo/go-plugger/v3"
"github.com/thediveo/whalewatcher/engineclient/containerd/test/ctr"
"github.com/thediveo/morbyd"
"github.com/thediveo/morbyd/build"
"github.com/thediveo/morbyd/exec"
"github.com/thediveo/morbyd/run"
"github.com/thediveo/morbyd/session"
"github.com/thediveo/morbyd/timestamper"
"github.com/thediveo/whalewatcher/engineclient/cri/test/img"
"github.com/thediveo/whalewatcher/test"

Expand All @@ -37,9 +39,9 @@ const (

var _ = Describe("containerd turtle watcher", Ordered, func() {

var providerCntr *dockertest.Resource
var providerCntr *morbyd.Container

BeforeAll(func() {
BeforeAll(func(ctx context.Context) {
if os.Getuid() != 0 {
Skip("needs root")
}
Expand All @@ -52,18 +54,21 @@ var _ = Describe("containerd turtle watcher", Ordered, func() {
Expect(Filedescriptors()).NotTo(HaveLeakedFds(goodfds))
})

By("creating a new Docker session for testing")
sess := Successful(morbyd.NewSession(ctx,
session.WithAutoCleaning("test.turtlefinder=detector/containerd")))
DeferCleanup(func(ctx context.Context) {
By("auto-cleaning the session")
sess.Close(ctx)
})

By("spinning up a Docker container with stand-alone containerd, courtesy of the KinD k8s sig")
pool := Successful(dockertest.NewPool("unix:///run/docker.sock"))
_ = pool.RemoveContainerByName(kindischName)
// The necessary container start arguments come from KinD's Docker node
// provisioner, see:
// https://github.com/kubernetes-sigs/kind/blob/3610f606516ccaa88aa098465d8c13af70937050/pkg/cluster/internal/providers/docker/provision.go#L133
//
// Please note that --privileged already implies switching off AppArmor.
//
// Please note further, that currently some Docker client CLI flags
// don't translate into dockertest-supported options.
//
// docker run -it --rm --name kindisch-...
// --privileged
// --cgroupns=private
Expand All @@ -75,47 +80,31 @@ var _ = Describe("containerd turtle watcher", Ordered, func() {
// --volume /var
// --volume /lib/modules:/lib/modules:ro
// kindisch-...
Expect(pool.Client.BuildImage(docker.BuildImageOptions{
Name: img.Name,
ContextDir: "./_test/kindisch", // sorry, couldn't resist the pun.
Dockerfile: "Dockerfile",
BuildArgs: []docker.BuildArg{
{Name: "KINDEST_BASE_TAG", Value: test.KindestBaseImageTag},
},
OutputStream: io.Discard,
})).To(Succeed())
providerCntr = Successful(pool.RunWithOptions(
&dockertest.RunOptions{
Name: kindischName,
Repository: img.Name,
Privileged: true,
Mounts: []string{
"/var", // well, this actually is an unnamed volume
"/dev/mapper:/dev/mapper",
"/lib/modules:/lib/modules:ro",
},
Tty: true,
}, func(hc *docker.HostConfig) {
hc.Init = false
hc.Tmpfs = map[string]string{
"/tmp": "",
"/run": "",
}
hc.Devices = []docker.Device{
{PathOnHost: "/dev/fuse"},
}
}))
DeferCleanup(func() {
By("removing the containerd Docker container")
Expect(pool.Purge(providerCntr)).To(Succeed())
})
Expect(sess.BuildImage(ctx, "./_test/kindisch",
build.WithTag(img.Name),
build.WithBuildArg("KINDEST_BASE_TAG="+test.KindestBaseImageTag),
build.WithOutput(timestamper.New(GinkgoWriter)))).
Error().NotTo(HaveOccurred())
providerCntr = Successful(sess.Run(ctx, img.Name,
run.WithName(kindischName),
run.WithAutoRemove(),
run.WithPrivileged(),
run.WithSecurityOpt("label=disable"),
run.WithCgroupnsMode("private"),
run.WithVolume("/var"),
run.WithVolume("/dev/mapper:/dev/mapper"),
run.WithVolume("/lib/modules:/lib/modules:ro"),
run.WithTmpfs("/tmp"),
run.WithTmpfs("/run"),
run.WithDevice("/dev/fuse"),
run.WithCombinedOutput(timestamper.New(GinkgoWriter))))

By("waiting for containerized containerd to become responsive")
Expect(providerCntr.Container.State.Pid).NotTo(BeZero())
pid := Successful(providerCntr.PID(ctx))
// apipath must not include absolute symbolic links, but already be
// properly resolved.
endpointPath := fmt.Sprintf("/proc/%d/root%s",
providerCntr.Container.State.Pid, "/run/containerd/containerd.sock")
pid, "/run/containerd/containerd.sock")
var cdclient *containerd.Client
Eventually(func() error {
var err error
Expand All @@ -139,29 +128,43 @@ var _ = Describe("containerd turtle watcher", Ordered, func() {

It("watches successfully", NodeTimeout(30*time.Second), func(ctx context.Context) {
By("pulling a busybox image (if necessary)")
ctr.Successfully(providerCntr,
"-n", testNamespace,
"image", "pull", testImageRef)
ctr := Successful(providerCntr.Exec(ctx,
exec.Command("ctr",
"-n", testNamespace,
"image", "pull", testImageRef),
exec.WithCombinedOutput(timestamper.New(GinkgoWriter))))
Expect(ctr.Wait(ctx)).To(BeZero())

By("creating a new container+task and starting it")
ctr.Successfully(providerCntr,
"-n", testNamespace,
"run", "-d",
testImageRef,
testContainerName,
"/bin/sleep", "30s")
DeferCleanup(func() {
_ = ctr.Exec(providerCntr,
"-n", testNamespace,
"task", "rm", "-f", testContainerName)
_ = ctr.Exec(providerCntr,
ctr = Successful(providerCntr.Exec(ctx,
exec.Command("ctr",
"-n", testNamespace,
"container", "rm", testContainerName)
"run", "-d",
testImageRef,
testContainerName,
"/bin/sleep", "30s"),
exec.WithCombinedOutput(timestamper.New(GinkgoWriter))))
Expect(ctr.Wait(ctx)).To(BeZero())

DeferCleanup(func(ctx context.Context) {
ctr := Successful(providerCntr.Exec(ctx,
exec.Command("ctr",
"-n", testNamespace,
"task", "rm", "-f", testContainerName),
exec.WithCombinedOutput(timestamper.New(GinkgoWriter))))
_, _ = ctr.Wait(ctx)

ctr = Successful(providerCntr.Exec(ctx,
exec.Command("ctr",
"-n", testNamespace,
"container", "rm", testContainerName),
exec.WithCombinedOutput(timestamper.New(GinkgoWriter))))
_, _ = ctr.Wait(ctx)
})

By("running the detector on the API endpoints")
d := &Detector{}
wormhole := fmt.Sprintf("/proc/%d/root", providerCntr.Container.State.Pid)
wormhole := fmt.Sprintf("/proc/%d/root", Successful(providerCntr.PID(ctx)))
ws := d.NewWatchers(ctx, 0, []string{
wormhole + "/run/containerd/containerd.sock",
})
Expand Down
88 changes: 38 additions & 50 deletions detector/crio/crio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ package crio
import (
"context"
"fmt"
"io"
"os"
"time"

"github.com/containerd/containerd"
"github.com/google/uuid"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
detect "github.com/siemens/turtlefinder/detector"
"github.com/thediveo/go-plugger/v3"
"github.com/thediveo/morbyd"
"github.com/thediveo/morbyd/build"
"github.com/thediveo/morbyd/run"
"github.com/thediveo/morbyd/session"
"github.com/thediveo/morbyd/timestamper"
criengine "github.com/thediveo/whalewatcher/engineclient/cri"
"github.com/thediveo/whalewatcher/engineclient/cri/test/img"
"github.com/thediveo/whalewatcher/test"
Expand All @@ -41,9 +43,9 @@ const (

var _ = Describe("CRI-O turtle watcher", Ordered, func() {

var providerCntr *dockertest.Resource
var providerCntr *morbyd.Container

BeforeAll(func() {
BeforeAll(func(ctx context.Context) {
if os.Getuid() != 0 {
Skip("needs root")
}
Expand All @@ -56,18 +58,21 @@ var _ = Describe("CRI-O turtle watcher", Ordered, func() {
Expect(Filedescriptors()).NotTo(HaveLeakedFds(goodfds))
})

By("creating a new Docker session for testing")
sess := Successful(morbyd.NewSession(ctx,
session.WithAutoCleaning("test.turtlefinder=detector/crio")))
DeferCleanup(func(ctx context.Context) {
By("auto-cleaning the session")
sess.Close(ctx)
})

By("spinning up a Docker container with stand-alone CRI-O, courtesy of the KinD k8s sig and cri-o.io")
pool := Successful(dockertest.NewPool("unix:///run/docker.sock"))
_ = pool.RemoveContainerByName(kindischName)
// The necessary container start arguments come from KinD's Docker node
// provisioner, see:
// https://github.com/kubernetes-sigs/kind/blob/3610f606516ccaa88aa098465d8c13af70937050/pkg/cluster/internal/providers/docker/provision.go#L133
//
// Please note that --privileged already implies switching off AppArmor.
//
// Please note further, that currently some Docker client CLI flags
// don't translate into dockertest-supported options.
//
// docker run -it --rm --name kindisch-...
// --privileged
// --cgroupns=private
Expand All @@ -79,47 +84,31 @@ var _ = Describe("CRI-O turtle watcher", Ordered, func() {
// --volume /var
// --volume /lib/modules:/lib/modules:ro
// kindisch-...
Expect(pool.Client.BuildImage(docker.BuildImageOptions{
Name: img.Name,
ContextDir: "./_test/kindisch", // sorry, couldn't resist the pun.
Dockerfile: "Dockerfile",
BuildArgs: []docker.BuildArg{
{Name: "KINDEST_BASE_TAG", Value: test.KindestBaseImageTag},
},
OutputStream: io.Discard,
})).To(Succeed())
providerCntr = Successful(pool.RunWithOptions(
&dockertest.RunOptions{
Name: kindischName,
Repository: img.Name,
Privileged: true,
Mounts: []string{
"/var", // well, this actually is an unnamed volume
"/dev/mapper:/dev/mapper",
"/lib/modules:/lib/modules:ro",
},
Tty: true,
}, func(hc *docker.HostConfig) {
hc.Init = false
hc.Tmpfs = map[string]string{
"/tmp": "",
"/run": "",
}
hc.Devices = []docker.Device{
{PathOnHost: "/dev/fuse"},
}
}))
DeferCleanup(func() {
By("removing the CRI-O Docker container")
Expect(pool.Purge(providerCntr)).To(Succeed())
})
Expect(sess.BuildImage(ctx, "./_test/kindisch",
build.WithTag(img.Name),
build.WithBuildArg("KINDEST_BASE_TAG="+test.KindestBaseImageTag),
build.WithOutput(timestamper.New(GinkgoWriter)))).
Error().NotTo(HaveOccurred())
providerCntr = Successful(sess.Run(ctx, img.Name,
run.WithName(kindischName),
run.WithAutoRemove(),
run.WithPrivileged(),
run.WithSecurityOpt("label=disable"),
run.WithCgroupnsMode("private"),
run.WithVolume("/var"),
run.WithVolume("/dev/mapper:/dev/mapper"),
run.WithVolume("/lib/modules:/lib/modules:ro"),
run.WithTmpfs("/tmp"),
run.WithTmpfs("/run"),
run.WithDevice("/dev/fuse"),
run.WithCombinedOutput(timestamper.New(GinkgoWriter))))

By("waiting for containerized CRI-O to become responsive")
Expect(providerCntr.Container.State.Pid).NotTo(BeZero())
pid := Successful(providerCntr.PID(ctx))
// apipath must not include absolute symbolic links, but already be
// properly resolved.
endpointPath := fmt.Sprintf("/proc/%d/root%s",
providerCntr.Container.State.Pid, "/run/crio/crio.sock")
pid, "/run/crio/crio.sock")
var cdclient *containerd.Client
Eventually(func() error {
var err error
Expand All @@ -145,11 +134,10 @@ var _ = Describe("CRI-O turtle watcher", Ordered, func() {
var cricl *criengine.Client

By("waiting for the CRI-O API to become responsive")
Expect(providerCntr.Container.State.Pid).NotTo(BeZero())
pid := Successful(providerCntr.PID(ctx))
// apipath must not include absolute symbolic links, but already be
// properly resolved.
endpoint := fmt.Sprintf("/proc/%d/root/run/crio/crio.sock",
providerCntr.Container.State.Pid)
endpoint := fmt.Sprintf("/proc/%d/root/run/crio/crio.sock", pid)
Eventually(func() error {
var err error
cricl, err = criengine.New(endpoint, criengine.WithTimeout(1*time.Second))
Expand Down Expand Up @@ -232,7 +220,7 @@ var _ = Describe("CRI-O turtle watcher", Ordered, func() {

By("running the detector on the API endpoints")
d := &Detector{}
wormhole := fmt.Sprintf("/proc/%d/root", providerCntr.Container.State.Pid)
wormhole := fmt.Sprintf("/proc/%d/root", pid)
ws := d.NewWatchers(ctx, 0, []string{
wormhole + "/run/crio/crio.sock",
})
Expand Down
Loading

0 comments on commit f21b669

Please sign in to comment.