buildinfo: set frontend attrs to bridge result

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
master
CrazyMax 2022-02-11 17:42:54 +01:00
parent 7d0f8e4408
commit b2e5d1938d
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
6 changed files with 109 additions and 10 deletions

View File

@ -3,6 +3,8 @@ package client
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/base64"
"encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -55,6 +57,7 @@ func TestClientGatewayIntegration(t *testing.T) {
testClientGatewayContainerExtraHosts, testClientGatewayContainerExtraHosts,
testClientGatewayContainerSignal, testClientGatewayContainerSignal,
testWarnings, testWarnings,
testClientGatewayFrontendAttrs,
), integration.WithMirroredImages(integration.OfficialImages("busybox:latest"))) ), integration.WithMirroredImages(integration.OfficialImages("busybox:latest")))
integration.Run(t, integration.TestFuncs( integration.Run(t, integration.TestFuncs(
@ -1994,6 +1997,52 @@ func testClientGatewayContainerSignal(t *testing.T, sb integration.Sandbox) {
checkAllReleasable(t, c, sb, true) checkAllReleasable(t, c, sb, true)
} }
// moby/buildkit#2476
func testClientGatewayFrontendAttrs(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)
c, err := New(sb.Context(), sb.Address())
require.NoError(t, err)
defer c.Close()
attrs := map[string]string{"build-arg:foo": "bar"}
dtattrs, err := json.Marshal(attrs)
require.NoError(t, err)
b := func(ctx context.Context, c client.Client) (*client.Result, error) {
st := llb.Image("busybox:latest").Run(
llb.ReadonlyRootFS(),
llb.Args([]string{"/bin/sh", "-c", `echo hello`}),
)
def, err := st.Marshal(sb.Context())
if err != nil {
return nil, err
}
res, err := c.Solve(ctx, client.SolveRequest{
Definition: def.ToPB(),
FrontendOpt: attrs,
})
require.Contains(t, res.Metadata, "buildinfo.attrs")
require.Equal(t, res.Metadata["buildinfo.attrs"], dtattrs)
return res, err
}
res, err := c.Build(sb.Context(), SolveOpt{}, "", b, nil)
require.NoError(t, err)
require.Contains(t, res.ExporterResponse, exptypes.ExporterBuildInfo)
decbi, err := base64.StdEncoding.DecodeString(res.ExporterResponse[exptypes.ExporterBuildInfo])
require.NoError(t, err)
var bi binfotypes.BuildInfo
err = json.Unmarshal(decbi, &bi)
require.NoError(t, err)
require.Contains(t, bi.Attrs, "build-arg:foo")
require.Equal(t, "bar", bi.Attrs["build-arg:foo"])
checkAllReleasable(t, c, sb, true)
}
type nopCloser struct { type nopCloser struct {
io.Writer io.Writer
} }

View File

@ -148,6 +148,7 @@ func TestIntegration(t *testing.T) {
testRmSymlink, testRmSymlink,
testMoveParentDir, testMoveParentDir,
testBuildExportWithForeignLayer, testBuildExportWithForeignLayer,
testFrontendAttrs,
) )
tests = append(tests, diffOpTestCases()...) tests = append(tests, diffOpTestCases()...)
integration.Run(t, tests, mirrors) integration.Run(t, tests, mirrors)
@ -5038,6 +5039,40 @@ func testRelativeMountpoint(t *testing.T, sb integration.Sandbox) {
require.Equal(t, dt, []byte(id)) require.Equal(t, dt, []byte(id))
} }
// moby/buildkit#2476
func testFrontendAttrs(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)
c, err := New(sb.Context(), sb.Address())
require.NoError(t, err)
defer c.Close()
attrs := map[string]string{"build-arg:foo": "bar"}
dtattrs, err := json.Marshal(attrs)
require.NoError(t, err)
frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
st := llb.Image("busybox:latest").Run(
llb.Args([]string{"/bin/sh", "-c", `echo hello`}),
)
def, err := st.Marshal(sb.Context())
if err != nil {
return nil, err
}
res, err := c.Solve(ctx, gateway.SolveRequest{
Definition: def.ToPB(),
FrontendOpt: attrs,
})
require.Contains(t, res.Metadata, "buildinfo.attrs")
require.Equal(t, res.Metadata["buildinfo.attrs"], dtattrs)
return res, err
}
_, err = c.Build(sb.Context(), SolveOpt{}, "", frontend, nil)
require.NoError(t, err)
checkAllReleasable(t, c, sb, true)
}
func tmpdir(appliers ...fstest.Applier) (string, error) { func tmpdir(appliers ...fstest.Applier) (string, error) {
tmpdir, err := ioutil.TempDir("", "buildkit-client") tmpdir, err := ioutil.TempDir("", "buildkit-client")
if err != nil { if err != nil {

View File

@ -13,6 +13,7 @@ const (
ExporterImageDescriptorKey = "containerimage.descriptor" ExporterImageDescriptorKey = "containerimage.descriptor"
ExporterInlineCache = "containerimage.inlinecache" ExporterInlineCache = "containerimage.inlinecache"
ExporterBuildInfo = "containerimage.buildinfo" ExporterBuildInfo = "containerimage.buildinfo"
ExporterBuildInfoAttrs = "buildinfo.attrs"
ExporterPlatformsKey = "refs.platforms" ExporterPlatformsKey = "refs.platforms"
) )

View File

@ -2,6 +2,7 @@ package llbsolver
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"strings" "strings"
"sync" "sync"
@ -12,6 +13,7 @@ import (
"github.com/moby/buildkit/cache/remotecache" "github.com/moby/buildkit/cache/remotecache"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
"github.com/moby/buildkit/frontend" "github.com/moby/buildkit/frontend"
gw "github.com/moby/buildkit/frontend/gateway/client" gw "github.com/moby/buildkit/frontend/gateway/client"
"github.com/moby/buildkit/identity" "github.com/moby/buildkit/identity"
@ -142,8 +144,7 @@ func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest, sid st
if req.Definition != nil && req.Definition.Def != nil { if req.Definition != nil && req.Definition.Def != nil {
res = &frontend.Result{Ref: newResultProxy(b, req)} res = &frontend.Result{Ref: newResultProxy(b, req)}
if req.Evaluate { if req.Evaluate {
_, err := res.Ref.Result(ctx) _, err = res.Ref.Result(ctx)
return res, err
} }
} else if req.Frontend != "" { } else if req.Frontend != "" {
f, ok := b.frontends[req.Frontend] f, ok := b.frontends[req.Frontend]
@ -158,6 +159,16 @@ func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest, sid st
return &frontend.Result{}, nil return &frontend.Result{}, nil
} }
if res.Metadata == nil {
res.Metadata = make(map[string][]byte)
}
attrs, errm := json.Marshal(req.FrontendOpt)
if errm != nil {
return nil, errm
}
res.Metadata[exptypes.ExporterBuildInfoAttrs] = attrs
return return
} }

View File

@ -175,8 +175,7 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro
return nil, errors.Errorf("invalid reference: %T", r.Sys()) return nil, errors.Errorf("invalid reference: %T", r.Sys())
} }
inp.Ref = workerRef.ImmutableRef inp.Ref = workerRef.ImmutableRef
dtbi, err := buildinfo.Encode(ctx, req.Frontend, inp.Metadata[exptypes.ExporterBuildInfoAttrs], res.BuildSources(), inp.Metadata[exptypes.ExporterImageConfigKey])
dtbi, err := buildinfo.Encode(ctx, req, res.BuildSources(), inp.Metadata[exptypes.ExporterImageConfigKey])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -207,8 +206,7 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro
return nil, errors.Errorf("invalid reference: %T", r.Sys()) return nil, errors.Errorf("invalid reference: %T", r.Sys())
} }
m[k] = workerRef.ImmutableRef m[k] = workerRef.ImmutableRef
dtbi, err := buildinfo.Encode(ctx, req.Frontend, inp.Metadata[exptypes.ExporterBuildInfoAttrs], res.BuildSources(), inp.Metadata[fmt.Sprintf("%s/%s", exptypes.ExporterImageConfigKey, k)])
dtbi, err := buildinfo.Encode(ctx, req, res.BuildSources(), inp.Metadata[fmt.Sprintf("%s/%s", exptypes.ExporterImageConfigKey, k)])
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -8,7 +8,6 @@ import (
"strings" "strings"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/moby/buildkit/frontend"
"github.com/moby/buildkit/source" "github.com/moby/buildkit/source"
binfotypes "github.com/moby/buildkit/util/buildinfo/types" binfotypes "github.com/moby/buildkit/util/buildinfo/types"
"github.com/moby/buildkit/util/urlutil" "github.com/moby/buildkit/util/urlutil"
@ -26,7 +25,7 @@ func Decode(enc string) (bi binfotypes.BuildInfo, _ error) {
} }
// Encode encodes build info. // Encode encodes build info.
func Encode(ctx context.Context, req frontend.SolveRequest, buildSources map[string]string, imageConfig []byte) ([]byte, error) { func Encode(ctx context.Context, frontend string, frontendAttrs []byte, buildSources map[string]string, imageConfig []byte) ([]byte, error) {
icbi, err := FromImageConfig(imageConfig) icbi, err := FromImageConfig(imageConfig)
if err != nil { if err != nil {
return nil, err return nil, err
@ -35,9 +34,15 @@ func Encode(ctx context.Context, req frontend.SolveRequest, buildSources map[str
if err != nil { if err != nil {
return nil, err return nil, err
} }
attrs := make(map[string]string)
if frontendAttrs != nil {
if err := json.Unmarshal(frontendAttrs, &attrs); err != nil {
return nil, err
}
}
return json.Marshal(binfotypes.BuildInfo{ return json.Marshal(binfotypes.BuildInfo{
Frontend: req.Frontend, Frontend: frontend,
Attrs: filterAttrs(req.FrontendOpt), Attrs: filterAttrs(attrs),
Sources: srcs, Sources: srcs,
}) })
} }