Add --metadata-file flag to output build metadata

Signed-off-by: Jesse Rittner <rittneje@gmail.com>
v0.9
Jesse Rittner 2021-04-28 22:08:53 -04:00
parent 3e808950fc
commit 0406194498
4 changed files with 93 additions and 1 deletions

View File

@ -374,6 +374,20 @@ consider client-side load balancing using consistent hashing.
See [`./examples/kubernetes/consistenthash`](./examples/kubernetes/consistenthash).
## Metadata
To output build metadata such as the image digest, pass the `--metadata-file` flag.
The metadata will be written as a JSON object to the specified file.
The directory of the specified file must already exist and be writable.
```
buildctl build ... --metadata-file metadata.json
```
```
{"containerimage.digest": "sha256:ea0cfb27fd41ea0405d3095880c1efa45710f5bcdddb7d7d5a7317ad4825ae14",...}
```
## Systemd socket activation
On Systemd based systems, you can communicate with the daemon via [Systemd socket activation](http://0pointer.de/blog/projects/socket-activation.html), use `buildkitd --addr fd://`.

View File

@ -6,6 +6,7 @@ import (
"io"
"os"
"github.com/containerd/continuity"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/cmd/buildctl/build"
@ -101,6 +102,10 @@ var buildCommand = cli.Command{
Name: "ssh",
Usage: "Allow forwarding SSH agent to the builder. Format default|<id>[=<socket>|<key>[,<key>]]",
},
cli.StringFlag{
Name: "metadata-file",
Usage: "Output build metadata (e.g., image digest) to a file as JSON",
},
},
}
@ -290,7 +295,15 @@ func buildAction(clicontext *cli.Context) error {
for k, v := range resp.ExporterResponse {
logrus.Debugf("exporter response: %s=%s", k, v)
}
return err
metadataFile := clicontext.String("metadata-file")
if metadataFile != "" && resp.ExporterResponse != nil {
if err := writeMetadataFile(metadataFile, resp.ExporterResponse); err != nil {
return err
}
}
return nil
})
eg.Go(func() error {
@ -300,3 +313,11 @@ func buildAction(clicontext *cli.Context) error {
return eg.Wait()
}
func writeMetadataFile(filename string, exporterResponse map[string]string) error {
b, err := json.Marshal(exporterResponse)
if err != nil {
return err
}
return continuity.AtomicWriteFile(filename, b, 0666)
}

View File

@ -3,6 +3,7 @@ package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
@ -111,6 +112,61 @@ func testBuildContainerdExporter(t *testing.T, sb integration.Sandbox) {
require.Equal(t, ok, true)
}
func testBuildMetadataFile(t *testing.T, sb integration.Sandbox) {
st := llb.Image("busybox").
Run(llb.Shlex("sh -c 'echo -n bar > /foo'"))
rdr, err := marshal(st.Root())
require.NoError(t, err)
tmpDir, err := ioutil.TempDir("", "buildkit-buildctl")
require.NoError(t, err)
defer os.RemoveAll(tmpDir)
imageName := "example.com/moby/metadata:test"
metadataFile := filepath.Join(tmpDir, "metadata.json")
buildCmd := []string{
"build", "--progress=plain",
"--output type=image,name=" + imageName + ",push=false",
"--metadata-file", metadataFile,
}
cmd := sb.Cmd(strings.Join(buildCmd, " "))
cmd.Stdin = rdr
err = cmd.Run()
require.NoError(t, err)
require.FileExists(t, metadataFile)
metadataBytes, err := ioutil.ReadFile(metadataFile)
require.NoError(t, err)
var metadata map[string]string
err = json.Unmarshal(metadataBytes, &metadata)
require.NoError(t, err)
require.Equal(t, imageName, metadata["image.name"])
digest := metadata["containerimage.digest"]
require.NotEmpty(t, digest)
cdAddress := sb.ContainerdAddress()
if cdAddress == "" {
t.Log("no containerd worker, skipping digest verification")
} else {
client, err := containerd.New(cdAddress, containerd.WithTimeout(60*time.Second))
require.NoError(t, err)
defer client.Close()
ctx := namespaces.WithNamespace(context.Background(), "buildkit")
img, err := client.GetImage(ctx, imageName)
require.NoError(t, err)
require.Equal(t, img.Metadata().Target.Digest.String(), digest)
}
}
func marshal(st llb.State) (io.Reader, error) {
def, err := st.Marshal(context.TODO())
if err != nil {

View File

@ -18,6 +18,7 @@ func TestCLIIntegration(t *testing.T) {
testBuildWithLocalFiles,
testBuildLocalExporter,
testBuildContainerdExporter,
testBuildMetadataFile,
testPrune,
testUsage,
},