...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient/idempotency_test.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient

     1  /*
     2  Copyright 2018 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 apiclient
    18  
    19  import (
    20  	"context"
    21  	"os"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/pkg/errors"
    27  
    28  	apps "k8s.io/api/apps/v1"
    29  	v1 "k8s.io/api/core/v1"
    30  	rbac "k8s.io/api/rbac/v1"
    31  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	"k8s.io/apimachinery/pkg/runtime"
    34  	"k8s.io/apimachinery/pkg/runtime/schema"
    35  	clientsetfake "k8s.io/client-go/kubernetes/fake"
    36  	clientgotesting "k8s.io/client-go/testing"
    37  
    38  	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
    39  )
    40  
    41  func TestMain(m *testing.M) {
    42  	// Override the default interval and timeouts during tests
    43  	defaultRetryInterval := apiCallRetryInterval
    44  	apiCallRetryInterval = time.Millisecond * 50
    45  
    46  	defaultTimeouts := kubeadmapi.GetActiveTimeouts()
    47  	defaultAPICallTimeout := defaultTimeouts.KubernetesAPICall
    48  	defaultTimeouts.KubernetesAPICall = &metav1.Duration{Duration: apiCallRetryInterval}
    49  
    50  	exitVal := m.Run()
    51  
    52  	// Restore the default interval and timeouts
    53  	apiCallRetryInterval = defaultRetryInterval
    54  	defaultTimeouts.KubernetesAPICall = defaultAPICallTimeout
    55  
    56  	os.Exit(exitVal)
    57  }
    58  
    59  func TestCreateOrUpdateConfigMap(t *testing.T) {
    60  	tests := []struct {
    61  		name          string
    62  		setupClient   func(*clientsetfake.Clientset)
    63  		expectedError bool
    64  	}{
    65  		{
    66  			name: "create configmap success",
    67  			setupClient: func(client *clientsetfake.Clientset) {
    68  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
    69  					return true, nil, nil
    70  				})
    71  			},
    72  			expectedError: false,
    73  		},
    74  		{
    75  			name: "create configmap returns error",
    76  			setupClient: func(client *clientsetfake.Clientset) {
    77  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
    78  					return true, nil, errors.New("unknown error")
    79  				})
    80  			},
    81  			expectedError: true,
    82  		},
    83  		{
    84  			name: "configmap exists, update it",
    85  			setupClient: func(client *clientsetfake.Clientset) {
    86  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
    87  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
    88  				})
    89  				client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
    90  					return true, nil, nil
    91  				})
    92  			},
    93  			expectedError: false,
    94  		},
    95  		{
    96  			name: "configmap exists, update error",
    97  			setupClient: func(client *clientsetfake.Clientset) {
    98  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
    99  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   100  				})
   101  				client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   102  					return true, nil, errors.New("")
   103  				})
   104  			},
   105  			expectedError: true,
   106  		},
   107  	}
   108  
   109  	for _, tc := range tests {
   110  		t.Run(tc.name, func(t *testing.T) {
   111  			client := clientsetfake.NewSimpleClientset()
   112  			tc.setupClient(client)
   113  			err := CreateOrUpdateConfigMap(client, &v1.ConfigMap{})
   114  			if (err != nil) != tc.expectedError {
   115  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   116  			}
   117  		})
   118  	}
   119  }
   120  
   121  func TestCreateOrMutateConfigMap(t *testing.T) {
   122  	tests := []struct {
   123  		name          string
   124  		setupClient   func(*clientsetfake.Clientset)
   125  		mutator       func(*v1.ConfigMap) error
   126  		expectedError bool
   127  	}{
   128  		{
   129  			name: "create configmap",
   130  			setupClient: func(client *clientsetfake.Clientset) {
   131  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   132  					return true, nil, nil
   133  				})
   134  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   135  					return true, nil, nil
   136  				})
   137  				client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   138  					return true, nil, nil
   139  				})
   140  			},
   141  			expectedError: false,
   142  		},
   143  		{
   144  			name: "create configmap error",
   145  			setupClient: func(client *clientsetfake.Clientset) {
   146  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   147  					return true, nil, errors.New("")
   148  				})
   149  			},
   150  			expectedError: true,
   151  		},
   152  		{
   153  			name: "configmap exists, mutate returns error",
   154  			setupClient: func(client *clientsetfake.Clientset) {
   155  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   156  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   157  				})
   158  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   159  					return true, &v1.ConfigMap{}, nil
   160  				})
   161  			},
   162  			mutator:       func(*v1.ConfigMap) error { return errors.New("") },
   163  			expectedError: true,
   164  		},
   165  		{
   166  			name: "configmap exists, get returns error",
   167  			setupClient: func(client *clientsetfake.Clientset) {
   168  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   169  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   170  				})
   171  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   172  					return true, nil, errors.New("")
   173  				})
   174  			},
   175  			expectedError: true,
   176  		},
   177  		{
   178  			name: "configmap exists, mutate returns error",
   179  			setupClient: func(client *clientsetfake.Clientset) {
   180  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   181  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   182  				})
   183  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   184  					return true, &v1.ConfigMap{}, nil
   185  				})
   186  				client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   187  					return true, nil, errors.New("")
   188  				})
   189  			},
   190  			mutator:       func(*v1.ConfigMap) error { return nil },
   191  			expectedError: true,
   192  		},
   193  	}
   194  
   195  	for _, tc := range tests {
   196  		t.Run(tc.name, func(t *testing.T) {
   197  			client := clientsetfake.NewSimpleClientset()
   198  			tc.setupClient(client)
   199  			err := CreateOrMutateConfigMap(client, &v1.ConfigMap{}, tc.mutator)
   200  			if (err != nil) != tc.expectedError {
   201  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   202  			}
   203  		})
   204  	}
   205  }
   206  
   207  func TestCreateOrRetainConfigMap(t *testing.T) {
   208  	tests := []struct {
   209  		name          string
   210  		setupClient   func(*clientsetfake.Clientset)
   211  		expectedError bool
   212  	}{
   213  		{
   214  			name: "configmap exists",
   215  			setupClient: func(client *clientsetfake.Clientset) {
   216  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   217  					return true, &v1.ConfigMap{}, nil
   218  				})
   219  			},
   220  			expectedError: false,
   221  		},
   222  		{
   223  			name: "configmap get returns an error",
   224  			setupClient: func(client *clientsetfake.Clientset) {
   225  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   226  					return true, nil, errors.New("")
   227  				})
   228  			},
   229  			expectedError: true,
   230  		},
   231  		{
   232  			name: "configmap is not found, create it",
   233  			setupClient: func(client *clientsetfake.Clientset) {
   234  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   235  					return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name")
   236  				})
   237  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   238  					return true, nil, nil
   239  				})
   240  			},
   241  			expectedError: false,
   242  		},
   243  		{
   244  			name: "configmap is not found, create returns an error",
   245  			setupClient: func(client *clientsetfake.Clientset) {
   246  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   247  					return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name")
   248  				})
   249  				client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
   250  					return true, nil, errors.New("")
   251  				})
   252  			},
   253  			expectedError: true,
   254  		},
   255  	}
   256  
   257  	for _, tc := range tests {
   258  		t.Run(tc.name, func(t *testing.T) {
   259  			client := clientsetfake.NewSimpleClientset()
   260  			tc.setupClient(client)
   261  			err := CreateOrRetainConfigMap(client, &v1.ConfigMap{}, "some-cm")
   262  			if (err != nil) != tc.expectedError {
   263  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   264  			}
   265  		})
   266  	}
   267  }
   268  
   269  func TestCreateOrUpdateSecret(t *testing.T) {
   270  	tests := []struct {
   271  		name          string
   272  		setupClient   func(*clientsetfake.Clientset)
   273  		expectedError bool
   274  	}{
   275  		{
   276  			name: "create secret success",
   277  			setupClient: func(client *clientsetfake.Clientset) {
   278  				client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   279  					return true, nil, nil
   280  				})
   281  			},
   282  			expectedError: false,
   283  		},
   284  		{
   285  			name: "create secret returns error",
   286  			setupClient: func(client *clientsetfake.Clientset) {
   287  				client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   288  					return true, nil, errors.New("unknown error")
   289  				})
   290  			},
   291  			expectedError: true,
   292  		},
   293  		{
   294  			name: "secret exists, update it",
   295  			setupClient: func(client *clientsetfake.Clientset) {
   296  				client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   297  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   298  				})
   299  				client.PrependReactor("update", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   300  					return true, nil, nil
   301  				})
   302  			},
   303  			expectedError: false,
   304  		},
   305  		{
   306  			name: "secret exists, update error",
   307  			setupClient: func(client *clientsetfake.Clientset) {
   308  				client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   309  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   310  				})
   311  				client.PrependReactor("update", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   312  					return true, nil, errors.New("")
   313  				})
   314  			},
   315  			expectedError: true,
   316  		},
   317  	}
   318  
   319  	for _, tc := range tests {
   320  		t.Run(tc.name, func(t *testing.T) {
   321  			client := clientsetfake.NewSimpleClientset()
   322  			tc.setupClient(client)
   323  			err := CreateOrUpdateSecret(client, &v1.Secret{})
   324  			if (err != nil) != tc.expectedError {
   325  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   326  			}
   327  		})
   328  	}
   329  }
   330  
   331  func TestCreateOrUpdateServiceAccount(t *testing.T) {
   332  	tests := []struct {
   333  		name          string
   334  		setupClient   func(*clientsetfake.Clientset)
   335  		expectedError bool
   336  	}{
   337  		{
   338  			name: "create serviceaccount success",
   339  			setupClient: func(client *clientsetfake.Clientset) {
   340  				client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) {
   341  					return true, nil, nil
   342  				})
   343  			},
   344  			expectedError: false,
   345  		},
   346  		{
   347  			name: "create serviceaccount returns error",
   348  			setupClient: func(client *clientsetfake.Clientset) {
   349  				client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) {
   350  					return true, nil, errors.New("unknown error")
   351  				})
   352  			},
   353  			expectedError: true,
   354  		},
   355  		{
   356  			name: "serviceaccount exists, update it",
   357  			setupClient: func(client *clientsetfake.Clientset) {
   358  				client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) {
   359  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   360  				})
   361  				client.PrependReactor("update", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) {
   362  					return true, nil, nil
   363  				})
   364  			},
   365  			expectedError: false,
   366  		},
   367  		{
   368  			name: "serviceaccount exists, update error",
   369  			setupClient: func(client *clientsetfake.Clientset) {
   370  				client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) {
   371  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   372  				})
   373  				client.PrependReactor("update", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) {
   374  					return true, nil, errors.New("")
   375  				})
   376  			},
   377  			expectedError: true,
   378  		},
   379  	}
   380  
   381  	for _, tc := range tests {
   382  		t.Run(tc.name, func(t *testing.T) {
   383  			client := clientsetfake.NewSimpleClientset()
   384  			tc.setupClient(client)
   385  			err := CreateOrUpdateServiceAccount(client, &v1.ServiceAccount{})
   386  			if (err != nil) != tc.expectedError {
   387  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   388  			}
   389  		})
   390  	}
   391  }
   392  
   393  func TestCreateOrUpdateDeployment(t *testing.T) {
   394  	tests := []struct {
   395  		name          string
   396  		setupClient   func(*clientsetfake.Clientset)
   397  		expectedError bool
   398  	}{
   399  		{
   400  			name: "create deployment success",
   401  			setupClient: func(client *clientsetfake.Clientset) {
   402  				client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   403  					return true, nil, nil
   404  				})
   405  			},
   406  			expectedError: false,
   407  		},
   408  		{
   409  			name: "create deployment returns error",
   410  			setupClient: func(client *clientsetfake.Clientset) {
   411  				client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   412  					return true, nil, errors.New("unknown error")
   413  				})
   414  			},
   415  			expectedError: true,
   416  		},
   417  		{
   418  			name: "deployment exists, update it",
   419  			setupClient: func(client *clientsetfake.Clientset) {
   420  				client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   421  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   422  				})
   423  				client.PrependReactor("update", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   424  					return true, nil, nil
   425  				})
   426  			},
   427  			expectedError: false,
   428  		},
   429  		{
   430  			name: "deployment exists, update error",
   431  			setupClient: func(client *clientsetfake.Clientset) {
   432  				client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   433  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   434  				})
   435  				client.PrependReactor("update", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   436  					return true, nil, errors.New("")
   437  				})
   438  			},
   439  			expectedError: true,
   440  		},
   441  	}
   442  
   443  	for _, tc := range tests {
   444  		t.Run(tc.name, func(t *testing.T) {
   445  			client := clientsetfake.NewSimpleClientset()
   446  			tc.setupClient(client)
   447  			err := CreateOrUpdateDeployment(client, &apps.Deployment{})
   448  			if (err != nil) != tc.expectedError {
   449  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   450  			}
   451  		})
   452  	}
   453  }
   454  
   455  func TestCreateOrRetainDeployment(t *testing.T) {
   456  	tests := []struct {
   457  		name          string
   458  		setupClient   func(*clientsetfake.Clientset)
   459  		expectedError bool
   460  	}{
   461  		{
   462  			name: "deployment exists",
   463  			setupClient: func(client *clientsetfake.Clientset) {
   464  				client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   465  					return true, &apps.Deployment{}, nil
   466  				})
   467  			},
   468  			expectedError: false,
   469  		},
   470  		{
   471  			name: "deployment get returns an error",
   472  			setupClient: func(client *clientsetfake.Clientset) {
   473  				client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   474  					return true, nil, errors.New("")
   475  				})
   476  			},
   477  			expectedError: true,
   478  		},
   479  		{
   480  			name: "deployment is not found, create it",
   481  			setupClient: func(client *clientsetfake.Clientset) {
   482  				client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   483  					return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name")
   484  				})
   485  				client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   486  					return true, nil, nil
   487  				})
   488  			},
   489  			expectedError: false,
   490  		},
   491  		{
   492  			name: "deployment is not found, create returns an error",
   493  			setupClient: func(client *clientsetfake.Clientset) {
   494  				client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   495  					return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name")
   496  				})
   497  				client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) {
   498  					return true, nil, errors.New("")
   499  				})
   500  			},
   501  			expectedError: true,
   502  		},
   503  	}
   504  
   505  	for _, tc := range tests {
   506  		t.Run(tc.name, func(t *testing.T) {
   507  			client := clientsetfake.NewSimpleClientset()
   508  			tc.setupClient(client)
   509  			err := CreateOrRetainDeployment(client, &apps.Deployment{}, "some-deployment")
   510  			if (err != nil) != tc.expectedError {
   511  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   512  			}
   513  		})
   514  	}
   515  }
   516  
   517  func TestCreateOrUpdateDaemonSet(t *testing.T) {
   518  	tests := []struct {
   519  		name          string
   520  		setupClient   func(*clientsetfake.Clientset)
   521  		expectedError bool
   522  	}{
   523  		{
   524  			name: "create daemonset success",
   525  			setupClient: func(client *clientsetfake.Clientset) {
   526  				client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   527  					return true, nil, nil
   528  				})
   529  			},
   530  			expectedError: false,
   531  		},
   532  		{
   533  			name: "create daemonset returns error",
   534  			setupClient: func(client *clientsetfake.Clientset) {
   535  				client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   536  					return true, nil, errors.New("unknown error")
   537  				})
   538  			},
   539  			expectedError: true,
   540  		},
   541  		{
   542  			name: "daemonset exists, update it",
   543  			setupClient: func(client *clientsetfake.Clientset) {
   544  				client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   545  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   546  				})
   547  				client.PrependReactor("update", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   548  					return true, nil, nil
   549  				})
   550  			},
   551  			expectedError: false,
   552  		},
   553  		{
   554  			name: "daemonset exists, update error",
   555  			setupClient: func(client *clientsetfake.Clientset) {
   556  				client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   557  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   558  				})
   559  				client.PrependReactor("update", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) {
   560  					return true, nil, errors.New("")
   561  				})
   562  			},
   563  			expectedError: true,
   564  		},
   565  	}
   566  
   567  	for _, tc := range tests {
   568  		t.Run(tc.name, func(t *testing.T) {
   569  			client := clientsetfake.NewSimpleClientset()
   570  			tc.setupClient(client)
   571  			err := CreateOrUpdateDaemonSet(client, &apps.DaemonSet{})
   572  			if (err != nil) != tc.expectedError {
   573  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   574  			}
   575  		})
   576  	}
   577  }
   578  
   579  func TestCreateOrUpdateRole(t *testing.T) {
   580  	tests := []struct {
   581  		name          string
   582  		setupClient   func(*clientsetfake.Clientset)
   583  		expectedError bool
   584  	}{
   585  		{
   586  			name: "create role success",
   587  			setupClient: func(client *clientsetfake.Clientset) {
   588  				client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   589  					return true, nil, nil
   590  				})
   591  			},
   592  			expectedError: false,
   593  		},
   594  		{
   595  			name: "create role returns error",
   596  			setupClient: func(client *clientsetfake.Clientset) {
   597  				client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   598  					return true, nil, errors.New("unknown error")
   599  				})
   600  			},
   601  			expectedError: true,
   602  		},
   603  		{
   604  			name: "role exists, update it",
   605  			setupClient: func(client *clientsetfake.Clientset) {
   606  				client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   607  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   608  				})
   609  				client.PrependReactor("update", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   610  					return true, nil, nil
   611  				})
   612  			},
   613  			expectedError: false,
   614  		},
   615  		{
   616  			name: "role exists, update error",
   617  			setupClient: func(client *clientsetfake.Clientset) {
   618  				client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   619  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   620  				})
   621  				client.PrependReactor("update", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   622  					return true, nil, errors.New("")
   623  				})
   624  			},
   625  			expectedError: true,
   626  		},
   627  	}
   628  
   629  	for _, tc := range tests {
   630  		t.Run(tc.name, func(t *testing.T) {
   631  			client := clientsetfake.NewSimpleClientset()
   632  			tc.setupClient(client)
   633  			err := CreateOrUpdateRole(client, &rbac.Role{})
   634  			if (err != nil) != tc.expectedError {
   635  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   636  			}
   637  		})
   638  	}
   639  }
   640  
   641  func TestCreateOrUpdateRoleBindings(t *testing.T) {
   642  	tests := []struct {
   643  		name          string
   644  		setupClient   func(*clientsetfake.Clientset)
   645  		expectedError bool
   646  	}{
   647  		{
   648  			name: "create rolebinding success",
   649  			setupClient: func(client *clientsetfake.Clientset) {
   650  				client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   651  					return true, nil, nil
   652  				})
   653  			},
   654  			expectedError: false,
   655  		},
   656  		{
   657  			name: "create rolebinding returns error",
   658  			setupClient: func(client *clientsetfake.Clientset) {
   659  				client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   660  					return true, nil, errors.New("unknown error")
   661  				})
   662  			},
   663  			expectedError: true,
   664  		},
   665  		{
   666  			name: "rolebinding exists, update it",
   667  			setupClient: func(client *clientsetfake.Clientset) {
   668  				client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   669  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   670  				})
   671  				client.PrependReactor("update", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   672  					return true, nil, nil
   673  				})
   674  			},
   675  			expectedError: false,
   676  		},
   677  		{
   678  			name: "rolebinding exists, update error",
   679  			setupClient: func(client *clientsetfake.Clientset) {
   680  				client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   681  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   682  				})
   683  				client.PrependReactor("update", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   684  					return true, nil, errors.New("")
   685  				})
   686  			},
   687  			expectedError: true,
   688  		},
   689  	}
   690  
   691  	for _, tc := range tests {
   692  		t.Run(tc.name, func(t *testing.T) {
   693  			client := clientsetfake.NewSimpleClientset()
   694  			tc.setupClient(client)
   695  			err := CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{})
   696  			if (err != nil) != tc.expectedError {
   697  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   698  			}
   699  		})
   700  	}
   701  }
   702  
   703  func TestCreateOrUpdateClusterRole(t *testing.T) {
   704  	tests := []struct {
   705  		name          string
   706  		setupClient   func(*clientsetfake.Clientset)
   707  		expectedError bool
   708  	}{
   709  		{
   710  			name: "create clusterrole success",
   711  			setupClient: func(client *clientsetfake.Clientset) {
   712  				client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   713  					return true, nil, nil
   714  				})
   715  			},
   716  			expectedError: false,
   717  		},
   718  		{
   719  			name: "create clusterrole returns error",
   720  			setupClient: func(client *clientsetfake.Clientset) {
   721  				client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   722  					return true, nil, errors.New("unknown error")
   723  				})
   724  			},
   725  			expectedError: true,
   726  		},
   727  		{
   728  			name: "clusterrole exists, update it",
   729  			setupClient: func(client *clientsetfake.Clientset) {
   730  				client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   731  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   732  				})
   733  				client.PrependReactor("update", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   734  					return true, nil, nil
   735  				})
   736  			},
   737  			expectedError: false,
   738  		},
   739  		{
   740  			name: "clusterrole exists, update error",
   741  			setupClient: func(client *clientsetfake.Clientset) {
   742  				client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   743  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   744  				})
   745  				client.PrependReactor("update", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) {
   746  					return true, nil, errors.New("")
   747  				})
   748  			},
   749  			expectedError: true,
   750  		},
   751  	}
   752  
   753  	for _, tc := range tests {
   754  		t.Run(tc.name, func(t *testing.T) {
   755  			client := clientsetfake.NewSimpleClientset()
   756  			tc.setupClient(client)
   757  			err := CreateOrUpdateClusterRole(client, &rbac.ClusterRole{})
   758  			if (err != nil) != tc.expectedError {
   759  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   760  			}
   761  		})
   762  	}
   763  }
   764  
   765  func TestCreateOrUpdateClusterRoleBindings(t *testing.T) {
   766  	tests := []struct {
   767  		name          string
   768  		setupClient   func(*clientsetfake.Clientset)
   769  		expectedError bool
   770  	}{
   771  		{
   772  			name: "create clusterrolebinding success",
   773  			setupClient: func(client *clientsetfake.Clientset) {
   774  				client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   775  					return true, nil, nil
   776  				})
   777  			},
   778  			expectedError: false,
   779  		},
   780  		{
   781  			name: "create clusterrolebinding returns error",
   782  			setupClient: func(client *clientsetfake.Clientset) {
   783  				client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   784  					return true, nil, errors.New("unknown error")
   785  				})
   786  			},
   787  			expectedError: true,
   788  		},
   789  		{
   790  			name: "clusterrolebinding exists, update it",
   791  			setupClient: func(client *clientsetfake.Clientset) {
   792  				client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   793  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   794  				})
   795  				client.PrependReactor("update", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   796  					return true, nil, nil
   797  				})
   798  			},
   799  			expectedError: false,
   800  		},
   801  		{
   802  			name: "clusterrolebinding exists, update error",
   803  			setupClient: func(client *clientsetfake.Clientset) {
   804  				client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   805  					return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name")
   806  				})
   807  				client.PrependReactor("update", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) {
   808  					return true, nil, errors.New("")
   809  				})
   810  			},
   811  			expectedError: true,
   812  		},
   813  	}
   814  
   815  	for _, tc := range tests {
   816  		t.Run(tc.name, func(t *testing.T) {
   817  			client := clientsetfake.NewSimpleClientset()
   818  			tc.setupClient(client)
   819  			err := CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{})
   820  			if (err != nil) != tc.expectedError {
   821  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   822  			}
   823  		})
   824  	}
   825  }
   826  
   827  func TestPatchNodeOnce(t *testing.T) {
   828  	testcases := []struct {
   829  		name       string
   830  		lookupName string
   831  		node       v1.Node
   832  		success    bool
   833  		fakeError  error
   834  	}{
   835  		{
   836  			name:       "simple update",
   837  			lookupName: "testnode",
   838  			node: v1.Node{
   839  				ObjectMeta: metav1.ObjectMeta{
   840  					Name:   "testnode",
   841  					Labels: map[string]string{v1.LabelHostname: ""},
   842  				},
   843  			},
   844  			success: true,
   845  		},
   846  		{
   847  			name:       "node does not exist",
   848  			lookupName: "whale",
   849  			success:    false,
   850  		},
   851  		{
   852  			name:       "node not labelled yet",
   853  			lookupName: "robin",
   854  			node: v1.Node{
   855  				ObjectMeta: metav1.ObjectMeta{
   856  					Name: "robin",
   857  				},
   858  			},
   859  			success: false,
   860  		},
   861  		{
   862  			name:       "patch node when timeout",
   863  			lookupName: "testnode",
   864  			node: v1.Node{
   865  				ObjectMeta: metav1.ObjectMeta{
   866  					Name:   "testnode",
   867  					Labels: map[string]string{v1.LabelHostname: ""},
   868  				},
   869  			},
   870  			success:   false,
   871  			fakeError: apierrors.NewTimeoutError("fake timeout", -1),
   872  		},
   873  		{
   874  			name:       "patch node when conflict",
   875  			lookupName: "testnode",
   876  			node: v1.Node{
   877  				ObjectMeta: metav1.ObjectMeta{
   878  					Name:   "testnode",
   879  					Labels: map[string]string{v1.LabelHostname: ""},
   880  				},
   881  			},
   882  			success:   false,
   883  			fakeError: apierrors.NewConflict(schema.GroupResource{}, "fake conflict", nil),
   884  		},
   885  		{
   886  			name:       "patch node when there is a server timeout",
   887  			lookupName: "testnode",
   888  			node: v1.Node{
   889  				ObjectMeta: metav1.ObjectMeta{
   890  					Name:   "testnode",
   891  					Labels: map[string]string{v1.LabelHostname: ""},
   892  				},
   893  			},
   894  			success:   false,
   895  			fakeError: apierrors.NewServerTimeout(schema.GroupResource{}, "fake server timeout", 1),
   896  		},
   897  		{
   898  			name:       "patch node when the service is unavailable",
   899  			lookupName: "testnode",
   900  			node: v1.Node{
   901  				ObjectMeta: metav1.ObjectMeta{
   902  					Name:   "testnode",
   903  					Labels: map[string]string{v1.LabelHostname: ""},
   904  				},
   905  			},
   906  			success:   false,
   907  			fakeError: apierrors.NewServiceUnavailable("fake service unavailable"),
   908  		},
   909  		{
   910  			name:       "patch node failed with unknown error",
   911  			lookupName: "testnode",
   912  			node: v1.Node{
   913  				ObjectMeta: metav1.ObjectMeta{
   914  					Name:   "testnode",
   915  					Labels: map[string]string{v1.LabelHostname: ""},
   916  				},
   917  			},
   918  			success:   false,
   919  			fakeError: errors.New("unknown error"),
   920  		},
   921  	}
   922  
   923  	for _, tc := range testcases {
   924  		t.Run(tc.name, func(t *testing.T) {
   925  			client := clientsetfake.NewSimpleClientset()
   926  			_, err := client.CoreV1().Nodes().Create(context.Background(), &tc.node, metav1.CreateOptions{})
   927  			if err != nil {
   928  				t.Fatalf("failed to create node to fake client: %v", err)
   929  			}
   930  			if tc.fakeError != nil {
   931  				client.PrependReactor("patch", "nodes", func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
   932  					return true, nil, tc.fakeError
   933  				})
   934  			}
   935  			var lastError error
   936  			conditionFunction := PatchNodeOnce(client, tc.lookupName, func(node *v1.Node) {
   937  				node.Annotations = map[string]string{
   938  					"updatedBy": "test",
   939  				}
   940  			}, &lastError)
   941  			success, err := conditionFunction(context.Background())
   942  			if err != nil && tc.success {
   943  				t.Fatalf("did not expect error: %v", err)
   944  			}
   945  			if success != tc.success {
   946  				t.Fatalf("expected %v got %v", tc.success, success)
   947  			}
   948  		})
   949  	}
   950  }
   951  
   952  func TestPatchNode(t *testing.T) {
   953  	tests := []struct {
   954  		name          string
   955  		setupClient   func(*clientsetfake.Clientset)
   956  		expectedError bool
   957  	}{
   958  		{
   959  			name: "success",
   960  			setupClient: func(client *clientsetfake.Clientset) {
   961  				client.PrependReactor("get", "nodes", func(clientgotesting.Action) (bool, runtime.Object, error) {
   962  					return true, &v1.Node{
   963  						ObjectMeta: metav1.ObjectMeta{
   964  							Name:   "some-node",
   965  							Labels: map[string]string{v1.LabelHostname: ""},
   966  						},
   967  					}, nil
   968  				})
   969  				client.PrependReactor("patch", "nodes", func(clientgotesting.Action) (bool, runtime.Object, error) {
   970  					return true, nil, nil
   971  				})
   972  			},
   973  			expectedError: false,
   974  		},
   975  		{
   976  			name: "error",
   977  			setupClient: func(client *clientsetfake.Clientset) {
   978  				client.PrependReactor("get", "nodes", func(clientgotesting.Action) (bool, runtime.Object, error) {
   979  					return true, nil, errors.New("unknown error")
   980  				})
   981  			},
   982  			expectedError: true,
   983  		},
   984  	}
   985  
   986  	for _, tc := range tests {
   987  		t.Run(tc.name, func(t *testing.T) {
   988  			client := clientsetfake.NewSimpleClientset()
   989  			tc.setupClient(client)
   990  			patchFn := func(*v1.Node) {}
   991  			err := PatchNode(client, "some-node", patchFn)
   992  			if (err != nil) != tc.expectedError {
   993  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   994  			}
   995  		})
   996  	}
   997  }
   998  
   999  func TestGetConfigMapWithShortRetry(t *testing.T) {
  1000  	expectedConfigMap := &v1.ConfigMap{
  1001  		ObjectMeta: metav1.ObjectMeta{
  1002  			Namespace: "ns",
  1003  			Name:      "some-cm",
  1004  		},
  1005  	}
  1006  	tests := []struct {
  1007  		name              string
  1008  		setupClient       func(*clientsetfake.Clientset)
  1009  		expectedConfigMap *v1.ConfigMap
  1010  		expectedError     bool
  1011  	}{
  1012  		{
  1013  			name: "configmap exists",
  1014  			setupClient: func(client *clientsetfake.Clientset) {
  1015  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
  1016  					return true, expectedConfigMap, nil
  1017  				})
  1018  			},
  1019  			expectedConfigMap: expectedConfigMap,
  1020  			expectedError:     false,
  1021  		},
  1022  		{
  1023  			name: "configmap get returns an error",
  1024  			setupClient: func(client *clientsetfake.Clientset) {
  1025  				client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) {
  1026  					return true, nil, errors.New("")
  1027  				})
  1028  			},
  1029  			expectedError: true,
  1030  		},
  1031  	}
  1032  
  1033  	for _, tc := range tests {
  1034  		t.Run(tc.name, func(t *testing.T) {
  1035  			client := clientsetfake.NewSimpleClientset()
  1036  			tc.setupClient(client)
  1037  			actual, err := GetConfigMapWithShortRetry(client, "ns", "some-cm")
  1038  			if (err != nil) != tc.expectedError {
  1039  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
  1040  			}
  1041  			if err != nil {
  1042  				return
  1043  			}
  1044  			diff := cmp.Diff(tc.expectedConfigMap, actual)
  1045  			if len(diff) > 0 {
  1046  				t.Fatalf("got a diff with the expected config (-want,+got):\n%s", diff)
  1047  			}
  1048  		})
  1049  	}
  1050  }
  1051  

View as plain text