...

Source file src/sigs.k8s.io/cli-utils/pkg/ordering/sort.go

Documentation: sigs.k8s.io/cli-utils/pkg/ordering

     1  // Copyright 2020 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package ordering
     5  
     6  import (
     7  	"sort"
     8  
     9  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    10  	"k8s.io/apimachinery/pkg/runtime/schema"
    11  	"k8s.io/cli-runtime/pkg/resource"
    12  	"sigs.k8s.io/cli-utils/pkg/object"
    13  )
    14  
    15  type SortableInfos []*resource.Info
    16  
    17  var _ sort.Interface = SortableInfos{}
    18  
    19  func (a SortableInfos) Len() int      { return len(a) }
    20  func (a SortableInfos) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
    21  func (a SortableInfos) Less(i, j int) bool {
    22  	first, err := object.InfoToObjMeta(a[i])
    23  	if err != nil {
    24  		return false
    25  	}
    26  	second, err := object.InfoToObjMeta(a[j])
    27  	if err != nil {
    28  		return false
    29  	}
    30  	return less(first, second)
    31  }
    32  
    33  type SortableUnstructureds []*unstructured.Unstructured
    34  
    35  var _ sort.Interface = SortableUnstructureds{}
    36  
    37  func (a SortableUnstructureds) Len() int      { return len(a) }
    38  func (a SortableUnstructureds) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
    39  func (a SortableUnstructureds) Less(i, j int) bool {
    40  	first := object.UnstructuredToObjMetadata(a[i])
    41  	second := object.UnstructuredToObjMetadata(a[j])
    42  	return less(first, second)
    43  }
    44  
    45  type SortableMetas []object.ObjMetadata
    46  
    47  var _ sort.Interface = SortableMetas{}
    48  
    49  func (a SortableMetas) Len() int      { return len(a) }
    50  func (a SortableMetas) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
    51  func (a SortableMetas) Less(i, j int) bool {
    52  	return less(a[i], a[j])
    53  }
    54  
    55  func less(i, j object.ObjMetadata) bool {
    56  	if !Equals(i.GroupKind, j.GroupKind) {
    57  		return IsLessThan(i.GroupKind, j.GroupKind)
    58  	}
    59  	// In case of tie, compare the namespace and name combination so that the output
    60  	// order is consistent irrespective of input order
    61  	if i.Namespace != j.Namespace {
    62  		return i.Namespace < j.Namespace
    63  	}
    64  	return i.Name < j.Name
    65  }
    66  
    67  var groupKind2index = computeGroupKind2index()
    68  
    69  func computeGroupKind2index() map[schema.GroupKind]int {
    70  	// An attempt to order things to help k8s, e.g.
    71  	// a Service should come before things that refer to it.
    72  	// Namespace should be first.
    73  	// In some cases order just specified to provide determinism.
    74  	orderFirst := []schema.GroupKind{
    75  		{Group: "", Kind: "Namespace"},
    76  		{Group: "", Kind: "ResourceQuota"},
    77  		{Group: "storage.k8s.io", Kind: "StorageClass"},
    78  		{Group: "apiextensions.k8s.io", Kind: "CustomResourceDefinition"},
    79  		{Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration"},
    80  		{Group: "", Kind: "ServiceAccount"},
    81  		{Group: "extensions", Kind: "PodSecurityPolicy"}, // deprecated=1.11, removed=1.16
    82  		{Group: "policy", Kind: "PodSecurityPolicy"},     // deprecated=1.21, removed=1.25
    83  		{Group: "rbac.authorization.k8s.io", Kind: "Role"},
    84  		{Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"},
    85  		{Group: "rbac.authorization.k8s.io", Kind: "RoleBinding"},
    86  		{Group: "rbac.authorization.k8s.io", Kind: "ClusterRoleBinding"},
    87  		{Group: "", Kind: "ConfigMap"},
    88  		{Group: "", Kind: "Secret"},
    89  		{Group: "", Kind: "Service"},
    90  		{Group: "", Kind: "LimitRange"},
    91  		{Group: "scheduling.k8s.io", Kind: "PriorityClass"},
    92  		{Group: "extensions", Kind: "Deployment"}, // deprecated=1.8, removed=1.16
    93  		{Group: "apps", Kind: "Deployment"},
    94  		{Group: "apps", Kind: "StatefulSet"},
    95  		{Group: "batch", Kind: "CronJob"},
    96  		{Group: "policy", Kind: "PodDisruptionBudget"},
    97  	}
    98  	orderLast := []schema.GroupKind{
    99  		{Group: "admissionregistration.k8s.io", Kind: "ValidatingWebhookConfiguration"},
   100  	}
   101  	kind2indexResult := make(map[schema.GroupKind]int, len(orderFirst)+len(orderLast))
   102  	for i, n := range orderFirst {
   103  		kind2indexResult[n] = -len(orderFirst) + i
   104  	}
   105  	for i, n := range orderLast {
   106  		kind2indexResult[n] = 1 + i
   107  	}
   108  	return kind2indexResult
   109  }
   110  
   111  func Equals(i, j schema.GroupKind) bool {
   112  	return i.Group == j.Group && i.Kind == j.Kind
   113  }
   114  
   115  func IsLessThan(i, j schema.GroupKind) bool {
   116  	indexI := groupKind2index[i]
   117  	indexJ := groupKind2index[j]
   118  	if indexI != indexJ {
   119  		return indexI < indexJ
   120  	}
   121  	if i.Group != j.Group {
   122  		return i.Group < j.Group
   123  	}
   124  	return i.Kind < j.Kind
   125  }
   126  

View as plain text