github.com/hernad/nomad@v1.6.112/nomad/namespace_endpoint_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package nomad 5 6 import ( 7 "fmt" 8 "testing" 9 "time" 10 11 msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc" 12 "github.com/hernad/nomad/acl" 13 "github.com/hernad/nomad/ci" 14 "github.com/hernad/nomad/helper/uuid" 15 "github.com/hernad/nomad/nomad/mock" 16 "github.com/hernad/nomad/nomad/structs" 17 "github.com/hernad/nomad/testutil" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 func TestNamespaceEndpoint_GetNamespace(t *testing.T) { 22 ci.Parallel(t) 23 assert := assert.New(t) 24 s1, cleanupS1 := TestServer(t, nil) 25 defer cleanupS1() 26 codec := rpcClient(t, s1) 27 testutil.WaitForLeader(t, s1.RPC) 28 29 // Create the register request 30 ns := mock.Namespace() 31 s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns}) 32 33 // Lookup the namespace 34 get := &structs.NamespaceSpecificRequest{ 35 Name: ns.Name, 36 QueryOptions: structs.QueryOptions{Region: "global"}, 37 } 38 var resp structs.SingleNamespaceResponse 39 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", get, &resp)) 40 assert.EqualValues(1000, resp.Index) 41 assert.Equal(ns, resp.Namespace) 42 43 // Lookup non-existing namespace 44 get.Name = uuid.Generate() 45 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", get, &resp)) 46 assert.EqualValues(1000, resp.Index) 47 assert.Nil(resp.Namespace) 48 } 49 50 func TestNamespaceEndpoint_GetNamespace_ACL(t *testing.T) { 51 ci.Parallel(t) 52 assert := assert.New(t) 53 s1, root, cleanupS1 := TestACLServer(t, nil) 54 defer cleanupS1() 55 codec := rpcClient(t, s1) 56 testutil.WaitForLeader(t, s1.RPC) 57 58 // Create the register request 59 ns1 := mock.Namespace() 60 ns2 := mock.Namespace() 61 state := s1.fsm.State() 62 s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2}) 63 64 // Create the policy and tokens 65 validToken := mock.CreatePolicyAndToken(t, state, 1002, "test-valid", 66 mock.NamespacePolicy(ns1.Name, "", []string{acl.NamespaceCapabilityReadJob})) 67 invalidToken := mock.CreatePolicyAndToken(t, state, 1003, "test-invalid", 68 mock.NamespacePolicy(ns2.Name, "", []string{acl.NamespaceCapabilityReadJob})) 69 70 get := &structs.NamespaceSpecificRequest{ 71 Name: ns1.Name, 72 QueryOptions: structs.QueryOptions{Region: "global"}, 73 } 74 75 // Lookup the namespace without a token and expect failure 76 { 77 var resp structs.SingleNamespaceResponse 78 err := msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", get, &resp) 79 assert.NotNil(err) 80 assert.Equal(err.Error(), structs.ErrPermissionDenied.Error()) 81 } 82 83 // Try with an invalid token 84 get.AuthToken = invalidToken.SecretID 85 { 86 var resp structs.SingleNamespaceResponse 87 err := msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", get, &resp) 88 assert.NotNil(err) 89 assert.Equal(err.Error(), structs.ErrPermissionDenied.Error()) 90 } 91 92 // Try with a valid token 93 get.AuthToken = validToken.SecretID 94 { 95 var resp structs.SingleNamespaceResponse 96 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", get, &resp)) 97 assert.EqualValues(1000, resp.Index) 98 assert.Equal(ns1, resp.Namespace) 99 } 100 101 // Try with a root token 102 get.AuthToken = root.SecretID 103 { 104 var resp structs.SingleNamespaceResponse 105 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", get, &resp)) 106 assert.EqualValues(1000, resp.Index) 107 assert.Equal(ns1, resp.Namespace) 108 } 109 } 110 111 func TestNamespaceEndpoint_GetNamespace_Blocking(t *testing.T) { 112 ci.Parallel(t) 113 assert := assert.New(t) 114 s1, cleanupS1 := TestServer(t, nil) 115 defer cleanupS1() 116 state := s1.fsm.State() 117 codec := rpcClient(t, s1) 118 testutil.WaitForLeader(t, s1.RPC) 119 120 // Create the namespaces 121 ns1 := mock.Namespace() 122 ns2 := mock.Namespace() 123 124 // First create an namespace 125 time.AfterFunc(100*time.Millisecond, func() { 126 assert.Nil(state.UpsertNamespaces(100, []*structs.Namespace{ns1})) 127 }) 128 129 // Upsert the namespace we are watching later 130 time.AfterFunc(200*time.Millisecond, func() { 131 assert.Nil(state.UpsertNamespaces(200, []*structs.Namespace{ns2})) 132 }) 133 134 // Lookup the namespace 135 req := &structs.NamespaceSpecificRequest{ 136 Name: ns2.Name, 137 QueryOptions: structs.QueryOptions{ 138 Region: "global", 139 MinQueryIndex: 150, 140 }, 141 } 142 var resp structs.SingleNamespaceResponse 143 start := time.Now() 144 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", req, &resp)) 145 assert.EqualValues(200, resp.Index) 146 assert.NotNil(resp.Namespace) 147 assert.Equal(ns2.Name, resp.Namespace.Name) 148 149 if elapsed := time.Since(start); elapsed < 200*time.Millisecond { 150 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 151 } 152 153 // Namespace delete triggers watches 154 time.AfterFunc(100*time.Millisecond, func() { 155 assert.Nil(state.DeleteNamespaces(300, []string{ns2.Name})) 156 }) 157 158 req.QueryOptions.MinQueryIndex = 250 159 var resp2 structs.SingleNamespaceResponse 160 start = time.Now() 161 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespace", req, &resp2)) 162 assert.EqualValues(300, resp2.Index) 163 assert.Nil(resp2.Namespace) 164 165 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 166 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 167 } 168 } 169 170 func TestNamespaceEndpoint_GetNamespaces(t *testing.T) { 171 ci.Parallel(t) 172 assert := assert.New(t) 173 s1, cleanupS1 := TestServer(t, nil) 174 defer cleanupS1() 175 codec := rpcClient(t, s1) 176 testutil.WaitForLeader(t, s1.RPC) 177 178 // Create the register request 179 ns1 := mock.Namespace() 180 ns2 := mock.Namespace() 181 s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2}) 182 183 // Lookup the namespace 184 get := &structs.NamespaceSetRequest{ 185 Namespaces: []string{ns1.Name, ns2.Name}, 186 QueryOptions: structs.QueryOptions{Region: "global"}, 187 } 188 var resp structs.NamespaceSetResponse 189 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespaces", get, &resp)) 190 assert.EqualValues(1000, resp.Index) 191 assert.Len(resp.Namespaces, 2) 192 assert.Contains(resp.Namespaces, ns1.Name) 193 assert.Contains(resp.Namespaces, ns2.Name) 194 } 195 196 func TestNamespaceEndpoint_GetNamespaces_ACL(t *testing.T) { 197 ci.Parallel(t) 198 assert := assert.New(t) 199 s1, root, cleanupS1 := TestACLServer(t, nil) 200 defer cleanupS1() 201 codec := rpcClient(t, s1) 202 testutil.WaitForLeader(t, s1.RPC) 203 204 // Create the register request 205 ns1 := mock.Namespace() 206 ns2 := mock.Namespace() 207 state := s1.fsm.State() 208 state.UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2}) 209 210 // Create the policy and tokens 211 validToken := mock.CreatePolicyAndToken(t, state, 1002, "test-valid", 212 mock.NamespacePolicy(ns1.Name, "", []string{acl.NamespaceCapabilityReadJob})) 213 214 // Lookup the namespace 215 get := &structs.NamespaceSetRequest{ 216 Namespaces: []string{ns1.Name, ns2.Name}, 217 QueryOptions: structs.QueryOptions{Region: "global"}, 218 } 219 220 // Lookup the namespaces without a token and expect a failure 221 { 222 var resp structs.NamespaceSetResponse 223 assert.NotNil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespaces", get, &resp)) 224 } 225 226 // Try with an non-management token 227 get.AuthToken = validToken.SecretID 228 { 229 var resp structs.NamespaceSetResponse 230 assert.NotNil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespaces", get, &resp)) 231 } 232 233 // Try with a root token 234 get.AuthToken = root.SecretID 235 { 236 var resp structs.NamespaceSetResponse 237 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespaces", get, &resp)) 238 assert.EqualValues(1000, resp.Index) 239 assert.Len(resp.Namespaces, 2) 240 assert.Contains(resp.Namespaces, ns1.Name) 241 assert.Contains(resp.Namespaces, ns2.Name) 242 } 243 } 244 245 func TestNamespaceEndpoint_GetNamespaces_Blocking(t *testing.T) { 246 ci.Parallel(t) 247 assert := assert.New(t) 248 s1, cleanupS1 := TestServer(t, nil) 249 defer cleanupS1() 250 state := s1.fsm.State() 251 codec := rpcClient(t, s1) 252 testutil.WaitForLeader(t, s1.RPC) 253 254 // Create the namespaces 255 ns1 := mock.Namespace() 256 ns2 := mock.Namespace() 257 258 // First create an namespace 259 time.AfterFunc(100*time.Millisecond, func() { 260 assert.Nil(state.UpsertNamespaces(100, []*structs.Namespace{ns1})) 261 }) 262 263 // Upsert the namespace we are watching later 264 time.AfterFunc(200*time.Millisecond, func() { 265 assert.Nil(state.UpsertNamespaces(200, []*structs.Namespace{ns2})) 266 }) 267 268 // Lookup the namespace 269 req := &structs.NamespaceSetRequest{ 270 Namespaces: []string{ns2.Name}, 271 QueryOptions: structs.QueryOptions{ 272 Region: "global", 273 MinQueryIndex: 150, 274 }, 275 } 276 var resp structs.NamespaceSetResponse 277 start := time.Now() 278 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespaces", req, &resp)) 279 assert.EqualValues(200, resp.Index) 280 assert.Len(resp.Namespaces, 1) 281 assert.Contains(resp.Namespaces, ns2.Name) 282 283 if elapsed := time.Since(start); elapsed < 200*time.Millisecond { 284 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 285 } 286 287 // Namespace delete triggers watches 288 time.AfterFunc(100*time.Millisecond, func() { 289 assert.Nil(state.DeleteNamespaces(300, []string{ns2.Name})) 290 }) 291 292 req.QueryOptions.MinQueryIndex = 250 293 var resp2 structs.NamespaceSetResponse 294 start = time.Now() 295 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.GetNamespaces", req, &resp2)) 296 assert.EqualValues(300, resp2.Index) 297 assert.Empty(resp2.Namespaces) 298 299 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 300 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 301 } 302 } 303 304 func TestNamespaceEndpoint_List(t *testing.T) { 305 ci.Parallel(t) 306 assert := assert.New(t) 307 s1, cleanupS1 := TestServer(t, nil) 308 defer cleanupS1() 309 codec := rpcClient(t, s1) 310 testutil.WaitForLeader(t, s1.RPC) 311 312 // Create the register request 313 ns1 := mock.Namespace() 314 ns2 := mock.Namespace() 315 316 ns1.Name = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9" 317 ns2.Name = "aaaabbbb-3350-4b4b-d185-0e1992ed43e9" 318 assert.Nil(s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2})) 319 320 // Lookup the namespaces 321 get := &structs.NamespaceListRequest{ 322 QueryOptions: structs.QueryOptions{Region: "global"}, 323 } 324 var resp structs.NamespaceListResponse 325 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", get, &resp)) 326 assert.EqualValues(1000, resp.Index) 327 assert.Len(resp.Namespaces, 3) 328 329 // Lookup the namespaces by prefix 330 get = &structs.NamespaceListRequest{ 331 QueryOptions: structs.QueryOptions{ 332 Region: "global", 333 Prefix: "aaaabb", 334 }, 335 } 336 var resp2 structs.NamespaceListResponse 337 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", get, &resp2)) 338 assert.EqualValues(1000, resp2.Index) 339 assert.Len(resp2.Namespaces, 1) 340 } 341 342 func TestNamespaceEndpoint_List_ACL(t *testing.T) { 343 ci.Parallel(t) 344 assert := assert.New(t) 345 s1, root, cleanupS1 := TestACLServer(t, nil) 346 defer cleanupS1() 347 codec := rpcClient(t, s1) 348 testutil.WaitForLeader(t, s1.RPC) 349 350 // Create the register request 351 ns1 := mock.Namespace() 352 ns2 := mock.Namespace() 353 state := s1.fsm.State() 354 355 ns1.Name = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9" 356 ns2.Name = "bbbbbbbb-3350-4b4b-d185-0e1992ed43e9" 357 assert.Nil(s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2})) 358 359 validDefToken := mock.CreatePolicyAndToken(t, state, 1001, "test-def-valid", 360 mock.NamespacePolicy(structs.DefaultNamespace, "", []string{acl.NamespaceCapabilityReadFS})) 361 validMultiToken := mock.CreatePolicyAndToken(t, state, 1002, "test-multi-valid", fmt.Sprintf("%s\n%s", 362 mock.NamespacePolicy(ns1.Name, "", []string{acl.NamespaceCapabilityReadJob}), 363 mock.NamespacePolicy(structs.DefaultNamespace, "", []string{acl.NamespaceCapabilityReadJob}))) 364 invalidToken := mock.CreatePolicyAndToken(t, state, 1003, "test-invalid", 365 mock.NamespacePolicy("invalid-namespace", "", []string{acl.NamespaceCapabilityReadJob})) 366 367 get := &structs.NamespaceListRequest{ 368 QueryOptions: structs.QueryOptions{Region: "global"}, 369 } 370 371 // Lookup the namespaces without a token and expect a failure 372 { 373 var resp structs.NamespaceListResponse 374 err := msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", get, &resp) 375 assert.Nil(err) 376 assert.Len(resp.Namespaces, 0) 377 } 378 379 // Try with an invalid token 380 get.AuthToken = invalidToken.SecretID 381 { 382 var resp structs.NamespaceListResponse 383 err := msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", get, &resp) 384 assert.Nil(err) 385 assert.Len(resp.Namespaces, 0) 386 } 387 388 // Try with a valid token for one 389 get.AuthToken = validDefToken.SecretID 390 { 391 var resp structs.NamespaceListResponse 392 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", get, &resp)) 393 assert.EqualValues(1000, resp.Index) 394 assert.Len(resp.Namespaces, 1) 395 } 396 397 // Try with a valid token for two 398 get.AuthToken = validMultiToken.SecretID 399 { 400 var resp structs.NamespaceListResponse 401 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", get, &resp)) 402 assert.EqualValues(1000, resp.Index) 403 assert.Len(resp.Namespaces, 2) 404 } 405 406 // Try with a root token 407 get.AuthToken = root.SecretID 408 { 409 var resp structs.NamespaceListResponse 410 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", get, &resp)) 411 assert.EqualValues(1000, resp.Index) 412 assert.Len(resp.Namespaces, 3) 413 } 414 } 415 416 func TestNamespaceEndpoint_List_Blocking(t *testing.T) { 417 ci.Parallel(t) 418 assert := assert.New(t) 419 s1, cleanupS1 := TestServer(t, nil) 420 defer cleanupS1() 421 state := s1.fsm.State() 422 codec := rpcClient(t, s1) 423 testutil.WaitForLeader(t, s1.RPC) 424 425 // Create the namespace 426 ns := mock.Namespace() 427 428 // Upsert namespace triggers watches 429 time.AfterFunc(100*time.Millisecond, func() { 430 assert.Nil(state.UpsertNamespaces(200, []*structs.Namespace{ns})) 431 }) 432 433 req := &structs.NamespaceListRequest{ 434 QueryOptions: structs.QueryOptions{ 435 Region: "global", 436 MinQueryIndex: 150, 437 }, 438 } 439 start := time.Now() 440 var resp structs.NamespaceListResponse 441 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", req, &resp)) 442 443 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 444 t.Fatalf("should block (returned in %s) %#v", elapsed, resp) 445 } 446 assert.EqualValues(200, resp.Index) 447 assert.Len(resp.Namespaces, 2) 448 449 // Namespace deletion triggers watches 450 time.AfterFunc(100*time.Millisecond, func() { 451 assert.Nil(state.DeleteNamespaces(300, []string{ns.Name})) 452 }) 453 454 req.MinQueryIndex = 200 455 start = time.Now() 456 var resp2 structs.NamespaceListResponse 457 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.ListNamespaces", req, &resp2)) 458 459 if elapsed := time.Since(start); elapsed < 100*time.Millisecond { 460 t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) 461 } 462 assert.EqualValues(300, resp2.Index) 463 assert.Len(resp2.Namespaces, 1) 464 } 465 466 func TestNamespaceEndpoint_DeleteNamespaces(t *testing.T) { 467 ci.Parallel(t) 468 assert := assert.New(t) 469 s1, cleanupS1 := TestServer(t, nil) 470 defer cleanupS1() 471 codec := rpcClient(t, s1) 472 testutil.WaitForLeader(t, s1.RPC) 473 474 // Create the register request 475 ns1 := mock.Namespace() 476 ns2 := mock.Namespace() 477 s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2}) 478 479 // Lookup the namespaces 480 req := &structs.NamespaceDeleteRequest{ 481 Namespaces: []string{ns1.Name, ns2.Name}, 482 WriteRequest: structs.WriteRequest{Region: "global"}, 483 } 484 var resp structs.GenericResponse 485 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp)) 486 assert.NotEqual(uint64(0), resp.Index) 487 } 488 489 func TestNamespaceEndpoint_DeleteNamespaces_NonTerminal_Local(t *testing.T) { 490 ci.Parallel(t) 491 assert := assert.New(t) 492 s1, cleanupS1 := TestServer(t, nil) 493 defer cleanupS1() 494 codec := rpcClient(t, s1) 495 testutil.WaitForLeader(t, s1.RPC) 496 497 // Create the register request 498 ns1 := mock.Namespace() 499 ns2 := mock.Namespace() 500 s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2}) 501 502 // Create a job in one 503 j := mock.Job() 504 j.Namespace = ns1.Name 505 assert.Nil(s1.fsm.State().UpsertJob(structs.MsgTypeTestSetup, 1001, nil, j)) 506 507 // Lookup the namespaces 508 req := &structs.NamespaceDeleteRequest{ 509 Namespaces: []string{ns1.Name, ns2.Name}, 510 WriteRequest: structs.WriteRequest{Region: "global"}, 511 } 512 var resp structs.GenericResponse 513 err := msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp) 514 if assert.NotNil(err) { 515 assert.Contains(err.Error(), "has non-terminal jobs") 516 } 517 } 518 519 func TestNamespaceEndpoint_DeleteNamespaces_NonTerminal_Federated_ACL(t *testing.T) { 520 ci.Parallel(t) 521 assert := assert.New(t) 522 s1, root, cleanupS1 := TestACLServer(t, func(c *Config) { 523 c.Region = "region1" 524 c.AuthoritativeRegion = "region1" 525 c.ACLEnabled = true 526 }) 527 defer cleanupS1() 528 s2, _, cleanupS2 := TestACLServer(t, func(c *Config) { 529 c.Region = "region2" 530 c.AuthoritativeRegion = "region1" 531 c.ACLEnabled = true 532 c.ReplicationBackoff = 20 * time.Millisecond 533 c.ReplicationToken = root.SecretID 534 }) 535 defer cleanupS2() 536 TestJoin(t, s1, s2) 537 testutil.WaitForLeader(t, s1.RPC) 538 testutil.WaitForLeader(t, s2.RPC) 539 codec := rpcClient(t, s1) 540 541 // Create the register request 542 ns1 := mock.Namespace() 543 s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1}) 544 545 testutil.WaitForResult(func() (bool, error) { 546 state := s2.State() 547 out, err := state.NamespaceByName(nil, ns1.Name) 548 return out != nil, err 549 }, func(err error) { 550 t.Fatalf("should replicate namespace") 551 }) 552 553 // Create a job in the namespace on the non-authority 554 j := mock.Job() 555 j.Namespace = ns1.Name 556 assert.Nil(s2.fsm.State().UpsertJob(structs.MsgTypeTestSetup, 1001, nil, j)) 557 558 // Delete the namespaces without the correct permissions 559 req := &structs.NamespaceDeleteRequest{ 560 Namespaces: []string{ns1.Name}, 561 WriteRequest: structs.WriteRequest{ 562 Region: "global", 563 }, 564 } 565 var resp structs.GenericResponse 566 err := msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp) 567 if assert.NotNil(err) { 568 assert.EqualError(err, structs.ErrPermissionDenied.Error()) 569 } 570 571 // Try with a auth token 572 req.AuthToken = root.SecretID 573 var resp2 structs.GenericResponse 574 err = msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp2) 575 if assert.NotNil(err) { 576 assert.Contains(err.Error(), "has non-terminal jobs") 577 } 578 } 579 580 func TestNamespaceEndpoint_DeleteNamespaces_ACL(t *testing.T) { 581 ci.Parallel(t) 582 assert := assert.New(t) 583 s1, root, cleanupS1 := TestACLServer(t, nil) 584 defer cleanupS1() 585 codec := rpcClient(t, s1) 586 testutil.WaitForLeader(t, s1.RPC) 587 588 ns1 := mock.Namespace() 589 ns2 := mock.Namespace() 590 state := s1.fsm.State() 591 s1.fsm.State().UpsertNamespaces(1000, []*structs.Namespace{ns1, ns2}) 592 593 // Create the policy and tokens 594 invalidToken := mock.CreatePolicyAndToken(t, state, 1003, "test-invalid", 595 mock.NamespacePolicy(structs.DefaultNamespace, "", []string{acl.NamespaceCapabilityReadJob})) 596 597 req := &structs.NamespaceDeleteRequest{ 598 Namespaces: []string{ns1.Name, ns2.Name}, 599 WriteRequest: structs.WriteRequest{Region: "global"}, 600 } 601 602 // Delete namespaces without a token and expect failure 603 { 604 var resp structs.GenericResponse 605 err := msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp) 606 assert.NotNil(err) 607 assert.Equal(err.Error(), structs.ErrPermissionDenied.Error()) 608 609 // Check we did not delete the namespaces 610 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 611 assert.Nil(err) 612 assert.NotNil(out) 613 614 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 615 assert.Nil(err) 616 assert.NotNil(out) 617 } 618 619 // Try with an invalid token 620 req.AuthToken = invalidToken.SecretID 621 { 622 var resp structs.GenericResponse 623 err := msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp) 624 assert.NotNil(err) 625 assert.Equal(err.Error(), structs.ErrPermissionDenied.Error()) 626 627 // Check we did not delete the namespaces 628 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 629 assert.Nil(err) 630 assert.NotNil(out) 631 632 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 633 assert.Nil(err) 634 assert.NotNil(out) 635 } 636 637 // Try with a root token 638 req.AuthToken = root.SecretID 639 { 640 var resp structs.GenericResponse 641 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp)) 642 assert.NotEqual(uint64(0), resp.Index) 643 644 // Check we deleted the namespaces 645 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 646 assert.Nil(err) 647 assert.Nil(out) 648 649 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 650 assert.Nil(err) 651 assert.Nil(out) 652 } 653 } 654 655 func TestNamespaceEndpoint_DeleteNamespaces_Default(t *testing.T) { 656 ci.Parallel(t) 657 assert := assert.New(t) 658 s1, cleanupS1 := TestServer(t, nil) 659 defer cleanupS1() 660 codec := rpcClient(t, s1) 661 testutil.WaitForLeader(t, s1.RPC) 662 663 // Delete the default namespace 664 req := &structs.NamespaceDeleteRequest{ 665 Namespaces: []string{structs.DefaultNamespace}, 666 WriteRequest: structs.WriteRequest{Region: "global"}, 667 } 668 var resp structs.GenericResponse 669 assert.NotNil(msgpackrpc.CallWithCodec(codec, "Namespace.DeleteNamespaces", req, &resp)) 670 } 671 672 func TestNamespaceEndpoint_UpsertNamespaces(t *testing.T) { 673 ci.Parallel(t) 674 assert := assert.New(t) 675 s1, cleanupS1 := TestServer(t, nil) 676 defer cleanupS1() 677 codec := rpcClient(t, s1) 678 testutil.WaitForLeader(t, s1.RPC) 679 680 // Create the register request 681 ns1 := mock.Namespace() 682 ns2 := mock.Namespace() 683 684 // Lookup the namespaces 685 req := &structs.NamespaceUpsertRequest{ 686 Namespaces: []*structs.Namespace{ns1, ns2}, 687 WriteRequest: structs.WriteRequest{Region: "global"}, 688 } 689 var resp structs.GenericResponse 690 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.UpsertNamespaces", req, &resp)) 691 assert.NotEqual(uint64(0), resp.Index) 692 693 // Check we created the namespaces 694 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 695 assert.Nil(err) 696 assert.NotNil(out) 697 698 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 699 assert.Nil(err) 700 assert.NotNil(out) 701 } 702 703 func TestNamespaceEndpoint_UpsertNamespaces_ACL(t *testing.T) { 704 ci.Parallel(t) 705 assert := assert.New(t) 706 s1, root, cleanupS1 := TestACLServer(t, nil) 707 defer cleanupS1() 708 codec := rpcClient(t, s1) 709 testutil.WaitForLeader(t, s1.RPC) 710 711 ns1 := mock.Namespace() 712 ns2 := mock.Namespace() 713 state := s1.fsm.State() 714 715 // Create the policy and tokens 716 invalidToken := mock.CreatePolicyAndToken(t, state, 1003, "test-invalid", 717 mock.NamespacePolicy(structs.DefaultNamespace, "", []string{acl.NamespaceCapabilityReadJob})) 718 719 // Create the register request 720 req := &structs.NamespaceUpsertRequest{ 721 Namespaces: []*structs.Namespace{ns1, ns2}, 722 WriteRequest: structs.WriteRequest{Region: "global"}, 723 } 724 725 // Upsert the namespace without a token and expect failure 726 { 727 var resp structs.GenericResponse 728 err := msgpackrpc.CallWithCodec(codec, "Namespace.UpsertNamespaces", req, &resp) 729 assert.NotNil(err) 730 assert.Equal(err.Error(), structs.ErrPermissionDenied.Error()) 731 732 // Check we did not create the namespaces 733 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 734 assert.Nil(err) 735 assert.Nil(out) 736 737 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 738 assert.Nil(err) 739 assert.Nil(out) 740 } 741 742 // Try with an invalid token 743 req.AuthToken = invalidToken.SecretID 744 { 745 var resp structs.GenericResponse 746 err := msgpackrpc.CallWithCodec(codec, "Namespace.UpsertNamespaces", req, &resp) 747 assert.NotNil(err) 748 assert.Equal(err.Error(), structs.ErrPermissionDenied.Error()) 749 750 // Check we did not create the namespaces 751 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 752 assert.Nil(err) 753 assert.Nil(out) 754 755 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 756 assert.Nil(err) 757 assert.Nil(out) 758 } 759 760 // Try with a bogus token 761 req.AuthToken = uuid.Generate() 762 { 763 var resp structs.GenericResponse 764 err := msgpackrpc.CallWithCodec(codec, "Namespace.UpsertNamespaces", req, &resp) 765 assert.NotNil(err) 766 assert.Equal(err.Error(), structs.ErrPermissionDenied.Error()) 767 768 // Check we did not create the namespaces 769 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 770 assert.Nil(err) 771 assert.Nil(out) 772 773 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 774 assert.Nil(err) 775 assert.Nil(out) 776 } 777 778 // Try with a root token 779 req.AuthToken = root.SecretID 780 { 781 var resp structs.GenericResponse 782 assert.Nil(msgpackrpc.CallWithCodec(codec, "Namespace.UpsertNamespaces", req, &resp)) 783 assert.NotEqual(uint64(0), resp.Index) 784 785 // Check we created the namespaces 786 out, err := s1.fsm.State().NamespaceByName(nil, ns1.Name) 787 assert.Nil(err) 788 assert.NotNil(out) 789 790 out, err = s1.fsm.State().NamespaceByName(nil, ns2.Name) 791 assert.Nil(err) 792 assert.NotNil(out) 793 } 794 }