Skip to content

Commit

Permalink
fix: review changes
Browse files Browse the repository at this point in the history
- updated table as the default output format
- updated tablewriter settings
- added unit test for the components of db providers command
- added dummy "provider-metadata.json" to aid unit tests
- added table and json assertion to cli test

Signed-off-by: Adnan Gulegulzar <gulegulzaradnan@gmail.com>
  • Loading branch information
ADorigi committed Oct 22, 2024
1 parent 687f789 commit 902e9a7
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 10 deletions.
41 changes: 32 additions & 9 deletions cmd/grype/cli/commands/db_providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (d *dbProvidersOptions) AddFlags(flags clio.FlagSet) {

func DBProviders(app clio.Application) *cobra.Command {
opts := &dbProvidersOptions{
Output: internal.JSONOutputFormat,
Output: internal.TableOutputFormat,
}

return app.SetupCommand(&cobra.Command{
Expand All @@ -54,7 +54,12 @@ func DBProviders(app clio.Application) *cobra.Command {
}

func runDBProviders(opts *dbProvidersOptions, app clio.Application) error {
providers, err := getDBProviders(app)

metadataFileLocation, err := getMetadataFileLocation(app)
if err != nil {
return nil
}
providers, err := getDBProviders(*metadataFileLocation)
if err != nil {
return err
}
Expand All @@ -77,32 +82,38 @@ func runDBProviders(opts *dbProvidersOptions, app clio.Application) error {
return nil
}

func getDBProviders(app clio.Application) (*dbProviders, error) {
func getMetadataFileLocation(app clio.Application) (*string, error) {

dbCurator, err := distribution.NewCurator(dbOptionsDefault(app.ID()).DB.ToCuratorConfig())
if err != nil {
return nil, err
}

metadataFileLocation := dbCurator.Status().Location
location := dbCurator.Status().Location

return &location, nil
}

func getDBProviders(metadataFileLocation string) (*dbProviders, error) {
metadataFile := path.Join(metadataFileLocation, metadataFileName)

file, err := os.Open(metadataFile)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("file not found: %v", err)
return nil, fmt.Errorf("file not found: %w", err)
}
return nil, fmt.Errorf("error opening file: %v", err)
return nil, fmt.Errorf("error opening file: %w", err)
}
defer file.Close()

var providers dbProviders
fileBytes, err := io.ReadAll(file)
if err != nil {
return nil, fmt.Errorf("error reading file: %v", err)
return nil, fmt.Errorf("error reading file: %w", err)
}
err = json.Unmarshal(fileBytes, &providers)
if err != nil {
return nil, fmt.Errorf("cannot unmarshal providers: %v", err)
return nil, fmt.Errorf("cannot unmarshal providers: %w", err)
}

return &providers, nil
Expand All @@ -117,6 +128,18 @@ func displayDBProvidersTable(providers []dbProviderMetadata, output io.Writer) {
table := tablewriter.NewWriter(output)
table.SetHeader([]string{"Name", "Last Successful Run"})

table.SetHeaderLine(false)
table.SetBorder(false)
table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetTablePadding(" ")
table.SetNoWhiteSpace(true)

table.AppendBulk(rows)
table.Render()
}
Expand All @@ -127,7 +150,7 @@ func displayDBProvidersJSON(providers *dbProviders, output io.Writer) error {
encoder.SetIndent("", " ")
err := encoder.Encode(providers)
if err != nil {
return fmt.Errorf("cannot display json: %v", err)
return fmt.Errorf("cannot display json: %w", err)
}
return nil
}
151 changes: 151 additions & 0 deletions cmd/grype/cli/commands/db_providers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package commands

import (
"bytes"
"encoding/json"
"errors"
"os"
"reflect"
"testing"
)

func TestGetDBProviders(t *testing.T) {

tests := []struct {
name string
fileLocation string
expectedProviders dbProviders
expectedError error
}{
{
name: "test provider metadata file",
fileLocation: "./test-fixtures",
expectedProviders: dbProviders{
Providers: []dbProviderMetadata{
dbProviderMetadata{
Name: "provider1",
LastSuccessfulRun: "2024-10-16T01:33:16.844201Z",
},
dbProviderMetadata{
Name: "provider2",
LastSuccessfulRun: "2024-10-16T01:32:43.516596Z",
},
},
},
expectedError: nil,
},
{
name: "no metadata file found",
fileLocation: "./",
expectedProviders: dbProviders{},
expectedError: os.ErrNotExist,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
providers, err := getDBProviders(test.fileLocation)
if err != nil {
if errors.Is(err, test.expectedError) {
return
}
t.Errorf("getDBProviders() expected list of providers, got error: %v", err)
return
}
if !reflect.DeepEqual(*providers, test.expectedProviders) {
t.Error("getDBProviders() providers comparison failed, got error")
}
})
}

}

func TestDisplayDBProvidersTable(t *testing.T) {
tests := []struct {
name string
providers dbProviders
expectedOutput string
}{
{
name: "display providers table",
providers: dbProviders{
Providers: []dbProviderMetadata{
dbProviderMetadata{
Name: "provider1",
LastSuccessfulRun: "2024-10-16T01:33:16.844201Z",
},
dbProviderMetadata{
Name: "provider2",
LastSuccessfulRun: "2024-10-16T01:32:43.516596Z",
},
},
},
expectedOutput: "NAME LAST SUCCESSFUL RUN \nprovider1 2024-10-16T01:33:16.844201Z \nprovider2 2024-10-16T01:32:43.516596Z \n",
},
{
name: "empty list of providers",
providers: dbProviders{
Providers: []dbProviderMetadata{},
},
expectedOutput: "NAME LAST SUCCESSFUL RUN \n",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {

var out bytes.Buffer
displayDBProvidersTable(test.providers.Providers, &out)
outputString := out.String()
if outputString != test.expectedOutput {
t.Errorf("displayDBProvidersTable() = %v, want %v", out.String(), test.expectedOutput)
}
})
}
}

func TestDisplayDBProvidersJSON(t *testing.T) {
tests := []struct {
name string
providers dbProviders
}{

{
name: "display providers table",
providers: dbProviders{
Providers: []dbProviderMetadata{
dbProviderMetadata{
Name: "provider1",
LastSuccessfulRun: "2024-10-16T01:33:16.844201Z",
},
dbProviderMetadata{
Name: "provider2",
LastSuccessfulRun: "2024-10-16T01:32:43.516596Z",
},
},
},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {

var out bytes.Buffer
err := displayDBProvidersJSON(&test.providers, &out)
if err != nil {
t.Error(err)
}
var providers dbProviders

err = json.Unmarshal(out.Bytes(), &providers)
if err != nil {
t.Error(err)
}

if !reflect.DeepEqual(providers, test.providers) {
t.Error("DBProvidersJSON() providers comparison failed, got error")
}

})
}
}
12 changes: 12 additions & 0 deletions cmd/grype/cli/commands/test-fixtures/provider-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"providers": [
{
"name": "provider1",
"lastSuccessfulRun": "2024-10-16T01:33:16.844201Z"
},
{
"name": "provider2",
"lastSuccessfulRun": "2024-10-16T01:32:43.516596Z"
}
]
}
5 changes: 4 additions & 1 deletion test/cli/db_providers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ func TestDBProviders(t *testing.T) {
name: "db providers command",
args: []string{"db", "providers"},
assertions: []traitAssertion{
assertInOutput("providers"),
assertInOutput("LAST SUCCESSFUL RUN"),
assertNoStderr,
assertTableReport,
},
},
{
Expand All @@ -34,6 +35,7 @@ func TestDBProviders(t *testing.T) {
assertions: []traitAssertion{
assertInOutput("LAST SUCCESSFUL RUN"),
assertNoStderr,
assertTableReport,
},
},
{
Expand All @@ -42,6 +44,7 @@ func TestDBProviders(t *testing.T) {
assertions: []traitAssertion{
assertInOutput("providers"),
assertNoStderr,
assertJsonReport,
},
},
}
Expand Down
17 changes: 17 additions & 0 deletions test/cli/trait_assertions_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cli

import (
"encoding/json"
"strings"
"testing"

Expand Down Expand Up @@ -70,3 +71,19 @@ func assertNotInOutput(notWanted string) traitAssertion {
}
}
}

func assertJsonReport(tb testing.TB, stdout, _ string, _ int) {
tb.Helper()
var data interface{}

if err := json.Unmarshal([]byte(stdout), &data); err != nil {
tb.Errorf("expected to find a JSON report, but was unmarshalable: %+v", err)
}
}

func assertTableReport(tb testing.TB, stdout, _ string, _ int) {
tb.Helper()
if !strings.Contains(stdout, "NAME") || !strings.Contains(stdout, "LAST SUCCESSFUL RUN") {
tb.Errorf("expected to find a table report, but did not")
}
}

0 comments on commit 902e9a7

Please # to comment.