Просмотр исходного кода

improve node recommendations and add archiving/delete system

Alexander Belanger 3 лет назад
Родитель
Сommit
61b9d71d3b

+ 3 - 0
internal/models/monitor.go

@@ -21,6 +21,9 @@ type MonitorTestResult struct {
 	LastRunResult     string
 	LastRunResultEnum uint
 
+	LastRecommenderRunID string
+	Archived             bool
+
 	Title   string
 	Message string
 

+ 12 - 1
internal/opa/policies/node/healthy.rego

@@ -10,7 +10,7 @@ POLICY_SEVERITY := "critical"
 
 POLICY_TITLE := sprintf("The node %s should be healthy", [input.metadata.name])
 
-POLICY_SUCCESS_MESSAGE := sprintf("Success: this node is healthy", [])
+POLICY_SUCCESS_MESSAGE := sprintf("Success: this node is healthy or is younger than 10 minutes", [])
 
 # check if one of the node's conditions states that the kubelet is ready
 allow if {
@@ -19,7 +19,18 @@ allow if {
 	condition.status = "True"
 }
 
+# if the node was started in the last 10 minutes, we do not track it - it may 
+# be unhealthy while initializing the CNI
+allow if {
+	rfc3339_is_younger_than_10_minutes(input.metadata.creationTimestamp)
+}
+
 FAILURE_MESSAGE contains msg if {
 	not allow
 	msg := sprintf("Failed: the node %s is not healthy", [input.metadata.name])
 }
+
+rfc3339_is_younger_than_10_minutes(a) if {
+	# add 10 minutes (in nanoseconds) to the creation timestamp and see if it's greater than current time 
+	time.parse_rfc3339_ns(a) + ((((10 * 60) * 1000) * 1000) * 1000) > time.now_ns()
+}

+ 26 - 0
internal/repository/gorm/monitor.go

@@ -42,3 +42,29 @@ func (m *MonitorTestResultRepository) UpdateMonitorTestResult(monitor *models.Mo
 
 	return monitor, nil
 }
+
+func (m *MonitorTestResultRepository) ArchiveMonitorTestResults(recommenderID string) error {
+	query := m.db.Debug().Unscoped().Model(&models.MonitorTestResult{}).Where("last_recommender_run_id IS NOT ?", recommenderID)
+
+	return query.Update("archived", true).Error
+}
+
+func (m *MonitorTestResultRepository) DeleteOldMonitorTestResults(recommenderID string) error {
+	monitors := make([]*models.MonitorTestResult, 0)
+
+	query := m.db.Debug().Unscoped().Where("last_recommender_run_id IS NOT ?", recommenderID)
+
+	// we need to switch on the database type to delete records older than 24 hours
+	switch m.db.Dialector.Name() {
+	case "sqlite":
+		query = query.Where(
+			"last_tested < DATETIME('now', '-1 day')",
+		)
+	case "postgres":
+		query = query.Where(
+			"last_tested < NOW() - INTERVAL '1 day'",
+		)
+	}
+
+	return query.Delete(monitors).Error
+}

+ 3 - 0
internal/repository/monitor.go

@@ -6,4 +6,7 @@ type MonitorTestResultRepository interface {
 	CreateMonitorTestResult(monitor *models.MonitorTestResult) (*models.MonitorTestResult, error)
 	ReadMonitorTestResult(projectID, clusterID uint, operationID string) (*models.MonitorTestResult, error)
 	UpdateMonitorTestResult(monitor *models.MonitorTestResult) (*models.MonitorTestResult, error)
+
+	ArchiveMonitorTestResults(recommenderID string) error
+	DeleteOldMonitorTestResults(recommenderID string) error
 }

+ 8 - 0
internal/repository/test/monitor.go

@@ -22,3 +22,11 @@ func (n *MonitorTestResultRepository) ReadMonitorTestResult(projectID, clusterID
 func (n *MonitorTestResultRepository) UpdateMonitorTestResult(monitor *models.MonitorTestResult) (*models.MonitorTestResult, error) {
 	panic("not implemented") // TODO: Implement
 }
+
+func (n *MonitorTestResultRepository) ArchiveMonitorTestResults(recommenderID string) error {
+	panic("not implemented") // TODO: Implement
+}
+
+func (n *MonitorTestResultRepository) DeleteOldMonitorTestResults(recommenderID string) error {
+	panic("not implemented") // TODO: Implement
+}

+ 37 - 18
workers/jobs/recommender.go

@@ -22,6 +22,7 @@ import (
 	"github.com/porter-dev/porter/api/types"
 
 	"github.com/porter-dev/porter/ee/integrations/vault"
+	"github.com/porter-dev/porter/internal/encryption"
 	"github.com/porter-dev/porter/internal/kubernetes"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/oauth"
@@ -41,6 +42,7 @@ type recommender struct {
 	clusterAndProjectIDs []clusterAndProjectID
 	categories           []string
 	policies             *opa.KubernetesPolicies
+	runRecommenderID     string
 }
 
 // RecommenderOpts holds the options required to run this job
@@ -122,8 +124,14 @@ func NewRecommender(
 		return nil, err
 	}
 
+	recommenderID, err := encryption.GenerateRandomBytes(32)
+
+	if err != nil {
+		return nil, err
+	}
+
 	return &recommender{
-		enqueueTime, db, repo, doConf, clusterIDs, parsedInput.Categories, opaPolicies,
+		enqueueTime, db, repo, doConf, clusterIDs, parsedInput.Categories, opaPolicies, string(recommenderID),
 	}, nil
 }
 
@@ -231,12 +239,12 @@ func (n *recommender) Run() error {
 
 			if err != nil {
 				if errors.Is(err, gorm.ErrRecordNotFound) {
-					monitor, err = n.repo.MonitorTestResult().CreateMonitorTestResult(n.getMonitorTestResultFromQueryResult(cluster, queryRes))
+					monitor, err = n.repo.MonitorTestResult().CreateMonitorTestResult(n.getMonitorTestResultFromQueryResult(cluster, queryRes, n.runRecommenderID))
 				} else {
 					continue
 				}
 			} else {
-				monitor, err = n.repo.MonitorTestResult().UpdateMonitorTestResult(mergeMonitorTestResultFromQueryResult(monitor, queryRes))
+				monitor, err = n.repo.MonitorTestResult().UpdateMonitorTestResult(mergeMonitorTestResultFromQueryResult(monitor, queryRes, n.runRecommenderID))
 			}
 
 			if err != nil {
@@ -245,10 +253,17 @@ func (n *recommender) Run() error {
 		}
 	}
 
-	return nil
+	// archive any test results which don't match
+	err := n.repo.MonitorTestResult().ArchiveMonitorTestResults(n.runRecommenderID)
+
+	if err != nil {
+		return err
+	}
+
+	return n.repo.MonitorTestResult().DeleteOldMonitorTestResults(n.runRecommenderID)
 }
 
-func (n *recommender) getMonitorTestResultFromQueryResult(cluster *models.Cluster, queryRes *opa.OPARecommenderQueryResult) *models.MonitorTestResult {
+func (n *recommender) getMonitorTestResultFromQueryResult(cluster *models.Cluster, queryRes *opa.OPARecommenderQueryResult, recommenderID string) *models.MonitorTestResult {
 	runResult := types.MonitorTestStatusSuccess
 
 	if !queryRes.Allow {
@@ -258,22 +273,24 @@ func (n *recommender) getMonitorTestResultFromQueryResult(cluster *models.Cluste
 	currTime := time.Now()
 
 	return &models.MonitorTestResult{
-		ProjectID:         cluster.ProjectID,
-		ClusterID:         cluster.ID,
-		Category:          queryRes.CategoryName,
-		ObjectID:          queryRes.ObjectID,
-		LastStatusChange:  &currTime,
-		LastTested:        &currTime,
-		LastRunResult:     string(runResult),
-		LastRunResultEnum: models.GetLastRunResultEnum(string(runResult)),
-		Title:             queryRes.PolicyTitle,
-		Message:           queryRes.PolicyMessage,
-		Severity:          queryRes.PolicySeverity,
-		SeverityEnum:      models.GetSeverityEnum(queryRes.PolicySeverity),
+		ProjectID:            cluster.ProjectID,
+		ClusterID:            cluster.ID,
+		Category:             queryRes.CategoryName,
+		ObjectID:             queryRes.ObjectID,
+		LastStatusChange:     &currTime,
+		LastTested:           &currTime,
+		LastRunResult:        string(runResult),
+		LastRunResultEnum:    models.GetLastRunResultEnum(string(runResult)),
+		LastRecommenderRunID: recommenderID,
+		Title:                queryRes.PolicyTitle,
+		Message:              queryRes.PolicyMessage,
+		Severity:             queryRes.PolicySeverity,
+		SeverityEnum:         models.GetSeverityEnum(queryRes.PolicySeverity),
+		Archived:             false,
 	}
 }
 
-func mergeMonitorTestResultFromQueryResult(monitor *models.MonitorTestResult, queryRes *opa.OPARecommenderQueryResult) *models.MonitorTestResult {
+func mergeMonitorTestResultFromQueryResult(monitor *models.MonitorTestResult, queryRes *opa.OPARecommenderQueryResult, recommenderID string) *models.MonitorTestResult {
 	runResult := types.MonitorTestStatusSuccess
 
 	if !queryRes.Allow {
@@ -293,6 +310,8 @@ func mergeMonitorTestResultFromQueryResult(monitor *models.MonitorTestResult, qu
 	monitor.Severity = queryRes.PolicySeverity
 	monitor.SeverityEnum = models.GetSeverityEnum(queryRes.PolicySeverity)
 	monitor.LastRunResultEnum = models.GetLastRunResultEnum(string(runResult))
+	monitor.LastRecommenderRunID = recommenderID
+	monitor.Archived = false
 
 	return monitor
 }