1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package leaser_test
19
20 import (
21 "context"
22 "fmt"
23 "testing"
24 "time"
25
26 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
27 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/lease/leaser"
28 testreconciler "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller/reconciler"
29 testmain "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/main"
30 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/resourcefixture"
31 testrunner "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/runner"
32
33 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
34 "sigs.k8s.io/controller-runtime/pkg/manager"
35 )
36
37 var (
38 mgr manager.Manager
39 defaultLeaseDuration = 5 * time.Minute
40 )
41
42 func TestUnsupportedResourceShouldFail(t *testing.T) {
43 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
44 switch fixture.GVK.Kind {
45 case "SourceRepoRepository",
46 "DataflowJob":
47 return true
48 default:
49 return false
50 }
51 }
52 testFunc := func(t *testing.T, testContext testrunner.TestContext, systemContext testrunner.SystemContext) {
53 leaser := leaser.NewLeaser(systemContext.TFProvider, systemContext.SMLoader, systemContext.Manager.GetClient())
54 ok, err := leaser.UnstructuredSupportsLeasing(testContext.CreateUnstruct)
55 if err != nil {
56 t.Fatalf("error checking for lease support: %v", err)
57 }
58 if ok {
59 t.Fatalf("test should only be run on resources that do not support locking")
60 }
61 err = leaser.Obtain(context.Background(), testContext.CreateUnstruct, "my-owner-id", defaultLeaseDuration, defaultLeaseDuration)
62 if err == nil {
63 t.Fatalf("expected error, instead got nil")
64 }
65 expectedMsg := fmt.Sprintf("gvk '%v' does not support locking", testContext.CreateUnstruct.GroupVersionKind())
66 errMsg := err.Error()
67 if errMsg != expectedMsg {
68 t.Fatalf("unexpected error message: got '%v', want '%v'", errMsg, expectedMsg)
69 }
70 }
71 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testFunc)
72 }
73
74 func TestAll(t *testing.T) {
75 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
76 switch fixture.GVK.Kind {
77 case "PubSubTopic":
78 return true
79 default:
80 return false
81 }
82 }
83 testFunc := func(t *testing.T, testContext testrunner.TestContext, systemContext testrunner.SystemContext) {
84
85
86
87
88 k8s.SetAnnotation(k8s.ManagementConflictPreventionPolicyFullyQualifiedAnnotation, k8s.ManagementConflictPreventionPolicyNone, testContext.CreateUnstruct)
89 if err := systemContext.Manager.GetClient().Create(context.TODO(), testContext.CreateUnstruct); err != nil {
90 t.Fatalf("error creating resource: %v", err)
91 }
92 resourceCleanup := systemContext.Reconciler.BuildCleanupFunc(testContext.CreateUnstruct, testreconciler.CleanupPolicyAlways)
93 defer resourceCleanup()
94 systemContext.Reconciler.Reconcile(testContext.CreateUnstruct, testreconciler.ExpectedSuccessfulReconcileResultFor(systemContext.Reconciler, testContext.CreateUnstruct), nil)
95 leaser := leaser.NewLeaser(systemContext.TFProvider, systemContext.SMLoader, systemContext.Manager.GetClient())
96 uniqueId1 := fmt.Sprintf("l1-%v", testContext.UniqueId)
97 uniqueId2 := fmt.Sprintf("l2-%v", testContext.UniqueId)
98 initialUnstruct := testContext.CreateUnstruct
99 testObtainReleaseShouldSucceed(t, initialUnstruct, uniqueId1, leaser)
100 testObtainTwiceShouldSucceed(t, initialUnstruct, uniqueId1, leaser)
101 testReleaseUnobtainedShouldFail(t, initialUnstruct, uniqueId1, leaser)
102 testReleasingExpiredResourceShouldFail(t, initialUnstruct, uniqueId1, leaser)
103 testRenewLease(t, initialUnstruct, uniqueId1, leaser)
104 testObtainingPreviouslyReleasedResourceShouldSucceed(t, initialUnstruct, uniqueId1, uniqueId2, leaser)
105 testObtainingLockedResourceShouldFail(t, initialUnstruct, uniqueId1, uniqueId2, leaser)
106 testReleasingLockedResourceShouldFail(t, initialUnstruct, uniqueId1, uniqueId2, leaser)
107 testObtainingExpiredLeaseShouldSucceed(t, initialUnstruct, uniqueId1, uniqueId2, leaser)
108 }
109 testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testFunc)
110 }
111
112 func testObtainReleaseShouldSucceed(t *testing.T, u *unstructured.Unstructured, uniqueId string, leaser *leaser.Leaser) {
113 obtainAssertSuccess(t, u, uniqueId, defaultLeaseDuration, defaultLeaseDuration, leaser)
114 releaseAssertSuccess(t, u, uniqueId, leaser)
115 }
116
117 func testObtainTwiceShouldSucceed(t *testing.T, u *unstructured.Unstructured, uniqueId string, leaser *leaser.Leaser) {
118 obtainAssertSuccess(t, u, uniqueId, defaultLeaseDuration, defaultLeaseDuration, leaser)
119 obtainAssertSuccess(t, u, uniqueId, defaultLeaseDuration, defaultLeaseDuration, leaser)
120 releaseAssertSuccess(t, u, uniqueId, leaser)
121 }
122
123 func testReleaseUnobtainedShouldFail(t *testing.T, u *unstructured.Unstructured, uniqueId string, leaser *leaser.Leaser) {
124 releaseAssertError(t, u, uniqueId, leaser)
125 }
126
127 func testObtainingPreviouslyReleasedResourceShouldSucceed(t *testing.T, u *unstructured.Unstructured, uniqueId1, uniqueId2 string, leaser *leaser.Leaser) {
128 obtainAssertSuccess(t, u, uniqueId1, defaultLeaseDuration, defaultLeaseDuration, leaser)
129 releaseAssertSuccess(t, u, uniqueId1, leaser)
130 obtainAssertSuccess(t, u, uniqueId2, defaultLeaseDuration, defaultLeaseDuration, leaser)
131 releaseAssertSuccess(t, u, uniqueId2, leaser)
132 }
133
134 func testObtainingLockedResourceShouldFail(t *testing.T, u *unstructured.Unstructured, uniqueId1, uniqueId2 string, leaser *leaser.Leaser) {
135 obtainAssertSuccess(t, u, uniqueId1, defaultLeaseDuration, defaultLeaseDuration, leaser)
136 obtainAssertError(t, u, uniqueId2, defaultLeaseDuration, defaultLeaseDuration, leaser)
137 releaseAssertSuccess(t, u, uniqueId1, leaser)
138 }
139
140 func testReleasingLockedResourceShouldFail(t *testing.T, u *unstructured.Unstructured, uniqueId1, uniqueId2 string, leaser *leaser.Leaser) {
141 obtainAssertSuccess(t, u, uniqueId1, defaultLeaseDuration, defaultLeaseDuration, leaser)
142 releaseAssertError(t, u, uniqueId2, leaser)
143 releaseAssertSuccess(t, u, uniqueId1, leaser)
144 }
145
146 func testReleasingExpiredResourceShouldFail(t *testing.T, u *unstructured.Unstructured, uniqueId string, leaser *leaser.Leaser) {
147 shortLeaseDuration := 1 * time.Second
148 obtainAssertSuccess(t, u, uniqueId, shortLeaseDuration, shortLeaseDuration, leaser)
149 time.Sleep(shortLeaseDuration + 1*time.Second)
150 releaseAssertError(t, u, uniqueId, leaser)
151 }
152
153 func testObtainingExpiredLeaseShouldSucceed(t *testing.T, u *unstructured.Unstructured, uniqueId1, uniqueId2 string, leaser *leaser.Leaser) {
154 shortLeaseDuration := 10 * time.Second
155 obtainAssertSuccess(t, u, uniqueId1, shortLeaseDuration, shortLeaseDuration, leaser)
156 obtainAssertError(t, u, uniqueId2, defaultLeaseDuration, defaultLeaseDuration, leaser)
157 time.Sleep(shortLeaseDuration)
158 obtainAssertSuccess(t, u, uniqueId2, defaultLeaseDuration, defaultLeaseDuration, leaser)
159 releaseAssertError(t, u, uniqueId1, leaser)
160 releaseAssertSuccess(t, u, uniqueId2, leaser)
161 }
162
163 func testRenewLease(t *testing.T, u *unstructured.Unstructured, uniqueId string, leaser *leaser.Leaser) {
164 shortMinRemaining := 2 * time.Second
165 obtainAssertSuccess(t, u, uniqueId, defaultLeaseDuration, defaultLeaseDuration, leaser)
166 _, originalExpirationTIme := getOwnerAndExpirationTime(t, u, leaser)
167 obtainAssertSuccess(t, u, uniqueId, defaultLeaseDuration, shortMinRemaining, leaser)
168 _, expirationTime := getOwnerAndExpirationTime(t, u, leaser)
169 if expirationTime != originalExpirationTIme {
170 t.Fatalf("expected expiration times to be equal, instead '%v' and '%v'", expirationTime, originalExpirationTIme)
171 }
172 time.Sleep(shortMinRemaining + 1*time.Second)
173 obtainAssertSuccess(t, u, uniqueId, defaultLeaseDuration, defaultLeaseDuration-shortMinRemaining, leaser)
174 _, expirationTime = getOwnerAndExpirationTime(t, u, leaser)
175 if expirationTime == originalExpirationTIme {
176 t.Fatalf("expected expiration times to NOT be equal")
177 }
178 if originalExpirationTIme.After(expirationTime) {
179 t.Fatalf("expected original expiration time '%v' to be after updated expiration time '%v'", originalExpirationTIme, expirationTime)
180 }
181 releaseAssertSuccess(t, u, uniqueId, leaser)
182 }
183
184 func getOwnerAndExpirationTime(t *testing.T, u *unstructured.Unstructured, leaser *leaser.Leaser) (string, time.Time) {
185 ownerId, expirationTime, err := leaser.GetOwnerAndExpirationTime(context.Background(), u)
186 if err != nil {
187 t.Fatalf("error getting owner and expiration time: %v", err)
188 }
189 return ownerId, expirationTime
190 }
191
192 func obtainAssertSuccess(t *testing.T, u *unstructured.Unstructured, uniqueId string, duration time.Duration, minRemaining time.Duration, leaser *leaser.Leaser) {
193 t.Helper()
194 err := leaser.Obtain(context.Background(), u, uniqueId, duration, minRemaining)
195 if err != nil {
196 t.Fatalf("error obtaining lease: %v", err)
197 }
198 }
199
200 func obtainAssertError(t *testing.T, u *unstructured.Unstructured, uniqueId string, duration time.Duration, minRemaining time.Duration, leaser *leaser.Leaser) {
201 t.Helper()
202 err := leaser.Obtain(context.Background(), u, uniqueId, duration, minRemaining)
203 if err == nil {
204 t.Fatalf("expected error when obtaining, instead got 'nil'")
205 }
206 }
207
208 func releaseAssertSuccess(t *testing.T, u *unstructured.Unstructured, uniqueId string, leaser *leaser.Leaser) {
209 t.Helper()
210 err := leaser.Release(context.Background(), u, uniqueId)
211 if err != nil {
212 t.Fatalf("error obtaining lease: %v", err)
213 }
214 }
215
216 func releaseAssertError(t *testing.T, u *unstructured.Unstructured, uniqueId string, leaser *leaser.Leaser) {
217 t.Helper()
218 err := leaser.Release(context.Background(), u, uniqueId)
219 if err == nil {
220 t.Fatalf("expected error when releasing, instead got 'nil'")
221 }
222 }
223
224 func TestMain(m *testing.M) {
225 testmain.TestMainForIntegrationTests(m, &mgr)
226 }
227
View as plain text