...

Source file src/helm.sh/helm/v3/pkg/releaseutil/kind_sorter_test.go

Documentation: helm.sh/helm/v3/pkg/releaseutil

     1  /*
     2  Copyright The Helm 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  package releaseutil
    18  
    19  import (
    20  	"bytes"
    21  	"testing"
    22  
    23  	"helm.sh/helm/v3/pkg/release"
    24  )
    25  
    26  func TestKindSorter(t *testing.T) {
    27  	manifests := []Manifest{
    28  		{
    29  			Name: "U",
    30  			Head: &SimpleHead{Kind: "IngressClass"},
    31  		},
    32  		{
    33  			Name: "E",
    34  			Head: &SimpleHead{Kind: "SecretList"},
    35  		},
    36  		{
    37  			Name: "i",
    38  			Head: &SimpleHead{Kind: "ClusterRole"},
    39  		},
    40  		{
    41  			Name: "I",
    42  			Head: &SimpleHead{Kind: "ClusterRoleList"},
    43  		},
    44  		{
    45  			Name: "j",
    46  			Head: &SimpleHead{Kind: "ClusterRoleBinding"},
    47  		},
    48  		{
    49  			Name: "J",
    50  			Head: &SimpleHead{Kind: "ClusterRoleBindingList"},
    51  		},
    52  		{
    53  			Name: "f",
    54  			Head: &SimpleHead{Kind: "ConfigMap"},
    55  		},
    56  		{
    57  			Name: "u",
    58  			Head: &SimpleHead{Kind: "CronJob"},
    59  		},
    60  		{
    61  			Name: "2",
    62  			Head: &SimpleHead{Kind: "CustomResourceDefinition"},
    63  		},
    64  		{
    65  			Name: "n",
    66  			Head: &SimpleHead{Kind: "DaemonSet"},
    67  		},
    68  		{
    69  			Name: "r",
    70  			Head: &SimpleHead{Kind: "Deployment"},
    71  		},
    72  		{
    73  			Name: "!",
    74  			Head: &SimpleHead{Kind: "HonkyTonkSet"},
    75  		},
    76  		{
    77  			Name: "v",
    78  			Head: &SimpleHead{Kind: "Ingress"},
    79  		},
    80  		{
    81  			Name: "t",
    82  			Head: &SimpleHead{Kind: "Job"},
    83  		},
    84  		{
    85  			Name: "c",
    86  			Head: &SimpleHead{Kind: "LimitRange"},
    87  		},
    88  		{
    89  			Name: "a",
    90  			Head: &SimpleHead{Kind: "Namespace"},
    91  		},
    92  		{
    93  			Name: "A",
    94  			Head: &SimpleHead{Kind: "NetworkPolicy"},
    95  		},
    96  		{
    97  			Name: "g",
    98  			Head: &SimpleHead{Kind: "PersistentVolume"},
    99  		},
   100  		{
   101  			Name: "h",
   102  			Head: &SimpleHead{Kind: "PersistentVolumeClaim"},
   103  		},
   104  		{
   105  			Name: "o",
   106  			Head: &SimpleHead{Kind: "Pod"},
   107  		},
   108  		{
   109  			Name: "3",
   110  			Head: &SimpleHead{Kind: "PodDisruptionBudget"},
   111  		},
   112  		{
   113  			Name: "C",
   114  			Head: &SimpleHead{Kind: "PodSecurityPolicy"},
   115  		},
   116  		{
   117  			Name: "q",
   118  			Head: &SimpleHead{Kind: "ReplicaSet"},
   119  		},
   120  		{
   121  			Name: "p",
   122  			Head: &SimpleHead{Kind: "ReplicationController"},
   123  		},
   124  		{
   125  			Name: "b",
   126  			Head: &SimpleHead{Kind: "ResourceQuota"},
   127  		},
   128  		{
   129  			Name: "k",
   130  			Head: &SimpleHead{Kind: "Role"},
   131  		},
   132  		{
   133  			Name: "K",
   134  			Head: &SimpleHead{Kind: "RoleList"},
   135  		},
   136  		{
   137  			Name: "l",
   138  			Head: &SimpleHead{Kind: "RoleBinding"},
   139  		},
   140  		{
   141  			Name: "L",
   142  			Head: &SimpleHead{Kind: "RoleBindingList"},
   143  		},
   144  		{
   145  			Name: "e",
   146  			Head: &SimpleHead{Kind: "Secret"},
   147  		},
   148  		{
   149  			Name: "m",
   150  			Head: &SimpleHead{Kind: "Service"},
   151  		},
   152  		{
   153  			Name: "d",
   154  			Head: &SimpleHead{Kind: "ServiceAccount"},
   155  		},
   156  		{
   157  			Name: "s",
   158  			Head: &SimpleHead{Kind: "StatefulSet"},
   159  		},
   160  		{
   161  			Name: "1",
   162  			Head: &SimpleHead{Kind: "StorageClass"},
   163  		},
   164  		{
   165  			Name: "w",
   166  			Head: &SimpleHead{Kind: "APIService"},
   167  		},
   168  		{
   169  			Name: "x",
   170  			Head: &SimpleHead{Kind: "HorizontalPodAutoscaler"},
   171  		},
   172  		{
   173  			Name: "F",
   174  			Head: &SimpleHead{Kind: "PriorityClass"},
   175  		},
   176  	}
   177  
   178  	for _, test := range []struct {
   179  		description string
   180  		order       KindSortOrder
   181  		expected    string
   182  	}{
   183  		{"install", InstallOrder, "FaAbcC3deEf1gh2iIjJkKlLmnopqrxstuUvw!"},
   184  		{"uninstall", UninstallOrder, "wvUmutsxrqponLlKkJjIi2hg1fEed3CcbAaF!"},
   185  	} {
   186  		var buf bytes.Buffer
   187  		t.Run(test.description, func(t *testing.T) {
   188  			if got, want := len(test.expected), len(manifests); got != want {
   189  				t.Fatalf("Expected %d names in order, got %d", want, got)
   190  			}
   191  			defer buf.Reset()
   192  			orig := manifests
   193  			for _, r := range sortManifestsByKind(manifests, test.order) {
   194  				buf.WriteString(r.Name)
   195  			}
   196  			if got := buf.String(); got != test.expected {
   197  				t.Errorf("Expected %q, got %q", test.expected, got)
   198  			}
   199  			for i, manifest := range orig {
   200  				if manifest != manifests[i] {
   201  					t.Fatal("Expected input to sortManifestsByKind to stay the same")
   202  				}
   203  			}
   204  		})
   205  	}
   206  }
   207  
   208  // TestKindSorterKeepOriginalOrder verifies manifests of same kind are kept in original order
   209  func TestKindSorterKeepOriginalOrder(t *testing.T) {
   210  	manifests := []Manifest{
   211  		{
   212  			Name: "a",
   213  			Head: &SimpleHead{Kind: "ClusterRole"},
   214  		},
   215  		{
   216  			Name: "A",
   217  			Head: &SimpleHead{Kind: "ClusterRole"},
   218  		},
   219  		{
   220  			Name: "0",
   221  			Head: &SimpleHead{Kind: "ConfigMap"},
   222  		},
   223  		{
   224  			Name: "1",
   225  			Head: &SimpleHead{Kind: "ConfigMap"},
   226  		},
   227  		{
   228  			Name: "z",
   229  			Head: &SimpleHead{Kind: "ClusterRoleBinding"},
   230  		},
   231  		{
   232  			Name: "!",
   233  			Head: &SimpleHead{Kind: "ClusterRoleBinding"},
   234  		},
   235  		{
   236  			Name: "u2",
   237  			Head: &SimpleHead{Kind: "Unknown"},
   238  		},
   239  		{
   240  			Name: "u1",
   241  			Head: &SimpleHead{Kind: "Unknown"},
   242  		},
   243  		{
   244  			Name: "t3",
   245  			Head: &SimpleHead{Kind: "Unknown2"},
   246  		},
   247  	}
   248  	for _, test := range []struct {
   249  		description string
   250  		order       KindSortOrder
   251  		expected    string
   252  	}{
   253  		// expectation is sorted by kind (unknown is last) and within each group of same kind, the order is kept
   254  		{"cm,clusterRole,clusterRoleBinding,Unknown,Unknown2", InstallOrder, "01aAz!u2u1t3"},
   255  	} {
   256  		var buf bytes.Buffer
   257  		t.Run(test.description, func(t *testing.T) {
   258  			defer buf.Reset()
   259  			for _, r := range sortManifestsByKind(manifests, test.order) {
   260  				buf.WriteString(r.Name)
   261  			}
   262  			if got := buf.String(); got != test.expected {
   263  				t.Errorf("Expected %q, got %q", test.expected, got)
   264  			}
   265  		})
   266  	}
   267  }
   268  
   269  func TestKindSorterNamespaceAgainstUnknown(t *testing.T) {
   270  	unknown := Manifest{
   271  		Name: "a",
   272  		Head: &SimpleHead{Kind: "Unknown"},
   273  	}
   274  	namespace := Manifest{
   275  		Name: "b",
   276  		Head: &SimpleHead{Kind: "Namespace"},
   277  	}
   278  
   279  	manifests := []Manifest{unknown, namespace}
   280  	manifests = sortManifestsByKind(manifests, InstallOrder)
   281  
   282  	expectedOrder := []Manifest{namespace, unknown}
   283  	for i, manifest := range manifests {
   284  		if expectedOrder[i].Name != manifest.Name {
   285  			t.Errorf("Expected %s, got %s", expectedOrder[i].Name, manifest.Name)
   286  		}
   287  	}
   288  }
   289  
   290  // test hook sorting with a small subset of kinds, since it uses the same algorithm as sortManifestsByKind
   291  func TestKindSorterForHooks(t *testing.T) {
   292  	hooks := []*release.Hook{
   293  		{
   294  			Name: "i",
   295  			Kind: "ClusterRole",
   296  		},
   297  		{
   298  			Name: "j",
   299  			Kind: "ClusterRoleBinding",
   300  		},
   301  		{
   302  			Name: "c",
   303  			Kind: "LimitRange",
   304  		},
   305  		{
   306  			Name: "a",
   307  			Kind: "Namespace",
   308  		},
   309  	}
   310  
   311  	for _, test := range []struct {
   312  		description string
   313  		order       KindSortOrder
   314  		expected    string
   315  	}{
   316  		{"install", InstallOrder, "acij"},
   317  		{"uninstall", UninstallOrder, "jica"},
   318  	} {
   319  		var buf bytes.Buffer
   320  		t.Run(test.description, func(t *testing.T) {
   321  			if got, want := len(test.expected), len(hooks); got != want {
   322  				t.Fatalf("Expected %d names in order, got %d", want, got)
   323  			}
   324  			defer buf.Reset()
   325  			orig := hooks
   326  			for _, r := range sortHooksByKind(hooks, test.order) {
   327  				buf.WriteString(r.Name)
   328  			}
   329  			for i, hook := range orig {
   330  				if hook != hooks[i] {
   331  					t.Fatal("Expected input to sortHooksByKind to stay the same")
   332  				}
   333  			}
   334  			if got := buf.String(); got != test.expected {
   335  				t.Errorf("Expected %q, got %q", test.expected, got)
   336  			}
   337  		})
   338  	}
   339  }
   340  

View as plain text