diff --git a/internal/core/sapsystem/sapsystem.go b/internal/core/sapsystem/sapsystem.go index e1c1c494..73b8ee21 100644 --- a/internal/core/sapsystem/sapsystem.go +++ b/internal/core/sapsystem/sapsystem.go @@ -177,14 +177,14 @@ func NewSAPSystem( } if systemType == Database { - databaseList, err := getDatabases(fs, sid) + databaseList, err := GetDatabases(fs, sid) if err != nil { log.Errorf("Error getting the database list: %s", err) } else { system.Databases = databaseList } } else if systemType == Application { - addr, err := getDBAddress(system) + addr, err := system.GetDBAddress() if err != nil { log.Errorf("Error getting the database address: %s", err) } else { @@ -195,6 +195,29 @@ func NewSAPSystem( return system, nil } +func (system *SAPSystem) GetDBAddress() (string, error) { + sapdbhost, found := system.Profile["SAPDBHOST"] + if !found { + return "", fmt.Errorf("SAPDBHOST field not found in the SAP profile") + } + + addrList, err := net.LookupIP(sapdbhost) + if err != nil { + return "", fmt.Errorf("could not resolve \"%s\" hostname", sapdbhost) + } + + // Get 1st IPv4 address + for _, addr := range addrList { + addrStr := addr.String() + ip := net.ParseIP(addrStr) + if ip.To4() != nil { + return addrStr, nil + } + } + + return "", fmt.Errorf("could not get any IPv4 address") +} + // FindSystems returns the installed SAP systems in the /usr/sap folder // It returns the list of found SAP system paths func FindSystems(fs afero.Fs) ([]string, error) { @@ -282,31 +305,54 @@ func GetProfileData(fs afero.Fs, profilePath string) (map[string]string, error) return profile, nil } -func getProfilePath(sysPath string) string { - return path.Join(sysPath, "SYS", "profile", SapDefaultProfile) -} - -func getDBAddress(system *SAPSystem) (string, error) { - sapdbhost, found := system.Profile["SAPDBHOST"] - if !found { - return "", fmt.Errorf("SAPDBHOST field not found in the SAP profile") - } - - addrList, err := net.LookupIP(sapdbhost) +// The content type of the databases.lst looks like +// # DATABASE:CONTAINER:USER:GROUP:USERID:GROUPID:HOST:SQLPORT:ACTIVE +// PRD::::::hana02:30015:yes +// DEV::::::hana02:30044:yes +func GetDatabases(fs afero.Fs, sid string) ([]*DatabaseData, error) { + databasesListPath := fmt.Sprintf( + "/usr/sap/%s/SYS/global/hdb/mdc/databases.lst", sid) + databasesListFile, err := fs.Open(databasesListPath) if err != nil { - return "", fmt.Errorf("could not resolve \"%s\" hostname", sapdbhost) + return nil, errors.Wrap(err, "could not open the databases list file") } - // Get 1st IPv4 address - for _, addr := range addrList { - addrStr := addr.String() - ip := net.ParseIP(addrStr) - if ip.To4() != nil { - return addrStr, nil + defer databasesListFile.Close() + + databaseScanner := bufio.NewScanner(databasesListFile) + databaseList := make([]*DatabaseData, 0) + + for databaseScanner.Scan() { + line := databaseScanner.Text() + if strings.HasPrefix(line, "#") || len(strings.TrimSpace(line)) == 0 { + continue + } + + data := strings.Split(line, ":") + if len(data) != 9 { + continue + } + + databaseEntry := &DatabaseData{ + Database: data[0], + Container: data[1], + User: data[2], + Group: data[3], + UserID: data[4], + GroupID: data[5], + Host: data[6], + SQLPort: data[7], + Active: data[8], } + + databaseList = append(databaseList, databaseEntry) } - return "", fmt.Errorf("could not get any IPv4 address") + return databaseList, nil +} + +func getProfilePath(sysPath string) string { + return path.Join(sysPath, "SYS", "profile", SapDefaultProfile) } func detectSystemID(fs afero.Fs, executor utils.CommandExecutor, sType SystemType, sid string) (string, error) { @@ -373,49 +419,3 @@ func getUniqueIDDiagnostics(fs afero.Fs) (string, error) { id := Md5sum(machineID) return id, nil } - -// The content type of the databases.lst looks like -// # DATABASE:CONTAINER:USER:GROUP:USERID:GROUPID:HOST:SQLPORT:ACTIVE -// PRD::::::hana02:30015:yes -// DEV::::::hana02:30044:yes -func getDatabases(fs afero.Fs, sid string) ([]*DatabaseData, error) { - databasesListPath := fmt.Sprintf( - "/usr/sap/%s/SYS/global/hdb/mdc/databases.lst", sid) - databasesListFile, err := fs.Open(databasesListPath) - if err != nil { - return nil, errors.Wrap(err, "could not open the databases list file") - } - - defer databasesListFile.Close() - - databaseScanner := bufio.NewScanner(databasesListFile) - databaseList := make([]*DatabaseData, 0) - - for databaseScanner.Scan() { - line := databaseScanner.Text() - if strings.HasPrefix(line, "#") || len(strings.TrimSpace(line)) == 0 { - continue - } - - data := strings.Split(line, ":") - if len(data) != 9 { - continue - } - - databaseEntry := &DatabaseData{ - Database: data[0], - Container: data[1], - User: data[2], - Group: data[3], - UserID: data[4], - GroupID: data[5], - Host: data[6], - SQLPort: data[7], - Active: data[8], - } - - databaseList = append(databaseList, databaseEntry) - } - - return databaseList, nil -} diff --git a/internal/core/sapsystem/sapsystem_test.go b/internal/core/sapsystem/sapsystem_test.go index e4e8a8aa..8ee87e40 100644 --- a/internal/core/sapsystem/sapsystem_test.go +++ b/internal/core/sapsystem/sapsystem_test.go @@ -1,17 +1,18 @@ -//nolint:exhaustruct,gosec,nosnakecase,gochecknoglobals,lll,dupl -package sapsystem +//nolint:nosnakecase,dupl +package sapsystem_test import ( - "fmt" "io" "os" "testing" "github.com/spf13/afero" "github.com/stretchr/testify/suite" + "github.com/trento-project/agent/internal/core/sapsystem" "github.com/trento-project/agent/internal/core/sapsystem/sapcontrolapi" sapcontrol "github.com/trento-project/agent/internal/core/sapsystem/sapcontrolapi" sapControlMocks "github.com/trento-project/agent/internal/core/sapsystem/sapcontrolapi/mocks" + "github.com/trento-project/agent/pkg/utils/mocks" utilsMocks "github.com/trento-project/agent/pkg/utils/mocks" "github.com/trento-project/agent/test/helpers" ) @@ -25,7 +26,7 @@ func TestSAPSystemTestSuite(t *testing.T) { suite.Run(t, testSuite) } -func fakeNewWebService(instName string) sapcontrolapi.WebService { +func fakeNewWebService(instName string, features string) sapcontrolapi.WebService { mockWebService := new(sapControlMocks.WebService) mockWebService.On("GetInstanceProperties").Return(&sapcontrol.GetInstancePropertiesResponse{ @@ -53,12 +54,67 @@ func fakeNewWebService(instName string) sapcontrolapi.WebService { }, nil) mockWebService.On("GetSystemInstanceList").Return(&sapcontrol.GetSystemInstanceListResponse{ - Instances: []*sapcontrol.SAPInstance{}, + Instances: []*sapcontrol.SAPInstance{ + { + Hostname: "host", + InstanceNr: 0, + HttpPort: 50013, + HttpsPort: 50014, + StartPriority: "0.3", + Features: features, + Dispstatus: sapcontrol.STATECOLOR_GREEN, + }, + }, }, nil) return mockWebService } +func mockDEVFileSystem() (afero.Fs, error) { + appFS := afero.NewMemMapFs() + err := appFS.MkdirAll("/usr/sap/DEV/ASCS01", 0755) + if err != nil { + return nil, err + } + err = afero.WriteFile(appFS, "/usr/sap/DEV/SYS/profile/DEFAULT.PFL", []byte{}, 0644) + if err != nil { + return nil, err + } + err = appFS.MkdirAll("/usr/sap/DEV/SYS/global/hdb/custom/config/", 0755) + if err != nil { + return nil, err + } + return appFS, nil +} + +func mockLandscapeHostConfiguration() []byte { + lFile, err := os.Open(helpers.GetFixturePath("discovery/sap_system/landscape_host_configuration")) + if err != nil { + panic(err) + } + content, err := io.ReadAll(lFile) + if err != nil { + panic(err) + } + return content +} + +func mockHdbnsutilSrstate() []byte { + lFile, err := os.Open(helpers.GetFixturePath("discovery/sap_system/hdbnsutil_srstate")) + if err != nil { + panic(err) + } + content, err := io.ReadAll(lFile) + if err != nil { + panic(err) + } + return content +} + +func mockSappfpar() []byte { + return []byte("systemId") +} + func (suite *SAPSystemTestSuite) TestNewSAPSystemsList() { appFS := afero.NewMemMapFs() err := appFS.MkdirAll("/usr/sap/DEV/ASCS01", 0755) @@ -73,10 +129,10 @@ func (suite *SAPSystemTestSuite) TestNewSAPSystemsList() { mockCommand := new(utilsMocks.CommandExecutor) mockWebServiceConnector := new(sapControlMocks.WebServiceConnector) - mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("ASCS01")) - mockWebServiceConnector.On("New", "02").Return(fakeNewWebService("ERS02")) + mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("ASCS01", "")) + mockWebServiceConnector.On("New", "02").Return(fakeNewWebService("ERS02", "")) - systems, err := NewSAPSystemsList(appFS, mockCommand, mockWebServiceConnector) + systems, err := sapsystem.NewSAPSystemsList(appFS, mockCommand, mockWebServiceConnector) suite.Len(systems, 2) suite.Equal(systems[0].SID, "DEV") @@ -85,11 +141,10 @@ func (suite *SAPSystemTestSuite) TestNewSAPSystemsList() { } func (suite *SAPSystemTestSuite) TestNewSAPSystem() { - mockCommand := new(utilsMocks.CommandExecutor) mockWebServiceConnector := new(sapControlMocks.WebServiceConnector) - mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("ASCS01")) - mockWebServiceConnector.On("New", "02").Return(fakeNewWebService("ERS02")) + mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("ASCS01", "")) + mockWebServiceConnector.On("New", "02").Return(fakeNewWebService("ERS02", "")) appFS := afero.NewMemMapFs() err := appFS.MkdirAll("/usr/sap/DEV/ASCS01", 0755) @@ -105,7 +160,7 @@ func (suite *SAPSystemTestSuite) TestNewSAPSystem() { err = afero.WriteFile(appFS, "/usr/sap/DEV/SYS/profile/DEFAULT.PFL", profileContent, 0644) suite.NoError(err) - expectedProfile := SAPProfile{ + expectedProfile := sapsystem.SAPProfile{ "SAPSYSTEMNAME": "HA1", "SAPGLOBALHOST": "sapha1as", "rdisp/mshost": "sapha1as", @@ -136,15 +191,15 @@ func (suite *SAPSystemTestSuite) TestNewSAPSystem() { "vmcj/enable": "off", } - cmd := fmt.Sprintf(sappfparCmd, "DEV") - mockCommand.On("Exec", "su", "-lc", cmd, "devadm").Return(mockSappfpar(), nil) + sappfparCmd := "sappfpar SAPSYSTEMNAME SAPGLOBALHOST SAPFQDN SAPDBHOST dbs/hdb/dbname dbs/hdb/schema rdisp/msp/msserv rdisp/msserv_internal name=DEV" + mockCommand.On("Exec", "su", "-lc", sappfparCmd, "devadm").Return(mockSappfpar(), nil) - system, err := NewSAPSystem(appFS, mockCommand, mockWebServiceConnector, "/usr/sap/DEV") + system, err := sapsystem.NewSAPSystem(appFS, mockCommand, mockWebServiceConnector, "/usr/sap/DEV") - suite.Equal(Unknown, system.Type) - suite.Contains(system.Instances[0].Name, "ASCS01") - suite.Contains(system.Instances[1].Name, "ERS02") - suite.Equal(system.Profile, expectedProfile) + suite.Equal(sapsystem.Unknown, system.Type) + suite.Contains("ASCS01", system.Instances[0].Name) + suite.Contains("ERS02", system.Instances[1].Name) + suite.Equal(expectedProfile, system.Profile) suite.NoError(err) } @@ -160,41 +215,9 @@ func mockSystemReplicationStatus() []byte { return content } -func mockLandscapeHostConfiguration() []byte { - lFile, err := os.Open(helpers.GetFixturePath("discovery/sap_system/landscape_host_configuration")) - if err != nil { - panic(err) - } - content, err := io.ReadAll(lFile) - if err != nil { - panic(err) - } - return content -} - -func mockHdbnsutilSrstate() []byte { - lFile, err := os.Open(helpers.GetFixturePath("discovery/sap_system/hdbnsutil_srstate")) - if err != nil { - panic(err) - } - content, err := io.ReadAll(lFile) - if err != nil { - panic(err) - } - return content -} - -func mockSappfpar() []byte { - return []byte("systemId") -} - -func (suite *SAPSystemTestSuite) TestDetectSystemIdDatabase() { - appFS := afero.NewMemMapFs() - mockCommand := new(utilsMocks.CommandExecutor) - - err := appFS.MkdirAll("/usr/sap/DEV/SYS/global/hdb/custom/config/", 0755) +func (suite *SAPSystemTestSuite) TestDetectSystemId_Database() { + appFS, err := mockDEVFileSystem() suite.NoError(err) - nameserverContent := []byte(` key1 = value1 id = systemId @@ -206,41 +229,45 @@ key2 = value2 nameserverContent, 0644) suite.NoError(err) - id, err := detectSystemID(appFS, mockCommand, Database, "DEV") - - suite.NoError(err) - suite.Equal("089d1a278481b86e821237f8e98e6de7", id) -} - -func (suite *SAPSystemTestSuite) TestDetectSystemIdApplication() { - appFS := afero.NewMemMapFs() mockCommand := new(utilsMocks.CommandExecutor) + mockWebServiceConnector := new(sapControlMocks.WebServiceConnector) - cmd := fmt.Sprintf(sappfparCmd, "DEV") - mockCommand.On("Exec", "su", "-lc", cmd, "devadm").Return(mockSappfpar(), nil) + mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("HDB00", "HDB")) + mockCommand. + On("Exec", "su", "-lc", "python /usr/sap/DEV/HDB00/exe/python_support/systemReplicationStatus.py --sapcontrol=1", "devadm"). + Return(mockSystemReplicationStatus(), nil). + On("Exec", "su", "-lc", "python /usr/sap/DEV/HDB00/exe/python_support/landscapeHostConfiguration.py --sapcontrol=1", "devadm"). + Return(mockLandscapeHostConfiguration(), nil). + On("Exec", "su", "-lc", "/usr/sap/DEV/HDB00/exe/hdbnsutil -sr_state -sapcontrol=1", "devadm"). + Return(mockHdbnsutilSrstate(), nil) - id, err := detectSystemID(appFS, mockCommand, Application, "DEV") + system, err := sapsystem.NewSAPSystem(appFS, mockCommand, mockWebServiceConnector, "/usr/sap/DEV") + suite.Equal("089d1a278481b86e821237f8e98e6de7", system.ID) + suite.Equal(sapsystem.Database, system.Type) suite.NoError(err) - suite.Equal("089d1a278481b86e821237f8e98e6de7", id) } -func (suite *SAPSystemTestSuite) TestSetSystemIdOther() { - appFS := afero.NewMemMapFs() +func (suite *SAPSystemTestSuite) TestDetectSystemId_Application() { + appFS, err := mockDEVFileSystem() + suite.NoError(err) mockCommand := new(utilsMocks.CommandExecutor) + mockWebServiceConnector := new(sapControlMocks.WebServiceConnector) - id, err := detectSystemID(appFS, mockCommand, Unknown, "DEV") + mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("HDB00", "MESSAGESERVER|ENQUE")) + sappfparCmd := "sappfpar SAPSYSTEMNAME SAPGLOBALHOST SAPFQDN SAPDBHOST dbs/hdb/dbname dbs/hdb/schema rdisp/msp/msserv rdisp/msserv_internal name=DEV" + mockCommand.On("Exec", "su", "-lc", sappfparCmd, "devadm").Return(mockSappfpar(), nil) + system, err := sapsystem.NewSAPSystem(appFS, mockCommand, mockWebServiceConnector, "/usr/sap/DEV") + + suite.Equal("089d1a278481b86e821237f8e98e6de7", system.ID) + suite.Equal(sapsystem.Application, system.Type) suite.NoError(err) - suite.Equal("-", id) } -func (suite *SAPSystemTestSuite) TestDetectSystemIdDiagnostics() { - appFS := afero.NewMemMapFs() - mockCommand := new(utilsMocks.CommandExecutor) - err := appFS.MkdirAll("/etc", 0755) +func (suite *SAPSystemTestSuite) TestDetectSystemId_Diagnostics() { + appFS, err := mockDEVFileSystem() suite.NoError(err) - machineIDContent := []byte(`dummy-machine-id`) err = afero.WriteFile( @@ -248,10 +275,31 @@ func (suite *SAPSystemTestSuite) TestDetectSystemIdDiagnostics() { machineIDContent, 0644) suite.NoError(err) - id, err := detectSystemID(appFS, mockCommand, DiagnosticsAgent, "DAA") + mockCommand := new(utilsMocks.CommandExecutor) + mockWebServiceConnector := new(sapControlMocks.WebServiceConnector) + + mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("HDB00", "SMDAGENT")) + + system, err := sapsystem.NewSAPSystem(appFS, mockCommand, mockWebServiceConnector, "/usr/sap/DEV") + + suite.Equal("d3d5dd5ec501127e0011a2531e3b11ff", system.ID) + suite.Equal(sapsystem.DiagnosticsAgent, system.Type) + suite.NoError(err) +} + +func (suite *SAPSystemTestSuite) TestDetectSystemId_Unknown() { + appFS, err := mockDEVFileSystem() + suite.NoError(err) + mockCommand := new(utilsMocks.CommandExecutor) + mockWebServiceConnector := new(sapControlMocks.WebServiceConnector) + + mockWebServiceConnector.On("New", "01").Return(fakeNewWebService("HDB00", "UNKNOWN")) + system, err := sapsystem.NewSAPSystem(appFS, mockCommand, mockWebServiceConnector, "/usr/sap/DEV") + + suite.Equal("-", system.ID) + suite.Equal(sapsystem.Unknown, system.Type) suite.NoError(err) - suite.Equal("d3d5dd5ec501127e0011a2531e3b11ff", id) } func (suite *SAPSystemTestSuite) TestGetDatabases() { @@ -272,9 +320,9 @@ ERR::: nameserverContent, 0644) suite.NoError(err) - dbs, err := getDatabases(appFS, "DEV") + dbs, err := sapsystem.GetDatabases(appFS, "DEV") - expectedDbs := []*DatabaseData{ + expectedDbs := []*sapsystem.DatabaseData{ { Database: "PRD", Container: "", @@ -305,15 +353,15 @@ ERR::: } func (suite *SAPSystemTestSuite) TestGetDBAddress() { - s := &SAPSystem{Profile: SAPProfile{"SAPDBHOST": "localhost"}} - addr, err := getDBAddress(s) + s := &sapsystem.SAPSystem{Profile: sapsystem.SAPProfile{"SAPDBHOST": "localhost"}} + addr, err := s.GetDBAddress() suite.NoError(err) suite.Equal("127.0.0.1", addr) } func (suite *SAPSystemTestSuite) TestGetDBAddress_ResolveError() { - s := &SAPSystem{Profile: SAPProfile{"SAPDBHOST": "other"}} - _, err := getDBAddress(s) + s := &sapsystem.SAPSystem{Profile: sapsystem.SAPProfile{"SAPDBHOST": "other"}} + _, err := s.GetDBAddress() suite.EqualError(err, "could not resolve \"other\" hostname") } @@ -404,14 +452,14 @@ func (suite *SAPSystemTestSuite) TestNewSAPInstanceDatabase() { mockHdbnsutilSrstate(), nil, ) - sapInstance, _ := NewSAPInstance(mockWebService, mockCommand) + sapInstance, _ := sapsystem.NewSAPInstance(mockWebService, mockCommand) host, _ := os.Hostname() - expectedInstance := &SAPInstance{ + expectedInstance := &sapsystem.SAPInstance{ Name: "HDB00", - Type: Database, + Type: sapsystem.Database, Host: host, - SAPControl: &SAPControl{ + SAPControl: &sapsystem.SAPControl{ Processes: []*sapcontrol.OSProcess{ { Name: "enserver", @@ -475,7 +523,7 @@ func (suite *SAPSystemTestSuite) TestNewSAPInstanceDatabase() { }, }, }, - SystemReplication: SystemReplication{ + SystemReplication: sapsystem.SystemReplication{ "service/hana01/30001/SHIPPED_LOG_POSITION_TIME": "2021-06-12 12:43:13.059197", "service/hana01/30001/LAST_LOG_POSITION_TIME": "2021-06-12 12:43:13.059197", "service/hana01/30001/SHIPPED_FULL_REPLICA_DURATION": "4060418", @@ -518,7 +566,7 @@ func (suite *SAPSystemTestSuite) TestNewSAPInstanceDatabase() { "site/1/SITE_NAME": "Site1", "local_site_id": "1", }, - HostConfiguration: HostConfiguration{ + HostConfiguration: sapsystem.HostConfiguration{ "hostActualRoles": "worker", "removeStatus": "", "nameServerConfigRole": "master 1", @@ -538,7 +586,7 @@ func (suite *SAPSystemTestSuite) TestNewSAPInstanceDatabase() { "hostStatus": "ok", "storagePartition": "1", }, - HdbnsutilSRstate: HdbnsutilSRstate{ + HdbnsutilSRstate: sapsystem.HdbnsutilSRstate{ "online": "true", "mode": "primary", "operation_mode": "primary", @@ -640,14 +688,14 @@ func (suite *SAPSystemTestSuite) TestNewSAPInstanceApp() { }, }, nil) - sapInstance, _ := NewSAPInstance(mockWebService, new(utilsMocks.CommandExecutor)) + sapInstance, _ := sapsystem.NewSAPInstance(mockWebService, new(utilsMocks.CommandExecutor)) host, _ := os.Hostname() - expectedInstance := &SAPInstance{ + expectedInstance := &sapsystem.SAPInstance{ Name: "HDB00", - Type: Application, + Type: sapsystem.Application, Host: host, - SAPControl: &SAPControl{ + SAPControl: &sapsystem.SAPControl{ Processes: []*sapcontrol.OSProcess{ { Name: "enserver", @@ -711,28 +759,28 @@ func (suite *SAPSystemTestSuite) TestNewSAPInstanceApp() { }, }, }, - SystemReplication: SystemReplication(nil), - HostConfiguration: HostConfiguration(nil), - HdbnsutilSRstate: HdbnsutilSRstate(nil), + SystemReplication: sapsystem.SystemReplication(nil), + HostConfiguration: sapsystem.HostConfiguration(nil), + HdbnsutilSRstate: sapsystem.HdbnsutilSRstate(nil), } suite.Equal(expectedInstance, sapInstance) } func (suite *SAPSystemTestSuite) TestGetSIDsString() { - sysList := SAPSystemsList{ - &SAPSystem{ + sysList := sapsystem.SAPSystemsList{ + &sapsystem.SAPSystem{ SID: "PRD", }, } suite.Equal("PRD", sysList.GetSIDsString()) - sysList = SAPSystemsList{ - &SAPSystem{ + sysList = sapsystem.SAPSystemsList{ + &sapsystem.SAPSystem{ SID: "PRD", }, - &SAPSystem{ + &sapsystem.SAPSystem{ SID: "QAS", }, } @@ -749,9 +797,10 @@ func (suite *SAPSystemTestSuite) TestFindSystemsNotFound() { err = appFS.MkdirAll("/usr/sap/DEV1/", 0755) suite.NoError(err) - systems, _ := FindSystems(appFS) + systems, err := sapsystem.FindSystems(appFS) suite.Equal([]string{}, systems) + suite.NoError(err) } func (suite *SAPSystemTestSuite) TestFindSystems() { @@ -775,8 +824,9 @@ func (suite *SAPSystemTestSuite) TestFindSystems() { err = appFS.MkdirAll("/usr/sap/DEV/PRD0", 0755) suite.NoError(err) - systems, _ := FindSystems(appFS) + systems, err := sapsystem.FindSystems(appFS) suite.ElementsMatch([]string{"/usr/sap/PRD", "/usr/sap/DEV"}, systems) + suite.NoError(err) } func (suite *SAPSystemTestSuite) TestFindInstancesNotFound() { @@ -785,9 +835,10 @@ func (suite *SAPSystemTestSuite) TestFindInstancesNotFound() { err := appFS.MkdirAll("/usr/sap/DEV/SYS/BLA12", 0755) suite.NoError(err) - instances, _ := FindInstances(appFS, "/usr/sap/DEV") + instances, err := sapsystem.FindInstances(appFS, "/usr/sap/DEV") suite.Equal([][]string{}, instances) + suite.NoError(err) } func (suite *SAPSystemTestSuite) TestFindInstances() { @@ -805,12 +856,13 @@ func (suite *SAPSystemTestSuite) TestFindInstances() { err = appFS.MkdirAll("/usr/sap/DEV/ERS10", 0755) suite.NoError(err) - instances, _ := FindInstances(appFS, "/usr/sap/DEV") + instances, err := sapsystem.FindInstances(appFS, "/usr/sap/DEV") expectedInstance := [][]string{ {"ASCS02", "02"}, {"ERS10", "10"}, } suite.ElementsMatch(expectedInstance, instances) + suite.NoError(err) } func (suite *SAPSystemTestSuite) TestFindProfilesNotFound() { @@ -821,9 +873,10 @@ func (suite *SAPSystemTestSuite) TestFindProfilesNotFound() { err = appFS.MkdirAll("/sapmnt/PRD/profile", 0755) suite.NoError(err) - profiles, _ := FindProfiles(appFS, "DEV") + profiles, err := sapsystem.FindProfiles(appFS, "DEV") suite.Equal([]string{}, profiles) + suite.NoError(err) } func (suite *SAPSystemTestSuite) TestFindProfiles() { @@ -842,118 +895,122 @@ func (suite *SAPSystemTestSuite) TestFindProfiles() { err = afero.WriteFile(appFS, "/sapmnt/PRD/profile/prd_profile", []byte{}, 0644) suite.NoError(err) - profiles, _ := FindProfiles(appFS, "DEV") + profiles, err := sapsystem.FindProfiles(appFS, "DEV") expectedProfiles := []string{"DEFAULT.PFL", "dev_profile"} suite.ElementsMatch(expectedProfiles, profiles) -} - -func (suite *SAPSystemTestSuite) TestDetectType_Database() { - sapControl := &SAPControl{ - Properties: []*sapcontrol.InstanceProperty{ - { - Property: "SAPLOCALHOST", - Propertytype: "string", - Value: "host2", - }, - }, - Instances: []*sapcontrol.SAPInstance{ - { - Hostname: "host1", - Features: "other", - }, - { - Hostname: "host2", - Features: "HDB|HDB_WORKER", - }, - }, - } - - instanceType, err := detectType(sapControl) - suite.NoError(err) - suite.Equal(Database, instanceType) } -func (suite *SAPSystemTestSuite) TestDetectType_Application() { - sapControl := &SAPControl{ - Properties: []*sapcontrol.InstanceProperty{ - { - Property: "SAPLOCALHOST", - Propertytype: "string", - Value: "host1", - }, - }, - Instances: []*sapcontrol.SAPInstance{ - { - Hostname: "host1", +func (suite *SAPSystemTestSuite) TestDetectType() { + cases := []struct { + instance *sapcontrol.SAPInstance + expectedType sapsystem.SystemType + }{ + { + instance: &sapcontrol.SAPInstance{ + Hostname: "host", Features: "MESSAGESERVER|ENQUE", }, + expectedType: sapsystem.Application, }, - } - - instanceType, err := detectType(sapControl) - - suite.NoError(err) - suite.Equal(Application, instanceType) - - sapControl.Instances = []*sapcontrol.SAPInstance{ { - Hostname: "host1", - Features: "ENQREP", + instance: &sapcontrol.SAPInstance{ + Hostname: "host", + Features: "ENQREP", + }, + expectedType: sapsystem.Application, }, - } - - instanceType, err = detectType(sapControl) - - suite.NoError(err) - suite.Equal(Application, instanceType) - - sapControl.Instances = []*sapcontrol.SAPInstance{ { - Hostname: "host1", - Features: "ABAP|GATEWAY|ICMAN|IGS", - }, - } - - instanceType, err = detectType(sapControl) - - suite.NoError(err) - suite.Equal(Application, instanceType) -} - -func (suite *SAPSystemTestSuite) TestDetectType_Diagnostics() { - sapControl := &SAPControl{ - Properties: []*sapcontrol.InstanceProperty{ - { - Property: "SAPLOCALHOST", - Propertytype: "string", - Value: "host1", + instance: &sapcontrol.SAPInstance{ + Hostname: "host", + Features: "ABAP|GATEWAY|ICMAN|IGS", }, + expectedType: sapsystem.Application, }, - Instances: []*sapcontrol.SAPInstance{ - { - Hostname: "host1", + { + instance: &sapcontrol.SAPInstance{ + Hostname: "host", Features: "SMDAGENT", }, + expectedType: sapsystem.DiagnosticsAgent, + }, + { + instance: &sapcontrol.SAPInstance{ + Hostname: "host", + Features: "UNKNOWNFEATURE", + }, + expectedType: sapsystem.Unknown, }, } - instanceType, err := detectType(sapControl) - - suite.NoError(err) - suite.Equal(DiagnosticsAgent, instanceType) + for _, tt := range cases { + mockWebService := new(sapControlMocks.WebService) + mockWebService. + On("GetInstanceProperties"). + Return(&sapcontrol.GetInstancePropertiesResponse{ + Properties: []*sapcontrol.InstanceProperty{ + { + Property: "SAPSYSTEMNAME", + Propertytype: "string", + Value: "PRD", + }, + { + Property: "INSTANCE_NAME", + Propertytype: "string", + Value: "ASCS00", + }, + { + Property: "SAPLOCALHOST", + Propertytype: "string", + Value: "host", + }, + }, + }, nil). + On("GetProcessList"). + Return(&sapcontrol.GetProcessListResponse{ + Processes: []*sapcontrol.OSProcess{}, + }, nil). + On("GetSystemInstanceList").Return(&sapcontrol.GetSystemInstanceListResponse{ + Instances: []*sapcontrol.SAPInstance{tt.instance}, + }, nil) + + mockCommand := new(mocks.CommandExecutor) + instance, err := sapsystem.NewSAPInstance(mockWebService, mockCommand) + + suite.NoError(err) + suite.Equal(tt.expectedType, instance.Type) + } } -func (suite *SAPSystemTestSuite) TestDetectType_Unknown() { - sapControl := &SAPControl{ - Properties: []*sapcontrol.InstanceProperty{ - { - Property: "SAPLOCALHOST", - Propertytype: "string", - Value: "host2", +func (suite *SAPSystemTestSuite) TestDetectType_Database() { + mockWebService := new(sapControlMocks.WebService) + mockWebService. + On("GetInstanceProperties"). + Return(&sapcontrol.GetInstancePropertiesResponse{ + Properties: []*sapcontrol.InstanceProperty{ + { + Property: "SAPSYSTEMNAME", + Propertytype: "string", + Value: "HDB", + }, + { + Property: "INSTANCE_NAME", + Propertytype: "string", + Value: "HDB00", + }, + { + Property: "SAPLOCALHOST", + Propertytype: "string", + Value: "host2", + }, }, - }, + }, nil). + On("GetProcessList"). + Return(&sapcontrol.GetProcessListResponse{ + Processes: []*sapcontrol.OSProcess{}, + }, nil). + On("GetSystemInstanceList").Return(&sapcontrol.GetSystemInstanceListResponse{ Instances: []*sapcontrol.SAPInstance{ { Hostname: "host1", @@ -961,13 +1018,22 @@ func (suite *SAPSystemTestSuite) TestDetectType_Unknown() { }, { Hostname: "host2", - Features: "another", + Features: "HDB|HDB_WORKER", }, }, - } + }, nil) + + mockCommand := new(mocks.CommandExecutor) + mockCommand. + On("Exec", "su", "-lc", "python /usr/sap/HDB/HDB00/exe/python_support/systemReplicationStatus.py --sapcontrol=1", "hdbadm"). + Return(mockSystemReplicationStatus(), nil). + On("Exec", "su", "-lc", "python /usr/sap/HDB/HDB00/exe/python_support/landscapeHostConfiguration.py --sapcontrol=1", "hdbadm"). + Return(mockLandscapeHostConfiguration(), nil). + On("Exec", "su", "-lc", "/usr/sap/HDB/HDB00/exe/hdbnsutil -sr_state -sapcontrol=1", "hdbadm"). + Return(mockHdbnsutilSrstate(), nil) - instanceType, err := detectType(sapControl) + instance, err := sapsystem.NewSAPInstance(mockWebService, mockCommand) suite.NoError(err) - suite.Equal(Unknown, instanceType) + suite.Equal(sapsystem.Database, instance.Type) }