Repository: datreeio/datree
Pull request #16 (2021-04-19 16:38:13)

fix: send log metadata


Patch:
diff --git a/bl/evaluator.go b/bl/evaluator.go
index 5bdaf10..6c8724d 100644
--- a/bl/evaluator.go
+++ b/bl/evaluator.go
@@ -17,15 +17,17 @@ type Printer interface {
 	PrintSummaryTable(summary printer.Summary)
 }
 type CLIClient interface {
-	RequestEvaluation(pattern string, files []*propertiesExtractor.FileProperties, cliId string) (cliClient.EvaluationResponse, error)
+	RequestEvaluation(cliClient.EvaluationRequest) (cliClient.EvaluationResponse, error)
 }
 type PropertiesExtractor interface {
 	ReadFilesFromPattern(pattern string, conc int) ([]*propertiesExtractor.FileProperties, []propertiesExtractor.FileError, []error)
 }
+
 type Evaluator struct {
 	propertiesExtractor PropertiesExtractor
 	cliClient           CLIClient
 	printer             Printer
+	osInfo              *OSInfo
 }
 
 func CreateNewEvaluator(pe PropertiesExtractor, c CLIClient, p Printer) *Evaluator {
@@ -33,6 +35,7 @@ func CreateNewEvaluator(pe PropertiesExtractor, c CLIClient, p Printer) *Evaluat
 		propertiesExtractor: pe,
 		cliClient:           c,
 		printer:             p,
+		osInfo:              NewOsInfo(),
 	}
 }
 
@@ -45,7 +48,13 @@ type EvaluationResults struct {
 	}
 }
 
-func (e *Evaluator) Evaluate(pattern string, cliId string, evaluationConc int) (*EvaluationResults, []propertiesExtractor.FileError, error) {
+type UserAgent struct {
+	OS              string
+	PlatformVersion string
+	KernelVersion   string
+}
+
+func (e *Evaluator) Evaluate(pattern string, cliId string, evaluationConc int, cliVersion string) (*EvaluationResults, []propertiesExtractor.FileError, error) {
 	files, fileErrors, errors := e.propertiesExtractor.ReadFilesFromPattern(pattern, evaluationConc)
 	if len(errors) > 0 {
 		return nil, fileErrors, fmt.Errorf("failed evaluation with the following errors: %s", errors)
@@ -55,7 +64,25 @@ func (e *Evaluator) Evaluate(pattern string, cliId string, evaluationConc int) (
 		return nil, fileErrors, fmt.Errorf("no files detected")
 	}
 
-	res, err := e.cliClient.RequestEvaluation(pattern, files, cliId)
+	var filesProperties []propertiesExtractor.FileProperties
+
+	for _, file := range files {
+		filesProperties = append(filesProperties, *file)
+	}
+
+	evaluationRequest := cliClient.EvaluationRequest{
+		CliId:   cliId,
+		Pattern: pattern,
+		Metadata: cliClient.Metadata{
+			CliVersion:      cliVersion,
+			Os:              e.osInfo.OS,
+			PlatformVersion: e.osInfo.PlatformVersion,
+			KernelVersion:   e.osInfo.KernelVersion,
+		},
+		Files: filesProperties,
+	}
+
+	res, err := e.cliClient.RequestEvaluation(evaluationRequest)
 	if err != nil {
 		return nil, fileErrors, err
 	}
diff --git a/bl/osInfo.go b/bl/osInfo.go
new file mode 100644
index 0000000..4a5e39a
--- /dev/null
+++ b/bl/osInfo.go
@@ -0,0 +1,18 @@
+package bl
+
+import "github.com/shirou/gopsutil/host"
+
+type OSInfo struct {
+	OS              string
+	PlatformVersion string
+	KernelVersion   string
+}
+
+func NewOsInfo() *OSInfo {
+	infoStat, _ := host.Info()
+	return &OSInfo{
+		OS:              infoStat.OS,
+		KernelVersion:   infoStat.KernelVersion,
+		PlatformVersion: infoStat.PlatformVersion,
+	}
+}
diff --git a/go.mod b/go.mod
index 60fccb7..b202560 100644
--- a/go.mod
+++ b/go.mod
@@ -3,15 +3,19 @@ module github.com/datreeio/datree
 go 1.15
 
 require (
+	github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
 	github.com/bmatcuk/doublestar/v2 v2.0.4
 	github.com/briandowns/spinner v1.12.0
 	github.com/fatih/color v1.10.0
+	github.com/go-ole/go-ole v1.2.5 // indirect
 	github.com/google/uuid v1.2.0 // indirect
 	github.com/kyokomi/emoji v2.2.4+incompatible
 	github.com/lithammer/shortuuid v3.0.0+incompatible
 	github.com/olekukonko/tablewriter v0.0.5
+	github.com/shirou/gopsutil v3.21.3+incompatible
 	github.com/spf13/cobra v1.1.3
 	github.com/spf13/viper v1.7.1
 	github.com/stretchr/testify v1.7.0
+	github.com/tklauser/go-sysconf v0.3.5 // indirect
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 )
diff --git a/go.sum b/go.sum
index 1246e4e..1eb0ce5 100644
--- a/go.sum
+++ b/go.sum
@@ -15,6 +15,8 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY=
+github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -53,6 +55,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
+github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@@ -177,6 +181,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/shirou/gopsutil v3.21.3+incompatible h1:uenXGGa8ESCQq+dbgtl916dmg6PSAz2cXov0uORQ9v8=
+github.com/shirou/gopsutil v3.21.3+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
@@ -208,6 +214,10 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
+github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
+github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
+github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -276,9 +286,12 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa h1:ZYxPR6aca/uhfRJyaOAtflSHjJYiktO7QnJC5ut7iY4=
+golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
diff --git a/pkg/cliClient/cliClient.go b/pkg/cliClient/cliClient.go
index 019dd30..fe1eb80 100644
--- a/pkg/cliClient/cliClient.go
+++ b/pkg/cliClient/cliClient.go
@@ -3,7 +3,6 @@ package cliClient
 import (
 	"encoding/json"
 	"net/http"
-	"runtime"
 
 	"github.com/datreeio/datree/pkg/httpClient"
 	extractor "github.com/datreeio/datree/pkg/propertiesExtractor"
@@ -12,7 +11,6 @@ import (
 type HTTPClient interface {
 	Request(method string, resourceURI string, body interface{}, headers map[string]string) (httpClient.Response, error)
 }
-
 type CliClient struct {
 	baseUrl    string
 	httpClient HTTPClient
@@ -26,14 +24,18 @@ func NewCliClient(url string) *CliClient {
 	}
 }
 
+type Metadata struct {
+	CliVersion      string `json:"cliVersion"`
+	Os              string `json:"os"`
+	PlatformVersion string `json:"platformVersion"`
+	KernelVersion   string `json:"kernelVersion"`
+}
+
 type EvaluationRequest struct {
-	CliId    string `json:"cliId"`
-	Pattern  string `json:"pattern"`
-	Metadata struct {
-		CliVersion string `json:"cliVersion"`
-		Os         string `json:"os"`
-	} `json:"metadata"`
-	Files []extractor.FileProperties `json:"files"`
+	CliId    string                     `json:"cliId"`
+	Pattern  string                     `json:"pattern"`
+	Metadata Metadata                   `json:"metadata"`
+	Files    []extractor.FileProperties `json:"files"`
 }
 
 type Match struct {
@@ -62,9 +64,8 @@ type EvaluationResponse struct {
 	Status       string             `json:"status"`
 }
 
-func (c *CliClient) RequestEvaluation(pattern string, files []*extractor.FileProperties, cliId string) (EvaluationResponse, error) {
-	evaluationRequest := c.createEvaluationRequest(pattern, files, cliId)
-	res, err := c.httpClient.Request(http.MethodPost, "/cli/evaluate", evaluationRequest, nil)
+func (c *CliClient) RequestEvaluation(request EvaluationRequest) (EvaluationResponse, error) {
+	res, err := c.httpClient.Request(http.MethodPost, "/cli/evaluate", request, nil)
 	if err != nil {
 		return EvaluationResponse{}, err
 	}
@@ -77,24 +78,3 @@ func (c *CliClient) RequestEvaluation(pattern string, files []*extractor.FilePro
 
 	return *evaluationResponse, nil
 }
-
-func (c *CliClient) createEvaluationRequest(pattern string, files []*extractor.FileProperties, cliId string) EvaluationRequest {
-	var filesProperties []extractor.FileProperties
-
-	for _, file := range files {
-		filesProperties = append(filesProperties, *file)
-	}
-
-	return EvaluationRequest{
-		CliId:   cliId,
-		Pattern: pattern,
-		Metadata: struct {
-			CliVersion string "json:\"cliVersion\""
-			Os         string "json:\"os\""
-		}{
-			CliVersion: "0.0.1",
-			Os:         runtime.GOOS,
-		},
-		Files: filesProperties,
-	}
-}


Test patch:
diff --git a/bl/evaluator_test.go b/bl/evaluator_test.go
index f4c30c5..1402de2 100644
--- a/bl/evaluator_test.go
+++ b/bl/evaluator_test.go
@@ -24,8 +24,8 @@ type mockCliClient struct {
 	mock.Mock
 }
 
-func (m *mockCliClient) RequestEvaluation(pattern string, files []*propertiesExtractor.FileProperties, cliId string) (cliClient.EvaluationResponse, error) {
-	args := m.Called(pattern, files, cliId)
+func (m *mockCliClient) RequestEvaluation(evaluationRequest cliClient.EvaluationRequest) (cliClient.EvaluationResponse, error) {
+	args := m.Called(evaluationRequest)
 	return args.Get(0).(cliClient.EvaluationResponse), args.Error(1)
 }
 
@@ -59,9 +59,10 @@ type cliClientMockTestCase struct {
 type evaluateTestCase struct {
 	name string
 	args struct {
-		pattern        string
-		cliId          string
-		evaluationConc int
+		pattern           string
+		cliId             string
+		evaluationConc    int
+		evaluationRequest cliClient.EvaluationRequest
 	}
 	mock struct {
 		propertiesExtractor propertiesExtractorMockTestCase
@@ -86,18 +87,23 @@ func TestEvaluate(t *testing.T) {
 			printer := &mockPrinter{}
 
 			propertiesExtractor.On("ReadFilesFromPattern", mock.Anything, mock.Anything).Return(tt.mock.propertiesExtractor.readFilesFromPattern.properties, tt.mock.propertiesExtractor.readFilesFromPattern.filesErrors, tt.mock.propertiesExtractor.readFilesFromPattern.errors)
-			cliClient.On("RequestEvaluation", mock.Anything, mock.Anything, mock.Anything).Return(tt.mock.cliClient.requestEvaluation.response, tt.mock.cliClient.requestEvaluation.errors)
+			cliClient.On("RequestEvaluation", mock.Anything).Return(tt.mock.cliClient.requestEvaluation.response, tt.mock.cliClient.requestEvaluation.errors)
 
 			evaluator := &Evaluator{
 				propertiesExtractor: propertiesExtractor,
 				cliClient:           cliClient,
 				printer:             printer,
+				osInfo: &OSInfo{
+					OS:              "darwin",
+					PlatformVersion: "1.2.3",
+					KernelVersion:   "4.5.6",
+				},
 			}
 
-			actualResponse, actualFilesErrs, actualErr := evaluator.Evaluate(tt.args.pattern, tt.args.cliId, tt.args.evaluationConc)
+			actualResponse, actualFilesErrs, actualErr := evaluator.Evaluate(tt.args.pattern, tt.args.cliId, tt.args.evaluationConc, "0.0.1")
 
 			propertiesExtractor.AssertCalled(t, "ReadFilesFromPattern", tt.args.pattern, tt.args.evaluationConc)
-			cliClient.AssertCalled(t, "RequestEvaluation", tt.args.pattern, tt.mock.propertiesExtractor.readFilesFromPattern.properties, tt.args.cliId)
+			cliClient.AssertCalled(t, "RequestEvaluation", tt.args.evaluationRequest)
 
 			assert.Equal(t, tt.expected.response, actualResponse)
 			assert.Equal(t, tt.expected.fileErrors, actualFilesErrs)
@@ -125,14 +131,28 @@ func test_evaluate_success() *evaluateTestCase {
 	return &evaluateTestCase{
 		name: "success",
 		args: struct {
-			pattern        string
-			cliId          string
-			evaluationConc int
+			pattern           string
+			cliId             string
+			evaluationConc    int
+			evaluationRequest cliClient.EvaluationRequest
 		}{
 			pattern:        "*/*",
 			cliId:          "cliId-test",
 			evaluationConc: 1,
-		},
+			evaluationRequest: cliClient.EvaluationRequest{
+				Pattern: "*/*",
+				CliId:   "cliId-test",
+				Metadata: cliClient.Metadata{
+					CliVersion:      "0.0.1",
+					Os:              "darwin",
+					PlatformVersion: "1.2.3",
+					KernelVersion:   "4.5.6",
+				},
+				Files: []propertiesExtractor.FileProperties{{
+					FileName:       "path1/path2/file.yaml",
+					Configurations: []propertiesExtractor.K8sConfiguration{{"apiVersion": "extensions/v1beta1"}},
+				}},
+			}},
 		mock: struct {
 			propertiesExtractor propertiesExtractorMockTestCase
 			cliClient           cliClientMockTestCase
@@ -184,14 +204,28 @@ func test_evaluate_failedRequest() *evaluateTestCase {
 	return &evaluateTestCase{
 		name: "fail",
 		args: struct {
-			pattern        string
-			cliId          string
-			evaluationConc int
+			pattern           string
+			cliId             string
+			evaluationConc    int
+			evaluationRequest cliClient.EvaluationRequest
 		}{
 			pattern:        "*/*",
 			cliId:          "cliId-test",
 			evaluationConc: 1,
-		},
+			evaluationRequest: cliClient.EvaluationRequest{
+				Pattern: "*/*",
+				CliId:   "cliId-test",
+				Metadata: cliClient.Metadata{
+					CliVersion:      "0.0.1",
+					Os:              "darwin",
+					PlatformVersion: "1.2.3",
+					KernelVersion:   "4.5.6",
+				},
+				Files: []propertiesExtractor.FileProperties{{
+					FileName:       "path1/path2/file.yaml",
+					Configurations: []propertiesExtractor.K8sConfiguration{{"apiVersion": "extensions/v1beta1"}},
+				}},
+			}},
 		mock: struct {
 			propertiesExtractor propertiesExtractorMockTestCase
 			cliClient           cliClientMockTestCase
diff --git a/cmd/test/main.go b/cmd/test/main.go
index c49ad24..f6b5343 100644
--- a/cmd/test/main.go
+++ b/cmd/test/main.go
@@ -19,7 +19,7 @@ type LocalConfigManager interface {
 type Evaluator interface {
 	PrintResults(results *bl.EvaluationResults, cliId string, output string) error
 	PrintFileParsingErrors(errors []propertiesExtractor.FileError)
-	Evaluate(pattern string, cliId string, evaluationConc int) (*bl.EvaluationResults, []propertiesExtractor.FileError, error)
+	Evaluate(pattern string, cliId string, evaluationConc int, cliVersion string) (*bl.EvaluationResults, []propertiesExtractor.FileError, error)
 }
 
 type TestCommandContext struct {
@@ -74,7 +74,7 @@ func test(ctx *TestCommandContext, pattern string, flags TestCommandFlags) error
 		return err
 	}
 
-	evaluationResponse, fileParsingErrors, err := ctx.Evaluator.Evaluate(absolutePath, config.CliId, 50)
+	evaluationResponse, fileParsingErrors, err := ctx.Evaluator.Evaluate(absolutePath, config.CliId, 50, "0.0.1")
 	s.Stop()
 
 	if err != nil {
diff --git a/cmd/test/main_test.go b/cmd/test/main_test.go
index 7cde8aa..e069150 100644
--- a/cmd/test/main_test.go
+++ b/cmd/test/main_test.go
@@ -32,7 +32,7 @@ func (m *mockEvaluator) PrintFileParsingErrors(errors []propertiesExtractor.File
 	m.Called(errors)
 }
 
-func (m *mockEvaluator) Evaluate(pattern string, cliId string, evaluationConc int) (*bl.EvaluationResults, []propertiesExtractor.FileError, error) {
+func (m *mockEvaluator) Evaluate(pattern string, cliId string, evaluationConc int, cliVersion string) (*bl.EvaluationResults, []propertiesExtractor.FileError, error) {
 	args := m.Called(pattern, cliId, evaluationConc)
 	return args.Get(0).(*bl.EvaluationResults), args.Get(1).([]propertiesExtractor.FileError), args.Error(2)
 }
@@ -45,7 +45,7 @@ func TestTestCommand(t *testing.T) {
 			FilesCount       int
 		}{RulesCount: 1, TotalFailedRules: 0, FilesCount: 0},
 	}
-	evaluator.On("Evaluate", mock.Anything, mock.Anything, mock.Anything).Return(mockedEvaluateResponse, []propertiesExtractor.FileError{}, nil)
+	evaluator.On("Evaluate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(mockedEvaluateResponse, []propertiesExtractor.FileError{}, nil)
 	evaluator.On("PrintFileParsingErrors", mock.Anything).Return()
 	evaluator.On("PrintResults", mock.Anything, mock.Anything, mock.Anything).Return()
 
diff --git a/pkg/cliClient/cliClient_test.go b/pkg/cliClient/cliClient_test.go
index 2a1f135..bf6e210 100644
--- a/pkg/cliClient/cliClient_test.go
+++ b/pkg/cliClient/cliClient_test.go
@@ -5,7 +5,6 @@ import (
 	"io/ioutil"
 	"net/http"
 	"path/filepath"
-	"runtime"
 	"testing"
 
 	"github.com/datreeio/datree/pkg/httpClient"
@@ -27,9 +26,7 @@ func (c *mockHTTPClient) Request(method string, resourceURI string, body interfa
 type RequestEvaluationTestCase struct {
 	name string
 	args struct {
-		pattern    string
-		cliId      string
-		properties []*extractor.FileProperties
+		evaluationRequest *EvaluationRequest
 	}
 	mock struct {
 		response struct {
@@ -66,7 +63,7 @@ func TestRequestEvaluation(t *testing.T) {
 				httpClient: &httpClientMock,
 			}
 
-			res, _ := client.RequestEvaluation(tt.args.pattern, tt.args.properties, tt.args.cliId)
+			res, _ := client.RequestEvaluation(*tt.args.evaluationRequest)
 
 			httpClientMock.AssertCalled(t, "Request", tt.expected.request.method, tt.expected.request.uri, *tt.expected.request.body, tt.expected.request.headers)
 			assert.Equal(t, *tt.expected.response, res)
@@ -118,13 +115,19 @@ func test_requestEvaluation_success() *RequestEvaluationTestCase {
 	return &RequestEvaluationTestCase{
 		name: "success - request evaluation",
 		args: struct {
-			pattern    string
-			cliId      string
-			properties []*extractor.FileProperties
+			evaluationRequest *EvaluationRequest
 		}{
-			pattern:    "pattern",
-			properties: castPropertiesPointersMock("service_mock", "mocks/service_mock.yaml"),
-			cliId:      "cli-id-test",
+			evaluationRequest: &EvaluationRequest{
+				CliId:   "cli-id-test",
+				Pattern: "pattern",
+				Files:   castPropertiesMock("service_mock", "mocks/service_mock.yaml"),
+				Metadata: Metadata{
+					CliVersion:      "0.0.1",
+					Os:              "darwin",
+					PlatformVersion: "1.2.3",
+					KernelVersion:   "4.5.6",
+				},
+			},
 		},
 		mock: struct {
 			response struct {
@@ -161,12 +164,11 @@ func test_requestEvaluation_success() *RequestEvaluationTestCase {
 					CliId:   "cli-id-test",
 					Pattern: "pattern",
 					Files:   castPropertiesMock("service_mock", "mocks/service_mock.yaml"),
-					Metadata: struct {
-						CliVersion string "json:\"cliVersion\""
-						Os         string "json:\"os\""
-					}{
-						CliVersion: "0.0.1",
-						Os:         runtime.GOOS,
+					Metadata: Metadata{
+						CliVersion:      "0.0.1",
+						Os:              "darwin",
+						PlatformVersion: "1.2.3",
+						KernelVersion:   "4.5.6",
 					},
 				},
 				headers: nil,