-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implemente disp+work gatherer * Add gatherer to standard gatherers list
- Loading branch information
Showing
6 changed files
with
381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package gatherers | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"path/filepath" | ||
"regexp" | ||
"strings" | ||
|
||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/afero" | ||
"github.com/trento-project/agent/internal/core/sapsystem" | ||
"github.com/trento-project/agent/pkg/factsengine/entities" | ||
"github.com/trento-project/agent/pkg/utils" | ||
) | ||
|
||
const ( | ||
DispWorkGathererName = "disp+work" | ||
) | ||
|
||
// nolint:gochecknoglobals | ||
var ( | ||
DispWorkFileSystemError = entities.FactGatheringError{ | ||
Type: "dispwork-file-system-error", | ||
Message: "error reading the file system", | ||
} | ||
|
||
DispWorkCommandError = entities.FactGatheringError{ | ||
Type: "dispwork-command-error", | ||
Message: "error running disp+work command", | ||
} | ||
|
||
DispWorkDecodingError = entities.FactGatheringError{ | ||
Type: "dispwork-decoding-error", | ||
Message: "error decoding disp+work output", | ||
} | ||
|
||
// the names groups values are the values used to compose the resulting fact value map | ||
entriesPatternCompiled = regexp.MustCompile("(?m)" + | ||
"^kernel release\\s+(?P<kernel_release>.*)$|" + | ||
"^compilation mode\\s+(?P<compilation_mode>.*)$|" + | ||
"^patch number\\s+(?P<patch_number>.*)$") | ||
|
||
groupedNames = entriesPatternCompiled.SubexpNames()[1:] | ||
) | ||
|
||
type DispWorkGatherer struct { | ||
fs afero.Fs | ||
executor utils.CommandExecutor | ||
} | ||
|
||
type dispWorkData struct { | ||
CompilationMode string `json:"compilation_mode"` | ||
KernelRelease string `json:"kernel_release"` | ||
PatchNumber string `json:"patch_number"` | ||
} | ||
|
||
func NewDefaultDispWorkGatherer() *DispWorkGatherer { | ||
return NewDispWorkGatherer(afero.NewOsFs(), utils.Executor{}) | ||
} | ||
|
||
func NewDispWorkGatherer(fs afero.Fs, executor utils.CommandExecutor) *DispWorkGatherer { | ||
return &DispWorkGatherer{ | ||
fs: fs, | ||
executor: executor, | ||
} | ||
} | ||
|
||
func (g *DispWorkGatherer) Gather(factsRequests []entities.FactRequest) ([]entities.Fact, error) { | ||
facts := []entities.Fact{} | ||
log.Infof("Starting %s facts gathering process", DispWorkGathererName) | ||
|
||
systemPaths, err := sapsystem.FindSystems(g.fs) | ||
if err != nil { | ||
return nil, DispWorkFileSystemError.Wrap(err.Error()) | ||
} | ||
|
||
dispWorkMap := make(map[string]dispWorkData) | ||
|
||
for _, systemPath := range systemPaths { | ||
sid := filepath.Base(systemPath) | ||
sapUser := fmt.Sprintf("%sadm", strings.ToLower(sid)) | ||
|
||
dispWorkOutput, err := g.executor.Exec("su", "-", sapUser, "-c", "\"disp+work\"") | ||
if err != nil { | ||
gatheringError := DispWorkCommandError.Wrap(err.Error()) | ||
log.Error(gatheringError) | ||
dispWorkMap[sid] = dispWorkData{} // fill with empty data | ||
continue | ||
} | ||
|
||
result := fillRegexpGroups(string(dispWorkOutput)) | ||
|
||
dispWorkMap[sid] = dispWorkData{ | ||
CompilationMode: result["compilation_mode"], | ||
KernelRelease: result["kernel_release"], | ||
PatchNumber: result["patch_number"], | ||
} | ||
} | ||
|
||
factValue, err := dispWorkDataToFactValue(dispWorkMap) | ||
if err != nil { | ||
gatheringError := DispWorkDecodingError.Wrap(err.Error()) | ||
log.Error(gatheringError) | ||
return nil, gatheringError | ||
} | ||
|
||
for _, factReq := range factsRequests { | ||
facts = append(facts, entities.NewFactGatheredWithRequest(factReq, factValue)) | ||
} | ||
|
||
log.Infof("Requested %s facts gathered", DispWorkGathererName) | ||
return facts, nil | ||
} | ||
|
||
func fillRegexpGroups(output string) map[string]string { | ||
result := make(map[string]string) | ||
for _, match := range entriesPatternCompiled.FindAllStringSubmatch(output, -1) { | ||
for i, name := range groupedNames { | ||
if value, found := result[name]; found && value != "" { | ||
continue | ||
} | ||
result[name] = match[i+1] | ||
} | ||
} | ||
return result | ||
} | ||
|
||
func dispWorkDataToFactValue(data map[string]dispWorkData) (entities.FactValue, error) { | ||
marshalled, err := json.Marshal(&data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var unmarshalled map[string]interface{} | ||
err = json.Unmarshal(marshalled, &unmarshalled) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return entities.NewFactValue(unmarshalled) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package gatherers_test | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
"os" | ||
"testing" | ||
|
||
"github.com/spf13/afero" | ||
"github.com/stretchr/testify/suite" | ||
"github.com/trento-project/agent/internal/factsengine/gatherers" | ||
"github.com/trento-project/agent/pkg/factsengine/entities" | ||
utilsMocks "github.com/trento-project/agent/pkg/utils/mocks" | ||
"github.com/trento-project/agent/test/helpers" | ||
) | ||
|
||
type DispWorkGathererTestSuite struct { | ||
suite.Suite | ||
fs afero.Fs | ||
mockExecutor *utilsMocks.CommandExecutor | ||
} | ||
|
||
func TestDispWorkGathererSuite(t *testing.T) { | ||
suite.Run(t, new(DispWorkGathererTestSuite)) | ||
} | ||
|
||
func (suite *DispWorkGathererTestSuite) SetupTest() { | ||
fs := afero.NewMemMapFs() | ||
err := fs.MkdirAll("/usr/sap/PRD", 0644) | ||
suite.NoError(err) | ||
err = fs.MkdirAll("/usr/sap/QAS", 0644) | ||
suite.NoError(err) | ||
err = fs.MkdirAll("/usr/sap/QA2", 0644) | ||
suite.NoError(err) | ||
err = fs.MkdirAll("/usr/sap/DEV", 0644) | ||
suite.NoError(err) | ||
|
||
suite.fs = fs | ||
suite.mockExecutor = new(utilsMocks.CommandExecutor) | ||
} | ||
|
||
func (suite *DispWorkGathererTestSuite) TestDispWorkGatheringSuccess() { | ||
validOutputFile, _ := os.Open(helpers.GetFixturePath("gatherers/dispwork-valid.output")) | ||
validOutput, _ := io.ReadAll(validOutputFile) | ||
partialOutputFile, _ := os.Open(helpers.GetFixturePath("gatherers/dispwork-partial.output")) | ||
partialOutput, _ := io.ReadAll(partialOutputFile) | ||
unsortedOutputFile, _ := os.Open(helpers.GetFixturePath("gatherers/dispwork-unsorted.output")) | ||
unsortedOutput, _ := io.ReadAll(unsortedOutputFile) | ||
suite.mockExecutor. | ||
On("Exec", "su", "-", "prdadm", "-c", "\"disp+work\""). | ||
Return(validOutput, nil). | ||
On("Exec", "su", "-", "qasadm", "-c", "\"disp+work\""). | ||
Return(partialOutput, nil). | ||
On("Exec", "su", "-", "qa2adm", "-c", "\"disp+work\""). | ||
Return(unsortedOutput, nil). | ||
On("Exec", "su", "-", "devadm", "-c", "\"disp+work\""). | ||
Return(nil, errors.New("some error")) | ||
|
||
g := gatherers.NewDispWorkGatherer(suite.fs, suite.mockExecutor) | ||
|
||
fr := []entities.FactRequest{ | ||
{ | ||
Name: "dispwork", | ||
CheckID: "check1", | ||
Gatherer: "disp+work", | ||
}, | ||
} | ||
|
||
expectedResults := []entities.Fact{{ | ||
Name: "dispwork", | ||
CheckID: "check1", | ||
Value: &entities.FactValueMap{ | ||
Value: map[string]entities.FactValue{ | ||
"PRD": &entities.FactValueMap{ | ||
Value: map[string]entities.FactValue{ | ||
"compilation_mode": &entities.FactValueString{Value: "UNICODE"}, | ||
"kernel_release": &entities.FactValueString{Value: "753"}, | ||
"patch_number": &entities.FactValueString{Value: "900"}, | ||
}, | ||
}, | ||
"QAS": &entities.FactValueMap{ | ||
Value: map[string]entities.FactValue{ | ||
"compilation_mode": &entities.FactValueString{Value: ""}, | ||
"kernel_release": &entities.FactValueString{Value: "753"}, | ||
"patch_number": &entities.FactValueString{Value: ""}, | ||
}, | ||
}, | ||
"QA2": &entities.FactValueMap{ | ||
Value: map[string]entities.FactValue{ | ||
"compilation_mode": &entities.FactValueString{Value: "UNICODE"}, | ||
"kernel_release": &entities.FactValueString{Value: "753"}, | ||
"patch_number": &entities.FactValueString{Value: "900"}, | ||
}, | ||
}, | ||
"DEV": &entities.FactValueMap{ | ||
Value: map[string]entities.FactValue{ | ||
"compilation_mode": &entities.FactValueString{Value: ""}, | ||
"kernel_release": &entities.FactValueString{Value: ""}, | ||
"patch_number": &entities.FactValueString{Value: ""}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}} | ||
|
||
result, err := g.Gather(fr) | ||
suite.NoError(err) | ||
suite.EqualValues(expectedResults, result) | ||
} | ||
|
||
func (suite *DispWorkGathererTestSuite) TestDispWorkGatheringEmptyFileSystem() { | ||
g := gatherers.NewDispWorkGatherer(afero.NewMemMapFs(), suite.mockExecutor) | ||
|
||
fr := []entities.FactRequest{ | ||
{ | ||
Name: "dispwork", | ||
CheckID: "check1", | ||
Gatherer: "disp+work", | ||
}, | ||
} | ||
|
||
expectedResults := []entities.Fact{{ | ||
Name: "dispwork", | ||
CheckID: "check1", | ||
Value: &entities.FactValueMap{ | ||
Value: map[string]entities.FactValue{}, | ||
}, | ||
}} | ||
|
||
result, err := g.Gather(fr) | ||
suite.NoError(err) | ||
suite.EqualValues(expectedResults, result) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
|
||
-------------------- | ||
disp+work information | ||
-------------------- | ||
|
||
kernel release 753 | ||
|
||
kernel make variant 753_REL | ||
|
||
compiled on Linux GNU SLES-11 x86_64 cc4.8.5 use-pr211015 for linuxx86_64 | ||
|
||
compiled for 64 BIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
|
||
-------------------- | ||
disp+work information | ||
-------------------- | ||
|
||
patch number 900 | ||
|
||
kernel make variant 753_REL | ||
|
||
compilation mode UNICODE | ||
|
||
compiled on Linux GNU SLES-11 x86_64 cc4.8.5 use-pr211015 for linuxx86_64 | ||
|
||
compiled for 64 BIT | ||
|
||
kernel release 753 | ||
|
||
compile time Oct 16 2021 00:21:02 | ||
|
||
Wed Oct 18 13:22:52 2023 | ||
Loading DB library '/usr/sap/NWP/SYS/exe/run/dbhdbslib.so' ... | ||
Library '/usr/sap/NWP/SYS/exe/run/dbhdbslib.so' loaded | ||
Version of '/usr/sap/NWP/SYS/exe/run/dbhdbslib.so' is "753.02", patchlevel (0.900) | ||
|
||
update level 0 | ||
|
||
|
||
source id 0.900 | ||
|
||
RKS compatibility level 1 | ||
|
||
DW_GUI compatibility level 900 | ||
|
||
|
||
--------------------- | ||
supported environment | ||
--------------------- | ||
|
||
database (SAP, table SVERS) 740 | ||
750 | ||
751 | ||
752 | ||
769 | ||
|
||
operating system | ||
Linux |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
|
||
-------------------- | ||
disp+work information | ||
-------------------- | ||
|
||
kernel release 753 | ||
|
||
kernel make variant 753_REL | ||
|
||
compiled on Linux GNU SLES-11 x86_64 cc4.8.5 use-pr211015 for linuxx86_64 | ||
|
||
compiled for 64 BIT | ||
|
||
compilation mode UNICODE | ||
|
||
compile time Oct 16 2021 00:21:02 | ||
|
||
Wed Oct 18 13:22:52 2023 | ||
Loading DB library '/usr/sap/NWP/SYS/exe/run/dbhdbslib.so' ... | ||
Library '/usr/sap/NWP/SYS/exe/run/dbhdbslib.so' loaded | ||
Version of '/usr/sap/NWP/SYS/exe/run/dbhdbslib.so' is "753.02", patchlevel (0.900) | ||
|
||
update level 0 | ||
|
||
patch number 900 | ||
|
||
source id 0.900 | ||
|
||
RKS compatibility level 1 | ||
|
||
DW_GUI compatibility level 900 | ||
|
||
|
||
--------------------- | ||
supported environment | ||
--------------------- | ||
|
||
database (SAP, table SVERS) 740 | ||
750 | ||
751 | ||
752 | ||
769 | ||
|
||
operating system | ||
Linux |