pipeline/target: implement as variant types
Go doesn't really do variants, so we must somehow emulate it. The json objects we use are essentially tagged unions, with a `name` field in reverse domain name notation identifying the type and a type specific 'options' object. In Go we represent this by having an BarOptions interface, which implements a private method `isBarOptions()`, making sure that only types in the same package are able to implement it. Each type FooBar that should belong to the variant implements the interface, and a constructor `NewFooBar(options *FooBarOptions) *Bar` that makes sure the `name` field is set correctly. This would be enough to represent our types and marshal them into JSON, but unmarshalling would not work (json does not know about our tags, so would not know what concrete types to demarshal to). We therefore must also implement the Unmarshall interface for Bar, to select the right types for the Options field. We implement his logic for Target, Stage and Assembler. A handful of concrete types are also implemented, matching what osbuild supports. Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
parent
87bcd7f9d3
commit
7625d26ff5
17 changed files with 393 additions and 70 deletions
20
internal/target/local_target.go
Normal file
20
internal/target/local_target.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package target
|
||||
|
||||
type LocalTargetOptions struct {
|
||||
Location string `json:"location"`
|
||||
}
|
||||
|
||||
func (LocalTargetOptions) isTargetOptions() {}
|
||||
|
||||
func NewLocalTargetOptions(location string) *LocalTargetOptions {
|
||||
return &LocalTargetOptions{
|
||||
Location: location,
|
||||
}
|
||||
}
|
||||
|
||||
func NewLocalTarget(options *LocalTargetOptions) *Target {
|
||||
return &Target{
|
||||
Name: "org.osbuild.local",
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,44 @@
|
|||
package target
|
||||
|
||||
import "github.com/google/uuid"
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Target struct {
|
||||
Name string `json:"name"`
|
||||
Options Options `json:"options"`
|
||||
Name string `json:"name"`
|
||||
Options TargetOptions `json:"options"`
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
Location string `json:"location"`
|
||||
type TargetOptions interface {
|
||||
isTargetOptions()
|
||||
}
|
||||
|
||||
func New(ComposeID uuid.UUID) *Target {
|
||||
return &Target{
|
||||
Name: "org.osbuild.local",
|
||||
Options: Options{
|
||||
Location: "/var/lib/osbuild-composer/outputs/" + ComposeID.String(),
|
||||
},
|
||||
type rawTarget struct {
|
||||
Name string `json:"name"`
|
||||
Options json.RawMessage `json:"options"`
|
||||
}
|
||||
|
||||
func (target *Target) UnmarshalJSON(data []byte) error {
|
||||
var rawTarget rawTarget
|
||||
err := json.Unmarshal(data, &rawTarget)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var options TargetOptions
|
||||
switch rawTarget.Name {
|
||||
case "org.osbuild.local":
|
||||
options = new(LocalTargetOptions)
|
||||
default:
|
||||
return errors.New("unexpected target name")
|
||||
}
|
||||
err = json.Unmarshal(rawTarget.Options, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target.Name = rawTarget.Name
|
||||
target.Options = options
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue