github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/filter_condition.go (about) 1 package govcd 2 3 /* 4 * Copyright 2020 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. 5 */ 6 7 import ( 8 "fmt" 9 "regexp" 10 11 "github.com/kr/pretty" 12 ) 13 14 // A conditionDef is the data being carried by the filter engine when performing comparisons 15 type conditionDef struct { 16 conditionType string // it's one of SupportedFilters 17 stored interface{} // Any value as handled by the filter being used 18 } 19 20 // A dateCondition can evaluate a date expression 21 type dateCondition struct { 22 dateExpression string 23 } 24 25 // A regexpCondition is a generic filter that is the basis for other filters that require a regular expression 26 type regexpCondition struct { 27 regExpression *regexp.Regexp 28 } 29 30 // an ipCondition is a condition that compares an IP using a regexp 31 type ipCondition regexpCondition 32 33 // a nameCondition is a condition that compares a name using a regexp 34 type nameCondition regexpCondition 35 36 // a metadataRegexpCondition compares the values corresponding to the given key using a regexp 37 type metadataRegexpCondition struct { 38 key string 39 regExpression *regexp.Regexp 40 } 41 42 // a parentCondition compares the entity parent name with the one stored 43 type parentCondition struct { 44 parentName string 45 } 46 47 // a parentIdCondition compares the entity parent ID with the one stored 48 type parentIdCondition struct { 49 parentId string 50 } 51 52 // matchParent matches the wanted parent name (passed in 'stored') to the parent of the queryItem 53 // Input: 54 // - stored: the data of the condition (a parentCondition) 55 // - item: a QueryItem 56 // 57 // Returns: 58 // - bool: the result of the comparison 59 // - string: a description of the operation 60 // - error: an error when the input is not as expected 61 func matchParent(stored, item interface{}) (bool, string, error) { 62 condition, ok := stored.(parentCondition) 63 if !ok { 64 return false, "", fmt.Errorf("stored value is not a Parent condition (%# v)", pretty.Formatter(stored)) 65 } 66 queryItem, ok := item.(QueryItem) 67 if !ok { 68 return false, "", fmt.Errorf("item is not a queryItem searchable by parent: %# v", pretty.Formatter(item)) 69 } 70 parent := queryItem.GetParentName() 71 72 return condition.parentName == parent, fmt.Sprintf("%s == %s", condition.parentName, queryItem.GetParentName()), nil 73 } 74 75 // matchParentId matches the wanted parent ID (passed in 'stored') to the parent ID of the queryItem 76 // The IDs being compared are filtered through extractUuid, to make them homogeneous 77 // Input: 78 // - stored: the data of the condition (a parentCondition) 79 // - item: a QueryItem 80 // 81 // Returns: 82 // - bool: the result of the comparison 83 // - string: a description of the operation 84 // - error: an error when the input is not as expected 85 func matchParentId(stored, item interface{}) (bool, string, error) { 86 condition, ok := stored.(parentIdCondition) 87 if !ok { 88 return false, "", fmt.Errorf("stored value is not a parent ID condition (%# v)", pretty.Formatter(stored)) 89 } 90 queryItem, ok := item.(QueryItem) 91 if !ok { 92 return false, "", fmt.Errorf("item is not a queryItem searchable by parent ID: %# v", pretty.Formatter(item)) 93 } 94 parentId := queryItem.GetParentId() 95 parentId = extractUuid(parentId) 96 condition.parentId = extractUuid(condition.parentId) 97 98 return condition.parentId == parentId, fmt.Sprintf("%s =~ %s", condition.parentId, parentId), nil 99 } 100 101 // matchName matches a name (passed in 'stored') to the name of the queryItem 102 // Input: 103 // - stored: the data of the condition (a nameCondition) 104 // - item: a QueryItem 105 // 106 // Returns: 107 // - bool: the result of the comparison 108 // - string: a description of the operation 109 // - error: an error when the input is not as expected 110 func matchName(stored, item interface{}) (bool, string, error) { 111 re, ok := stored.(nameCondition) 112 if !ok { 113 return false, "", fmt.Errorf("stored value is not a Name Regexp (%# v)", pretty.Formatter(stored)) 114 } 115 queryItem, ok := item.(QueryItem) 116 if !ok { 117 return false, "", fmt.Errorf("item is not a queryItem searchable by regex: %# v", pretty.Formatter(item)) 118 } 119 return re.regExpression.MatchString(queryItem.GetName()), fmt.Sprintf("%s =~ %s", re.regExpression.String(), queryItem.GetName()), nil 120 } 121 122 // matchIp matches an IP (passed in 'stored') to the IP of the queryItem 123 // Input: 124 // - stored: the data of the condition (an ipCondition) 125 // - item: a QueryItem 126 // 127 // Returns: 128 // - bool: the result of the comparison 129 // - string: a description of the operation 130 // - error: an error when the input is not as expected 131 func matchIp(stored, item interface{}) (bool, string, error) { 132 re, ok := stored.(ipCondition) 133 if !ok { 134 return false, "", fmt.Errorf("stored value is not a Condition Regexp (%# v)", pretty.Formatter(stored)) 135 } 136 queryItem, ok := item.(QueryItem) 137 if !ok { 138 return false, "", fmt.Errorf("item is not a queryItem searchable by Ip: %# v", pretty.Formatter(item)) 139 } 140 ip := queryItem.GetIp() 141 if ip == "" { 142 return false, "", fmt.Errorf("%s %s doesn't have an IP", queryItem.GetType(), queryItem.GetName()) 143 } 144 return re.regExpression.MatchString(ip), fmt.Sprintf("%s =~ %s", re.regExpression.String(), queryItem.GetIp()), nil 145 } 146 147 // matchDate matches a date (passed in 'stored') to the date of the queryItem 148 // Input: 149 // - stored: the data of the condition (a dateCondition) 150 // - item: a QueryItem 151 // 152 // Returns: 153 // - bool: the result of the comparison 154 // - string: a description of the operation 155 // - error: an error when the input is not as expected 156 func matchDate(stored, item interface{}) (bool, string, error) { 157 expr, ok := stored.(dateCondition) 158 if !ok { 159 return false, "", fmt.Errorf("stored value is not a condition date (%# v)", pretty.Formatter(stored)) 160 } 161 queryItem, ok := item.(QueryItem) 162 if !ok { 163 return false, "", fmt.Errorf("item is not a queryItem searchable by date: %# v", pretty.Formatter(item)) 164 } 165 if queryItem.GetDate() == "" { 166 return false, "", nil 167 } 168 169 result, err := compareDate(expr.dateExpression, queryItem.GetDate()) 170 return result, fmt.Sprintf("%s %s", queryItem.GetDate(), expr.dateExpression), err 171 } 172 173 // matchMetadata matches a value (passed in 'stored') to the metadata value retrieved from queryItem 174 // Input: 175 // - stored: the data of the condition (a metadataRegexpCondition) 176 // - item: a QueryItem 177 // 178 // Returns: 179 // - bool: the result of the comparison 180 // - string: a description of the operation 181 // - error: an error when the input is not as expected 182 func matchMetadata(stored, item interface{}) (bool, string, error) { 183 re, ok := stored.(metadataRegexpCondition) 184 if !ok { 185 return false, "", fmt.Errorf("stored value is not a Metadata condition (%# v)", pretty.Formatter(stored)) 186 } 187 queryItem, ok := item.(QueryItem) 188 if !ok { 189 return false, "", fmt.Errorf("item is not a queryItem searchable by Metadata: %# v", pretty.Formatter(item)) 190 } 191 return re.regExpression.MatchString(queryItem.GetMetadataValue(re.key)), fmt.Sprintf("metadata: %s -> %s", re.key, re.regExpression.String()), nil 192 }