github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/nomad/system_endpoint_test.go (about) 1 package nomad 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 8 memdb "github.com/hashicorp/go-memdb" 9 "github.com/hashicorp/net-rpc-msgpackrpc" 10 "github.com/hashicorp/nomad/acl" 11 "github.com/hashicorp/nomad/nomad/mock" 12 "github.com/hashicorp/nomad/nomad/structs" 13 "github.com/hashicorp/nomad/testutil" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func TestSystemEndpoint_GarbageCollect(t *testing.T) { 18 t.Parallel() 19 s1 := TestServer(t, nil) 20 defer s1.Shutdown() 21 codec := rpcClient(t, s1) 22 testutil.WaitForLeader(t, s1.RPC) 23 24 // Insert a job that can be GC'd 25 state := s1.fsm.State() 26 job := mock.Job() 27 job.Type = structs.JobTypeBatch 28 job.Stop = true 29 if err := state.UpsertJob(1000, job); err != nil { 30 t.Fatalf("UpsertJob() failed: %v", err) 31 } 32 33 eval := mock.Eval() 34 eval.Status = structs.EvalStatusComplete 35 eval.JobID = job.ID 36 if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil { 37 t.Fatalf("UpsertEvals() failed: %v", err) 38 } 39 40 // Make the GC request 41 req := &structs.GenericRequest{ 42 QueryOptions: structs.QueryOptions{ 43 Region: "global", 44 }, 45 } 46 var resp structs.GenericResponse 47 if err := msgpackrpc.CallWithCodec(codec, "System.GarbageCollect", req, &resp); err != nil { 48 t.Fatalf("expect err") 49 } 50 51 testutil.WaitForResult(func() (bool, error) { 52 // Check if the job has been GC'd 53 ws := memdb.NewWatchSet() 54 exist, err := state.JobByID(ws, job.Namespace, job.ID) 55 if err != nil { 56 return false, err 57 } 58 if exist != nil { 59 return false, fmt.Errorf("job %+v wasn't garbage collected", job) 60 } 61 return true, nil 62 }, func(err error) { 63 t.Fatalf("err: %s", err) 64 }) 65 } 66 67 func TestSystemEndpoint_GarbageCollect_ACL(t *testing.T) { 68 t.Parallel() 69 s1, root := TestACLServer(t, nil) 70 defer s1.Shutdown() 71 codec := rpcClient(t, s1) 72 assert := assert.New(t) 73 testutil.WaitForLeader(t, s1.RPC) 74 state := s1.fsm.State() 75 76 // Create ACL tokens 77 invalidToken := mock.CreatePolicyAndToken(t, state, 1001, "test-invalid", mock.NodePolicy(acl.PolicyWrite)) 78 79 // Make the GC request 80 req := &structs.GenericRequest{ 81 QueryOptions: structs.QueryOptions{ 82 Region: "global", 83 }, 84 } 85 86 // Try without a token and expect failure 87 { 88 var resp structs.GenericResponse 89 err := msgpackrpc.CallWithCodec(codec, "System.GarbageCollect", req, &resp) 90 assert.NotNil(err) 91 assert.Contains(err.Error(), structs.ErrPermissionDenied.Error()) 92 } 93 94 // Try with an invalid token and expect failure 95 { 96 req.AuthToken = invalidToken.SecretID 97 var resp structs.GenericResponse 98 err := msgpackrpc.CallWithCodec(codec, "System.GarbageCollect", req, &resp) 99 assert.NotNil(err) 100 assert.Contains(err.Error(), structs.ErrPermissionDenied.Error()) 101 } 102 103 // Try with a management token 104 { 105 req.AuthToken = root.SecretID 106 var resp structs.GenericResponse 107 assert.Nil(msgpackrpc.CallWithCodec(codec, "System.GarbageCollect", req, &resp)) 108 } 109 } 110 111 func TestSystemEndpoint_ReconcileSummaries(t *testing.T) { 112 t.Parallel() 113 s1 := TestServer(t, nil) 114 defer s1.Shutdown() 115 codec := rpcClient(t, s1) 116 testutil.WaitForLeader(t, s1.RPC) 117 118 // Insert a job that can be GC'd 119 state := s1.fsm.State() 120 s1.fsm.State() 121 job := mock.Job() 122 if err := state.UpsertJob(1000, job); err != nil { 123 t.Fatalf("UpsertJob() failed: %v", err) 124 } 125 126 // Delete the job summary 127 state.DeleteJobSummary(1001, job.Namespace, job.ID) 128 129 // Make the GC request 130 req := &structs.GenericRequest{ 131 QueryOptions: structs.QueryOptions{ 132 Region: "global", 133 }, 134 } 135 var resp structs.GenericResponse 136 if err := msgpackrpc.CallWithCodec(codec, "System.ReconcileJobSummaries", req, &resp); err != nil { 137 t.Fatalf("expect err: %v", err) 138 } 139 140 testutil.WaitForResult(func() (bool, error) { 141 // Check if Nomad has reconciled the summary for the job 142 ws := memdb.NewWatchSet() 143 summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID) 144 if err != nil { 145 return false, err 146 } 147 if summary.CreateIndex == 0 || summary.ModifyIndex == 0 { 148 t.Fatalf("create index: %v, modify index: %v", summary.CreateIndex, summary.ModifyIndex) 149 } 150 151 // setting the modifyindex and createindex of the expected summary to 152 // the output so that we can do deep equal 153 expectedSummary := structs.JobSummary{ 154 JobID: job.ID, 155 Namespace: job.Namespace, 156 Summary: map[string]structs.TaskGroupSummary{ 157 "web": { 158 Queued: 10, 159 }, 160 }, 161 ModifyIndex: summary.ModifyIndex, 162 CreateIndex: summary.CreateIndex, 163 } 164 if !reflect.DeepEqual(&expectedSummary, summary) { 165 return false, fmt.Errorf("expected: %v, actual: %v", expectedSummary, summary) 166 } 167 return true, nil 168 }, func(err error) { 169 t.Fatalf("err: %s", err) 170 }) 171 } 172 173 func TestSystemEndpoint_ReconcileJobSummaries_ACL(t *testing.T) { 174 t.Parallel() 175 s1, root := TestACLServer(t, nil) 176 defer s1.Shutdown() 177 codec := rpcClient(t, s1) 178 assert := assert.New(t) 179 testutil.WaitForLeader(t, s1.RPC) 180 state := s1.fsm.State() 181 182 // Create ACL tokens 183 invalidToken := mock.CreatePolicyAndToken(t, state, 1001, "test-invalid", mock.NodePolicy(acl.PolicyWrite)) 184 185 // Make the request 186 req := &structs.GenericRequest{ 187 QueryOptions: structs.QueryOptions{ 188 Region: "global", 189 }, 190 } 191 192 // Try without a token and expect failure 193 { 194 var resp structs.GenericResponse 195 err := msgpackrpc.CallWithCodec(codec, "System.ReconcileJobSummaries", req, &resp) 196 assert.NotNil(err) 197 assert.Contains(err.Error(), structs.ErrPermissionDenied.Error()) 198 } 199 200 // Try with an invalid token and expect failure 201 { 202 req.AuthToken = invalidToken.SecretID 203 var resp structs.GenericResponse 204 err := msgpackrpc.CallWithCodec(codec, "System.ReconcileJobSummaries", req, &resp) 205 assert.NotNil(err) 206 assert.Contains(err.Error(), structs.ErrPermissionDenied.Error()) 207 } 208 209 // Try with a management token 210 { 211 req.AuthToken = root.SecretID 212 var resp structs.GenericResponse 213 assert.Nil(msgpackrpc.CallWithCodec(codec, "System.ReconcileJobSummaries", req, &resp)) 214 } 215 }