github.com/bigcommerce/nomad@v0.9.3-bc/e2e/e2eutil/utils.go (about)

     1  package e2eutil
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/hashicorp/nomad/api"
     9  	"github.com/hashicorp/nomad/helper"
    10  	"github.com/hashicorp/nomad/jobspec"
    11  	"github.com/hashicorp/nomad/nomad/structs"
    12  	"github.com/hashicorp/nomad/testutil"
    13  	"github.com/kr/pretty"
    14  	. "github.com/onsi/gomega"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // retries is used to control how many times to retry checking if the cluster has a leader yet
    19  const retries = 500
    20  
    21  func WaitForLeader(t *testing.T, nomadClient *api.Client) {
    22  	statusAPI := nomadClient.Status()
    23  
    24  	testutil.WaitForResultRetries(retries, func() (bool, error) {
    25  		leader, err := statusAPI.Leader()
    26  		return leader != "", err
    27  	}, func(err error) {
    28  		t.Fatalf("failed to find leader: %v", err)
    29  	})
    30  }
    31  
    32  // WaitForNodesReady waits until at least `nodes` number of nodes are ready or
    33  // fails the test.
    34  func WaitForNodesReady(t *testing.T, nomadClient *api.Client, nodes int) {
    35  	nodesAPI := nomadClient.Nodes()
    36  
    37  	testutil.WaitForResultRetries(retries, func() (bool, error) {
    38  		defer time.Sleep(time.Millisecond * 100)
    39  		nodesList, _, err := nodesAPI.List(nil)
    40  		if err != nil {
    41  			return false, fmt.Errorf("error listing nodes: %v", err)
    42  		}
    43  
    44  		eligibleNodes := 0
    45  		for _, node := range nodesList {
    46  			if node.Status == "ready" {
    47  				eligibleNodes++
    48  			}
    49  		}
    50  
    51  		return eligibleNodes >= nodes, fmt.Errorf("only %d nodes ready (wanted at least %d)", eligibleNodes, nodes)
    52  	}, func(err error) {
    53  		t.Fatalf("failed to get enough ready nodes: %v", err)
    54  	})
    55  }
    56  
    57  func RegisterAllocs(t *testing.T, nomadClient *api.Client, jobFile string, jobID string) []*api.AllocationListStub {
    58  	// Parse job
    59  	job, err := jobspec.ParseFile(jobFile)
    60  	require := require.New(t)
    61  	require.Nil(err)
    62  	job.ID = helper.StringToPtr(jobID)
    63  
    64  	// Register job
    65  	jobs := nomadClient.Jobs()
    66  	testutil.WaitForResult(func() (bool, error) {
    67  		resp, _, err := jobs.Register(job, nil)
    68  		if err != nil {
    69  			return false, err
    70  		}
    71  		return resp.EvalID != "", fmt.Errorf("expected EvalID:%s", pretty.Sprint(resp))
    72  	}, func(err error) {
    73  		require.NoError(err)
    74  	})
    75  
    76  	allocs, _, _ := jobs.Allocations(jobID, false, nil)
    77  	return allocs
    78  }
    79  
    80  func RegisterAndWaitForAllocs(t *testing.T, nomadClient *api.Client, jobFile string, jobID string) []*api.AllocationListStub {
    81  	require := require.New(t)
    82  	g := NewGomegaWithT(t)
    83  	jobs := nomadClient.Jobs()
    84  
    85  	// Start allocations
    86  	RegisterAllocs(t, nomadClient, jobFile, jobID)
    87  
    88  	// Wrap in retry to wait until placement
    89  	g.Eventually(func() []*api.AllocationListStub {
    90  		// Look for allocations
    91  		allocs, _, _ := jobs.Allocations(jobID, false, nil)
    92  		return allocs
    93  	}, 30*time.Second, time.Second).ShouldNot(BeEmpty())
    94  
    95  	allocs, _, err := jobs.Allocations(jobID, false, nil)
    96  	require.NoError(err)
    97  	return allocs
    98  }
    99  
   100  func WaitForAllocRunning(t *testing.T, nomadClient *api.Client, allocID string) {
   101  	testutil.WaitForResultRetries(retries, func() (bool, error) {
   102  		time.Sleep(time.Millisecond * 100)
   103  		alloc, _, err := nomadClient.Allocations().Info(allocID, nil)
   104  		if err != nil {
   105  			return false, err
   106  		}
   107  
   108  		return alloc.ClientStatus == structs.AllocClientStatusRunning, fmt.Errorf("expected status running, but was: %s", alloc.ClientStatus)
   109  	}, func(err error) {
   110  		t.Fatalf("failed to wait on alloc: %v", err)
   111  	})
   112  }
   113  
   114  func DeploymentsForJob(t *testing.T, nomadClient *api.Client, jobID string) []*api.Deployment {
   115  	ds, _, err := nomadClient.Deployments().List(nil)
   116  	require.NoError(t, err)
   117  
   118  	out := []*api.Deployment{}
   119  	for _, d := range ds {
   120  		if d.JobID == jobID {
   121  			out = append(out, d)
   122  		}
   123  	}
   124  
   125  	return out
   126  }
   127  
   128  func WaitForDeployment(t *testing.T, nomadClient *api.Client, deployID string, status string, statusDesc string) {
   129  	testutil.WaitForResultRetries(retries, func() (bool, error) {
   130  		time.Sleep(time.Millisecond * 100)
   131  		deploy, _, err := nomadClient.Deployments().Info(deployID, nil)
   132  		if err != nil {
   133  			return false, err
   134  		}
   135  
   136  		if deploy.Status == status && deploy.StatusDescription == statusDesc {
   137  			return true, nil
   138  		}
   139  		return false, fmt.Errorf("expected status %s \"%s\", but got: %s \"%s\"",
   140  			status,
   141  			statusDesc,
   142  			deploy.Status,
   143  			deploy.StatusDescription,
   144  		)
   145  
   146  	}, func(err error) {
   147  		t.Fatalf("failed to wait on deployment: %v", err)
   148  	})
   149  }