github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/e2e/consul/consul.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/hashicorp/nomad/api" 8 "github.com/hashicorp/nomad/e2e/e2eutil" 9 "github.com/hashicorp/nomad/e2e/framework" 10 "github.com/hashicorp/nomad/helper" 11 "github.com/hashicorp/nomad/helper/uuid" 12 "github.com/hashicorp/nomad/nomad/structs" 13 "github.com/hashicorp/nomad/testutil" 14 "github.com/stretchr/testify/require" 15 ) 16 17 const ( 18 consulJobBasic = "consul/input/consul_example.nomad" 19 consulJobCanaryTags = "consul/input/canary_tags.nomad" 20 21 consulJobRegisterOnUpdatePart1 = "consul/input/services_empty.nomad" 22 consulJobRegisterOnUpdatePart2 = "consul/input/services_present.nomad" 23 ) 24 25 type ConsulE2ETest struct { 26 framework.TC 27 jobIds []string 28 } 29 30 func init() { 31 framework.AddSuites(&framework.TestSuite{ 32 Component: "Consul", 33 CanRunLocal: true, 34 Consul: true, 35 Cases: []framework.TestCase{ 36 new(ConsulE2ETest), 37 new(ScriptChecksE2ETest), 38 new(CheckRestartE2ETest), 39 new(OnUpdateChecksTest), 40 }, 41 }) 42 } 43 44 func (tc *ConsulE2ETest) BeforeAll(f *framework.F) { 45 e2eutil.WaitForLeader(f.T(), tc.Nomad()) 46 e2eutil.WaitForNodesReady(f.T(), tc.Nomad(), 1) 47 } 48 49 func (tc *ConsulE2ETest) AfterEach(f *framework.F) { 50 if os.Getenv("NOMAD_TEST_SKIPCLEANUP") == "1" { 51 return 52 } 53 54 for _, id := range tc.jobIds { 55 _, _, err := tc.Nomad().Jobs().Deregister(id, true, nil) 56 require.NoError(f.T(), err) 57 } 58 tc.jobIds = []string{} 59 require.NoError(f.T(), tc.Nomad().System().GarbageCollect()) 60 } 61 62 // TestConsulRegistration asserts that a job registers services with tags in Consul. 63 func (tc *ConsulE2ETest) TestConsulRegistration(f *framework.F) { 64 t := f.T() 65 r := require.New(t) 66 67 nomadClient := tc.Nomad() 68 jobId := "consul" + uuid.Short() 69 tc.jobIds = append(tc.jobIds, jobId) 70 71 allocations := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, consulJobBasic, jobId, "") 72 require.Equal(t, 3, len(allocations)) 73 allocIDs := e2eutil.AllocIDsFromAllocationListStubs(allocations) 74 e2eutil.WaitForAllocsRunning(t, tc.Nomad(), allocIDs) 75 76 expectedTags := []string{ 77 "cache", 78 "global", 79 } 80 81 // Assert services get registered 82 e2eutil.RequireConsulRegistered(r, tc.Consul(), "consul-example", 3) 83 services, _, err := tc.Consul().Catalog().Service("consul-example", "", nil) 84 require.NoError(t, err) 85 for _, s := range services { 86 // If we've made it this far the tags should *always* match 87 require.ElementsMatch(t, expectedTags, s.ServiceTags) 88 } 89 90 // Stop the job 91 e2eutil.WaitForJobStopped(t, nomadClient, jobId) 92 93 // Verify that services were de-registered in Consul 94 e2eutil.RequireConsulDeregistered(r, tc.Consul(), "consul-example") 95 } 96 97 func (tc *ConsulE2ETest) TestConsulRegisterOnUpdate(f *framework.F) { 98 t := f.T() 99 r := require.New(t) 100 101 nomadClient := tc.Nomad() 102 catalog := tc.Consul().Catalog() 103 jobID := "consul" + uuid.Short() 104 tc.jobIds = append(tc.jobIds, jobID) 105 106 // Initial job has no services for task. 107 allocations := e2eutil.RegisterAndWaitForAllocs(t, nomadClient, consulJobRegisterOnUpdatePart1, jobID, "") 108 require.Equal(t, 1, len(allocations)) 109 allocIDs := e2eutil.AllocIDsFromAllocationListStubs(allocations) 110 e2eutil.WaitForAllocsRunning(t, tc.Nomad(), allocIDs) 111 112 // Assert service not yet registered. 113 results, _, err := catalog.Service("nc-service", "", nil) 114 require.NoError(t, err) 115 require.Empty(t, results) 116 117 // On update, add services for task. 118 allocations = e2eutil.RegisterAndWaitForAllocs(t, nomadClient, consulJobRegisterOnUpdatePart2, jobID, "") 119 require.Equal(t, 1, len(allocations)) 120 allocIDs = e2eutil.AllocIDsFromAllocationListStubs(allocations) 121 e2eutil.WaitForAllocsRunning(t, tc.Nomad(), allocIDs) 122 123 // Assert service is now registered. 124 e2eutil.RequireConsulRegistered(r, tc.Consul(), "nc-service", 1) 125 } 126 127 // TestCanaryInplaceUpgrades verifies setting and unsetting canary tags 128 func (tc *ConsulE2ETest) TestCanaryInplaceUpgrades(f *framework.F) { 129 t := f.T() 130 131 // TODO(shoenig) https://github.com/hashicorp/nomad/issues/9627 132 t.Skip("THIS TEST IS BROKEN (#9627)") 133 134 nomadClient := tc.Nomad() 135 consulClient := tc.Consul() 136 jobId := "consul" + uuid.Generate()[0:8] 137 tc.jobIds = append(tc.jobIds, jobId) 138 139 allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, consulJobCanaryTags, jobId, "") 140 require.Equal(t, 2, len(allocs)) 141 142 allocIDs := e2eutil.AllocIDsFromAllocationListStubs(allocs) 143 e2eutil.WaitForAllocsRunning(t, nomadClient, allocIDs) 144 145 // Start a deployment 146 job, _, err := nomadClient.Jobs().Info(jobId, nil) 147 require.NoError(t, err) 148 job.Meta = map[string]string{"version": "2"} 149 resp, _, err := nomadClient.Jobs().Register(job, nil) 150 require.NoError(t, err) 151 require.NotEmpty(t, resp.EvalID) 152 153 // Eventually have a canary 154 var activeDeploy *api.Deployment 155 testutil.WaitForResult(func() (bool, error) { 156 deploys, _, err := nomadClient.Jobs().Deployments(jobId, false, nil) 157 if err != nil { 158 return false, err 159 } 160 if expected := 2; len(deploys) != expected { 161 return false, fmt.Errorf("expected 2 deploys but found %v", deploys) 162 } 163 164 for _, d := range deploys { 165 if d.Status == structs.DeploymentStatusRunning { 166 activeDeploy = d 167 break 168 } 169 } 170 if activeDeploy == nil { 171 return false, fmt.Errorf("no running deployments: %v", deploys) 172 } 173 if expected := 1; len(activeDeploy.TaskGroups["consul_canary_test"].PlacedCanaries) != expected { 174 return false, fmt.Errorf("expected %d placed canaries but found %#v", 175 expected, activeDeploy.TaskGroups["consul_canary_test"]) 176 } 177 178 return true, nil 179 }, func(err error) { 180 f.NoError(err, "error while waiting for deploys") 181 }) 182 183 allocID := activeDeploy.TaskGroups["consul_canary_test"].PlacedCanaries[0] 184 testutil.WaitForResult(func() (bool, error) { 185 alloc, _, err := nomadClient.Allocations().Info(allocID, nil) 186 if err != nil { 187 return false, err 188 } 189 190 if alloc.DeploymentStatus == nil { 191 return false, fmt.Errorf("canary alloc %s has no deployment status", allocID) 192 } 193 if alloc.DeploymentStatus.Healthy == nil { 194 return false, fmt.Errorf("canary alloc %s has no deployment health: %#v", 195 allocID, alloc.DeploymentStatus) 196 } 197 return *alloc.DeploymentStatus.Healthy, fmt.Errorf("expected healthy canary but found: %#v", 198 alloc.DeploymentStatus) 199 }, func(err error) { 200 f.NoError(err, "error waiting for canary to be healthy") 201 }) 202 203 // Check Consul for canary tags 204 testutil.WaitForResult(func() (bool, error) { 205 consulServices, _, err := consulClient.Catalog().Service("canarytest", "", nil) 206 if err != nil { 207 return false, err 208 } 209 for _, s := range consulServices { 210 if helper.CompareSliceSetString([]string{"canary", "foo"}, s.ServiceTags) { 211 return true, nil 212 } 213 } 214 return false, fmt.Errorf(`could not find service tags {"canary", "foo"}: %#v`, consulServices) 215 }, func(err error) { 216 f.NoError(err, "error waiting for canary tags") 217 }) 218 219 // Promote canary 220 { 221 resp, _, err := nomadClient.Deployments().PromoteAll(activeDeploy.ID, nil) 222 require.NoError(t, err) 223 require.NotEmpty(t, resp.EvalID) 224 } 225 226 // Eventually canary is promoted 227 testutil.WaitForResult(func() (bool, error) { 228 alloc, _, err := nomadClient.Allocations().Info(allocID, nil) 229 if err != nil { 230 return false, err 231 } 232 return !alloc.DeploymentStatus.Canary, fmt.Errorf("still a canary") 233 }, func(err error) { 234 require.NoError(t, err, "error waiting for canary to be promoted") 235 }) 236 237 // Verify that no instances have canary tags 238 expected := []string{"foo", "bar"} 239 testutil.WaitForResult(func() (bool, error) { 240 consulServices, _, err := consulClient.Catalog().Service("canarytest", "", nil) 241 if err != nil { 242 return false, err 243 } 244 for _, s := range consulServices { 245 if !helper.CompareSliceSetString(expected, s.ServiceTags) { 246 return false, fmt.Errorf("expected %#v Consul tags but found %#v", 247 expected, s.ServiceTags) 248 } 249 } 250 return true, nil 251 }, func(err error) { 252 require.NoError(t, err, "error waiting for non-canary tags") 253 }) 254 255 }