Browse code

daemon/server/backend: move build options to buildbackend

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/09/05 21:39:55
Showing 15 changed files
... ...
@@ -13,7 +13,6 @@ import (
13 13
 	buildkit "github.com/moby/moby/v2/daemon/internal/builder-next"
14 14
 	"github.com/moby/moby/v2/daemon/internal/image"
15 15
 	"github.com/moby/moby/v2/daemon/internal/stringid"
16
-	"github.com/moby/moby/v2/daemon/server/backend"
17 16
 	"github.com/moby/moby/v2/daemon/server/buildbackend"
18 17
 	"github.com/pkg/errors"
19 18
 	"google.golang.org/grpc"
... ...
@@ -27,7 +26,7 @@ type ImageComponent interface {
27 27
 
28 28
 // Builder defines interface for running a build
29 29
 type Builder interface {
30
-	Build(context.Context, backend.BuildConfig) (*builder.Result, error)
30
+	Build(context.Context, buildbackend.BuildConfig) (*builder.Result, error)
31 31
 }
32 32
 
33 33
 // Backend provides build functionality to the API router
... ...
@@ -51,7 +50,7 @@ func (b *Backend) RegisterGRPC(s *grpc.Server) {
51 51
 }
52 52
 
53 53
 // Build builds an image from a Source
54
-func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string, error) {
54
+func (b *Backend) Build(ctx context.Context, config buildbackend.BuildConfig) (string, error) {
55 55
 	options := config.Options
56 56
 	useBuildKit := options.Version == build.BuilderBuildKit
57 57
 
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/moby/moby/v2/daemon/internal/image"
14 14
 	"github.com/moby/moby/v2/daemon/internal/layer"
15 15
 	"github.com/moby/moby/v2/daemon/server/backend"
16
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
16 17
 	"github.com/opencontainers/go-digest"
17 18
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
18 19
 )
... ...
@@ -52,7 +53,7 @@ type Backend interface {
52 52
 
53 53
 // ImageBackend are the interface methods required from an image component
54 54
 type ImageBackend interface {
55
-	GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (Image, ROLayer, error)
55
+	GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts buildbackend.GetImageAndLayerOptions) (Image, ROLayer, error)
56 56
 }
57 57
 
58 58
 // ExecBackend contains the interface methods required for executing containers
... ...
@@ -18,7 +18,7 @@ import (
18 18
 	"github.com/moby/moby/v2/daemon/builder"
19 19
 	"github.com/moby/moby/v2/daemon/builder/remotecontext"
20 20
 	"github.com/moby/moby/v2/daemon/internal/stringid"
21
-	"github.com/moby/moby/v2/daemon/server/backend"
21
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
22 22
 	"github.com/moby/moby/v2/errdefs"
23 23
 	"github.com/moby/sys/user"
24 24
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -62,7 +62,7 @@ func NewBuildManager(b builder.Backend, identityMapping user.IdentityMapping) (*
62 62
 }
63 63
 
64 64
 // Build starts a new build from a BuildConfig
65
-func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (*builder.Result, error) {
65
+func (bm *BuildManager) Build(ctx context.Context, config buildbackend.BuildConfig) (*builder.Result, error) {
66 66
 	buildsTriggered.Inc()
67 67
 	if config.Options.Dockerfile == "" {
68 68
 		config.Options.Dockerfile = builder.DefaultDockerfileName
... ...
@@ -100,7 +100,7 @@ func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (
100 100
 type builderOptions struct {
101 101
 	Options        *build.ImageBuildOptions
102 102
 	Backend        builder.Backend
103
-	ProgressWriter backend.ProgressWriter
103
+	ProgressWriter buildbackend.ProgressWriter
104 104
 	PathCache      pathCache
105 105
 	IDMapping      user.IdentityMapping
106 106
 }
... ...
@@ -112,7 +112,7 @@ type Builder struct {
112 112
 
113 113
 	Stdout io.Writer
114 114
 	Stderr io.Writer
115
-	Aux    backend.AuxEmitter
115
+	Aux    buildbackend.AuxEmitter
116 116
 	Output io.Writer
117 117
 
118 118
 	docker builder.Backend
... ...
@@ -217,7 +217,7 @@ func (b *Builder) build(ctx context.Context, source builder.Source, dockerfile *
217 217
 	return &builder.Result{ImageID: state.imageID, FromImage: state.baseImage}, nil
218 218
 }
219 219
 
220
-func emitImageID(aux backend.AuxEmitter, state *dispatchState) error {
220
+func emitImageID(aux buildbackend.AuxEmitter, state *dispatchState) error {
221 221
 	if aux == nil || state.imageID == "" {
222 222
 		return nil
223 223
 	}
... ...
@@ -8,7 +8,7 @@ import (
8 8
 	"github.com/containerd/platforms"
9 9
 	"github.com/moby/moby/v2/daemon/builder"
10 10
 	dockerimage "github.com/moby/moby/v2/daemon/internal/image"
11
-	"github.com/moby/moby/v2/daemon/server/backend"
11
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
12 12
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
13 13
 	"github.com/pkg/errors"
14 14
 )
... ...
@@ -25,15 +25,15 @@ type imageSources struct {
25 25
 
26 26
 func newImageSources(options builderOptions) *imageSources {
27 27
 	getAndMount := func(ctx context.Context, idOrRef string, localOnly bool, platform *ocispec.Platform) (builder.Image, builder.ROLayer, error) {
28
-		pullOption := backend.PullOptionNoPull
28
+		pullOption := buildbackend.PullOptionNoPull
29 29
 		if !localOnly {
30 30
 			if options.Options.PullParent {
31
-				pullOption = backend.PullOptionForcePull
31
+				pullOption = buildbackend.PullOptionForcePull
32 32
 			} else {
33
-				pullOption = backend.PullOptionPreferLocal
33
+				pullOption = buildbackend.PullOptionPreferLocal
34 34
 			}
35 35
 		}
36
-		return options.Backend.GetImageAndReleasableLayer(ctx, idOrRef, backend.GetImageAndLayerOptions{
36
+		return options.Backend.GetImageAndReleasableLayer(ctx, idOrRef, buildbackend.GetImageAndLayerOptions{
37 37
 			PullOption: pullOption,
38 38
 			AuthConfig: options.Options.AuthConfigs,
39 39
 			Output:     options.ProgressWriter.Output,
... ...
@@ -14,7 +14,7 @@ import (
14 14
 	"github.com/moby/moby/v2/daemon/builder/remotecontext"
15 15
 	"github.com/moby/moby/v2/daemon/internal/image"
16 16
 	"github.com/moby/moby/v2/daemon/internal/layer"
17
-	"github.com/moby/moby/v2/daemon/server/backend"
17
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
18 18
 	"github.com/opencontainers/go-digest"
19 19
 	"gotest.tools/v3/assert"
20 20
 	is "gotest.tools/v3/assert/cmp"
... ...
@@ -75,7 +75,7 @@ func readAndCheckDockerfile(t *testing.T, testName, contextDir, dockerfilePath,
75 75
 		dockerfilePath = builder.DefaultDockerfileName
76 76
 	}
77 77
 
78
-	config := backend.BuildConfig{
78
+	config := buildbackend.BuildConfig{
79 79
 		Options: &build.ImageBuildOptions{Dockerfile: dockerfilePath},
80 80
 		Source:  tarStream,
81 81
 	}
... ...
@@ -12,6 +12,7 @@ import (
12 12
 	"github.com/moby/moby/v2/daemon/internal/image"
13 13
 	"github.com/moby/moby/v2/daemon/internal/layer"
14 14
 	"github.com/moby/moby/v2/daemon/server/backend"
15
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
15 16
 	"github.com/opencontainers/go-digest"
16 17
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
17 18
 )
... ...
@@ -62,7 +63,7 @@ func (m *MockBackend) CopyOnBuild(containerID string, destPath string, srcRoot s
62 62
 	return nil
63 63
 }
64 64
 
65
-func (m *MockBackend) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
65
+func (m *MockBackend) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts buildbackend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
66 66
 	if m.getImageFunc != nil {
67 67
 		return m.getImageFunc(refOrID)
68 68
 	}
... ...
@@ -15,7 +15,7 @@ import (
15 15
 	"github.com/moby/buildkit/frontend/dockerfile/parser"
16 16
 	"github.com/moby/moby/v2/daemon/builder"
17 17
 	"github.com/moby/moby/v2/daemon/builder/remotecontext/urlutil"
18
-	"github.com/moby/moby/v2/daemon/server/backend"
18
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
19 19
 	"github.com/moby/moby/v2/errdefs"
20 20
 	"github.com/moby/patternmatcher"
21 21
 	"github.com/moby/patternmatcher/ignorefile"
... ...
@@ -28,7 +28,7 @@ const ClientSessionRemote = "client-session"
28 28
 
29 29
 // Detect returns a context and dockerfile from remote location or local
30 30
 // archive.
31
-func Detect(config backend.BuildConfig) (remote builder.Source, dockerfile *parser.Result, _ error) {
31
+func Detect(config buildbackend.BuildConfig) (remote builder.Source, dockerfile *parser.Result, _ error) {
32 32
 	remoteURL := config.Options.RemoteContext
33 33
 	switch {
34 34
 	case remoteURL == "":
... ...
@@ -33,6 +33,7 @@ import (
33 33
 	"github.com/moby/moby/v2/daemon/internal/layer"
34 34
 	"github.com/moby/moby/v2/daemon/internal/stringid"
35 35
 	"github.com/moby/moby/v2/daemon/server/backend"
36
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
36 37
 	"github.com/moby/moby/v2/errdefs"
37 38
 	"github.com/opencontainers/go-digest"
38 39
 	"github.com/opencontainers/image-spec/identity"
... ...
@@ -64,7 +65,7 @@ const (
64 64
 // GetImageAndReleasableLayer returns an image and releaseable layer for a
65 65
 // reference or ID. Every call to GetImageAndReleasableLayer MUST call
66 66
 // releasableLayer.Release() to prevent leaking of layers.
67
-func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
67
+func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts buildbackend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
68 68
 	if refOrID == "" { // FROM scratch
69 69
 		if runtime.GOOS == "windows" {
70 70
 			return nil, nil, errors.New(`"FROM scratch" is not supported on Windows`)
... ...
@@ -80,10 +81,10 @@ func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID s
80 80
 		}, nil
81 81
 	}
82 82
 
83
-	if opts.PullOption != backend.PullOptionForcePull {
83
+	if opts.PullOption != buildbackend.PullOptionForcePull {
84 84
 		// TODO(laurazard): same as below
85 85
 		img, err := i.GetImage(ctx, refOrID, backend.GetImageOpts{Platform: opts.Platform})
86
-		if err != nil && opts.PullOption == backend.PullOptionNoPull {
86
+		if err != nil && opts.PullOption == buildbackend.PullOptionNoPull {
87 87
 			return nil, nil, err
88 88
 		}
89 89
 		imgDesc, err := i.resolveDescriptor(ctx, refOrID)
... ...
@@ -16,6 +16,7 @@ import (
16 16
 	"github.com/moby/moby/v2/daemon/internal/image"
17 17
 	"github.com/moby/moby/v2/daemon/internal/layer"
18 18
 	"github.com/moby/moby/v2/daemon/server/backend"
19
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
19 20
 	"github.com/moby/moby/v2/daemon/server/imagebackend"
20 21
 	"github.com/opencontainers/go-digest"
21 22
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
... ...
@@ -48,7 +49,7 @@ type ImageService interface {
48 48
 
49 49
 	// Layers
50 50
 
51
-	GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error)
51
+	GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts buildbackend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error)
52 52
 	CreateLayer(container *container.Container, initFunc layer.MountInit) (container.RWLayer, error)
53 53
 	CreateLayerFromImage(img *image.Image, layerName string, rwLayerOpts *layer.CreateRWLayerOpts) (container.RWLayer, error)
54 54
 	GetLayerByID(cid string) (container.RWLayer, error)
... ...
@@ -17,6 +17,7 @@ import (
17 17
 	"github.com/moby/moby/v2/daemon/internal/layer"
18 18
 	"github.com/moby/moby/v2/daemon/internal/stringid"
19 19
 	"github.com/moby/moby/v2/daemon/server/backend"
20
+	"github.com/moby/moby/v2/daemon/server/buildbackend"
20 21
 	"github.com/opencontainers/go-digest"
21 22
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
22 23
 	"github.com/pkg/errors"
... ...
@@ -195,7 +196,7 @@ Please notify the image author to correct the configuration.`,
195 195
 // GetImageAndReleasableLayer returns an image and releaseable layer for a reference or ID.
196 196
 // Every call to GetImageAndReleasableLayer MUST call releasableLayer.Release() to prevent
197 197
 // leaking of layers.
198
-func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
198
+func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts buildbackend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
199 199
 	if refOrID == "" { // FROM scratch
200 200
 		if runtime.GOOS == "windows" {
201 201
 			return nil, nil, errors.New(`"FROM scratch" is not supported on Windows`)
... ...
@@ -209,9 +210,9 @@ func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID s
209 209
 		return nil, lyr, err
210 210
 	}
211 211
 
212
-	if opts.PullOption != backend.PullOptionForcePull {
212
+	if opts.PullOption != buildbackend.PullOptionForcePull {
213 213
 		img, err := i.GetImage(ctx, refOrID, backend.GetImageOpts{Platform: opts.Platform})
214
-		if err != nil && opts.PullOption == backend.PullOptionNoPull {
214
+		if err != nil && opts.PullOption == buildbackend.PullOptionNoPull {
215 215
 			return nil, nil, err
216 216
 		}
217 217
 		if err != nil && !cerrdefs.IsNotFound(err) {
... ...
@@ -32,7 +32,6 @@ import (
32 32
 	"github.com/moby/moby/v2/daemon/internal/timestamp"
33 33
 	"github.com/moby/moby/v2/daemon/libnetwork"
34 34
 	"github.com/moby/moby/v2/daemon/pkg/opts"
35
-	"github.com/moby/moby/v2/daemon/server/backend"
36 35
 	"github.com/moby/moby/v2/daemon/server/buildbackend"
37 36
 	"github.com/moby/moby/v2/errdefs"
38 37
 	"github.com/moby/sys/user"
... ...
@@ -243,7 +242,7 @@ func (b *Builder) Prune(ctx context.Context, opts buildbackend.CachePruneOptions
243 243
 }
244 244
 
245 245
 // Build executes a build request
246
-func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.Result, error) {
246
+func (b *Builder) Build(ctx context.Context, opt buildbackend.BuildConfig) (*builder.Result, error) {
247 247
 	if len(opt.Options.Outputs) > 1 {
248 248
 		return nil, errors.Errorf("multiple outputs not supported")
249 249
 	}
250 250
deleted file mode 100644
... ...
@@ -1,50 +0,0 @@
1
-package backend
2
-
3
-import (
4
-	"io"
5
-
6
-	"github.com/moby/moby/api/types/build"
7
-	"github.com/moby/moby/api/types/registry"
8
-	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
9
-)
10
-
11
-// PullOption defines different modes for accessing images
12
-type PullOption int
13
-
14
-const (
15
-	// PullOptionNoPull only returns local images
16
-	PullOptionNoPull PullOption = iota
17
-	// PullOptionForcePull always tries to pull a ref from the registry first
18
-	PullOptionForcePull
19
-	// PullOptionPreferLocal uses local image if it exists, otherwise pulls
20
-	PullOptionPreferLocal
21
-)
22
-
23
-// ProgressWriter is a data object to transport progress streams to the client
24
-type ProgressWriter struct {
25
-	Output             io.Writer
26
-	StdoutFormatter    io.Writer
27
-	StderrFormatter    io.Writer
28
-	AuxFormatter       AuxEmitter
29
-	ProgressReaderFunc func(io.ReadCloser) io.ReadCloser
30
-}
31
-
32
-// AuxEmitter is an interface for emitting aux messages during build progress
33
-type AuxEmitter interface {
34
-	Emit(string, any) error
35
-}
36
-
37
-// BuildConfig is the configuration used by a BuildManager to start a build
38
-type BuildConfig struct {
39
-	Source         io.ReadCloser
40
-	ProgressWriter ProgressWriter
41
-	Options        *build.ImageBuildOptions
42
-}
43
-
44
-// GetImageAndLayerOptions are the options supported by GetImageAndReleasableLayer
45
-type GetImageAndLayerOptions struct {
46
-	PullOption PullOption
47
-	AuthConfig map[string]registry.AuthConfig
48
-	Output     io.Writer
49
-	Platform   *ocispec.Platform
50
-}
... ...
@@ -1,6 +1,14 @@
1 1
 package buildbackend
2 2
 
3
-import "github.com/moby/moby/api/types/filters"
3
+import (
4
+	"io"
5
+
6
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
7
+
8
+	"github.com/moby/moby/api/types/build"
9
+	"github.com/moby/moby/api/types/filters"
10
+	"github.com/moby/moby/api/types/registry"
11
+)
4 12
 
5 13
 type CachePruneOptions struct {
6 14
 	All           bool
... ...
@@ -9,3 +17,44 @@ type CachePruneOptions struct {
9 9
 	MinFreeSpace  int64
10 10
 	Filters       filters.Args
11 11
 }
12
+
13
+// PullOption defines different modes for accessing images
14
+type PullOption int
15
+
16
+const (
17
+	// PullOptionNoPull only returns local images
18
+	PullOptionNoPull PullOption = iota
19
+	// PullOptionForcePull always tries to pull a ref from the registry first
20
+	PullOptionForcePull
21
+	// PullOptionPreferLocal uses local image if it exists, otherwise pulls
22
+	PullOptionPreferLocal
23
+)
24
+
25
+// ProgressWriter is a data object to transport progress streams to the client
26
+type ProgressWriter struct {
27
+	Output             io.Writer
28
+	StdoutFormatter    io.Writer
29
+	StderrFormatter    io.Writer
30
+	AuxFormatter       AuxEmitter
31
+	ProgressReaderFunc func(io.ReadCloser) io.ReadCloser
32
+}
33
+
34
+// AuxEmitter is an interface for emitting aux messages during build progress
35
+type AuxEmitter interface {
36
+	Emit(string, any) error
37
+}
38
+
39
+// BuildConfig is the configuration used by a BuildManager to start a build
40
+type BuildConfig struct {
41
+	Source         io.ReadCloser
42
+	ProgressWriter ProgressWriter
43
+	Options        *build.ImageBuildOptions
44
+}
45
+
46
+// GetImageAndLayerOptions are the options supported by GetImageAndReleasableLayer
47
+type GetImageAndLayerOptions struct {
48
+	PullOption PullOption
49
+	AuthConfig map[string]registry.AuthConfig
50
+	Output     io.Writer
51
+	Platform   *ocispec.Platform
52
+}
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"context"
5 5
 
6 6
 	"github.com/moby/moby/api/types/build"
7
-	"github.com/moby/moby/v2/daemon/server/backend"
8 7
 	"github.com/moby/moby/v2/daemon/server/buildbackend"
9 8
 )
10 9
 
... ...
@@ -12,7 +11,7 @@ import (
12 12
 type Backend interface {
13 13
 	// Build a Docker image returning the id of the image
14 14
 	// TODO: make this return a reference instead of string
15
-	Build(context.Context, backend.BuildConfig) (string, error)
15
+	Build(context.Context, buildbackend.BuildConfig) (string, error)
16 16
 
17 17
 	// PruneCache prunes the build cache.
18 18
 	PruneCache(context.Context, buildbackend.CachePruneOptions) (*build.CachePruneReport, error)
... ...
@@ -23,7 +23,6 @@ import (
23 23
 	"github.com/moby/moby/api/types/filters"
24 24
 	"github.com/moby/moby/api/types/registry"
25 25
 	"github.com/moby/moby/api/types/versions"
26
-	"github.com/moby/moby/v2/daemon/server/backend"
27 26
 	"github.com/moby/moby/v2/daemon/server/buildbackend"
28 27
 	"github.com/moby/moby/v2/daemon/server/httputils"
29 28
 	"github.com/moby/moby/v2/pkg/ioutils"
... ...
@@ -314,7 +313,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
314 314
 
315 315
 	wantAux := versions.GreaterThanOrEqualTo(version, "1.30")
316 316
 
317
-	imgID, err := br.backend.Build(ctx, backend.BuildConfig{
317
+	imgID, err := br.backend.Build(ctx, buildbackend.BuildConfig{
318 318
 		Source:         body,
319 319
 		Options:        buildOptions,
320 320
 		ProgressWriter: buildProgressWriter(out, wantAux, createProgressReader),
... ...
@@ -360,7 +359,7 @@ func (s *syncWriter) Write(b []byte) (int, error) {
360 360
 	return s.w.Write(b)
361 361
 }
362 362
 
363
-func buildProgressWriter(out io.Writer, wantAux bool, createProgressReader func(io.ReadCloser) io.ReadCloser) backend.ProgressWriter {
363
+func buildProgressWriter(out io.Writer, wantAux bool, createProgressReader func(io.ReadCloser) io.ReadCloser) buildbackend.ProgressWriter {
364 364
 	// see https://github.com/moby/moby/pull/21406
365 365
 	out = &syncWriter{w: out}
366 366
 
... ...
@@ -369,7 +368,7 @@ func buildProgressWriter(out io.Writer, wantAux bool, createProgressReader func(
369 369
 		aux = &streamformatter.AuxFormatter{Writer: out}
370 370
 	}
371 371
 
372
-	return backend.ProgressWriter{
372
+	return buildbackend.ProgressWriter{
373 373
 		Output:             out,
374 374
 		StdoutFormatter:    streamformatter.NewStdoutWriter(out),
375 375
 		StderrFormatter:    streamformatter.NewStderrWriter(out),