github.com/hernad/nomad@v1.6.112/e2e/servicediscovery/nomad_checks_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package servicediscovery 5 6 import ( 7 "context" 8 "regexp" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/hernad/nomad/e2e/e2eutil" 14 "github.com/hernad/nomad/helper/uuid" 15 "github.com/hernad/nomad/nomad/structs" 16 "github.com/shoenig/test" 17 "github.com/shoenig/test/must" 18 "github.com/shoenig/test/wait" 19 "github.com/stretchr/testify/require" 20 ) 21 22 func testChecksHappy(t *testing.T) { 23 nomadClient := e2eutil.NomadClient(t) 24 25 // Generate our unique job ID which will be used for this test. 26 jobID := "nsd-check-happy-" + uuid.Short() 27 jobIDs := []string{jobID} 28 29 // Defer a cleanup function to remove the job. This will trigger if the 30 // test fails, unless the cancel function is called. 31 ctx, cancel := context.WithCancel(context.Background()) 32 defer cancel() 33 defer e2eutil.CleanupJobsAndGCWithContext(t, ctx, &jobIDs) 34 35 // Register the happy checks job. 36 allocStubs := e2eutil.RegisterAndWaitForAllocs(t, nomadClient, jobChecksHappy, jobID, "") 37 must.Len(t, 1, allocStubs) 38 39 // wait for the alloc to be running 40 e2eutil.WaitForAllocRunning(t, nomadClient, allocStubs[0].ID) 41 42 // Get and test the output of 'nomad alloc checks'. 43 require.Eventually(t, func() bool { 44 output, err := e2eutil.AllocChecks(allocStubs[0].ID) 45 if err != nil { 46 return false 47 } 48 49 // assert the output contains success 50 statusRe := regexp.MustCompile(`Status\s+=\s+success`) 51 if !statusRe.MatchString(output) { 52 return false 53 } 54 55 // assert the output contains 200 status code 56 statusCodeRe := regexp.MustCompile(`StatusCode\s+=\s+200`) 57 if !statusCodeRe.MatchString(output) { 58 return false 59 } 60 61 // assert output contains nomad's success string 62 return strings.Contains(output, `nomad: http ok`) 63 }, 5*time.Second, 200*time.Millisecond) 64 } 65 66 func testChecksSad(t *testing.T) { 67 nomadClient := e2eutil.NomadClient(t) 68 69 // Generate our unique job ID which will be used for this test. 70 jobID := "nsd-check-sad-" + uuid.Short() 71 jobIDs := []string{jobID} 72 73 // Defer a cleanup function to remove the job. This will trigger if the 74 // test fails, unless the cancel function is called. 75 ctx, cancel := context.WithCancel(context.Background()) 76 defer cancel() 77 defer e2eutil.CleanupJobsAndGCWithContext(t, ctx, &jobIDs) 78 79 // Register the sad checks job. 80 allocStubs := e2eutil.RegisterAndWaitForAllocs(t, nomadClient, jobChecksSad, jobID, "") 81 must.Len(t, 1, allocStubs) 82 83 // wait for the alloc to be running 84 e2eutil.WaitForAllocRunning(t, nomadClient, allocStubs[0].ID) 85 86 // Get and test the output of 'nomad alloc checks'. 87 require.Eventually(t, func() bool { 88 output, err := e2eutil.AllocChecks(allocStubs[0].ID) 89 if err != nil { 90 return false 91 } 92 93 // assert the output contains failure 94 statusRe := regexp.MustCompile(`Status\s+=\s+failure`) 95 if !statusRe.MatchString(output) { 96 return false 97 } 98 99 // assert the output contains 501 status code 100 statusCodeRe := regexp.MustCompile(`StatusCode\s+=\s+501`) 101 if !statusCodeRe.MatchString(output) { 102 return false 103 } 104 105 // assert output contains error output from python http.server 106 return strings.Contains(output, `<p>Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does not support this operation.</p>`) 107 }, 5*time.Second, 200*time.Millisecond) 108 } 109 110 func testChecksServiceReRegisterAfterCheckRestart(t *testing.T) { 111 const ( 112 jobChecksAfterRestartMain = "./input/checks_task_restart_main.nomad" 113 jobChecksAfterRestartHelper = "./input/checks_task_restart_helper.nomad" 114 ) 115 116 nomadClient := e2eutil.NomadClient(t) 117 118 idJobMain := "nsd-check-restart-services-" + uuid.Short() 119 idJobHelper := "nsd-check-restart-services-helper-" + uuid.Short() 120 jobIDs := []string{idJobMain, idJobHelper} 121 122 // Defer a cleanup function to remove the job. This will trigger if the 123 // test fails, unless the cancel function is called. 124 ctx, cancel := context.WithCancel(context.Background()) 125 defer cancel() 126 defer e2eutil.CleanupJobsAndGCWithContext(t, ctx, &jobIDs) 127 128 // register the main job 129 allocStubs := e2eutil.RegisterAndWaitForAllocs(t, nomadClient, jobChecksAfterRestartMain, idJobMain, "") 130 must.Len(t, 1, allocStubs) 131 132 // wait for task restart due to failing health check 133 must.Wait(t, wait.InitialSuccess( 134 wait.BoolFunc(func() bool { 135 allocEvents, err := e2eutil.AllocTaskEventsForJob(idJobMain, "") 136 if err != nil { 137 t.Log("failed to get task events for job", idJobMain, err) 138 return false 139 } 140 for _, events := range allocEvents { 141 for _, event := range events { 142 if event["Type"] == "Restarting" { 143 return true 144 } 145 } 146 } 147 return false 148 }), 149 wait.Timeout(30*time.Second), 150 wait.Gap(3*time.Second), 151 )) 152 153 runHelper := func(command string) { 154 vars := []string{"-var", "nodeID=" + allocStubs[0].NodeID, "-var", "cmd=touch", "-var", "delay=3s"} 155 err := e2eutil.RegisterWithArgs(idJobHelper, jobChecksAfterRestartHelper, vars...) 156 test.NoError(t, err) 157 } 158 159 // register helper job, triggering check to start passing 160 runHelper("touch") 161 defer func() { 162 runHelper("rm") 163 }() 164 165 // wait for main task to become healthy 166 e2eutil.WaitForAllocStatus(t, nomadClient, allocStubs[0].ID, structs.AllocClientStatusRunning) 167 168 // finally assert we have services 169 services := nomadClient.Services() 170 serviceStubs, _, err := services.Get("nsd-checks-task-restart-test", nil) 171 must.NoError(t, err) 172 must.Len(t, 1, serviceStubs) 173 }