Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kafka list): add search flag #364

Merged
merged 5 commits into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cmd/rhoas/pkged.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/commands/rhoas_kafka_list.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ rhoas kafka list [flags]
--limit int The maximum number of Kafka instances to be returned (default 100)
-o, --output string Format in which to display the Kafka instances. Choose from: "json", "yml", "yaml"
--page int Display the Kafka instances from the specified page number.
--search string Text search to filter the Kafka instances by name, owner, cloud_provider, region and status
....

=== Options inherited from parent commands
Expand Down
8 changes: 8 additions & 0 deletions locales/cmd/kafka/list/active.en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ one = 'Display the Kafka instances from the specified page number.'
description = 'Description for the --limit flag'
one = 'The maximum number of Kafka instances to be returned'

[kafka.list.flag.search]
description = 'Description for the --search flag'
one = 'Text search to filter the Kafka instances by name, owner, cloud_provider, region and status'

[kafka.list.log.debug.filteringKafkaList]
description = 'Debug message when filtering the list of Kafka instances'
one = 'Filtering Kafka instances with the query "{{.Search}}"'

[kafka.list.log.info.noKafkaInstances]
description = 'Info message when no Kafkas were found'
one = 'No Kafka instances were found.'
8 changes: 8 additions & 0 deletions locales/kafka/active.en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ Invalid Kafka instance name. Valid names must satisfy the following conditions:
[kafka.validation.name.error.lengthError]
one = 'Kafka instance name must be between 1 and 32 characters'

[kafka.validation.error.invalidSearchValue]
description = 'Error message when invalid search input is provided'
one = '''
illegal search value "{{.Search}}", search input must satisfy the following conditions:

- must be of 1 or more characters
- must only consist of alphanumeric characters, '-', '_' and '%'
'''

[kafka.common.error.notFoundErrorById]
one = 'Kafka instance with ID "{{.ID}}" not found'
32 changes: 32 additions & 0 deletions pkg/cmd/kafka/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package list
import (
"context"
"encoding/json"
"fmt"
"strconv"

kasclient "github.com/bf2fc6cc711aee1a0c2a/cli/pkg/api/kas/client"
flagutil "github.com/bf2fc6cc711aee1a0c2a/cli/pkg/cmdutil/flags"
"github.com/bf2fc6cc711aee1a0c2a/cli/pkg/iostreams"
"github.com/bf2fc6cc711aee1a0c2a/cli/pkg/kafka"

"github.com/bf2fc6cc711aee1a0c2a/cli/pkg/dump"

Expand Down Expand Up @@ -37,6 +39,7 @@ type options struct {
outputFormat string
page int
limit int
search string

IO *iostreams.IOStreams
Config config.IConfig
Expand All @@ -49,6 +52,7 @@ func NewListCommand(f *factory.Factory) *cobra.Command {
opts := &options{
page: 0,
limit: 100,
search: "",
Config: f.Config,
Connection: f.Connection,
Logger: f.Logger,
Expand All @@ -65,6 +69,10 @@ func NewListCommand(f *factory.Factory) *cobra.Command {
return flag.InvalidValueError("output", opts.outputFormat, flagutil.ValidOutputFormats...)
}

if err := kafka.ValidateSearchInput(opts.search); err != nil {
return err
}

return runList(opts)
},
}
Expand All @@ -75,6 +83,7 @@ func NewListCommand(f *factory.Factory) *cobra.Command {
}))
cmd.Flags().IntVarP(&opts.page, "page", "", 0, localizer.MustLocalizeFromID("kafka.list.flag.page"))
cmd.Flags().IntVarP(&opts.limit, "limit", "", 100, localizer.MustLocalizeFromID("kafka.list.flag.limit"))
cmd.Flags().StringVarP(&opts.search, "search", "", "", localizer.MustLocalizeFromID("kafka.list.flag.search"))

return cmd
}
Expand All @@ -95,6 +104,18 @@ func runList(opts *options) error {
a := api.Kafka().ListKafkas(context.Background())
a = a.Page(strconv.Itoa(opts.page))
a = a.Size(strconv.Itoa(opts.limit))

if opts.search != "" {

logger.Debug(localizer.MustLocalize(&localizer.Config{
MessageID: "kafka.list.log.debug.filteringKafkaList",
TemplateData: map[string]interface{}{
"Search": buildQuery(opts.search),
},
}))
a = a.Search(buildQuery(opts.search))
}

response, _, apiErr := a.Execute()

if apiErr.Error() != "" {
Expand Down Expand Up @@ -140,3 +161,14 @@ func mapResponseItemsToRows(kafkas []kasclient.KafkaRequest) []kafkaRow {

return rows
}

func buildQuery(search string) string {

queryString := fmt.Sprintf(
"name like %%%[1]v%% or owner like %%%[1]v%% or cloud_provider like %%%[1]v%% or region like %%%[1]v%% or status like %%%[1]v%%",
search,
)

return queryString

}
31 changes: 30 additions & 1 deletion pkg/kafka/kafka_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
)

var (
validNameRegexp = regexp.MustCompile(`^[a-z]([-a-z0-9]*[a-z0-9])?$`)
validNameRegexp = regexp.MustCompile(`^[a-z]([-a-z0-9]*[a-z0-9])?$`)
validSearchRegexp = regexp.MustCompile(`^([a-zA-Z0-9-_%]*[a-zA-Z0-9-_%])?$`)
)

// ValidateName validates the proposed name of a Kafka instance
Expand Down Expand Up @@ -69,3 +70,31 @@ func TransformKafkaRequest(kafka *kasclient.KafkaRequest) *kasclient.KafkaReques

return kafka
}

// ValidateSearchInput validates the text provided to filter the Kafka instances
func ValidateSearchInput(val interface{}) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add a comment documenting the purpose of this function

search, ok := val.(string)

if !ok {
return errors.New(localizer.MustLocalize(&localizer.Config{
MessageID: "common.error.castError",
TemplateData: map[string]interface{}{
"Value": val,
"Type": "string",
},
}))
}

matched := validSearchRegexp.MatchString(search)

if matched {
return nil
}

return errors.New(localizer.MustLocalize(&localizer.Config{
MessageID: "kafka.validation.error.invalidSearchValue",
TemplateData: map[string]interface{}{
"Search": search,
},
}))
}