Skip to content

Commit

Permalink
Merge pull request #91 from kubescape/substatus-upate
Browse files Browse the repository at this point in the history
Substatus update
  • Loading branch information
amirmalka authored Feb 6, 2023
2 parents 2aecc7d + d67682a commit 6e8c134
Show file tree
Hide file tree
Showing 26 changed files with 606 additions and 203 deletions.
1 change: 1 addition & 0 deletions reporthandling/apis/statuses.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
// IStatus interface handling status
type IStatus interface {
Status() ScanningStatus
GetSubStatus() ScanningSubStatus
Info() string
IsPassed() bool
IsFailed() bool
Expand Down
40 changes: 40 additions & 0 deletions reporthandling/apis/statuses_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func TestCompare(t *testing.T) {
assert.Equal(t, StatusFailed, Compare(StatusPassed, StatusFailed))
assert.Equal(t, StatusSkipped, Compare(StatusSkipped, StatusPassed))
assert.Equal(t, StatusPassed, Compare(StatusPassed, StatusPassed))
assert.Equal(t, StatusUnknown, Compare(StatusUnknown, StatusUnknown))
}

func TestCompareStatusAndSubStatus(t *testing.T) {
Expand All @@ -29,3 +30,42 @@ func TestCompareStatusAndSubStatus(t *testing.T) {
assert.Equal(t, makeIS(StatusSkipped, SubStatusManualReview), makeIS(CompareStatusAndSubStatus(StatusPassed, StatusSkipped, SubStatusUnknown, SubStatusManualReview)))
assert.Equal(t, makeIS(StatusSkipped, SubStatusRequiresReview), makeIS(CompareStatusAndSubStatus(StatusPassed, StatusSkipped, SubStatusUnknown, SubStatusRequiresReview)))
}

func TestConvertStatusToNewStatus(t *testing.T) {
tests := []struct {
name string
status ScanningStatus
expected ScanningStatus
sub ScanningSubStatus
}{
{
name: "StatusExcluded",
status: StatusExcluded,
expected: StatusPassed,
sub: SubStatusException,
},
{
name: "StatusIrrelevant",
status: StatusIrrelevant,
expected: StatusPassed,
sub: SubStatusIrrelevant,
},
{
name: "StatusPassed",
status: StatusPassed,
expected: StatusPassed,
sub: SubStatusUnknown,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actualStatus, actualSub := ConvertStatusToNewStatus(test.status)
if actualStatus != test.expected {
t.Errorf("Expected status %s, but got %s", test.expected, actualStatus)
}
if actualSub != test.sub {
t.Errorf("Expected sub status %s, but got %s", test.sub, actualSub)
}
})
}
}
9 changes: 7 additions & 2 deletions reporthandling/apis/statusinfo.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package apis

type StatusInfo struct {
InnerStatus ScanningStatus `json:"status,omitempty"`
InnerInfo string `json:"info,omitempty"`
InnerStatus ScanningStatus `json:"status,omitempty"`
SubStatus ScanningSubStatus `json:"subStatus,omitempty"`
InnerInfo string `json:"info,omitempty"`
}

func (s *StatusInfo) GetSubStatus() ScanningSubStatus {
return s.SubStatus
}

func (s *StatusInfo) Status() ScanningStatus {
Expand Down
46 changes: 46 additions & 0 deletions reporthandling/apis/statusinfo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package apis

import "testing"

func TestIsPassed(t *testing.T) {
s := &StatusInfo{InnerStatus: StatusPassed}
if !s.IsPassed() {
t.Fatalf("Expected status to be passed, got %v", s.InnerStatus)
}
}

func TestIsFailed(t *testing.T) {
s := &StatusInfo{InnerStatus: StatusFailed}
if !s.IsFailed() {
t.Fatalf("Expected status to be failed, got %v", s.InnerStatus)
}
}

func TestIsSkipped(t *testing.T) {
s := &StatusInfo{InnerStatus: StatusSkipped}
if !s.IsSkipped() {
t.Fatalf("Expected status to be skipped, got %v", s.InnerStatus)
}
}

func TestGetSubStatus(t *testing.T) {
s := &StatusInfo{SubStatus: SubStatusException}
if s.GetSubStatus() != SubStatusException {
t.Fatalf("Expected sub-status to be %v, got %v", SubStatusException, s.GetSubStatus())
}
}

func TestStatus(t *testing.T) {
s := &StatusInfo{InnerStatus: StatusPassed}
if s.Status() != StatusPassed {
t.Fatalf("Expected status to be %v, got %v", StatusPassed, s.Status())
}
}

func TestInfo(t *testing.T) {
info := "Test info"
s := &StatusInfo{InnerInfo: info}
if s.Info() != info {
t.Fatalf("Expected info to be %v, got %v", info, s.Info())
}
}
9 changes: 7 additions & 2 deletions reporthandling/helpers/v1/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ package v1
import "github.com/kubescape/opa-utils/reporthandling/apis"

type Status struct {
status apis.ScanningStatus
status apis.ScanningStatus
subStatus apis.ScanningSubStatus
}

func NewStatus(status apis.ScanningStatus) *Status {
return &Status{status: status}
}

func NewStatusInfo(status apis.ScanningStatus, info string) *apis.StatusInfo {
func NewStatusInfo(status apis.ScanningStatus, subStatus apis.ScanningSubStatus, info string) *apis.StatusInfo {
return &apis.StatusInfo{
InnerStatus: status,
SubStatus: subStatus,
InnerInfo: info,
}
}

func (s *Status) GetSubStatus() apis.ScanningSubStatus {
return s.subStatus
}
func (s *Status) Status() apis.ScanningStatus {
return s.status
}
Expand Down
135 changes: 135 additions & 0 deletions reporthandling/helpers/v1/status_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package v1

import (
"testing"

"github.com/kubescape/opa-utils/reporthandling/apis"
)

func TestNewStatus(t *testing.T) {
tests := []struct {
name string
status apis.ScanningStatus
want apis.ScanningStatus
}{
{
name: "Test passed status",
status: apis.StatusPassed,
want: apis.StatusPassed,
},
{
name: "Test failed status",
status: apis.StatusFailed,
want: apis.StatusFailed,
},
{
name: "Test skipped status",
status: apis.StatusSkipped,
want: apis.StatusSkipped,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := NewStatus(tt.status)
if got := s.Status(); got != tt.want {
t.Errorf("NewStatus().Status() = %v, want %v", got, tt.want)
}
})
}
}

func TestNewStatusInfo(t *testing.T) {
tests := []struct {
name string
status apis.ScanningStatus
subStatus apis.ScanningSubStatus
info string
wantStatus apis.ScanningStatus
wantSubStatus apis.ScanningSubStatus
wantInfo string
}{
{
name: "Test passed status with ignore sub status and info",
status: apis.StatusPassed,
subStatus: apis.SubStatusException,
info: string(apis.SubStatusConfigurationInfo),
wantStatus: apis.StatusPassed,
wantSubStatus: apis.SubStatusException,
wantInfo: string(apis.SubStatusConfigurationInfo),
},
{
name: "Test failed status and info",
status: apis.StatusFailed,
subStatus: "",
info: string(apis.SubStatusManualReviewInfo),
wantStatus: apis.StatusFailed,
wantSubStatus: "",
wantInfo: string(apis.SubStatusManualReviewInfo),
},
{
name: "Test skipped status with irrelevant sub status without info",
status: apis.StatusSkipped,
subStatus: apis.SubStatusConfiguration,
info: "",
wantStatus: apis.StatusSkipped,
wantSubStatus: apis.SubStatusConfiguration,
wantInfo: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := NewStatusInfo(tt.status, tt.subStatus, tt.info)
if got := s.Status(); got != tt.wantStatus {
t.Errorf("NewStatusInfo().Status() = %v, want %v", got, tt.wantStatus)
}
if got := s.GetSubStatus(); got != tt.wantSubStatus {
t.Errorf("NewStatusInfo().GetSubStatus() = %v, want %v", got, tt.wantSubStatus)
}
if got := s.Info(); got != tt.wantInfo {
t.Errorf("NewStatusInfo().Info() = %v, want %v", got, tt.wantInfo)
}
})
}
}

func TestGetSubStatus(t *testing.T) {
status := &Status{subStatus: apis.SubStatusIntegration}
if status.GetSubStatus() != apis.SubStatusIntegration {
t.Errorf("Expected subStatus to be %s, got %s", apis.SubStatusIntegration, status.GetSubStatus())
}
}

func TestStatus(t *testing.T) {
status := &Status{status: apis.StatusFailed}
if status.Status() != apis.StatusFailed {
t.Errorf("Expected status to be %s, got %s", apis.StatusFailed, status.Status())
}
}

func TestInfo(t *testing.T) {
status := &Status{}
if status.Info() != "" {
t.Errorf("Expected Info to be empty string, got %s", status.Info())
}
}

func TestIsPassed(t *testing.T) {
status := &Status{status: apis.StatusPassed}
if !status.IsPassed() {
t.Errorf("Expected IsPassed to be true, got false")
}
}

func TestIsFailed(t *testing.T) {
status := &Status{status: apis.StatusFailed}
if !status.IsFailed() {
t.Errorf("Expected IsFailed to be true, got false")
}
}

func TestIsSkipped(t *testing.T) {
status := &Status{status: apis.StatusSkipped}
if !status.IsSkipped() {
t.Errorf("Expected IsSkipped to be true, got false")
}
}
50 changes: 29 additions & 21 deletions reporthandling/results/v1/reportsummary/controlsummarymethods.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ func (controlSummary *ControlSummary) SetStatus(statusInfo *apis.StatusInfo) {
}

func (controlSummary *ControlSummary) SetSubStatus(subStatus apis.ScanningSubStatus) {
controlSummary.SubStatus = subStatus
controlSummary.StatusInfo.SubStatus = subStatus
}

// GetSubStatus get the control sub status. returns an apis.StatusInfo object
func (controlSummary *ControlSummary) GetSubStatus() apis.ScanningSubStatus {
return controlSummary.SubStatus
return controlSummary.StatusInfo.SubStatus
}

func (controlSummary *ControlSummary) CalculateStatus() {
Expand All @@ -42,37 +42,38 @@ func (controlSummary *ControlSummary) CalculateStatus() {

// calculateStatus set the control status based on the resource counters and the sub status based on the subStatus parameter
func (controlSummary *ControlSummary) calculateStatus(subStatus apis.ScanningSubStatus) {
controlSummary.StatusInfo.InnerStatus = calculateStatus(&controlSummary.ResourceCounters)
controlSummary.StatusInfo.InnerStatus = calculateStatus(&controlSummary.StatusCounters)

// Statuses should be the same
controlSummary.Status = controlSummary.StatusInfo.Status()
controlSummary.Status = controlSummary.StatusInfo.Status() // backward compatibility

controlSummary.CalculateSubStatus(subStatus)
controlSummary.calculateNSetSubStatus(subStatus)
}

// CalculateSubStatus set the control sub status based on the resource associated control sub status
func (controlSummary *ControlSummary) CalculateSubStatus(subStatus apis.ScanningSubStatus) {
func (controlSummary *ControlSummary) calculateNSetSubStatus(subStatus apis.ScanningSubStatus) {
switch controlSummary.Status {
case apis.StatusPassed:
if subStatus == apis.SubStatusIrrelevant || controlSummary.SubStatus == apis.SubStatusIrrelevant || controlSummary.ResourceCounters.All() == 0 {
controlSummary.SubStatus = apis.SubStatusIrrelevant
if subStatus == apis.SubStatusIrrelevant || controlSummary.StatusInfo.SubStatus == apis.SubStatusIrrelevant || controlSummary.StatusCounters.All() == 0 {
controlSummary.StatusInfo.SubStatus = apis.SubStatusIrrelevant
controlSummary.StatusInfo.InnerInfo = ""
} else if subStatus == apis.SubStatusException || controlSummary.SubStatus == apis.SubStatusException {
controlSummary.SubStatus = apis.SubStatusException
} else if subStatus == apis.SubStatusException || controlSummary.StatusInfo.SubStatus == apis.SubStatusException {
controlSummary.StatusInfo.SubStatus = apis.SubStatusException
controlSummary.StatusInfo.InnerInfo = ""
}
case apis.StatusSkipped:
if subStatus == apis.SubStatusConfiguration || controlSummary.SubStatus == apis.SubStatusConfiguration {
controlSummary.SubStatus = apis.SubStatusConfiguration
if subStatus == apis.SubStatusConfiguration || controlSummary.StatusInfo.SubStatus == apis.SubStatusConfiguration {
controlSummary.StatusInfo.SubStatus = apis.SubStatusConfiguration
controlSummary.StatusInfo.InnerInfo = string(apis.SubStatusConfigurationInfo)
} else if subStatus == apis.SubStatusManualReview || controlSummary.SubStatus == apis.SubStatusManualReview {
controlSummary.SubStatus = apis.SubStatusManualReview
} else if subStatus == apis.SubStatusManualReview || controlSummary.StatusInfo.SubStatus == apis.SubStatusManualReview {
controlSummary.StatusInfo.SubStatus = apis.SubStatusManualReview
controlSummary.StatusInfo.InnerInfo = string(apis.SubStatusManualReviewInfo)
} else if subStatus == apis.SubStatusRequiresReview || controlSummary.SubStatus == apis.SubStatusRequiresReview {
controlSummary.SubStatus = apis.SubStatusRequiresReview
} else if subStatus == apis.SubStatusRequiresReview || controlSummary.StatusInfo.SubStatus == apis.SubStatusRequiresReview {
controlSummary.StatusInfo.SubStatus = apis.SubStatusRequiresReview
controlSummary.StatusInfo.InnerInfo = string(apis.SubStatusRequiresReviewInfo)
}
case apis.StatusFailed:
controlSummary.SubStatus = apis.SubStatusUnknown
controlSummary.StatusInfo.SubStatus = apis.SubStatusUnknown
controlSummary.StatusInfo.InnerInfo = ""
}
}
Expand All @@ -82,14 +83,21 @@ func (controlSummary *ControlSummary) ListResourcesIDs() *helpersv1.AllLists {
return &controlSummary.ResourceIDs
}

// NumberOf get the number of resources
// Deprecated use 'ResourcesCounters' instead
// NumberOfResources get the status counters
func (controlSummary *ControlSummary) NumberOfResources() ICounters {
return &controlSummary.ResourceCounters
return &controlSummary.StatusCounters
}

// NumberOfResources get the status counters
func (controlSummary *ControlSummary) StatusesCounters() (ICounters, ISubCounters) {
return &controlSummary.StatusCounters, &controlSummary.SubStatusCounters
}

// Increase increases the counter based on the status
func (controlSummary *ControlSummary) increase(status apis.IStatus) {
controlSummary.ResourceCounters.Increase(status)
controlSummary.StatusCounters.Increase(status)
controlSummary.SubStatusCounters.Increase(status)
}

// Append increases the counter based on the status
Expand All @@ -98,7 +106,7 @@ func (controlSummary *ControlSummary) Append(status apis.IStatus, ids ...string)
controlSummary.ResourceIDs.Append(status.Status(), ids[i])
controlSummary.increase(status)
}
controlSummary.ResourceIDs.ToUniqueResources()
controlSummary.ResourceIDs.ToUniqueResources() // TODO: check if it is needed
}

// =================================== Score ============================================
Expand Down
Loading

0 comments on commit 6e8c134

Please sign in to comment.