forked from osbuild/image-builder-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
main: initial version of
ibuilder
with basic --list-images
This commit adds the new `ibuilder` binary (name still a bit TBD but this is the best so far IMHO). This binary is meant to build images from the CLI without the need to setup a daemon. The main use-case is CI/CD and admins running this in scripts or ad-hoc. The CLI should be pleasant to use. This first commit adds the `list-images` command which is a thin wrapper around functionality from the `osbuild/images` library. It will list all buildable images by default and can be trimmed down further via `--filter` which supports the filtering from the `images` library, see osbuild/images#1015 It also supports `--output` which will output the result in the given format. Currently "text" and "json" are supported. Note that this will not work on it's own yet, it will need an installed image-builder to get the repositories. This will need to get fixed via either: 1. a dependency package for `ibuilder` that carries all the repos 2. a shared repo that contains the repos 3. using go:embed to get them (see images#1038)
- Loading branch information
Showing
8 changed files
with
734 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package main | ||
|
||
import ( | ||
"io" | ||
"os" | ||
|
||
"github.com/osbuild/images/pkg/reporegistry" | ||
) | ||
|
||
func MockOsArgs(new []string) (restore func()) { | ||
saved := os.Args | ||
os.Args = append([]string{"argv0"}, new...) | ||
return func() { | ||
os.Args = saved | ||
} | ||
} | ||
|
||
func MockOsStdout(new io.Writer) (restore func()) { | ||
saved := osStdout | ||
osStdout = new | ||
return func() { | ||
osStdout = saved | ||
} | ||
} | ||
|
||
func MockOsStderr(new io.Writer) (restore func()) { | ||
saved := osStderr | ||
osStderr = new | ||
return func() { | ||
osStderr = saved | ||
} | ||
} | ||
|
||
func MockNewRepoRegistry(f func() (*reporegistry.RepoRegistry, error)) (restore func()) { | ||
saved := newRepoRegistry | ||
newRepoRegistry = f | ||
return func() { | ||
newRepoRegistry = saved | ||
} | ||
} | ||
|
||
var ( | ||
Run = run | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/osbuild/images/pkg/distrofactory" | ||
"github.com/osbuild/images/pkg/imagefilter" | ||
) | ||
|
||
func newImageFilterDefault() (*imagefilter.ImageFilter, error) { | ||
fac := distrofactory.NewDefault() | ||
repos, err := newRepoRegistry() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return imagefilter.New(fac, repos) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package main | ||
|
||
import ( | ||
"io" | ||
|
||
"github.com/osbuild/images/pkg/imagefilter" | ||
) | ||
|
||
func listImages(out io.Writer, output string, filterExprs []string) error { | ||
imageFilter, err := newImageFilterDefault() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
filteredResult, err := imageFilter.Filter(filterExprs...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmter, err := imagefilter.NewResultsFormatter(imagefilter.OutputFormat(output)) | ||
if err != nil { | ||
return err | ||
} | ||
if err := fmter.Output(out, filteredResult); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
osStdout io.Writer = os.Stdout | ||
osStderr io.Writer = os.Stderr | ||
) | ||
|
||
func cmdListImages(cmd *cobra.Command, args []string) error { | ||
filter, err := cmd.Flags().GetStringArray("filter") | ||
if err != nil { | ||
return err | ||
} | ||
output, err := cmd.Flags().GetString("output") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return listImages(osStdout, output, filter) | ||
} | ||
|
||
func run() error { | ||
// images logs a bunch of stuff to Debug/Info that is distracting | ||
// the user (at least by default, like what repos being loaded) | ||
logrus.SetLevel(logrus.WarnLevel) | ||
|
||
rootCmd := &cobra.Command{ | ||
Use: "ibuilder", | ||
Short: "Build operating system images from a given distro/image-type/blueprint", | ||
Long: `Build operating system images from a given distribution, | ||
image-type and blueprint. | ||
Image-builder builds operating system images for a range of predefined | ||
operating sytsems like centos and RHEL with easy customizations support.`, | ||
SilenceErrors: true, | ||
} | ||
rootCmd.SetOut(osStdout) | ||
rootCmd.SetErr(osStderr) | ||
|
||
listImagesCmd := &cobra.Command{ | ||
Use: "list-images", | ||
Short: "List buildable images, use --filter to limit further", | ||
RunE: cmdListImages, | ||
SilenceUsage: true, | ||
} | ||
listImagesCmd.Flags().StringArray("filter", nil, `Filter distributions by a specific criteria (e.g. "type:rhel*"`) | ||
listImagesCmd.Flags().String("output", "", "Output in a specific format (text, json)") | ||
rootCmd.AddCommand(listImagesCmd) | ||
|
||
return rootCmd.Execute() | ||
} | ||
|
||
func main() { | ||
if err := run(); err != nil { | ||
fmt.Fprintf(osStderr, "error: %s", err) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package main_test | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/sirupsen/logrus" | ||
"github.com/stretchr/testify/assert" | ||
|
||
testrepos "github.com/osbuild/images/test/data/repositories" | ||
|
||
"github.com/osbuild/image-builder-cli/cmd/ibuilder" | ||
) | ||
|
||
func init() { | ||
// silence logrus by default, it is quite verbose | ||
logrus.SetLevel(logrus.WarnLevel) | ||
} | ||
|
||
func TestListImagesNoArguments(t *testing.T) { | ||
restore := main.MockNewRepoRegistry(testrepos.New) | ||
defer restore() | ||
|
||
for _, args := range [][]string{nil, []string{"--output=text"}} { | ||
restore = main.MockOsArgs(append([]string{"list-images"}, args...)) | ||
defer restore() | ||
|
||
var fakeStdout bytes.Buffer | ||
restore = main.MockOsStdout(&fakeStdout) | ||
defer restore() | ||
|
||
err := main.Run() | ||
assert.NoError(t, err) | ||
// we expect at least this canary | ||
assert.Contains(t, fakeStdout.String(), "rhel-10.0 type:qcow2 arch:x86_64\n") | ||
// output is sorted, i.e. 8.9 comes before 8.10 | ||
assert.Regexp(t, `(?ms)rhel-8.9.*rhel-8.10`, fakeStdout.String()) | ||
} | ||
} | ||
|
||
func TestListImagesNoArgsOutputJSON(t *testing.T) { | ||
restore := main.MockNewRepoRegistry(testrepos.New) | ||
defer restore() | ||
|
||
restore = main.MockOsArgs([]string{"list-images", "--output=json"}) | ||
defer restore() | ||
|
||
var fakeStdout bytes.Buffer | ||
restore = main.MockOsStdout(&fakeStdout) | ||
defer restore() | ||
|
||
err := main.Run() | ||
assert.NoError(t, err) | ||
|
||
// smoke test only, we expect valid json and at least the | ||
// distro/arch/image_type keys in the json | ||
var jo []map[string]interface{} | ||
err = json.Unmarshal(fakeStdout.Bytes(), &jo) | ||
assert.NoError(t, err) | ||
res := jo[0] | ||
for _, key := range []string{"distro", "arch", "image_type"} { | ||
assert.NotNil(t, res[key]) | ||
} | ||
} | ||
|
||
func TestListImagesFilteringSmoke(t *testing.T) { | ||
restore := main.MockNewRepoRegistry(testrepos.New) | ||
defer restore() | ||
|
||
restore = main.MockOsArgs([]string{"list-images", "--filter=centos*"}) | ||
defer restore() | ||
|
||
var fakeStdout bytes.Buffer | ||
restore = main.MockOsStdout(&fakeStdout) | ||
defer restore() | ||
|
||
err := main.Run() | ||
assert.NoError(t, err) | ||
// we have centos | ||
assert.Contains(t, fakeStdout.String(), "centos-9 type:qcow2 arch:x86_64\n") | ||
// but not rhel | ||
assert.NotContains(t, fakeStdout.String(), "rhel") | ||
} | ||
|
||
func TestBadCmdErrorsNoExtraCobraNoise(t *testing.T) { | ||
var fakeStderr bytes.Buffer | ||
restore := main.MockOsStderr(&fakeStderr) | ||
defer restore() | ||
|
||
restore = main.MockOsArgs([]string{"bad-command"}) | ||
defer restore() | ||
|
||
err := main.Run() | ||
assert.EqualError(t, err, `unknown command "bad-command" for "ibuilder"`) | ||
// no extra output from cobra | ||
assert.Equal(t, "", fakeStderr.String()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/osbuild/images/pkg/reporegistry" | ||
) | ||
|
||
// XXX: copied from "composer", should be exported there so | ||
// that we keep this in sync | ||
// XXX2: means we need to depend on osbuild-composer-common or a new rpm | ||
// that provides the relevant packages *or* we use go:embed (cf images#1038) | ||
var repositoryConfigs = []string{ | ||
"/etc/osbuild-composer", | ||
"/usr/share/osbuild-composer", | ||
} | ||
|
||
var newRepoRegistry = func() (*reporegistry.RepoRegistry, error) { | ||
// TODO: add a extraReposPaths here so that users can do | ||
// "ibuilder --repositories ..." to add a custom path(s) | ||
|
||
return reporegistry.New(repositoryConfigs) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
module github.com/osbuild/image-builder-cli | ||
|
||
go 1.23 | ||
|
||
require ( | ||
dario.cat/mergo v1.0.0 // indirect | ||
github.com/BurntSushi/toml v1.4.0 // indirect | ||
github.com/Microsoft/go-winio v0.6.2 // indirect | ||
github.com/Microsoft/hcsshim v0.12.5 // indirect | ||
github.com/VividCortex/ewma v1.2.0 // indirect | ||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect | ||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect | ||
github.com/containerd/cgroups/v3 v3.0.3 // indirect | ||
github.com/containerd/errdefs v0.1.0 // indirect | ||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect | ||
github.com/containers/common v0.60.4 // indirect | ||
github.com/containers/image/v5 v5.32.2 // indirect | ||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect | ||
github.com/containers/ocicrypt v1.2.0 // indirect | ||
github.com/containers/storage v1.55.0 // indirect | ||
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect | ||
github.com/cyphar/filepath-securejoin v0.3.1 // indirect | ||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect | ||
github.com/distribution/reference v0.6.0 // indirect | ||
github.com/docker/distribution v2.8.3+incompatible // indirect | ||
github.com/docker/docker v27.1.1+incompatible // indirect | ||
github.com/docker/docker-credential-helpers v0.8.2 // indirect | ||
github.com/docker/go-connections v0.5.0 // indirect | ||
github.com/docker/go-units v0.5.0 // indirect | ||
github.com/felixge/httpsnoop v1.0.4 // indirect | ||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect | ||
github.com/go-logr/logr v1.4.2 // indirect | ||
github.com/go-logr/stdr v1.2.2 // indirect | ||
github.com/go-openapi/analysis v0.23.0 // indirect | ||
github.com/go-openapi/errors v0.22.0 // indirect | ||
github.com/go-openapi/jsonpointer v0.21.0 // indirect | ||
github.com/go-openapi/jsonreference v0.21.0 // indirect | ||
github.com/go-openapi/loads v0.22.0 // indirect | ||
github.com/go-openapi/runtime v0.28.0 // indirect | ||
github.com/go-openapi/spec v0.21.0 // indirect | ||
github.com/go-openapi/strfmt v0.23.0 // indirect | ||
github.com/go-openapi/swag v0.23.0 // indirect | ||
github.com/go-openapi/validate v0.24.0 // indirect | ||
github.com/gobwas/glob v0.2.3 // indirect | ||
github.com/gogo/protobuf v1.3.2 // indirect | ||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect | ||
github.com/golang/protobuf v1.5.4 // indirect | ||
github.com/google/go-containerregistry v0.20.0 // indirect | ||
github.com/google/go-intervals v0.0.2 // indirect | ||
github.com/google/uuid v1.6.0 // indirect | ||
github.com/gorilla/mux v1.8.1 // indirect | ||
github.com/hashicorp/errwrap v1.1.0 // indirect | ||
github.com/hashicorp/go-multierror v1.1.1 // indirect | ||
github.com/hashicorp/go-version v1.7.0 // indirect | ||
github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||
github.com/josharian/intern v1.0.0 // indirect | ||
github.com/json-iterator/go v1.1.12 // indirect | ||
github.com/klauspost/compress v1.17.9 // indirect | ||
github.com/klauspost/pgzip v1.2.6 // indirect | ||
github.com/letsencrypt/boulder v0.0.0-20240418210053-89b07f4543e0 // indirect | ||
github.com/mailru/easyjson v0.7.7 // indirect | ||
github.com/mattn/go-runewidth v0.0.16 // indirect | ||
github.com/mattn/go-sqlite3 v1.14.22 // indirect | ||
github.com/miekg/pkcs11 v1.1.1 // indirect | ||
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect | ||
github.com/mitchellh/mapstructure v1.5.0 // indirect | ||
github.com/moby/docker-image-spec v1.3.1 // indirect | ||
github.com/moby/sys/mountinfo v0.7.2 // indirect | ||
github.com/moby/sys/user v0.2.0 // indirect | ||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||
github.com/modern-go/reflect2 v1.0.2 // indirect | ||
github.com/oklog/ulid v1.3.1 // indirect | ||
github.com/opencontainers/go-digest v1.0.0 // indirect | ||
github.com/opencontainers/image-spec v1.1.0 // indirect | ||
github.com/opencontainers/runtime-spec v1.2.0 // indirect | ||
github.com/opencontainers/selinux v1.11.0 // indirect | ||
github.com/osbuild/images v0.98.0 // indirect | ||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect | ||
github.com/pkg/errors v0.9.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect | ||
github.com/proglottis/gpgme v0.1.3 // indirect | ||
github.com/rivo/uniseg v0.4.7 // indirect | ||
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect | ||
github.com/sigstore/fulcio v1.4.5 // indirect | ||
github.com/sigstore/rekor v1.3.6 // indirect | ||
github.com/sigstore/sigstore v1.8.4 // indirect | ||
github.com/sirupsen/logrus v1.9.3 // indirect | ||
github.com/spf13/cobra v1.8.1 // indirect | ||
github.com/spf13/pflag v1.0.5 // indirect | ||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect | ||
github.com/stretchr/testify v1.9.0 // indirect | ||
github.com/sylabs/sif/v2 v2.18.0 // indirect | ||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect | ||
github.com/tchap/go-patricia/v2 v2.3.1 // indirect | ||
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect | ||
github.com/ulikunitz/xz v0.5.12 // indirect | ||
github.com/vbatts/tar-split v0.11.5 // indirect | ||
github.com/vbauerster/mpb/v8 v8.7.5 // indirect | ||
go.mongodb.org/mongo-driver v1.14.0 // indirect | ||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect | ||
go.opencensus.io v0.24.0 // indirect | ||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect | ||
go.opentelemetry.io/otel v1.29.0 // indirect | ||
go.opentelemetry.io/otel/metric v1.29.0 // indirect | ||
go.opentelemetry.io/otel/trace v1.29.0 // indirect | ||
golang.org/x/crypto v0.28.0 // indirect | ||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect | ||
golang.org/x/net v0.30.0 // indirect | ||
golang.org/x/sync v0.8.0 // indirect | ||
golang.org/x/sys v0.26.0 // indirect | ||
golang.org/x/term v0.25.0 // indirect | ||
golang.org/x/text v0.19.0 // indirect | ||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect | ||
google.golang.org/grpc v1.67.1 // indirect | ||
google.golang.org/protobuf v1.35.1 // indirect | ||
gopkg.in/ini.v1 v1.67.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
Oops, something went wrong.