go.temporal.io/server/tests/namespace_test.go
458 LOC · 0 covered · 458 uncovered · 0 ranges · 0 concepts · 0 introducers · 0 tests
1
package tests
2
3
import (
4
"errors"
5
"fmt"
6
"strconv"
7
"testing"
8
"time"
9
10
"github.com/google/uuid"
11
commonpb "go.temporal.io/api/common/v1"
12
enumspb "go.temporal.io/api/enums/v1"
13
"go.temporal.io/api/operatorservice/v1"
14
"go.temporal.io/api/serviceerror"
15
taskqueuepb "go.temporal.io/api/taskqueue/v1"
16
"go.temporal.io/api/workflowservice/v1"
17
"go.temporal.io/server/chasm"
18
"go.temporal.io/server/common"
19
"go.temporal.io/server/common/dynamicconfig"
20
"go.temporal.io/server/common/persistence"
21
"go.temporal.io/server/common/testing/parallelsuite"
22
"go.temporal.io/server/common/testing/testvars"
23
"go.temporal.io/server/tests/testcore"
24
"google.golang.org/protobuf/types/known/durationpb"
25
)
26
27
type (
28
namespaceTestSuite struct {
29
parallelsuite.Suite[*namespaceTestSuite]
30
}
31
)
32
33
func TestNamespaceSuite(t *testing.T) {
34
parallelsuite.RunLegacySequential(t, &namespaceTestSuite{}) //nolint:staticcheck // SA1019: namespace deletion tests use dedicated worker-service clusters.
35
}
36
37
func (s *namespaceTestSuite) newTestEnv(opts ...testcore.TestOption) *testcore.TestEnv {
38
baseOpts := []testcore.TestOption{
39
testcore.WithWorkerService("namespace deletion tests require the system worker service"),
40
testcore.WithDynamicConfig(dynamicconfig.TransferProcessorUpdateAckInterval, 1*time.Second),
41
testcore.WithDynamicConfig(dynamicconfig.VisibilityProcessorUpdateAckInterval, 1*time.Second),
42
}
43
return testcore.NewEnv(s.T(), append(baseOpts, opts...)...)
44
}
45
46
func (s *namespaceTestSuite) Test_NamespaceDelete_Empty() {
47
env := s.newTestEnv()
48
49
retention := 24 * time.Hour
50
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
51
Namespace: "ns_name_san_diego",
52
Description: "Namespace to delete",
53
WorkflowExecutionRetentionPeriod: durationpb.New(retention),
54
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
55
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
56
})
57
s.NoError(err)
58
59
descResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
60
Namespace: "ns_name_san_diego",
61
})
62
s.NoError(err)
63
nsID := descResp.GetNamespaceInfo().GetId()
64
65
delResp, err := env.OperatorClient().DeleteNamespace(s.Context(), &operatorservice.DeleteNamespaceRequest{
66
Namespace: "ns_name_san_diego",
67
})
68
s.NoError(err)
69
s.Equal("ns_name_san_diego-deleted-"+nsID[:5], delResp.GetDeletedNamespace())
70
71
descResp2, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
72
Id: nsID,
73
})
74
s.NoError(err)
75
s.Equal(enumspb.NAMESPACE_STATE_DELETED, descResp2.GetNamespaceInfo().GetState())
76
s.Eventually(func() bool {
77
_, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
78
Id: nsID,
79
})
80
var notFound *serviceerror.NamespaceNotFound
81
if !errors.As(err, ¬Found) {
82
return false
83
}
84
85
return true
86
}, 20*time.Second, time.Second)
87
}
88
89
func (s *namespaceTestSuite) Test_NamespaceDelete_OverrideDelay() {
90
env := s.newTestEnv(testcore.WithDynamicConfig(dynamicconfig.DeleteNamespaceNamespaceDeleteDelay, time.Hour))
91
92
retention := 24 * time.Hour
93
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
94
Namespace: "ns_name_san_diego",
95
Description: "Namespace to delete",
96
WorkflowExecutionRetentionPeriod: durationpb.New(retention),
97
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
98
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
99
})
100
s.NoError(err)
101
102
descResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
103
Namespace: "ns_name_san_diego",
104
})
105
s.NoError(err)
106
nsID := descResp.GetNamespaceInfo().GetId()
107
108
delResp, err := env.OperatorClient().DeleteNamespace(s.Context(), &operatorservice.DeleteNamespaceRequest{
109
Namespace: "ns_name_san_diego",
110
NamespaceDeleteDelay: durationpb.New(0),
111
})
112
s.NoError(err)
113
s.Equal("ns_name_san_diego-deleted-"+nsID[:5], delResp.GetDeletedNamespace())
114
115
descResp2, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
116
Id: nsID,
117
})
118
s.NoError(err)
119
s.Equal(enumspb.NAMESPACE_STATE_DELETED, descResp2.GetNamespaceInfo().GetState())
120
s.Eventually(func() bool {
121
_, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
122
Id: nsID,
123
})
124
var notFound *serviceerror.NamespaceNotFound
125
if !errors.As(err, ¬Found) {
126
return false
127
}
128
129
return true
130
}, 20*time.Second, time.Second)
131
}
132
133
func (s *namespaceTestSuite) Test_NamespaceDelete_Empty_WithID() {
134
env := s.newTestEnv()
135
136
retention := 24 * time.Hour
137
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
138
Namespace: "ns_name_san_diego",
139
Description: "Namespace to delete",
140
WorkflowExecutionRetentionPeriod: durationpb.New(retention),
141
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
142
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
143
})
144
s.NoError(err)
145
146
descResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
147
Namespace: "ns_name_san_diego",
148
})
149
s.NoError(err)
150
nsID := descResp.GetNamespaceInfo().GetId()
151
152
delResp, err := env.OperatorClient().DeleteNamespace(s.Context(), &operatorservice.DeleteNamespaceRequest{
153
NamespaceId: nsID,
154
})
155
s.NoError(err)
156
s.Equal("ns_name_san_diego-deleted-"+nsID[:5], delResp.GetDeletedNamespace())
157
158
descResp2, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
159
Id: nsID,
160
})
161
s.NoError(err)
162
s.Equal(enumspb.NAMESPACE_STATE_DELETED, descResp2.GetNamespaceInfo().GetState())
163
s.Eventually(func() bool {
164
_, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
165
Id: nsID,
166
})
167
var notFound *serviceerror.NamespaceNotFound
168
if !errors.As(err, ¬Found) {
169
return false
170
}
171
172
return true
173
}, 20*time.Second, time.Second)
174
}
175
176
func (s *namespaceTestSuite) Test_NamespaceDelete_WithNameAndID() {
177
env := s.newTestEnv()
178
179
retention := 24 * time.Hour
180
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
181
Namespace: "ns_name_san_diego",
182
Description: "Namespace to delete",
183
WorkflowExecutionRetentionPeriod: durationpb.New(retention),
184
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
185
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
186
})
187
s.NoError(err)
188
189
descResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
190
Namespace: "ns_name_san_diego",
191
})
192
s.NoError(err)
193
nsID := descResp.GetNamespaceInfo().GetId()
194
195
_, err = env.OperatorClient().DeleteNamespace(s.Context(), &operatorservice.DeleteNamespaceRequest{
196
Namespace: "ns_name_san_diego",
197
NamespaceId: nsID,
198
})
199
s.EqualError(err, "Only one of namespace name or Id should be set on request.")
200
}
201
202
func (s *namespaceTestSuite) Test_NamespaceDelete_WithWorkflows() {
203
env := s.newTestEnv()
204
205
retention := 24 * time.Hour
206
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
207
Namespace: "ns_name_seattle",
208
Description: "Namespace to delete",
209
WorkflowExecutionRetentionPeriod: durationpb.New(retention),
210
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
211
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
212
})
213
s.NoError(err)
214
215
descResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
216
Namespace: "ns_name_seattle",
217
})
218
s.NoError(err)
219
nsID := descResp.GetNamespaceInfo().GetId()
220
221
// Start few workflow executions.
222
var executions []*commonpb.WorkflowExecution
223
for i := range 100 {
224
wid := "wf_id_" + strconv.Itoa(i)
225
resp, err := env.FrontendClient().StartWorkflowExecution(s.Context(), &workflowservice.StartWorkflowExecutionRequest{
226
RequestId: uuid.NewString(),
227
Namespace: "ns_name_seattle",
228
WorkflowId: wid,
229
WorkflowType: &commonpb.WorkflowType{Name: "workflowTypeName"},
230
TaskQueue: &taskqueuepb.TaskQueue{Name: "taskQueueName", Kind: enumspb.TASK_QUEUE_KIND_NORMAL},
231
})
232
s.NoError(err)
233
executions = append(executions, &commonpb.WorkflowExecution{
234
WorkflowId: wid,
235
RunId: resp.GetRunId(),
236
})
237
}
238
239
// Terminate some workflow executions.
240
for _, execution := range executions[:30] {
241
_, err = env.FrontendClient().TerminateWorkflowExecution(s.Context(), &workflowservice.TerminateWorkflowExecutionRequest{
242
Namespace: "ns_name_seattle",
243
WorkflowExecution: execution,
244
})
245
s.NoError(err)
246
}
247
248
delResp, err := env.OperatorClient().DeleteNamespace(s.Context(), &operatorservice.DeleteNamespaceRequest{
249
Namespace: "ns_name_seattle",
250
})
251
s.NoError(err)
252
s.Equal("ns_name_seattle-deleted-"+nsID[:5], delResp.GetDeletedNamespace())
253
254
descResp2, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
255
Id: nsID,
256
})
257
s.NoError(err)
258
s.Equal(enumspb.NAMESPACE_STATE_DELETED, descResp2.GetNamespaceInfo().GetState())
259
260
s.Eventually(func() bool {
261
_, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
262
Id: nsID,
263
})
264
var notFound *serviceerror.NamespaceNotFound
265
if !errors.As(err, ¬Found) {
266
return false // namespace still exists
267
}
268
269
for _, execution := range executions {
270
_, err = env.FrontendClient().DescribeWorkflowExecution(s.Context(), &workflowservice.DescribeWorkflowExecutionRequest{
271
Namespace: "ns_name_seattle",
272
Execution: &commonpb.WorkflowExecution{
273
WorkflowId: execution.GetWorkflowId(),
274
},
275
})
276
if !errors.As(err, ¬Found) {
277
return false // should never happen
278
}
279
}
280
return true
281
}, 20*time.Second, time.Second)
282
}
283
284
func (s *namespaceTestSuite) Test_NamespaceDelete_WithMissingWorkflows() {
285
env := s.newTestEnv()
286
287
retention := 24 * time.Hour
288
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
289
Namespace: "ns_name_los_angeles",
290
Description: "Namespace to delete",
291
WorkflowExecutionRetentionPeriod: durationpb.New(retention),
292
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
293
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
294
})
295
s.NoError(err)
296
297
descResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
298
Namespace: "ns_name_los_angeles",
299
})
300
s.NoError(err)
301
nsID := descResp.GetNamespaceInfo().GetId()
302
303
// Start few workflow executions.
304
305
var executions []*commonpb.WorkflowExecution
306
for i := range 10 {
307
wid := "wf_id_" + strconv.Itoa(i)
308
resp, err := env.FrontendClient().StartWorkflowExecution(s.Context(), &workflowservice.StartWorkflowExecutionRequest{
309
RequestId: uuid.NewString(),
310
Namespace: "ns_name_los_angeles",
311
WorkflowId: wid,
312
WorkflowType: &commonpb.WorkflowType{Name: "workflowTypeName"},
313
TaskQueue: &taskqueuepb.TaskQueue{Name: "taskQueueName", Kind: enumspb.TASK_QUEUE_KIND_NORMAL},
314
})
315
s.NoError(err)
316
executions = append(executions, &commonpb.WorkflowExecution{
317
WorkflowId: wid,
318
RunId: resp.GetRunId(),
319
})
320
}
321
322
// Delete some workflow executions from DB but not from visibility.
323
// Every subsequent delete (from deleteexecutions.Workflow) from ES will take at least 1s due to bulk processor.
324
for _, execution := range executions[0:5] {
325
shardID := common.WorkflowIDToHistoryShard(
326
nsID,
327
execution.GetWorkflowId(),
328
env.GetTestClusterConfig().HistoryConfig.NumHistoryShards,
329
)
330
331
err = env.GetTestCluster().ExecutionManager().DeleteWorkflowExecution(s.Context(), &persistence.DeleteWorkflowExecutionRequest{
332
ShardID: shardID,
333
NamespaceID: nsID,
334
WorkflowID: execution.GetWorkflowId(),
335
RunID: execution.GetRunId(),
336
ArchetypeID: chasm.WorkflowArchetypeID,
337
})
338
s.NoError(err)
339
}
340
341
delResp, err := env.OperatorClient().DeleteNamespace(s.Context(), &operatorservice.DeleteNamespaceRequest{
342
Namespace: "ns_name_los_angeles",
343
})
344
s.NoError(err)
345
s.Equal("ns_name_los_angeles-deleted-"+nsID[:5], delResp.GetDeletedNamespace())
346
347
descResp2, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
348
Id: nsID,
349
})
350
s.NoError(err)
351
s.Equal(enumspb.NAMESPACE_STATE_DELETED, descResp2.GetNamespaceInfo().GetState())
352
353
s.Eventually(func() bool {
354
_, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
355
Id: nsID,
356
})
357
var notFound *serviceerror.NamespaceNotFound
358
if !errors.As(err, ¬Found) {
359
return false // namespace still exists
360
}
361
362
for _, execution := range executions {
363
_, err = env.FrontendClient().DescribeWorkflowExecution(s.Context(), &workflowservice.DescribeWorkflowExecutionRequest{
364
Namespace: "ns_name_los_angeles",
365
Execution: &commonpb.WorkflowExecution{
366
WorkflowId: execution.GetWorkflowId(),
367
},
368
})
369
if !errors.As(err, ¬Found) {
370
return false // should never happen
371
}
372
}
373
return true
374
}, 20*time.Second, time.Second)
375
}
376
377
func (s *namespaceTestSuite) Test_NamespaceDelete_CrossNamespaceChild() {
378
// TODO (alex): create 2 namespaces, start workflow in first namespace and start child in second namespace.
379
// Delete second namespace and verify that parent received child termination signal.
380
}
381
382
func (s *namespaceTestSuite) Test_NamespaceDelete_Protected() {
383
tv := testvars.New(s.T())
384
env := s.newTestEnv(testcore.WithDynamicConfig(dynamicconfig.ProtectedNamespaces, []string{tv.NamespaceName().String()}))
385
386
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
387
Namespace: tv.NamespaceName().String(),
388
Description: tv.Any().String(),
389
WorkflowExecutionRetentionPeriod: tv.Any().InfiniteTimeout(),
390
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
391
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
392
})
393
s.NoError(err)
394
395
delResp, err := env.OperatorClient().DeleteNamespace(s.Context(), &operatorservice.DeleteNamespaceRequest{
396
Namespace: tv.NamespaceName().String(),
397
})
398
s.Error(err)
399
s.Nil(delResp)
400
401
var failedPreconditionErr *serviceerror.FailedPrecondition
402
s.ErrorAs(err, &failedPreconditionErr)
403
s.Equal(fmt.Sprintf("namespace %s is protected from deletion", tv.NamespaceName().String()), failedPreconditionErr.Message)
404
}
405
406
func (s *namespaceTestSuite) Test_DescribeNamespace_WeakConsistency() {
407
env := s.newTestEnv()
408
409
nsName := "ns_weak_" + uuid.NewString()
410
_, err := env.FrontendClient().RegisterNamespace(s.Context(), &workflowservice.RegisterNamespaceRequest{
411
Namespace: nsName,
412
Description: "weak consistency test",
413
WorkflowExecutionRetentionPeriod: durationpb.New(24 * time.Hour),
414
HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
415
VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
416
})
417
s.NoError(err)
418
419
var nsNotFound *serviceerror.NamespaceNotFound
420
421
// Cache is populated by the periodic refresh, so the weak path should eventually succeed.
422
var weakResp *workflowservice.DescribeNamespaceResponse
423
s.Eventually(func() bool {
424
weakResp, err = env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
425
Namespace: nsName,
426
WeakConsistency: true,
427
})
428
// fail the test if error is not nil or NamespaceNotFound
429
if err != nil && !errors.As(err, &nsNotFound) {
430
s.Failf("unexpected error", "Expected NamespaceNotFound error, got: %v", err)
431
}
432
return err == nil
433
}, 5*testcore.NamespaceCacheRefreshInterval, 100*time.Millisecond) //nolint:forbidigo
434
435
strongResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
436
Namespace: nsName,
437
})
438
s.NoError(err)
439
s.Equal(strongResp.GetNamespaceInfo().GetId(), weakResp.GetNamespaceInfo().GetId())
440
s.Equal(strongResp.GetNamespaceInfo().GetName(), weakResp.GetNamespaceInfo().GetName())
441
s.Equal(strongResp.GetIsGlobalNamespace(), weakResp.GetIsGlobalNamespace())
442
443
// Lookup by ID should also work via the weak path.
444
nsID := strongResp.GetNamespaceInfo().GetId()
445
weakByIDResp, err := env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
446
Id: nsID,
447
WeakConsistency: true,
448
})
449
s.NoError(err)
450
s.Equal(nsName, weakByIDResp.GetNamespaceInfo().GetName())
451
452
// Non-existent namespace should return NamespaceNotFound.
453
_, err = env.FrontendClient().DescribeNamespace(s.Context(), &workflowservice.DescribeNamespaceRequest{
454
Namespace: "ns_does_not_exist_" + uuid.NewString(),
455
WeakConsistency: true,
456
})
457
s.ErrorAs(err, &nsNotFound)
458
}