...

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

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

     1  /*
     2  Copyright 2019 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 apihelpers
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  
    24  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  )
    27  
    28  func TestIsProtectedCommunityGroup(t *testing.T) {
    29  	tests := []struct {
    30  		name string
    31  
    32  		group    string
    33  		expected bool
    34  	}{
    35  		{
    36  			name:     "bare k8s",
    37  			group:    "k8s.io",
    38  			expected: true,
    39  		},
    40  		{
    41  			name:     "bare kube",
    42  			group:    "kubernetes.io",
    43  			expected: true,
    44  		},
    45  		{
    46  			name:     "nested k8s",
    47  			group:    "sigs.k8s.io",
    48  			expected: true,
    49  		},
    50  		{
    51  			name:     "nested kube",
    52  			group:    "sigs.kubernetes.io",
    53  			expected: true,
    54  		},
    55  		{
    56  			name:     "alternative",
    57  			group:    "different.io",
    58  			expected: false,
    59  		},
    60  	}
    61  
    62  	for _, test := range tests {
    63  		t.Run(test.name, func(t *testing.T) {
    64  			actual := IsProtectedCommunityGroup(test.group)
    65  
    66  			if actual != test.expected {
    67  				t.Fatalf("expected %v, got %v", test.expected, actual)
    68  			}
    69  		})
    70  	}
    71  }
    72  
    73  func TestGetAPIApprovalState(t *testing.T) {
    74  	tests := []struct {
    75  		name string
    76  
    77  		annotations map[string]string
    78  		expected    APIApprovalState
    79  	}{
    80  		{
    81  			name:        "bare unapproved",
    82  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "unapproved"},
    83  			expected:    APIApprovalBypassed,
    84  		},
    85  		{
    86  			name:        "unapproved with message",
    87  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "unapproved, experimental-only"},
    88  			expected:    APIApprovalBypassed,
    89  		},
    90  		{
    91  			name:        "mismatched case",
    92  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "Unapproved"},
    93  			expected:    APIApprovalInvalid,
    94  		},
    95  		{
    96  			name:        "empty",
    97  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: ""},
    98  			expected:    APIApprovalMissing,
    99  		},
   100  		{
   101  			name:        "missing",
   102  			annotations: map[string]string{},
   103  			expected:    APIApprovalMissing,
   104  		},
   105  		{
   106  			name:        "url",
   107  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "https://github.com/kubernetes/kubernetes/pull/78458"},
   108  			expected:    APIApproved,
   109  		},
   110  		{
   111  			name:        "url - no scheme",
   112  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "github.com/kubernetes/kubernetes/pull/78458"},
   113  			expected:    APIApprovalInvalid,
   114  		},
   115  		{
   116  			name:        "url - no host",
   117  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "http:///kubernetes/kubernetes/pull/78458"},
   118  			expected:    APIApprovalInvalid,
   119  		},
   120  		{
   121  			name:        "url - just path",
   122  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "/"},
   123  			expected:    APIApprovalInvalid,
   124  		},
   125  		{
   126  			name:        "missing scheme",
   127  			annotations: map[string]string{apiextensionsv1.KubeAPIApprovedAnnotation: "github.com/kubernetes/kubernetes/pull/78458"},
   128  			expected:    APIApprovalInvalid,
   129  		},
   130  	}
   131  
   132  	for _, test := range tests {
   133  		t.Run(test.name, func(t *testing.T) {
   134  			actual, _ := GetAPIApprovalState(test.annotations)
   135  
   136  			if actual != test.expected {
   137  				t.Fatalf("expected %v, got %v", test.expected, actual)
   138  			}
   139  		})
   140  	}
   141  }
   142  
   143  func TestCRDHasFinalizer(t *testing.T) {
   144  	tests := []struct {
   145  		name             string
   146  		crd              *apiextensionsv1.CustomResourceDefinition
   147  		finalizerToCheck string
   148  
   149  		expected bool
   150  	}{
   151  		{
   152  			name: "missing",
   153  			crd: &apiextensionsv1.CustomResourceDefinition{
   154  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
   155  			},
   156  			finalizerToCheck: "it",
   157  			expected:         false,
   158  		},
   159  		{
   160  			name: "present",
   161  			crd: &apiextensionsv1.CustomResourceDefinition{
   162  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
   163  			},
   164  			finalizerToCheck: "it",
   165  			expected:         true,
   166  		},
   167  	}
   168  	for _, tc := range tests {
   169  		actual := CRDHasFinalizer(tc.crd, tc.finalizerToCheck)
   170  		if tc.expected != actual {
   171  			t.Errorf("%v expected %v, got %v", tc.name, tc.expected, actual)
   172  		}
   173  	}
   174  }
   175  
   176  func TestCRDRemoveFinalizer(t *testing.T) {
   177  	tests := []struct {
   178  		name             string
   179  		crd              *apiextensionsv1.CustomResourceDefinition
   180  		finalizerToCheck string
   181  
   182  		expected []string
   183  	}{
   184  		{
   185  			name: "missing",
   186  			crd: &apiextensionsv1.CustomResourceDefinition{
   187  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
   188  			},
   189  			finalizerToCheck: "it",
   190  			expected:         []string{"not-it"},
   191  		},
   192  		{
   193  			name: "present",
   194  			crd: &apiextensionsv1.CustomResourceDefinition{
   195  				ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
   196  			},
   197  			finalizerToCheck: "it",
   198  			expected:         []string{"not-it"},
   199  		},
   200  	}
   201  	for _, tc := range tests {
   202  		CRDRemoveFinalizer(tc.crd, tc.finalizerToCheck)
   203  		if !reflect.DeepEqual(tc.expected, tc.crd.Finalizers) {
   204  			t.Errorf("%v expected %v, got %v", tc.name, tc.expected, tc.crd.Finalizers)
   205  		}
   206  	}
   207  }
   208  
   209  func TestSetCRDCondition(t *testing.T) {
   210  	tests := []struct {
   211  		name                 string
   212  		crdCondition         []apiextensionsv1.CustomResourceDefinitionCondition
   213  		newCondition         apiextensionsv1.CustomResourceDefinitionCondition
   214  		expectedcrdCondition []apiextensionsv1.CustomResourceDefinitionCondition
   215  	}{
   216  		{
   217  			name: "test setCRDcondition when one condition",
   218  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   219  				{
   220  					Type:               apiextensionsv1.Established,
   221  					Status:             apiextensionsv1.ConditionTrue,
   222  					Reason:             "Accepted",
   223  					Message:            "the initial names have been accepted",
   224  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   225  				},
   226  			},
   227  			newCondition: apiextensionsv1.CustomResourceDefinitionCondition{
   228  				Type:               apiextensionsv1.Established,
   229  				Status:             apiextensionsv1.ConditionFalse,
   230  				Reason:             "NotAccepted",
   231  				Message:            "Not accepted",
   232  				LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   233  			},
   234  			expectedcrdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   235  				{
   236  					Type:               apiextensionsv1.Established,
   237  					Status:             apiextensionsv1.ConditionFalse,
   238  					Reason:             "NotAccepted",
   239  					Message:            "Not accepted",
   240  					LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   241  				},
   242  			},
   243  		},
   244  		{
   245  			name: "test setCRDcondition when two condition",
   246  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   247  				{
   248  					Type:               apiextensionsv1.Established,
   249  					Status:             apiextensionsv1.ConditionTrue,
   250  					Reason:             "Accepted",
   251  					Message:            "the initial names have been accepted",
   252  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   253  				},
   254  				{
   255  					Type:               apiextensionsv1.NamesAccepted,
   256  					Status:             apiextensionsv1.ConditionTrue,
   257  					Reason:             "NoConflicts",
   258  					Message:            "no conflicts found",
   259  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   260  				},
   261  			},
   262  			newCondition: apiextensionsv1.CustomResourceDefinitionCondition{
   263  				Type:               apiextensionsv1.NamesAccepted,
   264  				Status:             apiextensionsv1.ConditionFalse,
   265  				Reason:             "Conflicts",
   266  				Message:            "conflicts found",
   267  				LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   268  			},
   269  			expectedcrdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   270  				{
   271  					Type:               apiextensionsv1.Established,
   272  					Status:             apiextensionsv1.ConditionTrue,
   273  					Reason:             "Accepted",
   274  					Message:            "the initial names have been accepted",
   275  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   276  				},
   277  				{
   278  					Type:               apiextensionsv1.NamesAccepted,
   279  					Status:             apiextensionsv1.ConditionFalse,
   280  					Reason:             "Conflicts",
   281  					Message:            "conflicts found",
   282  					LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   283  				},
   284  			},
   285  		},
   286  		{
   287  			name: "test setCRDcondition when condition needs to be appended",
   288  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   289  				{
   290  					Type:               apiextensionsv1.Established,
   291  					Status:             apiextensionsv1.ConditionTrue,
   292  					Reason:             "Accepted",
   293  					Message:            "the initial names have been accepted",
   294  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   295  				},
   296  			},
   297  			newCondition: apiextensionsv1.CustomResourceDefinitionCondition{
   298  				Type:               apiextensionsv1.Terminating,
   299  				Status:             apiextensionsv1.ConditionFalse,
   300  				Reason:             "Neverapiextensionsv1.Established",
   301  				Message:            "resource was never apiextensionsv1.Established",
   302  				LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
   303  			},
   304  			expectedcrdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   305  				{
   306  					Type:               apiextensionsv1.Established,
   307  					Status:             apiextensionsv1.ConditionTrue,
   308  					Reason:             "Accepted",
   309  					Message:            "the initial names have been accepted",
   310  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   311  				},
   312  				{
   313  					Type:               apiextensionsv1.Terminating,
   314  					Status:             apiextensionsv1.ConditionFalse,
   315  					Reason:             "Neverapiextensionsv1.Established",
   316  					Message:            "resource was never apiextensionsv1.Established",
   317  					LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
   318  				},
   319  			},
   320  		},
   321  		{
   322  			name: "set new condition which doesn't have lastTransitionTime set",
   323  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   324  				{
   325  					Type:               apiextensionsv1.Established,
   326  					Status:             apiextensionsv1.ConditionTrue,
   327  					Reason:             "Accepted",
   328  					Message:            "the initial names have been accepted",
   329  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   330  				},
   331  			},
   332  			newCondition: apiextensionsv1.CustomResourceDefinitionCondition{
   333  				Type:    apiextensionsv1.Established,
   334  				Status:  apiextensionsv1.ConditionFalse,
   335  				Reason:  "NotAccepted",
   336  				Message: "Not accepted",
   337  			},
   338  			expectedcrdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   339  				{
   340  					Type:               apiextensionsv1.Established,
   341  					Status:             apiextensionsv1.ConditionFalse,
   342  					Reason:             "NotAccepted",
   343  					Message:            "Not accepted",
   344  					LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
   345  				},
   346  			},
   347  		},
   348  		{
   349  			name: "append new condition which doesn't have lastTransitionTime set",
   350  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   351  				{
   352  					Type:               apiextensionsv1.Established,
   353  					Status:             apiextensionsv1.ConditionTrue,
   354  					Reason:             "Accepted",
   355  					Message:            "the initial names have been accepted",
   356  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   357  				},
   358  			},
   359  			newCondition: apiextensionsv1.CustomResourceDefinitionCondition{
   360  				Type:    apiextensionsv1.Terminating,
   361  				Status:  apiextensionsv1.ConditionFalse,
   362  				Reason:  "Neverapiextensionsv1.Established",
   363  				Message: "resource was never apiextensionsv1.Established",
   364  			},
   365  			expectedcrdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   366  				{
   367  					Type:               apiextensionsv1.Established,
   368  					Status:             apiextensionsv1.ConditionTrue,
   369  					Reason:             "Accepted",
   370  					Message:            "the initial names have been accepted",
   371  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   372  				},
   373  				{
   374  					Type:               apiextensionsv1.Terminating,
   375  					Status:             apiextensionsv1.ConditionFalse,
   376  					Reason:             "Neverapiextensionsv1.Established",
   377  					Message:            "resource was never apiextensionsv1.Established",
   378  					LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
   379  				},
   380  			},
   381  		},
   382  	}
   383  	for _, tc := range tests {
   384  		crd := generateCRDwithCondition(tc.crdCondition)
   385  		SetCRDCondition(crd, tc.newCondition)
   386  		if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
   387  			t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
   388  		}
   389  		for i := range tc.expectedcrdCondition {
   390  			if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
   391  				t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition[i], crd.Status.Conditions[i])
   392  			}
   393  			if crd.Status.Conditions[i].LastTransitionTime.IsZero() {
   394  				t.Errorf("%q/%d lastTransitionTime should not be null: %v", tc.name, i, crd.Status.Conditions[i])
   395  			}
   396  		}
   397  	}
   398  }
   399  
   400  func TestRemoveCRDCondition(t *testing.T) {
   401  	tests := []struct {
   402  		name                 string
   403  		crdCondition         []apiextensionsv1.CustomResourceDefinitionCondition
   404  		conditionType        apiextensionsv1.CustomResourceDefinitionConditionType
   405  		expectedcrdCondition []apiextensionsv1.CustomResourceDefinitionCondition
   406  	}{
   407  		{
   408  			name: "test remove CRDCondition when the conditionType meets",
   409  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   410  				{
   411  					Type:               apiextensionsv1.Established,
   412  					Status:             apiextensionsv1.ConditionTrue,
   413  					Reason:             "Accepted",
   414  					Message:            "the initial names have been accepted",
   415  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   416  				},
   417  				{
   418  					Type:               apiextensionsv1.NamesAccepted,
   419  					Status:             apiextensionsv1.ConditionTrue,
   420  					Reason:             "NoConflicts",
   421  					Message:            "no conflicts found",
   422  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   423  				},
   424  			},
   425  			conditionType: apiextensionsv1.NamesAccepted,
   426  			expectedcrdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   427  				{
   428  					Type:               apiextensionsv1.Established,
   429  					Status:             apiextensionsv1.ConditionTrue,
   430  					Reason:             "Accepted",
   431  					Message:            "the initial names have been accepted",
   432  					LastTransitionTime: metav1.Date(2011, 1, 2, 0, 0, 0, 0, time.UTC),
   433  				},
   434  			},
   435  		},
   436  		{
   437  			name: "test remove CRDCondition when the conditionType not meets",
   438  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   439  				{
   440  					Type:               apiextensionsv1.Established,
   441  					Status:             apiextensionsv1.ConditionTrue,
   442  					Reason:             "Accepted",
   443  					Message:            "the initial names have been accepted",
   444  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   445  				},
   446  				{
   447  					Type:               apiextensionsv1.NamesAccepted,
   448  					Status:             apiextensionsv1.ConditionTrue,
   449  					Reason:             "NoConflicts",
   450  					Message:            "no conflicts found",
   451  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   452  				},
   453  			},
   454  			conditionType: apiextensionsv1.Terminating,
   455  			expectedcrdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   456  				{
   457  					Type:               apiextensionsv1.Established,
   458  					Status:             apiextensionsv1.ConditionTrue,
   459  					Reason:             "Accepted",
   460  					Message:            "the initial names have been accepted",
   461  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   462  				},
   463  				{
   464  					Type:               apiextensionsv1.NamesAccepted,
   465  					Status:             apiextensionsv1.ConditionTrue,
   466  					Reason:             "NoConflicts",
   467  					Message:            "no conflicts found",
   468  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   469  				},
   470  			},
   471  		},
   472  	}
   473  	for _, tc := range tests {
   474  		crd := generateCRDwithCondition(tc.crdCondition)
   475  		RemoveCRDCondition(crd, tc.conditionType)
   476  		if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
   477  			t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
   478  		}
   479  		for i := range tc.expectedcrdCondition {
   480  			if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
   481  				t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
   482  			}
   483  		}
   484  	}
   485  }
   486  
   487  func TestIsCRDConditionPresentAndEqual(t *testing.T) {
   488  	tests := []struct {
   489  		name          string
   490  		crdCondition  []apiextensionsv1.CustomResourceDefinitionCondition
   491  		conditionType apiextensionsv1.CustomResourceDefinitionConditionType
   492  		status        apiextensionsv1.ConditionStatus
   493  		expectresult  bool
   494  	}{
   495  		{
   496  			name: "test CRDCondition is not Present",
   497  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   498  				{
   499  					Type:               apiextensionsv1.Established,
   500  					Status:             apiextensionsv1.ConditionTrue,
   501  					Reason:             "Accepted",
   502  					Message:            "the initial names have been accepted",
   503  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   504  				},
   505  				{
   506  					Type:               apiextensionsv1.NamesAccepted,
   507  					Status:             apiextensionsv1.ConditionTrue,
   508  					Reason:             "NoConflicts",
   509  					Message:            "no conflicts found",
   510  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   511  				},
   512  			},
   513  			conditionType: apiextensionsv1.Terminating,
   514  			status:        apiextensionsv1.ConditionTrue,
   515  			expectresult:  false,
   516  		},
   517  		{
   518  			name: "test CRDCondition is Present but not Equal",
   519  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   520  				{
   521  					Type:               apiextensionsv1.Established,
   522  					Status:             apiextensionsv1.ConditionTrue,
   523  					Reason:             "Accepted",
   524  					Message:            "the initial names have been accepted",
   525  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   526  				},
   527  				{
   528  					Type:               apiextensionsv1.NamesAccepted,
   529  					Status:             apiextensionsv1.ConditionTrue,
   530  					Reason:             "NoConflicts",
   531  					Message:            "no conflicts found",
   532  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   533  				},
   534  			},
   535  			conditionType: apiextensionsv1.Established,
   536  			status:        apiextensionsv1.ConditionFalse,
   537  			expectresult:  false,
   538  		},
   539  		{
   540  			name: "test CRDCondition is Present and Equal",
   541  			crdCondition: []apiextensionsv1.CustomResourceDefinitionCondition{
   542  				{
   543  					Type:               apiextensionsv1.Established,
   544  					Status:             apiextensionsv1.ConditionTrue,
   545  					Reason:             "Accepted",
   546  					Message:            "the initial names have been accepted",
   547  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   548  				},
   549  				{
   550  					Type:               apiextensionsv1.NamesAccepted,
   551  					Status:             apiextensionsv1.ConditionTrue,
   552  					Reason:             "NoConflicts",
   553  					Message:            "no conflicts found",
   554  					LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
   555  				},
   556  			},
   557  			conditionType: apiextensionsv1.NamesAccepted,
   558  			status:        apiextensionsv1.ConditionTrue,
   559  			expectresult:  true,
   560  		},
   561  	}
   562  	for _, tc := range tests {
   563  		crd := generateCRDwithCondition(tc.crdCondition)
   564  		res := IsCRDConditionPresentAndEqual(crd, tc.conditionType, tc.status)
   565  		if res != tc.expectresult {
   566  			t.Errorf("%v expected %t, got %t", tc.name, tc.expectresult, res)
   567  		}
   568  	}
   569  }
   570  
   571  func generateCRDwithCondition(conditions []apiextensionsv1.CustomResourceDefinitionCondition) *apiextensionsv1.CustomResourceDefinition {
   572  	testCRDObjectMeta := metav1.ObjectMeta{
   573  		Name:            "plural.group.com",
   574  		ResourceVersion: "12",
   575  	}
   576  	testCRDSpec := apiextensionsv1.CustomResourceDefinitionSpec{
   577  		Group: "group.com",
   578  		Names: apiextensionsv1.CustomResourceDefinitionNames{
   579  			Plural:   "plural",
   580  			Singular: "singular",
   581  			Kind:     "kind",
   582  			ListKind: "listkind",
   583  		},
   584  	}
   585  	testCRDAcceptedNames := apiextensionsv1.CustomResourceDefinitionNames{
   586  		Plural:   "plural",
   587  		Singular: "singular",
   588  		Kind:     "kind",
   589  		ListKind: "listkind",
   590  	}
   591  	return &apiextensionsv1.CustomResourceDefinition{
   592  		ObjectMeta: testCRDObjectMeta,
   593  		Spec:       testCRDSpec,
   594  		Status: apiextensionsv1.CustomResourceDefinitionStatus{
   595  			AcceptedNames: testCRDAcceptedNames,
   596  			Conditions:    conditions,
   597  		},
   598  	}
   599  }
   600  

View as plain text