diff --git a/catalog/aws.go b/catalog/aws.go index f43deb0..ce79c94 100644 --- a/catalog/aws.go +++ b/catalog/aws.go @@ -1,6 +1,7 @@ package catalog import ( + "context" "fmt" "strconv" "strings" @@ -9,7 +10,9 @@ import ( x "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws/awserr" + "github.com/aws/aws-sdk-go-v2/service/ecs" sd "github.com/aws/aws-sdk-go-v2/service/servicediscovery" + "github.com/hashicorp/consul-aws/subcommand" "github.com/hashicorp/go-hclog" ) @@ -29,7 +32,7 @@ type namespace struct { type aws struct { lock sync.RWMutex - client *sd.ServiceDiscovery + client *sd.Client log hclog.Logger namespace namespace services map[string]service @@ -57,6 +60,12 @@ func (a *aws) sync(consul *consul, stop, stopped chan struct{}) { consul.log.Info("created", "count", fmt.Sprintf("%d", count)) } + create = tagsNeedUpdate(a.getServices(), consul.getServices()) + count = consul.create(create) + if count > 0 { + consul.log.Info("updated", "count", fmt.Sprintf("%d", count)) + } + remove := onlyInFirst(consul.getServices(), a.getServices()) count = consul.remove(remove) if count > 0 { @@ -70,7 +79,7 @@ func (a *aws) sync(consul *consul, stop, stopped chan struct{}) { func (a *aws) fetchNamespace(id string) (*sd.Namespace, error) { req := a.client.GetNamespaceRequest(&sd.GetNamespaceInput{Id: x.String(id)}) - resp, err := req.Send() + resp, err := req.Send(context.Background()) if err != nil { return nil, err } @@ -85,9 +94,9 @@ func (a *aws) fetchServices() ([]sd.ServiceSummary, error) { Values: []string{a.namespace.id}, }}, }) - p := req.Paginate() + p := sd.NewListServicesPaginator(req) services := []sd.ServiceSummary{} - for p.Next() { + for p.Next(context.Background()) { services = append(services, p.CurrentPage().Services...) } return services, p.Err() @@ -154,6 +163,19 @@ func (a *aws) fetch() error { } s.nodes = nodes + s.tags = make(map[string]string) + for _, nodes := range s.nodes { + for _, node := range nodes { + tags, err := a.discoverTags(node.awsID, node.attributes) + if err != nil { + a.log.Error("cannot discover tags", "error", err) + } + for k, v := range tags { + s.tags[k] = v + } + } + } + healths, err := a.fetchHealths(s.awsID) if err != nil { a.log.Error("cannot fetch healths", "error", err) @@ -230,8 +252,8 @@ func (a *aws) fetchHealths(id string) (map[string]health, error) { ServiceId: &id, }) result := map[string]health{} - p := req.Paginate() - for p.Next() { + p := sd.NewGetInstancesHealthStatusPaginator(req) + for p.Next(context.Background()) { for id, health := range p.CurrentPage().Status { result[id] = statusFromAWS(health) } @@ -273,9 +295,9 @@ func (a *aws) fetchNodes(id string) ([]sd.InstanceSummary, error) { req := a.client.ListInstancesRequest(&sd.ListInstancesInput{ ServiceId: &id, }) - p := req.Paginate() + p := sd.NewListInstancesPaginator(req) nodes := []sd.InstanceSummary{} - for p.Next() { + for p.Next(context.Background()) { nodes = append(nodes, p.CurrentPage().Instances...) } return nodes, p.Err() @@ -287,7 +309,7 @@ func (a *aws) discoverNodes(name string) ([]sd.InstanceSummary, error) { NamespaceName: x.String(a.namespace.name), ServiceName: x.String(name), }) - resp, err := req.Send() + resp, err := req.Send(context.Background()) if err != nil { return nil, err } @@ -298,6 +320,37 @@ func (a *aws) discoverNodes(name string) ([]sd.InstanceSummary, error) { return nodes, nil } +func (a *aws) discoverTags(id string, attributes map[string]string) (map[string]string, error) { + tags := map[string]string{} + ecsClusterName := attributes["ECS_CLUSTER_NAME"] + ecsServiceName := attributes["ECS_SERVICE_NAME"] + ecsTaskDefinitionFamily := attributes["ECS_TASK_DEFINITION_FAMILY"] + // If this is an ECS service we look for tags in the ECS task + if ecsClusterName != "" && ecsServiceName != "" && ecsTaskDefinitionFamily != "" { + config, err := subcommand.AWSConfig() + if err != nil { + return tags, err + } + client := ecs.New(config) + input := &ecs.DescribeTasksInput{ + Cluster: &ecsClusterName, + Tasks: []string{id}, + Include: []ecs.TaskField{ecs.TaskFieldTags}, + } + req := client.DescribeTasksRequest(input) + tasks, err := req.Send(context.Background()) + if err != nil { + return tags, err + } + for _, task := range tasks.Tasks { + for _, t := range task.Tags { + tags[*t.Key] = *t.Value + } + } + } + return tags, nil +} + func (a *aws) getServices() map[string]service { a.lock.RLock() copy := a.services @@ -341,7 +394,7 @@ func (a *aws) create(services map[string]service) int { } } req := a.client.CreateServiceRequest(&input) - resp, err := req.Send() + resp, err := req.Send(context.Background()) if err != nil { if err, ok := err.(awserr.Error); ok { switch err.Code() { @@ -370,7 +423,7 @@ func (a *aws) create(services map[string]service) int { Attributes: attributes, InstanceId: &instanceID, }) - _, err := req.Send() + _, err := req.Send(context.Background()) if err != nil { a.log.Error("cannot create nodes", "error", err.Error()) } @@ -412,7 +465,7 @@ func (a *aws) remove(services map[string]service) int { ServiceId: &serviceID, InstanceId: &id, }) - _, err := req.Send() + _, err := req.Send(context.Background()) if err != nil { a.log.Error("cannot remove instance", "error", err.Error()) } @@ -434,7 +487,7 @@ func (a *aws) remove(services map[string]service) int { req := a.client.DeleteServiceRequest(&sd.DeleteServiceInput{ Id: &s.awsID, }) - _, err := req.Send() + _, err := req.Send(context.Background()) if err != nil { a.log.Error("cannot remove services", "name", k, "id", s.awsID, "error", err.Error()) } else { diff --git a/catalog/aws_test.go b/catalog/aws_test.go index dbbdd9d..e40214c 100644 --- a/catalog/aws_test.go +++ b/catalog/aws_test.go @@ -10,7 +10,7 @@ import ( ) type mSDClint struct { - sdi.ServiceDiscoveryAPI + sdi.ClientAPI } func (m *mSDClint) CreateServiceRequest(input *sd.CreateServiceRequest) (*sd.CreateServiceOutput, error) { diff --git a/catalog/consul.go b/catalog/consul.go index 16f1db2..d231842 100644 --- a/catalog/consul.go +++ b/catalog/consul.go @@ -229,11 +229,12 @@ func (c *consul) fetch(waitIndex uint64) (uint64, error) { func (c *consul) transformServices(cservices map[string][]string) map[string]service { services := make(map[string]service, len(cservices)) for k, tags := range cservices { - s := service{id: k, name: k, consulID: k} + s := service{id: k, name: k, consulID: k, tags: map[string]string{}} for _, t := range tags { if t == ConsulAWSTag { s.fromAWS = true - break + } else if parts := strings.SplitN(t, ":", 2); len(parts) == 2 { + s.tags[parts[0]] = parts[1] } } if s.fromAWS { @@ -292,7 +293,7 @@ func (c *consul) create(services map[string]service) int { for h, nodes := range s.nodes { for _, n := range nodes { wg.Add(1) - go func(ns, k, name, h string, n node) { + go func(ns, k, name, h string, n node, tags map[string]string) { defer wg.Done() id := id(k, h, n.port) meta := map[string]string{} @@ -302,10 +303,14 @@ func (c *consul) create(services map[string]service) int { meta[ConsulSourceKey] = ConsulAWSTag meta[ConsulAWSNS] = ns meta[ConsulAWSID] = n.awsID + consulTags := []string{ConsulAWSTag} + for k, v := range tags { + consulTags = append(consulTags, fmt.Sprintf("%s:%s", k, v)) + } service := api.AgentService{ ID: id, Service: name, - Tags: []string{ConsulAWSTag}, + Tags: consulTags, Address: h, Meta: meta, } @@ -326,7 +331,7 @@ func (c *consul) create(services map[string]service) int { c.setNode(k, h, n.port, n) count++ } - }(s.awsNamespace, k, name, h, n) + }(s.awsNamespace, k, name, h, n, s.tags) } } for awsID, h := range s.healths { diff --git a/catalog/consul_test.go b/catalog/consul_test.go index 63067ef..a6847e1 100644 --- a/catalog/consul_test.go +++ b/catalog/consul_test.go @@ -48,7 +48,10 @@ func TestConsulRekeyHealths(t *testing.T) { func TestConsulTransformServices(t *testing.T) { c := consul{awsPrefix: "aws_"} services := map[string][]string{"s1": {"abc"}, "aws_s2": {ConsulAWSTag}} - expected := map[string]service{"s1": {id: "s1", name: "s1", consulID: "s1"}, "s2": {id: "aws_s2", name: "s2", consulID: "aws_s2", fromAWS: true}} + expected := map[string]service{ + "s1": {id: "s1", name: "s1", consulID: "s1", tags: map[string]string{}}, + "s2": {id: "aws_s2", name: "s2", consulID: "aws_s2", fromAWS: true, tags: map[string]string{}}, + } require.Equal(t, expected, c.transformServices(services)) } diff --git a/catalog/service.go b/catalog/service.go index 65a17cd..7dee4f2 100644 --- a/catalog/service.go +++ b/catalog/service.go @@ -2,6 +2,7 @@ package catalog import ( "fmt" + "reflect" "strconv" "strings" ) @@ -24,6 +25,7 @@ type service struct { awsID string consulID string awsNamespace string + tags map[string]string } type node struct { @@ -126,3 +128,17 @@ func onlyInFirst(servicesA, servicesB map[string]service) map[string]service { } return result } + +func tagsNeedUpdate(servicesA, servicesB map[string]service) map[string]service { + result := map[string]service{} + for k, sa := range servicesA { + sb, ok := servicesB[k] + if !ok { + continue + } + if !reflect.DeepEqual(sa.tags, sb.tags) { + result[k] = sa + } + } + return onlyInFirst(result, map[string]service{}) +} diff --git a/catalog/sync.go b/catalog/sync.go index 564975d..207aa58 100644 --- a/catalog/sync.go +++ b/catalog/sync.go @@ -9,7 +9,7 @@ import ( ) // Sync aws->consul and vice versa. -func Sync(toAWS, toConsul bool, namespaceID, consulPrefix, awsPrefix, awsPullInterval string, awsDNSTTL int64, stale bool, awsClient *sd.ServiceDiscovery, consulClient *api.Client, stop, stopped chan struct{}) { +func Sync(toAWS, toConsul bool, namespaceID, consulPrefix, awsPrefix, awsPullInterval string, awsDNSTTL int64, stale bool, awsClient *sd.Client, consulClient *api.Client, stop, stopped chan struct{}) { defer close(stopped) log := hclog.Default().Named("sync") consul := consul{ diff --git a/catalog/sync_test.go b/catalog/sync_test.go index 517e7a7..19701c0 100644 --- a/catalog/sync_test.go +++ b/catalog/sync_test.go @@ -1,6 +1,7 @@ package catalog import ( + "context" "fmt" "os" "testing" @@ -142,7 +143,7 @@ func deleteServiceInConsul(c *api.Client, id string) { c.Catalog().Deregister(&api.CatalogDeregistration{Node: ConsulAWSNodeName, ServiceID: id}, nil) } -func createServiceInAWS(a *sd.ServiceDiscovery, namespaceID, name string) (string, error) { +func createServiceInAWS(a *sd.Client, namespaceID, name string) (string, error) { ttl := int64(60) input := sd.CreateServiceInput{ Name: &name, @@ -156,14 +157,14 @@ func createServiceInAWS(a *sd.ServiceDiscovery, namespaceID, name string) (strin }, } req := a.CreateServiceRequest(&input) - resp, err := req.Send() + resp, err := req.Send(context.Background()) if err != nil { return "", err } return *resp.Service.Id, nil } -func createInstanceInAWS(a *sd.ServiceDiscovery, serviceID string) error { +func createInstanceInAWS(a *sd.Client, serviceID string) error { req := a.RegisterInstanceRequest(&sd.RegisterInstanceInput{ ServiceId: &serviceID, InstanceId: &serviceID, @@ -173,21 +174,21 @@ func createInstanceInAWS(a *sd.ServiceDiscovery, serviceID string) error { "FUBAR": "BARFU", }, }) - _, err := req.Send() + _, err := req.Send(context.Background()) return err } -func deleteInstanceInAWS(a *sd.ServiceDiscovery, id string) error { +func deleteInstanceInAWS(a *sd.Client, id string) error { req := a.DeregisterInstanceRequest(&sd.DeregisterInstanceInput{ServiceId: &id, InstanceId: &id}) - _, err := req.Send() + _, err := req.Send(context.Background()) return err } -func deleteServiceInAWS(a *sd.ServiceDiscovery, id string) error { +func deleteServiceInAWS(a *sd.Client, id string) error { var err error for i := 0; i < 50; i++ { req := a.DeleteServiceRequest(&sd.DeleteServiceInput{Id: &id}) - _, err = req.Send() + _, err = req.Send(context.Background()) if err != nil { time.Sleep(100 * time.Millisecond) } else { @@ -239,7 +240,7 @@ func checkForImportedAWSService(c *api.Client, name, namespaceID, serviceID stri return fmt.Errorf("shrug") } -func checkForImportedConsulService(a *sd.ServiceDiscovery, namespaceID, name string, repeat int) error { +func checkForImportedConsulService(a *sd.Client, namespaceID, name string, repeat int) error { for i := 0; i < repeat; i++ { req := a.ListServicesRequest(&sd.ListServicesInput{ Filters: []sd.ServiceFilter{{ @@ -248,8 +249,8 @@ func checkForImportedConsulService(a *sd.ServiceDiscovery, namespaceID, name str Values: []string{namespaceID}, }}, }) - p := req.Paginate() - for p.Next() { + p := sd.NewListServicesPaginator(req) + for p.Next(context.Background()) { for _, s := range p.CurrentPage().Services { if *s.Name == name { if !(s.Description != nil || *s.Description == awsServiceDescription) { @@ -260,7 +261,7 @@ func checkForImportedConsulService(a *sd.ServiceDiscovery, namespaceID, name str ireq := a.ListInstancesRequest(&sd.ListInstancesInput{ ServiceId: s.Id, }) - out, err := ireq.Send() + out, err := ireq.Send(context.Background()) if err != nil { continue } diff --git a/go.mod b/go.mod index 99e90e1..4d659c0 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/hashicorp/consul-aws require ( github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 // indirect github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect - github.com/aws/aws-sdk-go-v2 v0.6.0 + github.com/aws/aws-sdk-go-v2 v0.11.0 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect github.com/circonus-labs/circonus-gometrics v2.2.4+incompatible // indirect github.com/circonus-labs/circonusllhist v0.1.2 // indirect @@ -18,7 +18,6 @@ require ( github.com/hashicorp/memberlist v0.1.0 // indirect github.com/hashicorp/serf v0.8.1 // indirect github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect - github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/kr/pretty v0.1.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/miekg/dns v1.0.15 // indirect @@ -39,4 +38,8 @@ require ( google.golang.org/appengine v1.3.0 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/vmihailenco/msgpack.v2 v2.9.1 // indirect + labix.org/v2/mgo v0.0.0-20140701140051-000000000287 // indirect + launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect ) + +go 1.13 diff --git a/go.sum b/go.sum index e6ddc85..bac88e3 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,28 @@ +github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 h1:dmc/C8bpE5VkQn65PNbbyACDC8xw8Hpp/NEurdPmQDQ= github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v0.6.0 h1:vIMDY9xzK+3lNyIQeS++URcvmDFI6reOalHhyjEb7W8= -github.com/aws/aws-sdk-go-v2 v0.6.0/go.mod h1:Vb00pBiW2/e1Vi9eSv8ybD7uGD/S9+lLPMlpNoIFLgs= +github.com/aws/aws-sdk-go-v2 v0.11.0 h1:TMUl791B9lF/R8t3msh7id+mHxOXrQY6DAqLNEpre8w= +github.com/aws/aws-sdk-go-v2 v0.11.0/go.mod h1:cpXCmy3BB+lqwGweJjdawczHW3a+g8QgcFHcoOVoHao= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/circonus-labs/circonus-gometrics v2.2.4+incompatible h1:+ZwGzyJGsOwSxIEDDOXzPagR167tQak/1P5wBwH+/dM= github.com/circonus-labs/circonus-gometrics v2.2.4+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.2 h1:2jOJkxiDVNGbCtrwQwkZSvuguRLm3dZW2G2TyNltVN8= github.com/circonus-labs/circonusllhist v0.1.2/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gucumber/gucumber v0.0.0-20180127021336-7d5c79e832a2/go.mod h1:YbdHRK9ViqwGMS0rtRY+1I6faHvVyyurKPIPwifihxI= github.com/hashicorp/consul v1.4.0 h1:PQTW4xCuAExEiSbhrsFsikzbW5gVBoi74BjUvYFyKHw= github.com/hashicorp/consul v1.4.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= @@ -28,24 +31,31 @@ github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6K github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f h1:Yv9YzBlAETjy6AOX9eLBZ3nshNVRREgerT/3nvxlGho= github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c h1:BTAbnbegUIMB6xmQCwWE8yRzbA4XSpnZY5hvRJC188I= github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.5.0 h1:aVN0FYnPwAgZI/hVzqwfMiM86ttcHTlQKbBVeVmXPIs= github.com/hashicorp/go-retryablehttp v0.5.0/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:VBj0QYQ0u2MCJzBfeYXGexnAl17GsH1yidnoxCqqD9E= github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg= +github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 h1:7YOlAIO2YWnJZkQp7B5eFykaIY7C9JndqAFQyVV5BhM= github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/memberlist v0.1.0 h1:qSsCiC0WYD39lbSitKNt40e30uorm2Ss/d4JGU1hzH8= github.com/hashicorp/memberlist v0.1.0/go.mod h1:ncdBp14cuox2iFOq3kDiquKU6fqsTBc3W6JvZwjxxsE= github.com/hashicorp/serf v0.8.1 h1:mYs6SMzu72+90OcPa5wr3nfznA4Dw9UyR791ZFNOIf4= github.com/hashicorp/serf v0.8.1/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -54,42 +64,59 @@ github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRU github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.15 h1:9+UupePBQCG6zf1q/bGmTO1vumoG13jsrbWOSX1W6Tw= github.com/miekg/dns v1.0.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20181120120127-aeab699e26f4 h1:JN8iUqOgmRYninFWhPhdVhcxlJez35ZKpjibROwPiNA= github.com/prometheus/common v0.0.0-20181120120127-aeab699e26f4/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= -github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869 h1:kkXA53yGe04D0adEYJwEVQjeBppL01Exg+fnMjfUraU= golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc h1:MeuS1UDyZyFH++6vVy44PuufTeFF0d0nfI6XB87YGSk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/vmihailenco/msgpack.v2 v2.9.1 h1:kb0VV7NuIojvRfzwslQeP3yArBqJHW9tOl4t38VS1jM= gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8= +labix.org/v2/mgo v0.0.0-20140701140051-000000000287 h1:L0cnkNl4TfAXzvdrqsYEmxOHOCv2p5I3taaReO8BWFs= +labix.org/v2/mgo v0.0.0-20140701140051-000000000287/go.mod h1:Lg7AYkt1uXJoR9oeSZ3W/8IXLdvOfIITgZnommstyz4= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=