github.com/vmware/govmomi@v0.37.2/property/match.go (about)

     1  /*
     2  Copyright (c) 2017-2024 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package property
    18  
    19  import (
    20  	"fmt"
    21  	"path"
    22  	"reflect"
    23  	"strconv"
    24  	"strings"
    25  
    26  	"github.com/vmware/govmomi/vim25/types"
    27  )
    28  
    29  // Match provides methods for matching against types.DynamicProperty
    30  type Match map[string]types.AnyType
    31  
    32  // Keys returns the Match map keys as a []string
    33  func (m Match) Keys() []string {
    34  	keys := make([]string, 0, len(m))
    35  
    36  	for key := range m {
    37  		keys = append(keys, key)
    38  	}
    39  
    40  	return keys
    41  }
    42  
    43  // Property returns true if an entry matches the given prop.
    44  func (m Match) Property(prop types.DynamicProperty) bool {
    45  	if prop.Val == nil {
    46  		return false
    47  	}
    48  	match, ok := m[prop.Name]
    49  	if !ok {
    50  		return false
    51  	}
    52  
    53  	if match == prop.Val {
    54  		return true
    55  	}
    56  
    57  	ptype := reflect.TypeOf(prop.Val)
    58  
    59  	if strings.HasPrefix(ptype.Name(), "ArrayOf") {
    60  		pval := reflect.ValueOf(prop.Val).Field(0)
    61  
    62  		for i := 0; i < pval.Len(); i++ {
    63  			prop.Val = pval.Index(i).Interface()
    64  
    65  			if m.Property(prop) {
    66  				return true
    67  			}
    68  		}
    69  
    70  		return false
    71  	}
    72  
    73  	if reflect.TypeOf(match) != ptype {
    74  		s, ok := match.(string)
    75  		if !ok {
    76  			return false
    77  		}
    78  
    79  		// convert if we can
    80  		switch val := prop.Val.(type) {
    81  		case bool:
    82  			match, _ = strconv.ParseBool(s)
    83  		case int16:
    84  			x, _ := strconv.ParseInt(s, 10, 16)
    85  			match = int16(x)
    86  		case int32:
    87  			x, _ := strconv.ParseInt(s, 10, 32)
    88  			match = int32(x)
    89  		case int64:
    90  			match, _ = strconv.ParseInt(s, 10, 64)
    91  		case float32:
    92  			x, _ := strconv.ParseFloat(s, 32)
    93  			match = float32(x)
    94  		case float64:
    95  			match, _ = strconv.ParseFloat(s, 64)
    96  		case fmt.Stringer:
    97  			prop.Val = val.String()
    98  		case *types.CustomFieldStringValue:
    99  			prop.Val = fmt.Sprintf("%d:%s", val.Key, val.Value)
   100  		default:
   101  			if ptype.Kind() != reflect.String {
   102  				return false
   103  			}
   104  			// An enum type we can convert to a string type
   105  			prop.Val = reflect.ValueOf(prop.Val).String()
   106  		}
   107  	}
   108  
   109  	switch pval := prop.Val.(type) {
   110  	case string:
   111  		s := match.(string)
   112  		if s == "*" {
   113  			return true // TODO: path.Match fails if s contains a '/'
   114  		}
   115  		m, _ := path.Match(s, pval)
   116  		return m
   117  	default:
   118  		return reflect.DeepEqual(match, pval)
   119  	}
   120  }
   121  
   122  // List returns true if all given props match.
   123  func (m Match) List(props []types.DynamicProperty) bool {
   124  	for _, p := range props {
   125  		if !m.Property(p) {
   126  			return false
   127  		}
   128  	}
   129  
   130  	return len(m) == len(props) // false if a property such as VM "guest" is unset
   131  }
   132  
   133  // ObjectContent returns a list of ObjectContent.Obj where the
   134  // ObjectContent.PropSet matches all properties the Filter.
   135  func (m Match) ObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference {
   136  	var refs []types.ManagedObjectReference
   137  
   138  	for _, o := range objects {
   139  		if m.List(o.PropSet) {
   140  			refs = append(refs, o.Obj)
   141  		}
   142  	}
   143  
   144  	return refs
   145  }
   146  
   147  // AnyList returns true if any given props match.
   148  func (m Match) AnyList(props []types.DynamicProperty) bool {
   149  	for _, p := range props {
   150  		if m.Property(p) {
   151  			return true
   152  		}
   153  	}
   154  
   155  	return false
   156  }
   157  
   158  // AnyObjectContent returns a list of ObjectContent.Obj where the
   159  // ObjectContent.PropSet matches any property.
   160  func (m Match) AnyObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference {
   161  	var refs []types.ManagedObjectReference
   162  
   163  	for _, o := range objects {
   164  		if m.AnyList(o.PropSet) {
   165  			refs = append(refs, o.Obj)
   166  		}
   167  	}
   168  
   169  	return refs
   170  }