55package pm
66
77import (
8+ "bufio"
89 "encoding/json"
910 "errors"
1011 "flag"
@@ -29,7 +30,7 @@ import (
2930
3031var (
3132 // Version of the Plugin Manager (PM).
32- version = "4.8 "
33+ version = "4.9 "
3334)
3435
3536// Status of plugin execution used for displaying to user on console.
@@ -48,15 +49,16 @@ type Plugin struct {
4849 RequiredBy []string
4950 Requires []string
5051 Status string
51- StdOutErr string
52+ StdOutErr [] string
5253}
5354
5455// Plugins is a list of plugins' info.
5556type Plugins []Plugin
5657
5758// RunStatus is the pm run status.
5859type RunStatus struct {
59- Type string
60+ Type string
61+ Library string
6062 // TODO: Add Percentage to get no. of pending vs. completed run of plugins.
6163 Plugins Plugins `yaml:",omitempty"`
6264 Status string
@@ -158,10 +160,13 @@ func getPluginsInfoFromJSONStrOrFile(strOrFile string) (RunStatus, error) {
158160 jsonFormat = false
159161 }
160162 }
163+ // INFO: Use RunStatus to unmarshal to keep input consistent with current
164+ // output json, so that rerun failed could be done using result json.
165+ var pluginsData RunStatus
161166 if jsonFormat {
162- err = json .Unmarshal ([]byte (rawData ), & pluginsInfo )
167+ err = json .Unmarshal ([]byte (rawData ), & pluginsData )
163168 } else {
164- err = yaml .Unmarshal ([]byte (rawData ), & pluginsInfo )
169+ err = yaml .Unmarshal ([]byte (rawData ), & pluginsData )
165170 }
166171 if err != nil {
167172 logger .Error .Printf ("Failed to call Unmarshal(%s, %v); err=%#v" ,
@@ -170,7 +175,7 @@ func getPluginsInfoFromJSONStrOrFile(strOrFile string) (RunStatus, error) {
170175 logger .ConsoleError .PrintNReturnError (
171176 "Plugins is not in expected format. Error: %s" , err .Error ())
172177 }
173- return pluginsInfo , nil
178+ return pluginsData , nil
174179}
175180
176181func getPluginsInfoFromLibrary (pluginType , library string ) (Plugins , error ) {
@@ -411,7 +416,6 @@ func executePluginCmd(statusCh chan<- map[string]*Plugin, pInfo Plugin, failedDe
411416 updateGraph (getPluginType (p ), p , dStatusStart , "" )
412417 logger .ConsoleInfo .Printf ("%s: %s" , pInfo .Description , dStatusStart )
413418 pluginLogFile := ""
414- // Create chLog, by default it will use syslog, if user specified logFile, then use previous defined log generator
415419 var chLog * log.Logger
416420 if ! logger .IsFileLogger () {
417421 var logTag string
@@ -496,21 +500,45 @@ func executePluginCmd(statusCh chan<- map[string]*Plugin, pInfo Plugin, failedDe
496500 cmdParams := cmdParam [1 :]
497501 cmd := exec .Command (cmdStr , cmdParams ... )
498502 cmd .Env = envList
499- stdOutErr , err := cmd .CombinedOutput ()
503+ iostdout , err := cmd .StdoutPipe ()
504+ if err != nil {
505+ pInfo .Status = dStatusFail
506+ logger .Error .Printf ("Failed to execute plugin %s. Error: %s\n " , pInfo .Name , err .Error ())
507+ pInfo .StdOutErr = []string {err .Error ()}
508+ logger .ConsoleInfo .Printf ("%s: %s\n " , pInfo .Description , pInfo .Status )
509+ statusCh <- map [string ]* Plugin {p : & pInfo }
510+ return
511+ }
512+ cmd .Stderr = cmd .Stdout
513+
514+ chLog .Println ("Executing command:" , pInfo .ExecStart )
515+ err = cmd .Start ()
516+ var stdOutErr []string
517+ if err == nil {
518+ scanner := bufio .NewScanner (iostdout )
519+ scanner .Split (bufio .ScanLines )
520+ for scanner .Scan () {
521+ iobytes := scanner .Text ()
522+ chLog .Println (string (iobytes ))
523+ stdOutErr = append (stdOutErr , iobytes )
524+ }
525+ err = cmd .Wait ()
526+ // chLog.Printf("command exited with code: %+v", err)
527+ }
500528
501529 func () {
502530 chLog .Printf ("INFO: Plugin(%s): Executing command: %s" , p , pInfo .ExecStart )
503531 if err != nil {
504532 chLog .Printf ("ERROR: Plugin(%s): Failed to execute command, err=%s" , p , err .Error ())
505533 updateGraph (getPluginType (p ), p , dStatusFail , pluginLogFile )
506534 } else {
507- chLog .Printf ("INFO: Plugin(%s): Stdout & Stderr: %s " , p , string ( stdOutErr ) )
535+ chLog .Printf ("INFO: Plugin(%s): Stdout & Stderr: %v " , p , stdOutErr )
508536 updateGraph (getPluginType (p ), p , dStatusOk , pluginLogFile )
509537 }
510538 }()
511539
512- logger .Debug .Println ("Stdout & Stderr:" , string ( stdOutErr ) )
513- pStatus := Plugin {StdOutErr : string ( stdOutErr ) }
540+ logger .Debug .Println ("Stdout & Stderr:" , stdOutErr )
541+ pStatus := Plugin {StdOutErr : stdOutErr }
514542 if err != nil {
515543 pStatus .Status = dStatusFail
516544 logger .Error .Printf ("Failed to execute plugin %s. err=%s\n " , p , err .Error ())
@@ -760,9 +788,20 @@ func RunFromJSONStrOrFile(result *RunStatus, jsonStrOrFile string, runOptions Ru
760788 result .StdOutErr = err .Error ()
761789 return err
762790 }
763- result .Plugins = pluginsInfo .Plugins
764791 result .Type = pluginsInfo .Type
765-
792+ result .Library = pluginsInfo .Library
793+ result .Plugins = pluginsInfo .Plugins
794+ // INFO: Override values of json/file with explicitly passed cmdline parameter. Else, set runOptions type from json/file.
795+ if runOptions .Type != "" {
796+ result .Type = runOptions .Type
797+ } else {
798+ runOptions .Type = pluginsInfo .Type
799+ }
800+ if runOptions .Library != "" {
801+ result .Library = runOptions .Library
802+ } else {
803+ runOptions .Library = pluginsInfo .Library
804+ }
766805 return run (result , runOptions )
767806}
768807
@@ -903,7 +942,7 @@ func ScanCommandOptions(options map[string]interface{}) error {
903942 // but only extensions (i.e., they get created as hidden files).
904943 config .SetPMLogFile (tLogFile )
905944 myLogFile += config .GetPMLogFile ()
906- if myLogFile != config .DefaultLogPath {
945+ if myLogFile != logger .DefaultLogPath {
907946 myLogFile := filepath .Clean (myLogFile )
908947 logger .Info .Println ("Logging to specified log file:" , myLogFile )
909948 errList := logger .DeInitLogger ()
0 commit comments