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  }