...

Source file src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go

Documentation: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions

     1  /*
     2  Copyright 2017 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  package apiextensions
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  )
    26  
    27  func TestCRDHasFinalizer(t *testing.T) {
    28  	tests := []struct {
    29  		name             string
    30  		crd              *CustomResourceDefinition
    31  		finalizerToCheck string
    32  
    33  		expected bool
    34  	}{
    35  		{
    36  			name: "missing",
    37  			crd: &CustomResourceDefinition{
    38  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
    39  			},
    40  			finalizerToCheck: "it",
    41  			expected:         false,
    42  		},
    43  		{
    44  			name: "present",
    45  			crd: &CustomResourceDefinition{
    46  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
    47  			},
    48  			finalizerToCheck: "it",
    49  			expected:         true,
    50  		},
    51  	}
    52  	for _, tc := range tests {
    53  		actual := CRDHasFinalizer(tc.crd, tc.finalizerToCheck)
    54  		if tc.expected != actual {
    55  			t.Errorf("%v expected %v, got %v", tc.name, tc.expected, actual)
    56  		}
    57  	}
    58  }
    59  
    60  func TestCRDRemoveFinalizer(t *testing.T) {
    61  	tests := []struct {
    62  		name             string
    63  		crd              *CustomResourceDefinition
    64  		finalizerToCheck string
    65  
    66  		expected []string
    67  	}{
    68  		{
    69  			name: "missing",
    70  			crd: &CustomResourceDefinition{
    71  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
    72  			},
    73  			finalizerToCheck: "it",
    74  			expected:         []string{"not-it"},
    75  		},
    76  		{
    77  			name: "present",
    78  			crd: &CustomResourceDefinition{
    79  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
    80  			},
    81  			finalizerToCheck: "it",
    82  			expected:         []string{"not-it"},
    83  		},
    84  	}
    85  	for _, tc := range tests {
    86  		CRDRemoveFinalizer(tc.crd, tc.finalizerToCheck)
    87  		if !reflect.DeepEqual(tc.expected, tc.crd.Finalizers) {
    88  			t.Errorf("%v expected %v, got %v", tc.name, tc.expected, tc.crd.Finalizers)
    89  		}
    90  	}
    91  }
    92  
    93  func TestSetCRDCondition(t *testing.T) {
    94  	tests := []struct {
    95  		name                 string
    96  		crdCondition         []CustomResourceDefinitionCondition
    97  		newCondition         CustomResourceDefinitionCondition
    98  		expectedcrdCondition []CustomResourceDefinitionCondition
    99  	}{
   100  		{
   101  			name: "test setCRDcondition when one condition",
   102  			crdCondition: []CustomResourceDefinitionCondition{
   103  				{
   104  					Type:               Established,
   105  					Status:             ConditionTrue,
   106  					Reason:             "Accepted",
   107  					Message:            "the initial names have been accepted",
   108  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   109  				},
   110  			},
   111  			newCondition: CustomResourceDefinitionCondition{
   112  				Type:               Established,
   113  				Status:             ConditionFalse,
   114  				Reason:             "NotAccepted",
   115  				Message:            "Not accepted",
   116  				LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   117  			},
   118  			expectedcrdCondition: []CustomResourceDefinitionCondition{
   119  				{
   120  					Type:               Established,
   121  					Status:             ConditionFalse,
   122  					Reason:             "NotAccepted",
   123  					Message:            "Not accepted",
   124  					LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   125  				},
   126  			},
   127  		},
   128  		{
   129  			name: "test setCRDcondition when two condition",
   130  			crdCondition: []CustomResourceDefinitionCondition{
   131  				{
   132  					Type:               Established,
   133  					Status:             ConditionTrue,
   134  					Reason:             "Accepted",
   135  					Message:            "the initial names have been accepted",
   136  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   137  				},
   138  				{
   139  					Type:               NamesAccepted,
   140  					Status:             ConditionTrue,
   141  					Reason:             "NoConflicts",
   142  					Message:            "no conflicts found",
   143  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   144  				},
   145  			},
   146  			newCondition: CustomResourceDefinitionCondition{
   147  				Type:               NamesAccepted,
   148  				Status:             ConditionFalse,
   149  				Reason:             "Conflicts",
   150  				Message:            "conflicts found",
   151  				LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   152  			},
   153  			expectedcrdCondition: []CustomResourceDefinitionCondition{
   154  				{
   155  					Type:               Established,
   156  					Status:             ConditionTrue,
   157  					Reason:             "Accepted",
   158  					Message:            "the initial names have been accepted",
   159  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   160  				},
   161  				{
   162  					Type:               NamesAccepted,
   163  					Status:             ConditionFalse,
   164  					Reason:             "Conflicts",
   165  					Message:            "conflicts found",
   166  					LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   167  				},
   168  			},
   169  		},
   170  		{
   171  			name: "test setCRDcondition when condition needs to be appended",
   172  			crdCondition: []CustomResourceDefinitionCondition{
   173  				{
   174  					Type:               Established,
   175  					Status:             ConditionTrue,
   176  					Reason:             "Accepted",
   177  					Message:            "the initial names have been accepted",
   178  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   179  				},
   180  			},
   181  			newCondition: CustomResourceDefinitionCondition{
   182  				Type:               Terminating,
   183  				Status:             ConditionFalse,
   184  				Reason:             "NeverEstablished",
   185  				Message:            "resource was never established",
   186  				LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
   187  			},
   188  			expectedcrdCondition: []CustomResourceDefinitionCondition{
   189  				{
   190  					Type:               Established,
   191  					Status:             ConditionTrue,
   192  					Reason:             "Accepted",
   193  					Message:            "the initial names have been accepted",
   194  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   195  				},
   196  				{
   197  					Type:               Terminating,
   198  					Status:             ConditionFalse,
   199  					Reason:             "NeverEstablished",
   200  					Message:            "resource was never established",
   201  					LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
   202  				},
   203  			},
   204  		},
   205  		{
   206  			name: "set new condition which doesn't have lastTransitionTime set",
   207  			crdCondition: []CustomResourceDefinitionCondition{
   208  				{
   209  					Type:               Established,
   210  					Status:             ConditionTrue,
   211  					Reason:             "Accepted",
   212  					Message:            "the initial names have been accepted",
   213  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   214  				},
   215  			},
   216  			newCondition: CustomResourceDefinitionCondition{
   217  				Type:    Established,
   218  				Status:  ConditionFalse,
   219  				Reason:  "NotAccepted",
   220  				Message: "Not accepted",
   221  			},
   222  			expectedcrdCondition: []CustomResourceDefinitionCondition{
   223  				{
   224  					Type:               Established,
   225  					Status:             ConditionFalse,
   226  					Reason:             "NotAccepted",
   227  					Message:            "Not accepted",
   228  					LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   229  				},
   230  			},
   231  		},
   232  		{
   233  			name: "append new condition which doesn't have lastTransitionTime set",
   234  			crdCondition: []CustomResourceDefinitionCondition{
   235  				{
   236  					Type:               Established,
   237  					Status:             ConditionTrue,
   238  					Reason:             "Accepted",
   239  					Message:            "the initial names have been accepted",
   240  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   241  				},
   242  			},
   243  			newCondition: CustomResourceDefinitionCondition{
   244  				Type:    Terminating,
   245  				Status:  ConditionFalse,
   246  				Reason:  "NeverEstablished",
   247  				Message: "resource was never established",
   248  			},
   249  			expectedcrdCondition: []CustomResourceDefinitionCondition{
   250  				{
   251  					Type:               Established,
   252  					Status:             ConditionTrue,
   253  					Reason:             "Accepted",
   254  					Message:            "the initial names have been accepted",
   255  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   256  				},
   257  				{
   258  					Type:               Terminating,
   259  					Status:             ConditionFalse,
   260  					Reason:             "NeverEstablished",
   261  					Message:            "resource was never established",
   262  					LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
   263  				},
   264  			},
   265  		},
   266  	}
   267  	for _, tc := range tests {
   268  		crd := generateCRDwithCondition(tc.crdCondition)
   269  		SetCRDCondition(crd, tc.newCondition)
   270  		if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
   271  			t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
   272  		}
   273  		for i := range tc.expectedcrdCondition {
   274  			if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
   275  				t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition[i], crd.Status.Conditions[i])
   276  			}
   277  			if crd.Status.Conditions[i].LastTransitionTime.IsZero() {
   278  				t.Errorf("%q/%d lastTransitionTime should not be null: %v", tc.name, i, crd.Status.Conditions[i])
   279  			}
   280  		}
   281  	}
   282  }
   283  
   284  func TestRemoveCRDCondition(t *testing.T) {
   285  	tests := []struct {
   286  		name                 string
   287  		crdCondition         []CustomResourceDefinitionCondition
   288  		conditionType        CustomResourceDefinitionConditionType
   289  		expectedcrdCondition []CustomResourceDefinitionCondition
   290  	}{
   291  		{
   292  			name: "test remove CRDCondition when the conditionType meets",
   293  			crdCondition: []CustomResourceDefinitionCondition{
   294  				{
   295  					Type:               Established,
   296  					Status:             ConditionTrue,
   297  					Reason:             "Accepted",
   298  					Message:            "the initial names have been accepted",
   299  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   300  				},
   301  				{
   302  					Type:               NamesAccepted,
   303  					Status:             ConditionTrue,
   304  					Reason:             "NoConflicts",
   305  					Message:            "no conflicts found",
   306  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   307  				},
   308  			},
   309  			conditionType: NamesAccepted,
   310  			expectedcrdCondition: []CustomResourceDefinitionCondition{
   311  				{
   312  					Type:               Established,
   313  					Status:             ConditionTrue,
   314  					Reason:             "Accepted",
   315  					Message:            "the initial names have been accepted",
   316  					LastTransitionTime: metav1.Date(2011, 1, 2, 0, 0, 0, 0, time.UTC),
   317  				},
   318  			},
   319  		},
   320  		{
   321  			name: "test remove CRDCondition when the conditionType not meets",
   322  			crdCondition: []CustomResourceDefinitionCondition{
   323  				{
   324  					Type:               Established,
   325  					Status:             ConditionTrue,
   326  					Reason:             "Accepted",
   327  					Message:            "the initial names have been accepted",
   328  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   329  				},
   330  				{
   331  					Type:               NamesAccepted,
   332  					Status:             ConditionTrue,
   333  					Reason:             "NoConflicts",
   334  					Message:            "no conflicts found",
   335  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   336  				},
   337  			},
   338  			conditionType: Terminating,
   339  			expectedcrdCondition: []CustomResourceDefinitionCondition{
   340  				{
   341  					Type:               Established,
   342  					Status:             ConditionTrue,
   343  					Reason:             "Accepted",
   344  					Message:            "the initial names have been accepted",
   345  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   346  				},
   347  				{
   348  					Type:               NamesAccepted,
   349  					Status:             ConditionTrue,
   350  					Reason:             "NoConflicts",
   351  					Message:            "no conflicts found",
   352  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   353  				},
   354  			},
   355  		},
   356  	}
   357  	for _, tc := range tests {
   358  		crd := generateCRDwithCondition(tc.crdCondition)
   359  		RemoveCRDCondition(crd, tc.conditionType)
   360  		if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
   361  			t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
   362  		}
   363  		for i := range tc.expectedcrdCondition {
   364  			if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
   365  				t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
   366  			}
   367  		}
   368  	}
   369  }
   370  
   371  func TestIsCRDConditionPresentAndEqual(t *testing.T) {
   372  	tests := []struct {
   373  		name          string
   374  		crdCondition  []CustomResourceDefinitionCondition
   375  		conditionType CustomResourceDefinitionConditionType
   376  		status        ConditionStatus
   377  		expectresult  bool
   378  	}{
   379  		{
   380  			name: "test CRDCondition is not Present",
   381  			crdCondition: []CustomResourceDefinitionCondition{
   382  				{
   383  					Type:               Established,
   384  					Status:             ConditionTrue,
   385  					Reason:             "Accepted",
   386  					Message:            "the initial names have been accepted",
   387  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   388  				},
   389  				{
   390  					Type:               NamesAccepted,
   391  					Status:             ConditionTrue,
   392  					Reason:             "NoConflicts",
   393  					Message:            "no conflicts found",
   394  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   395  				},
   396  			},
   397  			conditionType: Terminating,
   398  			status:        ConditionTrue,
   399  			expectresult:  false,
   400  		},
   401  		{
   402  			name: "test CRDCondition is Present but not Equal",
   403  			crdCondition: []CustomResourceDefinitionCondition{
   404  				{
   405  					Type:               Established,
   406  					Status:             ConditionTrue,
   407  					Reason:             "Accepted",
   408  					Message:            "the initial names have been accepted",
   409  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   410  				},
   411  				{
   412  					Type:               NamesAccepted,
   413  					Status:             ConditionTrue,
   414  					Reason:             "NoConflicts",
   415  					Message:            "no conflicts found",
   416  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   417  				},
   418  			},
   419  			conditionType: Established,
   420  			status:        ConditionFalse,
   421  			expectresult:  false,
   422  		},
   423  		{
   424  			name: "test CRDCondition is Present and Equal",
   425  			crdCondition: []CustomResourceDefinitionCondition{
   426  				{
   427  					Type:               Established,
   428  					Status:             ConditionTrue,
   429  					Reason:             "Accepted",
   430  					Message:            "the initial names have been accepted",
   431  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   432  				},
   433  				{
   434  					Type:               NamesAccepted,
   435  					Status:             ConditionTrue,
   436  					Reason:             "NoConflicts",
   437  					Message:            "no conflicts found",
   438  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   439  				},
   440  			},
   441  			conditionType: NamesAccepted,
   442  			status:        ConditionTrue,
   443  			expectresult:  true,
   444  		},
   445  	}
   446  	for _, tc := range tests {
   447  		crd := generateCRDwithCondition(tc.crdCondition)
   448  		res := IsCRDConditionPresentAndEqual(crd, tc.conditionType, tc.status)
   449  		if res != tc.expectresult {
   450  			t.Errorf("%v expected %t, got %t", tc.name, tc.expectresult, res)
   451  		}
   452  	}
   453  }
   454  
   455  func generateCRDwithCondition(conditions []CustomResourceDefinitionCondition) *CustomResourceDefinition {
   456  	testCRDObjectMeta := metav1.ObjectMeta{
   457  		Name:            "plural.group.com",
   458  		ResourceVersion: "12",
   459  	}
   460  	testCRDSpec := CustomResourceDefinitionSpec{
   461  		Group:   "group.com",
   462  		Version: "version",
   463  		Scope:   ResourceScope("Cluster"),
   464  		Names: CustomResourceDefinitionNames{
   465  			Plural:   "plural",
   466  			Singular: "singular",
   467  			Kind:     "kind",
   468  			ListKind: "listkind",
   469  		},
   470  	}
   471  	testCRDAcceptedNames := CustomResourceDefinitionNames{
   472  		Plural:   "plural",
   473  		Singular: "singular",
   474  		Kind:     "kind",
   475  		ListKind: "listkind",
   476  	}
   477  	return &CustomResourceDefinition{
   478  		ObjectMeta: testCRDObjectMeta,
   479  		Spec:       testCRDSpec,
   480  		Status: CustomResourceDefinitionStatus{
   481  			AcceptedNames: testCRDAcceptedNames,
   482  			Conditions:    conditions,
   483  		},
   484  	}
   485  }
   486  

View as plain text