Skip to content

Commit

Permalink
Sapservices gatherer improvement (#337)
Browse files Browse the repository at this point in the history
* Remove comments from sap services entries

* Instance number extraction from sapservices entries

* Addressing review feedbacks
  • Loading branch information
CDimonaco authored Jun 25, 2024
1 parent a03e341 commit 269792f
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 36 deletions.
54 changes: 32 additions & 22 deletions internal/factsengine/gatherers/sapservices.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ var (
Type: "sap-services-reading-error",
Message: "error reading the sapservices file",
}
SapstartSIDExtractionPattern = regexp.MustCompile(`(?s)pf=[^[:space:]]+/(.*?)_.*_.*`)
SystemdSIDExtractionPattern = regexp.MustCompile(`(?s)start SAP(.*?)_.*`)
SapstartSIDExtractionPattern = regexp.MustCompile(`(?s)pf=[^[:space:]]+/(.*?)_(.*(\d{2}))_.*`)
SystemdSIDExtractionPattern = regexp.MustCompile(`(?s)start SAP(.*?)_(\d{2})`)
)

type SapServicesEntry struct {
SID string `json:"sid"`
Kind SapServicesStartupKind `json:"kind"`
Content string `json:"content"`
SID string `json:"sid"`
Kind SapServicesStartupKind `json:"kind"`
Content string `json:"content"`
Instance string `json:"instance_nr"`
}

func systemdStartup(sapServicesContent string) bool {
Expand All @@ -49,20 +50,20 @@ func sapstartStartup(sapServicesContent string) bool {
return strings.Contains(sapServicesContent, "sapstartsrv")
}

func extractSIDFromSystemdService(sapServicesContent string) string {
func extractInfoFromSystemdService(sapServicesContent string) (string, string) {
matches := SystemdSIDExtractionPattern.FindStringSubmatch(sapServicesContent)
if len(matches) != 2 {
return ""
if len(matches) != 3 {
return "", ""
}
return matches[1]
return matches[1], matches[2]
}

func extractSIDFromSapstartService(sapServicesContent string) string {
func extractInfoFromSapstartService(sapServicesContent string) (string, string) {
matches := SapstartSIDExtractionPattern.FindStringSubmatch(sapServicesContent)
if len(matches) != 2 {
return ""
if len(matches) != 4 {
return "", ""
}
return matches[1]
return matches[1], matches[3]
}

type SapServices struct {
Expand Down Expand Up @@ -129,29 +130,37 @@ func (s *SapServices) getSapServicesFileEntries() ([]SapServicesEntry, error) {
continue
}

// If the line does not start with a comment but has a comment in the middle, cut the comment
cleanedLine, _, _ := strings.Cut(scannedLine, "#")
scannedLine = cleanedLine

var kind SapServicesStartupKind
var sid string
var instance string

if systemdStartup(scannedLine) {
kind = SapServicesSystemdStartup
extractedSID := extractSIDFromSystemdService(scannedLine)
if extractedSID == "" {
extractedSID, extractedInstance := extractInfoFromSystemdService(scannedLine)
if extractedSID == "" || extractedInstance == "" {
return nil, SapServicesParsingError.Wrap(
fmt.Sprintf("could not extract sid from systemd SAP services entry: %s", scannedLine),
fmt.Sprintf("could not extract values from systemd SAP services entry: %s", scannedLine),
)
}

sid = extractedSID
instance = extractedInstance
}

if sapstartStartup(scannedLine) {
kind = SapServicesSapstartStartup
extractedSID := extractSIDFromSapstartService(scannedLine)
if extractedSID == "" {
extractedSID, extractedInstance := extractInfoFromSapstartService(scannedLine)
if extractedSID == "" || extractedInstance == "" {
return nil, SapServicesParsingError.Wrap(
fmt.Sprintf("could not extract sid from sapstartsrv SAP services entry: %s", scannedLine),
fmt.Sprintf("could not extract values from sapstartsrv SAP services entry: %s", scannedLine),
)
}
sid = extractedSID
instance = extractedInstance
}

if kind == "" {
Expand All @@ -160,9 +169,10 @@ func (s *SapServices) getSapServicesFileEntries() ([]SapServicesEntry, error) {
}

entry := SapServicesEntry{
SID: sid,
Kind: kind,
Content: scannedLine,
SID: sid,
Kind: kind,
Content: scannedLine,
Instance: instance,
}

entries = append(entries, entry)
Expand Down
129 changes: 115 additions & 14 deletions internal/factsengine/gatherers/sapservices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,29 @@ func (s *SapServicesGathererSuite) TestSapServicesGathererFileNotFound() {
s.EqualError(err, "fact gathering error: sap-services-reading-error - error reading the sapservices file: open /usr/sap/sapservices: file does not exist")
}

func (s *SapServicesGathererSuite) TestSapServicesGathererInstanceNotIdentifiedSystemd() {
tFs := afero.NewMemMapFs()
_ = afero.WriteFile(tFs, "/usr/sap/sapservices", []byte(`
#!/bin/sh
limit.descriptors=1048576
systemctl --no-ask-password start SAPS41_0
systemctl --no-ask-password start SAPS41_1
`), 0777)

fr := []entities.FactRequest{
{
Name: "sapservices",
CheckID: "check1",
Gatherer: "sapservices",
},
}

g := gatherers.NewSapServicesGatherer("/usr/sap/sapservices", tFs)
result, err := g.Gather(fr)
s.Nil(result)
s.EqualError(err, "fact gathering error: sap-services-parsing-error - error parsing the sapservices file: could not extract values from systemd SAP services entry: systemctl --no-ask-password start SAPS41_0 ")

}
func (s *SapServicesGathererSuite) TestSapServicesGathererSIDNotIdentifiedSystemd() {
tFs := afero.NewMemMapFs()
_ = afero.WriteFile(tFs, "/usr/sap/sapservices", []byte(`
Expand All @@ -54,7 +77,7 @@ systemctl --no-ask-password start SADS41_41
g := gatherers.NewSapServicesGatherer("/usr/sap/sapservices", tFs)
result, err := g.Gather(fr)
s.Nil(result)
s.EqualError(err, "fact gathering error: sap-services-parsing-error - error parsing the sapservices file: could not extract sid from systemd SAP services entry: systemctl --no-ask-password start SADS41_41")
s.EqualError(err, "fact gathering error: sap-services-parsing-error - error parsing the sapservices file: could not extract values from systemd SAP services entry: systemctl --no-ask-password start SADS41_41")

}

Expand All @@ -79,7 +102,31 @@ LD_LIBRARY_PATH=/usr/sap/S41/D40/exe:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; /
g := gatherers.NewSapServicesGatherer("/usr/sap/sapservices", tFs)
result, err := g.Gather(fr)
s.Nil(result)
s.EqualError(err, "fact gathering error: sap-services-parsing-error - error parsing the sapservices file: could not extract sid from sapstartsrv SAP services entry: LD_LIBRARY_PATH=/usr/sap/HS1/HDB11/exe:$LD_LIBRARY_PATH;export LD_LIBRARY_PATH;/usr/sap/HS1/HDB11/exe/sapstartsrv pf=/usr/sap/HS1/SYS/profile/HS1HDB11_s41db -D -u hs1adm")
s.EqualError(err, "fact gathering error: sap-services-parsing-error - error parsing the sapservices file: could not extract values from sapstartsrv SAP services entry: LD_LIBRARY_PATH=/usr/sap/HS1/HDB11/exe:$LD_LIBRARY_PATH;export LD_LIBRARY_PATH;/usr/sap/HS1/HDB11/exe/sapstartsrv pf=/usr/sap/HS1/SYS/profile/HS1HDB11_s41db -D -u hs1adm")
}

func (s *SapServicesGathererSuite) TestSapServicesGathererInstanceNotIdentifiedSapstart() {
tFs := afero.NewMemMapFs()
_ = afero.WriteFile(tFs, "/usr/sap/sapservices", []byte(`
#!/bin/sh
limit.descriptors=1048576
LD_LIBRARY_PATH=/usr/sap/HS1/HDB11/exe:$LD_LIBRARY_PATH;export LD_LIBRARY_PATH;/usr/sap/HS1/HDB11/exe/sapstartsrv pf=/usr/sap/HS1/SYS/profile/HS1_HDB1_s41db -D -u hs1adm
LD_LIBRARY_PATH=/usr/sap/S41/ASCS41/exe:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; /usr/sap/S41/ASCS41/exe/sapstartsrv pf=/usr/sap/S41/SYS/profile/S41_ASCS41_s41app -D -u s41adm
LD_LIBRARY_PATH=/usr/sap/S41/D40/exe:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; /usr/sap/S41/D40/exe/sapstartsrv pf=/usr/sap/S41/SYS/profile/S41_D40_s41app -D -u s41adm
`), 0777)

fr := []entities.FactRequest{
{
Name: "sapservices",
CheckID: "check1",
Gatherer: "sapservices",
},
}

g := gatherers.NewSapServicesGatherer("/usr/sap/sapservices", tFs)
result, err := g.Gather(fr)
s.Nil(result)
s.EqualError(err, "fact gathering error: sap-services-parsing-error - error parsing the sapservices file: could not extract values from sapstartsrv SAP services entry: LD_LIBRARY_PATH=/usr/sap/HS1/HDB11/exe:$LD_LIBRARY_PATH;export LD_LIBRARY_PATH;/usr/sap/HS1/HDB11/exe/sapstartsrv pf=/usr/sap/HS1/SYS/profile/HS1_HDB1_s41db -D -u hs1adm")
}

func (s *SapServicesGathererSuite) TestSapServicesGathererSuccessSapstart() { //nolint:dupl
Expand Down Expand Up @@ -107,16 +154,18 @@ LD_LIBRARY_PATH=/usr/sap/S41/ASCS41/exe:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH
Value: []entities.FactValue{
&entities.FactValueMap{
Value: map[string]entities.FactValue{
"sid": &entities.FactValueString{Value: "HS1"},
"kind": &entities.FactValueString{Value: "sapstartsrv"},
"content": &entities.FactValueString{Value: "LD_LIBRARY_PATH=/usr/sap/HS1/HDB11/exe:$LD_LIBRARY_PATH;export LD_LIBRARY_PATH;/usr/sap/HS1/HDB11/exe/sapstartsrv pf=/usr/sap/HS1/SYS/profile/HS1_HDB11_s41db -D -u hs1adm"},
"sid": &entities.FactValueString{Value: "HS1"},
"kind": &entities.FactValueString{Value: "sapstartsrv"},
"instance_nr": &entities.FactValueString{Value: "11"},
"content": &entities.FactValueString{Value: "LD_LIBRARY_PATH=/usr/sap/HS1/HDB11/exe:$LD_LIBRARY_PATH;export LD_LIBRARY_PATH;/usr/sap/HS1/HDB11/exe/sapstartsrv pf=/usr/sap/HS1/SYS/profile/HS1_HDB11_s41db -D -u hs1adm"},
},
},
&entities.FactValueMap{
Value: map[string]entities.FactValue{
"sid": &entities.FactValueString{Value: "S41"},
"kind": &entities.FactValueString{Value: "sapstartsrv"},
"content": &entities.FactValueString{Value: "LD_LIBRARY_PATH=/usr/sap/S41/ASCS41/exe:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; /usr/sap/S41/ASCS41/exe/sapstartsrv pf=/usr/sap/S41/SYS/profile/S41_ASCS41_s41app -D -u s41adm"},
"sid": &entities.FactValueString{Value: "S41"},
"kind": &entities.FactValueString{Value: "sapstartsrv"},
"instance_nr": &entities.FactValueString{Value: "41"},
"content": &entities.FactValueString{Value: "LD_LIBRARY_PATH=/usr/sap/S41/ASCS41/exe:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; /usr/sap/S41/ASCS41/exe/sapstartsrv pf=/usr/sap/S41/SYS/profile/S41_ASCS41_s41app -D -u s41adm"},
},
},
},
Expand Down Expand Up @@ -154,16 +203,68 @@ systemctl --no-ask-password start SAPS42_41
Value: []entities.FactValue{
&entities.FactValueMap{
Value: map[string]entities.FactValue{
"sid": &entities.FactValueString{Value: "S41"},
"kind": &entities.FactValueString{Value: "systemctl"},
"content": &entities.FactValueString{Value: "systemctl --no-ask-password start SAPS41_40"},
"sid": &entities.FactValueString{Value: "S41"},
"kind": &entities.FactValueString{Value: "systemctl"},
"instance_nr": &entities.FactValueString{Value: "40"},
"content": &entities.FactValueString{Value: "systemctl --no-ask-password start SAPS41_40"},
},
},
&entities.FactValueMap{
Value: map[string]entities.FactValue{
"sid": &entities.FactValueString{Value: "S42"},
"kind": &entities.FactValueString{Value: "systemctl"},
"instance_nr": &entities.FactValueString{Value: "41"},
"content": &entities.FactValueString{Value: "systemctl --no-ask-password start SAPS42_41"},
},
},
},
},
},
}
g := gatherers.NewSapServicesGatherer("/usr/sap/sapservices", tFs)
result, err := g.Gather(fr)
s.NoError(err)
s.EqualValues(expectedFacts, result)
}

func (s *SapServicesGathererSuite) TestSapServicesGathererSuccessWithAMiddleComment() { //nolint:dupl
tFs := afero.NewMemMapFs()
_ = afero.WriteFile(tFs, "/usr/sap/sapservices", []byte(`
#!/bin/sh
limit.descriptors=1048576
systemctl --no-ask-password start SAPHA1_10 # sapstartsrv pf=/usr/sap/HA1/SYS/profile/HA1_ERS10_sapha1er
systemctl --no-ask-password start SAPS42_41
`), 0777)

fr := []entities.FactRequest{
{
Name: "sapservices",
CheckID: "check1",
Gatherer: "sapservices",
},
}

expectedFacts := []entities.Fact{
{
Name: "sapservices",
CheckID: "check1",
Value: &entities.FactValueList{
Value: []entities.FactValue{
&entities.FactValueMap{
Value: map[string]entities.FactValue{
"sid": &entities.FactValueString{Value: "HA1"},
"kind": &entities.FactValueString{Value: "systemctl"},
"instance_nr": &entities.FactValueString{Value: "10"},

"content": &entities.FactValueString{Value: "systemctl --no-ask-password start SAPHA1_10 "},
},
},
&entities.FactValueMap{
Value: map[string]entities.FactValue{
"sid": &entities.FactValueString{Value: "S42"},
"kind": &entities.FactValueString{Value: "systemctl"},
"content": &entities.FactValueString{Value: "systemctl --no-ask-password start SAPS42_41"},
"sid": &entities.FactValueString{Value: "S42"},
"kind": &entities.FactValueString{Value: "systemctl"},
"instance_nr": &entities.FactValueString{Value: "41"},
"content": &entities.FactValueString{Value: "systemctl --no-ask-password start SAPS42_41"},
},
},
},
Expand Down

0 comments on commit 269792f

Please sign in to comment.