func TestTaskRunner_Update(t *testing.T) { ctestutil.ExecCompatible(t) _, tr := testTaskRunner(false) // Change command to ensure we run for a bit tr.task.Config["command"] = "/bin/sleep" tr.task.Config["args"] = []string{"100"} go tr.Run() defer tr.Destroy(structs.NewTaskEvent(structs.TaskKilled)) defer tr.ctx.AllocDir.Destroy() // Update the task definition updateAlloc := tr.alloc.Copy() // Update the restart policy newTG := updateAlloc.Job.TaskGroups[0] newMode := "foo" newTG.RestartPolicy.Mode = newMode newTask := updateAlloc.Job.TaskGroups[0].Tasks[0] newTask.Driver = "foobar" // Update the kill timeout testutil.WaitForResult(func() (bool, error) { if tr.handle == nil { return false, fmt.Errorf("task not started") } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) oldHandle := tr.handle.ID() newTask.KillTimeout = time.Hour tr.Update(updateAlloc) // Wait for update to take place testutil.WaitForResult(func() (bool, error) { if tr.task == newTask { return false, fmt.Errorf("We copied the pointer! This would be very bad") } if tr.task.Driver != newTask.Driver { return false, fmt.Errorf("Task not copied") } if tr.restartTracker.policy.Mode != newMode { return false, fmt.Errorf("restart policy not updated") } if tr.handle.ID() == oldHandle { return false, fmt.Errorf("handle not updated") } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
func TestAllocRunner_SaveRestoreState(t *testing.T) { ctestutil.ExecCompatible(t) upd, ar := testAllocRunner(false) // Ensure task takes some time task := ar.alloc.Job.TaskGroups[0].Tasks[0] task.Config["command"] = "/bin/sleep" task.Config["args"] = []string{"10"} go ar.Run() defer ar.Destroy() // Snapshot state testutil.WaitForResult(func() (bool, error) { return len(ar.tasks) == 1, nil }, func(err error) { t.Fatalf("task never started: %v", err) }) err := ar.SaveState() if err != nil { t.Fatalf("err: %v", err) } // Create a new alloc runner consulClient, err := NewConsulService(&consulServiceConfig{ar.logger, "127.0.0.1:8500", "", "", false, false, &structs.Node{}}) ar2 := NewAllocRunner(ar.logger, ar.config, upd.Update, &structs.Allocation{ID: ar.alloc.ID}, consulClient) err = ar2.RestoreState() if err != nil { t.Fatalf("err: %v", err) } go ar2.Run() // Destroy and wait ar2.Destroy() start := time.Now() testutil.WaitForResult(func() (bool, error) { if upd.Count == 0 { return false, nil } last := upd.Allocs[upd.Count-1] return last.ClientStatus != structs.AllocClientStatusPending, nil }, func(err error) { t.Fatalf("err: %v %#v %#v", err, upd.Allocs[0], ar.alloc.TaskStates) }) if time.Since(start) > time.Duration(testutil.TestMultiplier()*15)*time.Second { t.Fatalf("took too long to terminate") } }
func TestLeader_LeftLeader(t *testing.T) { s1 := testServer(t, nil) defer s1.Shutdown() s2 := testServer(t, func(c *Config) { c.DevDisableBootstrap = true }) defer s2.Shutdown() s3 := testServer(t, func(c *Config) { c.DevDisableBootstrap = true }) defer s3.Shutdown() servers := []*Server{s1, s2, s3} testJoin(t, s1, s2, s3) for _, s := range servers { testutil.WaitForResult(func() (bool, error) { peers, _ := s.raftPeers.Peers() return len(peers) == 3, nil }, func(err error) { t.Fatalf("should have 3 peers") }) } // Kill the leader! var leader *Server for _, s := range servers { if s.IsLeader() { leader = s break } } if leader == nil { t.Fatalf("Should have a leader") } leader.Leave() leader.Shutdown() for _, s := range servers { if s == leader { continue } testutil.WaitForResult(func() (bool, error) { peers, _ := s.raftPeers.Peers() return len(peers) == 2, errors.New(fmt.Sprintf("%v", peers)) }, func(err error) { t.Fatalf("should have 2 peers: %v", err) }) } }
func TestServer_Regions(t *testing.T) { // Make the servers s1 := testServer(t, func(c *Config) { c.Region = "region1" }) defer s1.Shutdown() s2 := testServer(t, func(c *Config) { c.Region = "region2" }) defer s2.Shutdown() // Join them together s2Addr := fmt.Sprintf("127.0.0.1:%d", s2.config.SerfConfig.MemberlistConfig.BindPort) if n, err := s1.Join([]string{s2Addr}); err != nil || n != 1 { t.Fatalf("Failed joining: %v (%d joined)", err, n) } // Try listing the regions testutil.WaitForResult(func() (bool, error) { out := s1.Regions() if len(out) != 2 || out[0] != "region1" || out[1] != "region2" { return false, fmt.Errorf("unexpected regions: %v", out) } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
func TestRegionList(t *testing.T) { // Make the servers s1 := testServer(t, func(c *Config) { c.Region = "region1" }) defer s1.Shutdown() codec := rpcClient(t, s1) s2 := testServer(t, func(c *Config) { c.Region = "region2" }) defer s2.Shutdown() // Join the servers s2Addr := fmt.Sprintf("127.0.0.1:%d", s2.config.SerfConfig.MemberlistConfig.BindPort) if n, err := s1.Join([]string{s2Addr}); err != nil || n != 1 { t.Fatalf("Failed joining: %v (%d joined)", err, n) } // Query the regions list testutil.WaitForResult(func() (bool, error) { var arg structs.GenericRequest var out []string if err := msgpackrpc.CallWithCodec(codec, "Region.List", &arg, &out); err != nil { t.Fatalf("err: %v", err) } if len(out) != 2 || out[0] != "region1" || out[1] != "region2" { t.Fatalf("unexpected regions: %v", out) } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
func waitForConnection(v *vaultClient, t *testing.T) { testutil.WaitForResult(func() (bool, error) { return v.ConnectionEstablished(), nil }, func(err error) { t.Fatalf("Connection not established") }) }
func TestLxcDriver_Open_Wait(t *testing.T) { if !lxcPresent(t) { t.Skip("lxc not present") } task := &structs.Task{ Name: "foo", Config: map[string]interface{}{ "template": "/usr/share/lxc/templates/lxc-busybox", }, KillTimeout: 10 * time.Second, Resources: structs.DefaultResources(), } driverCtx, execCtx := testDriverContexts(task) defer execCtx.AllocDir.Destroy() d := NewLxcDriver(driverCtx) handle, err := d.Start(execCtx, task) if err != nil { t.Fatalf("err: %v", err) } if handle == nil { t.Fatalf("missing handle") } // Destroy the container after the test if lh, ok := handle.(*lxcDriverHandle); ok { defer func() { lh.container.Stop() lh.container.Destroy() }() } handle2, err := d.Open(execCtx, handle.ID()) if err != nil { t.Fatalf("err: %v", err) } if handle2 == nil { t.Fatalf("missing handle on open") } lxcHandle, _ := handle2.(*lxcDriverHandle) testutil.WaitForResult(func() (bool, error) { state := lxcHandle.container.State() if state == lxc.RUNNING { return true, nil } return false, fmt.Errorf("container in state: %v", state) }, func(err error) { t.Fatalf("err: %v", err) }) // Desroy the container if err := handle2.Kill(); err != nil { t.Fatalf("err: %v", err) } }
func TestTaskRunner_SaveRestoreState(t *testing.T) { ctestutil.ExecCompatible(t) upd, tr := testTaskRunner(false) // Change command to ensure we run for a bit tr.task.Config["command"] = "/bin/sleep" tr.task.Config["args"] = []string{"10"} go tr.Run() defer tr.Destroy() // Snapshot state time.Sleep(2 * time.Second) if err := tr.SaveState(); err != nil { t.Fatalf("err: %v", err) } // Create a new task runner consulClient, _ := NewConsulService(&consulServiceConfig{tr.logger, "127.0.0.1:8500", "", "", false, false, &structs.Node{}}) tr2 := NewTaskRunner(tr.logger, tr.config, upd.Update, tr.ctx, tr.alloc, &structs.Task{Name: tr.task.Name}, consulClient) if err := tr2.RestoreState(); err != nil { t.Fatalf("err: %v", err) } go tr2.Run() defer tr2.Destroy() // Destroy and wait testutil.WaitForResult(func() (bool, error) { return tr2.handle != nil, fmt.Errorf("RestoreState() didn't open handle") }, func(err error) { t.Fatalf("err: %v", err) }) }
func TestBlockedEvals_UnblockEscaped(t *testing.T) { blocked, broker := testBlockedEvals(t) // Create an escaped eval and add it to the blocked tracker. e := mock.Eval() e.Status = structs.EvalStatusBlocked e.EscapedComputedClass = true blocked.Block(e) // Verify block caused the eval to be tracked bStats := blocked.Stats() if bStats.TotalBlocked != 1 || bStats.TotalEscaped != 1 { t.Fatalf("bad: %#v", bStats) } blocked.Unblock("v1:123", 1000) testutil.WaitForResult(func() (bool, error) { // Verify Unblock caused an enqueue brokerStats := broker.Stats() if brokerStats.TotalReady != 1 { return false, fmt.Errorf("bad: %#v", brokerStats) } // Verify Unblock updates the stats bStats := blocked.Stats() if bStats.TotalBlocked != 0 || bStats.TotalEscaped != 0 { return false, fmt.Errorf("bad: %#v", bStats) } return true, nil }, func(err error) { t.Fatalf("err: %s", err) }) }
func TestAllocRunner_Update(t *testing.T) { ctestutil.ExecCompatible(t) _, ar := testAllocRunner(false) // Ensure task takes some time task := ar.alloc.Job.TaskGroups[0].Tasks[0] task.Config["command"] = "/bin/sleep" task.Config["args"] = []string{"10"} go ar.Run() defer ar.Destroy() // Update the alloc definition newAlloc := new(structs.Allocation) *newAlloc = *ar.alloc newAlloc.Name = "FOO" newAlloc.AllocModifyIndex++ ar.Update(newAlloc) // Check the alloc runner stores the update allocation. testutil.WaitForResult(func() (bool, error) { return ar.Alloc().Name == "FOO", nil }, func(err error) { t.Fatalf("err: %v %#v", err, ar.Alloc()) }) }
func TestLeader_ReapDuplicateEval(t *testing.T) { s1 := testServer(t, func(c *Config) { c.NumSchedulers = 0 }) defer s1.Shutdown() testutil.WaitForLeader(t, s1.RPC) // Create a duplicate blocked eval eval := mock.Eval() eval2 := mock.Eval() eval2.JobID = eval.JobID s1.blockedEvals.Block(eval) s1.blockedEvals.Block(eval2) // Wait for the evaluation to marked as cancelled state := s1.fsm.State() testutil.WaitForResult(func() (bool, error) { out, err := state.EvalByID(eval2.ID) if err != nil { return false, err } return out != nil && out.Status == structs.EvalStatusCancelled, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
func TestVaultClient_EstablishConnection(t *testing.T) { v := testutil.NewTestVault(t) logger := log.New(os.Stderr, "TEST: ", log.Lshortfile|log.LstdFlags) v.Config.ConnectionRetryIntv = 100 * time.Millisecond v.Config.TaskTokenTTL = "10s" c, err := NewVaultClient(v.Config, logger, nil) if err != nil { t.Fatalf("failed to build vault client: %v", err) } c.Start() defer c.Stop() // Sleep a little while and check that no connection has been established. time.Sleep(100 * time.Duration(testutil.TestMultiplier()) * time.Millisecond) if c.ConnectionEstablished() { t.Fatalf("ConnectionEstablished() returned true before Vault server started") } // Start Vault v.Start() defer v.Stop() testutil.WaitForResult(func() (bool, error) { return c.ConnectionEstablished(), nil }, func(err error) { t.Fatalf("Connection not established") }) }
func TestClient_Heartbeat(t *testing.T) { s1, _ := testServer(t, func(c *nomad.Config) { c.MinHeartbeatTTL = 50 * time.Millisecond }) defer s1.Shutdown() testutil.WaitForLeader(t, s1.RPC) c1 := testClient(t, func(c *config.Config) { c.RPCHandler = s1 }) defer c1.Shutdown() req := structs.NodeSpecificRequest{ NodeID: c1.Node().ID, QueryOptions: structs.QueryOptions{Region: "global"}, } var out structs.SingleNodeResponse // Register should succeed testutil.WaitForResult(func() (bool, error) { err := s1.RPC("Node.GetNode", &req, &out) if err != nil { return false, err } if out.Node == nil { return false, fmt.Errorf("missing reg") } return out.Node.Status == structs.NodeStatusReady, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
func TestLeader_ReapFailedEval(t *testing.T) { s1 := testServer(t, func(c *Config) { c.NumSchedulers = 0 c.EvalDeliveryLimit = 1 }) defer s1.Shutdown() testutil.WaitForLeader(t, s1.RPC) // Wait for a periodic dispatch eval := mock.Eval() s1.evalBroker.Enqueue(eval) // Dequeue and Nack out, token, err := s1.evalBroker.Dequeue(defaultSched, time.Second) if err != nil { t.Fatalf("err: %v", err) } s1.evalBroker.Nack(out.ID, token) // Wait updated evaluation state := s1.fsm.State() testutil.WaitForResult(func() (bool, error) { out, err := state.EvalByID(eval.ID) if err != nil { return false, err } return out != nil && out.Status == structs.EvalStatusFailed, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
func TestWorker_dequeueEvaluation(t *testing.T) { s1 := testServer(t, func(c *Config) { c.NumSchedulers = 0 c.EnabledSchedulers = []string{structs.JobTypeService} }) defer s1.Shutdown() testutil.WaitForLeader(t, s1.RPC) // Create the evaluation eval1 := mock.Eval() testutil.WaitForResult(func() (bool, error) { err := s1.evalBroker.Enqueue(eval1) return err == nil, err }, func(err error) { t.Fatalf("err: %v", err) }) // Create a worker w := &Worker{srv: s1, logger: s1.logger} // Attempt dequeue eval, token, shutdown := w.dequeueEvaluation(10 * time.Millisecond) if shutdown { t.Fatalf("should not shutdown") } if token == "" { t.Fatalf("should get token") } // Ensure we get a sane eval if !reflect.DeepEqual(eval, eval1) { t.Fatalf("bad: %#v %#v", eval, eval1) } }
func TestClient_UpdateAllocStatus(t *testing.T) { s1, _ := testServer(t, nil) defer s1.Shutdown() testutil.WaitForLeader(t, s1.RPC) c1 := testClient(t, func(c *config.Config) { c.RPCHandler = s1 }) defer c1.Shutdown() alloc := mock.Alloc() alloc.NodeID = c1.Node().ID originalStatus := "foo" alloc.ClientStatus = originalStatus state := s1.State() state.UpsertAllocs(100, []*structs.Allocation{alloc}) testutil.WaitForResult(func() (bool, error) { out, err := state.AllocByID(alloc.ID) if err != nil { return false, err } if out == nil { return false, fmt.Errorf("no such alloc") } if out.ClientStatus == originalStatus { return false, fmt.Errorf("Alloc client status not updated; got %v", out.ClientStatus) } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
// Test the block case in which the eval should be immediately unblocked since // it a class it is eligible for has been unblocked func TestBlockedEvals_Block_ImmediateUnblock_SeenClass(t *testing.T) { blocked, broker := testBlockedEvals(t) // Do an unblock prior to blocking blocked.Unblock("v1:123", 1000) // Create a blocked eval that is eligible on a specific node class and add // it to the blocked tracker. e := mock.Eval() e.Status = structs.EvalStatusBlocked e.ClassEligibility = map[string]bool{"v1:123": true, "v1:456": false} e.SnapshotIndex = 900 blocked.Block(e) // Verify block caused the eval to be immediately unblocked blockedStats := blocked.Stats() if blockedStats.TotalBlocked != 0 && blockedStats.TotalEscaped != 0 { t.Fatalf("bad: %#v", blockedStats) } testutil.WaitForResult(func() (bool, error) { // Verify Unblock caused an enqueue brokerStats := broker.Stats() if brokerStats.TotalReady != 1 { return false, fmt.Errorf("bad: %#v", brokerStats) } return true, nil }, func(err error) { t.Fatalf("err: %s", err) }) }
func TestBlockedEvals_UnblockFailed(t *testing.T) { blocked, broker := testBlockedEvals(t) // Create blocked evals that are due to failures e := mock.Eval() e.Status = structs.EvalStatusBlocked e.TriggeredBy = structs.EvalTriggerMaxPlans e.EscapedComputedClass = true blocked.Block(e) e2 := mock.Eval() e2.Status = structs.EvalStatusBlocked e2.TriggeredBy = structs.EvalTriggerMaxPlans e2.ClassEligibility = map[string]bool{"v1:123": true, "v1:456": false} blocked.Block(e2) // Trigger an unblock fail blocked.UnblockFailed() testutil.WaitForResult(func() (bool, error) { // Verify Unblock caused an enqueue brokerStats := broker.Stats() if brokerStats.TotalReady != 2 { return false, fmt.Errorf("bad: %#v", brokerStats) } return true, nil }, func(err error) { t.Fatalf("err: %s", err) }) }
func TestRegionsList(t *testing.T) { c1, s1 := makeClient(t, nil, func(c *testutil.TestServerConfig) { c.Region = "regionA" }) defer s1.Stop() c2, s2 := makeClient(t, nil, func(c *testutil.TestServerConfig) { c.Region = "regionB" }) defer s2.Stop() // Join the servers if _, err := c2.Agent().Join(s1.SerfAddr); err != nil { t.Fatalf("err: %v", err) } // Regions returned and sorted testutil.WaitForResult(func() (bool, error) { regions, err := c1.Regions().List() if err != nil { return false, err } if n := len(regions); n != 2 { return false, fmt.Errorf("expected 2 regions, got: %d", n) } if regions[0] != "regionA" || regions[1] != "regionB" { return false, fmt.Errorf("bad: %#v", regions) } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) }
func TestBlockedEvals_UnblockIneligible(t *testing.T) { blocked, broker := testBlockedEvals(t) // Create a blocked eval that is ineligible on a specific node class and add // it to the blocked tracker. e := mock.Eval() e.Status = structs.EvalStatusBlocked e.ClassEligibility = map[string]bool{"v1:123": false} blocked.Block(e) // Verify block caused the eval to be tracked blockedStats := blocked.Stats() if blockedStats.TotalBlocked != 1 && blockedStats.TotalEscaped != 0 { t.Fatalf("bad: %#v", blockedStats) } // Should do nothing blocked.Unblock("v1:123", 1000) testutil.WaitForResult(func() (bool, error) { // Verify Unblock didn't cause an enqueue brokerStats := broker.Stats() if brokerStats.TotalReady != 0 { return false, fmt.Errorf("bad: %#v", brokerStats) } bStats := blocked.Stats() if bStats.TotalBlocked != 1 || bStats.TotalEscaped != 0 { return false, fmt.Errorf("bad: %#v", bStats) } return true, nil }, func(err error) { t.Fatalf("err: %s", err) }) }
func TestEvalEndpoint_Reblock_NonExistent(t *testing.T) { s1 := testServer(t, func(c *Config) { c.NumSchedulers = 0 // Prevent automatic dequeue }) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForResult(func() (bool, error) { return s1.evalBroker.Enabled(), nil }, func(err error) { t.Fatalf("should enable eval broker") }) // Create the register request eval1 := mock.Eval() s1.evalBroker.Enqueue(eval1) out, token, err := s1.evalBroker.Dequeue(defaultSched, time.Second) if err != nil { t.Fatalf("err: %v", err) } if out == nil { t.Fatalf("missing eval") } get := &structs.EvalUpdateRequest{ Evals: []*structs.Evaluation{eval1}, EvalToken: token, WriteRequest: structs.WriteRequest{Region: "global"}, } var resp structs.GenericResponse if err := msgpackrpc.CallWithCodec(codec, "Eval.Reblock", get, &resp); err == nil { t.Fatalf("expect error since eval does not exist") } }
func TestAllocRunner_Update(t *testing.T) { ctestutil.ExecCompatible(t) upd, ar := testAllocRunner(false) // Ensure task takes some time task := ar.alloc.Job.TaskGroups[0].Tasks[0] task.Config["command"] = "/bin/sleep" task.Config["args"] = []string{"10"} go ar.Run() defer ar.Destroy() start := time.Now() // Update the alloc definition newAlloc := new(structs.Allocation) *newAlloc = *ar.alloc newAlloc.DesiredStatus = structs.AllocDesiredStatusStop ar.Update(newAlloc) testutil.WaitForResult(func() (bool, error) { if upd.Count == 0 { return false, nil } last := upd.Allocs[upd.Count-1] return last.ClientStatus == structs.AllocClientStatusDead, nil }, func(err error) { t.Fatalf("err: %v %#v %#v", err, upd.Allocs[0], ar.alloc.TaskStates) }) if time.Since(start) > 8*time.Second { t.Fatalf("took too long to terminate") } }
func TestAllocRunner_Destroy(t *testing.T) { ctestutil.ExecCompatible(t) upd, ar := testAllocRunner(false) // Ensure task takes some time task := ar.alloc.Job.TaskGroups[0].Tasks[0] task.Config["command"] = "/bin/sleep" task.Config["args"] = []string{"10"} go ar.Run() start := time.Now() // Begin the tear down go func() { time.Sleep(100 * time.Millisecond) ar.Destroy() }() testutil.WaitForResult(func() (bool, error) { if upd.Count == 0 { return false, nil } last := upd.Allocs[upd.Count-1] return last.ClientStatus == structs.AllocClientStatusDead, nil }, func(err error) { t.Fatalf("err: %v %#v %#v", err, upd.Allocs[0], ar.alloc.TaskStates) }) if time.Since(start) > 8*time.Second { t.Fatalf("took too long to terminate") } }
func TestNodes_List(t *testing.T) { c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) { c.DevMode = true }) defer s.Stop() nodes := c.Nodes() var qm *QueryMeta var out []*NodeListStub var err error testutil.WaitForResult(func() (bool, error) { out, qm, err = nodes.List(nil) if err != nil { return false, err } if n := len(out); n != 1 { return false, fmt.Errorf("expected 1 node, got: %d", n) } return true, nil }, func(err error) { t.Fatalf("err: %s", err) }) // Check that we got valid QueryMeta. assertQueryMeta(t, qm) }
func TestLeader_MultiBootstrap(t *testing.T) { s1 := testServer(t, nil) defer s1.Shutdown() s2 := testServer(t, nil) defer s2.Shutdown() servers := []*Server{s1, s2} testJoin(t, s1, s2) for _, s := range servers { testutil.WaitForResult(func() (bool, error) { peers := s.Members() return len(peers) == 2, nil }, func(err error) { t.Fatalf("should have 2 peers") }) } // Ensure we don't have multiple raft peers for _, s := range servers { peers, _ := s.raftPeers.Peers() if len(peers) != 1 { t.Fatalf("should only have 1 raft peer!") } } }
func TestAllocRunner_SimpleRun_VaultToken(t *testing.T) { alloc := mock.Alloc() task := alloc.Job.TaskGroups[0].Tasks[0] task.Driver = "mock_driver" task.Config = map[string]interface{}{"exit_code": "0"} task.Vault = &structs.Vault{ Policies: []string{"default"}, } upd, ar := testAllocRunnerFromAlloc(alloc, false) go ar.Run() defer ar.Destroy() testutil.WaitForResult(func() (bool, error) { if upd.Count == 0 { return false, fmt.Errorf("No updates") } last := upd.Allocs[upd.Count-1] if last.ClientStatus != structs.AllocClientStatusComplete { return false, fmt.Errorf("got status %v; want %v", last.ClientStatus, structs.AllocClientStatusComplete) } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) tr, ok := ar.tasks[task.Name] if !ok { t.Fatalf("No task runner made") } // Check that the task runner was given the token token := tr.vaultToken if token == "" || tr.vaultRenewalCh == nil { t.Fatalf("Vault token not set properly") } // Check that it was written to disk secretDir, err := ar.ctx.AllocDir.GetSecretDir(task.Name) if err != nil { t.Fatalf("bad: %v", err) } tokenPath := filepath.Join(secretDir, vaultTokenFile) data, err := ioutil.ReadFile(tokenPath) if err != nil { t.Fatalf("token not written to disk: %v", err) } if string(data) != token { t.Fatalf("Bad token written to disk") } // Check that we stopped renewing the token mockVC := ar.vaultClient.(*vaultclient.MockVaultClient) if len(mockVC.StoppedTokens) != 1 || mockVC.StoppedTokens[0] != token { t.Fatalf("We didn't stop renewing the token") } }
func TestLeader_LeftServer(t *testing.T) { s1 := testServer(t, nil) defer s1.Shutdown() s2 := testServer(t, func(c *Config) { c.DevDisableBootstrap = true }) defer s2.Shutdown() s3 := testServer(t, func(c *Config) { c.DevDisableBootstrap = true }) defer s3.Shutdown() servers := []*Server{s1, s2, s3} testJoin(t, s1, s2, s3) for _, s := range servers { testutil.WaitForResult(func() (bool, error) { peers, _ := s.raftPeers.Peers() return len(peers) == 3, nil }, func(err error) { t.Fatalf("should have 3 peers") }) } // Kill any server servers[0].Shutdown() testutil.WaitForResult(func() (bool, error) { // Force remove the non-leader (transition to left state) name := fmt.Sprintf("%s.%s", servers[0].config.NodeName, servers[0].config.Region) if err := servers[1].RemoveFailedNode(name); err != nil { t.Fatalf("err: %v", err) } for _, s := range servers[1:] { peers, _ := s.raftPeers.Peers() return len(peers) == 2, errors.New(fmt.Sprintf("%v", peers)) } return true, nil }, func(err error) { t.Fatalf("err: %s", err) }) }
func TestTaskRunner_Destroy(t *testing.T) { ctestutil.ExecCompatible(t) upd, tr := testTaskRunner(true) tr.MarkReceived() defer tr.ctx.AllocDir.Destroy() // Change command to ensure we run for a bit tr.task.Config["command"] = "/bin/sleep" tr.task.Config["args"] = []string{"1000"} go tr.Run() testutil.WaitForResult(func() (bool, error) { if l := len(upd.events); l != 2 { return false, fmt.Errorf("Expect two events; got %v", l) } if upd.events[0].Type != structs.TaskReceived { return false, fmt.Errorf("First Event was %v; want %v", upd.events[0].Type, structs.TaskReceived) } if upd.events[1].Type != structs.TaskStarted { return false, fmt.Errorf("Second Event was %v; want %v", upd.events[1].Type, structs.TaskStarted) } return true, nil }, func(err error) { t.Fatalf("err: %v", err) }) // Make sure we are collecting afew stats time.Sleep(2 * time.Second) stats := tr.StatsReporter().ResourceUsage() if len(stats) == 0 { t.Fatalf("expected task runner to have some stats") } // Begin the tear down tr.Destroy() select { case <-tr.WaitCh(): case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second): t.Fatalf("timeout") } if len(upd.events) != 3 { t.Fatalf("should have 3 updates: %#v", upd.events) } if upd.state != structs.TaskStateDead { t.Fatalf("TaskState %v; want %v", upd.state, structs.TaskStateDead) } if upd.events[2].Type != structs.TaskKilled { t.Fatalf("Third Event was %v; want %v", upd.events[2].Type, structs.TaskKilled) } }
func TestSystemEndpoint_ReconcileSummaries(t *testing.T) { s1 := testServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) // Insert a job that can be GC'd state := s1.fsm.State() s1.fsm.State() job := mock.Job() if err := state.UpsertJob(1000, job); err != nil { t.Fatalf("UpsertJob() failed: %v", err) } // Delete the job summary state.DeleteJobSummary(1001, job.ID) // Make the GC request req := &structs.GenericRequest{ QueryOptions: structs.QueryOptions{ Region: "global", }, } var resp structs.GenericResponse if err := msgpackrpc.CallWithCodec(codec, "System.ReconcileJobSummaries", req, &resp); err != nil { t.Fatalf("expect err: %v", err) } testutil.WaitForResult(func() (bool, error) { // Check if Nomad has reconciled the summary for the job summary, err := state.JobSummaryByID(job.ID) if err != nil { return false, err } if summary.CreateIndex == 0 || summary.ModifyIndex == 0 { t.Fatalf("create index: %v, modify index: %v", summary.CreateIndex, summary.ModifyIndex) } // setting the modifyindex and createindex of the expected summary to // the output so that we can do deep equal expectedSummary := structs.JobSummary{ JobID: job.ID, Summary: map[string]structs.TaskGroupSummary{ "web": structs.TaskGroupSummary{ Queued: 10, }, }, ModifyIndex: summary.ModifyIndex, CreateIndex: summary.CreateIndex, } if !reflect.DeepEqual(&expectedSummary, summary) { return false, fmt.Errorf("expected: %v, actual: %v", expectedSummary, summary) } return true, nil }, func(err error) { t.Fatalf("err: %s", err) }) }
func TestClient_SaveRestoreState(t *testing.T) { ctestutil.ExecCompatible(t) s1, _ := testServer(t, nil) defer s1.Shutdown() testutil.WaitForLeader(t, s1.RPC) c1 := testClient(t, func(c *config.Config) { c.DevMode = false c.RPCHandler = s1 }) defer c1.Shutdown() // Create mock allocations alloc1 := mock.Alloc() alloc1.NodeID = c1.Node().ID task := alloc1.Job.TaskGroups[0].Tasks[0] task.Config["command"] = "/bin/sleep" task.Config["args"] = []string{"10"} state := s1.State() err := state.UpsertAllocs(100, []*structs.Allocation{alloc1}) if err != nil { t.Fatalf("err: %v", err) } // Allocations should get registered testutil.WaitForResult(func() (bool, error) { c1.allocLock.RLock() ar := c1.allocs[alloc1.ID] c1.allocLock.RUnlock() return ar != nil && ar.Alloc().ClientStatus == structs.AllocClientStatusRunning, nil }, func(err error) { t.Fatalf("err: %v", err) }) // Shutdown the client, saves state err = c1.Shutdown() if err != nil { t.Fatalf("err: %v", err) } // Create a new client c2, err := NewClient(c1.config) if err != nil { t.Fatalf("err: %v", err) } defer c2.Shutdown() // Ensure the allocation is running c2.allocLock.RLock() ar := c2.allocs[alloc1.ID] c2.allocLock.RUnlock() if ar.Alloc().ClientStatus != structs.AllocClientStatusRunning { t.Fatalf("bad: %#v", ar.Alloc()) } }