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  }