forked from sonic-net/sonic-mgmt-framework
/
common.go
149 lines (132 loc) · 6.59 KB
/
common.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
139
140
141
142
143
144
145
146
147
148
////////////////////////////////////////////////////////////////////////////////
// //
// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or //
// its subsidiaries. //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// //
////////////////////////////////////////////////////////////////////////////////
package custom_validation
import (
"reflect"
"github.com/antchfx/xmlquery"
"github.com/go-redis/redis"
. "cvl/internal/util"
"cvl/internal/yparser"
)
type CustomValidation struct {}
type CVLValidateType uint
const (
VALIDATE_NONE CVLValidateType = iota //Data is used as dependent data
VALIDATE_SYNTAX //Syntax is checked and data is used as dependent data
VALIDATE_SEMANTICS //Semantics is checked
VALIDATE_ALL //Syntax and Semantics are checked
)
type CVLOperation uint
const (
OP_NONE CVLOperation = 0 //Used to just validate the config without any operation
OP_CREATE = 1 << 0//For Create operation
OP_UPDATE = 1 << 1//For Update operation
OP_DELETE = 1 << 2//For Delete operation
)
//Error code
type CVLRetCode int
const (
CVL_SUCCESS CVLRetCode = iota
CVL_ERROR
CVL_NOT_IMPLEMENTED
CVL_INTERNAL_UNKNOWN
CVL_FAILURE
CVL_SYNTAX_ERROR = CVLRetCode(yparser.YP_SYNTAX_ERROR)
CVL_SEMANTIC_ERROR = CVLRetCode(yparser.YP_SEMANTIC_ERROR)
CVL_SYNTAX_MISSING_FIELD = CVLRetCode(yparser.YP_SYNTAX_MISSING_FIELD)
CVL_SYNTAX_INVALID_FIELD = CVLRetCode(yparser.YP_SYNTAX_INVALID_FIELD) /* Invalid Field */
CVL_SYNTAX_INVALID_INPUT_DATA = CVLRetCode(yparser.YP_SYNTAX_INVALID_INPUT_DATA) /*Invalid Input Data */
CVL_SYNTAX_MULTIPLE_INSTANCE = CVLRetCode(yparser.YP_SYNTAX_MULTIPLE_INSTANCE) /* Multiple Field Instances */
CVL_SYNTAX_DUPLICATE = CVLRetCode(yparser.YP_SYNTAX_DUPLICATE) /* Duplicate Fields */
CVL_SYNTAX_ENUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_ENUM_INVALID) /* Invalid enum value */
CVL_SYNTAX_ENUM_INVALID_NAME = CVLRetCode(yparser.YP_SYNTAX_ENUM_INVALID_NAME) /* Invalid enum name */
CVL_SYNTAX_ENUM_WHITESPACE = CVLRetCode(yparser.YP_SYNTAX_ENUM_WHITESPACE) /* Enum name with leading/trailing whitespaces */
CVL_SYNTAX_OUT_OF_RANGE = CVLRetCode(yparser.YP_SYNTAX_OUT_OF_RANGE) /* Value out of range/length/pattern (data) */
CVL_SYNTAX_MINIMUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_MINIMUM_INVALID) /* min-elements constraint not honored */
CVL_SYNTAX_MAXIMUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_MAXIMUM_INVALID) /* max-elements constraint not honored */
CVL_SEMANTIC_DEPENDENT_DATA_MISSING = CVLRetCode(yparser.YP_SEMANTIC_DEPENDENT_DATA_MISSING) /* Dependent Data is missing */
CVL_SEMANTIC_MANDATORY_DATA_MISSING = CVLRetCode(yparser.YP_SEMANTIC_MANDATORY_DATA_MISSING) /* Mandatory Data is missing */
CVL_SEMANTIC_KEY_ALREADY_EXIST = CVLRetCode(yparser.YP_SEMANTIC_KEY_ALREADY_EXIST) /* Key already existing. */
CVL_SEMANTIC_KEY_NOT_EXIST = CVLRetCode(yparser.YP_SEMANTIC_KEY_NOT_EXIST) /* Key is missing. */
CVL_SEMANTIC_KEY_DUPLICATE = CVLRetCode(yparser.YP_SEMANTIC_KEY_DUPLICATE) /* Duplicate key. */
CVL_SEMANTIC_KEY_INVALID = CVLRetCode(yparser.YP_SEMANTIC_KEY_INVALID)
)
//Strcture for key and data in API
type CVLEditConfigData struct {
VType CVLValidateType //Validation type
VOp CVLOperation //Operation type
Key string //Key format : "PORT|Ethernet4"
Data map[string]string //Value : {"alias": "40GE0/28", "mtu" : 9100, "admin_status": down}
}
/* CVL Error Structure. */
type CVLErrorInfo struct {
TableName string /* Table having error */
ErrCode CVLRetCode /* CVL Error return Code. */
CVLErrDetails string /* CVL Error Message details. */
Keys []string /* Keys of the Table having error. */
Value string /* Field Value throwing error */
Field string /* Field Name throwing error . */
Msg string /* Detailed error message. */
ConstraintErrMsg string /* Constraint error message. */
ErrAppTag string
}
type CustValidationCache struct {
Data interface{}
}
//Custom validation context passed to custom validation function
type CustValidationCtxt struct {
ReqData []CVLEditConfigData //All request data
CurCfg *CVLEditConfigData //Current request data for which validation should be done
YNodeName string //YANG node name
YNodeVal string //YANG node value, leaf-list will have "," separated value
YCur *xmlquery.Node //YANG data tree
SessCache *CustValidationCache //Session cache, can be used for storing data, persistent in session
RClient *redis.Client //Redis client
}
func getAppDbClient() *redis.Client {
rclient := redis.NewClient(&redis.Options{
Network: "tcp",
Addr: "localhost:6379",
Password: "", // no password set
DB: 0,
DialTimeout: 0,
})
_, err := rclient.Ping().Result()
if err != nil {
CVL_LEVEL_LOG(TRACE_SEMANTIC, "Failed to connect to Redis server = %v", err)
return nil
}
return rclient
}
//Common function to invoke custom validation
//TBD should we do this using GO plugin feature ?
func InvokeCustomValidation(cv *CustomValidation, name string, args... interface{}) CVLErrorInfo {
inputs := make([]reflect.Value, len(args))
for i, _ := range args {
inputs[i] = reflect.ValueOf(args[i])
}
f := reflect.ValueOf(cv).MethodByName(name)
if (f.IsNil() == false) {
v := f.Call(inputs)
TRACE_LEVEL_LOG(TRACE_SEMANTIC,
"InvokeCustomValidation: %s(), return value = %v", v[0])
return (v[0].Interface()).(CVLErrorInfo)
}
return CVLErrorInfo{ErrCode: CVL_SUCCESS}
}