github.com/vmware/govmomi@v0.43.0/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 }