-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add saptune core functionality * Add saptune discovery
- Loading branch information
Showing
9 changed files
with
318 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
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
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,77 @@ | ||
package saptune | ||
|
||
import ( | ||
"github.com/pkg/errors" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/trento-project/agent/pkg/utils" | ||
"golang.org/x/mod/semver" | ||
) | ||
|
||
var ( | ||
ErrSaptuneVersionUnknown = errors.New("could not determine saptune version") | ||
ErrUnsupportedSaptuneVer = errors.New("saptune version is not supported") | ||
) | ||
|
||
const ( | ||
MinimalSaptuneVersion = "v3.1.0" | ||
) | ||
|
||
type Saptune struct { | ||
Version string | ||
IsJSONSupported bool | ||
executor utils.CommandExecutor | ||
} | ||
|
||
func getSaptuneVersion(commandExecutor utils.CommandExecutor) (string, error) { | ||
log.Info("Requesting Saptune version...") | ||
versionOutput, err := commandExecutor.Exec("rpm", "-q", "--qf", "%{VERSION}", "saptune") | ||
if err != nil { | ||
return "", errors.Wrap(err, ErrSaptuneVersionUnknown.Error()) | ||
} | ||
|
||
log.Infof("saptune version output: %s", string(versionOutput)) | ||
|
||
return string(versionOutput), nil | ||
} | ||
|
||
func isSaptuneVersionSupported(version string) bool { | ||
compareOutput := semver.Compare(MinimalSaptuneVersion, "v"+version) | ||
|
||
return compareOutput != 1 | ||
} | ||
|
||
func NewSaptune(commandExecutor utils.CommandExecutor) (Saptune, error) { | ||
saptuneVersion, err := getSaptuneVersion(commandExecutor) | ||
if err != nil { | ||
return Saptune{}, err | ||
} | ||
|
||
saptune := Saptune{ | ||
Version: saptuneVersion, | ||
executor: commandExecutor, | ||
IsJSONSupported: isSaptuneVersionSupported(saptuneVersion), | ||
} | ||
|
||
return saptune, nil | ||
} | ||
|
||
func (s *Saptune) RunCommand(args ...string) ([]byte, error) { | ||
log.Infof("Running saptune command: saptune %v", args) | ||
output, err := s.executor.Exec("saptune", args...) | ||
if err != nil { | ||
log.Debugf(err.Error()) | ||
} | ||
log.Debugf("saptune output: %s", string(output)) | ||
log.Infof("Saptune command executed") | ||
|
||
return output, nil | ||
} | ||
|
||
func (s *Saptune) RunCommandJSON(args ...string) ([]byte, error) { | ||
if !s.IsJSONSupported { | ||
return nil, ErrUnsupportedSaptuneVer | ||
} | ||
|
||
prependedArgs := append([]string{"--format", "json"}, args...) | ||
return s.RunCommand(prependedArgs...) | ||
} |
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,135 @@ | ||
package saptune | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/pkg/errors" | ||
"github.com/stretchr/testify/suite" | ||
"github.com/trento-project/agent/pkg/utils/mocks" | ||
) | ||
|
||
type SaptuneTestSuite struct { | ||
suite.Suite | ||
} | ||
|
||
func TestSaptuneTestSuite(t *testing.T) { | ||
suite.Run(t, new(SaptuneTestSuite)) | ||
} | ||
|
||
func (suite *SaptuneTestSuite) TestNewSaptune() { | ||
mockCommand := new(mocks.CommandExecutor) | ||
|
||
mockCommand.On("Exec", "rpm", "-q", "--qf", "%{VERSION}", "saptune").Return( | ||
[]byte("3.1.0"), nil, | ||
) | ||
|
||
saptuneRetriever, err := NewSaptune(mockCommand) | ||
|
||
expectedSaptune := Saptune{ | ||
Version: "3.1.0", | ||
IsJSONSupported: true, | ||
executor: mockCommand, | ||
} | ||
|
||
suite.NoError(err) | ||
suite.Equal(expectedSaptune, saptuneRetriever) | ||
} | ||
|
||
func (suite *SaptuneTestSuite) TestNewSaptuneUnsupportedSaptuneVer() { | ||
mockCommand := new(mocks.CommandExecutor) | ||
|
||
mockCommand.On("Exec", "rpm", "-q", "--qf", "%{VERSION}", "saptune").Return( | ||
[]byte("3.0.0"), nil, | ||
) | ||
|
||
saptuneRetriever, err := NewSaptune(mockCommand) | ||
|
||
expectedSaptune := Saptune{ | ||
Version: "3.0.0", | ||
IsJSONSupported: false, | ||
executor: mockCommand, | ||
} | ||
|
||
suite.NoError(err) | ||
suite.Equal(expectedSaptune, saptuneRetriever) | ||
} | ||
|
||
func (suite *SaptuneTestSuite) TestNewSaptuneSaptuneVersionUnknownErr() { | ||
mockCommand := new(mocks.CommandExecutor) | ||
|
||
mockCommand.On("Exec", "rpm", "-q", "--qf", "%{VERSION}", "saptune").Return( | ||
nil, errors.New("Error: exec: \"rpm\": executable file not found in $PATH"), | ||
) | ||
|
||
saptuneRetriever, err := NewSaptune(mockCommand) | ||
|
||
expectedSaptune := Saptune{ | ||
Version: "", | ||
IsJSONSupported: false, | ||
} | ||
|
||
suite.EqualError(err, ErrSaptuneVersionUnknown.Error()+": Error: exec: \"rpm\": executable file not found in $PATH") | ||
suite.Equal(expectedSaptune, saptuneRetriever) | ||
} | ||
|
||
func (suite *SaptuneTestSuite) TestRunCommand() { | ||
mockCommand := new(mocks.CommandExecutor) | ||
|
||
saptuneRetriever := Saptune{ | ||
Version: "3.0.0", | ||
IsJSONSupported: false, | ||
executor: mockCommand, | ||
} | ||
|
||
saptuneOutput := []byte("some_output") | ||
|
||
mockCommand.On("Exec", "saptune", "some_command").Return( | ||
saptuneOutput, nil, | ||
) | ||
|
||
statusOutput, err := saptuneRetriever.RunCommand("some_command") | ||
|
||
expectedOutput := []byte("some_output") | ||
|
||
suite.NoError(err) | ||
suite.Equal(expectedOutput, statusOutput) | ||
} | ||
|
||
func (suite *SaptuneTestSuite) TestRunCommandJSON() { | ||
mockCommand := new(mocks.CommandExecutor) | ||
|
||
saptuneRetriever := Saptune{ | ||
Version: "3.1.0", | ||
IsJSONSupported: true, | ||
executor: mockCommand, | ||
} | ||
|
||
saptuneOutput := []byte("{\"some_json_key\": \"some_value\"}") | ||
|
||
mockCommand.On("Exec", "saptune", "--format", "json", "status").Return( | ||
saptuneOutput, nil, | ||
) | ||
|
||
statusOutput, err := saptuneRetriever.RunCommandJSON("status") | ||
|
||
expectedOutput := []byte("{\"some_json_key\": \"some_value\"}") | ||
|
||
suite.NoError(err) | ||
suite.Equal(expectedOutput, statusOutput) | ||
} | ||
|
||
func (suite *SaptuneTestSuite) TestRunCommandJSONNoJSONSupported() { | ||
mockCommand := new(mocks.CommandExecutor) | ||
|
||
saptuneRetriever := Saptune{ | ||
IsJSONSupported: false, | ||
executor: mockCommand, | ||
} | ||
|
||
statusOutput, err := saptuneRetriever.RunCommandJSON("status") | ||
|
||
expectedOutput := []byte(nil) | ||
|
||
suite.EqualError(err, ErrUnsupportedSaptuneVer.Error()) | ||
suite.Equal(expectedOutput, statusOutput) | ||
} |
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,88 @@ | ||
package discovery | ||
|
||
import ( | ||
"encoding/json" | ||
"time" | ||
|
||
log "github.com/sirupsen/logrus" | ||
"github.com/trento-project/agent/internal/core/saptune" | ||
"github.com/trento-project/agent/internal/discovery/collector" | ||
"github.com/trento-project/agent/pkg/utils" | ||
) | ||
|
||
const SaptuneDiscoveryID string = "saptune_discovery" | ||
const SaptuneDiscoveryMinPeriod time.Duration = 1 * time.Second | ||
|
||
type SaptuneDiscovery struct { | ||
id string | ||
collectorClient collector.Client | ||
interval time.Duration | ||
} | ||
|
||
type SaptuneDiscoveryPayload struct { | ||
PackageVersion string `json:"package_version"` | ||
SaptuneInstalled bool `json:"saptune_installed"` | ||
Status interface{} `json:"status"` | ||
} | ||
|
||
func NewSaptuneDiscovery(collectorClient collector.Client, config DiscoveriesConfig) Discovery { | ||
return SaptuneDiscovery{ | ||
id: SaptuneDiscoveryID, | ||
collectorClient: collectorClient, | ||
interval: config.DiscoveriesPeriodsConfig.Saptune, | ||
} | ||
} | ||
|
||
func (d SaptuneDiscovery) GetID() string { | ||
return d.id | ||
} | ||
|
||
func (d SaptuneDiscovery) GetInterval() time.Duration { | ||
return d.interval | ||
} | ||
|
||
func (d SaptuneDiscovery) Discover() (string, error) { | ||
var saptunePayload SaptuneDiscoveryPayload | ||
|
||
saptuneRetriever, err := saptune.NewSaptune(utils.Executor{}) | ||
switch { | ||
case err != nil: | ||
saptunePayload = SaptuneDiscoveryPayload{ | ||
PackageVersion: "", | ||
SaptuneInstalled: false, | ||
Status: nil, | ||
} | ||
case !saptuneRetriever.IsJSONSupported: | ||
saptunePayload = SaptuneDiscoveryPayload{ | ||
PackageVersion: saptuneRetriever.Version, | ||
SaptuneInstalled: true, | ||
Status: nil, | ||
} | ||
default: | ||
saptuneData, _ := saptuneRetriever.RunCommandJSON("status") | ||
unmarshalled := make(map[string]interface{}) | ||
err = json.Unmarshal(saptuneData, &unmarshalled) | ||
if err != nil { | ||
log.Debugf("Error while unmarshalling saptune status: %s", err) | ||
saptunePayload = SaptuneDiscoveryPayload{ | ||
PackageVersion: saptuneRetriever.Version, | ||
SaptuneInstalled: true, | ||
Status: nil, | ||
} | ||
} else { | ||
saptunePayload = SaptuneDiscoveryPayload{ | ||
PackageVersion: saptuneRetriever.Version, | ||
SaptuneInstalled: true, | ||
Status: unmarshalled, | ||
} | ||
} | ||
} | ||
|
||
err = d.collectorClient.Publish(d.id, saptunePayload) | ||
if err != nil { | ||
log.Debugf("Error while sending saptune discovery to data collector: %s", err) | ||
return "", err | ||
} | ||
|
||
return "Saptune data discovery completed", nil | ||
} |
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