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

     1  package consultemplate
     2  
     3  import (
     4  	"time"
     5  
     6  	capi "github.com/hashicorp/consul/api"
     7  	"github.com/hashicorp/nomad/e2e/framework"
     8  	"github.com/hashicorp/nomad/helper"
     9  	"github.com/hashicorp/nomad/helper/uuid"
    10  	"github.com/hashicorp/nomad/jobspec"
    11  	"github.com/hashicorp/nomad/nomad/structs"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  type ConsulTemplateTest struct {
    18  	framework.TC
    19  	jobIds []string
    20  }
    21  
    22  func init() {
    23  	framework.AddSuites(&framework.TestSuite{
    24  		Component:   "Consul Template",
    25  		CanRunLocal: true,
    26  		Consul:      true,
    27  		Cases: []framework.TestCase{
    28  			new(ConsulTemplateTest),
    29  		},
    30  	})
    31  }
    32  
    33  func (tc *ConsulTemplateTest) TestUpdatesRestartTasks(f *framework.F) {
    34  	require := require.New(f.T())
    35  	g := NewGomegaWithT(f.T())
    36  
    37  	nomadClient := tc.Nomad()
    38  	consulClient := tc.Consul()
    39  
    40  	// Ensure consultemplatetest does not exist
    41  	_, err := consulClient.KV().Delete("consultemplatetest", nil)
    42  	require.NoError(err)
    43  
    44  	// Parse job
    45  	job, err := jobspec.ParseFile("consultemplate/input/docker.nomad")
    46  	require.Nil(err)
    47  	uuid := uuid.Generate()
    48  	jobId := helper.StringToPtr("cltp" + uuid[:8])
    49  	job.ID = jobId
    50  
    51  	tc.jobIds = append(tc.jobIds, *jobId)
    52  
    53  	// Register job
    54  	jobs := nomadClient.Jobs()
    55  	resp, _, err := jobs.Register(job, nil)
    56  	require.Nil(err)
    57  	require.NotEmpty(resp.EvalID)
    58  
    59  	waitForTaskState := func(taskState string) {
    60  		g.Eventually(func() string {
    61  			allocs, _, _ := jobs.Allocations(*job.ID, false, nil)
    62  			if len(allocs) != 1 {
    63  				return ""
    64  			}
    65  			first := allocs[0]
    66  			taskState := first.TaskStates["test"]
    67  			if taskState == nil {
    68  				return ""
    69  			}
    70  
    71  			return taskState.State
    72  		}, 5*time.Second, time.Second).Should(Equal(taskState), "Incorrect task state")
    73  	}
    74  
    75  	waitForClientAllocStatus := func(allocState string) {
    76  		g.Eventually(func() string {
    77  			allocSummaries, _, _ := jobs.Allocations(*job.ID, false, nil)
    78  			if len(allocSummaries) != 1 {
    79  				return ""
    80  			}
    81  
    82  			alloc, _, _ := nomadClient.Allocations().Info(allocSummaries[0].ID, nil)
    83  			if alloc == nil {
    84  				return ""
    85  			}
    86  
    87  			return alloc.ClientStatus
    88  		}, 5*time.Second, time.Second).Should(Equal(allocState), "Incorrect alloc state")
    89  	}
    90  
    91  	waitForRestartCount := func(count uint64) {
    92  		g.Eventually(func() uint64 {
    93  			allocs, _, _ := jobs.Allocations(*job.ID, false, nil)
    94  			if len(allocs) != 1 {
    95  				return 0
    96  			}
    97  			first := allocs[0]
    98  			return first.TaskStates["test"].Restarts
    99  		}, 10*time.Second, time.Second).Should(Equal(count), "Incorrect restart count")
   100  	}
   101  
   102  	// Wrap in retry to wait until placement
   103  	waitForTaskState(structs.TaskStatePending)
   104  
   105  	// Client should be pending
   106  	waitForClientAllocStatus(structs.AllocClientStatusPending)
   107  
   108  	// Alloc should have a blocked event
   109  	g.Eventually(func() []string {
   110  		allocSummaries, _, _ := jobs.Allocations(*job.ID, false, nil)
   111  		events := allocSummaries[0].TaskStates["test"].Events
   112  		messages := []string{}
   113  		for _, event := range events {
   114  			messages = append(messages, event.DisplayMessage)
   115  		}
   116  
   117  		return messages
   118  	}, 5*time.Second, time.Second).Should(ContainElement(ContainSubstring("kv.block")))
   119  
   120  	// Insert consultemplatetest
   121  	_, err = consulClient.KV().Put(&capi.KVPair{Key: "consultemplatetest", Value: []byte("bar")}, nil)
   122  	require.Nil(err)
   123  
   124  	// Placement should start running
   125  	waitForClientAllocStatus(structs.AllocClientStatusRunning)
   126  
   127  	// Ensure restart count 0 -- we should be going from blocked to running.
   128  	waitForRestartCount(0)
   129  
   130  	// Update consultemplatetest
   131  	_, err = consulClient.KV().Put(&capi.KVPair{Key: "consultemplatetest", Value: []byte("baz")}, nil)
   132  	require.Nil(err)
   133  
   134  	// Wrap in retry to wait until restart
   135  	waitForRestartCount(1)
   136  }
   137  
   138  func (tc *ConsulTemplateTest) AfterEach(f *framework.F) {
   139  	nomadClient := tc.Nomad()
   140  	consulClient := tc.Consul()
   141  
   142  	jobs := nomadClient.Jobs()
   143  	// Stop all jobs in test
   144  	for _, id := range tc.jobIds {
   145  		jobs.Deregister(id, true, nil)
   146  	}
   147  	// Garbage collect
   148  	nomadClient.System().GarbageCollect()
   149  
   150  	// Ensure consultemplatetest does not exist
   151  	consulClient.KV().Delete("consultemplatetest", nil)
   152  }