package model import ( "encoding/json" "fmt" "reflect" "github.com/ovn-org/libovsdb/ovsdb" ) // A Model is the base interface used to build Database Models. It is used // to express how data from a specific Database Table shall be translated into structs // A Model is a struct with at least one (most likely more) field tagged with the 'ovs' tag // The value of 'ovs' field must be a valid column name in the OVS Database // A field associated with the "_uuid" column mandatory. The rest of the columns are optional // The struct may also have non-tagged fields (which will be ignored by the API calls) // The Model interface must be implemented by the pointer to such type // Example: //type MyLogicalRouter struct { // UUID string `ovsdb:"_uuid"` // Name string `ovsdb:"name"` // ExternalIDs map[string]string `ovsdb:"external_ids"` // LoadBalancers []string `ovsdb:"load_balancer"` //} type Model interface{} type CloneableModel interface { CloneModel() Model CloneModelInto(Model) } type ComparableModel interface { EqualsModel(Model) bool } // Clone creates a deep copy of a model func Clone(a Model) Model { if cloner, ok := a.(CloneableModel); ok { return cloner.CloneModel() } val := reflect.Indirect(reflect.ValueOf(a)) b := reflect.New(val.Type()).Interface() aBytes, _ := json.Marshal(a) _ = json.Unmarshal(aBytes, b) return b } // CloneInto deep copies a model into another one func CloneInto(src, dst Model) { if cloner, ok := src.(CloneableModel); ok { cloner.CloneModelInto(dst) return } aBytes, _ := json.Marshal(src) _ = json.Unmarshal(aBytes, dst) } func Equal(l, r Model) bool { if comparator, ok := l.(ComparableModel); ok { return comparator.EqualsModel(r) } return reflect.DeepEqual(l, r) } func modelSetUUID(model Model, uuid string) error { modelVal := reflect.ValueOf(model).Elem() for i := 0; i < modelVal.NumField(); i++ { if field := modelVal.Type().Field(i); field.Tag.Get("ovsdb") == "_uuid" && field.Type.Kind() == reflect.String { modelVal.Field(i).Set(reflect.ValueOf(uuid)) return nil } } return fmt.Errorf("model is expected to have a string field mapped to column _uuid") } // Condition is a model-based representation of an OVSDB Condition type Condition struct { // Pointer to the field of the model where the operation applies Field interface{} // Condition function Function ovsdb.ConditionFunction // Value to use in the condition Value interface{} } // Mutation is a model-based representation of an OVSDB Mutation type Mutation struct { // Pointer to the field of the model that shall be mutated Field interface{} // String representing the mutator (as per RFC7047) Mutator ovsdb.Mutator // Value to use in the mutation Value interface{} }