Skip to content

Commit 6f7873e

Browse files
Merge pull request #1 from WoodProgrammer/oci-export
oci-export: Implementation for OCI image export
2 parents 8f20613 + 6528e88 commit 6f7873e

File tree

7 files changed

+240
-2
lines changed

7 files changed

+240
-2
lines changed

go.mod

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
11
module firecracker-vmbuilder
22

3+
replace github.com/WoodProgrammer/firecracker-vmbuilder/src => ./src
4+
35
go 1.24.1
6+
7+
require (
8+
github.com/WoodProgrammer/firecracker-vmbuilder/src v0.0.0-00010101000000-000000000000
9+
github.com/rs/zerolog v1.33.0
10+
github.com/spf13/cobra v1.9.1
11+
)
12+
13+
require (
14+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
15+
github.com/mattn/go-colorable v0.1.13 // indirect
16+
github.com/mattn/go-isatty v0.0.19 // indirect
17+
github.com/spf13/pflag v1.0.6 // indirect
18+
golang.org/x/sys v0.12.0 // indirect
19+
gopkg.in/yaml.v2 v2.4.0 // indirect
20+
)

go.sum

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
2+
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
3+
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
4+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
5+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
6+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
7+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
8+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
9+
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
10+
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
11+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
12+
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
13+
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
14+
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
15+
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
16+
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
17+
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
18+
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
19+
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
20+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
21+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
22+
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
23+
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
24+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
25+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
26+
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
27+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
28+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

main.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,70 @@
11
package main
22

3-
import "fmt"
3+
import (
4+
"os"
5+
6+
src "github.com/WoodProgrammer/firecracker-vmbuilder/src"
7+
"github.com/rs/zerolog/log"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var (
12+
configFile string
13+
)
14+
15+
func newBuildClient() src.Builder {
16+
return &src.BuildHandler{}
17+
}
18+
19+
func newParserClient() src.Parser {
20+
return &src.ParseHandler{}
21+
}
22+
23+
func newRootFSClient() src.RootFS {
24+
return &src.RootFSHandler{}
25+
}
26+
27+
func HandleRootFS() {
28+
parserClient := newParserClient()
29+
buildCLient := newBuildClient()
30+
rootFsClient := newRootFSClient()
31+
32+
result, err := parserClient.ParseYamlFile(configFile)
33+
if err != nil {
34+
log.Err(err).Msg("Error while running parserCli.ParseYamlFile()")
35+
}
36+
37+
err = rootFsClient.CreateFileDD(10, "ops")
38+
if err != nil {
39+
log.Err(err).Msg("Error while running rootFsClient.CreateFileDD()")
40+
}
41+
42+
fsErr := rootFsClient.FormatandMountFileSystem("ops", result.TargetDirectory)
43+
if fsErr != nil {
44+
log.Err(fsErr).Msg("Error while running rootFsClient.FormatFileSystem()")
45+
}
46+
47+
err = buildCLient.BuildExportDockerImage(result.Context, result.DockerfilePath, result.TargetDirectory)
48+
if err != nil {
49+
log.Err(err).Msg("Error while running buildCLient.BuildExportDockerImage()")
50+
}
51+
52+
}
453

554
func main() {
6-
fmt.Println("This is firecracker vmbuilder 0.0.1")
55+
var rootCmd = &cobra.Command{
56+
Use: "rootfsCreator",
57+
Short: "CLI tool to manage RootFS for firecracker micro VMs",
58+
Run: func(cmd *cobra.Command, args []string) {
59+
HandleRootFS()
60+
},
61+
}
62+
rootCmd.Flags().StringVarP(&configFile, "config", "C", "config.yaml", "Config file of RootFS creation")
63+
64+
rootCmd.MarkFlagRequired("config")
65+
66+
if err := rootCmd.Execute(); err != nil {
67+
log.Err(err).Msg("rootfsCreator execution failed")
68+
os.Exit(1)
69+
}
770
}

src/container.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package src
2+
3+
import (
4+
"os/exec"
5+
6+
"github.com/rs/zerolog/log"
7+
)
8+
9+
type Builder interface {
10+
BuildExportDockerImage(context, dockerFile, targetDirectory string) error
11+
}
12+
13+
type BuildHandler struct{}
14+
15+
func (buildClient *BuildHandler) BuildExportDockerImage(context, dockerFile, targetDirectory string) error {
16+
cmd := exec.Command("docker", "buildx", "build", "-f", dockerFile, "--output", targetDirectory, context)
17+
18+
output, err := cmd.CombinedOutput()
19+
if err != nil {
20+
log.Err(err).Msgf("docker buildx error : %s", output)
21+
return err
22+
}
23+
log.Info().Msgf("Build Result %s", string(output))
24+
return nil
25+
}

src/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module firecracker-vmbuilder/src
2+
3+
go 1.24.1

src/parser.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package src
2+
3+
import (
4+
"os"
5+
6+
"github.com/rs/zerolog/log"
7+
yaml "gopkg.in/yaml.v2"
8+
)
9+
10+
type RootFSManifest struct {
11+
Image string `yaml:"image"`
12+
TargetDirectory string `yaml:"target_directory"`
13+
RootFsRegistry string `yaml:"rootfs_registry"`
14+
Context string `yaml:"context"`
15+
DockerfilePath string `yaml:"docker_file"`
16+
}
17+
18+
type Parser interface {
19+
ParseYamlFile(configFile string) (RootFSManifest, error)
20+
}
21+
22+
type ParseHandler struct{}
23+
24+
func (parser *ParseHandler) ParseYamlFile(configFile string) (RootFSManifest, error) {
25+
var config RootFSManifest
26+
data, err := os.ReadFile("config.yaml")
27+
28+
if err != nil {
29+
log.Err(err).Msg("Error reading YAML file:")
30+
return config, err
31+
}
32+
33+
err = yaml.Unmarshal(data, &config)
34+
if err != nil {
35+
log.Err(err).Msg("Error parsing YAML:")
36+
return config, err
37+
}
38+
39+
return config, nil
40+
}

src/rootfs.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package src
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
7+
"github.com/rs/zerolog/log"
8+
)
9+
10+
type RootFS interface {
11+
CreateFileDD(size int64, fileName string) error
12+
FormatandMountFileSystem(path, targetDirectory string) error
13+
}
14+
15+
type RootFSHandler struct{}
16+
17+
func (rootfs *RootFSHandler) FormatandMountFileSystem(path, targetDirectory string) error {
18+
cmd := exec.Command("mkfs.ext4", path)
19+
output, err := cmd.CombinedOutput()
20+
if err != nil {
21+
log.Err(err).Msg("Error running mkfs.ext4:")
22+
log.Info().Msgf("Output: %s", string(output))
23+
return err
24+
}
25+
26+
log.Info().Msgf("Output: %s", string(output))
27+
28+
cmd = exec.Command("mount", path, targetDirectory)
29+
output, err = cmd.CombinedOutput()
30+
if err != nil {
31+
log.Err(err).Msg("Error running mount")
32+
log.Info().Msgf("Mount exec output: %s", string(output))
33+
return err
34+
}
35+
36+
log.Info().Msgf("Mount exec output: %s", string(output))
37+
return nil
38+
}
39+
40+
func (rootfs *RootFSHandler) CreateFileDD(size int64, fileName string) error {
41+
42+
size = int64(size * 1024 * 1024) // in MiB files
43+
44+
file, err := os.Create(fileName)
45+
if err != nil {
46+
log.Err(err).Msg("Error creating file:")
47+
return err
48+
}
49+
defer file.Close()
50+
51+
zeroBlock := make([]byte, 1024*1024) // 1 MiB bufferred files in there
52+
for i := 0; i < 50; i++ {
53+
_, err := file.Write(zeroBlock)
54+
if err != nil {
55+
log.Err(err).Msg("Error writing to file:")
56+
return err
57+
}
58+
}
59+
60+
log.Info().Msg("rootfs.ext4 created successfully")
61+
return nil
62+
}

0 commit comments

Comments
 (0)