From fece1ae73270525d79bfa3ccfbf82bd19eb4cf39 Mon Sep 17 00:00:00 2001 From: Yoni Bettan Date: Tue, 3 Sep 2024 12:59:11 +0300 Subject: [PATCH] Removing the `ImageMounter` interface. (#1196) Now that we are using the cluster's container-runtime to pull the driver-container, then we don't need to manually pull and mount the images from the worker's code anymore. Signed-off-by: Yoni Bettan --- cmd/worker/funcs_kmod.go | 21 +- internal/worker/imagemounter.go | 88 -------- internal/worker/imagemounter_test.go | 65 ------ internal/worker/mock_imagemounter.go | 93 --------- internal/worker/mock_remoteimagemounter.go | 55 ----- internal/worker/remoteimagemounter.go | 175 ---------------- internal/worker/remoteimagemounter_test.go | 228 --------------------- internal/worker/tarimagemounter.go | 52 ----- internal/worker/tarimagemounter_test.go | 69 ------- internal/worker/worker.go | 4 +- internal/worker/worker_test.go | 10 +- 11 files changed, 5 insertions(+), 855 deletions(-) delete mode 100644 internal/worker/imagemounter.go delete mode 100644 internal/worker/imagemounter_test.go delete mode 100644 internal/worker/mock_imagemounter.go delete mode 100644 internal/worker/mock_remoteimagemounter.go delete mode 100644 internal/worker/remoteimagemounter.go delete mode 100644 internal/worker/remoteimagemounter_test.go delete mode 100644 internal/worker/tarimagemounter.go delete mode 100644 internal/worker/tarimagemounter_test.go diff --git a/cmd/worker/funcs_kmod.go b/cmd/worker/funcs_kmod.go index 82ed06a93..217f79dbc 100644 --- a/cmd/worker/funcs_kmod.go +++ b/cmd/worker/funcs_kmod.go @@ -10,12 +10,8 @@ import ( func rootFuncPreRunE(cmd *cobra.Command, args []string) error { logger.Info("Starting worker", "version", Version, "git commit", GitCommit) - im, err := getImageMounter(cmd) - if err != nil { - return fmt.Errorf("failed to get appropriate ImageMounter: %v", err) - } mr := worker.NewModprobeRunner(logger) - w = worker.NewWorker(im, mr, logger) + w = worker.NewWorker(mr, logger) return nil } @@ -78,18 +74,3 @@ func setCommandsFlags() { "If true, extract the image from a tarball image instead of pulling from the registry", ) } - -func getImageMounter(cmd *cobra.Command) (worker.ImageMounter, error) { - flag := cmd.Flags().Lookup("tarball") - if flag.Changed { - return worker.NewTarImageMounter(worker.ImagesDir, logger), nil - } - - logger.Info("Reading pull secrets", "base dir", worker.PullSecretsDir) - keyChain, err := worker.ReadKubernetesSecrets(cmd.Context(), worker.PullSecretsDir, logger) - if err != nil { - return nil, fmt.Errorf("could not read pull secrets: %v", err) - } - res := worker.NewMirrorResolver(logger) - return worker.NewRemoteImageMounter(worker.ImagesDir, res, keyChain, logger), nil -} diff --git a/internal/worker/imagemounter.go b/internal/worker/imagemounter.go deleted file mode 100644 index 50976bbe8..000000000 --- a/internal/worker/imagemounter.go +++ /dev/null @@ -1,88 +0,0 @@ -package worker - -import ( - "context" - "errors" - "fmt" - "io" - "sync" - - "github.com/docker/docker/pkg/idtools" - "github.com/go-logr/logr" - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/v1" - "github.com/moby/moby/pkg/archive" - kmmv1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1" -) - -//go:generate mockgen -source=imagemounter.go -package=worker -destination=mock_imagemounter.go ImageMounter - -type ImageMounter interface { - MountImage(ctx context.Context, imageName string, cfg *kmmv1beta1.ModuleConfig) (string, error) -} - -//go:generate mockgen -source=imagemounter.go -package=worker -destination=mock_imagemounter.go ociImageMounterHelperAPI - -type ociImageMounterHelperAPI interface { - mountOCIImage(image v1.Image, dstDirFS string) error -} - -type ociImageMounterHelper struct { - logger logr.Logger -} - -func newOCIImageMounterHelper(logger logr.Logger) ociImageMounterHelperAPI { - return &ociImageMounterHelper{logger: logger} -} - -func (oimh *ociImageMounterHelper) mountOCIImage(ociImage v1.Image, dstDirFS string) error { - errs := make(chan error, 2) - - wg := sync.WaitGroup{} - wg.Add(2) - - rd, wr := io.Pipe() - - go func() { - defer wg.Done() - defer wr.Close() - - oimh.logger.V(1).Info("Starting to export OCI image") - - if err := crane.Export(ociImage, wr); err != nil { - errs <- err - return - } - - oimh.logger.V(1).Info("Done exporting OCI image") - }() - - go func() { - defer wg.Done() - defer rd.Close() - - id := idtools.CurrentIdentity() - - tarOpts := &archive.TarOptions{ChownOpts: &id} - - if err := archive.Untar(rd, dstDirFS, tarOpts); err != nil { - errs <- err - return - } - - oimh.logger.V(1).Info("Done writing tar archive") - }() - - wg.Wait() - close(errs) - chErrs := make([]error, 0) - - for chErr := range errs { - chErrs = append(chErrs, chErr) - } - - if err := errors.Join(chErrs...); err != nil { - return fmt.Errorf("got one or more errors while writing the image: %v", err) - } - return nil -} diff --git a/internal/worker/imagemounter_test.go b/internal/worker/imagemounter_test.go deleted file mode 100644 index d3e54c036..000000000 --- a/internal/worker/imagemounter_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package worker - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/v1/empty" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func sameFiles(a, b string) (bool, error) { - fiA, err := os.Stat(a) - if err != nil { - return false, fmt.Errorf("could not stat() the first file: %v", err) - } - - fiB, err := os.Stat(b) - if err != nil { - return false, fmt.Errorf("could not stat() the second file: %v", err) - } - - return os.SameFile(fiA, fiB), nil -} - -var _ = Describe("ImageMounter_mountOCIImage", func() { - - It("good flow", func() { - tmpDir := GinkgoT().TempDir() - - ociImage, err := crane.Append(empty.Image, "testdata/archive.tar") - Expect(err).NotTo(HaveOccurred()) - - oimh := newOCIImageMounterHelper(GinkgoLogr) - err = oimh.mountOCIImage(ociImage, tmpDir) - - Expect(err).NotTo(HaveOccurred()) - Expect(filepath.Join(tmpDir, "subdir")).To(BeADirectory()) - Expect(filepath.Join(tmpDir, "subdir", "subsubdir")).To(BeADirectory()) - - Expect(filepath.Join(tmpDir, "a")).To(BeARegularFile()) - Expect(filepath.Join(tmpDir, "subdir", "b")).To(BeARegularFile()) - Expect(filepath.Join(tmpDir, "subdir", "subsubdir", "c")).To(BeARegularFile()) - - Expect( - os.Readlink(filepath.Join(tmpDir, "lib-modules-symlink")), - ).To( - Equal("/lib/modules"), - ) - - Expect( - os.Readlink(filepath.Join(tmpDir, "symlink")), - ).To( - Equal("a"), - ) - - Expect( - sameFiles(filepath.Join(tmpDir, "link"), filepath.Join(tmpDir, "a")), - ).To( - BeTrue(), - ) - }) -}) diff --git a/internal/worker/mock_imagemounter.go b/internal/worker/mock_imagemounter.go deleted file mode 100644 index d8bca0be1..000000000 --- a/internal/worker/mock_imagemounter.go +++ /dev/null @@ -1,93 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: imagemounter.go -// -// Generated by this command: -// -// mockgen -source=imagemounter.go -package=worker -destination=mock_imagemounter.go ociImageMounterHelperAPI -// -// Package worker is a generated GoMock package. -package worker - -import ( - context "context" - reflect "reflect" - - v1 "github.com/google/go-containerregistry/pkg/v1" - v1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1" - gomock "go.uber.org/mock/gomock" -) - -// MockImageMounter is a mock of ImageMounter interface. -type MockImageMounter struct { - ctrl *gomock.Controller - recorder *MockImageMounterMockRecorder -} - -// MockImageMounterMockRecorder is the mock recorder for MockImageMounter. -type MockImageMounterMockRecorder struct { - mock *MockImageMounter -} - -// NewMockImageMounter creates a new mock instance. -func NewMockImageMounter(ctrl *gomock.Controller) *MockImageMounter { - mock := &MockImageMounter{ctrl: ctrl} - mock.recorder = &MockImageMounterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockImageMounter) EXPECT() *MockImageMounterMockRecorder { - return m.recorder -} - -// MountImage mocks base method. -func (m *MockImageMounter) MountImage(ctx context.Context, imageName string, cfg *v1beta1.ModuleConfig) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "MountImage", ctx, imageName, cfg) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// MountImage indicates an expected call of MountImage. -func (mr *MockImageMounterMockRecorder) MountImage(ctx, imageName, cfg any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MountImage", reflect.TypeOf((*MockImageMounter)(nil).MountImage), ctx, imageName, cfg) -} - -// MockociImageMounterHelperAPI is a mock of ociImageMounterHelperAPI interface. -type MockociImageMounterHelperAPI struct { - ctrl *gomock.Controller - recorder *MockociImageMounterHelperAPIMockRecorder -} - -// MockociImageMounterHelperAPIMockRecorder is the mock recorder for MockociImageMounterHelperAPI. -type MockociImageMounterHelperAPIMockRecorder struct { - mock *MockociImageMounterHelperAPI -} - -// NewMockociImageMounterHelperAPI creates a new mock instance. -func NewMockociImageMounterHelperAPI(ctrl *gomock.Controller) *MockociImageMounterHelperAPI { - mock := &MockociImageMounterHelperAPI{ctrl: ctrl} - mock.recorder = &MockociImageMounterHelperAPIMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockociImageMounterHelperAPI) EXPECT() *MockociImageMounterHelperAPIMockRecorder { - return m.recorder -} - -// mountOCIImage mocks base method. -func (m *MockociImageMounterHelperAPI) mountOCIImage(image v1.Image, dstDirFS string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "mountOCIImage", image, dstDirFS) - ret0, _ := ret[0].(error) - return ret0 -} - -// mountOCIImage indicates an expected call of mountOCIImage. -func (mr *MockociImageMounterHelperAPIMockRecorder) mountOCIImage(image, dstDirFS any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mountOCIImage", reflect.TypeOf((*MockociImageMounterHelperAPI)(nil).mountOCIImage), image, dstDirFS) -} diff --git a/internal/worker/mock_remoteimagemounter.go b/internal/worker/mock_remoteimagemounter.go deleted file mode 100644 index d1ab06f49..000000000 --- a/internal/worker/mock_remoteimagemounter.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: remoteimagemounter.go -// -// Generated by this command: -// -// mockgen -source=remoteimagemounter.go -package=worker -destination=mock_remoteimagemounter.go remoteImageMounterHelperAPI -// -// Package worker is a generated GoMock package. -package worker - -import ( - context "context" - reflect "reflect" - - v1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1" - gomock "go.uber.org/mock/gomock" -) - -// MockremoteImageMounterHelperAPI is a mock of remoteImageMounterHelperAPI interface. -type MockremoteImageMounterHelperAPI struct { - ctrl *gomock.Controller - recorder *MockremoteImageMounterHelperAPIMockRecorder -} - -// MockremoteImageMounterHelperAPIMockRecorder is the mock recorder for MockremoteImageMounterHelperAPI. -type MockremoteImageMounterHelperAPIMockRecorder struct { - mock *MockremoteImageMounterHelperAPI -} - -// NewMockremoteImageMounterHelperAPI creates a new mock instance. -func NewMockremoteImageMounterHelperAPI(ctrl *gomock.Controller) *MockremoteImageMounterHelperAPI { - mock := &MockremoteImageMounterHelperAPI{ctrl: ctrl} - mock.recorder = &MockremoteImageMounterHelperAPIMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockremoteImageMounterHelperAPI) EXPECT() *MockremoteImageMounterHelperAPIMockRecorder { - return m.recorder -} - -// mountImage mocks base method. -func (m *MockremoteImageMounterHelperAPI) mountImage(ctx context.Context, imageName string, cfg *v1beta1.ModuleConfig) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "mountImage", ctx, imageName, cfg) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// mountImage indicates an expected call of mountImage. -func (mr *MockremoteImageMounterHelperAPIMockRecorder) mountImage(ctx, imageName, cfg any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "mountImage", reflect.TypeOf((*MockremoteImageMounterHelperAPI)(nil).mountImage), ctx, imageName, cfg) -} diff --git a/internal/worker/remoteimagemounter.go b/internal/worker/remoteimagemounter.go deleted file mode 100644 index a184a7892..000000000 --- a/internal/worker/remoteimagemounter.go +++ /dev/null @@ -1,175 +0,0 @@ -package worker - -import ( - "context" - "errors" - "fmt" - "os" - "path/filepath" - - "github.com/go-logr/logr" - "github.com/google/go-containerregistry/pkg/authn" - "github.com/google/go-containerregistry/pkg/crane" - kmmv1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1" - "github.com/rh-ecosystem-edge/kernel-module-management/internal/utils" -) - -type remoteImageMounter struct { - logger logr.Logger - res MirrorResolver - helper remoteImageMounterHelperAPI -} - -func NewRemoteImageMounter(baseDir string, res MirrorResolver, keyChain authn.Keychain, logger logr.Logger) ImageMounter { - helper := newRemoteImageMounterHelper(baseDir, keyChain, logger) - return &remoteImageMounter{ - logger: logger, - res: res, - helper: helper, - } -} - -func (rim *remoteImageMounter) MountImage(ctx context.Context, imageName string, cfg *kmmv1beta1.ModuleConfig) (string, error) { - imageNames, err := rim.res.GetAllReferences(imageName) - if err != nil { - return "", fmt.Errorf("could not resolve all mirrored names for %q: %v", imageName, err) - } - - for _, in := range imageNames { - logger := rim.logger.WithValues("image name", in) - logger.Info("Pulling and mounting image") - - fsDir, err := rim.helper.mountImage(ctx, in, cfg) - if err != nil { - logger.Error(err, "Could not pull and mount image") - continue - } - - logger.Info("Image pulled and mounted successfully", "dir", fsDir) - return fsDir, nil - } - - return "", errors.New("all mirrors tried") -} - -//go:generate mockgen -source=remoteimagemounter.go -package=worker -destination=mock_remoteimagemounter.go remoteImageMounterHelperAPI - -type remoteImageMounterHelperAPI interface { - mountImage(ctx context.Context, imageName string, cfg *kmmv1beta1.ModuleConfig) (string, error) -} - -type remoteImageMounterHelper struct { - ociImageHelper ociImageMounterHelperAPI - baseDir string - keyChain authn.Keychain - logger logr.Logger -} - -func newRemoteImageMounterHelper(baseDir string, keyChain authn.Keychain, logger logr.Logger) remoteImageMounterHelperAPI { - ociImageHelper := newOCIImageMounterHelper(logger) - return &remoteImageMounterHelper{ - ociImageHelper: ociImageHelper, - baseDir: baseDir, - keyChain: keyChain, - logger: logger, - } -} - -func (rimh *remoteImageMounterHelper) mountImage(ctx context.Context, imageName string, cfg *kmmv1beta1.ModuleConfig) (string, error) { - logger := rimh.logger.V(1).WithValues("image name", imageName) - - opts := []crane.Option{ - crane.WithContext(ctx), - crane.WithAuthFromKeychain(rimh.keyChain), - } - - if cfg.InsecurePull { - logger.Info(utils.WarnString("Pulling without TLS")) - opts = append(opts, crane.Insecure) - } - - logger.V(1).Info("Getting digest") - - remoteDigest, err := crane.Digest(imageName, opts...) - if err != nil { - return "", fmt.Errorf("could not get the digest for %s: %v", imageName, err) - } - - dstDir := filepath.Join(rimh.baseDir, imageName) - digestPath := filepath.Join(dstDir, "digest") - - dstDirFS := filepath.Join(dstDir, "fs") - cleanup := false - - logger.Info("Reading digest file", "path", digestPath) - - b, err := os.ReadFile(digestPath) - if err != nil { - if os.IsNotExist(err) { - cleanup = true - } else { - return "", fmt.Errorf("could not open the digest file %s: %v", digestPath, err) - } - } else { - logger.V(1).Info( - "Comparing digests", - "local file", - string(b), - "remote image", - remoteDigest, - ) - - if string(b) == remoteDigest { - logger.Info("Local file and remote digest are identical; skipping pull") - return dstDirFS, nil - } else { - logger.Info("Local file and remote digest differ; pulling image") - cleanup = true - } - } - - if cleanup { - logger.Info("Cleaning up image directory", "path", dstDir) - - if err = os.RemoveAll(dstDir); err != nil { - return "", fmt.Errorf("could not cleanup %s: %v", dstDir, err) - } - } - - if err = os.MkdirAll(dstDirFS, os.ModeDir|0755); err != nil { - return "", fmt.Errorf("could not create the filesystem directory %s: %v", dstDirFS, err) - } - - logger.V(1).Info("Pulling image") - - img, err := crane.Pull(imageName, opts...) - if err != nil { - return "", fmt.Errorf("could not pull %s: %v", imageName, err) - } - - err = rimh.ociImageHelper.mountOCIImage(img, dstDirFS) - if err != nil { - return "", fmt.Errorf("failed mounting oci image: %v", err) - } - - if err = ctx.Err(); err != nil { - return "", fmt.Errorf("not writing digest file: %v", err) - } - - logger.V(1).Info("Image written to the filesystem") - - digest, err := img.Digest() - if err != nil { - return "", fmt.Errorf("could not get the digest of the pulled image: %v", err) - } - - digestStr := digest.String() - - logger.V(1).Info("Writing digest", "digest", digestStr) - - if err = os.WriteFile(digestPath, []byte(digestStr), 0644); err != nil { - return "", fmt.Errorf("could not write the digest file at %s: %v", digestPath, err) - } - - return dstDirFS, nil -} diff --git a/internal/worker/remoteimagemounter_test.go b/internal/worker/remoteimagemounter_test.go deleted file mode 100644 index 9a14e7887..000000000 --- a/internal/worker/remoteimagemounter_test.go +++ /dev/null @@ -1,228 +0,0 @@ -package worker - -import ( - "context" - "encoding/base64" - "fmt" - "log" - "net/http" - "net/http/httptest" - "net/url" - "os" - "path/filepath" - - "github.com/google/go-containerregistry/pkg/authn" - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/registry" - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/empty" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - kmmv1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1" - "go.uber.org/mock/gomock" - "k8s.io/utils/ptr" -) - -const ( - username = "username" - password = "password" -) - -type fakeKeyChainAndAuthenticator struct { - token string -} - -func (f *fakeKeyChainAndAuthenticator) Resolve(_ authn.Resource) (authn.Authenticator, error) { - return f, nil -} - -func (f *fakeKeyChainAndAuthenticator) Authorization() (*authn.AuthConfig, error) { - return &authn.AuthConfig{Auth: f.token}, nil -} - -var _ = Describe("imageMounter_mountImage", func() { - var ( - oimh *MockociImageMounterHelperAPI - expectedToken *string - remoteImageName string - srcImg v1.Image - srcDigest v1.Hash - server *httptest.Server - serverURL *url.URL - ) - - const imagePathAndTag = "/test/archive:tag" - - modConfig := &kmmv1beta1.ModuleConfig{ - InsecurePull: true, - } - - BeforeEach(func() { - ctrl := gomock.NewController(GinkgoT()) - oimh = NewMockociImageMounterHelperAPI(ctrl) - var err error - - srcImg, err = crane.Append(empty.Image, "testdata/archive.tar") - Expect(err).NotTo(HaveOccurred()) - - srcDigest, err = srcImg.Digest() - Expect(err).NotTo(HaveOccurred()) - - ginkgoLogger := log.New(GinkgoWriter, "registry | ", log.LstdFlags) - - mw := func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if expectedToken != nil { - user, pass, ok := r.BasicAuth() - if !ok { - w.WriteHeader(http.StatusUnauthorized) - return - } - - if user != username || pass != password { - http.Error(w, fmt.Sprintf("Unexpected credentials: %s %s", user, pass), http.StatusForbidden) - } - } - - next.ServeHTTP(w, r) - }) - } - - handler := mw( - registry.New(registry.Logger(ginkgoLogger)), - ) - - server = httptest.NewServer(handler) - - GinkgoWriter.Println("Listening on " + server.URL) - - serverURL, err = url.Parse(server.URL) - Expect(err).NotTo(HaveOccurred()) - - remoteImageName = serverURL.Host + imagePathAndTag - - Expect( - crane.Push(srcImg, remoteImageName, crane.Insecure), - ).NotTo( - HaveOccurred(), - ) - }) - - AfterEach(func() { - server.Close() - expectedToken = nil - }) - - DescribeTable( - "should work as expected", - func(token string) { - tmpDir := GinkgoT().TempDir() - - keyChain := authn.NewMultiKeychain() - - if token != "" { - expectedToken = ptr.To( - base64.StdEncoding.EncodeToString([]byte(username + ":" + password)), - ) - - keyChain = &fakeKeyChainAndAuthenticator{token: *expectedToken} - } - - rimh := &remoteImageMounterHelper{ - ociImageHelper: oimh, - baseDir: tmpDir, - keyChain: keyChain, - logger: GinkgoLogr, - } - oimh.EXPECT().mountOCIImage(gomock.Any(), gomock.Any()).Return(nil) - - res, err := rimh.mountImage(context.Background(), remoteImageName, modConfig) - Expect(err).NotTo(HaveOccurred()) - - imgRoot := filepath.Join(tmpDir, serverURL.Host, "test", "archive:tag", "fs") - Expect(res).To(Equal(imgRoot)) - - Expect(imgRoot).To(BeADirectory()) - digestFilePath := filepath.Join(tmpDir, serverURL.Host, "test", "archive:tag", "digest") - Expect(os.ReadFile(digestFilePath)).To(Equal([]byte(srcDigest.String()))) - }, - Entry("without authentication", ""), - Entry("with authentication", ""), - ) - - It("should not pull if the digest file exist an has the expected value", func() { - tmpDir := GinkgoT().TempDir() - - dstDir := filepath.Join(tmpDir, serverURL.Host, "test", "archive:tag") - - Expect( - os.MkdirAll(dstDir, os.ModeDir|0755), - ).NotTo( - HaveOccurred(), - ) - - Expect( - os.WriteFile(filepath.Join(dstDir, "digest"), []byte(srcDigest.String()), 0700), - ).NotTo( - HaveOccurred(), - ) - - rimh := newRemoteImageMounterHelper(tmpDir, authn.NewMultiKeychain(), GinkgoLogr) - - res, err := rimh.mountImage(context.Background(), remoteImageName, modConfig) - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(Equal(filepath.Join(dstDir, "fs"))) - }) -}) - -var _ = Describe("imageMounter_MountImage", func() { - var ( - helperMock *MockremoteImageMounterHelperAPI - rim *remoteImageMounter - resMock *MockMirrorResolver - ) - - BeforeEach(func() { - ctrl := gomock.NewController(GinkgoT()) - helperMock = NewMockremoteImageMounterHelperAPI(ctrl) - resMock = NewMockMirrorResolver(ctrl) - rim = &remoteImageMounter{ - helper: helperMock, - logger: GinkgoLogr, - res: resMock, - } - - }) - - ctx := context.Background() - cfg := &kmmv1beta1.ModuleConfig{} - - It("GetAllReferences failed", func() { - resMock.EXPECT().GetAllReferences("imageName").Return(nil, fmt.Errorf("some error")) - - fdDir, err := rim.MountImage(ctx, "imageName", cfg) - - Expect(err).ToNot(BeNil()) - Expect(fdDir).To(BeEmpty()) - }) - - It("mirrowed image found, pulled and mounted", func() { - resMock.EXPECT().GetAllReferences("imageName").Return([]string{"mirroredImage"}, nil) - helperMock.EXPECT().mountImage(ctx, "mirroredImage", cfg).Return("mountDir", nil) - - fdDir, err := rim.MountImage(ctx, "imageName", cfg) - - Expect(err).To(BeNil()) - Expect(fdDir).To(Equal("mountDir")) - }) - - It("mirrowed image found, but not pulled and mounted", func() { - resMock.EXPECT().GetAllReferences("imageName").Return([]string{"mirroredImage"}, nil) - helperMock.EXPECT().mountImage(ctx, "mirroredImage", cfg).Return("", fmt.Errorf("some error")) - - fdDir, err := rim.MountImage(ctx, "imageName", cfg) - - Expect(err).ToNot(BeNil()) - Expect(fdDir).To(BeEmpty()) - }) -}) diff --git a/internal/worker/tarimagemounter.go b/internal/worker/tarimagemounter.go deleted file mode 100644 index 4ad89f027..000000000 --- a/internal/worker/tarimagemounter.go +++ /dev/null @@ -1,52 +0,0 @@ -package worker - -import ( - "context" - "fmt" - "os" - "path/filepath" - - "github.com/go-logr/logr" - "github.com/google/go-containerregistry/pkg/v1/tarball" - kmmv1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1" -) - -type tarImageMounter struct { - ociImageHelper ociImageMounterHelperAPI - logger logr.Logger - baseDir string -} - -func NewTarImageMounter(baseDir string, logger logr.Logger) ImageMounter { - ociImageHelper := newOCIImageMounterHelper(logger) - return &tarImageMounter{ - ociImageHelper: ociImageHelper, - logger: logger, - baseDir: baseDir, - } -} - -func (tim *tarImageMounter) MountImage(ctx context.Context, imagePath string, cfg *kmmv1beta1.ModuleConfig) (string, error) { - dstDir := filepath.Join(tim.baseDir, imagePath) - - dstDirFS := filepath.Join(dstDir, "fs") - if err := os.MkdirAll(dstDirFS, os.ModeDir|0755); err != nil { - return "", fmt.Errorf("could not create the filesystem directory %s: %v", dstDirFS, err) - } - - tim.logger.V(1).Info("Converting tarball into OCI image") - - img, err := tarball.ImageFromPath(imagePath, nil) - if err != nil { - return "", fmt.Errorf("could not create image from path %s: %v", imagePath, err) - } - - err = tim.ociImageHelper.mountOCIImage(img, dstDirFS) - if err != nil { - return "", fmt.Errorf("failed mounting oci image: %v", err) - } - - tim.logger.Info("Image written to the filesystem") - - return dstDirFS, nil -} diff --git a/internal/worker/tarimagemounter_test.go b/internal/worker/tarimagemounter_test.go deleted file mode 100644 index 68139f0d8..000000000 --- a/internal/worker/tarimagemounter_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package worker - -import ( - "context" - "fmt" - "path/filepath" - - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/name" - "github.com/google/go-containerregistry/pkg/v1/empty" - "github.com/google/go-containerregistry/pkg/v1/tarball" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "go.uber.org/mock/gomock" -) - -var _ = Describe("TarImageMounter_MountImage", func() { - var oimh *MockociImageMounterHelperAPI - - BeforeEach(func() { - ctrl := gomock.NewController(GinkgoT()) - oimh = NewMockociImageMounterHelperAPI(ctrl) - }) - - It("good flow", func() { - tmpDir := GinkgoT().TempDir() - testImage := prepareTestTarball(tmpDir) - - tim := &tarImageMounter{ - ociImageHelper: oimh, - baseDir: tmpDir, - logger: GinkgoLogr, - } - - oimh.EXPECT().mountOCIImage(gomock.Any(), filepath.Join(tmpDir, testImage, "fs")).Return(nil) - - res, err := tim.MountImage(context.Background(), testImage, nil) - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(Equal(filepath.Join(tmpDir, testImage, "fs"))) - }) - - It("failed to mount OCI image", func() { - tmpDir := GinkgoT().TempDir() - testImage := prepareTestTarball(tmpDir) - - tim := &tarImageMounter{ - ociImageHelper: oimh, - baseDir: tmpDir, - logger: GinkgoLogr, - } - - oimh.EXPECT().mountOCIImage(gomock.Any(), filepath.Join(tmpDir, testImage, "fs")).Return(fmt.Errorf("some error")) - - res, err := tim.MountImage(context.Background(), testImage, nil) - Expect(err).To(HaveOccurred()) - Expect(res).To(BeEmpty()) - }) -}) - -func prepareTestTarball(tarballDir string) string { - srcImg, err := crane.Append(empty.Image, "testdata/archive.tar") - Expect(err).NotTo(HaveOccurred()) - reference, err := name.NewTag("some-tag") - Expect(err).NotTo(HaveOccurred()) - tarballFilePath := filepath.Join(tarballDir, "input-image-tarball-file") - err = tarball.WriteToFile(tarballFilePath, reference, srcImg) - Expect(err).NotTo(HaveOccurred()) - return tarballFilePath -} diff --git a/internal/worker/worker.go b/internal/worker/worker.go index 61d499e20..d17b73d9b 100644 --- a/internal/worker/worker.go +++ b/internal/worker/worker.go @@ -22,14 +22,12 @@ type Worker interface { } type worker struct { - im ImageMounter logger logr.Logger mr ModprobeRunner } -func NewWorker(im ImageMounter, mr ModprobeRunner, logger logr.Logger) Worker { +func NewWorker(mr ModprobeRunner, logger logr.Logger) Worker { return &worker{ - im: im, logger: logger, mr: mr, } diff --git a/internal/worker/worker_test.go b/internal/worker/worker_test.go index 1488b21bc..1b39e816e 100644 --- a/internal/worker/worker_test.go +++ b/internal/worker/worker_test.go @@ -14,7 +14,6 @@ import ( var _ = Describe("worker_LoadKmod", func() { var ( - im *MockImageMounter mr *MockModprobeRunner w Worker imageDir string @@ -23,9 +22,8 @@ var _ = Describe("worker_LoadKmod", func() { BeforeEach(func() { ctrl := gomock.NewController(GinkgoT()) - im = NewMockImageMounter(ctrl) mr = NewMockModprobeRunner(ctrl) - w = NewWorker(im, mr, GinkgoLogr) + w = NewWorker(mr, GinkgoLogr) var err error imageDir, err = os.MkdirTemp("", "imageDir") @@ -187,7 +185,7 @@ var _ = Describe("worker_LoadKmod", func() { }) var _ = Describe("worker_SetFirmwareClassPath", func() { - w := NewWorker(nil, nil, GinkgoLogr) + w := NewWorker(nil, GinkgoLogr) AfterEach(func() { firmwareClassPathLocation = FirmwareClassPathLocation @@ -235,7 +233,6 @@ var _ = Describe("worker_SetFirmwareClassPath", func() { var _ = Describe("worker_UnloadKmod", func() { var ( - im *MockImageMounter mr *MockModprobeRunner w Worker imageDir string @@ -244,9 +241,8 @@ var _ = Describe("worker_UnloadKmod", func() { BeforeEach(func() { ctrl := gomock.NewController(GinkgoT()) - im = NewMockImageMounter(ctrl) mr = NewMockModprobeRunner(ctrl) - w = NewWorker(im, mr, GinkgoLogr) + w = NewWorker(mr, GinkgoLogr) var err error imageDir, err = os.MkdirTemp("", "imageDir") Expect(err).Should(BeNil())