From d767523565f8dbf9f88df13c7613957d1f745287 Mon Sep 17 00:00:00 2001 From: mudler Date: Thu, 2 Feb 2023 15:12:33 +0100 Subject: [PATCH] Add simple test suite --- Earthfile | 30 ++++++++++++ go.mod | 6 +++ go.sum | 7 ++- internal/cmd/commands.go | 7 +-- pkg/mount/mount.go | 29 ++++++++++-- pkg/mount/mount_suite_test.go | 13 ++++++ pkg/mount/mount_test.go | 87 +++++++++++++++++++++++++++++++++++ 7 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 pkg/mount/mount_suite_test.go create mode 100644 pkg/mount/mount_test.go diff --git a/Earthfile b/Earthfile index 2b963e5..ffe233a 100644 --- a/Earthfile +++ b/Earthfile @@ -4,6 +4,36 @@ VERSION 0.6 # Framework images should use our initrd ARG BASE_IMAGE=quay.io/kairos/core-opensuse-leap +ARG GO_VERSION=1.18 +ARG GOLINT_VERSION=1.47.3 + +go-deps: + ARG GO_VERSION + FROM golang:$GO_VERSION + WORKDIR /build + COPY go.mod go.sum ./ + RUN go mod download + RUN apt-get update + SAVE ARTIFACT go.mod AS LOCAL go.mod + SAVE ARTIFACT go.sum AS LOCAL go.sum + +test: + FROM +go-deps + WORKDIR /build + RUN go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo + COPY . . + RUN ginkgo run --race --fail-fast --slow-spec-threshold 30s --covermode=atomic --coverprofile=coverage.out -p -r ./... + SAVE ARTIFACT coverage.out AS LOCAL coverage.out + +lint: + ARG GO_VERSION + FROM golang:$GO_VERSION + ARG GOLINT_VERSION + RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v$GOLINT_VERSION + WORKDIR /build + COPY . . + RUN golangci-lint run + build-immucore: FROM golang:alpine RUN apk add git diff --git a/go.mod b/go.mod index 602bf4b..dc4c6c6 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ require ( github.com/deniswernert/go-fstab v0.0.0-20141204152952-eb4090f26517 github.com/kairos-io/kairos v1.5.0 github.com/moby/sys/mountinfo v0.5.0 + github.com/onsi/ginkgo/v2 v2.7.1 + github.com/onsi/gomega v1.26.0 github.com/rs/zerolog v1.29.0 github.com/spectrocloud-labs/herd v0.2.1 github.com/urfave/cli v1.22.10 @@ -21,8 +23,10 @@ require ( github.com/containerd/cgroups v1.0.4 // indirect github.com/containerd/console v1.0.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/go-logr/logr v1.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/gookit/color v1.5.2 // indirect github.com/joho/godotenv v1.4.0 // indirect github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c // indirect @@ -40,8 +44,10 @@ require ( github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opencensus.io v0.23.0 // indirect + golang.org/x/net v0.5.0 // indirect golang.org/x/sys v0.4.0 // indirect golang.org/x/term v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 17a2f45..322c786 100644 --- a/go.sum +++ b/go.sum @@ -300,6 +300,7 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -356,6 +357,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -370,6 +372,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -526,9 +529,9 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo/v2 v2.7.1 h1:YgLPk+gpqDtAPeRCWEmfO8oxE6ru3xcVSXAM7wn8w9I= +github.com/onsi/ginkgo/v2 v2.7.1/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -537,6 +540,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -815,6 +819,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/internal/cmd/commands.go b/internal/cmd/commands.go index bfdb431..6c21283 100644 --- a/internal/cmd/commands.go +++ b/internal/cmd/commands.go @@ -29,7 +29,8 @@ Sends a generic event payload with the configuration found in the scanned direct s := &mount.State{Rootdir: "/"} s.Register(g) - writeDag(g.Analyze()) + + log.Print(s.WriteDAG(g)) return nil //return g.Run(context.Background()) }, @@ -41,9 +42,9 @@ func writeDag(d [][]herd.GraphEntry) { log.Printf("%d.", (i + 1)) for _, op := range layer { if op.Error != nil { - log.Printf(" <%s> (error: %s) (background: %t)", op.Name, op.Error.Error(), op.Background) + log.Printf(" <%s> (error: %s) (background: %t) (weak: %t)", op.Name, op.Error.Error(), op.Background, op.WeakDeps) } else { - log.Printf(" <%s> (background: %t)", op.Name, op.Background) + log.Printf(" <%s> (background: %t) (weak: %t)", op.Name, op.Background, op.WeakDeps) } } log.Print("") diff --git a/pkg/mount/mount.go b/pkg/mount/mount.go index 810cdac..9a813e5 100644 --- a/pkg/mount/mount.go +++ b/pkg/mount/mount.go @@ -56,6 +56,7 @@ const ( opOverlayMount = "overlay-mount" opWriteFstab = "write-fstab" opMountBaseOverlay = "mount-base-overlay" + opMountOEM = "mount-oem" ) func (s *State) path(p ...string) string { @@ -119,6 +120,20 @@ func (s *State) MountOP(what, where, t string, options []string, timeout time.Du } } +func (s *State) WriteDAG(g *herd.Graph) (out string) { + for i, layer := range g.Analyze() { + out += fmt.Sprintf("%d.\n", (i + 1)) + for _, op := range layer { + if op.Error != nil { + out += fmt.Sprintf(" <%s> (error: %s) (background: %t) (weak: %t)\n", op.Name, op.Error.Error(), op.Background, op.WeakDeps) + } else { + out += fmt.Sprintf(" <%s> (background: %t) (weak: %t)\n", op.Name, op.Background, op.WeakDeps) + } + } + } + return +} + func (s *State) Register(g *herd.Graph) error { // TODO: add, hooks, fstab, systemd compat @@ -166,6 +181,9 @@ func (s *State) Register(g *herd.Graph) error { ) } + + mountRootCondition := herd.ConditionalOption(func() bool { return s.MountRoot }, herd.WithDeps(opMountRoot)) + // end sysroot mount // overlay mount start @@ -195,6 +213,7 @@ func (s *State) Register(g *herd.Graph) error { g.Add( genOpreferenceName(opOverlayMount, p), overlayCondition, + mountRootCondition, herd.WithCallback( func(ctx context.Context) error { op, err := mountWithBaseOverlay(p, s.Rootdir, "/run/overlay") @@ -212,6 +231,7 @@ func (s *State) Register(g *herd.Graph) error { for id, mountpoint := range s.CustomMounts { g.Add( genOpreferenceName(opCustomMounts, mountpoint), + mountRootCondition, overlayCondition, herd.WithCallback( s.MountOP( @@ -231,6 +251,7 @@ func (s *State) Register(g *herd.Graph) error { g.Add( genOpreferenceName(opMountState, p), overlayCondition, + mountRootCondition, herd.WithDeps(genOpreferenceFromMap(opCustomMounts, s.CustomMounts)...), herd.WithCallback( func(ctx context.Context) error { @@ -246,8 +267,9 @@ func (s *State) Register(g *herd.Graph) error { } // overlay mount end - g.Add(opMountRoot, - herd.ConditionalOption(func() bool { return s.MountRoot }, herd.WithDeps("mount-overlay-base")), + g.Add(opMountOEM, + overlayCondition, + mountRootCondition, herd.WithCallback( s.MountOP( "/dev/disk/by-label/COS_OEM", @@ -268,7 +290,8 @@ func (s *State) Register(g *herd.Graph) error { g.Add(opWriteFstab, overlayCondition, herd.ConditionalOption(func() bool { return s.MountRoot }, herd.WithDeps(opMountRoot)), - herd.WithDeps(opMountRoot), + herd.WithDeps(opMountOEM), + herd.WeakDeps, herd.WithDeps(genOpreferenceFromMap(opCustomMounts, s.CustomMounts)...), herd.WithDeps(genOpreference(opMountState, s.BindMounts)...), herd.WithDeps(genOpreference(opOverlayMount, s.OverlayDir)...), diff --git a/pkg/mount/mount_suite_test.go b/pkg/mount/mount_suite_test.go new file mode 100644 index 0000000..7acb880 --- /dev/null +++ b/pkg/mount/mount_suite_test.go @@ -0,0 +1,13 @@ +package mount_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestSuite(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "mount test Suite") +} diff --git a/pkg/mount/mount_test.go b/pkg/mount/mount_test.go new file mode 100644 index 0000000..fc95623 --- /dev/null +++ b/pkg/mount/mount_test.go @@ -0,0 +1,87 @@ +package mount_test + +import ( + "github.com/kairos-io/immucore/pkg/mount" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/spectrocloud-labs/herd" +) + +var _ = Describe("mounting immutable setup", func() { + var g *herd.Graph + + BeforeEach(func() { + g = herd.DAG() + }) + + Context("simple invocation", func() { + It("mounts base overlay, attempt to mount oem, and updates the fstab", func() { + s := &mount.State{Rootdir: "/"} + + s.Register(g) + + dag := g.Analyze() + + Expect(len(dag)).To(Equal(3)) // Expect 3 layers + Expect(len(dag[0])).To(Equal(1)) // 1 Item for each layer, as are tight deps + Expect(len(dag[1])).To(Equal(1)) + Expect(len(dag[2])).To(Equal(1)) + + Expect(dag[0][0].Name).To(Equal("mount-base-overlay")) + Expect(dag[1][0].Name).To(Equal("mount-oem")) + Expect(dag[2][0].Name).To(Equal("write-fstab")) + }) + + It("mounts base overlay, attempt to mount oem, and updates the fstab", func() { + s := &mount.State{Rootdir: "/", MountRoot: true} + + s.Register(g) + + dag := g.Analyze() + + Expect(len(dag)).To(Equal(5), s.WriteDAG(g)) // Expect 4 layers + Expect(len(dag[0])).To(Equal(2), s.WriteDAG(g)) // 2 items in first layer + Expect(len(dag[1])).To(Equal(1)) // 1 Item for each layer, as are tight deps + Expect(len(dag[2])).To(Equal(1)) + Expect(len(dag[3])).To(Equal(1)) + Expect(len(dag[4])).To(Equal(1)) + + Expect(dag[0][0].Name).To(Or(Equal("mount-base-overlay"), Equal("mount-state"))) + Expect(dag[0][1].Name).To(Or(Equal("mount-base-overlay"), Equal("mount-state"))) + + Expect(dag[1][0].Name).To(Equal("discover-state")) + Expect(dag[2][0].Name).To(Equal("mount-root")) + Expect(dag[3][0].Name).To(Equal("mount-oem")) + Expect(dag[4][0].Name).To(Equal("write-fstab")) + }) + + It("mounts all", func() { + s := &mount.State{Rootdir: "/", MountRoot: true, OverlayDir: []string{"/etc"}, BindMounts: []string{"/etc/kubernetes"}, CustomMounts: map[string]string{"COS_PERSISTENT": "/usr/local"}} + + s.Register(g) + + dag := g.Analyze() + + Expect(len(dag)).To(Equal(6), s.WriteDAG(g)) // Expect 6 layers + Expect(len(dag[0])).To(Equal(2), s.WriteDAG(g)) // 2 items in first layer + Expect(len(dag[1])).To(Equal(1), s.WriteDAG(g)) // 1 Item for each layer, as are tight deps + Expect(len(dag[2])).To(Equal(1), s.WriteDAG(g)) + Expect(len(dag[3])).To(Equal(3), s.WriteDAG(g)) + Expect(len(dag[4])).To(Equal(1), s.WriteDAG(g)) + Expect(len(dag[5])).To(Equal(1), s.WriteDAG(g)) + + Expect(dag[0][0].Name).To(Or(Equal("mount-base-overlay"), Equal("mount-state"))) + Expect(dag[0][1].Name).To(Or(Equal("mount-base-overlay"), Equal("mount-state"))) + + Expect(dag[1][0].Name).To(Equal("discover-state")) + Expect(dag[2][0].Name).To(Equal("mount-root")) + + Expect(dag[3][0].Name).To(Or(Equal("mount-oem"), Equal("overlay-mount-/etc"), Equal("custom-mount-/usr/local"))) + Expect(dag[3][1].Name).To(Or(Equal("mount-oem"), Equal("overlay-mount-/etc"), Equal("custom-mount-/usr/local"))) + Expect(dag[3][2].Name).To(Or(Equal("mount-oem"), Equal("overlay-mount-/etc"), Equal("custom-mount-/usr/local"))) + + Expect(dag[4][0].Name).To(Equal("mount-state-/etc/kubernetes")) + Expect(dag[5][0].Name).To(Equal("write-fstab")) + }) + }) +})