Skip to content

Commit

Permalink
Add support for bunnyfile
Browse files Browse the repository at this point in the history
Add support to read and create the unikernel OCI image for urunc,
reading a yaml file that has the structure of bunnyfile.

Signed-off-by: Charalampos Mainas <[email protected]>
  • Loading branch information
cmainas committed Jan 13, 2025
1 parent f767f6c commit f4271ff
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 0 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ module bunny
go 1.23.4

require (
github.com/hashicorp/go-version v1.7.0
github.com/moby/buildkit v0.18.2
github.com/opencontainers/image-spec v1.1.0
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand All @@ -29,6 +31,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/in-toto/in-toto-golang v0.5.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/sys/signal v0.7.1 // indirect
Expand Down
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oL
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -63,12 +64,18 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF/XEFBbY=
github.com/in-toto/in-toto-golang v0.5.0/go.mod h1:/Rq0IZHLV7Ku5gielPT4wPHJfH1GdHMCq8+WPxw8/BE=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/moby/buildkit v0.18.2 h1:l86uBvxh4ntNoUUg3Y0eGTbKg1PbUh6tawJ4Xt75SpQ=
github.com/moby/buildkit v0.18.2/go.mod h1:vCR5CX8NGsPTthTg681+9kdmfvkvqJBXEv71GZe5msU=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
Expand Down Expand Up @@ -172,6 +179,8 @@ google.golang.org/grpc v1.66.3/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
115 changes: 115 additions & 0 deletions hops/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,139 @@ import (
"bytes"
"strings"

"gopkg.in/yaml.v3"
"github.com/moby/buildkit/client/llb"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
"github.com/moby/buildkit/frontend/dockerfile/parser"
"github.com/hashicorp/go-version"
)

const (
DefaultKernelPath string = "/.boot/kernel"
DefaultInitrdPath string = "/.boot/initrd"
unikraftKernelPath string = "/unikraft/bin/kernel"
unikraftHub string = "unikraft.org"
uruncJSONPath string = "/urunc.json"
bunnyFileVersion string = "0.1"
)

type HopsPlatform struct {
Framework string `yaml:"framework"`
Version string `yaml:"version"`
Monitor string `yaml:"monitor"`
Arch string `yaml:"arch"`
}

type HopsRootfs struct {
From string `yaml:"from"`
Path string `yaml:"path"`
}

type HopsKernel struct {
From string `yaml:"from"`
Path string `yaml:"path"`
}

type Hops struct {
Version string `yaml:"version"`
Platform HopsPlatform `yaml:"platforms"`
Rootfs HopsRootfs `yaml:"rootfs"`
Kernel HopsKernel `yaml:"kernel"`
Cmd string `yaml:"cmdline"`
}

type PackInstructions struct {
Base string // The Base image to use
Copies map[string]string // Mappings of files top copy, source as key and destination as value
Annots map[string]string // Annotations
}

// HopsToPack converts Hops into PackInstructions
func HopsToPack(hops Hops) (*PackInstructions, error) {
var instr *PackInstructions
instr = new(PackInstructions)
instr.Copies = make(map[string]string)
instr.Annots = make(map[string]string)

if hops.Kernel.From == "local" {
instr.Base = "scratch"
instr.Copies[hops.Kernel.Path] = DefaultKernelPath
instr.Annots["com.urunc.unikernel.binary"] = DefaultKernelPath
} else {
instr.Base = hops.Kernel.From
instr.Annots["com.urunc.unikernel.binary"] = hops.Kernel.Path
}

if hops.Rootfs.From == "local" && hops.Platform.Framework == "unikraft" {
instr.Copies[hops.Rootfs.Path] = DefaultInitrdPath
instr.Annots["com.urunc.unikernel.initrd"] = DefaultInitrdPath
}
instr.Annots["com.urunc.unikernel.unikernelType"] = hops.Platform.Framework
instr.Annots["com.urunc.unikernel.cmdline"] = hops.Cmd
instr.Annots["com.urunc.unikernel.hypervisor"] = hops.Platform.Monitor
if hops.Platform.Version != "" {
instr.Annots["com.urunc.unikernel.unikernelVersion"] = hops.Platform.Version
}

return instr, nil
}

// CheckBunnyfileVersion checks if the version of the user's input file
// is compatible with the supported version.
func CheckBunnyfileVersion(userVersion string) error {
if userVersion == "" {
return fmt.Errorf("The version field is necessary")
}
hopsVersion, err := version.NewVersion(bunnyFileVersion)
if err != nil {
return fmt.Errorf("Internal error in current bunnyfile version %s: %v", bunnyFileVersion, err)
}
userFileVer, err := version.NewVersion(userVersion)
if err != nil {
return fmt.Errorf("Could not parse version in user bunnyfile %s: %v", userVersion, err)
}
if hopsVersion.LessThan(userFileVer) {
return fmt.Errorf("Unsupported version %s. Please use %s or earlier", userVersion, bunnyFileVersion)
}

return nil
}

// ParseBunnyFile reads a yaml file which contains instructions for
// bunny.
func ParseBunnyFile(fileBytes []byte) (*PackInstructions, error) {
var bunnyHops Hops

err := yaml.Unmarshal(fileBytes, &bunnyHops)
if err != nil {
return nil, err
}

err = CheckBunnyfileVersion(bunnyHops.Version)
if err != nil {
return nil, err
}

if bunnyHops.Platform.Framework == "" {
return nil, fmt.Errorf("The framework field of platforms is necessary")
}

if bunnyHops.Platform.Monitor == "" {
return nil, fmt.Errorf("The monitor field of platforms is necessary")
}

if bunnyHops.Kernel.From == "" {
return nil, fmt.Errorf("The from field of kernel is necessary")
}

if bunnyHops.Kernel.Path == "" {
return nil, fmt.Errorf("The path field of kernel is necessary")
}

return HopsToPack(bunnyHops)
}

// ParseDockerFile reads a Dockerfile-like file and returns a Hops
// struct with the info from the file
func ParseDockerFile(fileBytes []byte) (*PackInstructions, error) {
Expand Down

0 comments on commit f4271ff

Please sign in to comment.