github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/cloudlets/v3/match_rule.go (about) 1 package v3 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 8 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr" 9 10 validation "github.com/go-ozzo/ozzo-validation/v4" 11 ) 12 13 type ( 14 // MatchRule is base interface for MatchRuleXX 15 MatchRule interface { 16 // cloudletType is a private method to ensure that only match rules for supported cloudlets can be used 17 cloudletType() string 18 Validate() error 19 } 20 21 // MatchRules is an array of *MatchRuleXX depending on the cloudletId (9 or 0) of the policy 22 MatchRules []MatchRule 23 24 // MatchRuleAP represents an API Prioritization (AP) match rule resource for create or update 25 MatchRuleAP struct { 26 Name string `json:"name,omitempty"` 27 Type MatchRuleType `json:"type,omitempty"` 28 Start int64 `json:"start,omitempty"` 29 End int64 `json:"end,omitempty"` 30 ID int64 `json:"id,omitempty"` 31 Matches []MatchCriteriaAP `json:"matches,omitempty"` 32 MatchURL string `json:"matchURL,omitempty"` 33 PassThroughPercent *float64 `json:"passThroughPercent"` 34 Disabled bool `json:"disabled,omitempty"` 35 } 36 37 // MatchRuleAS represents an Application Segmentation (AS) match rule resource for create or update resource 38 MatchRuleAS struct { 39 Name string `json:"name,omitempty"` 40 Type MatchRuleType `json:"type,omitempty"` 41 Start int64 `json:"start,omitempty"` 42 End int64 `json:"end,omitempty"` 43 ID int64 `json:"id,omitempty"` 44 Matches []MatchCriteriaAS `json:"matches,omitempty"` 45 MatchURL string `json:"matchURL,omitempty"` 46 ForwardSettings ForwardSettingsAS `json:"forwardSettings"` 47 Disabled bool `json:"disabled,omitempty"` 48 } 49 50 // ForwardSettingsAS represents forward settings for an Application Segmentation (AS) 51 ForwardSettingsAS struct { 52 PathAndQS string `json:"pathAndQS,omitempty"` 53 UseIncomingQueryString bool `json:"useIncomingQueryString,omitempty"` 54 OriginID string `json:"originId,omitempty"` 55 } 56 57 // MatchRulePR represents a Phased Release (PR aka CD) match rule resource for create or update resource 58 MatchRulePR struct { 59 Name string `json:"name,omitempty"` 60 Type MatchRuleType `json:"type,omitempty"` 61 Start int64 `json:"start,omitempty"` 62 End int64 `json:"end,omitempty"` 63 ID int64 `json:"id,omitempty"` 64 Matches []MatchCriteriaPR `json:"matches,omitempty"` 65 MatchURL string `json:"matchURL,omitempty"` 66 ForwardSettings ForwardSettingsPR `json:"forwardSettings"` 67 Disabled bool `json:"disabled,omitempty"` 68 MatchesAlways bool `json:"matchesAlways,omitempty"` 69 } 70 71 // ForwardSettingsPR represents forward settings for a Phased Release (PR aka CD) 72 ForwardSettingsPR struct { 73 OriginID string `json:"originId"` 74 Percent int `json:"percent"` 75 } 76 77 // MatchRuleER represents an Edge Redirector (ER) match rule resource for create or update resource 78 MatchRuleER struct { 79 Name string `json:"name,omitempty"` 80 Type MatchRuleType `json:"type,omitempty"` 81 Start int64 `json:"start,omitempty"` 82 End int64 `json:"end,omitempty"` 83 ID int64 `json:"id,omitempty"` 84 Matches []MatchCriteriaER `json:"matches,omitempty"` 85 MatchesAlways bool `json:"matchesAlways,omitempty"` 86 UseRelativeURL string `json:"useRelativeUrl,omitempty"` 87 StatusCode int `json:"statusCode"` 88 RedirectURL string `json:"redirectURL"` 89 MatchURL string `json:"matchURL,omitempty"` 90 UseIncomingQueryString bool `json:"useIncomingQueryString"` 91 UseIncomingSchemeAndHost bool `json:"useIncomingSchemeAndHost"` 92 Disabled bool `json:"disabled,omitempty"` 93 } 94 95 // MatchRuleFR represents a Forward Rewrite (FR) match rule resource for create or update resource 96 MatchRuleFR struct { 97 Name string `json:"name,omitempty"` 98 Type MatchRuleType `json:"type,omitempty"` 99 Start int64 `json:"start,omitempty"` 100 End int64 `json:"end,omitempty"` 101 ID int64 `json:"id,omitempty"` 102 Matches []MatchCriteriaFR `json:"matches,omitempty"` 103 MatchURL string `json:"matchURL,omitempty"` 104 ForwardSettings ForwardSettingsFR `json:"forwardSettings"` 105 Disabled bool `json:"disabled,omitempty"` 106 } 107 108 // ForwardSettingsFR represents forward settings for a Forward Rewrite (FR) 109 ForwardSettingsFR struct { 110 PathAndQS string `json:"pathAndQS,omitempty"` 111 UseIncomingQueryString bool `json:"useIncomingQueryString,omitempty"` 112 OriginID string `json:"originId,omitempty"` 113 } 114 115 // MatchRuleRC represents a Request Control (RC aka IG) match rule resource for create or update resource 116 MatchRuleRC struct { 117 Name string `json:"name,omitempty"` 118 Type MatchRuleType `json:"type,omitempty"` 119 Start int64 `json:"start,omitempty"` 120 End int64 `json:"end,omitempty"` 121 ID int64 `json:"id,omitempty"` 122 Matches []MatchCriteriaRC `json:"matches,omitempty"` 123 MatchesAlways bool `json:"matchesAlways,omitempty"` 124 AllowDeny AllowDeny `json:"allowDeny"` 125 Disabled bool `json:"disabled,omitempty"` 126 } 127 128 // MatchCriteria represents a match criteria resource for match rule for cloudlet 129 MatchCriteria struct { 130 MatchType string `json:"matchType,omitempty"` 131 MatchValue string `json:"matchValue,omitempty"` 132 MatchOperator MatchOperator `json:"matchOperator,omitempty"` 133 CaseSensitive bool `json:"caseSensitive"` 134 Negate bool `json:"negate"` 135 CheckIPs CheckIPs `json:"checkIPs,omitempty"` 136 ObjectMatchValue interface{} `json:"objectMatchValue,omitempty"` 137 } 138 139 // MatchCriteriaAP represents a match criteria resource for match rule for cloudlet API Prioritization (AP) 140 // ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple 141 MatchCriteriaAP MatchCriteria 142 143 // MatchCriteriaAS represents a match criteria resource for match rule for cloudlet Application Segmentation (AS) 144 // ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple or ObjectMatchValueRange 145 MatchCriteriaAS MatchCriteria 146 147 // MatchCriteriaPR represents a match criteria resource for match rule for cloudlet Phased Release (PR aka CD) 148 // ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple 149 MatchCriteriaPR MatchCriteria 150 151 // MatchCriteriaER represents a match criteria resource for match rule for cloudlet Edge Redirector (ER) 152 // ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple 153 MatchCriteriaER MatchCriteria 154 155 // MatchCriteriaFR represents a match criteria resource for match rule for cloudlet Forward Rewrite (FR) 156 // ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple 157 MatchCriteriaFR MatchCriteria 158 159 // MatchCriteriaRC represents a match criteria resource for match rule for cloudlet Request Control (RC aka IG) 160 // ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple 161 MatchCriteriaRC MatchCriteria 162 163 // ObjectMatchValueObject represents an object match value resource for match criteria of type object 164 ObjectMatchValueObject struct { 165 Name string `json:"name"` 166 Type ObjectMatchValueObjectType `json:"type"` 167 NameCaseSensitive bool `json:"nameCaseSensitive"` 168 NameHasWildcard bool `json:"nameHasWildcard"` 169 Options *Options `json:"options,omitempty"` 170 } 171 172 // ObjectMatchValueSimple represents an object match value resource for match criteria of type simple 173 ObjectMatchValueSimple struct { 174 Type ObjectMatchValueSimpleType `json:"type"` 175 Value []string `json:"value,omitempty"` 176 } 177 178 // ObjectMatchValueRange represents an object match value resource for match criteria of type range 179 ObjectMatchValueRange struct { 180 Type ObjectMatchValueRangeType `json:"type"` 181 Value []int64 `json:"value,omitempty"` 182 } 183 184 // Options represents an option resource for ObjectMatchValueObject 185 Options struct { 186 Value []string `json:"value,omitempty"` 187 ValueHasWildcard bool `json:"valueHasWildcard,omitempty"` 188 ValueCaseSensitive bool `json:"valueCaseSensitive,omitempty"` 189 ValueEscaped bool `json:"valueEscaped,omitempty"` 190 } 191 192 //MatchRuleType enum type 193 MatchRuleType string 194 // MatchRuleFormat enum type 195 MatchRuleFormat string 196 // MatchOperator enum type 197 MatchOperator string 198 // AllowDeny enum type 199 AllowDeny string 200 // CheckIPs enum type 201 CheckIPs string 202 // ObjectMatchValueRangeType enum type 203 ObjectMatchValueRangeType string 204 // ObjectMatchValueSimpleType enum type 205 ObjectMatchValueSimpleType string 206 // ObjectMatchValueObjectType enum type 207 ObjectMatchValueObjectType string 208 ) 209 210 const ( 211 // MatchRuleTypeAP represents rule type for API Prioritization (AP) cloudlets 212 MatchRuleTypeAP MatchRuleType = "apMatchRule" 213 // MatchRuleTypeAS represents rule type for Application Segmentation (AS) cloudlets 214 MatchRuleTypeAS MatchRuleType = "asMatchRule" 215 // MatchRuleTypePR represents rule type for Phased Release (PR aka CD) cloudlets 216 MatchRuleTypePR MatchRuleType = "cdMatchRule" 217 // MatchRuleTypeER represents rule type for Edge Redirector (ER) cloudlets 218 MatchRuleTypeER MatchRuleType = "erMatchRule" 219 // MatchRuleTypeFR represents rule type for Forward Rewrite (FR) cloudlets 220 MatchRuleTypeFR MatchRuleType = "frMatchRule" 221 // MatchRuleTypeRC represents rule type for Request Control (RC aka IG) cloudlets 222 MatchRuleTypeRC MatchRuleType = "igMatchRule" 223 // MatchRuleTypeVP represents rule type for Visitor Prioritization (VP) cloudlets 224 MatchRuleTypeVP MatchRuleType = "vpMatchRule" 225 ) 226 227 const ( 228 // MatchRuleFormat10 represents default match rule format 229 MatchRuleFormat10 MatchRuleFormat = "1.0" 230 ) 231 232 const ( 233 // MatchOperatorContains represents contains operator 234 MatchOperatorContains MatchOperator = "contains" 235 // MatchOperatorExists represents exists operator 236 MatchOperatorExists MatchOperator = "exists" 237 // MatchOperatorEquals represents equals operator 238 MatchOperatorEquals MatchOperator = "equals" 239 ) 240 241 const ( 242 // Allow represents allow option 243 Allow AllowDeny = "allow" 244 // Deny represents deny option 245 Deny AllowDeny = "deny" 246 // DenyBranded represents denybranded option 247 DenyBranded AllowDeny = "denybranded" 248 ) 249 250 const ( 251 // CheckIPsConnectingIP represents connecting ip option 252 CheckIPsConnectingIP CheckIPs = "CONNECTING_IP" 253 // CheckIPsXFFHeaders represents xff headers option 254 CheckIPsXFFHeaders CheckIPs = "XFF_HEADERS" 255 // CheckIPsConnectingIPXFFHeaders represents connecting ip + xff headers option 256 CheckIPsConnectingIPXFFHeaders CheckIPs = "CONNECTING_IP XFF_HEADERS" 257 ) 258 259 const ( 260 // Range represents range option 261 Range ObjectMatchValueRangeType = "range" 262 // Simple represents simple option 263 Simple ObjectMatchValueSimpleType = "simple" 264 // Object represents object option 265 Object ObjectMatchValueObjectType = "object" 266 ) 267 268 var ( 269 // ErrUnmarshallMatchCriteriaAP is returned when unmarshalling of MatchCriteriaAP fails 270 ErrUnmarshallMatchCriteriaAP = errors.New("unmarshalling MatchCriteriaAP") 271 // ErrUnmarshallMatchCriteriaAS is returned when unmarshalling of MatchCriteriaAS fails 272 ErrUnmarshallMatchCriteriaAS = errors.New("unmarshalling MatchCriteriaAS") 273 // ErrUnmarshallMatchCriteriaPR is returned when unmarshalling of MatchCriteriaPR fails 274 ErrUnmarshallMatchCriteriaPR = errors.New("unmarshalling MatchCriteriaPR") 275 // ErrUnmarshallMatchCriteriaER is returned when unmarshalling of MatchCriteriaER fails 276 ErrUnmarshallMatchCriteriaER = errors.New("unmarshalling MatchCriteriaER") 277 // ErrUnmarshallMatchCriteriaFR is returned when unmarshalling of MatchCriteriaFR fails 278 ErrUnmarshallMatchCriteriaFR = errors.New("unmarshalling MatchCriteriaFR") 279 // ErrUnmarshallMatchCriteriaRC is returned when unmarshalling of MatchCriteriaRC fails 280 ErrUnmarshallMatchCriteriaRC = errors.New("unmarshalling MatchCriteriaRC") 281 // ErrUnmarshallMatchCriteriaVP is returned when unmarshalling of MatchCriteriaVP fails 282 ErrUnmarshallMatchCriteriaVP = errors.New("unmarshalling MatchCriteriaVP") 283 // ErrUnmarshallMatchRules is returned when unmarshalling of MatchRules fails 284 ErrUnmarshallMatchRules = errors.New("unmarshalling MatchRules") 285 ) 286 287 // matchRuleHandlers contains mapping between name of the type for MatchRule and its implementation 288 // It makes the UnmarshalJSON more compact and easier to support more cloudlet types 289 var matchRuleHandlers = map[string]func() MatchRule{ 290 "apMatchRule": func() MatchRule { return &MatchRuleAP{} }, 291 "asMatchRule": func() MatchRule { return &MatchRuleAS{} }, 292 "cdMatchRule": func() MatchRule { return &MatchRulePR{} }, 293 "erMatchRule": func() MatchRule { return &MatchRuleER{} }, 294 "frMatchRule": func() MatchRule { return &MatchRuleFR{} }, 295 "igMatchRule": func() MatchRule { return &MatchRuleRC{} }, 296 } 297 298 // objectOrRangeOrSimpleMatchValueHandlers contains mapping between name of the type for ObjectMatchValue and its implementation 299 // It makes the UnmarshalJSON more compact and easier to support more types 300 var objectOrRangeOrSimpleMatchValueHandlers = map[string]func() interface{}{ 301 "object": func() interface{} { return &ObjectMatchValueObject{} }, 302 "range": func() interface{} { return &ObjectMatchValueRange{} }, 303 "simple": func() interface{} { return &ObjectMatchValueSimple{} }, 304 } 305 306 // simpleObjectMatchValueHandlers contains mapping between name of the types (simple or object) for ObjectMatchValue and their implementations 307 // It makes the UnmarshalJSON more compact and easier to support more types 308 var simpleObjectMatchValueHandlers = map[string]func() interface{}{ 309 "object": func() interface{} { return &ObjectMatchValueObject{} }, 310 "simple": func() interface{} { return &ObjectMatchValueSimple{} }, 311 } 312 313 // Validate validates MatchRules 314 func (m MatchRules) Validate() error { 315 type matchRules MatchRules 316 317 errs := validation.Errors{ 318 "MatchRules": validation.Validate(matchRules(m), validation.Length(0, 5000)), 319 } 320 return edgegriderr.ParseValidationErrors(errs) 321 } 322 323 // Validate validates MatchRuleAP 324 func (m MatchRuleAP) Validate() error { 325 return validation.Errors{ 326 "Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeAP).Error( 327 fmt.Sprintf("value '%s' is invalid. Must be: 'apMatchRule'", (&m).Type))), 328 "Name": validation.Validate(m.Name, validation.Length(0, 8192)), 329 "Start": validation.Validate(m.Start, validation.Min(0)), 330 "End": validation.Validate(m.End, validation.Min(0)), 331 "MatchURL": validation.Validate(m.MatchURL, validation.Length(0, 8192)), 332 "PassThroughPercent": validation.Validate(m.PassThroughPercent, validation.By(passThroughPercentValidation)), 333 "Matches": validation.Validate(m.Matches), 334 }.Filter() 335 } 336 337 // Validate validates MatchRuleAS 338 func (m MatchRuleAS) Validate() error { 339 return validation.Errors{ 340 "Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeAS).Error( 341 fmt.Sprintf("value '%s' is invalid. Must be: 'asMatchRule'", (&m).Type))), 342 "Name": validation.Validate(m.Name, validation.Length(0, 8192)), 343 "Start": validation.Validate(m.Start, validation.Min(0)), 344 "End": validation.Validate(m.End, validation.Min(0)), 345 "MatchURL": validation.Validate(m.MatchURL, validation.Length(0, 8192)), 346 "Matches": validation.Validate(m.Matches), 347 "ForwardSettings": validation.Validate(m.ForwardSettings, validation.Required), 348 "ForwardSettings.PathAndQS": validation.Validate(m.ForwardSettings.PathAndQS, validation.Length(1, 8192)), 349 "ForwardSettings.OriginID": validation.Validate(m.ForwardSettings.OriginID, validation.Length(0, 8192)), 350 }.Filter() 351 } 352 353 // Validate validates MatchRulePR 354 func (m MatchRulePR) Validate() error { 355 return validation.Errors{ 356 "Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypePR).Error( 357 fmt.Sprintf("value '%s' is invalid. Must be: 'cdMatchRule'", (&m).Type))), 358 "Name": validation.Validate(m.Name, validation.Length(0, 8192)), 359 "Start": validation.Validate(m.Start, validation.Min(0)), 360 "End": validation.Validate(m.End, validation.Min(0)), 361 "MatchURL": validation.Validate(m.MatchURL, validation.Length(0, 8192)), 362 "ForwardSettings": validation.Validate(m.ForwardSettings, validation.Required), 363 "ForwardSettings.OriginID": validation.Validate(m.ForwardSettings.OriginID, validation.Required, validation.Length(0, 8192)), 364 "ForwardSettings.Percent": validation.Validate(m.ForwardSettings.Percent, validation.Required, validation.Min(1), validation.Max(100)), 365 "Matches": validation.Validate(m.Matches), 366 "Matches/MatchesAlways": validation.Validate(len(m.Matches), validation.When(m.MatchesAlways, validation.Empty.Error("only one of [ \"Matches\", \"MatchesAlways\" ] can be specified"))), 367 }.Filter() 368 } 369 370 // Validate validates MatchRuleER 371 func (m MatchRuleER) Validate() error { 372 return validation.Errors{ 373 "Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeER).Error( 374 fmt.Sprintf("value '%s' is invalid. Must be: 'erMatchRule'", (&m).Type))), 375 "Name": validation.Validate(m.Name, validation.Length(0, 8192)), 376 "Start": validation.Validate(m.Start, validation.Min(0)), 377 "End": validation.Validate(m.End, validation.Min(0)), 378 "MatchURL": validation.Validate(m.MatchURL, validation.Length(0, 8192)), 379 "RedirectURL": validation.Validate(m.RedirectURL, validation.Required, validation.Length(1, 8192)), 380 "UseRelativeURL": validation.Validate(m.UseRelativeURL, validation.In("none", "copy_scheme_hostname", "relative_url").Error( 381 fmt.Sprintf("value '%s' is invalid. Must be one of: 'none', 'copy_scheme_hostname', 'relative_url' or '' (empty)", (&m).UseRelativeURL))), 382 "StatusCode": validation.Validate(m.StatusCode, validation.Required, validation.In(301, 302, 303, 307, 308).Error( 383 fmt.Sprintf("value '%d' is invalid. Must be one of: 301, 302, 303, 307 or 308", (&m).StatusCode))), 384 "Matches": validation.Validate(m.Matches), 385 "Matches/MatchesAlways": validation.Validate(len(m.Matches), validation.When(m.MatchesAlways, validation.Empty.Error("only one of [ \"Matches\", \"MatchesAlways\" ] can be specified"))), 386 }.Filter() 387 } 388 389 // Validate validates MatchRuleFR 390 func (m MatchRuleFR) Validate() error { 391 return validation.Errors{ 392 "Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeFR).Error( 393 fmt.Sprintf("value '%s' is invalid. Must be: 'frMatchRule'", (&m).Type))), 394 "Name": validation.Validate(m.Name, validation.Length(0, 8192)), 395 "Start": validation.Validate(m.Start, validation.Min(0)), 396 "End": validation.Validate(m.End, validation.Min(0)), 397 "MatchURL": validation.Validate(m.MatchURL, validation.Length(0, 8192)), 398 "Matches": validation.Validate(m.Matches), 399 "ForwardSettings": validation.Validate(m.ForwardSettings, validation.Required), 400 "ForwardSettings.PathAndQS": validation.Validate(m.ForwardSettings.PathAndQS, validation.Length(1, 8192)), 401 "ForwardSettings.OriginID": validation.Validate(m.ForwardSettings.OriginID, validation.Length(0, 8192)), 402 }.Filter() 403 } 404 405 // Validate validates MatchRuleRC 406 func (m MatchRuleRC) Validate() error { 407 return validation.Errors{ 408 "Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeRC).Error( 409 fmt.Sprintf("value '%s' is invalid. Must be: 'igMatchRule'", (&m).Type))), 410 "Name": validation.Validate(m.Name, validation.Length(0, 8192)), 411 "Start": validation.Validate(m.Start, validation.Min(0)), 412 "End": validation.Validate(m.End, validation.Min(0)), 413 "Matches": validation.Validate(m.Matches), 414 "Matches/MatchesAlways": validation.Validate(len(m.Matches), validation.When(m.MatchesAlways, validation.Empty.Error("only one of [ \"Matches\", \"MatchesAlways\" ] can be specified"))), 415 "AllowDeny": validation.Validate(m.AllowDeny, validation.Required, validation.In(Allow, Deny, DenyBranded).Error( 416 fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s' or '%s'", (&m).AllowDeny, Allow, Deny, DenyBranded), 417 )), 418 }.Filter() 419 } 420 421 // Validate validates MatchCriteriaAP 422 func (m MatchCriteriaAP) Validate() error { 423 return validation.Errors{ 424 "MatchType": validation.Validate(m.MatchType, validation.In( 425 "header", "hostname", "path", "extension", "query", "cookie", "deviceCharacteristics", "clientip", 426 "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error( 427 fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'cookie', "+ 428 "'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))), 429 "MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"), 430 validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")), 431 "MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error( 432 fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))), 433 "CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error( 434 fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))), 435 "ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"), 436 validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)), 437 }.Filter() 438 } 439 440 // Validate validates MatchCriteriaAS 441 func (m MatchCriteriaAS) Validate() error { 442 return validation.Errors{ 443 "MatchType": validation.Validate(m.MatchType, validation.In("header", "hostname", "path", "extension", "query", "range", 444 "regex", "cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error( 445 fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'range', "+ 446 "'regex', 'cookie', 'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))), 447 "MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"), 448 validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")), 449 "MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error( 450 fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))), 451 "CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error( 452 fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))), 453 "ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"), 454 validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrRangeOrObjectValidation)), 455 }.Filter() 456 } 457 458 // Validate validates MatchCriteriaPR 459 func (m MatchCriteriaPR) Validate() error { 460 return validation.Errors{ 461 "MatchType": validation.Validate(m.MatchType, validation.In("header", "hostname", "path", "extension", 462 "query", "cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", 463 "method", "proxy").Error( 464 fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'cookie', "+ 465 "'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))), 466 "MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"), 467 validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")), 468 "MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error( 469 fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))), 470 "CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error( 471 fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))), 472 "ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"), 473 validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)), 474 }.Filter() 475 } 476 477 // Validate validates MatchCriteriaER 478 func (m MatchCriteriaER) Validate() error { 479 return validation.Errors{ 480 "MatchType": validation.Validate(m.MatchType, validation.In("header", "hostname", "path", "extension", "query", 481 "regex", "cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error( 482 fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'regex', 'cookie', "+ 483 "'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy' or '' (empty)", (&m).MatchType))), 484 "MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"), 485 validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")), 486 "MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error( 487 fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))), 488 "CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error( 489 fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))), 490 "ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"), 491 validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)), 492 }.Filter() 493 } 494 495 // Validate validates MatchCriteriaFR 496 func (m MatchCriteriaFR) Validate() error { 497 return validation.Errors{ 498 "MatchType": validation.Validate(m.MatchType, validation.Required, validation.In("header", "hostname", "path", "extension", "query", "regex", 499 "cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error( 500 fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'regex', 'cookie', "+ 501 "'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))), 502 "MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"), 503 validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")), 504 "MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error( 505 fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))), 506 "CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error( 507 fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))), 508 "ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"), 509 validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)), 510 }.Filter() 511 } 512 513 // Validate validates MatchCriteriaRC 514 func (m MatchCriteriaRC) Validate() error { 515 return validation.Errors{ 516 "MatchType": validation.Validate(m.MatchType, validation.Required, validation.In("header", "hostname", "path", "extension", "query", "cookie", 517 "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error( 518 fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'cookie', 'deviceCharacteristics', "+ 519 "'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))), 520 "MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"), 521 validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")), 522 "MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error( 523 fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))), 524 "CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error( 525 fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))), 526 "ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"), 527 validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)), 528 }.Filter() 529 } 530 531 func objectMatchValueSimpleOrObjectValidation(value interface{}) error { 532 if value == nil { 533 return nil 534 } 535 switch value.(type) { 536 case *ObjectMatchValueObject, *ObjectMatchValueSimple: 537 return nil 538 default: 539 return fmt.Errorf("type %T is invalid. Must be one of: 'simple' or 'object'", value) 540 } 541 } 542 543 func objectMatchValueSimpleOrRangeOrObjectValidation(value interface{}) error { 544 if value == nil { 545 return nil 546 } 547 switch value.(type) { 548 case *ObjectMatchValueObject, *ObjectMatchValueSimple, *ObjectMatchValueRange: 549 return nil 550 default: 551 return fmt.Errorf("type %T is invalid. Must be one of: 'simple', 'range' or 'object'", value) 552 } 553 } 554 555 func passThroughPercentValidation(value interface{}) error { 556 v, ok := value.(*float64) 557 if !ok { 558 return fmt.Errorf("type %T is invalid. Must be *float64", value) 559 } 560 if v == nil { 561 return fmt.Errorf("cannot be blank") 562 } 563 if *v < -1 { 564 return fmt.Errorf("must be no less than -1") 565 } 566 if *v > 100 { 567 return fmt.Errorf("must be no greater than 100") 568 } 569 return nil 570 } 571 572 // Validate validates ObjectMatchValueRange 573 func (o ObjectMatchValueRange) Validate() error { 574 return validation.Errors{ 575 "Type": validation.Validate(o.Type, validation.In(Range).Error( 576 fmt.Sprintf("value '%s' is invalid. Must be: 'range'", (&o).Type))), 577 }.Filter() 578 } 579 580 // Validate validates ObjectMatchValueSimple 581 func (o ObjectMatchValueSimple) Validate() error { 582 return validation.Errors{ 583 "Type": validation.Validate(o.Type, validation.In(Simple).Error( 584 fmt.Sprintf("value '%s' is invalid. Must be: 'simple'", (&o).Type))), 585 }.Filter() 586 } 587 588 // Validate validates ObjectMatchValueObject 589 func (o ObjectMatchValueObject) Validate() error { 590 return validation.Errors{ 591 "Name": validation.Validate(o.Name, validation.Required, validation.Length(0, 8192)), 592 "Type": validation.Validate(o.Type, validation.Required, validation.In(Object).Error( 593 fmt.Sprintf("value '%s' is invalid. Must be: 'object'", (&o).Type))), 594 }.Filter() 595 } 596 597 func (m MatchRuleAP) cloudletType() string { 598 return "apMatchRule" 599 } 600 601 func (m MatchRuleAS) cloudletType() string { 602 return "asMatchRule" 603 } 604 605 func (m MatchRulePR) cloudletType() string { 606 return "cdMatchRule" 607 } 608 609 func (m MatchRuleER) cloudletType() string { 610 return "erMatchRule" 611 } 612 613 func (m MatchRuleFR) cloudletType() string { 614 return "frMatchRule" 615 } 616 617 func (m MatchRuleRC) cloudletType() string { 618 return "igMatchRule" 619 } 620 621 // UnmarshalJSON helps to un-marshall items of MatchRules array as proper instances of or *MatchRuleER 622 func (m *MatchRules) UnmarshalJSON(b []byte) error { 623 data := make([]map[string]interface{}, 0) 624 if err := json.Unmarshal(b, &data); err != nil { 625 return fmt.Errorf("%w: %s", ErrUnmarshallMatchRules, err) 626 } 627 for _, matchRule := range data { 628 cloudletType, ok := matchRule["type"] 629 if !ok { 630 return fmt.Errorf("%w: match rule entry should contain 'type' field", ErrUnmarshallMatchRules) 631 } 632 cloudletTypeName, ok := cloudletType.(string) 633 if !ok { 634 return fmt.Errorf("%w: 'type' field on match rule entry should be a string", ErrUnmarshallMatchRules) 635 } 636 byteArr, err := json.Marshal(matchRule) 637 if err != nil { 638 return fmt.Errorf("%w: %s", ErrUnmarshallMatchRules, err) 639 } 640 641 matchRuleType, ok := matchRuleHandlers[cloudletTypeName] 642 if !ok { 643 return fmt.Errorf("%w: unsupported match rule type: %s", ErrUnmarshallMatchRules, cloudletTypeName) 644 } 645 dst := matchRuleType() 646 err = json.Unmarshal(byteArr, dst) 647 if err != nil { 648 return fmt.Errorf("%w: %s", ErrUnmarshallMatchRules, err) 649 } 650 *m = append(*m, dst) 651 } 652 return nil 653 } 654 655 // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaAP as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple 656 func (m *MatchCriteriaAP) UnmarshalJSON(b []byte) error { 657 // matchCriteriaAP is an alias for MatchCriteriaAP for un-marshalling purposes 658 type matchCriteriaAP MatchCriteriaAP 659 660 // populate common attributes using default json unmarshaler using aliased type 661 err := json.Unmarshal(b, (*matchCriteriaAP)(m)) 662 if err != nil { 663 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAP, err) 664 } 665 if m.ObjectMatchValue == nil { 666 return nil 667 } 668 669 objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue) 670 if err != nil { 671 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAP, err) 672 } 673 674 createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName] 675 if !ok { 676 return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaAP, objectMatchValueTypeName) 677 } 678 convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue()) 679 if err != nil { 680 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAP, err) 681 } 682 m.ObjectMatchValue = convertedObjectMatchValue 683 684 return nil 685 } 686 687 // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaAS as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple or *ObjectMatchValueRange 688 func (m *MatchCriteriaAS) UnmarshalJSON(b []byte) error { 689 // matchCriteriaAS is an alias for MatchCriteriaAS for un-marshalling purposes 690 type matchCriteriaAS MatchCriteriaAS 691 692 // populate common attributes using default json unmarshaler using aliased type 693 err := json.Unmarshal(b, (*matchCriteriaAS)(m)) 694 if err != nil { 695 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAS, err) 696 } 697 if m.ObjectMatchValue == nil { 698 return nil 699 } 700 701 objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue) 702 if err != nil { 703 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAS, err) 704 } 705 706 createObjectMatchValue, ok := objectOrRangeOrSimpleMatchValueHandlers[objectMatchValueTypeName] 707 if !ok { 708 return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaAS, objectMatchValueTypeName) 709 } 710 convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue()) 711 if err != nil { 712 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAS, err) 713 } 714 m.ObjectMatchValue = convertedObjectMatchValue 715 716 return nil 717 } 718 719 // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaPR as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple 720 func (m *MatchCriteriaPR) UnmarshalJSON(b []byte) error { 721 // matchCriteriaPR is an alias for MatchCriteriaPR for un-marshalling purposes 722 type matchCriteriaPR MatchCriteriaPR 723 724 // populate common attributes using default json unmarshaler using aliased type 725 err := json.Unmarshal(b, (*matchCriteriaPR)(m)) 726 if err != nil { 727 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaPR, err) 728 } 729 if m.ObjectMatchValue == nil { 730 return nil 731 } 732 733 objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue) 734 if err != nil { 735 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaPR, err) 736 } 737 738 createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName] 739 if !ok { 740 return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaPR, objectMatchValueTypeName) 741 } 742 convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue()) 743 if err != nil { 744 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaPR, err) 745 } 746 m.ObjectMatchValue = convertedObjectMatchValue 747 748 return nil 749 } 750 751 // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaER as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple 752 func (m *MatchCriteriaER) UnmarshalJSON(b []byte) error { 753 // matchCriteriaER is an alias for MatchCriteriaER for un-marshalling purposes 754 type matchCriteriaER MatchCriteriaER 755 756 // populate common attributes using default json unmarshaler using aliased type 757 err := json.Unmarshal(b, (*matchCriteriaER)(m)) 758 if err != nil { 759 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaER, err) 760 } 761 if m.ObjectMatchValue == nil { 762 return nil 763 } 764 765 objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue) 766 if err != nil { 767 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaER, err) 768 } 769 770 createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName] 771 if !ok { 772 return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaER, objectMatchValueTypeName) 773 } 774 convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue()) 775 if err != nil { 776 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaER, err) 777 } 778 m.ObjectMatchValue = convertedObjectMatchValue 779 780 return nil 781 } 782 783 // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaFR as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple 784 func (m *MatchCriteriaFR) UnmarshalJSON(b []byte) error { 785 // matchCriteriaFR is an alias for MatchCriteriaFR for un-marshalling purposes 786 type matchCriteriaFR MatchCriteriaFR 787 788 // populate common attributes using default json unmarshaler using aliased type 789 err := json.Unmarshal(b, (*matchCriteriaFR)(m)) 790 if err != nil { 791 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaFR, err) 792 } 793 if m.ObjectMatchValue == nil { 794 return nil 795 } 796 797 objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue) 798 if err != nil { 799 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaFR, err) 800 } 801 802 createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName] 803 if !ok { 804 return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaFR, objectMatchValueTypeName) 805 } 806 convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue()) 807 if err != nil { 808 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaFR, err) 809 } 810 m.ObjectMatchValue = convertedObjectMatchValue 811 812 return nil 813 } 814 815 // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaRC as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple 816 func (m *MatchCriteriaRC) UnmarshalJSON(b []byte) error { 817 // matchCriteriaRC is an alias for MatchCriteriaRC for un-marshalling purposes 818 type matchCriteriaRC MatchCriteriaRC 819 820 // populate common attributes using default json unmarshaler using aliased type 821 err := json.Unmarshal(b, (*matchCriteriaRC)(m)) 822 if err != nil { 823 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaRC, err) 824 } 825 if m.ObjectMatchValue == nil { 826 return nil 827 } 828 829 objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue) 830 if err != nil { 831 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaRC, err) 832 } 833 834 createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName] 835 if !ok { 836 return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaRC, objectMatchValueTypeName) 837 } 838 convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue()) 839 if err != nil { 840 return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaRC, err) 841 } 842 m.ObjectMatchValue = convertedObjectMatchValue 843 844 return nil 845 } 846 847 func getObjectMatchValueType(omv interface{}) (string, error) { 848 objectMatchValueMap, ok := omv.(map[string]interface{}) 849 if !ok { 850 return "", fmt.Errorf("structure of objectMatchValue should be 'map', but was '%T'", omv) 851 } 852 objectMatchValueType, ok := objectMatchValueMap["type"] 853 if !ok { 854 return "", fmt.Errorf("objectMatchValue should contain 'type' field") 855 } 856 objectMatchValueTypeName, ok := objectMatchValueType.(string) 857 if !ok { 858 return "", fmt.Errorf("'type' should be a string") 859 } 860 return objectMatchValueTypeName, nil 861 } 862 863 func convertObjectMatchValue(in, out interface{}) (interface{}, error) { 864 marshal, err := json.Marshal(in) 865 if err != nil { 866 return nil, fmt.Errorf("%s", err) 867 } 868 err = json.Unmarshal(marshal, out) 869 if err != nil { 870 return nil, fmt.Errorf("%s", err) 871 } 872 873 return out, nil 874 }