Repository: datreeio/datree
Pull request #30 (2021-05-09 15:03:16)

feat: print version message


Patch:
diff --git a/Makefile b/Makefile
index f55d67e..14533e3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,11 @@
 run: 
-	go run -tags staging main.go test "./internal/fixtures/**/*.yaml"
+	go run -tags staging -ldflags="-X github.com/datreeio/datree/cmd.CliVersion=0.0.1" main.go test ./internal/fixtures/**/*.yaml
 
 test:
 	go test ./...
 
 create-bin:
 	goreleaser --snapshot --skip-publish --rm-dist
+
+print-version:
+	go run -tags=staging -ldflags="-X github.com/datreeio/datree/cmd.CliVersion=0.0.1" main.go version
diff --git a/bl/versionMessage.go b/bl/versionMessage.go
new file mode 100644
index 0000000..8859881
--- /dev/null
+++ b/bl/versionMessage.go
@@ -0,0 +1,34 @@
+package bl
+
+import (
+	"time"
+
+	"github.com/datreeio/datree/pkg/cliClient"
+	"github.com/datreeio/datree/pkg/deploymentConfig"
+	"github.com/datreeio/datree/pkg/printer"
+)
+
+func PopulateVersionMessageChan(cliVersion string) chan *cliClient.VersionMessage {
+	messageChannel := make(chan *cliClient.VersionMessage, 1)
+	go func() {
+		c := cliClient.NewCliClient(deploymentConfig.URL)
+		msg, _ := c.GetVersionMessage(cliVersion)
+		if msg != nil {
+			messageChannel <- msg
+		}
+		close(messageChannel)
+	}()
+	return messageChannel
+}
+
+func HandleVersionMessage(messageChannel chan *cliClient.VersionMessage) {
+	select {
+	case msg := <-messageChannel:
+		if msg != nil {
+			p := printer.CreateNewPrinter()
+			p.PrintVersionMessage(msg.MessageText+"\n", msg.MessageColor)
+		}
+	case <-time.After(600 * time.Millisecond):
+		break
+	}
+}
diff --git a/cmd/root.go b/cmd/root.go
index d3ec039..056023b 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -1,8 +1,6 @@
 package cmd
 
 import (
-	"os"
-
 	"github.com/datreeio/datree/bl"
 	"github.com/datreeio/datree/cmd/test"
 	"github.com/datreeio/datree/cmd/version"
@@ -34,10 +32,8 @@ func init() {
 	rootCmd.AddCommand(version.NewVersionCommand(CliVersion))
 }
 
-func Execute() {
-	if err := rootCmd.Execute(); err != nil {
-		os.Exit(1)
-	}
+func Execute() error {
+	return rootCmd.Execute()
 }
 
 type app struct {
diff --git a/cmd/version/main.go b/cmd/version/main.go
index 4c7ea9c..c9dc1f3 100644
--- a/cmd/version/main.go
+++ b/cmd/version/main.go
@@ -3,6 +3,7 @@ package version
 import (
 	"fmt"
 
+	"github.com/datreeio/datree/bl"
 	"github.com/spf13/cobra"
 )
 
@@ -12,7 +13,9 @@ func NewVersionCommand(cliVersion string) *cobra.Command {
 		Short: "Print the version number",
 		Long:  "Print the version number",
 		Run: func(cmd *cobra.Command, args []string) {
+			messageChannel := bl.PopulateVersionMessageChan(cliVersion)
 			fmt.Println(cliVersion)
+			bl.HandleVersionMessage(messageChannel)
 		},
 	}
 	return versionCmd
diff --git a/main.go b/main.go
index 9b6e3cc..7612713 100644
--- a/main.go
+++ b/main.go
@@ -1,7 +1,13 @@
 package main
 
-import "github.com/datreeio/datree/cmd"
+import (
+	"os"
+
+	"github.com/datreeio/datree/cmd"
+)
 
 func main() {
-	cmd.Execute()
+	if err := cmd.Execute(); err != nil {
+		os.Exit(1)
+	}
 }
diff --git a/pkg/cliClient/cliClient.go b/pkg/cliClient/cliClient.go
index 1c90568..9b23826 100644
--- a/pkg/cliClient/cliClient.go
+++ b/pkg/cliClient/cliClient.go
@@ -63,6 +63,12 @@ type EvaluationResponse struct {
 	Status       string             `json:"status"`
 }
 
+type VersionMessage struct {
+	CliVersion   string `json:"cliVersion"`
+	MessageText  string `json:"messageText"`
+	MessageColor string `json:"messageColor"`
+}
+
 func (c *CliClient) RequestEvaluation(request EvaluationRequest) (EvaluationResponse, error) {
 	res, err := c.httpClient.Request(http.MethodPost, "/cli/evaluate", request, nil)
 	if err != nil {
@@ -77,3 +83,17 @@ func (c *CliClient) RequestEvaluation(request EvaluationRequest) (EvaluationResp
 
 	return *evaluationResponse, nil
 }
+
+func (c *CliClient) GetVersionMessage(cliVersion string) (*VersionMessage, error) {
+	res, err := c.httpClient.Request(http.MethodGet, "/cli/messages/versions/"+cliVersion, nil, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	var response = &VersionMessage{}
+	err = json.Unmarshal(res.Body, &response)
+	if err != nil {
+		return nil, err
+	}
+	return response, nil
+}
diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go
index f44a708..bc581dd 100644
--- a/pkg/printer/printer.go
+++ b/pkg/printer/printer.go
@@ -30,15 +30,15 @@ type Warning struct {
 
 func (p *Printer) PrintWarnings(warnings []Warning) {
 	for _, warning := range warnings {
-		p.printInColor(warning.Title, p.theme.Colors.Warning)
+		p.printInColor(warning.Title, p.theme.Colors.Yellow)
 
 		fmt.Println()
 
 		for _, d := range warning.Details {
 			formattedOccurrences := fmt.Sprintf(" [%d occurrences]", d.Occurrences)
-			occurrences := p.theme.Colors.Plain.Sprintf(formattedOccurrences)
+			occurrences := p.theme.Colors.White.Sprintf(formattedOccurrences)
 
-			caption := p.theme.Colors.Error.Sprint(d.Caption)
+			caption := p.theme.Colors.Red.Sprint(d.Caption)
 
 			fmt.Printf("%v %v %v\n", p.theme.Emoji.Error, caption, occurrences)
 			fmt.Printf("%v %v\n", p.theme.Emoji.Suggestion, d.Suggestion)
@@ -94,6 +94,24 @@ func (p *Printer) PrintSummaryTable(summary Summary) {
 }
 
 func (p *Printer) printInColor(title string, color *color.Color) {
-	warningColorPrintFn := color.PrintfFunc()
-	warningColorPrintFn(title)
+	colorPrintFn := color.PrintfFunc()
+	colorPrintFn(title)
+}
+
+func (p *Printer) createNewColor(clr string) *color.Color {
+	switch clr {
+	case "red":
+		return p.theme.Colors.Red
+	case "yellow":
+		return p.theme.Colors.Yellow
+	case "green":
+		return p.theme.Colors.Green
+	default:
+		return p.theme.Colors.White
+	}
+}
+
+func (p *Printer) PrintVersionMessage(messageText string, messageColor string) {
+	colorPrintFn := p.createNewColor(messageColor)
+	p.printInColor(messageText, colorPrintFn)
 }
diff --git a/pkg/printer/theme.go b/pkg/printer/theme.go
index 92ac8bd..3a9bd94 100644
--- a/pkg/printer/theme.go
+++ b/pkg/printer/theme.go
@@ -9,9 +9,10 @@ import (
 
 type theme struct {
 	Colors struct {
-		Warning *color.Color
-		Error   *color.Color
-		Plain   *color.Color
+		Green  *color.Color
+		Yellow *color.Color
+		Red    *color.Color
+		White  *color.Color
 	}
 	Spacing struct {
 		Default string
@@ -25,13 +26,15 @@ type theme struct {
 func createTheme() *theme {
 	return &theme{
 		Colors: struct {
-			Warning *color.Color
-			Error   *color.Color
-			Plain   *color.Color
+			Green  *color.Color
+			Yellow *color.Color
+			Red    *color.Color
+			White  *color.Color
 		}{
-			Warning: color.New(color.FgYellow),
-			Error:   color.New(color.FgHiRed, color.Bold),
-			Plain:   color.New(color.FgHiWhite),
+			Green:  color.New(color.FgGreen),
+			Yellow: color.New(color.FgYellow),
+			Red:    color.New(color.FgHiRed, color.Bold),
+			White:  color.New(color.FgHiWhite),
 		},
 		Spacing: struct{ Default string }{
 			Default: strings.Join([]string{" "}, ""),


Test patch:
diff --git a/cmd/test/main.go b/cmd/test/main.go
index 15a01c3..7f9ea63 100644
--- a/cmd/test/main.go
+++ b/cmd/test/main.go
@@ -81,8 +81,11 @@ func test(ctx *TestCommandContext, paths []string, flags TestCommandFlags) error
 	if evaluationResponse == nil {
 		err := fmt.Errorf("no response received")
 		return err
-
 	}
 
-	return ctx.Evaluator.PrintResults(evaluationResponse, config.CliId, flags.Output)
+	messageChannel := bl.PopulateVersionMessageChan(ctx.CliVersion)
+	err = ctx.Evaluator.PrintResults(evaluationResponse, config.CliId, flags.Output)
+	bl.HandleVersionMessage(messageChannel)
+
+	return err
 }
diff --git a/pkg/cliClient/cliClient_test.go b/pkg/cliClient/cliClient_test.go
index d01d7e3..85a4fbb 100644
--- a/pkg/cliClient/cliClient_test.go
+++ b/pkg/cliClient/cliClient_test.go
@@ -45,6 +45,28 @@ type RequestEvaluationTestCase struct {
 	}
 }
 
+type GetVersionMessageTestCase struct {
+	name string
+	args struct {
+		cliVersion string
+	}
+	mock struct {
+		response struct {
+			status int
+			body   *VersionMessage
+		}
+	}
+	expected struct {
+		request struct {
+			method  string
+			uri     string
+			body    interface{}
+			headers map[string]string
+		}
+		response *VersionMessage
+	}
+}
+
 func TestRequestEvaluation(t *testing.T) {
 	tests := []*RequestEvaluationTestCase{
 		test_requestEvaluation_success(),
@@ -72,6 +94,31 @@ func TestRequestEvaluation(t *testing.T) {
 	}
 }
 
+func TestGetVersionMessage(t *testing.T) {
+	tests := []*GetVersionMessageTestCase{
+		test_getVersionMessage_success(),
+	}
+	httpClientMock := mockHTTPClient{}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			body, _ := json.Marshal(tt.mock.response.body)
+			mockedHTTPResponse := httpClient.Response{StatusCode: tt.mock.response.status, Body: body}
+			httpClientMock.On("Request", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(mockedHTTPResponse, nil)
+
+			client := &CliClient{
+				baseUrl:    "http://cli-service.test.io",
+				httpClient: &httpClientMock,
+			}
+
+			res, _ := client.GetVersionMessage(tt.args.cliVersion)
+			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)
+
+		})
+	}
+}
+
 func readMock(path string, data interface{}) error {
 	absPath, _ := filepath.Abs(path)
 	f, err := ioutil.ReadFile(absPath)
@@ -111,6 +158,52 @@ func castPropertiesPointersMock(fileName string, path string) []*extractor.FileP
 
 }
 
+func test_getVersionMessage_success() *GetVersionMessageTestCase {
+	return &GetVersionMessageTestCase{
+		name: "success - get version message",
+		args: struct {
+			cliVersion string
+		}{
+			cliVersion: "0.0.1",
+		},
+		mock: struct {
+			response struct {
+				status int
+				body   *VersionMessage
+			}
+		}{
+			response: struct {
+				status int
+				body   *VersionMessage
+			}{
+				status: http.StatusOK,
+				body:   &VersionMessage{},
+			},
+		},
+		expected: struct {
+			request struct {
+				method  string
+				uri     string
+				body    interface{}
+				headers map[string]string
+			}
+			response *VersionMessage
+		}{
+			request: struct {
+				method  string
+				uri     string
+				body    interface{}
+				headers map[string]string
+			}{
+				method:  http.MethodGet,
+				uri:     "/cli/messages/versions/0.0.1",
+				body:    nil,
+				headers: nil,
+			},
+			response: &VersionMessage{},
+		},
+	}
+}
 func test_requestEvaluation_success() *RequestEvaluationTestCase {
 	return &RequestEvaluationTestCase{
 		name: "success - request evaluation",