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  }