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 }