get.porter.sh/porter@v1.3.0/pkg/plugins/runner.go (about) 1 package plugins 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "strings" 8 9 "get.porter.sh/porter/pkg/config" 10 "get.porter.sh/porter/pkg/portercontext" 11 "get.porter.sh/porter/pkg/tracing" 12 "go.opentelemetry.io/otel/attribute" 13 ) 14 15 type CommandOptions struct { 16 Command string 17 } 18 19 type PluginRunner struct { 20 *portercontext.Context 21 pluginName string 22 } 23 24 func NewRunner(pluginName string) *PluginRunner { 25 return &PluginRunner{ 26 Context: portercontext.New(), 27 pluginName: pluginName, 28 } 29 } 30 31 func (r *PluginRunner) Validate() error { 32 if r.pluginName == "" { 33 return errors.New("Plugin not specified") 34 } 35 36 pluginPath, err := config.New().GetPluginPath(r.pluginName) 37 if err != nil { 38 return fmt.Errorf("Failed to get plugin path for %s: %w", r.pluginName, err) 39 } 40 41 exists, err := r.FileSystem.Exists(pluginPath) 42 if err != nil { 43 return fmt.Errorf("Failed to stat path %s: %w", pluginPath, err) 44 } 45 if !exists { 46 return fmt.Errorf("Plugin %s doesn't exist in filesystem with path %s", r.pluginName, pluginPath) 47 } 48 49 return nil 50 } 51 52 func (r *PluginRunner) Run(ctx context.Context, commandOpts CommandOptions) error { 53 ctx, span := tracing.StartSpan(ctx, 54 attribute.String("name", r.pluginName), 55 attribute.String("partial-command", commandOpts.Command), 56 ) 57 defer span.EndSpan() 58 59 pluginPath, err := config.New().GetPluginPath(r.pluginName) 60 if err != nil { 61 return span.Error(fmt.Errorf("Failed to get plugin path for %s: %w", r.pluginName, err)) 62 } 63 span.SetAttributes(attribute.String("plugin-path", pluginPath)) 64 65 cmdArgs := strings.Split(commandOpts.Command, " ") 66 cmd := r.NewCommand(ctx, pluginPath, cmdArgs...) 67 68 // Pipe the output from the plugin to porter 69 cmd.Stdout = r.Out 70 cmd.Stderr = r.Err 71 72 prettyCmd := fmt.Sprintf("%s%s", cmd.Dir, strings.Join(cmd.Args, " ")) 73 span.SetAttributes(attribute.String("full-command", prettyCmd)) 74 75 err = cmd.Start() 76 if err != nil { 77 return span.Error(fmt.Errorf("could not run plugin command %s: %w", prettyCmd, err)) 78 } 79 80 return span.Error(cmd.Wait()) 81 }