Skip to content

Commit 3f8d98e

Browse files
committed
progress: use images/osbuild-exec as much as possible
The following moved into images: - OSBuildOptions; - construction of the osbuild command; - build log support; - synced writer; - monitor support. See osbuild/images#1966.
1 parent 687abf7 commit 3f8d98e

File tree

9 files changed

+48
-197
lines changed

9 files changed

+48
-197
lines changed

cmd/image-builder/build.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/osbuild/image-builder-cli/pkg/progress"
1010
"github.com/osbuild/images/pkg/imagefilter"
11+
"github.com/osbuild/images/pkg/osbuild"
1112
)
1213

1314
type buildOptions struct {
@@ -35,7 +36,7 @@ func buildImage(pbar progress.ProgressBar, res *imagefilter.Result, osbuildManif
3536
}
3637
}
3738

38-
osbuildOpts := &progress.OSBuildOptions{
39+
osbuildOpts := &osbuild.OSBuildOptions{
3940
StoreDir: opts.StoreDir,
4041
OutputDir: opts.OutputDir,
4142
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,5 @@ require (
141141
gopkg.in/ini.v1 v1.67.0 // indirect
142142
libvirt.org/go/libvirt v1.11006.0 // indirect
143143
)
144+
145+
replace github.com/osbuild/images => github.com/croissanne/images v0.0.0-20251023114920-81eefc443b5e

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ github.com/containers/storage v1.59.1/go.mod h1:KoAYHnAjP3/cTsRS+mmWZGkufSY2GACi
9090
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
9191
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
9292
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
93+
github.com/croissanne/images v0.0.0-20251023114920-81eefc443b5e h1:MuftBLwWLE8gWoJY1/P26tw0TL9HIkb4LcoTepZjVyY=
94+
github.com/croissanne/images v0.0.0-20251023114920-81eefc443b5e/go.mod h1:tZqcrs3eNUA0VPs1h3YCnbnpAskVVfo36CIi2USSfDs=
9395
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q=
9496
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
9597
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
@@ -245,10 +247,6 @@ github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplU
245247
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
246248
github.com/osbuild/blueprint v1.16.0 h1:f/kHih+xpeJ1v7wtIfzdHPZTsiXsqKeDQ1+rrue6298=
247249
github.com/osbuild/blueprint v1.16.0/go.mod h1:HPlJzkEl7q5g8hzaGksUk7ifFAy9QFw9LmzhuFOAVm4=
248-
github.com/osbuild/images v0.206.0 h1:F9G6dnqrURRUcWE2eWIPQLzHutSCT0OyWMcITK28uCQ=
249-
github.com/osbuild/images v0.206.0/go.mod h1:iF6bTLzBtyp9l27fexsD5AzwHEn9+bXF5Jr4HHQecmI=
250-
github.com/osbuild/images v0.209.0 h1:9BRf+N0op1WbQkc+7zVRBZxg4dqS4lty3i2stF3G9lo=
251-
github.com/osbuild/images v0.209.0/go.mod h1:tZqcrs3eNUA0VPs1h3YCnbnpAskVVfo36CIi2USSfDs=
252250
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
253251
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
254252
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

pkg/progress/command.go

Lines changed: 20 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,17 @@ import (
77
"io"
88
"log"
99
"os"
10-
"os/exec"
1110
"strings"
1211
"sync"
1312
"syscall"
1413

15-
"github.com/osbuild/images/pkg/datasizes"
1614
"github.com/osbuild/images/pkg/osbuild"
1715
)
1816

19-
type OSBuildOptions struct {
20-
StoreDir string
21-
OutputDir string
22-
ExtraEnv []string
23-
24-
// BuildLog writes the osbuild output to the given writer
25-
BuildLog io.Writer
26-
27-
CacheMaxSize int64
28-
}
29-
3017
// XXX: merge variant back into images/pkg/osbuild/osbuild-exec.go
31-
func RunOSBuild(pb ProgressBar, manifest []byte, exports []string, opts *OSBuildOptions) error {
18+
func RunOSBuild(pb ProgressBar, manifest []byte, exports []string, opts *osbuild.OSBuildOptions) error {
3219
if opts == nil {
33-
opts = &OSBuildOptions{}
20+
opts = &osbuild.OSBuildOptions{}
3421
}
3522

3623
// To keep maximum compatibility keep the old behavior to run osbuild
@@ -48,92 +35,37 @@ func RunOSBuild(pb ProgressBar, manifest []byte, exports []string, opts *OSBuild
4835
}
4936
}
5037

51-
func newOsbuildCmd(manifest []byte, exports []string, opts *OSBuildOptions) *exec.Cmd {
52-
cacheMaxSize := int64(20 * datasizes.GiB)
53-
if opts.CacheMaxSize != 0 {
54-
cacheMaxSize = opts.CacheMaxSize
55-
}
56-
cmd := exec.Command(
57-
osbuildCmd,
58-
"--store", opts.StoreDir,
59-
"--output-directory", opts.OutputDir,
60-
fmt.Sprintf("--cache-max-size=%v", cacheMaxSize),
61-
"-",
62-
)
63-
for _, export := range exports {
64-
cmd.Args = append(cmd.Args, "--export", export)
65-
}
66-
cmd.Env = append(os.Environ(), opts.ExtraEnv...)
67-
cmd.Stdin = bytes.NewBuffer(manifest)
68-
return cmd
69-
}
70-
71-
func runOSBuildNoProgress(pb ProgressBar, manifest []byte, exports []string, opts *OSBuildOptions) error {
72-
var stdout, stderr io.Writer
73-
74-
var writeMu sync.Mutex
75-
if opts.BuildLog == nil {
76-
// No external build log requested and we won't need an
77-
// internal one because all output goes directly to
78-
// stdout/stderr. This is for maximum compatibility with
79-
// the existing bootc-image-builder in "verbose" mode
80-
// where stdout, stderr come directly from osbuild.
81-
stdout = osStdout()
82-
stderr = osStderr()
83-
} else {
84-
// There is a slight wrinkle here: when requesting a
85-
// buildlog we can no longer write to separate
86-
// stdout/stderr streams without being racy and give
87-
// potential out-of-order output (which is very bad
88-
// and confusing in a log). The reason is that if
89-
// cmd.Std{out,err} are different "go" will start two
90-
// go-routine to monitor/copy those are racy when both
91-
// stdout,stderr output happens close together
92-
// (TestRunOSBuildWithBuildlog demos that). We cannot
93-
// have our cake and eat it so here we need to combine
94-
// osbuilds stderr into our stdout.
95-
mw := newSyncedWriter(&writeMu, io.MultiWriter(osStdout(), opts.BuildLog))
96-
stdout = mw
97-
stderr = mw
98-
}
99-
100-
cmd := newOsbuildCmd(manifest, exports, opts)
101-
cmd.Stdout = stdout
102-
cmd.Stderr = stderr
38+
func runOSBuildNoProgress(pb ProgressBar, manifest []byte, exports []string, opts *osbuild.OSBuildOptions) error {
39+
cmd := osbuild.NewOSBuildCmd(manifest, exports, opts)
10340
if err := cmd.Run(); err != nil {
10441
return fmt.Errorf("error running osbuild: %w", err)
10542
}
10643
return nil
10744
}
10845

109-
var osbuildCmd = "osbuild"
110-
111-
func runOSBuildWithProgress(pb ProgressBar, manifest []byte, exports []string, opts *OSBuildOptions) (err error) {
46+
func runOSBuildWithProgress(pb ProgressBar, manifest []byte, exports []string, opts *osbuild.OSBuildOptions) (err error) {
11247
rp, wp, err := os.Pipe()
11348
if err != nil {
11449
return fmt.Errorf("cannot create pipe for osbuild: %w", err)
11550
}
11651
defer rp.Close()
11752
defer wp.Close()
11853

119-
cmd := newOsbuildCmd(manifest, exports, opts)
120-
cmd.Args = append(cmd.Args, "--monitor=JSONSeqMonitor")
121-
cmd.Args = append(cmd.Args, "--monitor-fd=3")
12254

55+
opts.Monitor = osbuild.MonitorJSONSeq
56+
opts.MonitorFD = 3
57+
opts.MonitorFile = wp
12358
var stdio bytes.Buffer
124-
var mw, buildLog io.Writer
125-
var writeMu sync.Mutex
126-
if opts.BuildLog != nil {
127-
mw = newSyncedWriter(&writeMu, io.MultiWriter(&stdio, opts.BuildLog))
128-
buildLog = newSyncedWriter(&writeMu, opts.BuildLog)
129-
} else {
130-
mw = &stdio
59+
var mu sync.Mutex
60+
buildLog := opts.BuildLog
61+
opts.BuildLogMu = &mu
62+
if opts.BuildLog == nil {
63+
mw := &stdio
64+
opts.Stdout = mw
65+
opts.Stderr = mw
13166
buildLog = io.Discard
13267
}
133-
134-
cmd.Stdout = mw
135-
cmd.Stderr = mw
136-
cmd.ExtraFiles = []*os.File{wp}
68+
cmd := osbuild.NewOSBuildCmd(manifest, exports, opts)
13769

13870
osbuildStatus := osbuild.NewStatusScanner(rp)
13971
if err := cmd.Start(); err != nil {
@@ -186,10 +118,14 @@ func runOSBuildWithProgress(pb ProgressBar, manifest []byte, exports []string, o
186118
// external build log
187119
if st.Message != "" {
188120
tracesMsgs = append(tracesMsgs, st.Message)
121+
mu.Lock()
122+
defer mu.Unlock()
189123
fmt.Fprintln(buildLog, st.Message)
190124
}
191125
if st.Trace != "" {
192126
tracesMsgs = append(tracesMsgs, st.Trace)
127+
mu.Lock()
128+
defer mu.Unlock()
193129
fmt.Fprintln(buildLog, st.Trace)
194130
}
195131
}

pkg/progress/command_test.go

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
package progress_test
2-
32
import (
43
"bytes"
54
"fmt"
@@ -12,6 +11,7 @@ import (
1211
"github.com/stretchr/testify/assert"
1312

1413
"github.com/osbuild/image-builder-cli/pkg/progress"
14+
"github.com/osbuild/images/pkg/osbuild"
1515
)
1616

1717
func makeFakeOsbuild(t *testing.T, content string) string {
@@ -22,10 +22,7 @@ func makeFakeOsbuild(t *testing.T, content string) string {
2222
}
2323

2424
func TestRunOSBuildWithProgressErrorReporting(t *testing.T) {
25-
restore := progress.MockOsStderr(io.Discard)
26-
defer restore()
27-
28-
restore = progress.MockOsbuildCmd(makeFakeOsbuild(t, `
25+
restore := progress.MockOsbuildCmd(makeFakeOsbuild(t, `
2926
>&3 echo '{"message": "osbuild-stage-message"}'
3027
3128
echo osbuild-stdout-output
@@ -34,9 +31,13 @@ exit 112
3431
`))
3532
defer restore()
3633

34+
opts := &osbuild.OSBuildOptions{
35+
Stderr: io.Discard,
36+
}
37+
3738
pbar, err := progress.New("debug")
3839
assert.NoError(t, err)
39-
err = progress.RunOSBuild(pbar, []byte(`{"fake":"manifest"}`), nil, nil)
40+
err = progress.RunOSBuild(pbar, []byte(`{"fake":"manifest"}`), nil, opts)
4041
assert.EqualError(t, err, `error running osbuild: exit status 112
4142
BuildLog:
4243
osbuild-stage-message
@@ -93,20 +94,14 @@ sleep 0.1
9394
`))
9495
defer restore()
9596

96-
var fakeStdout, fakeStderr bytes.Buffer
97-
restore = progress.MockOsStdout(&fakeStdout)
98-
defer restore()
99-
restore = progress.MockOsStderr(&fakeStderr)
100-
defer restore()
101-
10297
pbar, err := progress.New("term")
10398
assert.NoError(t, err)
10499

105-
var buildLog bytes.Buffer
106-
opts := &progress.OSBuildOptions{
100+
var buildLog, stdout bytes.Buffer
101+
err = progress.RunOSBuild(pbar, []byte(`{"fake":"manifest"}`), nil, &osbuild.OSBuildOptions{
102+
Stdout: &stdout,
107103
BuildLog: &buildLog,
108-
}
109-
err = progress.RunOSBuild(pbar, []byte(`{"fake":"manifest"}`), nil, opts)
104+
})
110105
assert.NoError(t, err)
111106
expectedOutput := `osbuild-stdout-output
112107
osbuild-stderr-output
@@ -122,20 +117,14 @@ echo osbuild-stdout-output
122117
`))
123118
defer restore()
124119

125-
var fakeStdout, fakeStderr bytes.Buffer
126-
restore = progress.MockOsStdout(&fakeStdout)
127-
defer restore()
128-
restore = progress.MockOsStderr(&fakeStderr)
129-
defer restore()
130-
131120
pbar, err := progress.New("verbose")
132121
assert.NoError(t, err)
133122

134-
var buildLog bytes.Buffer
135-
opts := &progress.OSBuildOptions{
123+
var buildLog, stdout bytes.Buffer
124+
err = progress.RunOSBuild(pbar, []byte(`{"fake":"manifest"}`), nil, &osbuild.OSBuildOptions{
125+
Stdout: &stdout,
136126
BuildLog: &buildLog,
137-
}
138-
err = progress.RunOSBuild(pbar, []byte(`{"fake":"manifest"}`), nil, opts)
127+
})
139128
assert.NoError(t, err)
140129
expectedOutput := `osbuild-stdout-output
141130
osbuild-stderr-output
@@ -151,7 +140,7 @@ func TestRunOSBuildCacheMaxSize(t *testing.T) {
151140
pbar, err := progress.New("debug")
152141
assert.NoError(t, err)
153142

154-
osbuildOpts := &progress.OSBuildOptions{
143+
osbuildOpts := &osbuild.OSBuildOptions{
155144
CacheMaxSize: 77,
156145
}
157146
err = progress.RunOSBuild(pbar, []byte(`{"fake":"manifest"}`), nil, osbuildOpts)

pkg/progress/export_test.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package progress
22

33
import (
44
"io"
5+
6+
"github.com/osbuild/images/pkg/osbuild"
57
)
68

79
type (
@@ -11,17 +13,9 @@ type (
1113
)
1214

1315
var (
14-
NewSyncedWriter = newSyncedWriter
16+
OSStderr = osStderr
1517
)
1618

17-
func MockOsStdout(w io.Writer) (restore func()) {
18-
saved := osStdout
19-
osStdout = func() io.Writer { return w }
20-
return func() {
21-
osStdout = saved
22-
}
23-
}
24-
2519
func MockOsStderr(w io.Writer) (restore func()) {
2620
saved := osStderr
2721
osStderr = func() io.Writer { return w }
@@ -39,9 +33,9 @@ func MockIsattyIsTerminal(fn func(uintptr) bool) (restore func()) {
3933
}
4034

4135
func MockOsbuildCmd(s string) (restore func()) {
42-
saved := osbuildCmd
43-
osbuildCmd = s
36+
saved := osbuild.OSBuildCmd
37+
osbuild.OSBuildCmd = s
4438
return func() {
45-
osbuildCmd = saved
39+
osbuild.OSBuildCmd = saved
4640
}
4741
}

pkg/progress/progress.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ var (
2727
// Used for testing, this must be a function (instead of the usual
2828
// "var osStderr = os.Stderr" so that higher level libraries can test
2929
// this code by replacing "os.Stderr", e.g. testutil.CaptureStdio()
30-
var osStdout = func() io.Writer {
31-
return os.Stdout
32-
}
3330
var osStderr = func() io.Writer {
3431
return os.Stderr
3532
}

pkg/progress/syncwriter.go

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)