Skip to content

Commit

Permalink
test: retry containerd initialization (aquasecurity#5597)
Browse files Browse the repository at this point in the history
Signed-off-by: knqyf263 <knqyf263@gmail.com>
  • Loading branch information
knqyf263 authored Nov 16, 2023
1 parent 1336223 commit b6fafa0
Showing 1 changed file with 65 additions and 67 deletions.
132 changes: 65 additions & 67 deletions pkg/fanal/test/integration/containerd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"compress/gzip"
"context"
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -14,7 +15,7 @@ import (
"testing"
"time"

"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/samber/lo"

"github.com/containerd/containerd"
"github.com/containerd/containerd/images"
Expand All @@ -23,9 +24,10 @@ import (
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
testcontainers "github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"

"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/applier"
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
aimage "github.com/aquasecurity/trivy/pkg/fanal/artifact/image"
Expand All @@ -34,13 +36,12 @@ import (
"github.com/aquasecurity/trivy/pkg/fanal/types"
)

func configureTestDataPaths(t *testing.T, namespace string) (string, string) {
func setupContainerd(t *testing.T, ctx context.Context, namespace string) *containerd.Client {
t.Helper()
tmpDir, err := os.MkdirTemp("/tmp", "fanal")
require.NoError(t, err)
tmpDir := t.TempDir()

containerdDir := filepath.Join(tmpDir, "containerd")
err = os.MkdirAll(containerdDir, os.ModePerm)
err := os.MkdirAll(containerdDir, os.ModePerm)
require.NoError(t, err)

socketPath := filepath.Join(containerdDir, "containerd.sock")
Expand All @@ -49,10 +50,29 @@ func configureTestDataPaths(t *testing.T, namespace string) (string, string) {
t.Setenv("CONTAINERD_ADDRESS", socketPath)
t.Setenv("CONTAINERD_NAMESPACE", namespace)

return tmpDir, socketPath
startContainerd(t, ctx, tmpDir)

// Retry up to 3 times until containerd is ready
var client *containerd.Client
iteration, _, err := lo.AttemptWhileWithDelay(3, 1*time.Second, func(int, time.Duration) (error, bool) {
client, err = containerd.New(socketPath)
if err != nil {
if !errors.Is(err, os.ErrPermission) {
return err, false // unexpected error
}
return err, true
}
t.Cleanup(func() {
assert.NoError(t, client.Close())
})
return nil, false
})
require.NoErrorf(t, err, "attempted %d times ", iteration)

return client
}

func startContainerd(t *testing.T, ctx context.Context, hostPath string) testcontainers.Container {
func startContainerd(t *testing.T, ctx context.Context, hostPath string) {
t.Helper()
t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true")
req := testcontainers.ContainerRequest{
Expand Down Expand Up @@ -84,26 +104,32 @@ func startContainerd(t *testing.T, ctx context.Context, hostPath string) testcon
})
require.NoError(t, err)

return containerdC
t.Cleanup(func() {
assert.NoError(t, containerdC.Terminate(ctx))
})
}

// Each of these tests imports an image and tags it with the name found in the
// `imageName` field. Then, the containerd store is searched by the reference
// provided in the `searchName` field.
func TestContainerd_SearchLocalStoreByNameOrDigest(t *testing.T) {
type testInstance struct {
name string
imageName string
searchName string
expectErr bool
// Each architecture needs different images and test cases.
// Currently only amd64 architecture is supported
if runtime.GOARCH != "amd64" {
t.Skip("'Containerd' test only supports amd64 architecture")
}

digest := "sha256:f12582b2f2190f350e3904462c1c23aaf366b4f76705e97b199f9bbded1d816a"
basename := "hello"
tag := "world"
importedImageOriginalName := "ghcr.io/aquasecurity/trivy-test-images:alpine-310"

tests := []testInstance{
tests := []struct {
name string
imageName string
searchName string
wantErr bool
}{
{
name: "familiarName:tag",
imageName: fmt.Sprintf("%s:%s", basename, tag),
Expand All @@ -128,13 +154,13 @@ func TestContainerd_SearchLocalStoreByNameOrDigest(t *testing.T) {
name: "other-registry.io/library/name:wrongTag should fail",
imageName: fmt.Sprintf("other-registry.io/library/%s:%s", basename, tag),
searchName: fmt.Sprintf("other-registry.io/library/%s:badtag", basename),
expectErr: true,
wantErr: true,
},
{
name: "other-registry.io/library/wrongName:tag should fail",
imageName: fmt.Sprintf("other-registry.io/library/%s:%s", basename, tag),
searchName: fmt.Sprintf("other-registry.io/library/badname:%s", tag),
expectErr: true,
wantErr: true,
},
{
name: "digest should succeed",
Expand All @@ -145,7 +171,7 @@ func TestContainerd_SearchLocalStoreByNameOrDigest(t *testing.T) {
name: "wrong digest should fail",
imageName: "",
searchName: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
expectErr: true,
wantErr: true,
},
{
name: "name@digest",
Expand All @@ -171,32 +197,19 @@ func TestContainerd_SearchLocalStoreByNameOrDigest(t *testing.T) {
name: "wrongName@digest should fail",
imageName: fmt.Sprintf("%s:%s", basename, tag),
searchName: fmt.Sprintf("badname@%s", digest),
expectErr: true,
wantErr: true,
},
{
name: "compound/wrongName@digest should fail",
imageName: fmt.Sprintf("compound/%s:%s", basename, tag),
searchName: fmt.Sprintf("compound/badname@%s", digest),
expectErr: true,
wantErr: true,
},
}
// Each architecture needs different images and test cases.
// Currently only amd64 architecture is supported
if runtime.GOARCH != "amd64" {
t.Skip("'Containerd' test only supports amd64 architecture")
}

namespace := "default"
ctx := namespaces.WithNamespace(context.Background(), namespace)
tmpDir, socketPath := configureTestDataPaths(t, namespace)
defer os.RemoveAll(tmpDir)

containerdC := startContainerd(t, ctx, tmpDir)
defer containerdC.Terminate(ctx)

client, err := containerd.New(socketPath)
require.NoError(t, err)
defer client.Close()
client := setupContainerd(t, ctx, namespace)

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -240,7 +253,7 @@ func TestContainerd_SearchLocalStoreByNameOrDigest(t *testing.T) {
img, cleanup, err := image.NewContainerImage(ctx, tt.searchName,
types.ImageOptions{ImageSources: types.ImageSources{types.ContainerdImageSource}})
defer cleanup()
if tt.expectErr {
if tt.wantErr {
require.Error(t, err)
return
}
Expand Down Expand Up @@ -272,7 +285,12 @@ func TestContainerd_LocalImage_Alternative_Namespace(t *testing.T) {
}

func localImageTestWithNamespace(t *testing.T, namespace string) {
t.Helper()
// Each architecture needs different images and test cases.
// Currently only amd64 architecture is supported
if runtime.GOARCH != "amd64" {
t.Skip("'Containerd' test only supports amd64 architecture")
}

tests := []struct {
name string
imageName string
Expand Down Expand Up @@ -644,22 +662,10 @@ func localImageTestWithNamespace(t *testing.T, namespace string) {
},
},
}
// Each architecture needs different images and test cases.
// Currently only amd64 architecture is supported
if runtime.GOARCH != "amd64" {
t.Skip("'Containerd' test only supports amd64 architecture")
}
ctx := namespaces.WithNamespace(context.Background(), namespace)

tmpDir, socketPath := configureTestDataPaths(t, namespace)
defer os.RemoveAll(tmpDir)

containerdC := startContainerd(t, ctx, tmpDir)
defer containerdC.Terminate(ctx)

client, err := containerd.New(socketPath)
require.NoError(t, err)
defer client.Close()
t.Helper()
ctx := namespaces.WithNamespace(context.Background(), namespace)
client := setupContainerd(t, ctx, namespace)

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -731,6 +737,12 @@ func localImageTestWithNamespace(t *testing.T, namespace string) {
}

func TestContainerd_PullImage(t *testing.T) {
// Each architecture needs different images and test cases.
// Currently only amd64 architecture is supported
if runtime.GOARCH != "amd64" {
t.Skip("'Containerd' test only supports amd64 architecture")
}

tests := []struct {
name string
imageName string
Expand Down Expand Up @@ -786,23 +798,9 @@ func TestContainerd_PullImage(t *testing.T) {
},
}

// Each architecture needs different images and test cases.
// Currently only amd64 architecture is supported
if runtime.GOARCH != "amd64" {
t.Skip("'Containerd' test only supports amd64 architecture")
}

namespace := "default"
ctx := namespaces.WithNamespace(context.Background(), namespace)

tmpDir, socketPath := configureTestDataPaths(t, namespace)

containerdC := startContainerd(t, ctx, tmpDir)
defer containerdC.Terminate(ctx)

cli, err := containerd.New(socketPath)
require.NoError(t, err)
defer cli.Close()
client := setupContainerd(t, ctx, namespace)

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -815,7 +813,7 @@ func TestContainerd_PullImage(t *testing.T) {
c.Close()
}()

_, err = cli.Pull(ctx, tt.imageName)
_, err = client.Pull(ctx, tt.imageName)
require.NoError(t, err)

// Enable only containerd
Expand Down

0 comments on commit b6fafa0

Please sign in to comment.