forked from ovn-org/libovsdb
-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathnative.go
138 lines (123 loc) · 4.25 KB
/
native.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package libovsdb
import (
"fmt"
)
// ErrNoTable describes a error in the provided table information
type ErrNoTable struct {
table string
}
func (e *ErrNoTable) Error() string {
return fmt.Sprintf("Table not found: %s", e.table)
}
// NewErrNoTable creates a new ErrNoTable
func NewErrNoTable(table string) error {
return &ErrNoTable{
table: table,
}
}
// NativeAPI is an API that offers functions to interact with libovsdb without
// having to handle it's internal objects. It uses a DatabaseSchema to infer the
// type of each value and make translations.
// OvsMaps are translated to go maps with specific key and values. I.e instead of
// having to deal with map[interface{}][interface{}], the user will be able to
// user map[string] string (or whatever native type can hold the column value)
// OvsSets will be translated to slices
//
// OvsUUID are translated to and from strings
// If the column type is an enum, the native type associated with the underlying enum
// type is used (e.g: string or int)
// Also, type checkings are done. E.g: if you try to put an integer in a column that has
// type string, the API will refuse to create the Ovs object for you
type NativeAPI struct {
schema *DatabaseSchema
}
// NewNativeAPI returns a NativeAPI
func NewNativeAPI(schema *DatabaseSchema) NativeAPI {
return NativeAPI{
schema: schema,
}
}
// GetRowData transforms a Row to a native type data map[string] interface{}
func (na NativeAPI) GetRowData(tableName string, row *Row) (map[string]interface{}, error) {
if row == nil {
return nil, nil
}
return na.GetData(tableName, row.Fields)
}
// GetData transforms a map[string]interface{} containing OvS types (e.g: a ResultRow
// has this format) to native.
// The result object must be given as pointer to map[string] interface{}
func (na NativeAPI) GetData(tableName string, ovsData map[string]interface{}) (map[string]interface{}, error) {
table, ok := na.schema.Tables[tableName]
if !ok {
return nil, NewErrNoTable(tableName)
}
nativeRow := make(map[string]interface{}, len(table.Columns))
for name, column := range table.Columns {
ovsElem, ok := ovsData[name]
if !ok {
// Ignore missing columns
continue
}
nativeElem, err := OvsToNative(column, ovsElem)
if err != nil {
return nil, fmt.Errorf("Table %s, Column %s: Failed to extract native element: %s", tableName, name, err.Error())
}
nativeRow[name] = nativeElem
}
return nativeRow, nil
}
// NewRow creates a libovsdb Row from the input data
// data shall not contain libovsdb-specific types (except UUID)
func (na NativeAPI) NewRow(tableName string, data interface{}) (map[string]interface{}, error) {
table, ok := na.schema.Tables[tableName]
if !ok {
return nil, NewErrNoTable(tableName)
}
nativeRow, ok := data.(map[string]interface{})
if !ok {
return nil, NewErrWrongType("NativeAPI.NewRow", "map[string]interface{}", data)
}
ovsRow := make(map[string]interface{}, len(table.Columns))
for name, column := range table.Columns {
nativeElem, ok := nativeRow[name]
if !ok {
// Ignore missing columns
continue
}
ovsElem, err := NativeToOvs(column, nativeElem)
if err != nil {
return nil, fmt.Errorf("Table %s, Column %s: Failed to generate OvS element. %s", tableName, name, err.Error())
}
ovsRow[name] = ovsElem
}
return ovsRow, nil
}
// NewCondition returns a valid condition to be used inside a Operation
// It accepts native golang types (sets and maps)
// TODO: check condition validity
func (na NativeAPI) NewCondition(tableName, columnName, function string, value interface{}) ([]interface{}, error) {
column, err := na.schema.GetColumn(tableName, columnName)
if err != nil {
return nil, err
}
ovsVal, err := NativeToOvs(column, value)
if err != nil {
return nil, err
}
return []interface{}{columnName, function, ovsVal}, nil
}
// NewMutation returns a valid mutation to be used inside a Operation
// It accepts native golang types (sets and maps)
// TODO: check mutator validity
func (na NativeAPI) NewMutation(tableName, columnName, mutator string, value interface{}) ([]interface{}, error) {
column, err := na.schema.GetColumn(tableName, columnName)
if err != nil {
return nil, err
}
ovsVal, err := NativeToOvs(column, value)
if err != nil {
return nil, err
}
return []interface{}{columnName, mutator, ovsVal}, nil
}