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  }