github.com/manicqin/nomad@v0.9.5/client/allocrunner/groupservice_hook_test.go (about)

     1  package allocrunner
     2  
     3  import (
     4  	"io/ioutil"
     5  	"testing"
     6  	"time"
     7  
     8  	consulapi "github.com/hashicorp/consul/api"
     9  	ctestutil "github.com/hashicorp/consul/testutil"
    10  	"github.com/hashicorp/nomad/client/allocrunner/interfaces"
    11  	"github.com/hashicorp/nomad/client/consul"
    12  	"github.com/hashicorp/nomad/client/taskenv"
    13  	agentconsul "github.com/hashicorp/nomad/command/agent/consul"
    14  	"github.com/hashicorp/nomad/helper/testlog"
    15  	"github.com/hashicorp/nomad/nomad/mock"
    16  	"github.com/hashicorp/nomad/nomad/structs"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  var _ interfaces.RunnerPrerunHook = (*groupServiceHook)(nil)
    21  var _ interfaces.RunnerUpdateHook = (*groupServiceHook)(nil)
    22  var _ interfaces.RunnerPostrunHook = (*groupServiceHook)(nil)
    23  var _ interfaces.RunnerPreKillHook = (*groupServiceHook)(nil)
    24  
    25  // TestGroupServiceHook_NoGroupServices asserts calling group service hooks
    26  // without group services does not error.
    27  func TestGroupServiceHook_NoGroupServices(t *testing.T) {
    28  	t.Parallel()
    29  
    30  	alloc := mock.Alloc()
    31  	alloc.Job.TaskGroups[0].Services = []*structs.Service{{
    32  		Name:      "foo",
    33  		PortLabel: "9999",
    34  	}}
    35  	logger := testlog.HCLogger(t)
    36  	consulClient := consul.NewMockConsulServiceClient(t, logger)
    37  
    38  	h := newGroupServiceHook(groupServiceHookConfig{
    39  		alloc:          alloc,
    40  		consul:         consulClient,
    41  		restarter:      agentconsul.NoopRestarter(),
    42  		taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region),
    43  		logger:         logger,
    44  	})
    45  	require.NoError(t, h.Prerun())
    46  
    47  	req := &interfaces.RunnerUpdateRequest{Alloc: alloc}
    48  	require.NoError(t, h.Update(req))
    49  
    50  	require.NoError(t, h.Postrun())
    51  
    52  	ops := consulClient.GetOps()
    53  	require.Len(t, ops, 4)
    54  	require.Equal(t, "add", ops[0].Op)
    55  	require.Equal(t, "update", ops[1].Op)
    56  	require.Equal(t, "remove", ops[2].Op)
    57  }
    58  
    59  // TestGroupServiceHook_GroupServices asserts group service hooks with group
    60  // services does not error.
    61  func TestGroupServiceHook_GroupServices(t *testing.T) {
    62  	t.Parallel()
    63  
    64  	alloc := mock.ConnectAlloc()
    65  	logger := testlog.HCLogger(t)
    66  	consulClient := consul.NewMockConsulServiceClient(t, logger)
    67  
    68  	h := newGroupServiceHook(groupServiceHookConfig{
    69  		alloc:          alloc,
    70  		consul:         consulClient,
    71  		restarter:      agentconsul.NoopRestarter(),
    72  		taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region),
    73  		logger:         logger,
    74  	})
    75  	require.NoError(t, h.Prerun())
    76  
    77  	req := &interfaces.RunnerUpdateRequest{Alloc: alloc}
    78  	require.NoError(t, h.Update(req))
    79  
    80  	require.NoError(t, h.Postrun())
    81  
    82  	ops := consulClient.GetOps()
    83  	require.Len(t, ops, 4)
    84  	require.Equal(t, "add", ops[0].Op)
    85  	require.Equal(t, "update", ops[1].Op)
    86  	require.Equal(t, "remove", ops[2].Op)
    87  }
    88  
    89  // TestGroupServiceHook_Error asserts group service hooks with group
    90  // services but no group network returns an error.
    91  func TestGroupServiceHook_NoNetwork(t *testing.T) {
    92  	t.Parallel()
    93  
    94  	alloc := mock.Alloc()
    95  	alloc.Job.TaskGroups[0].Networks = []*structs.NetworkResource{}
    96  	tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
    97  	tg.Services = []*structs.Service{
    98  		{
    99  			Name:      "testconnect",
   100  			PortLabel: "9999",
   101  			Connect: &structs.ConsulConnect{
   102  				SidecarService: &structs.ConsulSidecarService{},
   103  			},
   104  		},
   105  	}
   106  	logger := testlog.HCLogger(t)
   107  
   108  	consulClient := consul.NewMockConsulServiceClient(t, logger)
   109  
   110  	h := newGroupServiceHook(groupServiceHookConfig{
   111  		alloc:          alloc,
   112  		consul:         consulClient,
   113  		restarter:      agentconsul.NoopRestarter(),
   114  		taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region),
   115  		logger:         logger,
   116  	})
   117  	require.NoError(t, h.Prerun())
   118  
   119  	req := &interfaces.RunnerUpdateRequest{Alloc: alloc}
   120  	require.NoError(t, h.Update(req))
   121  
   122  	require.NoError(t, h.Postrun())
   123  
   124  	ops := consulClient.GetOps()
   125  	require.Len(t, ops, 4)
   126  	require.Equal(t, "add", ops[0].Op)
   127  	require.Equal(t, "update", ops[1].Op)
   128  	require.Equal(t, "remove", ops[2].Op)
   129  }
   130  
   131  func TestGroupServiceHook_getWorkloadServices(t *testing.T) {
   132  	t.Parallel()
   133  
   134  	alloc := mock.Alloc()
   135  	alloc.Job.TaskGroups[0].Networks = []*structs.NetworkResource{}
   136  	tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
   137  	tg.Services = []*structs.Service{
   138  		{
   139  			Name:      "testconnect",
   140  			PortLabel: "9999",
   141  			Connect: &structs.ConsulConnect{
   142  				SidecarService: &structs.ConsulSidecarService{},
   143  			},
   144  		},
   145  	}
   146  	logger := testlog.HCLogger(t)
   147  
   148  	consulClient := consul.NewMockConsulServiceClient(t, logger)
   149  
   150  	h := newGroupServiceHook(groupServiceHookConfig{
   151  		alloc:          alloc,
   152  		consul:         consulClient,
   153  		restarter:      agentconsul.NoopRestarter(),
   154  		taskEnvBuilder: taskenv.NewBuilder(mock.Node(), alloc, nil, alloc.Job.Region),
   155  		logger:         logger,
   156  	})
   157  
   158  	services := h.getWorkloadServices()
   159  	require.Len(t, services.Services, 1)
   160  }
   161  
   162  // TestGroupServiceHook_Update08Alloc asserts that adding group services to a previously
   163  // 0.8 alloc works.
   164  //
   165  // COMPAT(0.11) Only valid for upgrades from 0.8.
   166  func TestGroupServiceHook_Update08Alloc(t *testing.T) {
   167  	// Create an embedded Consul server
   168  	testconsul, err := ctestutil.NewTestServerConfig(func(c *ctestutil.TestServerConfig) {
   169  		// If -v wasn't specified squelch consul logging
   170  		if !testing.Verbose() {
   171  			c.Stdout = ioutil.Discard
   172  			c.Stderr = ioutil.Discard
   173  		}
   174  	})
   175  	if err != nil {
   176  		t.Fatalf("error starting test consul server: %v", err)
   177  	}
   178  	defer testconsul.Stop()
   179  
   180  	consulConfig := consulapi.DefaultConfig()
   181  	consulConfig.Address = testconsul.HTTPAddr
   182  	consulClient, err := consulapi.NewClient(consulConfig)
   183  	require.NoError(t, err)
   184  	serviceClient := agentconsul.NewServiceClient(consulClient.Agent(), testlog.HCLogger(t), true)
   185  
   186  	// Lower periodicInterval to ensure periodic syncing doesn't improperly
   187  	// remove Connect services.
   188  	//const interval = 50 * time.Millisecond
   189  	//serviceClient.periodicInterval = interval
   190  
   191  	// Disable deregistration probation to test syncing
   192  	//serviceClient.deregisterProbationExpiry = time.Time{}
   193  
   194  	go serviceClient.Run()
   195  	defer serviceClient.Shutdown()
   196  
   197  	// Create new 0.10-style alloc
   198  	alloc := mock.Alloc()
   199  	alloc.AllocatedResources.Shared.Networks = []*structs.NetworkResource{
   200  		{
   201  			Mode: "bridge",
   202  			IP:   "10.0.0.1",
   203  			DynamicPorts: []structs.Port{
   204  				{
   205  					Label: "connect-proxy-testconnect",
   206  					Value: 9999,
   207  					To:    9998,
   208  				},
   209  			},
   210  		},
   211  	}
   212  	tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
   213  	tg.Services = []*structs.Service{
   214  		{
   215  			Name:      "testconnect",
   216  			PortLabel: "9999",
   217  			Connect: &structs.ConsulConnect{
   218  				SidecarService: &structs.ConsulSidecarService{
   219  					Proxy: &structs.ConsulProxy{
   220  						LocalServicePort: 9000,
   221  					},
   222  				},
   223  			},
   224  		},
   225  	}
   226  
   227  	// Create old 0.8-style alloc from new alloc
   228  	oldAlloc := alloc.Copy()
   229  	oldAlloc.AllocatedResources = nil
   230  	oldAlloc.Job.LookupTaskGroup(alloc.TaskGroup).Services = nil
   231  
   232  	// Create the group service hook
   233  	h := newGroupServiceHook(groupServiceHookConfig{
   234  		alloc:          oldAlloc,
   235  		consul:         serviceClient,
   236  		restarter:      agentconsul.NoopRestarter(),
   237  		taskEnvBuilder: taskenv.NewBuilder(mock.Node(), oldAlloc, nil, oldAlloc.Job.Region),
   238  		logger:         testlog.HCLogger(t),
   239  	})
   240  
   241  	require.NoError(t, h.Prerun())
   242  	require.NoError(t, h.Update(&interfaces.RunnerUpdateRequest{Alloc: alloc}))
   243  
   244  	// Assert the group and sidecar services are registered
   245  	require.Eventually(t, func() bool {
   246  		services, err := consulClient.Agent().Services()
   247  		require.NoError(t, err)
   248  		return len(services) == 2
   249  	}, 3*time.Second, 100*time.Millisecond)
   250  
   251  }