Skip to content

Commit d4213d7

Browse files
authored
Merge commit from fork
Adopt Go's os.Root for plugin file operations so that all path access derived from a plugin name stays within the plugin root (~/.trivy/plugins). Add pkg/x/os.Root, a small wrapper over os.Root with a Join helper, and route install, uninstall, and plugin loading through it instead of joining names onto the root path directly. NewManager opens the plugin root eagerly and returns an error, and exposes Close; the package-level Run/Start helpers wrap it for callers outside the plugin subcommands.
1 parent 246ee3c commit d4213d7

10 files changed

Lines changed: 345 additions & 112 deletions

File tree

integration/plugin_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ func TestPlugin(t *testing.T) {
4444

4545
for _, tt := range tests {
4646
t.Run(tt.name, func(t *testing.T) {
47-
// We can overwrite stdout for `_default_Manager` only once.
48-
// So we need to clear the temporary stdout file before each test case.
47+
// The output plugin appends to os.Stdout (redirected to tempStdOut),
48+
// so clear it before each test case.
4949
clearFile(t, tempStdOut)
5050

5151
t.Setenv("XDG_DATA_HOME", t.TempDir())

pkg/commands/app.go

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,17 @@ func loadPluginCommands() []*cobra.Command {
120120
ctx := context.Background()
121121

122122
var commands []*cobra.Command
123-
plugins, err := plugin.NewManager().LoadAll(ctx)
123+
// Avoid creating the plugin directory on every run; nothing to load if it is absent.
124+
if !plugin.DirExists() {
125+
return nil
126+
}
127+
manager, err := plugin.NewManager()
128+
if err != nil {
129+
log.WarnContext(ctx, "Failed to initialize the plugin manager", log.Err(err))
130+
return nil
131+
}
132+
defer manager.Close()
133+
plugins, err := manager.LoadAll(ctx)
124134
if err != nil {
125135
log.DebugContext(ctx, "No plugins loaded")
126136
return nil
@@ -751,6 +761,7 @@ func NewConfigCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
751761

752762
func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
753763
var pluginOptions flag.Options
764+
var manager *plugin.Manager
754765
pluginFlags := &flag.Flags{
755766
globalFlags,
756767
}
@@ -767,6 +778,16 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
767778
if err != nil {
768779
return err
769780
}
781+
manager, err = plugin.NewManager()
782+
if err != nil {
783+
return xerrors.Errorf("plugin manager error: %w", err)
784+
}
785+
return nil
786+
},
787+
PersistentPostRunE: func(_ *cobra.Command, _ []string) error {
788+
if manager != nil {
789+
return manager.Close()
790+
}
770791
return nil
771792
},
772793
}
@@ -788,7 +809,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
788809
DisableFlagsInUseLine: true,
789810
Args: cobra.ExactArgs(1),
790811
RunE: func(cmd *cobra.Command, args []string) error {
791-
if _, err := plugin.Install(cmd.Context(), args[0], plugin.Options{Insecure: pluginOptions.Insecure}); err != nil {
812+
if _, err := manager.Install(cmd.Context(), args[0], plugin.Options{Insecure: pluginOptions.Insecure}); err != nil {
792813
return xerrors.Errorf("plugin install error: %w", err)
793814
}
794815
return nil
@@ -803,7 +824,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
803824
SilenceUsage: true,
804825
Args: cobra.ExactArgs(1),
805826
RunE: func(cmd *cobra.Command, args []string) error {
806-
if err := plugin.Uninstall(cmd.Context(), args[0]); err != nil {
827+
if err := manager.Uninstall(cmd.Context(), args[0]); err != nil {
807828
return xerrors.Errorf("plugin uninstall error: %w", err)
808829
}
809830
return nil
@@ -818,7 +839,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
818839
Short: "List installed plugin",
819840
Args: cobra.NoArgs,
820841
RunE: func(cmd *cobra.Command, _ []string) error {
821-
if err := plugin.List(cmd.Context()); err != nil {
842+
if err := manager.List(cmd.Context()); err != nil {
822843
return xerrors.Errorf("plugin list display error: %w", err)
823844
}
824845
return nil
@@ -832,7 +853,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
832853
SilenceUsage: true,
833854
Args: cobra.ExactArgs(1),
834855
RunE: func(_ *cobra.Command, args []string) error {
835-
if err := plugin.Information(args[0]); err != nil {
856+
if err := manager.Information(args[0]); err != nil {
836857
return xerrors.Errorf("plugin information display error: %w", err)
837858
}
838859
return nil
@@ -847,7 +868,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
847868
Short: "Run a plugin on the fly",
848869
Args: cobra.MinimumNArgs(1),
849870
RunE: func(cmd *cobra.Command, args []string) error {
850-
return plugin.Run(cmd.Context(), args[0], plugin.Options{
871+
return manager.Run(cmd.Context(), args[0], plugin.Options{
851872
Args: args[1:],
852873
Insecure: pluginOptions.Insecure,
853874
})
@@ -861,7 +882,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
861882
SilenceUsage: true,
862883
Args: cobra.NoArgs,
863884
RunE: func(cmd *cobra.Command, _ []string) error {
864-
if err := plugin.Update(cmd.Context(), plugin.Options{Insecure: pluginOptions.Insecure}); err != nil {
885+
if err := manager.Update(cmd.Context(), plugin.Options{Insecure: pluginOptions.Insecure}); err != nil {
865886
return xerrors.Errorf("plugin update error: %w", err)
866887
}
867888
return nil
@@ -879,7 +900,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
879900
if len(args) == 1 {
880901
keyword = args[0]
881902
}
882-
return plugin.Search(cmd.Context(), keyword)
903+
return manager.Search(cmd.Context(), keyword)
883904
},
884905
},
885906
&cobra.Command{
@@ -889,7 +910,7 @@ func NewPluginCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
889910
SilenceErrors: true,
890911
SilenceUsage: true,
891912
RunE: func(cmd *cobra.Command, args []string) error {
892-
if err := plugin.Upgrade(cmd.Context(), args); err != nil {
913+
if err := manager.Upgrade(cmd.Context(), args); err != nil {
893914
return xerrors.Errorf("plugin upgrade error: %w", err)
894915
}
895916
return nil

pkg/plugin/index_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ func TestManager_Update(t *testing.T) {
2424
}))
2525
t.Cleanup(ts.Close)
2626

27-
manager := plugin.NewManager(plugin.WithIndexURL(ts.URL + "/index.yaml"))
28-
err := manager.Update(t.Context(), plugin.Options{})
27+
manager, err := plugin.NewManager(plugin.WithIndexURL(ts.URL + "/index.yaml"))
28+
require.NoError(t, err)
29+
err = manager.Update(t.Context(), plugin.Options{})
2930
require.NoError(t, err)
3031

3132
indexPath := filepath.Join(tempDir, ".trivy", "plugins", "index.yaml")
@@ -65,7 +66,7 @@ bar A bar plugin
6566
{
6667
name: "no index",
6768
keyword: "",
68-
dir: "unknown",
69+
dir: t.TempDir(), // a fresh dir without index.yaml
6970
wantErr: "plugin index not found",
7071
},
7172
}
@@ -74,8 +75,9 @@ bar A bar plugin
7475
t.Setenv("XDG_DATA_HOME", tt.dir)
7576

7677
var got bytes.Buffer
77-
m := plugin.NewManager(plugin.WithWriter(&got))
78-
err := m.Search(t.Context(), tt.keyword)
78+
m, err := plugin.NewManager(plugin.WithWriter(&got))
79+
require.NoError(t, err)
80+
err = m.Search(t.Context(), tt.keyword)
7981
if tt.wantErr != "" {
8082
require.ErrorContains(t, err, tt.wantErr)
8183
return

0 commit comments

Comments
 (0)