Skip to content

Commit dc90b68

Browse files
author
Abhijith Dadaga Arkakeerthy
committed
Move InitLogging to log utils so that it could be used in other modules like software update manager.
1 parent 0e754d4 commit dc90b68

7 files changed

Lines changed: 124 additions & 83 deletions

File tree

Makefile

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# Copyright (c) 2023 Veritas Technologies LLC. All rights reserved. IP63-2828-7171-04-15-9
1+
# Copyright (c) 2024 Veritas Technologies LLC. All rights reserved. IP63-2828-7171-04-15-9
22

33
# A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
44
.DEFAULT_GOAL := help
55
.PHONY: help
66
help: ## Display this help message.
7-
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
7+
@grep -Eh '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
88

99
TOP=$(CURDIR)
1010
include $(TOP)/Makefile.conf
@@ -29,8 +29,7 @@ clean: ## Clean Plugin Manager go build & test artifacts
2929
cd $(GOSRC); \
3030
go clean -i -mod=vendor ./...;
3131
@echo "Cleaning Go test artifacts... ";
32-
-@rm $(GOSRC)/{,.}*{dot,html,log,svg,xml};
33-
-@rm $(GOSRC)/cmd/pm/{,.}*{dot,log,svg};
32+
-@find $(GOSRC) -name "*.dot" -o -name "*.html" -o -name "*.log" -o -name "*.svg" -o -name "*.xml" | xargs -i rm -f {}
3433
-@rm -rf $(GOSRC)/plugins/
3534
-@rm -rf $(GOCOVERDIR);
3635

@@ -113,4 +112,13 @@ go-race: ## Run Go tests with race detector enabled
113112
export PM_CONF_FILE=$(GOSRC)/sample/pm.config.yaml; \
114113
go test -mod=vendor -v -race ./...;
115114

115+
.PHONY: update-go-tools
116+
update-go-tools: ## Update Go thirdparty tools to current go version
117+
export GOBIN=$(GOTOOLSBIN); \
118+
go install github.com/axw/gocov/gocov@latest; \
119+
go install github.com/AlekSi/gocov-xml@latest; \
120+
go install github.com/matm/gocov-html/cmd/gocov-html@latest; \
121+
go install github.com/jstemmer/go-junit-report/v2@latest; \
122+
go install golang.org/x/lint/golint@latest
123+
116124
.NOTPARALLEL:

cmd/pm/pm.go

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package main
66

77
import (
8-
"fmt"
98
"os"
109
"path/filepath"
1110

@@ -18,7 +17,7 @@ import (
1817
var (
1918
buildDate string
2019
// Version of the Plugin Manager (PM) command.
21-
version = "4.2"
20+
version = "4.4"
2221
// progname is name of my binary/program/executable.
2322
progname = filepath.Base(os.Args[0])
2423
)
@@ -28,29 +27,7 @@ func init() {
2827
config.EnvConfFile = "PM_CONF_FILE"
2928
// DefaultConfigPath is default path for config file used when EnvConfFile is not set.
3029
config.DefaultConfigPath = "/opt/veritas/appliance/asum/pm.config.yaml"
31-
// DefaultLogPath is default path for log file.
32-
config.DefaultLogPath = "./pm.log"
33-
// Use syslog until the config file is read.
34-
// If syslog initialization fails, file logging will be used.
35-
useFileLog := true
36-
if logger.IsSysLogConfigPresent() {
37-
err := logger.InitSysLogger("pm-main", logger.DefaultLogLevel)
38-
if err != nil {
39-
fmt.Printf("Failed to initialize SysLog for logging [%#v]. Proceeding with FileLog...\n", err)
40-
useFileLog = false
41-
}
42-
}
43-
if useFileLog {
44-
// NOTE: while running tests, the path of binary would be in `/tmp/<go-build*>`,
45-
// so, using relative logging path w.r.t. binary wouldn't be accessible on Jenkins.
46-
// So, use absolute path which also has write permissions (like current source directory).
47-
err := logger.InitFileLogger(config.DefaultLogPath, logger.DefaultLogLevel)
48-
if err != nil {
49-
fmt.Printf("Failed to initialize file logger [%#v].\n", err)
50-
os.Exit(1)
51-
}
52-
}
53-
30+
logger.InitLogging()
5431
}
5532

5633
func main() {

config/config.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ var (
3131
EnvConfFile string
3232
// DefaultConfigPath is default path for config file used when EnvConfFile is not set.
3333
DefaultConfigPath string
34-
// DefaultLogPath is default path for log file.
35-
DefaultLogPath string
3634
)
3735

3836
// GetLogDir provides location for storing logs.

graph_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import (
66
"reflect"
77
"sort"
88
"testing"
9-
10-
logger "github.com/VeritasOS/plugin-manager/utils/log"
119
)
1210

1311
func Test_getStatusColor(t *testing.T) {
@@ -199,8 +197,7 @@ func Test_initGraph(t *testing.T) {
199197
wantErr: false,
200198
},
201199
}
202-
// Set log file name to "test", so that cleaning becomes easier.
203-
logger.InitFileLogger("test.log", "INFO")
200+
204201
for _, tt := range tests {
205202
t.Run(tt.name, func(t *testing.T) {
206203
if err := initGraph(tt.args.pluginType, tt.args.pluginsInfo); (err != nil) != tt.wantErr {

plugin.go

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package pm
66

77
import (
8+
"bufio"
89
"encoding/json"
910
"errors"
1011
"flag"
@@ -29,7 +30,7 @@ import (
2930

3031
var (
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.
5556
type Plugins []Plugin
5657

5758
// RunStatus is the pm run status.
5859
type 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

176181
func 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()

plugin_test.go

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ func Test_executePlugins(t *testing.T) {
527527
pluginInfo: Plugins{},
528528
want: want{
529529
returnStatus: true,
530-
// psStatus: Plugins{},
530+
psStatus: Plugins{},
531531
},
532532
},
533533
{
@@ -602,16 +602,16 @@ func Test_executePlugins(t *testing.T) {
602602
{
603603
name: "Plugin with dependency",
604604
pluginInfo: Plugins{
605+
{
606+
Name: "A/a.test",
607+
Description: "Applying \"A\" settings",
608+
ExecStart: `/bin/echo Running A...`,
609+
},
605610
{
606611
Name: "D/d.test",
607612
Description: "Applying \"D\" settings",
608613
Requires: []string{"A/a.test"},
609-
ExecStart: `/bin/echo "Running D..."`,
610-
},
611-
{
612-
Name: "A/a.test",
613-
Description: "Applying \"A\" settings",
614-
ExecStart: `/bin/echo "Running A..."`,
614+
ExecStart: `/bin/echo Running D...`,
615615
},
616616
},
617617
want: want{
@@ -624,6 +624,7 @@ func Test_executePlugins(t *testing.T) {
624624
RequiredBy: []string{"D/d.test"},
625625
Requires: []string{},
626626
Status: "Succeeded",
627+
StdOutErr: []string{"Running A..."},
627628
},
628629
{
629630
Description: "Applying \"D\" settings",
@@ -632,6 +633,7 @@ func Test_executePlugins(t *testing.T) {
632633
RequiredBy: []string{},
633634
Requires: []string{"A/a.test"},
634635
Status: "Succeeded",
636+
StdOutErr: []string{"Running D..."},
635637
},
636638
},
637639
},
@@ -763,17 +765,16 @@ func Test_executePlugins(t *testing.T) {
763765
returnStatus: false,
764766
psStatus: Plugins{
765767
{
766-
Description: "Applying \"A\" settings",
767768
Name: "A/a.test",
769+
Description: "Applying \"A\" settings",
768770
ExecStart: "exit 1",
769-
RequiredBy: []string{"D/d.test"},
770771
Status: "Failed",
771772
},
772773
{
774+
Name: "D/d.test",
773775
Description: "Applying \"D\" settings",
774-
Requires: []string{"A/a.test"},
775776
ExecStart: "/bin/echo \"Running D...!\"",
776-
Name: "D/d.test",
777+
Requires: []string{"A/a.test"},
777778
RequiredBy: []string{},
778779
Status: "Skipped",
779780
},
@@ -788,41 +789,28 @@ func Test_executePlugins(t *testing.T) {
788789
for _, tt.sequential = range []bool{false, true} {
789790
t.Run(tt.name+fmt.Sprintf("(sequential=%v)", tt.sequential),
790791
func(t *testing.T) {
791-
// result := tt.pluginInfo
792792
res := executePlugins(&tt.pluginInfo, tt.sequential, map[string]string{})
793793
// t.Logf("res: %+v, expected: %v", res, tt.want.returnStatus)
794794
if res != tt.want.returnStatus {
795795
t.Errorf("Return value: got %+v, want %+v",
796796
res, tt.want.returnStatus)
797797
return
798798
}
799-
// if len(result) != 0 {
800-
t.Logf("result of all plugins: %+v", tt.pluginInfo)
799+
// t.Logf("result of all plugins: %+v", tt.pluginInfo)
801800
for i := range tt.pluginInfo {
802-
// TODO: Currently even though the expected and
803-
// obtained values are same, it's still failing.
804-
// Explore more on why that's the case for below
805-
// commented ones.
806-
// if reflect.DeepEqual(result[i].Plugin,
807-
// tt.want.psStatus[i].Plugin) == false {
808-
// t.Errorf("Plugins Plugin: got %+v, want %+v",
809-
// result[i].Plugin,
810-
// tt.want.psStatus[i].Plugin)
811-
// }
812801
if reflect.DeepEqual(tt.pluginInfo[i].Status,
813802
tt.want.psStatus[i].Status) == false {
814803
t.Errorf("Plugins %s Status: got %+v, want %+v",
815804
tt.pluginInfo[i].Name,
816805
tt.pluginInfo[i].Status, tt.want.psStatus[i].Status)
817806
}
818-
// if tt.want.psStatus[i].StdOutErr != "" &&
819-
// reflect.DeepEqual(result[i].StdOutErr,
820-
// tt.want.psStatus[i].StdOutErr) == false {
821-
// t.Errorf("Plugins StdOutErr: got %+v, want %+v",
822-
// result[i].StdOutErr,
823-
// tt.want.psStatus[i].StdOutErr)
824-
// }
825-
// }
807+
if len(tt.want.psStatus[i].StdOutErr) != 0 &&
808+
reflect.DeepEqual(tt.pluginInfo[i].StdOutErr,
809+
tt.want.psStatus[i].StdOutErr) == false {
810+
t.Errorf("Plugins StdOutErr: got %+v, want %+v",
811+
tt.pluginInfo[i].StdOutErr,
812+
tt.want.psStatus[i].StdOutErr)
813+
}
826814
}
827815
},
828816
)

0 commit comments

Comments
 (0)