main: add ostree integration
This commit adds integration for the ostree options. It is modelled
loosely after weldr-client/composer-cli and the
```
start-ostree --{ref,parent,url}
```
and uses
```
--ostree-{ref,parent,url}
```
A simple smoke test is provided that uses fedora-iot. Ideas welcome
for an easier way :)
This commit is contained in:
parent
00e18fe1cd
commit
8f94516779
3 changed files with 131 additions and 3 deletions
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/osbuild/images/pkg/arch"
|
||||
"github.com/osbuild/images/pkg/imagefilter"
|
||||
"github.com/osbuild/images/pkg/ostree"
|
||||
|
||||
"github.com/osbuild/image-builder-cli/internal/blueprintload"
|
||||
)
|
||||
|
|
@ -37,6 +38,31 @@ func cmdListImages(cmd *cobra.Command, args []string) error {
|
|||
return listImages(dataDir, output, filter)
|
||||
}
|
||||
|
||||
func ostreeImageOptions(cmd *cobra.Command) (*ostree.ImageOptions, error) {
|
||||
imageRef, err := cmd.Flags().GetString("ostree-ref")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentRef, err := cmd.Flags().GetString("ostree-parent")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
url, err := cmd.Flags().GetString("ostree-url")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if imageRef == "" && parentRef == "" && url == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// XXX: how to add RHSM?
|
||||
return &ostree.ImageOptions{
|
||||
ImageRef: imageRef,
|
||||
ParentRef: parentRef,
|
||||
URL: url,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func cmdManifestWrapper(cmd *cobra.Command, args []string, w io.Writer, archChecker func(string) error) (*imagefilter.Result, error) {
|
||||
dataDir, err := cmd.Flags().GetString("datadir")
|
||||
if err != nil {
|
||||
|
|
@ -53,6 +79,10 @@ func cmdManifestWrapper(cmd *cobra.Command, args []string, w io.Writer, archChec
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ostreeImgOpts, err := ostreeImageOptions(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var blueprintPath string
|
||||
imgTypeStr := args[0]
|
||||
|
|
@ -78,7 +108,7 @@ func cmdManifestWrapper(cmd *cobra.Command, args []string, w io.Writer, archChec
|
|||
}
|
||||
}
|
||||
|
||||
err = generateManifest(dataDir, blueprintPath, res, w)
|
||||
err = generateManifest(dataDir, blueprintPath, res, w, ostreeImgOpts)
|
||||
return res, err
|
||||
}
|
||||
|
||||
|
|
@ -148,6 +178,9 @@ operating sytsems like centos and RHEL with easy customizations support.`,
|
|||
}
|
||||
manifestCmd.Flags().String("arch", "", `build manifest for a different architecture`)
|
||||
manifestCmd.Flags().String("distro", "", `build manifest for a different distroname (e.g. centos-9)`)
|
||||
manifestCmd.Flags().String("ostree-ref", "", `OSTREE reference`)
|
||||
manifestCmd.Flags().String("ostree-parent", "", `OSTREE parent`)
|
||||
manifestCmd.Flags().String("ostree-url", "", `OSTREE url`)
|
||||
rootCmd.AddCommand(manifestCmd)
|
||||
|
||||
buildCmd := &cobra.Command{
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@ package main_test
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
|
@ -161,6 +164,7 @@ func TestManifestIntegrationSmoke(t *testing.T) {
|
|||
restore = main.MockOsArgs([]string{
|
||||
"manifest",
|
||||
"qcow2",
|
||||
"--arch=x86_64",
|
||||
"--distro=centos-9",
|
||||
makeTestBlueprint(t, testBlueprint),
|
||||
})
|
||||
|
|
@ -216,6 +220,89 @@ func TestManifestIntegrationCrossArch(t *testing.T) {
|
|||
assert.Contains(t, fakeStdout.String(), `.el9.s390x.rpm`)
|
||||
}
|
||||
|
||||
func TestManifestIntegrationOstreeSmoke(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("manifest generation takes a while")
|
||||
}
|
||||
if !hasDepsolveDnf() {
|
||||
t.Skip("no osbuild-depsolve-dnf binary found")
|
||||
}
|
||||
|
||||
restore := main.MockNewRepoRegistry(testrepos.New)
|
||||
defer restore()
|
||||
|
||||
// we cannot hit ostree.f.o directly, we need to go via the mirrorlist
|
||||
resp, err := http.Get("https://ostree.fedoraproject.org/iot/mirrorlist")
|
||||
assert.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
restore = main.MockOsArgs([]string{
|
||||
"manifest",
|
||||
"iot-raw-image",
|
||||
"--arch=x86_64",
|
||||
"--distro=fedora-40",
|
||||
"--ostree-url=" + strings.SplitN(string(body), "\n", 2)[0],
|
||||
"--ostree-ref=fedora/stable/x86_64/iot",
|
||||
})
|
||||
defer restore()
|
||||
|
||||
var fakeStdout bytes.Buffer
|
||||
restore = main.MockOsStdout(&fakeStdout)
|
||||
defer restore()
|
||||
|
||||
err = main.Run()
|
||||
assert.NoError(t, err)
|
||||
|
||||
pipelineNames, err := manifesttest.PipelineNamesFrom(fakeStdout.Bytes())
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, pipelineNames, "ostree-deployment")
|
||||
|
||||
// XXX: provide helpers in manifesttest to extract this in a nicer way
|
||||
assert.Contains(t, fakeStdout.String(), `{"type":"org.osbuild.ostree.init-fs"`)
|
||||
}
|
||||
|
||||
func TestManifestIntegrationOstreeSmokeErrors(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("manifest generation takes a while")
|
||||
}
|
||||
|
||||
restore := main.MockNewRepoRegistry(testrepos.New)
|
||||
defer restore()
|
||||
|
||||
baseArgs := []string{
|
||||
"manifest",
|
||||
"--arch=x86_64",
|
||||
"--distro=fedora-40",
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
extraArgs []string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
[]string{"iot-raw-image"},
|
||||
`iot-raw-image: ostree commit URL required`,
|
||||
},
|
||||
{
|
||||
[]string{"qcow2", "--ostree-url=http://example.com/"},
|
||||
`OSTree is not supported for "qcow2"`,
|
||||
},
|
||||
} {
|
||||
args := append(baseArgs, tc.extraArgs...)
|
||||
restore = main.MockOsArgs(args)
|
||||
defer restore()
|
||||
|
||||
var fakeStdout bytes.Buffer
|
||||
restore = main.MockOsStdout(&fakeStdout)
|
||||
defer restore()
|
||||
|
||||
err := main.Run()
|
||||
assert.EqualError(t, err, tc.expectedErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildIntegrationHappy(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("manifest generation takes a while")
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ package main
|
|||
import (
|
||||
"io"
|
||||
|
||||
"github.com/osbuild/images/pkg/distro"
|
||||
"github.com/osbuild/images/pkg/imagefilter"
|
||||
"github.com/osbuild/images/pkg/ostree"
|
||||
|
||||
"github.com/osbuild/image-builder-cli/internal/blueprintload"
|
||||
"github.com/osbuild/image-builder-cli/internal/manifestgen"
|
||||
)
|
||||
|
||||
func generateManifest(dataDir, blueprintPath string, res *imagefilter.Result, output io.Writer) error {
|
||||
func generateManifest(dataDir, blueprintPath string, res *imagefilter.Result, output io.Writer, ostreeOpts *ostree.ImageOptions) error {
|
||||
repos, err := newRepoRegistry(dataDir)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -25,6 +27,12 @@ func generateManifest(dataDir, blueprintPath string, res *imagefilter.Result, ou
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var imgOpts *distro.ImageOptions
|
||||
if ostreeOpts != nil {
|
||||
imgOpts = &distro.ImageOptions{
|
||||
OSTree: ostreeOpts,
|
||||
}
|
||||
}
|
||||
|
||||
return mg.Generate(bp, res.Distro, res.ImgType, res.Arch, nil)
|
||||
return mg.Generate(bp, res.Distro, res.ImgType, res.Arch, imgOpts)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue