github.com/uchennaokeke444/nomad@v0.11.8/e2e/e2eutil/node.go (about) 1 package e2eutil 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/hashicorp/nomad/api" 8 "github.com/hashicorp/nomad/helper/uuid" 9 ) 10 11 // AgentRestart is a test helper function that restarts a client node 12 // running under systemd using a raw_exec job. Returns the job ID of 13 // the restart job so that callers can clean it up. 14 func AgentRestart(client *api.Client, nodeID string) (string, error) { 15 ok, err := isUbuntu(client, nodeID) 16 if !ok { 17 // TODO(tgross): we're checking this because we want to use 18 // systemctl to restart the node, but we should also figure 19 // out a way to detect dev mode targets. 20 return "", fmt.Errorf("AgentRestart only works against ubuntu targets") 21 } 22 if err != nil { 23 return "", err 24 } 25 26 job := newRestartJob(nodeID) 27 jobID := *job.ID 28 _, _, err = client.Jobs().Register(job, nil) 29 if err != nil { 30 return jobID, err 31 } 32 33 reasonErr := fmt.Errorf("timed out") 34 retries := 30 35 for retries > 0 { 36 time.Sleep(1 * time.Second) 37 retries-- 38 39 allocStubs, _, err := client.Jobs().Allocations(jobID, true, nil) 40 if err != nil { 41 reasonErr = err 42 continue 43 } 44 45 if len(allocStubs) > 0 { 46 INNER: 47 for _, state := range allocStubs[0].TaskStates { 48 if state.State == "dead" { 49 node, _, err := client.Nodes().Info(nodeID, nil) 50 if err != nil { 51 reasonErr = err 52 break INNER 53 } 54 if node != nil && node.Status == "ready" { 55 return jobID, nil 56 } 57 reasonErr = fmt.Errorf("node status not ready") 58 } 59 } 60 } 61 } 62 return jobID, fmt.Errorf("node did not become ready: %v", reasonErr) 63 } 64 65 func isUbuntu(client *api.Client, nodeID string) (bool, error) { 66 node, _, err := client.Nodes().Info(nodeID, nil) 67 if err != nil || node == nil { 68 return false, err 69 } 70 if name, ok := node.Attributes["os.name"]; ok { 71 return name == "ubuntu", nil 72 } 73 return false, nil 74 } 75 76 func newRestartJob(nodeID string) *api.Job { 77 jobType := "batch" 78 name := "restart" 79 jobID := "restart-" + uuid.Generate()[0:8] 80 attempts := 0 81 job := &api.Job{ 82 Name: &name, 83 ID: &jobID, 84 Datacenters: []string{"dc1"}, 85 Type: &jobType, 86 TaskGroups: []*api.TaskGroup{ 87 { 88 Name: &name, 89 Constraints: []*api.Constraint{ 90 { 91 LTarget: "${node.unique.id}", 92 RTarget: nodeID, 93 Operand: "=", 94 }, 95 }, 96 RestartPolicy: &api.RestartPolicy{ 97 Attempts: &attempts, 98 }, 99 Tasks: []*api.Task{ 100 { 101 Name: name, 102 Driver: "raw_exec", 103 Config: map[string]interface{}{ 104 "command": "systemctl", 105 "args": []string{"restart", "nomad"}, 106 }, 107 }, 108 }, 109 }, 110 }, 111 } 112 job.Canonicalize() 113 return job 114 } 115 116 // ListWindowsClientNodes returns a list of Windows client IDs, so that tests 117 // can skip operating-specific tests if there are no Windows clients available. 118 // Returns an error only on client errors. 119 func ListWindowsClientNodes(client *api.Client) ([]string, error) { 120 return listClientNodesByOS(client, "windows") 121 } 122 123 // ListLinuxClientNodes returns a list of Linux client IDs, so that tests 124 // can skip operating-specific tests if there are no Linux clients available 125 // Returns an error only on client errors. 126 func ListLinuxClientNodes(client *api.Client) ([]string, error) { 127 return listClientNodesByOS(client, "linux") 128 } 129 130 func listClientNodesByOS(client *api.Client, osName string) ([]string, error) { 131 nodeIDs := []string{} 132 nodes, _, err := client.Nodes().List(&api.QueryOptions{}) 133 if err != nil { 134 return nodeIDs, fmt.Errorf("could not query nodes: %v", err) 135 } 136 for _, stubNode := range nodes { 137 node, _, err := client.Nodes().Info(stubNode.ID, nil) 138 if err != nil { 139 return nodeIDs, fmt.Errorf("could not query nodes: %v", err) 140 } 141 if name, ok := node.Attributes["kernel.name"]; ok && name == osName { 142 nodeIDs = append(nodeIDs, stubNode.ID) 143 } 144 } 145 return nodeIDs, nil 146 }