Skip to content

Commit

Permalink
feat: complete finalize plugin support
Browse files Browse the repository at this point in the history
  • Loading branch information
axtloss committed Aug 9, 2024
1 parent 74beccc commit 351d01b
Show file tree
Hide file tree
Showing 8 changed files with 1,081 additions and 80 deletions.
11 changes: 2 additions & 9 deletions api/finalize-scopes.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,13 @@ var RECIPE int32 = 4
// Get the used build runtime
var RUNTIME int32 = 8

// / Get a read-write filesystem of the Image
var RWFS int32 = 16

// / Get a read-only filesystem of the Image
var ROFS int32 = 32

// / Prepare the filesystem to be chrooted into, requires either RWFilesystem or ROFilesystem
var CHROOTFS int32 = 64
var FS int32 = 16

type ScopeData struct {
ImageName string
ImageID string
Recipe Recipe
Runtime string
RWFS string
ROFS string
FS string
}
2 changes: 1 addition & 1 deletion core/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func CompileRecipe(recipePath string, runtime string) error {
if err != nil {
return err
}
err = LoadFinalizePlugin(module.Type, module, &recipe, runtime)
err = LoadFinalizePlugin(module.Type, finalizeInterface, &recipe, runtime)
if err != nil {
return err
}
Expand Down
95 changes: 95 additions & 0 deletions core/finalize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package core

import (
"fmt"
cstorage "github.com/containers/storage"
"os/exec"
"strings"
)

type StorageConf struct {
Driver string
Runroot string
Graphroot string
}

func GetContainerStorage(runtime string) (cstorage.Store, error) {
storageconfig := &StorageConf{}
if runtime == "podman" {
podmanPath, err := exec.LookPath("podman")
out, err := exec.Command(
podmanPath, "info", "-f json").Output()
if err != nil {
fmt.Println("Failed to get podman info")
} else {
driver := strings.Split(strings.Split(string(out), "\"graphDriverName\": \"")[1], "\",")[0]
storageconfig.Driver = driver

graphRoot := strings.Split(strings.Split(string(out), "\"graphRoot\": \"")[1], "\",")[0]
storageconfig.Graphroot = graphRoot

runRoot := strings.Split(strings.Split(string(out), "\"runRoot\": \"")[1], "\",")[0]
storageconfig.Runroot = runRoot
}

}
if storageconfig.Runroot == "" {
storageconfig.Runroot = "/var/lib/vib/runroot"
storageconfig.Graphroot = "/var/lib/vib/graphroot"
storageconfig.Driver = "overlay"
}
store, err := cstorage.GetStore(cstorage.StoreOptions{
RunRoot: storageconfig.Runroot,
GraphRoot: storageconfig.Graphroot,
GraphDriverName: storageconfig.Driver,
})
if err != nil {
return store, err
}

return store, err
}

func GetImageID(name string, store cstorage.Store) (string, error) {
images, err := store.Images()
if err != nil {
return "", err
}
for _, img := range images {
for _, imgname := range img.Names {
if imgname == name {
return img.ID, nil
}
}
}
return "", fmt.Errorf("image not found")
}

func GetTopLayerID(imageid string, store cstorage.Store) (string, error) {
images, err := store.Images()
if err != nil {
return "", err
}
for _, img := range images {
if img.ID == imageid {
return img.TopLayer, nil
}
}
return "", fmt.Errorf("no top layer for id %s found", imageid)
}

func MountImage(imagename string, imageid string, runtime string) (string, error) {
store, err := GetContainerStorage(runtime)
if err != nil {
return "", err
}
topLayerID, err := GetTopLayerID(imageid, store)
if err != nil {
return "", err
}
mountDir, err := store.Mount(topLayerID, "")
if err != nil {
return "", err
}
return mountDir, err
}
57 changes: 0 additions & 57 deletions finalize-plugins/docker-remote.go

This file was deleted.

85 changes: 85 additions & 0 deletions finalize-plugins/sysext.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"C"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/vanilla-os/vib/api"
)

type Sysext struct {
Name string `json:"name"`
Type string `json:"type"`
OSReleaseID string `json:"osreleaseid"`
OSReleaseVersionID string `json:"osreleaseversionid"`
}

//export PlugInfo
func PlugInfo() *C.char {
plugininfo := &api.PluginInfo{Name: "sysext", Type: api.FinalizePlugin}
pluginjson, err := json.Marshal(plugininfo)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}
return C.CString(string(pluginjson))
}

//export PluginScope
func PluginScope() int32 { // int32 is defined as GoInt32 in cgo which is the same as a C int
return api.IMAGENAME | api.FS | api.RECIPE
}

//export FinalizeBuild
func FinalizeBuild(moduleInterface *C.char, extraData *C.char) *C.char {
var module *Sysext
var data *api.ScopeData

err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}

err = json.Unmarshal([]byte(C.GoString(extraData)), &data)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}

var extensionRelease strings.Builder
fmt.Fprintf(&extensionRelease, "ID=%s\n", module.OSReleaseID)
fmt.Fprintf(&extensionRelease, "VersionID=%s\n", module.OSReleaseVersionID)

err = os.MkdirAll(filepath.Join(data.FS, "usr/lib/extension-release.d"), 0o777)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}
err = os.WriteFile(filepath.Join(data.FS, fmt.Sprintf("usr/lib/extension-release.d/extension-release.%s", data.Recipe.Id)), []byte(extensionRelease.String()), 0o777)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}

mksquashfs, err := exec.LookPath("mksquashfs")
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}
cmd := exec.Command(
mksquashfs, data.FS,
filepath.Join(data.Recipe.ParentPath, fmt.Sprintf("%s.raw", data.Recipe.Id)),
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = data.Recipe.ParentPath

err = cmd.Run()
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}

return C.CString("")
}

func main() {}
79 changes: 79 additions & 0 deletions finalize-plugins/systemd-repart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package main

import (
"C"
"encoding/json"
"fmt"
"github.com/vanilla-os/vib/api"
"os"
"os/exec"
)

type SystemdRepart struct {
Name string `json:"name"`
Type string `json:"type"`
Output string `json:"output"`
Size string `json:"size"`
Seed string `json:"seed"`
}

//export PlugInfo
func PlugInfo() *C.char {
plugininfo := &api.PluginInfo{Name: "systemd-repart", Type: api.FinalizePlugin}
pluginjson, err := json.Marshal(plugininfo)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}
return C.CString(string(pluginjson))
}

//export PluginScope
func PluginScope() int32 { // int32 is defined as GoInt32 in cgo which is the same as a C int
return api.IMAGENAME | api.FS | api.RECIPE
}

//export FinalizeBuild
func FinalizeBuild(moduleInterface *C.char, extraData *C.char) *C.char {
var module *SystemdRepart
var data *api.ScopeData

err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}

err = json.Unmarshal([]byte(C.GoString(extraData)), &data)
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}

repart, err := exec.LookPath("systemd-repart")
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}
cmd := exec.Command(
repart,
"--definitions=definitions",
"--empty=create",
fmt.Sprintf("--size=%s", module.Size),
"--dry-run=no",
"--discard=no",
"--offline=true",
"--no-pager",
fmt.Sprintf("--seed=%s", module.Seed),
fmt.Sprintf("--root=%s", data.FS),
module.Output,
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = data.Recipe.ParentPath

err = cmd.Run()
if err != nil {
return C.CString(fmt.Sprintf("ERROR: %s", err.Error()))
}

return C.CString("")
}

func main() {}
Loading

0 comments on commit 351d01b

Please sign in to comment.