Browse code

Add test for patch+conflicts

Jordan Liggitt authored on 2016/03/18 06:38:36
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,121 @@
0
+// +build integration
1
+
2
+package integration
3
+
4
+import (
5
+	"fmt"
6
+	"sync"
7
+	"sync/atomic"
8
+	"testing"
9
+
10
+	"github.com/pborman/uuid"
11
+
12
+	kapi "k8s.io/kubernetes/pkg/api"
13
+	kapierrs "k8s.io/kubernetes/pkg/api/errors"
14
+	"k8s.io/kubernetes/pkg/api/meta"
15
+	"k8s.io/kubernetes/pkg/apiserver"
16
+	"k8s.io/kubernetes/pkg/client/restclient"
17
+
18
+	templatesapi "github.com/openshift/origin/pkg/template/api"
19
+	testutil "github.com/openshift/origin/test/util"
20
+	testserver "github.com/openshift/origin/test/util/server"
21
+)
22
+
23
+func TestPatchConflicts(t *testing.T) {
24
+
25
+	testutil.RequireEtcd(t)
26
+
27
+	_, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI()
28
+
29
+	if err != nil {
30
+		t.Fatalf("unexpected error: %v", err)
31
+	}
32
+
33
+	clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig)
34
+	if err != nil {
35
+		t.Fatalf("unexpected error: %v", err)
36
+	}
37
+
38
+	clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig)
39
+	if err != nil {
40
+		t.Fatalf("unexpected error: %v", err)
41
+	}
42
+
43
+	objName := "myobj"
44
+	ns := "patch-namespace"
45
+
46
+	if _, err := clusterAdminKubeClient.Namespaces().Create(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: ns}}); err != nil {
47
+		t.Fatalf("Error creating namespace:%v", err)
48
+	}
49
+	if _, err := clusterAdminKubeClient.Secrets(ns).Create(&kapi.Secret{ObjectMeta: kapi.ObjectMeta{Name: objName}}); err != nil {
50
+		t.Fatalf("Error creating k8s resource:%v", err)
51
+	}
52
+	if _, err := clusterAdminClient.Templates(ns).Create(&templatesapi.Template{ObjectMeta: kapi.ObjectMeta{Name: objName}}); err != nil {
53
+		t.Fatalf("Error creating origin resource:%v", err)
54
+	}
55
+
56
+	testcases := []struct {
57
+		client   *restclient.RESTClient
58
+		resource string
59
+	}{
60
+		{
61
+			client:   clusterAdminKubeClient.RESTClient,
62
+			resource: "secrets",
63
+		},
64
+		{
65
+			client:   clusterAdminClient.RESTClient,
66
+			resource: "templates",
67
+		},
68
+	}
69
+
70
+	for _, tc := range testcases {
71
+		successes := int32(0)
72
+
73
+		// Force patch to deal with resourceVersion conflicts applying non-conflicting patches
74
+		// ensure it handles reapplies without internal errors
75
+		wg := sync.WaitGroup{}
76
+		for i := 0; i < (2 * apiserver.MaxPatchConflicts); i++ {
77
+			wg.Add(1)
78
+			go func(labelName string) {
79
+				defer wg.Done()
80
+				labelValue := uuid.NewRandom().String()
81
+
82
+				obj, err := tc.client.Patch(kapi.StrategicMergePatchType).
83
+					Namespace(ns).
84
+					Resource(tc.resource).
85
+					Name(objName).
86
+					Body([]byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`, labelName, labelValue))).
87
+					Do().
88
+					Get()
89
+
90
+				if kapierrs.IsConflict(err) {
91
+					t.Logf("tolerated conflict error patching %s: %v", tc.resource, err)
92
+					return
93
+				}
94
+				if err != nil {
95
+					t.Errorf("error patching %s: %v", tc.resource, err)
96
+					return
97
+				}
98
+
99
+				accessor, err := meta.Accessor(obj)
100
+				if err != nil {
101
+					t.Errorf("error getting object from %s: %v", tc.resource, err)
102
+					return
103
+				}
104
+				if accessor.GetLabels()[labelName] != labelValue {
105
+					t.Errorf("patch of %s was ineffective, expected %s=%s, got labels %#v", tc.resource, labelName, labelValue, accessor.GetLabels())
106
+					return
107
+				}
108
+
109
+				atomic.AddInt32(&successes, 1)
110
+			}(fmt.Sprintf("label-%d", i))
111
+		}
112
+		wg.Wait()
113
+
114
+		if successes < apiserver.MaxPatchConflicts {
115
+			t.Errorf("Expected at least %d successful patches for %s, got %d", apiserver.MaxPatchConflicts, tc.resource, successes)
116
+		} else {
117
+			t.Logf("Got %d successful patches for %s", successes, tc.resource)
118
+		}
119
+	}
120
+}