github.com/vmware/govmomi@v0.51.0/property/match.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package property 6 7 import ( 8 "fmt" 9 "path" 10 "reflect" 11 "strconv" 12 "strings" 13 14 "github.com/vmware/govmomi/vim25/types" 15 ) 16 17 // Match provides methods for matching against types.DynamicProperty 18 type Match map[string]types.AnyType 19 20 // Keys returns the Match map keys as a []string 21 func (m Match) Keys() []string { 22 keys := make([]string, 0, len(m)) 23 24 for key := range m { 25 keys = append(keys, key) 26 } 27 28 return keys 29 } 30 31 // Property returns true if an entry matches the given prop. 32 func (m Match) Property(prop types.DynamicProperty) bool { 33 if prop.Val == nil { 34 return false 35 } 36 match, ok := m[prop.Name] 37 if !ok { 38 return false 39 } 40 41 if match == prop.Val { 42 return true 43 } 44 45 if matchFunc, ok := match.(func(any) bool); ok { 46 if matchFunc(prop.Val) { 47 return true 48 } 49 } 50 51 ptype := reflect.TypeOf(prop.Val) 52 53 if strings.HasPrefix(ptype.Name(), "ArrayOf") { 54 pval := reflect.ValueOf(prop.Val).Field(0) 55 56 for i := 0; i < pval.Len(); i++ { 57 prop.Val = pval.Index(i).Interface() 58 59 if m.Property(prop) { 60 return true 61 } 62 } 63 64 return false 65 } 66 67 if reflect.TypeOf(match) != ptype { 68 s, ok := match.(string) 69 if !ok { 70 return false 71 } 72 73 // convert if we can 74 switch val := prop.Val.(type) { 75 case bool: 76 match, _ = strconv.ParseBool(s) 77 case int16: 78 x, _ := strconv.ParseInt(s, 10, 16) 79 match = int16(x) 80 case int32: 81 x, _ := strconv.ParseInt(s, 10, 32) 82 match = int32(x) 83 case int64: 84 match, _ = strconv.ParseInt(s, 10, 64) 85 case float32: 86 x, _ := strconv.ParseFloat(s, 32) 87 match = float32(x) 88 case float64: 89 match, _ = strconv.ParseFloat(s, 64) 90 case fmt.Stringer: 91 prop.Val = val.String() 92 case *types.CustomFieldStringValue: 93 prop.Val = fmt.Sprintf("%d:%s", val.Key, val.Value) 94 default: 95 if ptype.Kind() != reflect.String { 96 return false 97 } 98 // An enum type we can convert to a string type 99 prop.Val = reflect.ValueOf(prop.Val).String() 100 } 101 } 102 103 switch pval := prop.Val.(type) { 104 case string: 105 s := match.(string) 106 if s == "*" { 107 return true // TODO: path.Match fails if s contains a '/' 108 } 109 m, _ := path.Match(s, pval) 110 return m 111 default: 112 return reflect.DeepEqual(match, pval) 113 } 114 } 115 116 // List returns true if all given props match. 117 func (m Match) List(props []types.DynamicProperty) bool { 118 for _, p := range props { 119 if !m.Property(p) { 120 return false 121 } 122 } 123 124 return len(m) == len(props) // false if a property such as VM "guest" is unset 125 } 126 127 // ObjectContent returns a list of ObjectContent.Obj where the 128 // ObjectContent.PropSet matches all properties the Filter. 129 func (m Match) ObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference { 130 var refs []types.ManagedObjectReference 131 132 for _, o := range objects { 133 if m.List(o.PropSet) { 134 refs = append(refs, o.Obj) 135 } 136 } 137 138 return refs 139 } 140 141 // AnyList returns true if any given props match. 142 func (m Match) AnyList(props []types.DynamicProperty) bool { 143 for _, p := range props { 144 if m.Property(p) { 145 return true 146 } 147 } 148 149 return false 150 } 151 152 // AnyObjectContent returns a list of ObjectContent.Obj where the 153 // ObjectContent.PropSet matches any property. 154 func (m Match) AnyObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference { 155 var refs []types.ManagedObjectReference 156 157 for _, o := range objects { 158 if m.AnyList(o.PropSet) { 159 refs = append(refs, o.Obj) 160 } 161 } 162 163 return refs 164 }