diff --git a/.cirrus.yml b/.cirrus.yml index ec2869ddd6..22f41d51c8 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -820,8 +820,6 @@ podman_machine_mac_task: # TODO: Timeout bumped b/c initial image download (~5min) and VM # resize (~2min) causes test-timeout (90s default). Should # tests deal with this internally? - smoke_test_script: - - MACHINE_TEST_TIMEOUT=500 make localmachine FOCUS_FILE="basic_test.go" test_script: - make localmachine # This host is/was shared with potentially many other CI tasks. diff --git a/contrib/cirrus/mac_setup.sh b/contrib/cirrus/mac_setup.sh index 1fd9042515..a2aad68438 100755 --- a/contrib/cirrus/mac_setup.sh +++ b/contrib/cirrus/mac_setup.sh @@ -32,6 +32,11 @@ echo "TMPDIR=/private/tmp/ci" >> $CIRRUS_ENV # Removed completely during cleanup. mkdir -p /private/tmp/ci +# Add policy.json +mkdir -p $HOME/ci/.config/containers +cp pkg/machine/ocipull/policy.json /$HOME/ci/.config/containers/ + + # Some test operations & checks require a git "identity" # N/B: $HOME in this context does not include the /ci part automatically # (see above) but it will when the next Cirrus-CI "_script" section diff --git a/contrib/cirrus/win-podman-machine-test.ps1 b/contrib/cirrus/win-podman-machine-test.ps1 index 5833d5bcc6..4d8ff59667 100644 --- a/contrib/cirrus/win-podman-machine-test.ps1 +++ b/contrib/cirrus/win-podman-machine-test.ps1 @@ -29,5 +29,9 @@ Set-Location "$ENV:CIRRUS_WORKING_DIR\repo" # Tests hard-code this location for podman-remote binary, make sure it actually runs. Run-Command ".\bin\windows\podman.exe --version" +# Add policy.json to filesystem for podman machine pulls +New-Item -ItemType "directory" -Path "$env:AppData\containers" +Copy-Item -Path pkg\machine\ocipull\policy.json -Destination "$env:AppData\containers" + Write-Host "`nRunning podman-machine e2e tests" Run-Command ".\winmake localmachine" diff --git a/pkg/machine/e2e/machine_pull_test.go b/pkg/machine/e2e/machine_pull_test.go new file mode 100644 index 0000000000..c441f91926 --- /dev/null +++ b/pkg/machine/e2e/machine_pull_test.go @@ -0,0 +1,43 @@ +package e2e_test + +import ( + "context" + "fmt" + "path/filepath" + "runtime" + "strings" + + "github.com/containers/podman/v5/pkg/machine/compression" + "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/ocipull" +) + +func pullOCITestDisk(finalDir string, vmType define.VMType) error { + imageCacheDir, err := define.NewMachineFile(finalDir, nil) + if err != nil { + return err + } + unusedFinalPath, err := imageCacheDir.AppendToNewVMFile(fmt.Sprintf("machinetest-%s", runtime.GOOS), nil) + if err != nil { + return err + } + dirs := define.MachineDirs{ImageCacheDir: imageCacheDir} + ociArtPull, err := ocipull.NewOCIArtifactPull(context.Background(), &dirs, "e2emachine", vmType, unusedFinalPath) + if err != nil { + return err + } + err = ociArtPull.GetNoCompress() + if err != nil { + return err + } + fp, originalName := ociArtPull.OriginalFileName() + // Rename the download to something we recognize + compressionExt := filepath.Ext(fp) + fqImageName = filepath.Join(tmpDir, strings.TrimSuffix(originalName, compressionExt)) + suiteImageName = filepath.Base(fqImageName) + compressedImage, err := define.NewMachineFile(fp, nil) + if err != nil { + return err + } + return compression.Decompress(compressedImage, fqImageName) +} diff --git a/pkg/machine/e2e/machine_test.go b/pkg/machine/e2e/machine_test.go index 249f0250e0..255b2b7edf 100644 --- a/pkg/machine/e2e/machine_test.go +++ b/pkg/machine/e2e/machine_test.go @@ -1,26 +1,20 @@ package e2e_test import ( + "errors" "fmt" "io" - url2 "net/url" + "io/fs" "os" - "path" "path/filepath" "runtime" - "strings" "testing" - "time" - "github.com/containers/podman/v5/pkg/machine/wsl" - - "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/compression" "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/containers/podman/v5/utils" - crcOs "github.com/crc-org/crc/v2/pkg/os" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -54,70 +48,21 @@ func TestMachine(t *testing.T) { var testProvider vmconfigs.VMProvider var _ = BeforeSuite(func() { - var err error + var ( + err error + pullError error + ) testProvider, err = provider.Get() if err != nil { Fail("unable to create testProvider") } - - downloadLocation := os.Getenv("MACHINE_IMAGE") - if downloadLocation == "" { - // TODO so beautifully gross ... ideally we can spend some time - // here making life easier on the next person - switch testProvider.VMType() { - case define.WSLVirt: - dl, _, _, _, err := wsl.GetFedoraDownloadForWSL() - if err != nil { - Fail("unable to determine WSL download") - } - downloadLocation = dl.String() - default: - downloadLocation, err = GetDownload(testProvider.VMType()) - if err != nil { - Fail(fmt.Sprintf("unable to derive download disk from fedora coreos: %q", err)) - } - } + if testProvider.VMType() == define.WSLVirt { + pullError = pullWSLDisk() + } else { + pullError = pullOCITestDisk(tmpDir, testProvider.VMType()) } - - if downloadLocation == "" { - Fail("machine tests require a file reference to a disk image right now") - } - - var compressionExtension string - switch testProvider.VMType() { - case define.AppleHvVirt: - compressionExtension = ".gz" - case define.HyperVVirt: - compressionExtension = ".zip" - default: - compressionExtension = ".xz" - } - - suiteImageName = strings.TrimSuffix(path.Base(downloadLocation), compressionExtension) - fqImageName = filepath.Join(tmpDir, suiteImageName) - if _, err := os.Stat(fqImageName); err != nil { - if os.IsNotExist(err) { - getMe, err := url2.Parse(downloadLocation) - if err != nil { - Fail(fmt.Sprintf("unable to create url for download: %q", err)) - } - now := time.Now() - if err := machine.DownloadVMImage(getMe, suiteImageName, fqImageName+compressionExtension); err != nil { - Fail(fmt.Sprintf("unable to download machine image: %q", err)) - } - GinkgoWriter.Println("Download took: ", time.Since(now).String()) - diskImage, err := define.NewMachineFile(fqImageName+compressionExtension, nil) - if err != nil { - Fail(fmt.Sprintf("unable to create vmfile %q: %v", fqImageName+compressionExtension, err)) - } - compressionStart := time.Now() - if err := compression.Decompress(diskImage, fqImageName); err != nil { - Fail(fmt.Sprintf("unable to decompress image file: %q", err)) - } - GinkgoWriter.Println("compression took: ", time.Since(compressionStart)) - } else { - Fail(fmt.Sprintf("unable to check for cache image: %q", err)) - } + if pullError != nil { + Fail(fmt.Sprintf("failed to pull wsl disk: %q", pullError)) } }) @@ -176,8 +121,9 @@ func setup() (string, *machineTestBuilder) { Fail(fmt.Sprintf("failed to create file %s: %q", mb.imagePath, err)) } defer func() { - if err := dest.Close(); err != nil { - Fail(fmt.Sprintf("failed to close destination file %q: %q", dest.Name(), err)) + closeErr := dest.Close() + if err != nil || !errors.Is(closeErr, fs.ErrClosed) { + fmt.Printf("failed to close destination file %q: %q\n", dest.Name(), err) } }() fmt.Printf("--> copying %q to %q/n", src.Name(), dest.Name()) @@ -186,7 +132,7 @@ func setup() (string, *machineTestBuilder) { Fail(fmt.Sprintf("failed to copy %ss to %s: %q", fqImageName, mb.imagePath, err)) } } else { - if _, err := crcOs.CopySparse(dest, src); err != nil { + if err := copySparse(dest, src); err != nil { Fail(fmt.Sprintf("failed to copy %q to %q: %q", src.Name(), dest.Name(), err)) } } @@ -214,3 +160,27 @@ func teardown(origHomeDir string, testDir string, mb *machineTestBuilder) { } } } + +// copySparseFile is a helper method for tests only. copies a file sparsely +// between two string inputs +func copySparseFile(src, dst string) error { //nolint:unused + dstWriter, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR, 0600) + if err != nil { + return err + } + dstWriter.Close() + fSrc, err := os.Open(src) + if err != nil { + return err + } + defer fSrc.Close() + return copySparse(dstWriter, fSrc) +} + +// copySparse is a helper method for tests only; caller is responsible for closures +func copySparse(dst compression.WriteSeekCloser, src io.Reader) error { + spWriter := compression.NewSparseWriter(dst) + defer spWriter.Close() + _, err := io.Copy(spWriter, src) + return err +} diff --git a/pkg/machine/e2e/machine_wsl_test.go b/pkg/machine/e2e/machine_wsl_test.go new file mode 100644 index 0000000000..161220086b --- /dev/null +++ b/pkg/machine/e2e/machine_wsl_test.go @@ -0,0 +1,55 @@ +package e2e_test + +import ( + "errors" + "fmt" + url2 "net/url" + "os" + "path" + "path/filepath" + "strings" + "time" + + "github.com/containers/podman/v5/pkg/machine" + "github.com/containers/podman/v5/pkg/machine/compression" + "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/wsl" + . "github.com/onsi/ginkgo/v2" +) + +func pullWSLDisk() error { + downloadLocation := os.Getenv("MACHINE_IMAGE") + if downloadLocation == "" { + dl, _, _, _, err := wsl.GetFedoraDownloadForWSL() + if err != nil { + return errors.New("unable to determine WSL download") + } + downloadLocation = dl.String() + } + + if downloadLocation == "" { + return errors.New("machine tests require a file reference to a disk image right now") + } + compressionExtension := ".xz" + suiteImageName = strings.TrimSuffix(path.Base(downloadLocation), compressionExtension) + fqImageName = filepath.Join(tmpDir, suiteImageName) + getMe, err := url2.Parse(downloadLocation) + if err != nil { + return fmt.Errorf("unable to create url for download: %q", err) + } + now := time.Now() + if err := machine.DownloadVMImage(getMe, suiteImageName, fqImageName+compressionExtension); err != nil { + return fmt.Errorf("unable to download machine image: %q", err) + } + GinkgoWriter.Println("Download took: ", time.Since(now).String()) + diskImage, err := define.NewMachineFile(fqImageName+compressionExtension, nil) + if err != nil { + return fmt.Errorf("unable to create vmfile %q: %v", fqImageName+compressionExtension, err) + } + compressionStart := time.Now() + if err := compression.Decompress(diskImage, fqImageName); err != nil { + return fmt.Errorf("unable to decompress image file: %q", err) + } + GinkgoWriter.Println("compression took: ", time.Since(compressionStart)) + return nil +} diff --git a/pkg/machine/gvproxy_unix.go b/pkg/machine/gvproxy_unix.go index 0e603ca29f..20869d583e 100644 --- a/pkg/machine/gvproxy_unix.go +++ b/pkg/machine/gvproxy_unix.go @@ -10,6 +10,7 @@ import ( psutil "github.com/shirou/gopsutil/v3/process" "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" ) const ( @@ -25,6 +26,11 @@ func backoffForProcess(p *psutil.Process) error { for i := 0; i < loops; i++ { running, err := p.IsRunning() if err != nil { + // It is possible that while in our loop, the PID vaporize triggering + // an input/output error (#21845) + if errors.Is(err, unix.EIO) { + return nil + } return fmt.Errorf("checking if process running: %w", err) } if !running { diff --git a/pkg/machine/ignition/ignition.go b/pkg/machine/ignition/ignition.go index 432d0bb8ee..03dcefaf97 100644 --- a/pkg/machine/ignition/ignition.go +++ b/pkg/machine/ignition/ignition.go @@ -171,13 +171,45 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error { ignStorage.Links = append(ignStorage.Links, tzLink) } - // Enables automatic login on the console; - // there's no security concerns here, and this makes debugging easier. - // xref https://docs.fedoraproject.org/en-US/fedora-coreos/tutorial-autologin/ - var autologinDropin = `[Service] -ExecStart= -ExecStart=-/usr/sbin/agetty --autologin root --noclear %I $TERM -` + // This service gets environment variables that are provided + // through qemu fw_cfg and then sets them into systemd/system.conf.d, + // profile.d and environment.d files + // + // Currently, it is used for propagating + // proxy settings e.g. HTTP_PROXY and others, on a start avoiding + // a need of re-creating/re-initiating a VM + + envset := parser.NewUnitFile() + envset.Add("Unit", "Description", "Environment setter from QEMU FW_CFG") + + envset.Add("Service", "Type", "oneshot") + envset.Add("Service", "RemainAfterExit", "yes") + envset.Add("Service", "Environment", "FWCFGRAW=/sys/firmware/qemu_fw_cfg/by_name/opt/com.coreos/environment/raw") + envset.Add("Service", "Environment", "SYSTEMD_CONF=/etc/systemd/system.conf.d/default-env.conf") + envset.Add("Service", "Environment", "ENVD_CONF=/etc/environment.d/default-env.conf") + envset.Add("Service", "Environment", "PROFILE_CONF=/etc/profile.d/default-env.sh") + envset.Add("Service", "ExecStart", `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} &&\ + echo "[Manager]\n#Got from QEMU FW_CFG\nDefaultEnvironment=$(/usr/bin/base64 -d ${FWCFGRAW} | sed -e "s+|+ +g")\n" > ${SYSTEMD_CONF} ||\ + echo "[Manager]\n#Got nothing from QEMU FW_CFG\n#DefaultEnvironment=\n" > ${SYSTEMD_CONF}'`) + envset.Add("Service", "ExecStart", `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\ + echo "#Got from QEMU FW_CFG"> ${ENVD_CONF};\ + IFS="|";\ + for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\ + echo "$iprxy" >> ${ENVD_CONF}; done ) || \ + echo "#Got nothing from QEMU FW_CFG"> ${ENVD_CONF}'`) + envset.Add("Service", "ExecStart", `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\ + echo "#Got from QEMU FW_CFG"> ${PROFILE_CONF};\ + IFS="|";\ + for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\ + echo "export $iprxy" >> ${PROFILE_CONF}; done ) || \ + echo "#Got nothing from QEMU FW_CFG"> ${PROFILE_CONF}'`) + envset.Add("Service", "ExecStartPost", "/usr/bin/systemctl daemon-reload") + + envset.Add("Install", "WantedBy", "sysinit.target") + envsetFile, err := envset.ToString() + if err != nil { + return err + } ignSystemd := Systemd{ Units: []Unit{ @@ -186,54 +218,24 @@ ExecStart=-/usr/sbin/agetty --autologin root --noclear %I $TERM Name: "podman.socket", }, { - Enabled: BoolToPtr(false), - Name: "docker.service", - Mask: BoolToPtr(true), - }, - { - Enabled: BoolToPtr(false), - Name: "docker.socket", - Mask: BoolToPtr(true), - }, - { + // TODO Need to understand if this could play a role in machine + // updates given a certain configuration // Disable auto-updating of fcos images // https://github.com/containers/podman/issues/20122 Enabled: BoolToPtr(false), Name: "zincati.service", }, - { - Name: "serial-getty@.service", - Dropins: []Dropin{ - { - Name: "10-autologin.conf", - Contents: &autologinDropin, - }, - }, - }, - { - Name: "getty@.service", - Dropins: []Dropin{ - { - Name: "10-autologin.conf", - Contents: &autologinDropin, - }, - }, - }, }, } - if ign.NetRecover { - contents, err := GetNetRecoveryUnitFile().ToString() - if err != nil { - return err - } - - recoveryUnit := Unit{ + // Only qemu has the qemu firmware environment setting + if ign.VMType == define.QemuVirt { + qemuUnit := Unit{ Enabled: BoolToPtr(true), - Name: "net-health-recovery.service", - Contents: &contents, + Name: "envset-fwcfg.service", + Contents: &envsetFile, } - ignSystemd.Units = append(ignSystemd.Units, recoveryUnit) + ignSystemd.Units = append(ignSystemd.Units, qemuUnit) } // Only after all checks are done @@ -272,43 +274,10 @@ func getDirs(usrName string) []Directory { dirs[i] = newDir } - // Issue #11489: make sure that we can inject a custom registries.conf - // file on the system level to force a single search registry. - // The remote client does not yet support prompting for short-name - // resolution, so we enforce a single search registry (i.e., docker.io) - // as a workaround. - dirs = append(dirs, Directory{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/containers/registries.conf.d", - User: GetNodeUsr("root"), - }, - DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)}, - }) - - // The directory is used by envset-fwcfg.service - // for propagating environment variables that got - // from a host - dirs = append(dirs, Directory{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/systemd/system.conf.d", - User: GetNodeUsr("root"), - }, - DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)}, - }, Directory{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/environment.d", - User: GetNodeUsr("root"), - }, - DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)}, - }) - return dirs } -func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, netRecover bool) []File { +func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, _ bool) []File { files := make([]File, 0) lingerExample := parser.NewUnitFile() @@ -325,15 +294,12 @@ func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, netRe netns="bridge" pids_limit=0 ` + // TODO I think this can be removed but leaving breadcrumb until certain. // Set deprecated machine_enabled until podman package on fcos is // current enough to no longer require it - rootContainers := `[engine] -machine_enabled=true -` - - delegateConf := `[Service] -Delegate=memory pids cpu io -` + // rootContainers := `[engine] + // machine_enabled=true + // ` // Prevent subUID from clashing with actual UID subUID := 100000 subUIDs := 1000000 @@ -374,6 +340,7 @@ Delegate=memory pids cpu io Mode: IntToPtr(0744), }, }) + // Set up /etc/subuid and /etc/subgid for _, sub := range []string{"/etc/subuid", "/etc/subgid"} { files = append(files, File{ @@ -393,50 +360,8 @@ Delegate=memory pids cpu io }) } - // Set delegate.conf so cpu,io subsystem is delegated to non-root users as well for cgroupv2 - // by default - files = append(files, File{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/systemd/system/user@.service.d/delegate.conf", - User: GetNodeUsr("root"), - }, - FileEmbedded1: FileEmbedded1{ - Append: nil, - Contents: Resource{ - Source: EncodeDataURLPtr(delegateConf), - }, - Mode: IntToPtr(0644), - }, - }) - - // Add a file into linger - files = append(files, File{ - Node: Node{ - Group: GetNodeGrp(usrName), - Path: "/var/lib/systemd/linger/core", - User: GetNodeUsr(usrName), - }, - FileEmbedded1: FileEmbedded1{Mode: IntToPtr(0644)}, - }) - - // Set deprecated machine_enabled to true to indicate we're in a VM - files = append(files, File{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/containers/containers.conf", - User: GetNodeUsr("root"), - }, - FileEmbedded1: FileEmbedded1{ - Append: nil, - Contents: Resource{ - Source: EncodeDataURLPtr(rootContainers), - }, - Mode: IntToPtr(0644), - }, - }) - - // Set machine marker file to indicate podman is in a qemu based machine + // Set machine marker file to indicate podman what vmtype we are + // operating under files = append(files, File{ Node: Node{ Group: GetNodeGrp("root"), @@ -452,42 +377,6 @@ Delegate=memory pids cpu io }, }) - // Increase the number of inotify instances. - files = append(files, File{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/sysctl.d/10-inotify-instances.conf", - User: GetNodeUsr("root"), - }, - FileEmbedded1: FileEmbedded1{ - Append: nil, - Contents: Resource{ - Source: EncodeDataURLPtr("fs.inotify.max_user_instances=524288\n"), - }, - Mode: IntToPtr(0644), - }, - }) - - // Issue #11489: make sure that we can inject a custom registries.conf - // file on the system level to force a single search registry. - // The remote client does not yet support prompting for short-name - // resolution, so we enforce a single search registry (i.e., docker.io) - // as a workaround. - files = append(files, File{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/containers/registries.conf.d/999-podman-machine.conf", - User: GetNodeUsr("root"), - }, - FileEmbedded1: FileEmbedded1{ - Append: nil, - Contents: Resource{ - Source: EncodeDataURLPtr("unqualified-search-registries=[\"docker.io\"]\n"), - }, - Mode: IntToPtr(0644), - }, - }) - files = append(files, File{ Node: Node{ Path: PodmanDockerTmpConfPath, @@ -502,24 +391,6 @@ Delegate=memory pids cpu io }, }) - setDockerHost := `export DOCKER_HOST="unix://$(podman info -f "{{.Host.RemoteSocket.Path}}")" -` - - files = append(files, File{ - Node: Node{ - Group: GetNodeGrp("root"), - Path: "/etc/profile.d/docker-host.sh", - User: GetNodeUsr("root"), - }, - FileEmbedded1: FileEmbedded1{ - Append: nil, - Contents: Resource{ - Source: EncodeDataURLPtr(setDockerHost), - }, - Mode: IntToPtr(0644), - }, - }) - // get certs for current user userHome, err := os.UserHomeDir() if err != nil { @@ -557,51 +428,6 @@ Delegate=memory pids cpu io files = append(files, getSSLEnvironmentFiles(sslCertFileName, sslCertDirName)...) } - files = append(files, File{ - Node: Node{ - User: GetNodeUsr("root"), - Group: GetNodeGrp("root"), - Path: "/etc/chrony.conf", - }, - FileEmbedded1: FileEmbedded1{ - Append: []Resource{{ - Source: EncodeDataURLPtr("\nconfdir /etc/chrony.d\n"), - }}, - }, - }) - - // Issue #11541: allow Chrony to update the system time when it has drifted - // far from NTP time. - files = append(files, File{ - Node: Node{ - User: GetNodeUsr("root"), - Group: GetNodeGrp("root"), - Path: "/etc/chrony.d/50-podman-makestep.conf", - }, - FileEmbedded1: FileEmbedded1{ - Contents: Resource{ - Source: EncodeDataURLPtr("makestep 1 -1\n"), - }, - }, - }) - - // Only necessary for qemu on mac - if netRecover { - files = append(files, File{ - Node: Node{ - User: GetNodeUsr("root"), - Group: GetNodeGrp("root"), - Path: "/usr/local/bin/net-health-recovery.sh", - }, - FileEmbedded1: FileEmbedded1{ - Mode: IntToPtr(0755), - Contents: Resource{ - Source: EncodeDataURLPtr(GetNetRecoveryFile()), - }, - }, - }) - } - return files } diff --git a/pkg/machine/ocipull/ociartifact.go b/pkg/machine/ocipull/ociartifact.go index 6f71a7f7a0..9307daf552 100644 --- a/pkg/machine/ocipull/ociartifact.go +++ b/pkg/machine/ocipull/ociartifact.go @@ -27,7 +27,7 @@ const ( // TODO This is temporary until we decide on a proper image name artifactRegistry = "quay.io" artifactRepo = "baude" - artifactImageName = "stage-podman-machine" + artifactImageName = "stage-podman-machine-image" artifactOriginalName = "org.opencontainers.image.title" machineOS = "linux" ) @@ -105,7 +105,22 @@ func NewOCIArtifactPull(ctx context.Context, dirs *define.MachineDirs, vmName st return &ociDisk, nil } +func (o *OCIArtifactDisk) OriginalFileName() (string, string) { + return o.cachedCompressedDiskPath.GetPath(), o.diskArtifactFileName +} + func (o *OCIArtifactDisk) Get() error { + if err := o.get(); err != nil { + return err + } + return o.decompress() +} + +func (o *OCIArtifactDisk) GetNoCompress() error { + return o.get() +} + +func (o *OCIArtifactDisk) get() error { destRef, artifactDigest, err := o.getDestArtifact() if err != nil { return err @@ -116,6 +131,7 @@ func (o *OCIArtifactDisk) Get() error { if err != nil { return err } + // check if we have the latest and greatest disk image if _, err = os.Stat(cachedImagePath.GetPath()); err != nil { if !errors.Is(err, os.ErrNotExist) { @@ -139,7 +155,7 @@ func (o *OCIArtifactDisk) Get() error { logrus.Debugf("cached image exists and is latest: %s", cachedImagePath.GetPath()) o.cachedCompressedDiskPath = cachedImagePath } - return o.decompress() + return nil } func (o *OCIArtifactDisk) getDestArtifact() (types.ImageReference, digest.Digest, error) {