github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/client/consul/sync_test.go (about)

     1  package consul
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"reflect"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/hashicorp/go-multierror"
    12  	"github.com/hashicorp/nomad/nomad/structs"
    13  )
    14  
    15  const (
    16  	allocID = "12"
    17  )
    18  
    19  var (
    20  	logger = log.New(os.Stdout, "", log.LstdFlags)
    21  	check1 = structs.ServiceCheck{
    22  		Name:     "check-foo-1",
    23  		Type:     structs.ServiceCheckTCP,
    24  		Interval: 30 * time.Second,
    25  		Timeout:  5 * time.Second,
    26  	}
    27  	service1 = structs.Service{
    28  		Name:      "foo-1",
    29  		Tags:      []string{"tag1", "tag2"},
    30  		PortLabel: "port1",
    31  		Checks: []*structs.ServiceCheck{
    32  			&check1,
    33  		},
    34  	}
    35  
    36  	service2 = structs.Service{
    37  		Name:      "foo-2",
    38  		Tags:      []string{"tag1", "tag2"},
    39  		PortLabel: "port2",
    40  	}
    41  )
    42  
    43  func TestConsulServiceRegisterServices(t *testing.T) {
    44  	cs, err := NewConsulService(&ConsulConfig{}, logger)
    45  	if err != nil {
    46  		t.Fatalf("Err: %v", err)
    47  	}
    48  	// Skipping the test if consul isn't present
    49  	if !cs.consulPresent() {
    50  		return
    51  	}
    52  	task := mockTask()
    53  	cs.SetServiceIdentifier(GenerateServiceIdentifier(allocID, task.Name))
    54  	cs.SetAddrFinder(task.FindHostAndPortFor)
    55  	if err := cs.SyncServices(task.Services); err != nil {
    56  		t.Fatalf("err: %v", err)
    57  	}
    58  	defer cs.Shutdown()
    59  
    60  	service1ID := service1.ID(GenerateServiceIdentifier(allocID, task.Name))
    61  	service2ID := service2.ID(GenerateServiceIdentifier(allocID, task.Name))
    62  	if err := servicesPresent(t, []string{service1ID, service2ID}, cs); err != nil {
    63  		t.Fatalf("err : %v", err)
    64  	}
    65  	if err := checksPresent(t, []string{check1.Hash(service1ID)}, cs); err != nil {
    66  		t.Fatalf("err : %v", err)
    67  	}
    68  }
    69  
    70  func TestConsulServiceUpdateService(t *testing.T) {
    71  	cs, err := NewConsulService(&ConsulConfig{}, logger)
    72  	if err != nil {
    73  		t.Fatalf("Err: %v", err)
    74  	}
    75  	// Skipping the test if consul isn't present
    76  	if !cs.consulPresent() {
    77  		return
    78  	}
    79  
    80  	task := mockTask()
    81  	cs.SetServiceIdentifier(GenerateServiceIdentifier(allocID, task.Name))
    82  	cs.SetAddrFinder(task.FindHostAndPortFor)
    83  	if err := cs.SyncServices(task.Services); err != nil {
    84  		t.Fatalf("err: %v", err)
    85  	}
    86  	defer cs.Shutdown()
    87  
    88  	//Update Service defn 1
    89  	newTags := []string{"tag3"}
    90  	task.Services[0].Tags = newTags
    91  	if err := cs.SyncServices(task.Services); err != nil {
    92  		t.Fatalf("err: %v", err)
    93  	}
    94  	// Make sure all the services and checks are still present
    95  	service1ID := service1.ID(GenerateServiceIdentifier(allocID, task.Name))
    96  	service2ID := service2.ID(GenerateServiceIdentifier(allocID, task.Name))
    97  	if err := servicesPresent(t, []string{service1ID, service2ID}, cs); err != nil {
    98  		t.Fatalf("err : %v", err)
    99  	}
   100  	if err := checksPresent(t, []string{check1.Hash(service1ID)}, cs); err != nil {
   101  		t.Fatalf("err : %v", err)
   102  	}
   103  
   104  	// check if service defn 1 has been updated
   105  	services, err := cs.client.Agent().Services()
   106  	if err != nil {
   107  		t.Fatalf("errL: %v", err)
   108  	}
   109  	srv, _ := services[service1ID]
   110  	if !reflect.DeepEqual(srv.Tags, newTags) {
   111  		t.Fatalf("expected tags: %v, actual: %v", newTags, srv.Tags)
   112  	}
   113  }
   114  
   115  func servicesPresent(t *testing.T, serviceIDs []string, consulService *ConsulService) error {
   116  	var mErr multierror.Error
   117  	services, err := consulService.client.Agent().Services()
   118  	if err != nil {
   119  		t.Fatalf("err: %v", err)
   120  	}
   121  
   122  	for _, serviceID := range serviceIDs {
   123  		if _, ok := services[serviceID]; !ok {
   124  			mErr.Errors = append(mErr.Errors, fmt.Errorf("service ID %q not synced", serviceID))
   125  		}
   126  	}
   127  	return mErr.ErrorOrNil()
   128  }
   129  
   130  func checksPresent(t *testing.T, checkIDs []string, consulService *ConsulService) error {
   131  	var mErr multierror.Error
   132  	checks, err := consulService.client.Agent().Checks()
   133  	if err != nil {
   134  		t.Fatalf("err: %v", err)
   135  	}
   136  
   137  	for _, checkID := range checkIDs {
   138  		if _, ok := checks[checkID]; !ok {
   139  			mErr.Errors = append(mErr.Errors, fmt.Errorf("check ID %q not synced", checkID))
   140  		}
   141  	}
   142  	return mErr.ErrorOrNil()
   143  }
   144  
   145  func mockTask() *structs.Task {
   146  	task := structs.Task{
   147  		Name:     "foo",
   148  		Services: []*structs.Service{&service1, &service2},
   149  		Resources: &structs.Resources{
   150  			Networks: []*structs.NetworkResource{
   151  				&structs.NetworkResource{
   152  					IP: "10.10.11.5",
   153  					DynamicPorts: []structs.Port{
   154  						structs.Port{
   155  							Label: "port1",
   156  							Value: 20002,
   157  						},
   158  						structs.Port{
   159  							Label: "port2",
   160  							Value: 20003,
   161  						},
   162  					},
   163  				},
   164  			},
   165  		},
   166  	}
   167  	return &task
   168  }