From 079709e3ca59010fdfdd23638c7cfe11fad058fb Mon Sep 17 00:00:00 2001 From: axtloss Date: Wed, 7 Aug 2024 18:26:39 +0200 Subject: [PATCH] feat: add initial support for finalize plugins waiter waiter! more breaking changes please!! (this is a breaking change) --- api/finalize-scopes.go | 19 ++++++++++++++++ api/structs.go | 13 +++++++++++ core/build.go | 2 +- core/plugins.in | 34 ++++++++++++++++++++++++++-- finalize-plugins/docker-remote.go | 37 +++++++++++++++++++++++++++++++ plugins/apt.go | 10 +++++++++ plugins/cmake.go | 10 +++++++++ plugins/dpkg-buildpackage.go | 18 ++++++++++----- plugins/go.go | 10 +++++++++ plugins/make.go | 10 +++++++++ plugins/meson.go | 10 +++++++++ 11 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 api/finalize-scopes.go create mode 100644 finalize-plugins/docker-remote.go diff --git a/api/finalize-scopes.go b/api/finalize-scopes.go new file mode 100644 index 0000000..7e4938c --- /dev/null +++ b/api/finalize-scopes.go @@ -0,0 +1,19 @@ +package api + +// / Get the final tagged Image name +var IMAEGNAME = 1 + +// / Get the final tagged Image ID +var IMAGEID = 2 + +// / Get the build recipe +var RECIPE = 4 + +// / Get a read-write filesystem of the Image +var RWFS = 8 + +// / Get a read-only filesystem of the Image +var ROFS = 16 + +// / Prepare the filesystem to be chrooted into, requires either RWFilesystem or ROFilesystem +var CHROOTFS = 32 diff --git a/api/structs.go b/api/structs.go index 1135d12..8fe7cf7 100644 --- a/api/structs.go +++ b/api/structs.go @@ -22,6 +22,7 @@ type Recipe struct { SourcesPath string PluginPath string Containerfile string + Finalize []interface{} } type Stage struct { @@ -40,6 +41,18 @@ type Stage struct { Entrypoint Entrypoint } +type PluginType int + +const ( + BuildPlugin PluginType = iota + FinalizePlugin +) + +type PluginInfo struct { + Name string + Type PluginType +} + type Copy struct { From string SrcDst map[string]string diff --git a/core/build.go b/core/build.go index a0f6246..4e105d8 100644 --- a/core/build.go +++ b/core/build.go @@ -417,7 +417,7 @@ func BuildModule(recipe *api.Recipe, moduleInterface interface{}) (string, error } commands = commands + " && " + command } else { - command, err := LoadPlugin(module.Type, moduleInterface, recipe) + command, err := LoadPlugin(module.Type, api.BuildPlugin, moduleInterface, recipe) if err != nil { return "", err } diff --git a/core/plugins.in b/core/plugins.in index b4338dd..6014b52 100644 --- a/core/plugins.in +++ b/core/plugins.in @@ -13,7 +13,7 @@ import "os" var openedPlugins map[string]Plugin -func LoadPlugin(name string, module interface{}, recipe *api.Recipe) (string, error) { +func LoadPlugin(name string, plugintype api.PluginType, module interface{}, recipe *api.Recipe) (string, error) { if openedPlugins == nil { openedPlugins = make(map[string]Plugin) } @@ -26,7 +26,7 @@ func LoadPlugin(name string, module interface{}, recipe *api.Recipe) (string, er localPluginPath := fmt.Sprintf("%s/%s.so", recipe.PluginPath, name) - globalPluginPath := fmt.Sprintf("$INSTALLPREFIX$/share/vib/plugins/%s.so", name) + globalPluginPath := fmt.Sprintf("%INSTALLPREFIX%/share/vib/plugins/%s.so", name) // Prefer local plugins before global ones var loadedPlugin uintptr @@ -43,6 +43,36 @@ func LoadPlugin(name string, module interface{}, recipe *api.Recipe) (string, er } } + infoLoc, err := purego.Dlsym(loadedPlugin, "PlugInfo") + if err != nil && !strings.Contains(err.Error(), "undefined symbol: PlugInfo") { + fmt.Println(err) + return "", err + } + + pluginInfo := &api.PluginInfo{} + + if infoLoc == 0 { + fmt.Println("== WARN ==") + fmt.Printf("Plugin %s does not contain function PlugInfo, assuming old BuildPlugin type\n", name) + fmt.Printf("Please update the plugin or request the developer of the plugin to update it!\n") + fmt.Println("== WARN ==") + pluginInfo.Name = name + pluginInfo.Type = api.BuildPlugin + } else { + var pluginInfoFunc func() string + purego.RegisterLibFunc(&pluginInfoFunc, loadedPlugin, "PlugInfo") + json.Unmarshal([]byte(pluginInfoFunc()), &pluginInfo) + } + + if pluginInfo.Type != plugintype { + if plugintype == api.BuildPlugin { + fmt.Printf("ERROR: Plugin %s is not of type BuildPlugin", name) + os.Exit(1) + } else if plugintype == api.FinalizePlugin { + fmt.Printf("ERROR: Plugin %s is not of type FinalizePlugin", name) + os.Exit(1) + } + } var buildFunction func(*C.char, *C.char) string purego.RegisterLibFunc(&buildFunction, loadedPlugin, "BuildModule") buildModule.BuildFunc = buildFunction diff --git a/finalize-plugins/docker-remote.go b/finalize-plugins/docker-remote.go new file mode 100644 index 0000000..267885a --- /dev/null +++ b/finalize-plugins/docker-remote.go @@ -0,0 +1,37 @@ +package main + +import ( + "encoding/json" + "fmt" + + "C" + + "github.com/vanilla-os/vib/api" +) + +type DockerRemote struct { + Name string `json:"name"` + Type string `json:"type"` + OCIRegistry string `json:"registry"` + ImageName string `json:"imagename"` + ImageTag string `json:"imagetag"` +} + +//export PluginScope +func PluginScope() int32 { // int32 is defined as GoInt32 in cgo which is the same as a C int + return int32(api.IMAEGNAME) +} + +//export FinalizeBuild +func FinalizeBuild(moduleInterface *C.char, extraData *C.char) *C.char { + var module *DockerRemote + + err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module) + if err != nil { + return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) + } + + return C.CString("ERROR: failed to upload image") +} + +func main() {} diff --git a/plugins/apt.go b/plugins/apt.go index f908bd7..353849e 100644 --- a/plugins/apt.go +++ b/plugins/apt.go @@ -26,6 +26,16 @@ type AptOptions struct { FixBroken bool `json:"fix_broken"` } +//export PlugInfo +func PlugInfo() *C.char { + plugininfo := &api.PluginInfo{Name: "apt", Type: api.BuildPlugin} + pluginjson, err := json.Marshal(plugininfo) + if err != nil { + return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) + } + return C.CString(string(pluginjson)) +} + // BuildAptModule builds a module that installs packages // using the apt package manager // diff --git a/plugins/cmake.go b/plugins/cmake.go index 6ff6e97..28e8e8f 100644 --- a/plugins/cmake.go +++ b/plugins/cmake.go @@ -17,6 +17,16 @@ type CMakeModule struct { Source api.Source } +//export PlugInfo +func PlugInfo() *C.char { + plugininfo := &api.PluginInfo{Name: "cmake", Type: api.BuildPlugin} + pluginjson, err := json.Marshal(plugininfo) + if err != nil { + return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) + } + return C.CString(string(pluginjson)) +} + // BuildCMakeModule builds a module that builds a CMake project // //export BuildModule diff --git a/plugins/dpkg-buildpackage.go b/plugins/dpkg-buildpackage.go index 10b3c0a..1db1985 100644 --- a/plugins/dpkg-buildpackage.go +++ b/plugins/dpkg-buildpackage.go @@ -2,9 +2,9 @@ package main import ( "C" + "encoding/json" "fmt" "path/filepath" - "encoding/json" "github.com/vanilla-os/vib/api" ) @@ -15,14 +15,24 @@ type DpkgBuildModule struct { Source api.Source } +//export PlugInfo +func PlugInfo() *C.char { + plugininfo := &api.PluginInfo{Name: "dpkg-buildpackage", Type: api.BuildPlugin} + pluginjson, err := json.Marshal(plugininfo) + if err != nil { + return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) + } + return C.CString(string(pluginjson)) +} + // BuildDpkgModule builds a module that builds a dpkg project // and installs the resulting .deb package +// //export BuildModule func BuildModule(moduleInterface *C.char, recipeInterface *C.char) *C.char { var module *DpkgBuildModule var recipe *api.Recipe - err := json.Unmarshal([]byte(C.GoString(moduleInterface)), &module) if err != nil { return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) @@ -55,6 +65,4 @@ func BuildModule(moduleInterface *C.char, recipeInterface *C.char) *C.char { return C.CString(cmd) } - - -func main() { fmt.Println("This plugin is not meant to run standalone!"); } +func main() { fmt.Println("This plugin is not meant to run standalone!") } diff --git a/plugins/go.go b/plugins/go.go index 4887729..5860717 100644 --- a/plugins/go.go +++ b/plugins/go.go @@ -16,6 +16,16 @@ type GoModule struct { BuildFlags string } +//export PlugInfo +func PlugInfo() *C.char { + plugininfo := &api.PluginInfo{Name: "go", Type: api.BuildPlugin} + pluginjson, err := json.Marshal(plugininfo) + if err != nil { + return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) + } + return C.CString(string(pluginjson)) +} + // BuildGoModule builds a module that builds a Go project // buildVars are used to customize the build command // like setting the output binary name and location diff --git a/plugins/make.go b/plugins/make.go index 3068373..b16ea8e 100644 --- a/plugins/make.go +++ b/plugins/make.go @@ -14,6 +14,16 @@ type MakeModule struct { Source api.Source } +//export PlugInfo +func PlugInfo() *C.char { + plugininfo := &api.PluginInfo{Name: "make", Type: api.BuildPlugin} + pluginjson, err := json.Marshal(plugininfo) + if err != nil { + return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) + } + return C.CString(string(pluginjson)) +} + // BuildMakeModule builds a module that builds a Make project // //export BuildModule diff --git a/plugins/meson.go b/plugins/meson.go index 3c77e03..8002751 100644 --- a/plugins/meson.go +++ b/plugins/meson.go @@ -14,6 +14,16 @@ type MesonModule struct { Source api.Source } +//export PlugInfo +func PlugInfo() *C.char { + plugininfo := &api.PluginInfo{Name: "meson", Type: api.BuildPlugin} + pluginjson, err := json.Marshal(plugininfo) + if err != nil { + return C.CString(fmt.Sprintf("ERROR: %s", err.Error())) + } + return C.CString(string(pluginjson)) +} + // BuildMesonModule builds a module that builds a Meson project // //export BuildModule