Skip to content

Commit

Permalink
Fixed CR
Browse files Browse the repository at this point in the history
Added resource set validation cloudquery#7

Added TableValidation to enforce column/table name longer than 63 char cloudquery#9
  • Loading branch information
zagronitay committed May 4, 2021
1 parent 7ca9ac8 commit f8f2df7
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 99 deletions.
46 changes: 2 additions & 44 deletions provider/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package provider

import (
"context"
"errors"
"fmt"
"reflect"
"runtime"
"strconv"
Expand All @@ -22,26 +20,16 @@ const queryTableColumns = `SELECT array_agg(column_name::text) as columns FROM i

const addColumnToTable = `ALTER TABLE %s ADD COLUMN IF NOT EXISTS %v %v;`

const maxTableName = 63

const maxColumnName = 63

// Migrator handles creation of schema.Table in database if they don't exist
type Migrator struct {
db schema.Database
log hclog.Logger
validators []TableValidator
db schema.Database
log hclog.Logger
}

func NewMigrator(db schema.Database, log hclog.Logger) Migrator {
return Migrator{
db,
log,
[]TableValidator{
LengthTableValidator{
log: log,
},
},
}
}

Expand Down Expand Up @@ -124,33 +112,3 @@ func (m Migrator) buildColumns(ctb *sqlbuilder.CreateTableBuilder, cc []schema.C
ctb.Define(defs...)
}
}

func (m Migrator) ValidateTable(t *schema.Table) error {
for _, validator := range m.validators {
return validator.Validate(t)
}
return nil
}

type TableValidator interface {
Validate(t *schema.Table) error
}

type LengthTableValidator struct {
log hclog.Logger
}

func (tv LengthTableValidator) Validate(t *schema.Table) error {
if len(t.Name) > maxTableName {
tv.log.Error("table name has exceeded max length", "table", t.Name)
return errors.New("table name has exceeded max length")
}

for _, col := range t.ColumnNames() {
if len(col) > maxColumnName {
tv.log.Error("column name has exceeded max length", "column", col)
return errors.New(fmt.Sprintf("column name %s has exceeded max length", col))
}
}
return nil
}
51 changes: 0 additions & 51 deletions provider/migrator_test.go

This file was deleted.

2 changes: 1 addition & 1 deletion provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (p *Provider) Init(_ string, dsn string, _ bool) error {
for _, t := range p.ResourceMap {

// validate table
validationErr := m.ValidateTable(t)
validationErr := schema.ValidateTable(t)
if validationErr != nil {
p.Logger.Error("table validation failed", "table", t.Name, "error", err)
return err
Expand Down
16 changes: 16 additions & 0 deletions provider/schema/resolvers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ func TestPathResolver(t *testing.T) {
resource := &Resource{
Item: testStruct{Inner: innerStruct{Value: "bla"}, Value: 5, unexported: false},
data: map[string]interface{}{},
table: &Table{
Columns: []Column{
{
Name: "test",
Type: TypeString,
},
{
Name: "int_value",
Type: TypeInt,
},
{
Name: "unexported",
Type: TypeBool,
},
},
},
}
err := r1(context.TODO(), nil, resource, Column{Name: "test"})

Expand Down
6 changes: 4 additions & 2 deletions provider/schema/resource.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package schema

import (
"errors"
"fmt"
"github.com/cloudquery/go-funk"
"github.com/google/uuid"
Expand Down Expand Up @@ -33,12 +34,13 @@ func (r Resource) Get(key string) interface{} {
return r.data[key]
}

func (r Resource) Set(key string, value interface{}) {
func (r Resource) Set(key string, value interface{}) error {
columnExists := funk.ContainsString(r.table.ColumnNames(), key)
if !columnExists {
panic(fmt.Sprintf("column %s does not exits", key))
return errors.New(fmt.Sprintf("column %s does not exits", key))
}
r.data[key] = value
return nil
}

func (r Resource) Id() uuid.UUID {
Expand Down
3 changes: 2 additions & 1 deletion provider/schema/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ func TestResourceColumns(t *testing.T) {
assert.Equal(t, v, []interface{}{r.id, "test", "name_no_prefix", "prefix_name"})

// check non existing col
assert.Panics(t, func() { r.Set("non_exist_col", "test") })
err = r.Set("non_exist_col", "test")
assert.Error(t, err)
}

func TestResourceResolveColumns(t *testing.T) {
Expand Down
54 changes: 54 additions & 0 deletions provider/schema/validators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package schema

import (
"errors"
"fmt"
)

const maxTableName = 63

const maxColumnName = 63

var defaultValidators = []TableValidator{
LengthTableValidator{},
}

func ValidateTable(t *Table) error {
for _, validator := range defaultValidators {
return validator.Validate(t)
}
return nil
}

type TableValidator interface {
Validate(t *Table) error
}

type LengthTableValidator struct{}

func validateTableAttributesNameLength(t *Table) error {
// validate table name
if len(t.Name) > maxTableName {
return errors.New("table name has exceeded max length")
}

// validate table columns
for _, col := range t.ColumnNames() {
if len(col) > maxColumnName {
return errors.New(fmt.Sprintf("column name %s has exceeded max length", col))
}
}

// validate table relations
for _, rel := range t.Relations {
err := validateTableAttributesNameLength(rel)
if err != nil {
return err
}
}
return nil
}

func (tv LengthTableValidator) Validate(t *Table) error {
return validateTableAttributesNameLength(t)
}
42 changes: 42 additions & 0 deletions provider/schema/validators_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package schema

import (
"github.com/stretchr/testify/assert"
"testing"
)

var testTableValidators = Table{
Name: "test_table_validator",
Columns: []Column{
{
Name: "zero_bool",
Type: TypeBool,
},
{
Name: "zero_int",
Type: TypeBigInt,
},
{
Name: "not_zero_bool",
Type: TypeBool,
},
},
}

func TestTableValidators(t *testing.T) {
// table has passed all validators
err := ValidateTable(&testTableValidators)
assert.Nil(t, err)

// table name is too long
tableWithLongName := testTableValidators
tableWithLongName.Name = "WithLongNametableWithLongNametableWithLongNametableWithLongNamet"
err = ValidateTable(&tableWithLongName)
assert.Error(t, err)

// column name is too long
tableWithLongColumnName := testTableValidators
tableWithLongName.Columns[0].Name = "tableWithLongColumnNametableWithLongColumnNametableWithLongColumnName"
err = ValidateTable(&tableWithLongColumnName)
assert.Error(t, err)
}

0 comments on commit f8f2df7

Please sign in to comment.