Skip to content
This repository has been archived by the owner on Aug 27, 2023. It is now read-only.

Commit

Permalink
Merge pull request #3 from armosec/fix-system-endpoint-race
Browse files Browse the repository at this point in the history
fix: support concurrent access in system report endpoint
  • Loading branch information
vladklokun authored Aug 23, 2023
2 parents 1f97711 + 1e393f4 commit dd11a23
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 11 deletions.
52 changes: 42 additions & 10 deletions system-reports/datastructures/basic_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,55 @@ import (
"github.com/armosec/utils-go/httputils"

Check failure on line 11 in system-reports/datastructures/basic_report.go

View workflow job for this annotation

GitHub Actions / build

cannot find package "github.com/armosec/utils-go/httputils" in any of:
)

const (
defaultSystemReportEndpoint = "/k8s/sysreport"
)

var (
systemReportEndpoint = ""
systemReportEndpoint = &sysEndpoint{}
)

func SetSystemReportEndpoint(endpoint string) {
if endpoint == "" {
endpoint = "/k8s/sysreport"
}
systemReportEndpoint = endpoint
type sysEndpoint struct {
value string
mu sync.RWMutex
}

func (e *sysEndpoint) IsEmpty() bool {
return e.Get() == ""
}

func (e *sysEndpoint) Set(value string) {
e.mu.Lock()
e.value = value
e.mu.Unlock()
}

func (e *sysEndpoint) Get() string {
e.mu.RLock()
defer e.mu.RUnlock()
return e.value
}

// SetOrDefault sets the system report endpoint to the provided value for valid
// inputs, or to a default value on invalid ones
//
// An empty input is considered invalid, and would thus be set to a default endpoint
func (e *sysEndpoint) SetOrDefault(value string) {
if value == "" {
value = defaultSystemReportEndpoint
}
e.Set(value)
}

func GetSystemReportEndpoint() string {
if systemReportEndpoint == "" {
SetSystemReportEndpoint("")
// GetOrDefault returns the value of the current system report endpoint if it
// is set. If not set, it sets the value to a default and returns the newly set
// value
func (e *sysEndpoint) GetOrDefault() string {
current := e.Get()
if current == "" {
e.SetOrDefault("")
}
return systemReportEndpoint
return e.Get()
}

// JobsAnnotations job annotation
Expand Down
90 changes: 90 additions & 0 deletions system-reports/datastructures/datastructures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,96 @@ import (
"github.com/francoispqt/gojay"
)

func TestSystemReportEndpointSetOrDefault(t *testing.T) {
tt := []struct {
name string
input string
want string
}{
{
name: "valid value is set",
input: "/k8s/sysreport-test",
want: "/k8s/sysreport-test",
},
{
name: "empty value is set to default",
input: "",
want: "/k8s/sysreport",
},
}

for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
systemReportEndpoint.SetOrDefault(tc.input)

got := systemReportEndpoint.Get()
assert.Equal(t, tc.want, got)
})
}
}

func TestSystemReportEndpointGetOrDefault(t *testing.T) {
tt := []struct {
name string
previousValue string
want string
wantAfter string
}{
{
name: "previously set value is returned",
previousValue: "/k8s/sysreport-test",
want: "/k8s/sysreport-test",
wantAfter: "/k8s/sysreport-test",
},
{
name: "no previous value returns default",
previousValue: "",
want: "/k8s/sysreport",
wantAfter: "/k8s/sysreport",
},
}

for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
systemReportEndpoint.Set(tc.previousValue)

got := systemReportEndpoint.GetOrDefault()
gotAfter := systemReportEndpoint.Get()
assert.Equal(t, tc.want, got)
assert.Equalf(t, tc.wantAfter, gotAfter, "default value has not been set after getting with default")
})
}
}

func TestSystemReportEndpointIsEmpty(t *testing.T) {
tt := []struct {
name string
value string
want bool
}{
{
name: "empty string as endpoint value is considered empty",
value: "",
want: true,
},
{
name: "non-empty string as endpoint value is considered empty",
value: "/k8s/sysreport",
want: false,
},
}

for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
systemReportEndpoint.Set(tc.value)

got := systemReportEndpoint.IsEmpty()

assert.Equal(t, tc.want, got)
})
}
}

func TestBaseReportStructure(t *testing.T) {
// a := BaseReport{Reporter: "unit-test", Target: "unit-test-framework", JobID: "id", ActionID: "id2"}
// timestamp := a.Timestamp
Expand Down
2 changes: 1 addition & 1 deletion system-reports/datastructures/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (report *BaseReport) GetReportID() string {

// Send - send http request. returns-> http status code, return message (jobID/OK), http/go error
func (report *BaseReport) Send() (int, string, error) {
url := report.eventReceiverUrl + GetSystemReportEndpoint()
url := report.eventReceiverUrl + systemReportEndpoint.GetOrDefault()
report.Timestamp = time.Now()
if report.ActionID == "" {
report.ActionID = "1"
Expand Down

0 comments on commit dd11a23

Please sign in to comment.