Skip to content

Commit e0545d7

Browse files
committed
Revert "address review comments"
This reverts commit eebe5b9.
1 parent eebe5b9 commit e0545d7

File tree

3 files changed

+93
-183
lines changed

3 files changed

+93
-183
lines changed

pkg/scanners/trivy/trivy.go

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"net/http"
99
"os"
10-
"os/exec"
1110
"time"
1211

1312
"github.com/eraser-dev/eraser/api/unversioned"
@@ -148,28 +147,19 @@ func runProfileServer() {
148147
log.Error(err, "pprof server failed")
149148
}
150149

151-
// ensureTrivyExecutable ensures that a trivy executable is available at the target path.
152-
// If the executable is not found at the target path, it searches for trivy in PATH
153-
// and creates a symlink at the target path pointing to the found executable.
154-
func ensureTrivyExecutable(targetPath string) error {
155-
// Check if trivy already exists at the target path
156-
if _, err := os.Stat(targetPath); err == nil {
157-
return nil
150+
func findTrivyExecutable() (string, error) {
151+
// First, check if trivy exists at the hardcoded path
152+
if _, err := os.Stat(trivyCommandName); err == nil {
153+
return trivyCommandName, nil
158154
}
159155

160-
// If not found at target path, try to find it in PATH
161-
pathLocation, err := exec.LookPath("trivy")
156+
// If not found at hardcoded path, try to find it in PATH
157+
path, err := currentExecutingLookPath("trivy")
162158
if err != nil {
163-
return fmt.Errorf("trivy executable not found at %s and not found in PATH: %w", targetPath, err)
159+
return "", fmt.Errorf("trivy executable not found at %s and not found in PATH: %w", trivyCommandName, err)
164160
}
165161

166-
// Create symlink at target path pointing to the found executable
167-
if err := os.Symlink(pathLocation, targetPath); err != nil {
168-
return fmt.Errorf("failed to create symlink from %s to %s: %w", targetPath, pathLocation, err)
169-
}
170-
171-
log.Info("created trivy symlink", "from", targetPath, "to", pathLocation)
172-
return nil
162+
return path, nil
173163
}
174164

175165
func initScanner(userConfig *Config) (Scanner, error) {
@@ -190,17 +180,19 @@ func initScanner(userConfig *Config) (Scanner, error) {
190180
Address: utils.CRIPath,
191181
}
192182

193-
// Ensure trivy executable is available at the hardcoded path
194-
if err := ensureTrivyExecutable(trivyCommandName); err != nil {
183+
// Find trivy executable path during initialization
184+
trivyPath, err := findTrivyExecutable()
185+
if err != nil {
195186
return nil, err
196187
}
197188

198189
totalTimeout := time.Duration(userConfig.Timeout.Total)
199190
timer := time.NewTimer(totalTimeout)
200191

201192
var s Scanner = &ImageScanner{
202-
config: *userConfig,
203-
timer: timer,
193+
config: *userConfig,
194+
timer: timer,
195+
trivyPath: trivyPath,
204196
}
205197
return s, nil
206198
}

pkg/scanners/trivy/types.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import (
1414
"github.com/eraser-dev/eraser/pkg/utils"
1515
)
1616

17+
// currentExecutingLookPath is a variable that points to exec.LookPath by default,
18+
// but can be overridden for testing purposes.
19+
var currentExecutingLookPath = exec.LookPath
20+
1721
const (
1822
StatusFailed ScanStatus = iota
1923
StatusNonCompliant
@@ -168,8 +172,9 @@ func (c *Config) getRuntimeVar() (string, error) {
168172
}
169173

170174
type ImageScanner struct {
171-
config Config
172-
timer *time.Timer
175+
config Config
176+
timer *time.Timer
177+
trivyPath string
173178
}
174179

175180
func (s *ImageScanner) Scan(img unversioned.Image) (ScanStatus, error) {
@@ -186,13 +191,13 @@ func (s *ImageScanner) Scan(img unversioned.Image) (ScanStatus, error) {
186191
stderr := new(bytes.Buffer)
187192

188193
cliArgs := s.config.cliArgs(refs[i])
189-
cmd := exec.Command(trivyCommandName, cliArgs...)
194+
cmd := exec.Command(s.trivyPath, cliArgs...) // nolint:gosec // G204: Subprocess launched with variable
190195
cmd.Stdout = stdout
191196
cmd.Stderr = stderr
192197
cmd.Env = append(cmd.Env, os.Environ()...)
193198
cmd.Env = setRuntimeSocketEnvVars(cmd, s.config.Runtime)
194199

195-
log.V(1).Info("scanning image ref", "ref", refs[i], "cli_invocation", fmt.Sprintf("%s %s", trivyCommandName, strings.Join(cliArgs, " ")), "env", cmd.Env)
200+
log.V(1).Info("scanning image ref", "ref", refs[i], "cli_invocation", fmt.Sprintf("%s %s", s.trivyPath, strings.Join(cliArgs, " ")), "env", cmd.Env)
196201
if err := cmd.Run(); err != nil {
197202
log.Error(err, "error scanning image", "imageID", img.ImageID, "reference", refs[i], "stderr", stderr.String())
198203
continue

pkg/scanners/trivy/types_test.go

Lines changed: 70 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package main
22

33
import (
4-
"os"
5-
"path/filepath"
4+
"errors"
65
"strings"
76
"testing"
87

98
"github.com/eraser-dev/eraser/api/unversioned"
9+
1010
"github.com/stretchr/testify/assert"
11-
"github.com/stretchr/testify/require"
1211
)
1312

1413
const (
@@ -173,189 +172,103 @@ func TestCLIArgs(t *testing.T) {
173172
}
174173
}
175174

176-
// TestEnsureTrivyExecutable tests the ensureTrivyExecutable function in isolation.
177-
func TestEnsureTrivyExecutable(t *testing.T) {
178-
// Save original PATH to restore after tests
179-
originalPath := os.Getenv("PATH")
180-
defer func() { os.Setenv("PATH", originalPath) }()
175+
// TestFindTrivyExecutable tests the findTrivyExecutable function in isolation.
176+
func TestFindTrivyExecutable(t *testing.T) {
177+
// Store original function to restore after tests
178+
originalLookPath := currentExecutingLookPath
179+
defer func() { currentExecutingLookPath = originalLookPath }()
181180

182181
testCases := []struct {
183-
name string
184-
setupFunc func(t *testing.T) (targetPath string, cleanup func())
185-
expectedError bool
186-
expectedErrorMsg string
187-
validateFunc func(t *testing.T, targetPath string)
182+
name string
183+
lookPathSetup func()
184+
expectedPath string
185+
expectedError bool
186+
expectedErrorMatch string
188187
}{
189188
{
190-
name: "Trivy already exists at target path",
191-
setupFunc: func(t *testing.T) (string, func()) {
192-
tempDir := t.TempDir()
193-
targetPath := filepath.Join(tempDir, "trivy")
194-
195-
// Create a trivy executable at the target path
196-
file, err := os.Create(targetPath)
197-
require.NoError(t, err)
198-
file.Close()
199-
err = os.Chmod(targetPath, 0o755)
200-
require.NoError(t, err)
201-
202-
return targetPath, func() {}
203-
},
204-
expectedError: false,
205-
validateFunc: func(t *testing.T, targetPath string) {
206-
// Should not create a symlink, original file should still exist
207-
info, err := os.Lstat(targetPath)
208-
require.NoError(t, err)
209-
assert.Equal(t, os.FileMode(0o755), info.Mode().Perm(), "Original file should be preserved")
210-
211-
// Verify it's not a symlink
212-
assert.Equal(t, 0, int(info.Mode()&os.ModeSymlink), "Should not be a symlink")
213-
},
214-
},
215-
{
216-
name: "Trivy found in PATH, symlink created successfully",
217-
setupFunc: func(t *testing.T) (string, func()) {
218-
tempDir := t.TempDir()
219-
pathDir := filepath.Join(tempDir, "bin")
220-
err := os.Mkdir(pathDir, 0o755)
221-
require.NoError(t, err)
222-
223-
// Create a trivy executable in the PATH directory
224-
trivyInPath := filepath.Join(pathDir, "trivy")
225-
file, err := os.Create(trivyInPath)
226-
require.NoError(t, err)
227-
file.Close()
228-
err = os.Chmod(trivyInPath, 0o755)
229-
require.NoError(t, err)
230-
231-
// Set PATH to include our temp bin directory
232-
os.Setenv("PATH", pathDir)
233-
234-
// Target path where symlink should be created
235-
targetPath := filepath.Join(tempDir, "target_trivy")
236-
237-
return targetPath, func() {}
189+
name: "Trivy found in PATH only",
190+
lookPathSetup: func() {
191+
currentExecutingLookPath = func(file string) (string, error) {
192+
if file == trivyExecutableName {
193+
return trivyPathBin, nil
194+
}
195+
return "", errors.New("not found")
196+
}
238197
},
198+
expectedPath: trivyPathBin,
239199
expectedError: false,
240-
validateFunc: func(t *testing.T, targetPath string) {
241-
// Should create a symlink at target path
242-
info, err := os.Lstat(targetPath)
243-
require.NoError(t, err)
244-
245-
// Verify it's a symlink
246-
assert.NotEqual(t, 0, int(info.Mode()&os.ModeSymlink), "Should be a symlink")
247-
248-
// Verify symlink points to the correct location
249-
linkTarget, err := os.Readlink(targetPath)
250-
require.NoError(t, err)
251-
assert.Contains(t, linkTarget, "trivy", "Symlink should point to trivy executable")
252-
},
253200
},
254201
{
255202
name: "Trivy not found anywhere",
256-
setupFunc: func(t *testing.T) (string, func()) {
257-
tempDir := t.TempDir()
258-
emptyPathDir := filepath.Join(tempDir, "empty")
259-
err := os.Mkdir(emptyPathDir, 0o755)
260-
require.NoError(t, err)
261-
262-
// Set PATH to empty directory without trivy
263-
os.Setenv("PATH", emptyPathDir)
264-
265-
targetPath := filepath.Join(tempDir, "target_trivy")
266-
return targetPath, func() {}
267-
},
268-
expectedError: true,
269-
expectedErrorMsg: "trivy executable not found",
270-
validateFunc: func(t *testing.T, targetPath string) {
271-
// Should not create any file or symlink
272-
_, err := os.Lstat(targetPath)
273-
assert.True(t, os.IsNotExist(err), "Target path should not exist when trivy is not found")
274-
},
275-
},
276-
{
277-
name: "Symlink creation fails due to permission",
278-
setupFunc: func(t *testing.T) (string, func()) {
279-
if os.Getuid() == 0 {
280-
t.Skip("Skipping permission test when running as root")
281-
}
282-
283-
tempDir := t.TempDir()
284-
pathDir := filepath.Join(tempDir, "bin")
285-
err := os.Mkdir(pathDir, 0o755)
286-
require.NoError(t, err)
287-
288-
// Create a trivy executable in PATH
289-
trivyInPath := filepath.Join(pathDir, "trivy")
290-
file, err := os.Create(trivyInPath)
291-
require.NoError(t, err)
292-
file.Close()
293-
err = os.Chmod(trivyInPath, 0o755)
294-
require.NoError(t, err)
295-
296-
os.Setenv("PATH", pathDir)
297-
298-
// Try to create symlink in root directory (should fail for non-root users)
299-
targetPath := "/trivy_test_symlink"
300-
301-
return targetPath, func() {
302-
// Clean up any created symlink
303-
os.Remove(targetPath)
203+
lookPathSetup: func() {
204+
currentExecutingLookPath = func(_ string) (string, error) {
205+
return "", errors.New("executable file not found in $PATH")
304206
}
305207
},
306-
expectedError: true,
307-
expectedErrorMsg: "failed to create symlink",
308-
validateFunc: func(t *testing.T, targetPath string) {
309-
// Should not create symlink due to permission error
310-
_, err := os.Lstat(targetPath)
311-
assert.True(t, os.IsNotExist(err), "Target path should not exist when symlink creation fails")
312-
},
208+
expectedPath: "",
209+
expectedError: true,
210+
expectedErrorMatch: "trivy executable not found at /trivy and not found in PATH",
313211
},
314212
}
315213

316214
for _, tc := range testCases {
317215
t.Run(tc.name, func(t *testing.T) {
318-
targetPath, cleanup := tc.setupFunc(t)
319-
defer cleanup()
216+
tc.lookPathSetup()
320217

321-
// Test the ensureTrivyExecutable function
322-
err := ensureTrivyExecutable(targetPath)
218+
path, err := findTrivyExecutable()
323219

324220
if tc.expectedError {
325221
assert.Error(t, err)
326-
assert.Contains(t, err.Error(), tc.expectedErrorMsg)
222+
assert.Contains(t, err.Error(), tc.expectedErrorMatch)
223+
assert.Empty(t, path)
327224
} else {
328225
assert.NoError(t, err)
329-
}
330-
331-
if tc.validateFunc != nil {
332-
tc.validateFunc(t, targetPath)
226+
assert.Equal(t, tc.expectedPath, path)
333227
}
334228
})
335229
}
336230
}
337231

338-
// TestInitScanner_TrivySymlinkCreation tests the symlink creation logic in initScanner.
339-
func TestInitScanner_TrivySymlinkCreation(t *testing.T) {
340-
// This test verifies that initScanner properly calls ensureTrivyExecutable
341-
// and handles errors appropriately. Since ensureTrivyExecutable is tested
342-
// comprehensively above, this focuses on the integration aspect.
232+
// TestImageScanner_Scan_TrivyPathLookup tests the logic for using the trivy executable path.
233+
func TestImageScanner_Scan_TrivyPathLookup(t *testing.T) {
234+
// Base configuration for the scanner
235+
baseConfig := DefaultConfig()
236+
// Dummy image for testing
237+
img := unversioned.Image{ImageID: "test-image-id", Names: []string{"test-image:latest"}}
343238

344-
// Save original PATH to restore after test
345-
originalPath := os.Getenv("PATH")
346-
defer func() { os.Setenv("PATH", originalPath) }()
239+
testCases := []struct {
240+
name string
241+
trivyPath string
242+
expectedStatus ScanStatus
243+
}{
244+
{
245+
name: "Trivy path set to hardcoded path /trivy",
246+
trivyPath: trivyCommandName,
247+
expectedStatus: StatusFailed, // Will fail during actual execution but not due to path issues
248+
},
249+
{
250+
name: "Trivy path set to system PATH location",
251+
trivyPath: trivyPathBin,
252+
expectedStatus: StatusFailed, // Will fail during actual execution but not due to path issues
253+
},
254+
}
347255

348-
t.Run("initScanner fails when trivy not found", func(t *testing.T) {
349-
// Set PATH to empty directory
350-
tempDir := t.TempDir()
351-
os.Setenv("PATH", tempDir)
256+
for _, tc := range testCases {
257+
t.Run(tc.name, func(t *testing.T) {
258+
scanner := &ImageScanner{
259+
config: *baseConfig,
260+
trivyPath: tc.trivyPath,
261+
}
352262

353-
config := DefaultConfig()
354-
scanner, err := initScanner(config)
263+
status, err := scanner.Scan(img)
355264

356-
// Should fail because trivy is not found
357-
assert.Error(t, err)
358-
assert.Contains(t, err.Error(), "trivy executable not found")
359-
assert.Nil(t, scanner)
360-
})
265+
// The scan will likely fail due to inability to run actual scan in test,
266+
// but it should not be a "trivy not found" error since the path is already set
267+
assert.Equal(t, tc.expectedStatus, status, "ScanStatus should be StatusFailed")
268+
if err != nil {
269+
assert.NotContains(t, err.Error(), "trivy executable not found",
270+
"Error should not be about trivy not being found since path is pre-set")
271+
}
272+
})
273+
}
361274
}

0 commit comments

Comments
 (0)