internal: add new blueprintload package
This commit provides a `blueprintload` package that can be used to load blueprints from json/toml from a path. This will be used in `bootc-image-builder` and `image-builder-cli` and should eventually be merged into `images`.
This commit is contained in:
parent
830528fa15
commit
f242005672
2 changed files with 139 additions and 0 deletions
67
internal/blueprintload/blueprintload.go
Normal file
67
internal/blueprintload/blueprintload.go
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package blueprintload
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"github.com/osbuild/images/pkg/blueprint"
|
||||
)
|
||||
|
||||
// XXX: move this helper into images, share with bib
|
||||
func decodeToml(r io.Reader, what string) (*blueprint.Blueprint, error) {
|
||||
dec := toml.NewDecoder(r)
|
||||
|
||||
var conf blueprint.Blueprint
|
||||
_, err := dec.Decode(&conf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot decode %q: %w", what, err)
|
||||
}
|
||||
|
||||
return &conf, nil
|
||||
}
|
||||
|
||||
func decodeJson(r io.Reader, what string) (*blueprint.Blueprint, error) {
|
||||
dec := json.NewDecoder(r)
|
||||
dec.DisallowUnknownFields()
|
||||
|
||||
var conf blueprint.Blueprint
|
||||
if err := dec.Decode(&conf); err != nil {
|
||||
return nil, fmt.Errorf("cannot decode %q: %w", what, err)
|
||||
}
|
||||
if dec.More() {
|
||||
return nil, fmt.Errorf("multiple configuration objects or extra data found in %q", what)
|
||||
}
|
||||
return &conf, nil
|
||||
}
|
||||
|
||||
func Load(path string) (*blueprint.Blueprint, error) {
|
||||
var fp io.ReadCloser
|
||||
var err error
|
||||
|
||||
switch path {
|
||||
case "":
|
||||
return &blueprint.Blueprint{}, nil
|
||||
case "-":
|
||||
fp = os.Stdin
|
||||
default:
|
||||
fp, err = os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fp.Close()
|
||||
}
|
||||
|
||||
switch {
|
||||
case path == "-", filepath.Ext(path) == ".json":
|
||||
return decodeJson(fp, path)
|
||||
case filepath.Ext(path) == ".toml":
|
||||
return decodeToml(fp, path)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported file extension for %q (please use .toml or .json)", path)
|
||||
}
|
||||
}
|
||||
72
internal/blueprintload/blueprintload_test.go
Normal file
72
internal/blueprintload/blueprintload_test.go
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package blueprintload_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/osbuild/images/pkg/blueprint"
|
||||
|
||||
"github.com/osbuild/image-builder-cli/internal/blueprintload"
|
||||
)
|
||||
|
||||
var testBlueprintJSON = `{
|
||||
"customizations": {
|
||||
"user": [
|
||||
{
|
||||
"name": "alice"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
var testBlueprintTOML = `
|
||||
[[customizations.user]]
|
||||
name = "alice"
|
||||
`
|
||||
|
||||
var expectedBlueprint = &blueprint.Blueprint{
|
||||
Customizations: &blueprint.Customizations{
|
||||
User: []blueprint.UserCustomization{
|
||||
{
|
||||
Name: "alice",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func makeTestBlueprint(t *testing.T, name, content string) string {
|
||||
tmpdir := t.TempDir()
|
||||
blueprintPath := filepath.Join(tmpdir, name)
|
||||
err := os.WriteFile(blueprintPath, []byte(content), 0644)
|
||||
assert.NoError(t, err)
|
||||
return blueprintPath
|
||||
}
|
||||
|
||||
func TestBlueprintLoadJSON(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
fname string
|
||||
content string
|
||||
|
||||
expectedBp *blueprint.Blueprint
|
||||
expectedError string
|
||||
}{
|
||||
{"bp.json", testBlueprintJSON, expectedBlueprint, ""},
|
||||
{"bp.toml", testBlueprintTOML, expectedBlueprint, ""},
|
||||
{"bp.toml", "wrong-content", nil, `cannot decode .*/bp.toml": toml: `},
|
||||
{"bp.json", "wrong-content", nil, `cannot decode .*/bp.json": invalid `},
|
||||
{"bp", "wrong-content", nil, `unsupported file extension for "/.*/bp"`},
|
||||
} {
|
||||
blueprintPath := makeTestBlueprint(t, tc.fname, tc.content)
|
||||
bp, err := blueprintload.Load(blueprintPath)
|
||||
if tc.expectedError == "" {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expectedBp, bp)
|
||||
} else {
|
||||
assert.NotNil(t, err)
|
||||
assert.Regexp(t, tc.expectedError, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue