mirror of
https://github.com/moby/buildkit.git
synced 2026-08-05 07:10:23 +00:00
Move client integration test declarations out of the large harness files into focused files for cache, exporters, sources, mounts, gateway behavior, and related client features. Keep registration lists grouped by source file, move non-gateway tests out of the gateway harness, and remove the now-empty build_test.go. This is intended as a mechanical split with no test logic changes. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
607 lines
16 KiB
Go
607 lines
16 KiB
Go
package client
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/containerd/containerd/v2/core/content"
|
|
"github.com/containerd/containerd/v2/plugins/content/local"
|
|
"github.com/containerd/platforms"
|
|
intoto "github.com/in-toto/in-toto-golang/in_toto"
|
|
"github.com/moby/buildkit/client/llb"
|
|
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
|
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
|
provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types"
|
|
"github.com/moby/buildkit/util/contentutil"
|
|
"github.com/moby/buildkit/util/iohelper"
|
|
"github.com/moby/buildkit/util/purl"
|
|
"github.com/moby/buildkit/util/testutil"
|
|
"github.com/moby/buildkit/util/testutil/integration"
|
|
"github.com/moby/buildkit/util/testutil/workers"
|
|
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
|
|
packageurl "github.com/package-url/packageurl-go"
|
|
"github.com/pkg/errors"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func testImageBlobSource(t *testing.T, sb integration.Sandbox) {
|
|
workers.CheckFeatureCompat(t, sb, workers.FeatureDirectPush)
|
|
requiresLinux(t)
|
|
c, err := New(sb.Context(), sb.Address())
|
|
require.NoError(t, err)
|
|
defer c.Close()
|
|
|
|
registry, err := sb.NewRegistry()
|
|
if errors.Is(err, integration.ErrRequirements) {
|
|
t.Skip(err.Error())
|
|
}
|
|
require.NoError(t, err)
|
|
|
|
st := llb.Image("alpine")
|
|
|
|
def, err := st.Marshal(sb.Context())
|
|
require.NoError(t, err)
|
|
|
|
name := registry + "/foo/blobtest:img"
|
|
|
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: "image",
|
|
Attrs: map[string]string{
|
|
"name": name,
|
|
"push": "true",
|
|
},
|
|
},
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
desc, provider, err := contentutil.ProviderFromRef(name)
|
|
require.NoError(t, err)
|
|
|
|
imgs, err := testutil.ReadImages(sb.Context(), provider, desc)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(imgs.Images))
|
|
mfst := imgs.Images[0].Manifest
|
|
require.GreaterOrEqual(t, len(mfst.Layers), 1)
|
|
|
|
l := mfst.Layers[0]
|
|
|
|
blob := llb.ImageBlob(registry+"/foo/blobtest@"+l.Digest.String(), llb.Filename("layer.tar.gz"), llb.Chown(123, 456))
|
|
st = llb.Image("alpine").Run(llb.Shlex(`sh -c 'sha256sum /layers/layer.tar.gz | cut -d" " -f0 > /out/checksum && stat -c "%u-%g-%s" /layers/layer.tar.gz > /out/stat'`), llb.AddMount("/layers", blob, llb.Readonly)).AddMount("/out", llb.Scratch())
|
|
|
|
def, err = st.Marshal(sb.Context())
|
|
require.NoError(t, err)
|
|
|
|
destDir := t.TempDir()
|
|
|
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
|
FrontendAttrs: map[string]string{
|
|
"attest:provenance": "",
|
|
},
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterLocal,
|
|
OutputDir: destDir,
|
|
},
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
dt, err := os.ReadFile(filepath.Join(destDir, "stat"))
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "123-456-"+strconv.FormatInt(l.Size, 10), strings.TrimSpace(string(dt)))
|
|
|
|
dt, err = os.ReadFile(filepath.Join(destDir, "checksum"))
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, l.Digest.Hex(), strings.TrimSpace(string(dt)))
|
|
|
|
provDt, err := os.ReadFile(filepath.Join(destDir, "provenance.json"))
|
|
require.NoError(t, err)
|
|
|
|
var stmt struct {
|
|
intoto.StatementHeader
|
|
Predicate provenancetypes.ProvenancePredicateSLSA1 `json:"predicate"`
|
|
}
|
|
require.NoError(t, json.Unmarshal(provDt, &stmt))
|
|
|
|
expectedName, err := purl.RefToPURL(packageurl.TypeDocker, registry+"/foo/blobtest@"+l.Digest.String(), nil)
|
|
require.NoError(t, err)
|
|
purlObj, err := packageurl.FromString(expectedName)
|
|
require.NoError(t, err)
|
|
purlObj.Qualifiers = append(purlObj.Qualifiers, packageurl.Qualifier{Key: "ref_type", Value: "blob"})
|
|
expectedName = purlObj.ToString()
|
|
|
|
found := false
|
|
for _, m := range stmt.Predicate.BuildDefinition.ResolvedDependencies {
|
|
if m.URI == expectedName {
|
|
found = true
|
|
require.Equal(t, l.Digest.Hex(), m.Digest["sha256"])
|
|
break
|
|
}
|
|
}
|
|
require.True(t, found, "expected to find %q in %+v", expectedName, stmt.Predicate.BuildDefinition.ResolvedDependencies)
|
|
}
|
|
|
|
func testNoTarOCIIndexMediaType(t *testing.T, sb integration.Sandbox) {
|
|
workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter)
|
|
c, err := New(sb.Context(), sb.Address())
|
|
require.NoError(t, err)
|
|
defer c.Close()
|
|
|
|
imgName := integration.UnixOrWindows("busybox:latest", "nanoserver:latest")
|
|
cmdStr := integration.UnixOrWindows(
|
|
`sh -c "echo -n hello > hello"`,
|
|
`cmd /C "echo hello> hello"`,
|
|
)
|
|
st := llb.Image(imgName).Run(llb.Shlex(cmdStr))
|
|
def, err := st.Marshal(sb.Context())
|
|
require.NoError(t, err)
|
|
|
|
destDir, err := os.MkdirTemp("", "buildkit")
|
|
require.NoError(t, err)
|
|
defer os.RemoveAll(destDir)
|
|
|
|
outDir := filepath.Join(destDir, "out.d")
|
|
require.NoError(t, err)
|
|
|
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterOCI,
|
|
Attrs: map[string]string{
|
|
"tar": "false",
|
|
},
|
|
OutputDir: outDir,
|
|
},
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
dt, err := os.ReadFile(filepath.Join(outDir, "index.json"))
|
|
require.NoError(t, err)
|
|
|
|
var index ocispecs.Index
|
|
err = json.Unmarshal(dt, &index)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "application/vnd.oci.image.index.v1+json", index.MediaType)
|
|
|
|
checkAllReleasable(t, c, sb, true)
|
|
}
|
|
|
|
func testOCIIndexMediatype(t *testing.T, sb integration.Sandbox) {
|
|
workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter)
|
|
c, err := New(sb.Context(), sb.Address())
|
|
require.NoError(t, err)
|
|
defer c.Close()
|
|
|
|
imgName := integration.UnixOrWindows("busybox:latest", "nanoserver:latest")
|
|
cmdStr := integration.UnixOrWindows(
|
|
`sh -c "echo -n hello > hello"`,
|
|
`cmd /C "echo hello> hello"`,
|
|
)
|
|
st := llb.Image(imgName).Run(llb.Shlex(cmdStr))
|
|
def, err := st.Marshal(sb.Context())
|
|
require.NoError(t, err)
|
|
|
|
destDir, err := os.MkdirTemp("", "buildkit")
|
|
require.NoError(t, err)
|
|
defer os.RemoveAll(destDir)
|
|
|
|
out := filepath.Join(destDir, "out.tar")
|
|
outW, err := os.Create(out)
|
|
require.NoError(t, err)
|
|
|
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterOCI,
|
|
Output: fixedWriteCloser(outW),
|
|
},
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
dt, err := os.ReadFile(out)
|
|
require.NoError(t, err)
|
|
|
|
m, err := testutil.ReadTarToMap(dt, false)
|
|
require.NoError(t, err)
|
|
|
|
indexDt, ok := m[ocispecs.ImageIndexFile]
|
|
require.True(t, ok)
|
|
|
|
var index ocispecs.Index
|
|
err = json.Unmarshal(indexDt.Data, &index)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "application/vnd.oci.image.index.v1+json", index.MediaType)
|
|
|
|
checkAllReleasable(t, c, sb, true)
|
|
}
|
|
|
|
func testOCILayoutBlobSource(t *testing.T, sb integration.Sandbox) {
|
|
workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter, workers.FeatureOCILayout)
|
|
requiresLinux(t)
|
|
c, err := New(sb.Context(), sb.Address())
|
|
require.NoError(t, err)
|
|
defer c.Close()
|
|
|
|
st := llb.Image("alpine")
|
|
def, err := st.Marshal(sb.Context())
|
|
require.NoError(t, err)
|
|
|
|
ociDir := t.TempDir()
|
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterOCI,
|
|
Attrs: map[string]string{
|
|
"tar": "false",
|
|
},
|
|
OutputDir: ociDir,
|
|
},
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
indexDt, err := os.ReadFile(filepath.Join(ociDir, ocispecs.ImageIndexFile))
|
|
require.NoError(t, err)
|
|
|
|
var index ocispecs.Index
|
|
err = json.Unmarshal(indexDt, &index)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(index.Manifests))
|
|
|
|
var mfst ocispecs.Manifest
|
|
mfstDt, err := os.ReadFile(filepath.Join(ociDir, "blobs/sha256", index.Manifests[0].Digest.Hex()))
|
|
require.NoError(t, err)
|
|
err = json.Unmarshal(mfstDt, &mfst)
|
|
require.NoError(t, err)
|
|
require.GreaterOrEqual(t, len(mfst.Layers), 1)
|
|
layer := mfst.Layers[0]
|
|
|
|
store, err := local.NewStore(ociDir)
|
|
require.NoError(t, err)
|
|
csID := "my-blob-content-store"
|
|
|
|
blob := llb.OCILayoutBlob("not/real@"+layer.Digest.String(), llb.ImageBlobOCIStore("", csID), llb.Filename("layer.tar.gz"), llb.Chown(123, 456))
|
|
st = llb.Image("alpine").Run(llb.Shlex(`sh -c 'sha256sum /layers/layer.tar.gz | cut -d" " -f0 > /out/checksum && stat -c "%u-%g-%s" /layers/layer.tar.gz > /out/stat'`), llb.AddMount("/layers", blob, llb.Readonly)).AddMount("/out", llb.Scratch())
|
|
|
|
def, err = st.Marshal(sb.Context())
|
|
require.NoError(t, err)
|
|
|
|
destDir := t.TempDir()
|
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
|
FrontendAttrs: map[string]string{
|
|
"attest:provenance": "",
|
|
},
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterLocal,
|
|
OutputDir: destDir,
|
|
},
|
|
},
|
|
OCIStores: map[string]content.Store{
|
|
csID: store,
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
dt, err := os.ReadFile(filepath.Join(destDir, "stat"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, "123-456-"+strconv.FormatInt(layer.Size, 10), strings.TrimSpace(string(dt)))
|
|
|
|
dt, err = os.ReadFile(filepath.Join(destDir, "checksum"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, layer.Digest.Hex(), strings.TrimSpace(string(dt)))
|
|
|
|
provDt, err := os.ReadFile(filepath.Join(destDir, "provenance.json"))
|
|
require.NoError(t, err)
|
|
|
|
var stmt struct {
|
|
intoto.StatementHeader
|
|
Predicate provenancetypes.ProvenancePredicateSLSA1 `json:"predicate"`
|
|
}
|
|
require.NoError(t, json.Unmarshal(provDt, &stmt))
|
|
|
|
expectedName, err := purl.RefToPURL(packageurl.TypeOCI, "not/real@"+layer.Digest.String(), nil)
|
|
require.NoError(t, err)
|
|
purlObj, err := packageurl.FromString(expectedName)
|
|
require.NoError(t, err)
|
|
purlObj.Qualifiers = append(purlObj.Qualifiers, packageurl.Qualifier{Key: "ref_type", Value: "blob"})
|
|
expectedName = purlObj.ToString()
|
|
|
|
found := false
|
|
for _, m := range stmt.Predicate.BuildDefinition.ResolvedDependencies {
|
|
if m.URI == expectedName {
|
|
found = true
|
|
require.Equal(t, layer.Digest.Hex(), m.Digest["sha256"])
|
|
break
|
|
}
|
|
}
|
|
require.True(t, found, "expected to find %q in %+v", expectedName, stmt.Predicate.BuildDefinition.ResolvedDependencies)
|
|
}
|
|
|
|
func testOCILayoutPlatformSource(t *testing.T, sb integration.Sandbox) {
|
|
workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter, workers.FeatureOCILayout)
|
|
requiresLinux(t)
|
|
c, err := New(context.TODO(), sb.Address())
|
|
require.NoError(t, err)
|
|
defer c.Close()
|
|
|
|
// create a tempdir where we will store the OCI layout
|
|
dir := t.TempDir()
|
|
|
|
platformsToTest := []string{"linux/amd64", "linux/arm64"}
|
|
|
|
frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
|
|
res := gateway.NewResult()
|
|
expPlatforms := &exptypes.Platforms{
|
|
Platforms: make([]exptypes.Platform, len(platformsToTest)),
|
|
}
|
|
for i, platform := range platformsToTest {
|
|
st := llb.Scratch().File(
|
|
llb.Mkfile("platform", 0600, []byte(platform)),
|
|
)
|
|
|
|
def, err := st.Marshal(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
r, err := c.Solve(ctx, gateway.SolveRequest{
|
|
Definition: def.ToPB(),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ref, err := r.SingleRef()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
_, err = ref.ToState()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res.AddRef(platform, ref)
|
|
|
|
expPlatforms.Platforms[i] = exptypes.Platform{
|
|
ID: platform,
|
|
Platform: platforms.MustParse(platform),
|
|
}
|
|
}
|
|
dt, err := json.Marshal(expPlatforms)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res.AddMeta(exptypes.ExporterPlatformsKey, dt)
|
|
|
|
return res, nil
|
|
}
|
|
attrs := map[string]string{}
|
|
outW := bytes.NewBuffer(nil)
|
|
_, err = c.Build(sb.Context(), SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterOCI,
|
|
Attrs: attrs,
|
|
Output: fixedWriteCloser(&iohelper.NopWriteCloser{Writer: outW}),
|
|
},
|
|
},
|
|
}, "", frontend, nil)
|
|
require.NoError(t, err)
|
|
|
|
// extract the tar stream to the directory as OCI layout
|
|
m, err := testutil.ReadTarToMap(outW.Bytes(), false)
|
|
require.NoError(t, err)
|
|
|
|
for filename, tarItem := range m {
|
|
fullFilename := path.Join(dir, filename)
|
|
err = os.MkdirAll(path.Dir(fullFilename), 0755)
|
|
require.NoError(t, err)
|
|
if tarItem.Header.FileInfo().IsDir() {
|
|
err = os.MkdirAll(fullFilename, 0755)
|
|
require.NoError(t, err)
|
|
} else {
|
|
err = os.WriteFile(fullFilename, tarItem.Data, 0644)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
var index ocispecs.Index
|
|
err = json.Unmarshal(m[ocispecs.ImageIndexFile].Data, &index)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(index.Manifests))
|
|
digest := index.Manifests[0].Digest
|
|
|
|
store, err := local.NewStore(dir)
|
|
require.NoError(t, err)
|
|
csID := "my-content-store"
|
|
|
|
destDir := t.TempDir()
|
|
|
|
frontendOCILayout := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
|
|
res := gateway.NewResult()
|
|
expPlatforms := &exptypes.Platforms{
|
|
Platforms: make([]exptypes.Platform, len(platformsToTest)),
|
|
}
|
|
for i, platform := range platformsToTest {
|
|
st := llb.OCILayout(fmt.Sprintf("not/real@%s", digest), llb.OCIStore("", csID))
|
|
|
|
def, err := st.Marshal(ctx, llb.Platform(platforms.MustParse(platform)))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
r, err := c.Solve(ctx, gateway.SolveRequest{
|
|
Definition: def.ToPB(),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ref, err := r.SingleRef()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
_, err = ref.ToState()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res.AddRef(platform, ref)
|
|
|
|
expPlatforms.Platforms[i] = exptypes.Platform{
|
|
ID: platform,
|
|
Platform: platforms.MustParse(platform),
|
|
}
|
|
}
|
|
dt, err := json.Marshal(expPlatforms)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res.AddMeta(exptypes.ExporterPlatformsKey, dt)
|
|
|
|
return res, nil
|
|
}
|
|
_, err = c.Build(sb.Context(), SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterLocal,
|
|
OutputDir: destDir,
|
|
},
|
|
},
|
|
OCIStores: map[string]content.Store{
|
|
csID: store,
|
|
},
|
|
}, "", frontendOCILayout, nil)
|
|
require.NoError(t, err)
|
|
|
|
for _, platform := range platformsToTest {
|
|
dt, err := os.ReadFile(filepath.Join(destDir, strings.ReplaceAll(platform, "/", "_"), "platform"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, []byte(platform), dt)
|
|
}
|
|
}
|
|
|
|
func testOCILayoutSource(t *testing.T, sb integration.Sandbox) {
|
|
workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter, workers.FeatureOCILayout)
|
|
c, err := New(context.TODO(), sb.Address())
|
|
require.NoError(t, err)
|
|
defer c.Close()
|
|
|
|
// create a tempdir where we will store the OCI layout
|
|
dir := t.TempDir()
|
|
|
|
// make an image that is exported there
|
|
imgName := integration.UnixOrWindows("busybox:latest", "nanoserver:latest")
|
|
busybox := llb.Image(imgName)
|
|
st := integration.UnixOrWindows(
|
|
llb.Scratch(),
|
|
llb.Image(imgName),
|
|
)
|
|
|
|
run := func(cmd string) {
|
|
st = busybox.Run(llb.Shlex(cmd), llb.Dir("/wd")).AddMount("/wd", st)
|
|
}
|
|
|
|
cmdPrefix := integration.UnixOrWindows(
|
|
`sh -c "echo -n`,
|
|
`cmd /C "echo`,
|
|
)
|
|
run(fmt.Sprintf(`%s first > foo"`, cmdPrefix))
|
|
run(fmt.Sprintf(`%s second > bar"`, cmdPrefix))
|
|
|
|
def, err := st.Marshal(sb.Context())
|
|
require.NoError(t, err)
|
|
|
|
outW := bytes.NewBuffer(nil)
|
|
attrs := map[string]string{}
|
|
_, err = c.Solve(sb.Context(), def, SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterOCI,
|
|
Attrs: attrs,
|
|
Output: fixedWriteCloser(&iohelper.NopWriteCloser{Writer: outW}),
|
|
},
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
// extract the tar stream to the directory as OCI layout
|
|
m, err := testutil.ReadTarToMap(outW.Bytes(), false)
|
|
require.NoError(t, err)
|
|
|
|
for filename, content := range m {
|
|
fullFilename := path.Join(dir, filename)
|
|
err = os.MkdirAll(path.Dir(fullFilename), 0755)
|
|
require.NoError(t, err)
|
|
if content.Header.FileInfo().IsDir() {
|
|
err = os.MkdirAll(fullFilename, 0755)
|
|
require.NoError(t, err)
|
|
} else {
|
|
err = os.WriteFile(fullFilename, content.Data, 0644)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
var index ocispecs.Index
|
|
err = json.Unmarshal(m[ocispecs.ImageIndexFile].Data, &index)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(index.Manifests))
|
|
digest := index.Manifests[0].Digest
|
|
|
|
store, err := local.NewStore(dir)
|
|
require.NoError(t, err)
|
|
|
|
// reference the OCI Layout in a build
|
|
// note that the key does not need to be the directory name, just something
|
|
// unique. since we are doing just one build with one remote here, we can
|
|
// give it any ID
|
|
csID := "my-content-store"
|
|
st = llb.OCILayout(fmt.Sprintf("not/real@%s", digest), llb.OCIStore("", csID))
|
|
|
|
def, err = st.Marshal(context.TODO())
|
|
require.NoError(t, err)
|
|
|
|
destDir := t.TempDir()
|
|
|
|
_, err = c.Solve(context.TODO(), def, SolveOpt{
|
|
Exports: []ExportEntry{
|
|
{
|
|
Type: ExporterLocal,
|
|
OutputDir: destDir,
|
|
},
|
|
},
|
|
OCIStores: map[string]content.Store{
|
|
csID: store,
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
dt, err := os.ReadFile(filepath.Join(destDir, "foo"))
|
|
require.NoError(t, err)
|
|
newLine := integration.UnixOrWindows("", " \r\n")
|
|
require.Equal(t, []byte("first"+newLine), dt)
|
|
|
|
dt, err = os.ReadFile(filepath.Join(destDir, "bar"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, []byte("second"+newLine), dt)
|
|
}
|