open-nomad/nomad/periodic_endpoint_test.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

201 lines
5.6 KiB
Go
Raw Permalink Normal View History

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
2016-01-13 18:19:53 +00:00
package nomad
import (
"testing"
2017-02-08 05:22:48 +00:00
memdb "github.com/hashicorp/go-memdb"
msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc"
2017-10-09 03:53:50 +00:00
"github.com/hashicorp/nomad/acl"
"github.com/hashicorp/nomad/ci"
2016-01-13 18:19:53 +00:00
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
2017-10-09 03:53:50 +00:00
"github.com/stretchr/testify/assert"
2016-01-13 18:19:53 +00:00
)
func TestPeriodicEndpoint_Force(t *testing.T) {
ci.Parallel(t)
s1, cleanupS1 := TestServer(t, func(c *Config) {
2016-01-13 18:19:53 +00:00
c.NumSchedulers = 0 // Prevent automatic dequeue
})
defer cleanupS1()
2016-01-13 18:19:53 +00:00
state := s1.fsm.State()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
// Create and insert a periodic job.
job := mock.PeriodicJob()
job.Periodic.ProhibitOverlap = true // Shouldn't affect anything.
if err := state.UpsertJob(structs.MsgTypeTestSetup, 100, nil, job); err != nil {
2016-01-13 18:19:53 +00:00
t.Fatalf("err: %v", err)
}
s1.periodicDispatcher.Add(job)
// Force launch it.
req := &structs.PeriodicForceRequest{
2017-09-07 23:56:15 +00:00
JobID: job.ID,
WriteRequest: structs.WriteRequest{
Region: "global",
Namespace: job.Namespace,
},
2016-01-13 18:19:53 +00:00
}
// Fetch the response
var resp structs.PeriodicForceResponse
if err := msgpackrpc.CallWithCodec(codec, "Periodic.Force", req, &resp); err != nil {
t.Fatalf("err: %v", err)
}
if resp.Index == 0 {
t.Fatalf("bad index: %d", resp.Index)
}
// Lookup the evaluation
2017-02-08 05:22:48 +00:00
ws := memdb.NewWatchSet()
eval, err := state.EvalByID(ws, resp.EvalID)
2016-01-13 18:19:53 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
if eval == nil {
t.Fatalf("expected eval")
}
if eval.CreateIndex != resp.EvalCreateIndex {
t.Fatalf("index mis-match")
}
}
2017-10-09 03:53:50 +00:00
func TestPeriodicEndpoint_Force_ACL(t *testing.T) {
ci.Parallel(t)
s1, root, cleanupS1 := TestACLServer(t, func(c *Config) {
2017-10-09 03:53:50 +00:00
c.NumSchedulers = 0 // Prevent automatic dequeue
})
defer cleanupS1()
2017-10-09 03:53:50 +00:00
state := s1.fsm.State()
assert := assert.New(t)
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
// Create and insert a periodic job.
job := mock.PeriodicJob()
job.Periodic.ProhibitOverlap = true // Shouldn't affect anything.
assert.Nil(state.UpsertJob(structs.MsgTypeTestSetup, 100, nil, job))
err := s1.periodicDispatcher.Add(job)
2017-10-09 03:53:50 +00:00
assert.Nil(err)
// Force launch it.
req := &structs.PeriodicForceRequest{
JobID: job.ID,
WriteRequest: structs.WriteRequest{
Region: "global",
Namespace: job.Namespace,
},
}
// Try with no token and expect permission denied
{
var resp structs.PeriodicForceResponse
err := msgpackrpc.CallWithCodec(codec, "Periodic.Force", req, &resp)
assert.NotNil(err)
assert.Contains(err.Error(), structs.ErrPermissionDenied.Error())
}
// Try with an invalid token and expect permission denied
{
invalidToken := mock.CreatePolicyAndToken(t, state, 1003, "invalid", mock.NodePolicy(acl.PolicyWrite))
2017-10-12 22:16:33 +00:00
req.AuthToken = invalidToken.SecretID
2017-10-09 03:53:50 +00:00
var resp structs.PeriodicForceResponse
err := msgpackrpc.CallWithCodec(codec, "Periodic.Force", req, &resp)
assert.NotNil(err)
assert.Contains(err.Error(), structs.ErrPermissionDenied.Error())
}
// Fetch the response with a valid token
{
policy := mock.NamespacePolicy(structs.DefaultNamespace, "", []string{acl.NamespaceCapabilitySubmitJob})
token := mock.CreatePolicyAndToken(t, state, 1005, "valid", policy)
2017-10-12 22:16:33 +00:00
req.AuthToken = token.SecretID
2017-10-09 03:53:50 +00:00
var resp structs.PeriodicForceResponse
assert.Nil(msgpackrpc.CallWithCodec(codec, "Periodic.Force", req, &resp))
assert.NotEqual(uint64(0), resp.Index)
2017-10-09 03:53:50 +00:00
// Lookup the evaluation
ws := memdb.NewWatchSet()
eval, err := state.EvalByID(ws, resp.EvalID)
assert.Nil(err)
test: fix race and nil panic in nomad/ tests Race was test only and due to unlocked map access. Panic was test only and due to checking a field on a struct even when we knew the struct was nil. Race output that was fixed: ``` ================== WARNING: DATA RACE Read at 0x00c000697dd0 by goroutine 768: runtime.mapaccess2() /usr/local/go/src/runtime/map.go:439 +0x0 github.com/hashicorp/nomad/nomad.TestLeader_PeriodicDispatcher_Restore_Adds.func8() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader_test.go:402 +0xe6 github.com/hashicorp/nomad/testutil.WaitForResultRetries() /home/schmichael/go/src/github.com/hashicorp/nomad/testutil/wait.go:30 +0x5a github.com/hashicorp/nomad/testutil.WaitForResult() /home/schmichael/go/src/github.com/hashicorp/nomad/testutil/wait.go:22 +0x57 github.com/hashicorp/nomad/nomad.TestLeader_PeriodicDispatcher_Restore_Adds() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader_test.go:401 +0xb53 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Previous write at 0x00c000697dd0 by goroutine 569: runtime.mapassign() /usr/local/go/src/runtime/map.go:549 +0x0 github.com/hashicorp/nomad/nomad.(*PeriodicDispatch).Add() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/periodic.go:224 +0x2eb github.com/hashicorp/nomad/nomad.(*Server).restorePeriodicDispatcher() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:394 +0x29a github.com/hashicorp/nomad/nomad.(*Server).establishLeadership() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:234 +0x593 github.com/hashicorp/nomad/nomad.(*Server).leaderLoop() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:117 +0x82e github.com/hashicorp/nomad/nomad.(*Server).monitorLeadership.func1() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:72 +0x6c Goroutine 768 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x650 testing.runTests.func1() /usr/local/go/src/testing/testing.go:1119 +0xa8 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 testing.runTests() /usr/local/go/src/testing/testing.go:1117 +0x4ee testing.(*M).Run() /usr/local/go/src/testing/testing.go:1034 +0x2ee main.main() _testmain.go:1150 +0x221 Goroutine 569 (running) created at: github.com/hashicorp/nomad/nomad.(*Server).monitorLeadership() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:70 +0x269 ================== ```
2018-12-19 21:05:12 +00:00
if assert.NotNil(eval) {
assert.Equal(eval.CreateIndex, resp.EvalCreateIndex)
}
2017-10-09 03:53:50 +00:00
}
// Fetch the response with a valid token having dispatch permission
{
policy := mock.NamespacePolicy(structs.DefaultNamespace, "", []string{acl.NamespaceCapabilityDispatchJob})
token := mock.CreatePolicyAndToken(t, state, 1005, "valid", policy)
req.AuthToken = token.SecretID
var resp structs.PeriodicForceResponse
assert.Nil(msgpackrpc.CallWithCodec(codec, "Periodic.Force", req, &resp))
assert.NotEqual(uint64(0), resp.Index)
// Lookup the evaluation
ws := memdb.NewWatchSet()
eval, err := state.EvalByID(ws, resp.EvalID)
assert.Nil(err)
if assert.NotNil(eval) {
assert.Equal(eval.CreateIndex, resp.EvalCreateIndex)
}
}
2017-10-09 03:53:50 +00:00
// Fetch the response with management token
{
2017-10-12 22:16:33 +00:00
req.AuthToken = root.SecretID
2017-10-09 03:53:50 +00:00
var resp structs.PeriodicForceResponse
assert.Nil(msgpackrpc.CallWithCodec(codec, "Periodic.Force", req, &resp))
assert.NotEqual(uint64(0), resp.Index)
2017-10-09 03:53:50 +00:00
// Lookup the evaluation
ws := memdb.NewWatchSet()
eval, err := state.EvalByID(ws, resp.EvalID)
assert.Nil(err)
test: fix race and nil panic in nomad/ tests Race was test only and due to unlocked map access. Panic was test only and due to checking a field on a struct even when we knew the struct was nil. Race output that was fixed: ``` ================== WARNING: DATA RACE Read at 0x00c000697dd0 by goroutine 768: runtime.mapaccess2() /usr/local/go/src/runtime/map.go:439 +0x0 github.com/hashicorp/nomad/nomad.TestLeader_PeriodicDispatcher_Restore_Adds.func8() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader_test.go:402 +0xe6 github.com/hashicorp/nomad/testutil.WaitForResultRetries() /home/schmichael/go/src/github.com/hashicorp/nomad/testutil/wait.go:30 +0x5a github.com/hashicorp/nomad/testutil.WaitForResult() /home/schmichael/go/src/github.com/hashicorp/nomad/testutil/wait.go:22 +0x57 github.com/hashicorp/nomad/nomad.TestLeader_PeriodicDispatcher_Restore_Adds() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader_test.go:401 +0xb53 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Previous write at 0x00c000697dd0 by goroutine 569: runtime.mapassign() /usr/local/go/src/runtime/map.go:549 +0x0 github.com/hashicorp/nomad/nomad.(*PeriodicDispatch).Add() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/periodic.go:224 +0x2eb github.com/hashicorp/nomad/nomad.(*Server).restorePeriodicDispatcher() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:394 +0x29a github.com/hashicorp/nomad/nomad.(*Server).establishLeadership() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:234 +0x593 github.com/hashicorp/nomad/nomad.(*Server).leaderLoop() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:117 +0x82e github.com/hashicorp/nomad/nomad.(*Server).monitorLeadership.func1() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:72 +0x6c Goroutine 768 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x650 testing.runTests.func1() /usr/local/go/src/testing/testing.go:1119 +0xa8 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 testing.runTests() /usr/local/go/src/testing/testing.go:1117 +0x4ee testing.(*M).Run() /usr/local/go/src/testing/testing.go:1034 +0x2ee main.main() _testmain.go:1150 +0x221 Goroutine 569 (running) created at: github.com/hashicorp/nomad/nomad.(*Server).monitorLeadership() /home/schmichael/go/src/github.com/hashicorp/nomad/nomad/leader.go:70 +0x269 ================== ```
2018-12-19 21:05:12 +00:00
if assert.NotNil(eval) {
assert.Equal(eval.CreateIndex, resp.EvalCreateIndex)
}
2017-10-09 03:53:50 +00:00
}
}
2016-01-13 18:19:53 +00:00
func TestPeriodicEndpoint_Force_NonPeriodic(t *testing.T) {
ci.Parallel(t)
s1, cleanupS1 := TestServer(t, func(c *Config) {
2016-01-13 18:19:53 +00:00
c.NumSchedulers = 0 // Prevent automatic dequeue
})
defer cleanupS1()
2016-01-13 18:19:53 +00:00
state := s1.fsm.State()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
// Create and insert a non-periodic job.
job := mock.Job()
if err := state.UpsertJob(structs.MsgTypeTestSetup, 100, nil, job); err != nil {
2016-01-13 18:19:53 +00:00
t.Fatalf("err: %v", err)
}
// Force launch it.
req := &structs.PeriodicForceRequest{
2017-09-07 23:56:15 +00:00
JobID: job.ID,
WriteRequest: structs.WriteRequest{
Region: "global",
Namespace: job.Namespace,
},
2016-01-13 18:19:53 +00:00
}
// Fetch the response
var resp structs.PeriodicForceResponse
if err := msgpackrpc.CallWithCodec(codec, "Periodic.Force", req, &resp); err == nil {
2018-03-11 18:37:05 +00:00
t.Fatalf("Force on non-periodic job should err")
2016-01-13 18:19:53 +00:00
}
}