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

Standardize old resources to to use list method with SQL Injection protection and stardardize PollingProfile file #2839

Merged
merged 3 commits into from
Jun 29, 2023
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
2 changes: 1 addition & 1 deletion server/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ init-submodule:
git submodule init
git submodule update

test: # run go tests for this application
test: ## run go tests for this application
go test -timeout 150s -coverprofile=coverage.out ./...

vet: ## run vet tool to analyze the code for suspicious, abnormal, or useless code
Expand Down
37 changes: 21 additions & 16 deletions server/config/demo/demo_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"

"github.com/kubeshop/tracetest/server/pkg/id"
"github.com/kubeshop/tracetest/server/pkg/sqlutil"
"github.com/kubeshop/tracetest/server/resourcemanager"
)

Expand Down Expand Up @@ -182,30 +183,34 @@ func (r Repository) SortingFields() []string {
return []string{"id", "name", "type"}
}

func (r *Repository) List(ctx context.Context, take, skip int, query, sortBy, sortDirection string) ([]Demo, error) {
listQuery := baseSelect
func listQuery(baseSQL, query string, params []any) (string, []any) {
paramNumber := len(params) + 1
condition := fmt.Sprintf(" AND (t.name ilike $%d)", paramNumber)

if sortDirection == "" {
sortDirection = "ASC"
}
sql, params := sqlutil.Search(baseSQL, condition, query, params)

if query != "" {
listQuery = fmt.Sprintf("%s WHERE %s", listQuery, query)
}
return sql, params
}

if sortBy != "" {
listQuery = fmt.Sprintf("%s ORDER BY %s %s", listQuery, sortBy, sortDirection)
}
func (r *Repository) List(ctx context.Context, take, skip int, query, sortBy, sortDirection string) ([]Demo, error) {
q, params := listQuery(baseSelect, query, []any{take, skip})

if take > 0 {
listQuery = fmt.Sprintf("%s LIMIT %d", listQuery, take)
sortingFields := map[string]string{
"id": "id",
"name": "name",
"type": "type",
}

if skip > 0 {
listQuery = fmt.Sprintf("%s OFFSET %d", listQuery, skip)
q = sqlutil.Sort(q, sortBy, sortDirection, "name", sortingFields)
q += " LIMIT $1 OFFSET $2"

stmt, err := r.db.Prepare(q)
if err != nil {
return nil, err
}
defer stmt.Close()

rows, err := r.db.QueryContext(ctx, listQuery)
rows, err := stmt.QueryContext(ctx, params...)
if err != nil {
return nil, fmt.Errorf("sql query: %w", err)
}
Expand Down
22 changes: 12 additions & 10 deletions server/environment/environment_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/kubeshop/tracetest/server/pkg/id"
"github.com/kubeshop/tracetest/server/pkg/sqlutil"
)

type Repository struct {
Expand Down Expand Up @@ -119,27 +120,28 @@ func (r *Repository) Delete(ctx context.Context, id id.ID) error {
return nil
}

func listQuery(baseSQL, query string, params []any) (string, []any) {
paramNumber := len(params) + 1
condition := fmt.Sprintf(" AND (t.name ilike $%d OR e.description ilike $%d)", paramNumber, paramNumber)

sql, params := sqlutil.Search(baseSQL, condition, query, params)

return sql, params
}

func (r *Repository) List(ctx context.Context, take, skip int, query, sortBy, sortDirection string) ([]Environment, error) {
if take == 0 {
take = 20
}

params := []any{take, skip}

sql := getQuery

const condition = "WHERE (e.name ilike $3 OR e.description ilike $3) "
if query != "" {
sql += condition
params = append(params, query)
}
sql, params := listQuery(getQuery, query, []any{take, skip})

sortingFields := map[string]string{
"created": "e.created_at",
"name": "e.name",
}

sql = sortQuery(sql, sortBy, sortDirection, sortingFields)
sql = sqlutil.Sort(sql, sortBy, sortDirection, "created", sortingFields)
sql += ` LIMIT $1 OFFSET $2 `

stmt, err := r.db.Prepare(sql)
Expand Down
100 changes: 100 additions & 0 deletions server/executor/pollingprofile/polling_profile_entities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package pollingprofile

import (
"fmt"
"math"
"time"

"github.com/kubeshop/tracetest/server/pkg/id"
"github.com/kubeshop/tracetest/server/resourcemanager"
)

type Strategy string

const (
Periodic Strategy = "periodic"
)

const (
ResourceName = "PollingProfile"
ResourceNamePlural = "PollingProfiles"
)

var Operations = []resourcemanager.Operation{
resourcemanager.OperationGet,
resourcemanager.OperationList,
resourcemanager.OperationUpdate,
}

var DefaultPollingProfile = PollingProfile{
ID: id.ID("current"),
Name: "default",
Default: true,
Strategy: Periodic,
Periodic: &PeriodicPollingConfig{
Timeout: "1m",
RetryDelay: "5s",
},
}

type PollingProfile struct {
ID id.ID `json:"id"`
Name string `json:"name"`
Default bool `json:"default"`
Strategy Strategy `json:"strategy"`
Periodic *PeriodicPollingConfig `json:"periodic"`
}

type PeriodicPollingConfig struct {
RetryDelay string `json:"retryDelay"`
Timeout string `json:"timeout"`
SelectorMatchRetries int `json:"selectorMatchRetries"`
}

func (ppc *PeriodicPollingConfig) TimeoutDuration() time.Duration {
d, _ := time.ParseDuration(ppc.Timeout)
return d
}

func (ppc *PeriodicPollingConfig) RetryDelayDuration() time.Duration {
d, _ := time.ParseDuration(ppc.RetryDelay)
return d
}

func (ppc *PeriodicPollingConfig) MaxTracePollRetry() int {
return int(math.Ceil(float64(ppc.TimeoutDuration()) / float64(ppc.RetryDelayDuration())))
}

func (ppc *PeriodicPollingConfig) Validate() error {
if ppc == nil {
return fmt.Errorf("missing periodic polling profile configuration")
}

if _, err := time.ParseDuration(ppc.RetryDelay); err != nil {
return fmt.Errorf("retry delay configuration is invalid: %w", err)
}

if _, err := time.ParseDuration(ppc.Timeout); err != nil {
return fmt.Errorf("timeout configuration is invalid: %w", err)
}

return nil
}

func (pp PollingProfile) HasID() bool {
return pp.ID.String() != ""
}

func (pp PollingProfile) GetID() id.ID {
return pp.ID
}

func (pp PollingProfile) Validate() error {
if pp.Strategy == Periodic {
if err := pp.Periodic.Validate(); err != nil {
return err
}
}

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,103 +6,10 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"time"

"github.com/kubeshop/tracetest/server/pkg/id"
"github.com/kubeshop/tracetest/server/resourcemanager"
)

type Strategy string

const (
Periodic Strategy = "periodic"
)

const (
ResourceName = "PollingProfile"
ResourceNamePlural = "PollingProfiles"
)

var Operations = []resourcemanager.Operation{
resourcemanager.OperationGet,
resourcemanager.OperationList,
resourcemanager.OperationUpdate,
}

var DefaultPollingProfile = PollingProfile{
ID: id.ID("current"),
Name: "default",
Default: true,
Strategy: Periodic,
Periodic: &PeriodicPollingConfig{
Timeout: "1m",
RetryDelay: "5s",
},
}

type PollingProfile struct {
ID id.ID `json:"id"`
Name string `json:"name"`
Default bool `json:"default"`
Strategy Strategy `json:"strategy"`
Periodic *PeriodicPollingConfig `json:"periodic"`
}

type PeriodicPollingConfig struct {
RetryDelay string `json:"retryDelay"`
Timeout string `json:"timeout"`
SelectorMatchRetries int `json:"selectorMatchRetries"`
}

func (ppc *PeriodicPollingConfig) TimeoutDuration() time.Duration {
d, _ := time.ParseDuration(ppc.Timeout)
return d
}

func (ppc *PeriodicPollingConfig) RetryDelayDuration() time.Duration {
d, _ := time.ParseDuration(ppc.RetryDelay)
return d
}

func (ppc *PeriodicPollingConfig) MaxTracePollRetry() int {
return int(math.Ceil(float64(ppc.TimeoutDuration()) / float64(ppc.RetryDelayDuration())))
}

func (ppc *PeriodicPollingConfig) Validate() error {
if ppc == nil {
return fmt.Errorf("missing periodic polling profile configuration")
}

if _, err := time.ParseDuration(ppc.RetryDelay); err != nil {
return fmt.Errorf("retry delay configuration is invalid: %w", err)
}

if _, err := time.ParseDuration(ppc.Timeout); err != nil {
return fmt.Errorf("timeout configuration is invalid: %w", err)
}

return nil
}

func (pp PollingProfile) HasID() bool {
return pp.ID.String() != ""
}

func (pp PollingProfile) GetID() id.ID {
return pp.ID
}

func (pp PollingProfile) Validate() error {
if pp.Strategy == Periodic {
if err := pp.Periodic.Validate(); err != nil {
return err
}
}

return nil
}

func NewRepository(db *sql.DB) *Repository {
return &Repository{db}
}
Expand Down