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

add enum support for modelgen #147

Merged
merged 1 commit into from
Jun 10, 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
83 changes: 78 additions & 5 deletions modelgen/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,23 @@ const BASE_TABLE_TEMPLATE = `{{ template "header" . }}

package {{ index . "PackageName" }}

{{ if index . "Enums" }}
type (
{{ range index . "Enums" }}
{{ .Alias }} = {{ .Type }}
{{- end }}
)

const (
{{ range index . "Enums" }}
{{- $e := . }}
{{- range .Sets }}
{{ $e.Alias }}{{ camelCase . }} {{ $e.Alias }} = {{ printVal . $e.Type }}
{{- end }}
{{- end }}
)
{{ end }}

{{ template "preStructDefinitions" }}
{{ template "structComment" . }}
type {{ index . "StructName" }} struct {
Expand Down Expand Up @@ -53,6 +70,13 @@ const DEFAULT_EXTRA_FIELDS_TEMPLATE = `{{ define "extraFields" }}{{ end }}`
// DEFAULT_POST_TABLE_TEMPLATE is the default template for "postStructDefinitions"
const DEFAULT_POST_TABLE_TEMPLATE = `{{ define "postStructDefinitions" }}{{ end }}`

// Enum represents the enum schema type
type Enum struct {
Type string
Alias string
Sets []interface{}
}

// Field represents the field information
type Field struct {
Column string
Expand All @@ -72,6 +96,7 @@ func GetTableTemplateData(pkg, name string, table *ovsdb.TableSchema) map[string
data["PackageName"] = pkg
data["StructName"] = StructName(name)
Fields := []Field{}
Enums := []Enum{}

// First, add UUID
Fields = append(Fields,
Expand All @@ -95,18 +120,26 @@ func GetTableTemplateData(pkg, name string, table *ovsdb.TableSchema) map[string
Fields = append(Fields, Field{
Column: columnName,
Name: FieldName(columnName),
Type: FieldType(columnSchema),
Type: FieldType(name, columnName, columnSchema),
Tag: Tag(columnName),
})
if enum := FieldEnum(name, columnName, columnSchema); enum != nil {
Enums = append(Enums, *enum)
}
}
data["Fields"] = Fields
data["Enums"] = Enums
return data
}

// NewTableTemplate returns a new TableTemplate and the TableTemplate data map
// See BASE_TABLE_TEMPLATE to a detailed explanation of the possible ways this template can be expanded
func NewTableTemplate(pkg string, name string, table *ovsdb.TableSchema) (*template.Template, map[string]interface{}) {
main, err := template.New(name).Parse(BASE_TABLE_TEMPLATE)
funcMap := template.FuncMap{
"printVal": printVal,
"camelCase": camelCase,
}
main, err := template.New(name).Funcs(funcMap).Parse(BASE_TABLE_TEMPLATE)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -144,24 +177,44 @@ func FieldName(column string) string {

// StructName returns the name of the table struct
func StructName(tableName string) string {
return strings.ReplaceAll(tableName, "_", "")
return strings.Title(strings.ReplaceAll(tableName, "_", ""))
amorenoz marked this conversation as resolved.
Show resolved Hide resolved
}

// EnumName returns the name of the enum field
func EnumName(tableName, columnName string) string {
return strings.Title(StructName(tableName)) + camelCase(columnName)
}

// FieldType returns the string representation of a column type
func FieldType(column *ovsdb.ColumnSchema) string {
func FieldType(tableName, columnName string, column *ovsdb.ColumnSchema) string {
switch column.Type {
case ovsdb.TypeEnum:
return AtomicType(column.TypeObj.Key.Type)
return EnumName(tableName, columnName)
case ovsdb.TypeMap:
return fmt.Sprintf("map[%s]%s", AtomicType(column.TypeObj.Key.Type),
AtomicType(column.TypeObj.Value.Type))
case ovsdb.TypeSet:
if FieldEnum(tableName, columnName, column) != nil {
return fmt.Sprintf("[]%s", EnumName(tableName, columnName))
}
return fmt.Sprintf("[]%s", AtomicType(column.TypeObj.Key.Type))
default:
return AtomicType(column.Type)
}
}

// FieldEnum returns the Enum if the column is an enum type
func FieldEnum(tableName, columnName string, column *ovsdb.ColumnSchema) *Enum {
amorenoz marked this conversation as resolved.
Show resolved Hide resolved
if column.TypeObj.Key.Enum == nil {
return nil
}
return &Enum{
Type: column.TypeObj.Key.Type,
Alias: EnumName(tableName, columnName),
Sets: column.TypeObj.Key.Enum,
}
}

// BasicType returns the string type of an AtomicType
func AtomicType(atype string) string {
switch atype {
Expand Down Expand Up @@ -211,9 +264,15 @@ var initialisms = map[string]bool{
"SSL": true,
"STP": true,
"TCP": true,
"SCTP": true,
"UDP": true,
"UUID": true,
"VLAN": true,
"STT": true,
"DNAT": true,
"SNAT": true,
"ICMP": true,
"SLB": true,
}

func camelCase(field string) string {
Expand Down Expand Up @@ -246,3 +305,17 @@ func expandInitilaisms(s string) string {
}
return s
}

func printVal(v interface{}, t string) string {
switch t {
case "int":
return fmt.Sprintf(`%d`, v)
case "float64":
return fmt.Sprintf(`%f`, v)
case "bool":
return fmt.Sprintf(`%t`, v)
case "string":
return fmt.Sprintf(`"%s"`, v)
}
return ""
}
105 changes: 78 additions & 27 deletions modelgen/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ func TestNewTableTemplate(t *testing.T) {
},
"float": {
"type": "real"
}
},
"protocol": {
"type": {"key": {"type": "string",
"enum": ["set", ["tcp", "udp", "sctp"]]},
"min": 0, "max": 1}},
"event_type": {"type": {"key": {"type": "string",
"enum": ["set", ["empty_lb_backends"]]}}}
}
}
}
Expand All @@ -46,12 +52,26 @@ func TestNewTableTemplate(t *testing.T) {

package test

// test defines an object in test table
type test struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
type (
AtomicTableEventType = string
AtomicTableProtocol = string
)

const (
AtomicTableEventTypeEmptyLbBackends AtomicTableEventType = "empty_lb_backends"
AtomicTableProtocolTCP AtomicTableProtocol = "tcp"
AtomicTableProtocolUDP AtomicTableProtocol = "udp"
AtomicTableProtocolSCTP AtomicTableProtocol = "sctp"
)

// AtomicTable defines an object in atomicTable table
type AtomicTable struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
EventType AtomicTableEventType ` + "`" + `ovs:"event_type"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Protocol []AtomicTableProtocol ` + "`" + `ovs:"protocol"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
}
`,
},
Expand All @@ -70,17 +90,33 @@ type test struct {

package test

// test defines an object in test table
type test struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `

OtherUUID string
OtherFloat float64
OtherInt int
OtherStr string
type (
AtomicTableEventType = string
AtomicTableProtocol = string
)

const (
AtomicTableEventTypeEmptyLbBackends AtomicTableEventType = "empty_lb_backends"
AtomicTableProtocolTCP AtomicTableProtocol = "tcp"
AtomicTableProtocolUDP AtomicTableProtocol = "udp"
AtomicTableProtocolSCTP AtomicTableProtocol = "sctp"
)

// AtomicTable defines an object in atomicTable table
type AtomicTable struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
EventType AtomicTableEventType ` + "`" + `ovs:"event_type"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Protocol []AtomicTableProtocol ` + "`" + `ovs:"protocol"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `

OtherUUID string
OtherEventType AtomicTableEventType
OtherFloat float64
OtherInt int
OtherProtocol []AtomicTableProtocol
OtherStr string
}
`,
},
Expand All @@ -103,16 +139,30 @@ func {{ index . "TestName" }} () string {

package test

// test defines an object in test table
type test struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
type (
AtomicTableEventType = string
AtomicTableProtocol = string
)

const (
AtomicTableEventTypeEmptyLbBackends AtomicTableEventType = "empty_lb_backends"
AtomicTableProtocolTCP AtomicTableProtocol = "tcp"
AtomicTableProtocolUDP AtomicTableProtocol = "udp"
AtomicTableProtocolSCTP AtomicTableProtocol = "sctp"
)

// AtomicTable defines an object in atomicTable table
type AtomicTable struct {
UUID string ` + "`" + `ovs:"_uuid"` + "`" + `
EventType AtomicTableEventType ` + "`" + `ovs:"event_type"` + "`" + `
Float float64 ` + "`" + `ovs:"float"` + "`" + `
Int int ` + "`" + `ovs:"int"` + "`" + `
Protocol []AtomicTableProtocol ` + "`" + `ovs:"protocol"` + "`" + `
Str string ` + "`" + `ovs:"str"` + "`" + `
}

func TestFunc() string {
return "test"
return "AtomicTable"
}
`,
},
Expand Down Expand Up @@ -140,10 +190,11 @@ WRONG FORMAT

for _, tt := range test {
t.Run(fmt.Sprintf("Table Test: %s", tt.name), func(t *testing.T) {
table := schema.Tables["atomicTable"]
fakeTable := "atomicTable"
table := schema.Tables[fakeTable]
templ, data := NewTableTemplate(
"test",
"test",
fakeTable,
&table,
)
if tt.err {
Expand Down