github.com/hernad/nomad@v1.6.112/e2e/lifecycle/lifecycle.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package lifecycle
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/hernad/nomad/api"
    10  	"github.com/hernad/nomad/e2e/e2eutil"
    11  	"github.com/hernad/nomad/e2e/framework"
    12  	"github.com/hernad/nomad/helper/uuid"
    13  	"github.com/hernad/nomad/nomad/structs"
    14  	"github.com/hernad/nomad/testutil"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  type LifecycleE2ETest struct {
    19  	framework.TC
    20  	jobIDs []string
    21  }
    22  
    23  func init() {
    24  	framework.AddSuites(&framework.TestSuite{
    25  		Component:   "Lifecycle",
    26  		CanRunLocal: true,
    27  		Cases:       []framework.TestCase{new(LifecycleE2ETest)},
    28  	})
    29  }
    30  
    31  // BeforeAll ensures the cluster has leader and at least 1 client node in a
    32  // ready state before running tests.
    33  func (tc *LifecycleE2ETest) BeforeAll(f *framework.F) {
    34  	e2eutil.WaitForLeader(f.T(), tc.Nomad())
    35  	e2eutil.WaitForNodesReady(f.T(), tc.Nomad(), 1)
    36  }
    37  
    38  // TestBatchJob runs a batch job with prestart and poststop hooks
    39  func (tc *LifecycleE2ETest) TestBatchJob(f *framework.F) {
    40  	t := f.T()
    41  	require := require.New(t)
    42  	nomadClient := tc.Nomad()
    43  	uuid := uuid.Generate()
    44  	jobID := "lifecycle-" + uuid[0:8]
    45  	tc.jobIDs = append(tc.jobIDs, jobID)
    46  
    47  	allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, "lifecycle/inputs/batch.nomad", jobID, "")
    48  	require.Equal(1, len(allocs))
    49  	allocID := allocs[0].ID
    50  
    51  	// wait for the job to stop and assert we stopped successfully, not failed
    52  	e2eutil.WaitForAllocStopped(t, nomadClient, allocID)
    53  	alloc, _, err := nomadClient.Allocations().Info(allocID, nil)
    54  	require.NoError(err)
    55  	require.Equal(structs.AllocClientStatusComplete, alloc.ClientStatus)
    56  
    57  	// assert the files were written as expected
    58  	afi, _, err := nomadClient.AllocFS().List(alloc, "alloc", nil)
    59  	require.NoError(err)
    60  	expected := map[string]bool{
    61  		"init-ran": true, "main-ran": true, "poststart-ran": true, "poststop-ran": true,
    62  		"init-running": false, "main-running": false, "poststart-running": false}
    63  	got := checkFiles(expected, afi)
    64  	require.Equal(expected, got)
    65  }
    66  
    67  // TestServiceJob runs a service job with prestart and poststop hooks
    68  func (tc *LifecycleE2ETest) TestServiceJob(f *framework.F) {
    69  	t := f.T()
    70  	require := require.New(t)
    71  	nomadClient := tc.Nomad()
    72  	uuid := uuid.Generate()
    73  	jobID := "lifecycle-" + uuid[0:8]
    74  	tc.jobIDs = append(tc.jobIDs, jobID)
    75  
    76  	allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, "lifecycle/inputs/service.nomad", jobID, "")
    77  	require.Equal(1, len(allocs))
    78  	allocID := allocs[0].ID
    79  
    80  	//e2eutil.WaitForAllocRunning(t, nomadClient, allocID)
    81  	testutil.WaitForResult(func() (bool, error) {
    82  		alloc, _, err := nomadClient.Allocations().Info(allocID, nil)
    83  		if err != nil {
    84  			return false, err
    85  		}
    86  
    87  		if alloc.ClientStatus != structs.AllocClientStatusRunning {
    88  			return false, fmt.Errorf("expected status running, but was: %s", alloc.ClientStatus)
    89  		}
    90  
    91  		if alloc.TaskStates["poststart"].FinishedAt.IsZero() {
    92  			return false, fmt.Errorf("poststart task hasn't started")
    93  		}
    94  
    95  		afi, _, err := nomadClient.AllocFS().List(alloc, "alloc", nil)
    96  		if err != nil {
    97  			return false, err
    98  		}
    99  		expected := map[string]bool{
   100  			"main-checked": true}
   101  		got := checkFiles(expected, afi)
   102  		if !got["main-checked"] {
   103  			return false, fmt.Errorf("main-checked file has not been written")
   104  		}
   105  
   106  		return true, nil
   107  	}, func(err error) {
   108  		require.NoError(err, "failed to wait on alloc")
   109  	})
   110  
   111  	alloc, _, err := nomadClient.Allocations().Info(allocID, nil)
   112  	require.NoError(err)
   113  
   114  	require.False(alloc.TaskStates["poststart"].Failed)
   115  
   116  	// stop the job
   117  	_, _, err = nomadClient.Jobs().Deregister(jobID, false, nil)
   118  	require.NoError(err)
   119  	e2eutil.WaitForAllocStopped(t, nomadClient, allocID)
   120  
   121  	require.False(alloc.TaskStates["poststop"].Failed)
   122  
   123  	// assert the files were written as expected
   124  	afi, _, err := nomadClient.AllocFS().List(alloc, "alloc", nil)
   125  	require.NoError(err)
   126  	expected := map[string]bool{
   127  		"init-ran": true, "sidecar-ran": true, "main-ran": true, "poststart-ran": true, "poststop-ran": true,
   128  		"poststart-started": true, "main-started": true, "poststop-started": true,
   129  		"init-running": false, "poststart-running": false, "poststop-running": false,
   130  		"main-checked": true}
   131  	got := checkFiles(expected, afi)
   132  	require.Equal(expected, got)
   133  }
   134  
   135  // checkFiles returns a map of whether the expected files were found
   136  // in the file info response
   137  func checkFiles(expected map[string]bool, got []*api.AllocFileInfo) map[string]bool {
   138  	results := map[string]bool{}
   139  	for expect := range expected {
   140  		results[expect] = false
   141  	}
   142  	for _, file := range got {
   143  		// there will be files unrelated to the test, so ignore those
   144  		if _, ok := results[file.Name]; ok {
   145  			results[file.Name] = true
   146  		}
   147  	}
   148  	return results
   149  }