sigs.k8s.io/cluster-api@v1.7.1/util/collections/machine_collection.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 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 // Modified copy of k8s.io/apimachinery/pkg/util/sets/int64.go 18 // Modifications 19 // - int64 became *clusterv1.Machine 20 // - Empty type is removed 21 // - Sortable data type is removed in favor of util.MachinesByCreationTimestamp 22 // - nil checks added to account for the pointer 23 // - Added Filter, AnyFilter, and Oldest methods 24 // - Added FromMachineList initializer 25 // - Updated Has to also check for equality of Machines 26 // - Removed unused methods 27 28 package collections 29 30 import ( 31 "sort" 32 33 "github.com/blang/semver/v4" 34 35 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 36 "sigs.k8s.io/cluster-api/util/conditions" 37 "sigs.k8s.io/cluster-api/util/version" 38 ) 39 40 // Machines is a set of Machines. 41 type Machines map[string]*clusterv1.Machine 42 43 // MachinesByVersion sorts the list of Machine by spec.version, using their names as tie breaker. 44 // machines with no version are placed lower in the order. 45 type machinesByVersion []*clusterv1.Machine 46 47 func (v machinesByVersion) Len() int { return len(v) } 48 func (v machinesByVersion) Swap(i, j int) { v[i], v[j] = v[j], v[i] } 49 func (v machinesByVersion) Less(i, j int) bool { 50 vi, _ := semver.ParseTolerant(*v[i].Spec.Version) 51 vj, _ := semver.ParseTolerant(*v[j].Spec.Version) 52 comp := version.Compare(vi, vj, version.WithBuildTags()) 53 if comp == 0 { 54 return v[i].Name < v[j].Name 55 } 56 return comp == -1 57 } 58 59 // machinesByCreationTimestamp sorts a list of Machine by creation timestamp, using their names as a tie breaker. 60 type machinesByCreationTimestamp []*clusterv1.Machine 61 62 func (o machinesByCreationTimestamp) Len() int { return len(o) } 63 func (o machinesByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } 64 func (o machinesByCreationTimestamp) Less(i, j int) bool { 65 if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) { 66 return o[i].Name < o[j].Name 67 } 68 return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp) 69 } 70 71 // New creates an empty Machines. 72 func New() Machines { 73 return make(Machines) 74 } 75 76 // FromMachines creates a Machines from a list of values. 77 func FromMachines(machines ...*clusterv1.Machine) Machines { 78 ss := make(Machines, len(machines)) 79 ss.Insert(machines...) 80 return ss 81 } 82 83 // FromMachineList creates a Machines from the given MachineList. 84 func FromMachineList(machineList *clusterv1.MachineList) Machines { 85 ss := make(Machines, len(machineList.Items)) 86 for i := range machineList.Items { 87 ss.Insert(&machineList.Items[i]) 88 } 89 return ss 90 } 91 92 // ToMachineList creates a MachineList from the given Machines. 93 func ToMachineList(machines Machines) clusterv1.MachineList { 94 ml := clusterv1.MachineList{} 95 for _, m := range machines { 96 ml.Items = append(ml.Items, *m) 97 } 98 return ml 99 } 100 101 // Insert adds items to the set. 102 func (s Machines) Insert(machines ...*clusterv1.Machine) { 103 for i := range machines { 104 if machines[i] != nil { 105 m := machines[i] 106 s[m.Name] = m 107 } 108 } 109 } 110 111 // Difference returns a copy without machines that are in the given collection. 112 func (s Machines) Difference(machines Machines) Machines { 113 return s.Filter(func(m *clusterv1.Machine) bool { 114 _, found := machines[m.Name] 115 return !found 116 }) 117 } 118 119 // SortedByCreationTimestamp returns the machines sorted by creation timestamp. 120 func (s Machines) SortedByCreationTimestamp() []*clusterv1.Machine { 121 res := make(machinesByCreationTimestamp, 0, len(s)) 122 for _, value := range s { 123 res = append(res, value) 124 } 125 sort.Sort(res) 126 return res 127 } 128 129 // UnsortedList returns the slice with contents in random order. 130 func (s Machines) UnsortedList() []*clusterv1.Machine { 131 res := make([]*clusterv1.Machine, 0, len(s)) 132 for _, value := range s { 133 res = append(res, value) 134 } 135 return res 136 } 137 138 // Len returns the size of the set. 139 func (s Machines) Len() int { 140 return len(s) 141 } 142 143 // newFilteredMachineCollection creates a Machines from a filtered list of values. 144 func newFilteredMachineCollection(filter Func, machines ...*clusterv1.Machine) Machines { 145 ss := make(Machines, len(machines)) 146 for i := range machines { 147 m := machines[i] 148 if filter(m) { 149 ss.Insert(m) 150 } 151 } 152 return ss 153 } 154 155 // Filter returns a Machines containing only the Machines that match all of the given MachineFilters. 156 func (s Machines) Filter(filters ...Func) Machines { 157 return newFilteredMachineCollection(And(filters...), s.UnsortedList()...) 158 } 159 160 // AnyFilter returns a Machines containing only the Machines that match any of the given MachineFilters. 161 func (s Machines) AnyFilter(filters ...Func) Machines { 162 return newFilteredMachineCollection(Or(filters...), s.UnsortedList()...) 163 } 164 165 // Oldest returns the Machine with the oldest CreationTimestamp. 166 func (s Machines) Oldest() *clusterv1.Machine { 167 if len(s) == 0 { 168 return nil 169 } 170 return s.SortedByCreationTimestamp()[0] 171 } 172 173 // Newest returns the Machine with the most recent CreationTimestamp. 174 func (s Machines) Newest() *clusterv1.Machine { 175 if len(s) == 0 { 176 return nil 177 } 178 return s.SortedByCreationTimestamp()[len(s)-1] 179 } 180 181 // DeepCopy returns a deep copy. 182 func (s Machines) DeepCopy() Machines { 183 result := make(Machines, len(s)) 184 for _, m := range s { 185 result.Insert(m.DeepCopy()) 186 } 187 return result 188 } 189 190 // ConditionGetters returns the slice with machines converted into conditions.Getter. 191 func (s Machines) ConditionGetters() []conditions.Getter { 192 res := make([]conditions.Getter, 0, len(s)) 193 for _, v := range s { 194 value := *v 195 res = append(res, &value) 196 } 197 return res 198 } 199 200 // Names returns a slice of the names of each machine in the collection. 201 // Useful for logging and test assertions. 202 func (s Machines) Names() []string { 203 names := make([]string, 0, s.Len()) 204 for _, m := range s { 205 names = append(names, m.Name) 206 } 207 return names 208 } 209 210 // SortedByVersion returns the machines sorted by version. 211 func (s Machines) sortedByVersion() []*clusterv1.Machine { 212 res := make(machinesByVersion, 0, len(s)) 213 for _, value := range s { 214 res = append(res, value) 215 } 216 sort.Sort(res) 217 return res 218 } 219 220 // LowestVersion returns the lowest version among all the machine with 221 // defined versions. If no machine has a defined version it returns an 222 // empty string. 223 func (s Machines) LowestVersion() *string { 224 machines := s.Filter(WithVersion()) 225 if len(machines) == 0 { 226 return nil 227 } 228 m := machines.sortedByVersion()[0] 229 return m.Spec.Version 230 }