feat: save container images
This commit is contained in:
		
							
								
								
									
										5
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							| @@ -101,7 +101,8 @@ jobs: | |||||||
|  |  | ||||||
|         ssh root@$IP "cloud-init status --wait" |         ssh root@$IP "cloud-init status --wait" | ||||||
|  |  | ||||||
|         ssh root@$IP "dnf install -y podman qemu-kvm-core" |         ssh root@$IP "dnf install -y podman qemu-kvm-core epel-release" | ||||||
|  |         ssh root@$IP "dnf install -y s3cmd" | ||||||
|  |  | ||||||
|         ssh root@$IP "ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-system-x86_64" |         ssh root@$IP "ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-system-x86_64" | ||||||
|  |  | ||||||
| @@ -133,6 +134,8 @@ jobs: | |||||||
|         echo 'TimeoutStopSec=1' >> test.service |         echo 'TimeoutStopSec=1' >> test.service | ||||||
|         echo 'ExecStart=/usr/local/bin/out-of-tree kernel autogen --threads=4 --max=256 --shuffle' >> test.service |         echo 'ExecStart=/usr/local/bin/out-of-tree kernel autogen --threads=4 --max=256 --shuffle' >> test.service | ||||||
|         echo 'ExecStart=/usr/local/bin/out-of-tree pew --qemu-timeout=10m --threads=4 --include-internal-errors' >> test.service |         echo 'ExecStart=/usr/local/bin/out-of-tree pew --qemu-timeout=10m --threads=4 --include-internal-errors' >> test.service | ||||||
|  |         echo 'ExecStart=/usr/local/bin/out-of-tree container save' >> test.service | ||||||
|  |         echo "ExecStart=/usr/bin/s3cmd put --acl-public *.tar.gz s3://out-of-tree/1.0.0/containers/ --host=fra1.digitaloceanspaces.com --host-bucket='%(bucket)s.fra1.digitaloceanspaces.com' --access_key=${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }} --secret_key=${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}" >> test.service | ||||||
|  |  | ||||||
|         scp test.service root@$IP:/etc/systemd/system/test.service |         scp test.service root@$IP:/etc/systemd/system/test.service | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ package cmd | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
|  | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"github.com/rs/zerolog/log" | 	"github.com/rs/zerolog/log" | ||||||
| @@ -18,6 +19,7 @@ type ContainerCmd struct { | |||||||
| 	Filter string `help:"filter by name"` | 	Filter string `help:"filter by name"` | ||||||
|  |  | ||||||
| 	List    ContainerListCmd    `cmd:"" help:"list containers"` | 	List    ContainerListCmd    `cmd:"" help:"list containers"` | ||||||
|  | 	Save    ContainerSaveCmd    `cmd:"" help:"save containers"` | ||||||
| 	Cleanup ContainerCleanupCmd `cmd:"" help:"cleanup containers"` | 	Cleanup ContainerCleanupCmd `cmd:"" help:"cleanup containers"` | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -45,6 +47,37 @@ func (cmd ContainerListCmd) Run(containerCmd *ContainerCmd) (err error) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type ContainerSaveCmd struct { | ||||||
|  | 	OutDir string `help:"directory to save containers" default:"./" type:"existingdir"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (cmd ContainerSaveCmd) Run(containerCmd *ContainerCmd) (err error) { | ||||||
|  | 	for _, name := range containerCmd.Containers() { | ||||||
|  | 		nlog := log.With().Str("name", name).Logger() | ||||||
|  |  | ||||||
|  | 		output := filepath.Join(cmd.OutDir, name+".tar") | ||||||
|  | 		nlog.Info().Msgf("saving to %v") | ||||||
|  |  | ||||||
|  | 		err = container.Save(name, output) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		compressed := output + ".gz" | ||||||
|  | 		nlog.Info().Msgf("compressing to %v", compressed) | ||||||
|  |  | ||||||
|  | 		var raw []byte | ||||||
|  | 		raw, err = exec.Command("gzip", output).CombinedOutput() | ||||||
|  | 		if err != nil { | ||||||
|  | 			nlog.Error().Err(err).Msg(string(raw)) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		nlog.Info().Msg("done") | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
| type ContainerCleanupCmd struct{} | type ContainerCleanupCmd struct{} | ||||||
|  |  | ||||||
| func (cmd ContainerCleanupCmd) Run(containerCmd *ContainerCmd) (err error) { | func (cmd ContainerCleanupCmd) Run(containerCmd *ContainerCmd) (err error) { | ||||||
|   | |||||||
| @@ -95,6 +95,26 @@ func Import(path, name string) (err error) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func Save(name, path string) (err error) { | ||||||
|  | 	exist := Container{name: name}.Exist() | ||||||
|  | 	if !exist { | ||||||
|  | 		err = errors.New("container does not exist") | ||||||
|  | 		log.Error().Err(err).Msg("") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cmd := exec.Command(Runtime, "save", name, path) | ||||||
|  | 	log.Debug().Msgf("%v", cmd) | ||||||
|  |  | ||||||
|  | 	raw, err := cmd.CombinedOutput() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error().Err(err).Msg(string(raw)) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
| type Volume struct { | type Volume struct { | ||||||
| 	Src, Dest string | 	Src, Dest string | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user