diff --git a/Makefile b/Makefile index f55d67e04b..14533e3e9d 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 0000000000..8859881734 --- /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 d3ec039263..056023b939 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/test/main.go b/cmd/test/main.go index 15a01c3732..7f9ea63185 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/cmd/version/main.go b/cmd/version/main.go index 4c7ea9c62a..c9dc1f3bad 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 9b6e3cc4a6..76127138a0 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 1c90568b7d..9b23826dce 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/cliClient/cliClient_test.go b/pkg/cliClient/cliClient_test.go index d01d7e386e..85a4fbba14 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", diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index f44a70854a..bc581ddd45 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 92ac8bd4e7..3a9bd94268 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{" "}, ""),