github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/e2e/consul/consul.go (about) 1 package consul 2 3 import ( 4 "time" 5 6 "github.com/hashicorp/nomad/api" 7 "github.com/hashicorp/nomad/e2e/e2eutil" 8 "github.com/hashicorp/nomad/e2e/framework" 9 "github.com/hashicorp/nomad/helper/uuid" 10 . "github.com/onsi/gomega" 11 "github.com/stretchr/testify/require" 12 ) 13 14 type ConsulE2ETest struct { 15 framework.TC 16 jobIds []string 17 } 18 19 func init() { 20 framework.AddSuites(&framework.TestSuite{ 21 Component: "Consul", 22 CanRunLocal: true, 23 Consul: true, 24 Cases: []framework.TestCase{ 25 new(ConsulE2ETest), 26 new(ScriptChecksE2ETest), 27 }, 28 }) 29 } 30 31 func (tc *ConsulE2ETest) BeforeAll(f *framework.F) { 32 // Ensure cluster has leader before running tests 33 e2eutil.WaitForLeader(f.T(), tc.Nomad()) 34 // Ensure that we have four client nodes in ready state 35 e2eutil.WaitForNodesReady(f.T(), tc.Nomad(), 1) 36 } 37 38 type serviceNameTagPair struct { 39 serviceName string 40 tags map[string]struct{} 41 } 42 43 // This test runs a job that registers in Consul with specific tags 44 func (tc *ConsulE2ETest) TestConsulRegistration(f *framework.F) { 45 nomadClient := tc.Nomad() 46 uuid := uuid.Generate() 47 jobId := "consul" + uuid[0:8] 48 tc.jobIds = append(tc.jobIds, jobId) 49 50 allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, "consul/input/consul_example.nomad", jobId, "") 51 consulClient := tc.Consul() 52 require := require.New(f.T()) 53 require.Equal(3, len(allocs)) 54 55 // Query consul catalog for service 56 catalog := consulClient.Catalog() 57 g := NewGomegaWithT(f.T()) 58 59 expectedTags := map[string]struct{}{} 60 expectedTags["global"] = struct{}{} 61 expectedTags["cache"] = struct{}{} 62 63 g.Eventually(func() []serviceNameTagPair { 64 consulService, _, err := catalog.Service("redis-cache", "", nil) 65 require.Nil(err) 66 var serviceInfo []serviceNameTagPair 67 for _, serviceInstance := range consulService { 68 tags := map[string]struct{}{} 69 for _, tag := range serviceInstance.ServiceTags { 70 tags[tag] = struct{}{} 71 } 72 serviceInfo = append(serviceInfo, serviceNameTagPair{serviceInstance.ServiceName, tags}) 73 } 74 return serviceInfo 75 }, 5*time.Second, time.Second).Should(ConsistOf([]serviceNameTagPair{ 76 {"redis-cache", expectedTags}, 77 {"redis-cache", expectedTags}, 78 {"redis-cache", expectedTags}, 79 })) 80 81 jobs := nomadClient.Jobs() 82 // Stop all jobs in test 83 for _, id := range tc.jobIds { 84 jobs.Deregister(id, true, nil) 85 } 86 // Garbage collect 87 nomadClient.System().GarbageCollect() 88 89 // Verify that services were deregistered in Consul 90 g.Eventually(func() []string { 91 consulService, _, err := catalog.Service("redis-cache", "", nil) 92 require.Nil(err) 93 var serviceIDs []string 94 for _, serviceInstance := range consulService { 95 serviceIDs = append(serviceIDs, serviceInstance.ServiceID) 96 } 97 return serviceIDs 98 }, 5*time.Second, time.Second).Should(BeEmpty()) 99 } 100 101 // This test verifies setting and unsetting canary tags 102 func (tc *ConsulE2ETest) TestCanaryInplaceUpgrades(f *framework.F) { 103 nomadClient := tc.Nomad() 104 uuid := uuid.Generate() 105 jobId := "consul" + uuid[0:8] 106 tc.jobIds = append(tc.jobIds, jobId) 107 108 allocs := e2eutil.RegisterAndWaitForAllocs(f.T(), nomadClient, "consul/input/canary_tags.nomad", jobId, "") 109 consulClient := tc.Consul() 110 require := require.New(f.T()) 111 require.Equal(2, len(allocs)) 112 113 jobs := nomadClient.Jobs() 114 g := NewGomegaWithT(f.T()) 115 116 g.Eventually(func() []string { 117 deploys, _, err := jobs.Deployments(jobId, false, nil) 118 require.Nil(err) 119 healthyDeploys := make([]string, 0, len(deploys)) 120 for _, d := range deploys { 121 if d.Status == "successful" { 122 healthyDeploys = append(healthyDeploys, d.ID) 123 } 124 } 125 return healthyDeploys 126 }, 5*time.Second, 20*time.Millisecond).Should(HaveLen(1)) 127 128 // Start a deployment 129 job, _, err := jobs.Info(jobId, nil) 130 require.Nil(err) 131 job.Meta = map[string]string{"version": "2"} 132 resp, _, err := jobs.Register(job, nil) 133 require.Nil(err) 134 require.NotEmpty(resp.EvalID) 135 136 // Eventually have a canary 137 var deploys []*api.Deployment 138 g.Eventually(func() []*api.Deployment { 139 deploys, _, err = jobs.Deployments(*job.ID, false, nil) 140 require.Nil(err) 141 return deploys 142 }, 2*time.Second, 20*time.Millisecond).Should(HaveLen(2)) 143 144 deployments := nomadClient.Deployments() 145 var deploy *api.Deployment 146 g.Eventually(func() []string { 147 deploy, _, err = deployments.Info(deploys[0].ID, nil) 148 require.Nil(err) 149 return deploy.TaskGroups["consul_canary_test"].PlacedCanaries 150 }, 2*time.Second, 20*time.Millisecond).Should(HaveLen(1)) 151 152 allocations := nomadClient.Allocations() 153 g.Eventually(func() bool { 154 allocID := deploy.TaskGroups["consul_canary_test"].PlacedCanaries[0] 155 alloc, _, err := allocations.Info(allocID, nil) 156 require.Nil(err) 157 return alloc.DeploymentStatus != nil && alloc.DeploymentStatus.Healthy != nil && *alloc.DeploymentStatus.Healthy 158 }, 3*time.Second, 20*time.Millisecond).Should(BeTrue()) 159 160 // Query consul catalog for service 161 catalog := consulClient.Catalog() 162 // Check Consul for canary tags 163 g.Eventually(func() []string { 164 consulServices, _, err := catalog.Service("canarytest", "", nil) 165 require.Nil(err) 166 167 for _, serviceInstance := range consulServices { 168 for _, tag := range serviceInstance.ServiceTags { 169 if tag == "canary" { 170 return serviceInstance.ServiceTags 171 } 172 } 173 } 174 175 return nil 176 }, 2*time.Second, 20*time.Millisecond).Should( 177 Equal([]string{"foo", "canary"})) 178 179 // Manually promote 180 { 181 resp, _, err := deployments.PromoteAll(deploys[0].ID, nil) 182 require.Nil(err) 183 require.NotEmpty(resp.EvalID) 184 } 185 186 // Eventually canary is removed 187 g.Eventually(func() bool { 188 allocID := deploy.TaskGroups["consul_canary_test"].PlacedCanaries[0] 189 alloc, _, err := allocations.Info(allocID, nil) 190 require.Nil(err) 191 return alloc.DeploymentStatus.Canary 192 }, 2*time.Second, 20*time.Millisecond).Should(BeFalse()) 193 194 // Verify that no instances have canary tags 195 expectedTags := map[string]struct{}{} 196 expectedTags["foo"] = struct{}{} 197 expectedTags["bar"] = struct{}{} 198 199 g.Eventually(func() []serviceNameTagPair { 200 consulServices, _, err := catalog.Service("canarytest", "", nil) 201 require.Nil(err) 202 var serviceInfo []serviceNameTagPair 203 for _, serviceInstance := range consulServices { 204 tags := map[string]struct{}{} 205 for _, tag := range serviceInstance.ServiceTags { 206 tags[tag] = struct{}{} 207 } 208 serviceInfo = append(serviceInfo, serviceNameTagPair{serviceInstance.ServiceName, tags}) 209 } 210 return serviceInfo 211 }, 3*time.Second, 20*time.Millisecond).Should(ConsistOf([]serviceNameTagPair{ 212 {"canarytest", expectedTags}, 213 {"canarytest", expectedTags}, 214 })) 215 216 } 217 218 func (tc *ConsulE2ETest) AfterEach(f *framework.F) { 219 nomadClient := tc.Nomad() 220 jobs := nomadClient.Jobs() 221 // Stop all jobs in test 222 for _, id := range tc.jobIds { 223 jobs.Deregister(id, true, nil) 224 } 225 // Garbage collect 226 nomadClient.System().GarbageCollect() 227 }