...

Source file src/k8s.io/kubernetes/pkg/controller/history/controller_history_test.go

Documentation: k8s.io/kubernetes/pkg/controller/history

     1  /*
     2  Copyright 2016 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 history
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/json"
    23  	"fmt"
    24  	"reflect"
    25  	"testing"
    26  	"time"
    27  
    28  	apps "k8s.io/api/apps/v1"
    29  	v1 "k8s.io/api/core/v1"
    30  	"k8s.io/client-go/informers"
    31  	"k8s.io/client-go/kubernetes/fake"
    32  	clientscheme "k8s.io/client-go/kubernetes/scheme"
    33  	core "k8s.io/client-go/testing"
    34  	"k8s.io/kubernetes/pkg/api/legacyscheme"
    35  	"k8s.io/kubernetes/pkg/controller"
    36  
    37  	"k8s.io/apimachinery/pkg/api/errors"
    38  	"k8s.io/apimachinery/pkg/api/resource"
    39  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    40  	"k8s.io/apimachinery/pkg/labels"
    41  	"k8s.io/apimachinery/pkg/runtime"
    42  	"k8s.io/apimachinery/pkg/types"
    43  	"k8s.io/apimachinery/pkg/util/strategicpatch"
    44  	"k8s.io/utils/pointer"
    45  )
    46  
    47  func TestRealHistory_ListControllerRevisions(t *testing.T) {
    48  	type testcase struct {
    49  		name      string
    50  		parent    metav1.Object
    51  		selector  labels.Selector
    52  		revisions []*apps.ControllerRevision
    53  		want      map[string]bool
    54  	}
    55  	testFn := func(test *testcase, t *testing.T) {
    56  		client := fake.NewSimpleClientset()
    57  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
    58  
    59  		stop := make(chan struct{})
    60  		defer close(stop)
    61  		informerFactory.Start(stop)
    62  		informer := informerFactory.Apps().V1().ControllerRevisions()
    63  		informerFactory.WaitForCacheSync(stop)
    64  		for i := range test.revisions {
    65  			informer.Informer().GetIndexer().Add(test.revisions[i])
    66  		}
    67  
    68  		history := NewHistory(client, informer.Lister())
    69  		revisions, err := history.ListControllerRevisions(test.parent, test.selector)
    70  		if err != nil {
    71  			t.Errorf("%s: %s", test.name, err)
    72  		}
    73  		got := make(map[string]bool)
    74  		for i := range revisions {
    75  			got[revisions[i].Name] = true
    76  		}
    77  		if !reflect.DeepEqual(test.want, got) {
    78  			t.Errorf("%s: want %v got %v", test.name, test.want, got)
    79  		}
    80  	}
    81  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
    82  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
    83  	sel1, err := metav1.LabelSelectorAsSelector(ss1.Spec.Selector)
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, nil)
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	ss1Rev1.Namespace = ss1.Namespace
    92  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, nil)
    93  	if err != nil {
    94  		t.Fatal(err)
    95  	}
    96  	ss1Rev2.Namespace = ss1.Namespace
    97  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, nil)
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	ss2Rev1.Namespace = ss2.Namespace
   102  	ss1Orphan, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, nil)
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	ss1Orphan.Namespace = ss1.Namespace
   107  	ss1Orphan.OwnerReferences = nil
   108  
   109  	tests := []testcase{
   110  		{
   111  			name:      "selects none",
   112  			parent:    &ss1.ObjectMeta,
   113  			selector:  sel1,
   114  			revisions: nil,
   115  			want:      map[string]bool{},
   116  		},
   117  		{
   118  			name:      "selects all",
   119  			parent:    &ss1.ObjectMeta,
   120  			selector:  sel1,
   121  			revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2},
   122  			want:      map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
   123  		},
   124  		{
   125  			name:      "doesn't select another Objects history",
   126  			parent:    &ss1.ObjectMeta,
   127  			selector:  sel1,
   128  			revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss2Rev1},
   129  			want:      map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
   130  		},
   131  		{
   132  			name:      "selects orphans",
   133  			parent:    &ss1.ObjectMeta,
   134  			selector:  sel1,
   135  			revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss1Orphan},
   136  			want:      map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true, ss1Orphan.Name: true},
   137  		},
   138  	}
   139  	for i := range tests {
   140  		testFn(&tests[i], t)
   141  	}
   142  }
   143  
   144  func TestFakeHistory_ListControllerRevisions(t *testing.T) {
   145  	type testcase struct {
   146  		name      string
   147  		parent    metav1.Object
   148  		selector  labels.Selector
   149  		revisions []*apps.ControllerRevision
   150  		want      map[string]bool
   151  	}
   152  	testFn := func(test *testcase, t *testing.T) {
   153  		client := fake.NewSimpleClientset()
   154  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   155  
   156  		stop := make(chan struct{})
   157  		defer close(stop)
   158  		informerFactory.Start(stop)
   159  		informer := informerFactory.Apps().V1().ControllerRevisions()
   160  		informerFactory.WaitForCacheSync(stop)
   161  		for i := range test.revisions {
   162  			informer.Informer().GetIndexer().Add(test.revisions[i])
   163  		}
   164  
   165  		history := NewFakeHistory(informer)
   166  		revisions, err := history.ListControllerRevisions(test.parent, test.selector)
   167  		if err != nil {
   168  			t.Errorf("%s: %s", test.name, err)
   169  		}
   170  		got := make(map[string]bool)
   171  		for i := range revisions {
   172  			got[revisions[i].Name] = true
   173  		}
   174  		if !reflect.DeepEqual(test.want, got) {
   175  			t.Errorf("%s: want %v got %v", test.name, test.want, got)
   176  		}
   177  	}
   178  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
   179  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
   180  	sel1, err := metav1.LabelSelectorAsSelector(ss1.Spec.Selector)
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, nil)
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  	ss1Rev1.Namespace = ss1.Namespace
   189  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, nil)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  	ss1Rev2.Namespace = ss1.Namespace
   194  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, nil)
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	ss2Rev1.Namespace = ss2.Namespace
   199  	ss1Orphan, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, nil)
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	ss1Orphan.Namespace = ss1.Namespace
   204  	ss1Orphan.OwnerReferences = nil
   205  
   206  	tests := []testcase{
   207  		{
   208  			name:      "selects none",
   209  			parent:    &ss1.ObjectMeta,
   210  			selector:  sel1,
   211  			revisions: nil,
   212  			want:      map[string]bool{},
   213  		},
   214  		{
   215  			name:      "selects all",
   216  			parent:    &ss1.ObjectMeta,
   217  			selector:  sel1,
   218  			revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2},
   219  			want:      map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
   220  		},
   221  		{
   222  			name:      "doesn't select another Objects history",
   223  			parent:    &ss1.ObjectMeta,
   224  			selector:  sel1,
   225  			revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss2Rev1},
   226  			want:      map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true},
   227  		},
   228  		{
   229  			name:      "selects orphans",
   230  			parent:    &ss1.ObjectMeta,
   231  			selector:  sel1,
   232  			revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss1Orphan},
   233  			want:      map[string]bool{ss1Rev1.Name: true, ss1Rev2.Name: true, ss1Orphan.Name: true},
   234  		},
   235  	}
   236  	for i := range tests {
   237  		testFn(&tests[i], t)
   238  	}
   239  }
   240  
   241  func TestRealHistory_CreateControllerRevision(t *testing.T) {
   242  	type testcase struct {
   243  		name     string
   244  		parent   metav1.Object
   245  		revision *apps.ControllerRevision
   246  		existing []struct {
   247  			parent   metav1.Object
   248  			revision *apps.ControllerRevision
   249  		}
   250  		rename bool
   251  	}
   252  	testFn := func(test *testcase, t *testing.T) {
   253  		client := fake.NewSimpleClientset()
   254  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   255  		stop := make(chan struct{})
   256  		defer close(stop)
   257  		informerFactory.Start(stop)
   258  		informer := informerFactory.Apps().V1().ControllerRevisions()
   259  		informerFactory.WaitForCacheSync(stop)
   260  		history := NewHistory(client, informer.Lister())
   261  
   262  		var collisionCount int32
   263  		for _, item := range test.existing {
   264  			_, err := client.AppsV1().ControllerRevisions(item.parent.GetNamespace()).Create(context.TODO(), item.revision, metav1.CreateOptions{})
   265  			if err != nil {
   266  				t.Fatal(err)
   267  			}
   268  		}
   269  		// Clear collisionCount before creating the test revision
   270  		collisionCount = 0
   271  		created, err := history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
   272  		if err != nil {
   273  			t.Errorf("%s: %s", test.name, err)
   274  		}
   275  
   276  		if test.rename {
   277  			if created.Name == test.revision.Name {
   278  				t.Errorf("%s: wanted rename got %s %s", test.name, created.Name, test.revision.Name)
   279  			}
   280  			expectedName := ControllerRevisionName(test.parent.GetName(), HashControllerRevision(test.revision, &collisionCount))
   281  			if created.Name != expectedName {
   282  				t.Errorf("%s: on name collision wanted new name %s got %s", test.name, expectedName, created.Name)
   283  			}
   284  
   285  			// Second name collision will be caused by an identical revision, so no need to do anything
   286  			_, err = history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
   287  			if err != nil {
   288  				t.Errorf("%s: %s", test.name, err)
   289  			}
   290  			if collisionCount != 1 {
   291  				t.Errorf("%s: on second name collision wanted collisionCount 1 got %d", test.name, collisionCount)
   292  			}
   293  		}
   294  		if !test.rename && created.Name != test.revision.Name {
   295  			t.Errorf("%s: wanted %s got %s", test.name, test.revision.Name, created.Name)
   296  		}
   297  	}
   298  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
   299  	ss1.Status.CollisionCount = new(int32)
   300  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
   301  	ss2.Status.CollisionCount = new(int32)
   302  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
   303  	if err != nil {
   304  		t.Fatal(err)
   305  	}
   306  	ss1Rev1.Namespace = ss1.Namespace
   307  
   308  	// Create a new revision with the same name and hash label as an existing revision, but with
   309  	// a different template. This could happen as a result of a hash collision, but in this test
   310  	// this situation is created by setting name and hash label to values known to be in use by
   311  	// an existing revision.
   312  	modTemplate := ss1.Spec.Template.DeepCopy()
   313  	modTemplate.Labels["foo"] = "not_bar"
   314  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(modTemplate), 2, ss1.Status.CollisionCount)
   315  	ss1Rev2.Name = ss1Rev1.Name
   316  	ss1Rev2.Labels[ControllerRevisionHashLabel] = ss1Rev1.Labels[ControllerRevisionHashLabel]
   317  	if err != nil {
   318  		t.Fatal(err)
   319  	}
   320  	ss1Rev2.Namespace = ss1.Namespace
   321  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
   322  	if err != nil {
   323  		t.Fatal(err)
   324  	}
   325  	ss2Rev1.Namespace = ss2.Namespace
   326  	tests := []testcase{
   327  		{
   328  			name:     "creates new",
   329  			parent:   &ss1.ObjectMeta,
   330  			revision: ss1Rev1,
   331  			existing: nil,
   332  
   333  			rename: false,
   334  		},
   335  		{
   336  			name:     "create doesn't conflict when parents differ",
   337  			parent:   &ss2.ObjectMeta,
   338  			revision: ss2Rev1,
   339  			existing: []struct {
   340  				parent   metav1.Object
   341  				revision *apps.ControllerRevision
   342  			}{
   343  				{
   344  					parent:   ss1,
   345  					revision: ss1Rev1,
   346  				},
   347  			},
   348  
   349  			rename: false,
   350  		},
   351  		{
   352  			name:     "create renames on conflict",
   353  			parent:   &ss1.ObjectMeta,
   354  			revision: ss1Rev1,
   355  			existing: []struct {
   356  				parent   metav1.Object
   357  				revision *apps.ControllerRevision
   358  			}{
   359  				{
   360  					parent:   ss1,
   361  					revision: ss1Rev2,
   362  				},
   363  			},
   364  			rename: true,
   365  		},
   366  	}
   367  	for i := range tests {
   368  		testFn(&tests[i], t)
   369  	}
   370  }
   371  
   372  func TestFakeHistory_CreateControllerRevision(t *testing.T) {
   373  	type testcase struct {
   374  		name     string
   375  		parent   metav1.Object
   376  		revision *apps.ControllerRevision
   377  		existing []struct {
   378  			parent   metav1.Object
   379  			revision *apps.ControllerRevision
   380  		}
   381  		rename bool
   382  	}
   383  	testFn := func(test *testcase, t *testing.T) {
   384  		client := fake.NewSimpleClientset()
   385  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   386  
   387  		stop := make(chan struct{})
   388  		defer close(stop)
   389  		informerFactory.Start(stop)
   390  		informer := informerFactory.Apps().V1().ControllerRevisions()
   391  		informerFactory.WaitForCacheSync(stop)
   392  		history := NewFakeHistory(informer)
   393  
   394  		var collisionCount int32
   395  		for i := range test.existing {
   396  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
   397  			if err != nil {
   398  				t.Fatal(err)
   399  			}
   400  		}
   401  		// Clear collisionCount before creating the test revision
   402  		collisionCount = 0
   403  		created, err := history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
   404  		if err != nil {
   405  			t.Errorf("%s: %s", test.name, err)
   406  		}
   407  
   408  		if test.rename {
   409  			if created.Name == test.revision.Name {
   410  				t.Errorf("%s: wanted rename got %s %s", test.name, created.Name, test.revision.Name)
   411  			}
   412  			expectedName := ControllerRevisionName(test.parent.GetName(), HashControllerRevision(test.revision, &collisionCount))
   413  			if created.Name != expectedName {
   414  				t.Errorf("%s: on name collision wanted new name %s got %s", test.name, expectedName, created.Name)
   415  			}
   416  
   417  			// Second name collision should have incremented collisionCount to 2
   418  			_, err = history.CreateControllerRevision(test.parent, test.revision, &collisionCount)
   419  			if err != nil {
   420  				t.Errorf("%s: %s", test.name, err)
   421  			}
   422  			if collisionCount != 2 {
   423  				t.Errorf("%s: on second name collision wanted collisionCount 1 got %d", test.name, collisionCount)
   424  			}
   425  		}
   426  		if !test.rename && created.Name != test.revision.Name {
   427  			t.Errorf("%s: wanted %s got %s", test.name, test.revision.Name, created.Name)
   428  		}
   429  	}
   430  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
   431  	ss1.Status.CollisionCount = new(int32)
   432  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
   433  	ss2.Status.CollisionCount = new(int32)
   434  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
   435  	if err != nil {
   436  		t.Fatal(err)
   437  	}
   438  	ss1Rev1.Namespace = ss1.Namespace
   439  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
   440  	if err != nil {
   441  		t.Fatal(err)
   442  	}
   443  	ss1Rev2.Namespace = ss1.Namespace
   444  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
   445  	if err != nil {
   446  		t.Fatal(err)
   447  	}
   448  	ss2Rev1.Namespace = ss2.Namespace
   449  	tests := []testcase{
   450  		{
   451  			name:     "creates new",
   452  			parent:   &ss1.ObjectMeta,
   453  			revision: ss1Rev1,
   454  			existing: nil,
   455  
   456  			rename: false,
   457  		},
   458  		{
   459  			name:     "create doesn't conflict when parents differ",
   460  			parent:   &ss2.ObjectMeta,
   461  			revision: ss2Rev1,
   462  			existing: []struct {
   463  				parent   metav1.Object
   464  				revision *apps.ControllerRevision
   465  			}{
   466  				{
   467  					parent:   ss1,
   468  					revision: ss1Rev1,
   469  				},
   470  			},
   471  
   472  			rename: false,
   473  		},
   474  		{
   475  			name:     "create renames on conflict",
   476  			parent:   &ss1.ObjectMeta,
   477  			revision: ss1Rev1,
   478  			existing: []struct {
   479  				parent   metav1.Object
   480  				revision *apps.ControllerRevision
   481  			}{
   482  				{
   483  					parent:   ss1,
   484  					revision: ss1Rev1,
   485  				},
   486  			},
   487  			rename: true,
   488  		},
   489  	}
   490  	for i := range tests {
   491  		testFn(&tests[i], t)
   492  	}
   493  }
   494  
   495  func TestRealHistory_UpdateControllerRevision(t *testing.T) {
   496  	conflictAttempts := 0
   497  	type testcase struct {
   498  		name        string
   499  		revision    *apps.ControllerRevision
   500  		newRevision int64
   501  		existing    []struct {
   502  			parent   metav1.Object
   503  			revision *apps.ControllerRevision
   504  		}
   505  		reactor core.ReactionFunc
   506  		err     bool
   507  	}
   508  	conflictSuccess := func(action core.Action) (bool, runtime.Object, error) {
   509  		defer func() {
   510  			conflictAttempts++
   511  		}()
   512  		switch action.(type) {
   513  
   514  		case core.UpdateActionImpl:
   515  			update := action.(core.UpdateAction)
   516  			if conflictAttempts < 2 {
   517  				return true, update.GetObject(), errors.NewConflict(update.GetResource().GroupResource(), "", fmt.Errorf("conflict"))
   518  			}
   519  			return true, update.GetObject(), nil
   520  		default:
   521  			return false, nil, nil
   522  		}
   523  	}
   524  	internalError := func(action core.Action) (bool, runtime.Object, error) {
   525  		switch action.(type) {
   526  		case core.UpdateActionImpl:
   527  			return true, nil, errors.NewInternalError(fmt.Errorf("internal error"))
   528  		default:
   529  			return false, nil, nil
   530  		}
   531  	}
   532  
   533  	testFn := func(test *testcase, t *testing.T) {
   534  		client := fake.NewSimpleClientset()
   535  
   536  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   537  		stop := make(chan struct{})
   538  		defer close(stop)
   539  		informerFactory.Start(stop)
   540  		informer := informerFactory.Apps().V1().ControllerRevisions()
   541  		informerFactory.WaitForCacheSync(stop)
   542  		history := NewHistory(client, informer.Lister())
   543  		var collisionCount int32
   544  		for i := range test.existing {
   545  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
   546  			if err != nil {
   547  				t.Fatal(err)
   548  			}
   549  		}
   550  		if test.reactor != nil {
   551  			client.PrependReactor("*", "*", test.reactor)
   552  		}
   553  		updated, err := history.UpdateControllerRevision(test.revision, test.newRevision)
   554  		if !test.err && err != nil {
   555  			t.Errorf("%s: %s", test.name, err)
   556  		}
   557  		if !test.err && updated.Revision != test.newRevision {
   558  			t.Errorf("%s: got %d want %d", test.name, updated.Revision, test.newRevision)
   559  		}
   560  		if test.err && err == nil {
   561  			t.Errorf("%s: expected error", test.name)
   562  		}
   563  	}
   564  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
   565  	ss1.Status.CollisionCount = new(int32)
   566  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
   567  	if err != nil {
   568  		t.Fatal(err)
   569  	}
   570  	ss1Rev1.Namespace = ss1.Namespace
   571  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
   572  	if err != nil {
   573  		t.Fatal(err)
   574  	}
   575  	ss1Rev2.Namespace = ss1.Namespace
   576  
   577  	tests := []testcase{
   578  		{
   579  			name:        "update succeeds",
   580  			revision:    ss1Rev1,
   581  			newRevision: ss1Rev1.Revision + 1,
   582  			existing: []struct {
   583  				parent   metav1.Object
   584  				revision *apps.ControllerRevision
   585  			}{
   586  				{
   587  					parent:   ss1,
   588  					revision: ss1Rev1,
   589  				},
   590  			},
   591  			reactor: nil,
   592  			err:     false,
   593  		},
   594  		{
   595  			name:        "update succeeds no noop",
   596  			revision:    ss1Rev1,
   597  			newRevision: ss1Rev1.Revision,
   598  			existing: []struct {
   599  				parent   metav1.Object
   600  				revision *apps.ControllerRevision
   601  			}{
   602  				{
   603  					parent:   ss1,
   604  					revision: ss1Rev1,
   605  				},
   606  			},
   607  			reactor: nil,
   608  			err:     false,
   609  		}, {
   610  			name:        "update fails on error",
   611  			revision:    ss1Rev1,
   612  			newRevision: ss1Rev1.Revision + 10,
   613  			existing: []struct {
   614  				parent   metav1.Object
   615  				revision *apps.ControllerRevision
   616  			}{
   617  				{
   618  					parent:   ss1,
   619  					revision: ss1Rev1,
   620  				},
   621  			},
   622  			reactor: internalError,
   623  			err:     true,
   624  		},
   625  		{
   626  			name:        "update on succeeds on conflict",
   627  			revision:    ss1Rev1,
   628  			newRevision: ss1Rev1.Revision + 1,
   629  			existing: []struct {
   630  				parent   metav1.Object
   631  				revision *apps.ControllerRevision
   632  			}{
   633  				{
   634  					parent:   ss1,
   635  					revision: ss1Rev1,
   636  				},
   637  			},
   638  			reactor: conflictSuccess,
   639  			err:     false,
   640  		},
   641  	}
   642  	for i := range tests {
   643  		conflictAttempts = 0
   644  		testFn(&tests[i], t)
   645  	}
   646  }
   647  
   648  func TestFakeHistory_UpdateControllerRevision(t *testing.T) {
   649  	type testcase struct {
   650  		name        string
   651  		revision    *apps.ControllerRevision
   652  		newRevision int64
   653  		existing    []struct {
   654  			parent   metav1.Object
   655  			revision *apps.ControllerRevision
   656  		}
   657  		err bool
   658  	}
   659  
   660  	testFn := func(test *testcase, t *testing.T) {
   661  		client := fake.NewSimpleClientset()
   662  
   663  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   664  		stop := make(chan struct{})
   665  		defer close(stop)
   666  		informerFactory.Start(stop)
   667  		informer := informerFactory.Apps().V1().ControllerRevisions()
   668  		informerFactory.WaitForCacheSync(stop)
   669  		history := NewFakeHistory(informer)
   670  		var collisionCount int32
   671  		for i := range test.existing {
   672  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
   673  			if err != nil {
   674  				t.Fatal(err)
   675  			}
   676  		}
   677  		updated, err := history.UpdateControllerRevision(test.revision, test.newRevision)
   678  		if !test.err && err != nil {
   679  			t.Errorf("%s: %s", test.name, err)
   680  		}
   681  		if !test.err && updated.Revision != test.newRevision {
   682  			t.Errorf("%s: got %d want %d", test.name, updated.Revision, test.newRevision)
   683  		}
   684  		if test.err && err == nil {
   685  			t.Errorf("%s: expected error", test.name)
   686  		}
   687  	}
   688  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
   689  	ss1.Status.CollisionCount = new(int32)
   690  
   691  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
   692  	if err != nil {
   693  		t.Fatal(err)
   694  	}
   695  	ss1Rev1.Namespace = ss1.Namespace
   696  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
   697  	if err != nil {
   698  		t.Fatal(err)
   699  	}
   700  	ss1Rev2.Namespace = ss1.Namespace
   701  	tests := []testcase{
   702  		{
   703  			name:        "update succeeds",
   704  			revision:    ss1Rev1,
   705  			newRevision: ss1Rev1.Revision + 1,
   706  			existing: []struct {
   707  				parent   metav1.Object
   708  				revision *apps.ControllerRevision
   709  			}{
   710  				{
   711  					parent:   ss1,
   712  					revision: ss1Rev1,
   713  				},
   714  			},
   715  			err: false,
   716  		},
   717  		{
   718  			name:        "update succeeds no noop",
   719  			revision:    ss1Rev1,
   720  			newRevision: ss1Rev1.Revision,
   721  			existing: []struct {
   722  				parent   metav1.Object
   723  				revision *apps.ControllerRevision
   724  			}{
   725  				{
   726  					parent:   ss1,
   727  					revision: ss1Rev1,
   728  				},
   729  			},
   730  			err: false,
   731  		},
   732  	}
   733  	for i := range tests {
   734  		testFn(&tests[i], t)
   735  	}
   736  }
   737  
   738  func TestRealHistory_DeleteControllerRevision(t *testing.T) {
   739  	type testcase struct {
   740  		name     string
   741  		revision *apps.ControllerRevision
   742  		existing []struct {
   743  			parent   metav1.Object
   744  			revision *apps.ControllerRevision
   745  		}
   746  		err bool
   747  	}
   748  	testFn := func(test *testcase, t *testing.T) {
   749  		client := fake.NewSimpleClientset()
   750  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   751  
   752  		stop := make(chan struct{})
   753  		defer close(stop)
   754  		informerFactory.Start(stop)
   755  		informer := informerFactory.Apps().V1().ControllerRevisions()
   756  		informerFactory.WaitForCacheSync(stop)
   757  		history := NewHistory(client, informer.Lister())
   758  		var collisionCount int32
   759  		for i := range test.existing {
   760  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
   761  			if err != nil {
   762  				t.Fatal(err)
   763  			}
   764  		}
   765  		err := history.DeleteControllerRevision(test.revision)
   766  		if !test.err && err != nil {
   767  			t.Errorf("%s: %s", test.name, err)
   768  		}
   769  		if test.err && err == nil {
   770  			t.Errorf("%s: expected error", test.name)
   771  		}
   772  	}
   773  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
   774  	ss1.Status.CollisionCount = new(int32)
   775  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
   776  	ss2.Status.CollisionCount = new(int32)
   777  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
   778  	if err != nil {
   779  		t.Fatal(err)
   780  	}
   781  	ss1Rev1.Namespace = ss1.Namespace
   782  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
   783  	if err != nil {
   784  		t.Fatal(err)
   785  	}
   786  	ss1Rev2.Namespace = ss1.Namespace
   787  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
   788  	if err != nil {
   789  		t.Fatal(err)
   790  	}
   791  	ss2Rev1.Namespace = ss2.Namespace
   792  	ss2Rev2, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 2, ss2.Status.CollisionCount)
   793  	if err != nil {
   794  		t.Fatal(err)
   795  	}
   796  	ss2Rev2.Namespace = ss2.Namespace
   797  	tests := []testcase{
   798  		{
   799  			name:     "delete empty fails",
   800  			revision: ss1Rev1,
   801  			existing: nil,
   802  			err:      true,
   803  		},
   804  		{
   805  			name:     "delete existing succeeds",
   806  			revision: ss1Rev1,
   807  			existing: []struct {
   808  				parent   metav1.Object
   809  				revision *apps.ControllerRevision
   810  			}{
   811  				{
   812  					parent:   ss1,
   813  					revision: ss1Rev1,
   814  				},
   815  			},
   816  			err: false,
   817  		}, {
   818  			name:     "delete non-existing fails",
   819  			revision: ss1Rev1,
   820  			existing: []struct {
   821  				parent   metav1.Object
   822  				revision *apps.ControllerRevision
   823  			}{
   824  				{
   825  					parent:   ss2,
   826  					revision: ss2Rev1,
   827  				},
   828  				{
   829  					parent:   ss2,
   830  					revision: ss2Rev2,
   831  				},
   832  			},
   833  			err: true,
   834  		},
   835  	}
   836  	for i := range tests {
   837  		testFn(&tests[i], t)
   838  	}
   839  }
   840  
   841  func TestFakeHistory_DeleteControllerRevision(t *testing.T) {
   842  	type testcase struct {
   843  		name     string
   844  		revision *apps.ControllerRevision
   845  		existing []struct {
   846  			parent   metav1.Object
   847  			revision *apps.ControllerRevision
   848  		}
   849  		err bool
   850  	}
   851  	testFn := func(test *testcase, t *testing.T) {
   852  		client := fake.NewSimpleClientset()
   853  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   854  
   855  		stop := make(chan struct{})
   856  		defer close(stop)
   857  		informerFactory.Start(stop)
   858  		informer := informerFactory.Apps().V1().ControllerRevisions()
   859  		informerFactory.WaitForCacheSync(stop)
   860  		history := NewFakeHistory(informer)
   861  		var collisionCount int32
   862  		for i := range test.existing {
   863  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
   864  			if err != nil {
   865  				t.Fatal(err)
   866  			}
   867  		}
   868  		err := history.DeleteControllerRevision(test.revision)
   869  		if !test.err && err != nil {
   870  			t.Errorf("%s: %s", test.name, err)
   871  		}
   872  		if test.err && err == nil {
   873  			t.Errorf("%s: expected error", test.name)
   874  		}
   875  	}
   876  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
   877  	ss1.Status.CollisionCount = new(int32)
   878  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
   879  	ss2.Status.CollisionCount = new(int32)
   880  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
   881  	if err != nil {
   882  		t.Fatal(err)
   883  	}
   884  	ss1Rev1.Namespace = ss1.Namespace
   885  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
   886  	if err != nil {
   887  		t.Fatal(err)
   888  	}
   889  	ss1Rev2.Namespace = ss1.Namespace
   890  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
   891  	if err != nil {
   892  		t.Fatal(err)
   893  	}
   894  	ss2Rev1.Namespace = ss2.Namespace
   895  	ss2Rev2, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 2, ss2.Status.CollisionCount)
   896  	if err != nil {
   897  		t.Fatal(err)
   898  	}
   899  	ss2Rev2.Namespace = ss2.Namespace
   900  	tests := []testcase{
   901  		{
   902  			name:     "delete empty fails",
   903  			revision: ss1Rev1,
   904  			existing: nil,
   905  			err:      true,
   906  		},
   907  		{
   908  			name:     "delete existing succeeds",
   909  			revision: ss1Rev1,
   910  			existing: []struct {
   911  				parent   metav1.Object
   912  				revision *apps.ControllerRevision
   913  			}{
   914  				{
   915  					parent:   ss1,
   916  					revision: ss1Rev1,
   917  				},
   918  			},
   919  			err: false,
   920  		}, {
   921  			name:     "delete non-existing fails",
   922  			revision: ss1Rev1,
   923  			existing: []struct {
   924  				parent   metav1.Object
   925  				revision *apps.ControllerRevision
   926  			}{
   927  				{
   928  					parent:   ss2,
   929  					revision: ss2Rev1,
   930  				},
   931  				{
   932  					parent:   ss2,
   933  					revision: ss2Rev2,
   934  				},
   935  			},
   936  			err: true,
   937  		},
   938  	}
   939  	for i := range tests {
   940  		testFn(&tests[i], t)
   941  	}
   942  }
   943  
   944  func TestRealHistory_AdoptControllerRevision(t *testing.T) {
   945  	type testcase struct {
   946  		name     string
   947  		parent   metav1.Object
   948  		revision *apps.ControllerRevision
   949  		existing []struct {
   950  			parent   metav1.Object
   951  			revision *apps.ControllerRevision
   952  		}
   953  		err bool
   954  	}
   955  	testFn := func(test *testcase, t *testing.T) {
   956  		client := fake.NewSimpleClientset()
   957  		client.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) {
   958  			switch action := action.(type) {
   959  			case core.PatchActionImpl:
   960  				var found *apps.ControllerRevision
   961  				for i := range test.existing {
   962  					if test.revision.Name == test.existing[i].revision.Name &&
   963  						test.revision.Namespace == test.existing[i].revision.Namespace {
   964  						found = test.existing[i].revision
   965  						break
   966  					}
   967  				}
   968  				if found == nil {
   969  					return true, nil, errors.NewNotFound(apps.Resource("controllerrevisions"), test.revision.Name)
   970  				}
   971  				b, err := strategicpatch.StrategicMergePatch(
   972  					[]byte(runtime.EncodeOrDie(clientscheme.Codecs.LegacyCodec(apps.SchemeGroupVersion), test.revision)),
   973  					action.GetPatch(), test.revision)
   974  				if err != nil {
   975  					return true, nil, err
   976  				}
   977  				obj, err := runtime.Decode(clientscheme.Codecs.LegacyCodec(apps.SchemeGroupVersion), b)
   978  				if err != nil {
   979  					return true, nil, err
   980  				}
   981  				patched, err := legacyscheme.Scheme.ConvertToVersion(obj, apps.SchemeGroupVersion)
   982  				if err != nil {
   983  					return true, nil, err
   984  				}
   985  				return true, patched, err
   986  			default:
   987  				return false, nil, nil
   988  			}
   989  
   990  		})
   991  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
   992  		stop := make(chan struct{})
   993  		defer close(stop)
   994  		informerFactory.Start(stop)
   995  		informer := informerFactory.Apps().V1().ControllerRevisions()
   996  		informerFactory.WaitForCacheSync(stop)
   997  
   998  		history := NewHistory(client, informer.Lister())
   999  		var collisionCount int32
  1000  		for i := range test.existing {
  1001  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  1002  			if err != nil {
  1003  				t.Fatal(err)
  1004  			}
  1005  		}
  1006  		adopted, err := history.AdoptControllerRevision(test.parent, parentKind, test.revision)
  1007  		if !test.err && err != nil {
  1008  			t.Errorf("%s: %s", test.name, err)
  1009  		}
  1010  		if !test.err && !metav1.IsControlledBy(adopted, test.parent) {
  1011  			t.Errorf("%s: adoption failed", test.name)
  1012  		}
  1013  		if test.err && err == nil {
  1014  			t.Errorf("%s: expected error", test.name)
  1015  		}
  1016  	}
  1017  
  1018  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1019  	ss1.Status.CollisionCount = new(int32)
  1020  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1021  	ss2.Status.CollisionCount = new(int32)
  1022  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1023  	if err != nil {
  1024  		t.Fatal(err)
  1025  	}
  1026  	ss1Rev1.Namespace = ss1.Namespace
  1027  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1028  	if err != nil {
  1029  		t.Fatal(err)
  1030  	}
  1031  	ss1Rev2.Namespace = ss1.Namespace
  1032  	ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1033  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  1034  	if err != nil {
  1035  		t.Fatal(err)
  1036  	}
  1037  	ss2Rev1.Namespace = ss2.Namespace
  1038  	tests := []testcase{
  1039  		{
  1040  			name:     "adopting an orphan succeeds",
  1041  			parent:   ss1,
  1042  			revision: ss1Rev2,
  1043  			existing: []struct {
  1044  				parent   metav1.Object
  1045  				revision *apps.ControllerRevision
  1046  			}{
  1047  				{
  1048  					parent:   ss1,
  1049  					revision: ss1Rev2,
  1050  				},
  1051  			},
  1052  			err: false,
  1053  		},
  1054  		{
  1055  			name:     "adopting an owned revision fails",
  1056  			parent:   ss1,
  1057  			revision: ss2Rev1,
  1058  			existing: []struct {
  1059  				parent   metav1.Object
  1060  				revision *apps.ControllerRevision
  1061  			}{
  1062  				{
  1063  					parent:   ss2,
  1064  					revision: ss2Rev1,
  1065  				},
  1066  			},
  1067  			err: true,
  1068  		},
  1069  		{
  1070  			name:     "adopting a non-existent revision fails",
  1071  			parent:   ss1,
  1072  			revision: ss1Rev2,
  1073  			existing: nil,
  1074  			err:      true,
  1075  		},
  1076  	}
  1077  	for i := range tests {
  1078  		testFn(&tests[i], t)
  1079  	}
  1080  }
  1081  
  1082  func TestFakeHistory_AdoptControllerRevision(t *testing.T) {
  1083  	type testcase struct {
  1084  		name       string
  1085  		parent     metav1.Object
  1086  		parentType *metav1.TypeMeta
  1087  		revision   *apps.ControllerRevision
  1088  		existing   []struct {
  1089  			parent   metav1.Object
  1090  			revision *apps.ControllerRevision
  1091  		}
  1092  		err bool
  1093  	}
  1094  	testFn := func(test *testcase, t *testing.T) {
  1095  		client := fake.NewSimpleClientset()
  1096  
  1097  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  1098  		stop := make(chan struct{})
  1099  		defer close(stop)
  1100  		informerFactory.Start(stop)
  1101  		informer := informerFactory.Apps().V1().ControllerRevisions()
  1102  		informerFactory.WaitForCacheSync(stop)
  1103  
  1104  		history := NewFakeHistory(informer)
  1105  		var collisionCount int32
  1106  		for i := range test.existing {
  1107  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  1108  			if err != nil {
  1109  				t.Fatal(err)
  1110  			}
  1111  		}
  1112  		adopted, err := history.AdoptControllerRevision(test.parent, parentKind, test.revision)
  1113  		if !test.err && err != nil {
  1114  			t.Errorf("%s: %s", test.name, err)
  1115  		}
  1116  		if !test.err && !metav1.IsControlledBy(adopted, test.parent) {
  1117  			t.Errorf("%s: adoption failed", test.name)
  1118  		}
  1119  		if test.err && err == nil {
  1120  			t.Errorf("%s: expected error", test.name)
  1121  		}
  1122  	}
  1123  
  1124  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1125  	ss1.Status.CollisionCount = new(int32)
  1126  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1127  	ss2.Status.CollisionCount = new(int32)
  1128  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1129  	if err != nil {
  1130  		t.Fatal(err)
  1131  	}
  1132  	ss1Rev1.Namespace = ss1.Namespace
  1133  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1134  	if err != nil {
  1135  		t.Fatal(err)
  1136  	}
  1137  	ss1Rev2.Namespace = ss1.Namespace
  1138  	ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1139  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  1140  	if err != nil {
  1141  		t.Fatal(err)
  1142  	}
  1143  	ss2Rev1.Namespace = ss2.Namespace
  1144  	tests := []testcase{
  1145  		{
  1146  			name:       "adopting an orphan succeeds",
  1147  			parent:     ss1,
  1148  			parentType: &ss1.TypeMeta,
  1149  			revision:   ss1Rev2,
  1150  			existing: []struct {
  1151  				parent   metav1.Object
  1152  				revision *apps.ControllerRevision
  1153  			}{
  1154  				{
  1155  					parent:   ss1,
  1156  					revision: ss1Rev2,
  1157  				},
  1158  			},
  1159  			err: false,
  1160  		},
  1161  		{
  1162  			name:       "adopting an owned revision fails",
  1163  			parent:     ss1,
  1164  			parentType: &ss1.TypeMeta,
  1165  			revision:   ss2Rev1,
  1166  			existing: []struct {
  1167  				parent   metav1.Object
  1168  				revision *apps.ControllerRevision
  1169  			}{
  1170  				{
  1171  					parent:   ss2,
  1172  					revision: ss2Rev1,
  1173  				},
  1174  			},
  1175  			err: true,
  1176  		},
  1177  		{
  1178  			name:       "adopting a non-existent revision fails",
  1179  			parent:     ss1,
  1180  			parentType: &ss1.TypeMeta,
  1181  			revision:   ss1Rev2,
  1182  			existing:   nil,
  1183  			err:        true,
  1184  		},
  1185  	}
  1186  	for i := range tests {
  1187  		testFn(&tests[i], t)
  1188  	}
  1189  }
  1190  
  1191  func TestRealHistory_ReleaseControllerRevision(t *testing.T) {
  1192  	type testcase struct {
  1193  		name     string
  1194  		parent   metav1.Object
  1195  		revision *apps.ControllerRevision
  1196  		existing []struct {
  1197  			parent   metav1.Object
  1198  			revision *apps.ControllerRevision
  1199  		}
  1200  		err bool
  1201  	}
  1202  	testFn := func(test *testcase, t *testing.T) {
  1203  		client := fake.NewSimpleClientset()
  1204  		client.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) {
  1205  			switch action := action.(type) {
  1206  			case core.PatchActionImpl:
  1207  				var found *apps.ControllerRevision
  1208  				for i := range test.existing {
  1209  					if test.revision.Name == test.existing[i].revision.Name &&
  1210  						test.revision.Namespace == test.existing[i].revision.Namespace {
  1211  						found = test.existing[i].revision
  1212  						break
  1213  					}
  1214  				}
  1215  				if found == nil {
  1216  					return true, nil, errors.NewNotFound(apps.Resource("controllerrevisions"), test.revision.Name)
  1217  				}
  1218  				if !metav1.IsControlledBy(test.revision, test.parent) {
  1219  					return true, nil, errors.NewInvalid(
  1220  						test.revision.GroupVersionKind().GroupKind(), test.revision.Name, nil)
  1221  				}
  1222  				b, err := strategicpatch.StrategicMergePatch(
  1223  					[]byte(runtime.EncodeOrDie(clientscheme.Codecs.LegacyCodec(apps.SchemeGroupVersion), test.revision)),
  1224  					action.GetPatch(), test.revision)
  1225  				if err != nil {
  1226  					return true, nil, err
  1227  				}
  1228  				obj, err := runtime.Decode(clientscheme.Codecs.LegacyCodec(apps.SchemeGroupVersion), b)
  1229  				if err != nil {
  1230  					return true, nil, err
  1231  				}
  1232  				patched, err := legacyscheme.Scheme.ConvertToVersion(obj, apps.SchemeGroupVersion)
  1233  				if err != nil {
  1234  					return true, nil, err
  1235  				}
  1236  				return true, patched, err
  1237  			default:
  1238  				return false, nil, nil
  1239  			}
  1240  
  1241  		})
  1242  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  1243  		stop := make(chan struct{})
  1244  		defer close(stop)
  1245  		informerFactory.Start(stop)
  1246  		informer := informerFactory.Apps().V1().ControllerRevisions()
  1247  		informerFactory.WaitForCacheSync(stop)
  1248  
  1249  		history := NewHistory(client, informer.Lister())
  1250  		var collisionCount int32
  1251  		for i := range test.existing {
  1252  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  1253  			if err != nil {
  1254  				t.Fatal(err)
  1255  			}
  1256  		}
  1257  		adopted, err := history.ReleaseControllerRevision(test.parent, test.revision)
  1258  		if !test.err {
  1259  			if err != nil {
  1260  				t.Errorf("%s: %s", test.name, err)
  1261  			}
  1262  			if adopted == nil {
  1263  				return
  1264  			}
  1265  			if metav1.IsControlledBy(adopted, test.parent) {
  1266  				t.Errorf("%s: release failed", test.name)
  1267  			}
  1268  		}
  1269  		if test.err && err == nil {
  1270  			t.Errorf("%s: expected error", test.name)
  1271  		}
  1272  	}
  1273  
  1274  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1275  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1276  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, nil)
  1277  	if err != nil {
  1278  		t.Fatal(err)
  1279  	}
  1280  	ss1Rev1.Namespace = ss1.Namespace
  1281  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, nil)
  1282  	if err != nil {
  1283  		t.Fatal(err)
  1284  	}
  1285  	ss1Rev2.Namespace = ss1.Namespace
  1286  	ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1287  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, nil)
  1288  	if err != nil {
  1289  		t.Fatal(err)
  1290  	}
  1291  	ss2Rev1.Namespace = ss2.Namespace
  1292  	tests := []testcase{
  1293  		{
  1294  			name:     "releasing an owned revision succeeds",
  1295  			parent:   ss1,
  1296  			revision: ss1Rev1,
  1297  			existing: []struct {
  1298  				parent   metav1.Object
  1299  				revision *apps.ControllerRevision
  1300  			}{
  1301  				{
  1302  					parent:   ss1,
  1303  					revision: ss1Rev1,
  1304  				},
  1305  			},
  1306  			err: false,
  1307  		},
  1308  		{
  1309  			name:     "releasing an orphan succeeds",
  1310  			parent:   ss1,
  1311  			revision: ss1Rev2,
  1312  			existing: []struct {
  1313  				parent   metav1.Object
  1314  				revision *apps.ControllerRevision
  1315  			}{
  1316  				{
  1317  					parent:   ss1,
  1318  					revision: ss1Rev2,
  1319  				},
  1320  			},
  1321  			err: false,
  1322  		},
  1323  		{
  1324  			name:     "releasing a revision owned by another controller succeeds",
  1325  			parent:   ss1,
  1326  			revision: ss2Rev1,
  1327  			existing: []struct {
  1328  				parent   metav1.Object
  1329  				revision *apps.ControllerRevision
  1330  			}{
  1331  				{
  1332  					parent:   ss2,
  1333  					revision: ss2Rev1,
  1334  				},
  1335  			},
  1336  			err: false,
  1337  		},
  1338  		{
  1339  			name:     "releasing a non-existent revision succeeds",
  1340  			parent:   ss1,
  1341  			revision: ss1Rev1,
  1342  			existing: nil,
  1343  			err:      false,
  1344  		},
  1345  	}
  1346  	for i := range tests {
  1347  		testFn(&tests[i], t)
  1348  	}
  1349  }
  1350  
  1351  func TestFakeHistory_ReleaseControllerRevision(t *testing.T) {
  1352  	type testcase struct {
  1353  		name     string
  1354  		parent   metav1.Object
  1355  		revision *apps.ControllerRevision
  1356  		existing []struct {
  1357  			parent   metav1.Object
  1358  			revision *apps.ControllerRevision
  1359  		}
  1360  		err bool
  1361  	}
  1362  	testFn := func(test *testcase, t *testing.T) {
  1363  		client := fake.NewSimpleClientset()
  1364  		informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
  1365  		stop := make(chan struct{})
  1366  		defer close(stop)
  1367  		informerFactory.Start(stop)
  1368  		informer := informerFactory.Apps().V1().ControllerRevisions()
  1369  		informerFactory.WaitForCacheSync(stop)
  1370  		history := NewFakeHistory(informer)
  1371  		var collisionCount int32
  1372  		for i := range test.existing {
  1373  			_, err := history.CreateControllerRevision(test.existing[i].parent, test.existing[i].revision, &collisionCount)
  1374  			if err != nil {
  1375  				t.Fatal(err)
  1376  			}
  1377  		}
  1378  		adopted, err := history.ReleaseControllerRevision(test.parent, test.revision)
  1379  		if !test.err {
  1380  			if err != nil {
  1381  				t.Errorf("%s: %s", test.name, err)
  1382  			}
  1383  			if adopted == nil {
  1384  				return
  1385  			}
  1386  			if metav1.IsControlledBy(adopted, test.parent) {
  1387  				t.Errorf("%s: release failed", test.name)
  1388  			}
  1389  		}
  1390  		if test.err && err == nil {
  1391  			t.Errorf("%s: expected error", test.name)
  1392  		}
  1393  	}
  1394  
  1395  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1396  	ss1.Status.CollisionCount = new(int32)
  1397  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1398  	ss2.Status.CollisionCount = new(int32)
  1399  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1400  	if err != nil {
  1401  		t.Fatal(err)
  1402  	}
  1403  	ss1Rev1.Namespace = ss1.Namespace
  1404  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1405  	if err != nil {
  1406  		t.Fatal(err)
  1407  	}
  1408  	ss1Rev2.Namespace = ss1.Namespace
  1409  	ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1410  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  1411  	if err != nil {
  1412  		t.Fatal(err)
  1413  	}
  1414  	ss2Rev1.Namespace = ss2.Namespace
  1415  	tests := []testcase{
  1416  		{
  1417  			name:     "releasing an owned revision succeeds",
  1418  			parent:   ss1,
  1419  			revision: ss1Rev1,
  1420  			existing: []struct {
  1421  				parent   metav1.Object
  1422  				revision *apps.ControllerRevision
  1423  			}{
  1424  				{
  1425  					parent:   ss1,
  1426  					revision: ss1Rev1,
  1427  				},
  1428  			},
  1429  			err: false,
  1430  		},
  1431  		{
  1432  			name:     "releasing an orphan succeeds",
  1433  			parent:   ss1,
  1434  			revision: ss1Rev2,
  1435  			existing: []struct {
  1436  				parent   metav1.Object
  1437  				revision *apps.ControllerRevision
  1438  			}{
  1439  				{
  1440  					parent:   ss1,
  1441  					revision: ss1Rev2,
  1442  				},
  1443  			},
  1444  			err: false,
  1445  		},
  1446  		{
  1447  			name:     "releasing a revision owned by another controller succeeds",
  1448  			parent:   ss1,
  1449  			revision: ss2Rev1,
  1450  			existing: []struct {
  1451  				parent   metav1.Object
  1452  				revision *apps.ControllerRevision
  1453  			}{
  1454  				{
  1455  					parent:   ss2,
  1456  					revision: ss2Rev1,
  1457  				},
  1458  			},
  1459  			err: false,
  1460  		},
  1461  		{
  1462  			name:     "releasing a non-existent revision succeeds",
  1463  			parent:   ss1,
  1464  			revision: ss1Rev1,
  1465  			existing: nil,
  1466  			err:      false,
  1467  		},
  1468  	}
  1469  	for i := range tests {
  1470  		testFn(&tests[i], t)
  1471  	}
  1472  }
  1473  
  1474  func TestFindEqualRevisions(t *testing.T) {
  1475  	type testcase struct {
  1476  		name      string
  1477  		revision  *apps.ControllerRevision
  1478  		revisions []*apps.ControllerRevision
  1479  		want      map[string]bool
  1480  	}
  1481  	testFn := func(test *testcase, t *testing.T) {
  1482  		found := FindEqualRevisions(test.revisions, test.revision)
  1483  		if len(found) != len(test.want) {
  1484  			t.Errorf("%s: want %d revisions found %d", test.name, len(test.want), len(found))
  1485  		}
  1486  		for i := range found {
  1487  			if !test.want[found[i].Name] {
  1488  				t.Errorf("%s: wanted %s not found", test.name, found[i].Name)
  1489  			}
  1490  
  1491  		}
  1492  	}
  1493  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1494  	ss1.Status.CollisionCount = new(int32)
  1495  	ss2 := newStatefulSet(3, "ss2", types.UID("ss2"), map[string]string{"goo": "car"})
  1496  	ss2.Status.CollisionCount = new(int32)
  1497  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1498  	if err != nil {
  1499  		t.Fatal(err)
  1500  	}
  1501  	ss1Rev1.Namespace = ss1.Namespace
  1502  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1503  	if err != nil {
  1504  		t.Fatal(err)
  1505  	}
  1506  	ss1Rev2.Namespace = ss1.Namespace
  1507  	ss1Rev2.OwnerReferences = []metav1.OwnerReference{}
  1508  	ss2Rev1, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 1, ss2.Status.CollisionCount)
  1509  	if err != nil {
  1510  		t.Fatal(err)
  1511  	}
  1512  	ss2Rev1.Namespace = ss2.Namespace
  1513  	ss2Rev2, err := NewControllerRevision(ss2, parentKind, ss2.Spec.Template.Labels, rawTemplate(&ss2.Spec.Template), 2, ss2.Status.CollisionCount)
  1514  	if err != nil {
  1515  		t.Fatal(err)
  1516  	}
  1517  	ss2Rev2.Namespace = ss2.Namespace
  1518  	tests := []testcase{
  1519  		{
  1520  			name:      "finds equivalent",
  1521  			revision:  ss1Rev1,
  1522  			revisions: []*apps.ControllerRevision{ss1Rev1, ss2Rev1, ss2Rev2},
  1523  			want:      map[string]bool{ss1Rev1.Name: true},
  1524  		},
  1525  		{
  1526  			name:      "finds nothing when empty",
  1527  			revision:  ss1Rev1,
  1528  			revisions: nil,
  1529  			want:      map[string]bool{},
  1530  		},
  1531  		{
  1532  			name:      "finds nothing with no matches",
  1533  			revision:  ss1Rev1,
  1534  			revisions: []*apps.ControllerRevision{ss2Rev2, ss2Rev1},
  1535  			want:      map[string]bool{},
  1536  		},
  1537  	}
  1538  	for i := range tests {
  1539  		testFn(&tests[i], t)
  1540  	}
  1541  }
  1542  
  1543  func TestSortControllerRevisions(t *testing.T) {
  1544  	type testcase struct {
  1545  		name      string
  1546  		revisions []*apps.ControllerRevision
  1547  		want      []string
  1548  	}
  1549  	testFn := func(test *testcase, t *testing.T) {
  1550  		t.Run(test.name, func(t *testing.T) {
  1551  			SortControllerRevisions(test.revisions)
  1552  			for i := range test.revisions {
  1553  				if test.revisions[i].Name != test.want[i] {
  1554  					t.Errorf("%s: want %s at %d got %s", test.name, test.want[i], i, test.revisions[i].Name)
  1555  				}
  1556  			}
  1557  		})
  1558  	}
  1559  	ss1 := newStatefulSet(3, "ss1", types.UID("ss1"), map[string]string{"foo": "bar"})
  1560  	ss1.Status.CollisionCount = new(int32)
  1561  
  1562  	ss1Rev1, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 1, ss1.Status.CollisionCount)
  1563  	if err != nil {
  1564  		t.Fatal(err)
  1565  	}
  1566  
  1567  	ss1Rev1.Namespace = ss1.Namespace
  1568  	ss1Rev2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 2, ss1.Status.CollisionCount)
  1569  	if err != nil {
  1570  		t.Fatal(err)
  1571  	}
  1572  
  1573  	ss1Rev2.Namespace = ss1.Namespace
  1574  	ss1Rev3, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount)
  1575  	if err != nil {
  1576  		t.Fatal(err)
  1577  	}
  1578  
  1579  	ss1Rev3Time2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount)
  1580  	if err != nil {
  1581  		t.Fatal(err)
  1582  	}
  1583  	ss1Rev3Time2.Namespace = ss1.Namespace
  1584  	ss1Rev3Time2.CreationTimestamp = metav1.Time{Time: ss1Rev3.CreationTimestamp.Add(time.Second)}
  1585  
  1586  	ss1Rev3Time2Name2, err := NewControllerRevision(ss1, parentKind, ss1.Spec.Template.Labels, rawTemplate(&ss1.Spec.Template), 3, ss1.Status.CollisionCount)
  1587  	if err != nil {
  1588  		t.Fatal(err)
  1589  	}
  1590  	ss1Rev3Time2Name2.Namespace = ss1.Namespace
  1591  	ss1Rev3Time2Name2.CreationTimestamp = metav1.Time{Time: ss1Rev3.CreationTimestamp.Add(time.Second)}
  1592  
  1593  	tests := []testcase{
  1594  		{
  1595  			name:      "out of order",
  1596  			revisions: []*apps.ControllerRevision{ss1Rev2, ss1Rev1, ss1Rev3},
  1597  			want:      []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name},
  1598  		},
  1599  		{
  1600  			name:      "sorted",
  1601  			revisions: []*apps.ControllerRevision{ss1Rev1, ss1Rev2, ss1Rev3},
  1602  			want:      []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name},
  1603  		},
  1604  		{
  1605  			name:      "reversed",
  1606  			revisions: []*apps.ControllerRevision{ss1Rev3, ss1Rev2, ss1Rev1},
  1607  			want:      []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name},
  1608  		},
  1609  		{
  1610  			name:      "with ties",
  1611  			revisions: []*apps.ControllerRevision{ss1Rev3, ss1Rev3Time2, ss1Rev2, ss1Rev1},
  1612  			want:      []string{ss1Rev1.Name, ss1Rev2.Name, ss1Rev3.Name, ss1Rev3Time2.Name, ss1Rev3Time2Name2.Name},
  1613  		},
  1614  		{
  1615  			name:      "empty",
  1616  			revisions: nil,
  1617  			want:      nil,
  1618  		},
  1619  	}
  1620  	for i := range tests {
  1621  		testFn(&tests[i], t)
  1622  	}
  1623  }
  1624  
  1625  func newStatefulSet(replicas int, name string, uid types.UID, labels map[string]string) *apps.StatefulSet {
  1626  	// Converting all the map-only selectors to set-based selectors.
  1627  	var testMatchExpressions []metav1.LabelSelectorRequirement
  1628  	for key, value := range labels {
  1629  		sel := metav1.LabelSelectorRequirement{
  1630  			Key:      key,
  1631  			Operator: metav1.LabelSelectorOpIn,
  1632  			Values:   []string{value},
  1633  		}
  1634  		testMatchExpressions = append(testMatchExpressions, sel)
  1635  	}
  1636  	return &apps.StatefulSet{
  1637  		TypeMeta: metav1.TypeMeta{
  1638  			Kind:       "StatefulSet",
  1639  			APIVersion: "apps/v1",
  1640  		},
  1641  		ObjectMeta: metav1.ObjectMeta{
  1642  			Name:      name,
  1643  			Namespace: v1.NamespaceDefault,
  1644  			UID:       uid,
  1645  		},
  1646  		Spec: apps.StatefulSetSpec{
  1647  			Selector: &metav1.LabelSelector{
  1648  				// Purposely leaving MatchLabels nil, so to ensure it will break if any link
  1649  				// in the chain ignores the set-based MatchExpressions.
  1650  				MatchLabels:      nil,
  1651  				MatchExpressions: testMatchExpressions,
  1652  			},
  1653  			Replicas: pointer.Int32(int32(replicas)),
  1654  			Template: v1.PodTemplateSpec{
  1655  				ObjectMeta: metav1.ObjectMeta{
  1656  					Labels: labels,
  1657  				},
  1658  				Spec: v1.PodSpec{
  1659  					Containers: []v1.Container{
  1660  						{
  1661  							Name:  "nginx",
  1662  							Image: "nginx",
  1663  							VolumeMounts: []v1.VolumeMount{
  1664  								{Name: "datadir", MountPath: "/tmp/"},
  1665  								{Name: "home", MountPath: "/home"},
  1666  							},
  1667  						},
  1668  					},
  1669  					Volumes: []v1.Volume{{
  1670  						Name: "home",
  1671  						VolumeSource: v1.VolumeSource{
  1672  							HostPath: &v1.HostPathVolumeSource{
  1673  								Path: fmt.Sprintf("/tmp/%v", "home"),
  1674  							},
  1675  						}}},
  1676  				},
  1677  			},
  1678  			VolumeClaimTemplates: []v1.PersistentVolumeClaim{
  1679  				{
  1680  					ObjectMeta: metav1.ObjectMeta{Name: "datadir"},
  1681  					Spec: v1.PersistentVolumeClaimSpec{
  1682  						Resources: v1.VolumeResourceRequirements{
  1683  							Requests: v1.ResourceList{
  1684  								v1.ResourceStorage: *resource.NewQuantity(1, resource.BinarySI),
  1685  							},
  1686  						},
  1687  					},
  1688  				},
  1689  			},
  1690  			ServiceName: "governingsvc",
  1691  		},
  1692  	}
  1693  }
  1694  
  1695  var parentKind = apps.SchemeGroupVersion.WithKind("StatefulSet")
  1696  
  1697  func rawTemplate(template *v1.PodTemplateSpec) runtime.RawExtension {
  1698  	buf := new(bytes.Buffer)
  1699  	enc := json.NewEncoder(buf)
  1700  	if err := enc.Encode(template); err != nil {
  1701  		panic(err)
  1702  	}
  1703  	return runtime.RawExtension{Raw: buf.Bytes()}
  1704  }
  1705  

View as plain text