mirror of
https://github.com/anchore/syft.git
synced 2026-02-13 19:16:43 +01:00
Fix potential race condition during event subscription (#993)
This commit is contained in:
parent
24f08e7738
commit
91e2fd8532
@ -98,11 +98,12 @@ func Run(ctx context.Context, app *config.Application, ko sign.KeyOpts, args []s
|
|||||||
eventBus := partybus.NewBus()
|
eventBus := partybus.NewBus()
|
||||||
stereoscope.SetBus(eventBus)
|
stereoscope.SetBus(eventBus)
|
||||||
syft.SetBus(eventBus)
|
syft.SetBus(eventBus)
|
||||||
|
subscription := eventBus.Subscribe()
|
||||||
|
|
||||||
return eventloop.EventLoop(
|
return eventloop.EventLoop(
|
||||||
execWorker(app, *si, format, predicateType, sv),
|
execWorker(app, *si, format, predicateType, sv),
|
||||||
eventloop.SetupSignals(),
|
eventloop.SetupSignals(),
|
||||||
eventBus.Subscribe(),
|
subscription,
|
||||||
stereoscope.Cleanup,
|
stereoscope.Cleanup,
|
||||||
ui.Select(options.IsVerbose(app), app.Quiet)...,
|
ui.Select(options.IsVerbose(app), app.Quiet)...,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -46,11 +46,12 @@ func Run(ctx context.Context, app *config.Application, args []string) error {
|
|||||||
eventBus := partybus.NewBus()
|
eventBus := partybus.NewBus()
|
||||||
stereoscope.SetBus(eventBus)
|
stereoscope.SetBus(eventBus)
|
||||||
syft.SetBus(eventBus)
|
syft.SetBus(eventBus)
|
||||||
|
subscription := eventBus.Subscribe()
|
||||||
|
|
||||||
return eventloop.EventLoop(
|
return eventloop.EventLoop(
|
||||||
execWorker(app, *si, writer),
|
execWorker(app, *si, writer),
|
||||||
eventloop.SetupSignals(),
|
eventloop.SetupSignals(),
|
||||||
eventBus.Subscribe(),
|
subscription,
|
||||||
stereoscope.Cleanup,
|
stereoscope.Cleanup,
|
||||||
ui.Select(options.IsVerbose(app), app.Quiet)...,
|
ui.Select(options.IsVerbose(app), app.Quiet)...,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -53,11 +53,12 @@ func Run(ctx context.Context, app *config.Application, args []string) error {
|
|||||||
eventBus := partybus.NewBus()
|
eventBus := partybus.NewBus()
|
||||||
stereoscope.SetBus(eventBus)
|
stereoscope.SetBus(eventBus)
|
||||||
syft.SetBus(eventBus)
|
syft.SetBus(eventBus)
|
||||||
|
subscription := eventBus.Subscribe()
|
||||||
|
|
||||||
return eventloop.EventLoop(
|
return eventloop.EventLoop(
|
||||||
execWorker(app, *si, writer),
|
execWorker(app, *si, writer),
|
||||||
eventloop.SetupSignals(),
|
eventloop.SetupSignals(),
|
||||||
eventBus.Subscribe(),
|
subscription,
|
||||||
stereoscope.Cleanup,
|
stereoscope.Cleanup,
|
||||||
ui.Select(options.IsVerbose(app), app.Quiet)...,
|
ui.Select(options.IsVerbose(app), app.Quiet)...,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -92,7 +92,7 @@ func TestPowerUserCmdFlags(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
cmd, stdout, stderr := runSyft(t, test.env, test.args...)
|
cmd, stdout, stderr := runSyftSafe(t, test.env, test.args...)
|
||||||
for _, traitFn := range test.assertions {
|
for _, traitFn := range test.assertions {
|
||||||
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
|
traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -152,7 +152,7 @@ func assertVerifyAttestation(coverageImage string) traitAssertion {
|
|||||||
coverageImage, // TODO which remote image to use?
|
coverageImage, // TODO which remote image to use?
|
||||||
)
|
)
|
||||||
|
|
||||||
stdout, stderr := runCommand(attachCmd, nil)
|
stdout, stderr, _ := runCommand(attachCmd, nil)
|
||||||
if attachCmd.ProcessState.ExitCode() != 0 {
|
if attachCmd.ProcessState.ExitCode() != 0 {
|
||||||
tb.Log("STDOUT", stdout)
|
tb.Log("STDOUT", stdout)
|
||||||
tb.Log("STDERR", stderr)
|
tb.Log("STDERR", stderr)
|
||||||
@ -165,7 +165,7 @@ func assertVerifyAttestation(coverageImage string) traitAssertion {
|
|||||||
coverageImage, // TODO which remote image to use?
|
coverageImage, // TODO which remote image to use?
|
||||||
)
|
)
|
||||||
|
|
||||||
stdout, stderr = runCommand(verifyCmd, nil)
|
stdout, stderr, _ = runCommand(verifyCmd, nil)
|
||||||
if attachCmd.ProcessState.ExitCode() != 0 {
|
if attachCmd.ProcessState.ExitCode() != 0 {
|
||||||
tb.Log("STDOUT", stdout)
|
tb.Log("STDOUT", stdout)
|
||||||
tb.Log("STDERR", stderr)
|
tb.Log("STDERR", stderr)
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
@ -11,12 +10,11 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope"
|
|
||||||
"github.com/anchore/stereoscope/pkg/imagetest"
|
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupPKI(t *testing.T, pw string) func() {
|
func setupPKI(t *testing.T, pw string) func() {
|
||||||
@ -27,7 +25,7 @@ func setupPKI(t *testing.T, pw string) func() {
|
|||||||
|
|
||||||
cosignPath := filepath.Join(repoRoot(t), ".tmp/cosign")
|
cosignPath := filepath.Join(repoRoot(t), ".tmp/cosign")
|
||||||
cmd := exec.Command(cosignPath, "generate-key-pair")
|
cmd := exec.Command(cosignPath, "generate-key-pair")
|
||||||
stdout, stderr := runCommand(cmd, nil)
|
stdout, stderr, _ := runCommand(cmd, nil)
|
||||||
if cmd.ProcessState.ExitCode() != 0 {
|
if cmd.ProcessState.ExitCode() != 0 {
|
||||||
t.Log("STDOUT", stdout)
|
t.Log("STDOUT", stdout)
|
||||||
t.Log("STDERR", stderr)
|
t.Log("STDERR", stderr)
|
||||||
@ -54,25 +52,13 @@ func setupPKI(t *testing.T, pw string) func() {
|
|||||||
|
|
||||||
func getFixtureImage(t testing.TB, fixtureImageName string) string {
|
func getFixtureImage(t testing.TB, fixtureImageName string) string {
|
||||||
t.Logf("obtaining fixture image for %s", fixtureImageName)
|
t.Logf("obtaining fixture image for %s", fixtureImageName)
|
||||||
request := imagetest.PrepareFixtureImage(t, "docker-archive", fixtureImageName)
|
imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
return imagetest.GetFixtureImageTarPath(t, fixtureImageName)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
i, err := stereoscope.GetImage(ctx, request)
|
|
||||||
t.Logf("got image %s: %s", fixtureImageName, i.Metadata.ID)
|
|
||||||
require.NoError(t, err)
|
|
||||||
t.Cleanup(func() {
|
|
||||||
require.NoError(t, i.Cleanup())
|
|
||||||
})
|
|
||||||
|
|
||||||
path := imagetest.GetFixtureImageTarPath(t, fixtureImageName)
|
|
||||||
t.Logf("returning %s: %s", fixtureImageName, path)
|
|
||||||
return path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pullDockerImage(t testing.TB, image string) {
|
func pullDockerImage(t testing.TB, image string) {
|
||||||
cmd := exec.Command("docker", "pull", image)
|
cmd := exec.Command("docker", "pull", image)
|
||||||
stdout, stderr := runCommand(cmd, nil)
|
stdout, stderr, _ := runCommand(cmd, nil)
|
||||||
if cmd.ProcessState.ExitCode() != 0 {
|
if cmd.ProcessState.ExitCode() != 0 {
|
||||||
t.Log("STDOUT", stdout)
|
t.Log("STDOUT", stdout)
|
||||||
t.Log("STDERR", stderr)
|
t.Log("STDERR", stderr)
|
||||||
@ -95,15 +81,25 @@ func runSyftInDocker(t testing.TB, env map[string]string, image string, args ...
|
|||||||
args...,
|
args...,
|
||||||
)
|
)
|
||||||
cmd := exec.Command("docker", allArgs...)
|
cmd := exec.Command("docker", allArgs...)
|
||||||
stdout, stderr := runCommand(cmd, env)
|
stdout, stderr, _ := runCommand(cmd, env)
|
||||||
return cmd, stdout, stderr
|
return cmd, stdout, stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSyft(t testing.TB, env map[string]string, args ...string) (*exec.Cmd, string, string) {
|
func runSyft(t testing.TB, env map[string]string, args ...string) (*exec.Cmd, string, string) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
return runSyftCommand(t, env, true, args...)
|
||||||
defer cancel()
|
}
|
||||||
cmd := exec.CommandContext(ctx, getSyftBinaryLocation(t), args...)
|
|
||||||
|
|
||||||
|
func runSyftSafe(t testing.TB, env map[string]string, args ...string) (*exec.Cmd, string, string) {
|
||||||
|
return runSyftCommand(t, env, false, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runSyftCommand(t testing.TB, env map[string]string, expectError bool, args ...string) (*exec.Cmd, string, string) {
|
||||||
|
cancel := make(chan bool, 1)
|
||||||
|
defer func() {
|
||||||
|
cancel <- true
|
||||||
|
}()
|
||||||
|
|
||||||
|
cmd := getSyftCommand(t, args...)
|
||||||
if env == nil {
|
if env == nil {
|
||||||
env = make(map[string]string)
|
env = make(map[string]string)
|
||||||
}
|
}
|
||||||
@ -111,7 +107,45 @@ func runSyft(t testing.TB, env map[string]string, args ...string) (*exec.Cmd, st
|
|||||||
// we should not have tests reaching out for app update checks
|
// we should not have tests reaching out for app update checks
|
||||||
env["SYFT_CHECK_FOR_APP_UPDATE"] = "false"
|
env["SYFT_CHECK_FOR_APP_UPDATE"] = "false"
|
||||||
|
|
||||||
stdout, stderr := runCommand(cmd, env)
|
timeout := func() {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case <-time.After(60 * time.Second):
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd != nil && cmd.Process != nil {
|
||||||
|
// get a stack trace printed
|
||||||
|
err := cmd.Process.Signal(syscall.SIGABRT)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error aborting: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go timeout()
|
||||||
|
|
||||||
|
stdout, stderr, err := runCommand(cmd, env)
|
||||||
|
|
||||||
|
if !expectError && err != nil && stdout == "" {
|
||||||
|
t.Errorf("error running syft: %+v", err)
|
||||||
|
t.Errorf("STDOUT: %s", stdout)
|
||||||
|
t.Errorf("STDERR: %s", stderr)
|
||||||
|
|
||||||
|
// this probably indicates a timeout
|
||||||
|
args = append(args, "-vv")
|
||||||
|
cmd = getSyftCommand(t, args...)
|
||||||
|
|
||||||
|
go timeout()
|
||||||
|
stdout, stderr, err = runCommand(cmd, env)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error rerunning syft: %+v", err)
|
||||||
|
t.Errorf("STDOUT: %s", stdout)
|
||||||
|
t.Errorf("STDERR: %s", stderr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return cmd, stdout, stderr
|
return cmd, stdout, stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +155,12 @@ func runCosign(t testing.TB, env map[string]string, args ...string) (*exec.Cmd,
|
|||||||
env = make(map[string]string)
|
env = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout, stderr := runCommand(cmd, env)
|
stdout, stderr, err := runCommand(cmd, env)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error running cosign: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return cmd, stdout, stderr
|
return cmd, stdout, stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +168,7 @@ func getCosignCommand(t testing.TB, args ...string) *exec.Cmd {
|
|||||||
return exec.Command(filepath.Join(repoRoot(t), ".tmp/cosign"), args...)
|
return exec.Command(filepath.Join(repoRoot(t), ".tmp/cosign"), args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCommand(cmd *exec.Cmd, env map[string]string) (string, string) {
|
func runCommand(cmd *exec.Cmd, env map[string]string) (string, string, error) {
|
||||||
if env != nil {
|
if env != nil {
|
||||||
cmd.Env = append(os.Environ(), envMapToSlice(env)...)
|
cmd.Env = append(os.Environ(), envMapToSlice(env)...)
|
||||||
}
|
}
|
||||||
@ -138,9 +177,9 @@ func runCommand(cmd *exec.Cmd, env map[string]string) (string, string) {
|
|||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
|
|
||||||
// ignore errors since this may be what the test expects
|
// ignore errors since this may be what the test expects
|
||||||
cmd.Run()
|
err := cmd.Run()
|
||||||
|
|
||||||
return stdout.String(), stderr.String()
|
return stdout.String(), stderr.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func envMapToSlice(env map[string]string) (envList []string) {
|
func envMapToSlice(env map[string]string) (envList []string) {
|
||||||
@ -153,6 +192,10 @@ func envMapToSlice(env map[string]string) (envList []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSyftCommand(t testing.TB, args ...string) *exec.Cmd {
|
||||||
|
return exec.Command(getSyftBinaryLocation(t), args...)
|
||||||
|
}
|
||||||
|
|
||||||
func getSyftBinaryLocation(t testing.TB) string {
|
func getSyftBinaryLocation(t testing.TB) string {
|
||||||
if os.Getenv("SYFT_BINARY_LOCATION") != "" {
|
if os.Getenv("SYFT_BINARY_LOCATION") != "" {
|
||||||
// SYFT_BINARY_LOCATION is the absolute path to the snapshot binary
|
// SYFT_BINARY_LOCATION is the absolute path to the snapshot binary
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user