Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature(CLI): Analyzer Resource Integration (#2726)
* feature(CLI): Analyzer Resource Integration * feature(CLI): including e2e tests * feature(CLI): including e2e tests * feature(CLI): including e2e tests * fixing comments * fixing test file names
- Loading branch information
Showing
19 changed files
with
517 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package actions | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/kubeshop/tracetest/cli/file" | ||
"github.com/kubeshop/tracetest/cli/openapi" | ||
"github.com/kubeshop/tracetest/cli/utils" | ||
"github.com/kubeshop/tracetest/server/model/yaml" | ||
) | ||
|
||
type analyzerActions struct { | ||
resourceArgs | ||
} | ||
|
||
var _ ResourceActions = &analyzerActions{} | ||
|
||
func NewAnalyzerActions(options ...ResourceArgsOption) analyzerActions { | ||
args := NewResourceArgs(options...) | ||
|
||
return analyzerActions{ | ||
resourceArgs: args, | ||
} | ||
} | ||
|
||
func (analyzerActions) FileType() yaml.FileType { | ||
return yaml.FileTypeAnalyzer | ||
} | ||
|
||
func (analyzerActions) Name() string { | ||
return "analyzer" | ||
} | ||
|
||
func (analyzer analyzerActions) GetID(file *file.File) (string, error) { | ||
resource, err := analyzer.formatter.ToStruct(file) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return *resource.(openapi.LinterResource).Spec.Id, nil | ||
} | ||
|
||
func (analyzer analyzerActions) Apply(ctx context.Context, fileContent file.File) (result *file.File, err error) { | ||
result, err = analyzer.resourceClient.Update(ctx, fileContent, currentConfigID) | ||
return result, err | ||
} | ||
|
||
func (analyzer analyzerActions) Get(ctx context.Context, ID string) (*file.File, error) { | ||
return analyzer.resourceClient.Get(ctx, currentConfigID) | ||
} | ||
|
||
func (analyzer analyzerActions) List(ctx context.Context, listArgs utils.ListArgs) (*file.File, error) { | ||
return analyzer.resourceClient.List(ctx, listArgs) | ||
} | ||
|
||
func (analyzer analyzerActions) Delete(ctx context.Context, ID string) (string, error) { | ||
return "", ErrNotSupportedResourceAction | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package formatters | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/alexeyco/simpletable" | ||
"github.com/goccy/go-yaml" | ||
"github.com/kubeshop/tracetest/cli/file" | ||
"github.com/kubeshop/tracetest/cli/openapi" | ||
) | ||
|
||
type AnalyzerFormatter struct{} | ||
|
||
var _ ResourceFormatter = AnalyzerFormatter{} | ||
|
||
func NewAnalyzerFormatter() AnalyzerFormatter { | ||
return AnalyzerFormatter{} | ||
} | ||
|
||
func (f AnalyzerFormatter) ToTable(file *file.File) (*simpletable.Header, *simpletable.Body, error) { | ||
rawConfig, err := f.ToStruct(file) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
linterResource := rawConfig.(openapi.LinterResource) | ||
row, err := f.getTableRow(linterResource) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
body := simpletable.Body{} | ||
body.Cells = [][]*simpletable.Cell{row} | ||
|
||
return f.getTableHeader(), &body, nil | ||
} | ||
|
||
func (f AnalyzerFormatter) ToListTable(file *file.File) (*simpletable.Header, *simpletable.Body, error) { | ||
rawConfigList, err := f.ToListStruct(file) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
body := simpletable.Body{} | ||
for _, rawConfig := range rawConfigList { | ||
linterResource := rawConfig.(openapi.LinterResource) | ||
row, err := f.getTableRow(linterResource) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
body.Cells = append(body.Cells, row) | ||
} | ||
|
||
return f.getTableHeader(), &body, nil | ||
} | ||
|
||
func (f AnalyzerFormatter) ToStruct(file *file.File) (interface{}, error) { | ||
var linterResource openapi.LinterResource | ||
err := yaml.Unmarshal([]byte(file.Contents()), &linterResource) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return linterResource, nil | ||
} | ||
|
||
func (f AnalyzerFormatter) ToListStruct(file *file.File) ([]interface{}, error) { | ||
var analyzerList openapi.LinterResourceList | ||
|
||
err := yaml.Unmarshal([]byte(file.Contents()), &analyzerList) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
items := make([]interface{}, len(analyzerList.Items)) | ||
for i, item := range analyzerList.Items { | ||
items[i] = item | ||
} | ||
|
||
return items, nil | ||
} | ||
|
||
func (f AnalyzerFormatter) getTableHeader() *simpletable.Header { | ||
return &simpletable.Header{ | ||
Cells: []*simpletable.Cell{ | ||
{Text: "ID"}, | ||
{Text: "NAME"}, | ||
{Text: "ENABLED"}, | ||
{Text: "MINIMUM SCORE"}, | ||
}, | ||
} | ||
} | ||
|
||
func (f AnalyzerFormatter) getTableRow(t openapi.LinterResource) ([]*simpletable.Cell, error) { | ||
return []*simpletable.Cell{ | ||
{Text: *t.Spec.Id}, | ||
{Text: *t.Spec.Name}, | ||
{Text: fmt.Sprintf("%t", *t.Spec.Enabled)}, | ||
{Text: fmt.Sprintf("%d", *t.Spec.MinimumScore)}, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
testing/cli-e2etest/testscenarios/analyzer/apply_analyzer_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package analyzer | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/kubeshop/tracetest/cli-e2etest/environment" | ||
"github.com/kubeshop/tracetest/cli-e2etest/helpers" | ||
"github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" | ||
"github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestApplyAnalyzer(t *testing.T) { | ||
// instantiate require with testing helper | ||
require := require.New(t) | ||
|
||
// setup isolated e2e environment | ||
env := environment.CreateAndStart(t) | ||
defer env.Close(t) | ||
|
||
cliConfig := env.GetCLIConfigPath(t) | ||
|
||
// Given I am a Tracetest CLI user | ||
// And I have my server recently created | ||
|
||
// When I try to set up a new analyzer | ||
// Then it should be applied with success | ||
configPath := env.GetTestResourcePath(t, "new-analyzer") | ||
|
||
result := tracetestcli.Exec(t, fmt.Sprintf("apply analyzer --file %s", configPath), tracetestcli.WithCLIConfig(cliConfig)) | ||
helpers.RequireExitCodeEqual(t, result, 0) | ||
|
||
// When I try to get a analyzer again | ||
// Then it should return the analyzer applied on the last step, with analytics disabled | ||
result = tracetestcli.Exec(t, "get analyzer --id current", tracetestcli.WithCLIConfig(cliConfig)) | ||
helpers.RequireExitCodeEqual(t, result, 0) | ||
|
||
analyzer := helpers.UnmarshalYAML[types.AnalyzerResource](t, result.StdOut) | ||
require.Equal("Analyzer", analyzer.Type) | ||
require.Equal("current", analyzer.Spec.Id) | ||
require.Equal("analyzer", analyzer.Spec.Name) | ||
require.True(analyzer.Spec.Enabled) | ||
require.Equal(analyzer.Spec.MinimumScore, 95) | ||
require.Len(analyzer.Spec.Plugins, 3) | ||
} |
30 changes: 30 additions & 0 deletions
30
testing/cli-e2etest/testscenarios/analyzer/delete_analyzer_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package analyzer | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/kubeshop/tracetest/cli-e2etest/environment" | ||
"github.com/kubeshop/tracetest/cli-e2etest/helpers" | ||
"github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestDeleteAnalyzer(t *testing.T) { | ||
// instantiate require with testing helper | ||
require := require.New(t) | ||
|
||
// setup isolated e2e environment | ||
env := environment.CreateAndStart(t) | ||
defer env.Close(t) | ||
|
||
cliConfig := env.GetCLIConfigPath(t) | ||
|
||
// Given I am a Tracetest CLI user | ||
// And I have my server recently created | ||
|
||
// When I try to delete the analyzer | ||
// Then it should return a error message, showing that we cannot delete a analyzer | ||
result := tracetestcli.Exec(t, "delete analyzer --id current", tracetestcli.WithCLIConfig(cliConfig)) | ||
helpers.RequireExitCodeEqual(t, result, 1) | ||
require.Contains(result.StdErr, "the specified resource type doesn't support the action") | ||
} |
108 changes: 108 additions & 0 deletions
108
testing/cli-e2etest/testscenarios/analyzer/get_analyzer_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package analyzer | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/kubeshop/tracetest/cli-e2etest/environment" | ||
"github.com/kubeshop/tracetest/cli-e2etest/helpers" | ||
"github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" | ||
"github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func addGetAnalyzerPreReqs(t *testing.T, env environment.Manager) { | ||
cliConfig := env.GetCLIConfigPath(t) | ||
|
||
// When I try to set up a analyzer | ||
// Then it should be applied with success | ||
configPath := env.GetTestResourcePath(t, "new-analyzer") | ||
|
||
result := tracetestcli.Exec(t, fmt.Sprintf("apply analyzer --file %s", configPath), tracetestcli.WithCLIConfig(cliConfig)) | ||
helpers.RequireExitCodeEqual(t, result, 0) | ||
} | ||
|
||
func TestGetAnalyzer(t *testing.T) { | ||
// instantiate require with testing helper | ||
require := require.New(t) | ||
|
||
env := environment.CreateAndStart(t) | ||
defer env.Close(t) | ||
|
||
cliConfig := env.GetCLIConfigPath(t) | ||
|
||
t.Run("get with no analyzer initialized", func(t *testing.T) { | ||
// Given I am a Tracetest CLI user | ||
// And I have my server recently created | ||
// And no analyzer previously registered | ||
|
||
// When I try to get a analyzer on yaml mode | ||
// Then it should print a YAML with the default analyzer | ||
result := tracetestcli.Exec(t, "get analyzer --id current --output yaml", tracetestcli.WithCLIConfig(cliConfig)) | ||
require.Equal(0, result.ExitCode) | ||
|
||
analyzer := helpers.UnmarshalYAML[types.AnalyzerResource](t, result.StdOut) | ||
require.Equal("Analyzer", analyzer.Type) | ||
require.Equal("current", analyzer.Spec.Id) | ||
require.Equal("analyzer", analyzer.Spec.Name) | ||
require.True(analyzer.Spec.Enabled) | ||
require.Equal(analyzer.Spec.MinimumScore, 0) | ||
require.Len(analyzer.Spec.Plugins, 3) | ||
}) | ||
|
||
addGetAnalyzerPreReqs(t, env) | ||
|
||
t.Run("get with YAML format", func(t *testing.T) { | ||
// Given I am a Tracetest CLI user | ||
// And I have my server recently created | ||
// And I have a config already set | ||
|
||
// When I try to get a config on yaml mode | ||
// Then it should print a YAML | ||
result := tracetestcli.Exec(t, "get analyzer --id current --output yaml", tracetestcli.WithCLIConfig(cliConfig)) | ||
require.Equal(0, result.ExitCode) | ||
|
||
analyzer := helpers.UnmarshalYAML[types.AnalyzerResource](t, result.StdOut) | ||
require.Equal("Analyzer", analyzer.Type) | ||
require.Equal("current", analyzer.Spec.Id) | ||
require.Equal("analyzer", analyzer.Spec.Name) | ||
require.True(analyzer.Spec.Enabled) | ||
require.Equal(analyzer.Spec.MinimumScore, 95) | ||
require.Len(analyzer.Spec.Plugins, 3) | ||
}) | ||
|
||
t.Run("get with JSON format", func(t *testing.T) { | ||
// Given I am a Tracetest CLI user | ||
// And I have my server recently created | ||
// And I have a analyzer already set | ||
|
||
// When I try to get a analyzer on json mode | ||
// Then it should print a json | ||
result := tracetestcli.Exec(t, "get analyzer --id current --output json", tracetestcli.WithCLIConfig(cliConfig)) | ||
helpers.RequireExitCodeEqual(t, result, 0) | ||
|
||
analyzer := helpers.UnmarshalJSON[types.AnalyzerResource](t, result.StdOut) | ||
require.Equal("Analyzer", analyzer.Type) | ||
require.Equal("current", analyzer.Spec.Id) | ||
require.Equal("analyzer", analyzer.Spec.Name) | ||
require.True(analyzer.Spec.Enabled) | ||
require.Equal(analyzer.Spec.MinimumScore, 95) | ||
require.Len(analyzer.Spec.Plugins, 3) | ||
}) | ||
|
||
t.Run("get with pretty format", func(t *testing.T) { | ||
// Given I am a Tracetest CLI user | ||
// And I have my server recently created | ||
// And I have a analyzer already set | ||
|
||
// When I try to get a analyzer on pretty mode | ||
// Then it should print a table with 4 lines printed: header, separator, a analyzer item and empty line | ||
result := tracetestcli.Exec(t, "get analyzer --id current --output pretty", tracetestcli.WithCLIConfig(cliConfig)) | ||
helpers.RequireExitCodeEqual(t, result, 0) | ||
require.Contains(result.StdOut, "current") | ||
|
||
lines := strings.Split(result.StdOut, "\n") | ||
require.Len(lines, 4) | ||
}) | ||
} |
Oops, something went wrong.