Class: ConsulSyncer

Inherits:
Object
  • Object
show all
Defined in:
lib/consul_syncer.rb,
lib/consul_syncer/version.rb,
lib/consul_syncer/wrapper.rb,
lib/consul_syncer/endpoint.rb

Overview

  • parses json responses

  • fails with descriptive output when a request fails

Defined Under Namespace

Classes: Endpoint, Wrapper

Constant Summary collapse

VERSION =
"0.6.0"

Instance Method Summary collapse

Constructor Details

#initialize(url, logger: Logger.new(STDOUT), params: {}) ⇒ ConsulSyncer

Returns a new instance of ConsulSyncer.



12
13
14
15
# File 'lib/consul_syncer.rb', line 12

def initialize(url, logger: Logger.new(STDOUT), params: {})
  @logger = logger
  @consul = Wrapper.new(Faraday.new(url), params: params, logger: @logger)
end

Instance Method Details

#sync(expected_definitions, tags) ⇒ Object

changing tags means all previous services need to be removed manually since they can no longer be found

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/consul_syncer.rb', line 19

def sync(expected_definitions, tags)
  raise ArgumentError, "Need at least 1 tag to reliably update endpoints" if tags.empty?

  modified = 0

  # ensure consistent tags to find the endpoints after adding
  expected_definitions = expected_definitions.dup
  expected_definitions.each do |d|
    d[:tags] += tags
    d[:tags].sort!
  end

  actual_definitions = consul_endpoints(tags).map do |consul_endpoint|
    {
      node: consul_endpoint.node,
      address: consul_endpoint.ip,
      service: consul_endpoint.name,
      service_id: consul_endpoint.service_id,
      service_address: consul_endpoint.service_address,
      tags: consul_endpoint.tags.sort,
      port: consul_endpoint.port
    }
  end

  identifying = [:node, :service_id]
  interesting = [*identifying, :service, :service_address, :address, :tags, :port]

  expected_definitions.each do |expected|
    description = "#{expected[:service] || "*"} / #{expected[:service_id] || "*"} on #{expected.fetch(:node)} in Consul"

    if expected[:keep]
      keep_identifying = identifying.dup
      keep_identifying.delete(:service_id) unless expected[:service_id]
      if remove_matching_service!(actual_definitions, expected, keep_identifying)
        @logger.warn "Kept #{description}"
      else
        @logger.error "Unable to keep #{description} since it was not found"
      end
    elsif remove_matching_service!(actual_definitions, expected, interesting)
      @logger.debug "Found #{description}"
    elsif remove_matching_service!(actual_definitions, expected, identifying)
      @logger.info "Updating #{description}"
      modified += 1
      register expected
    else
      @logger.info "Adding #{description}"
      modified += 1
      register expected
    end
  end

  # all definitions that are left did not match any expected definitions and are no longer needed
  actual_definitions.each do |actual|
    @logger.info "Removing #{actual.fetch(:service)} / #{actual.fetch(:service_id)} on #{actual.fetch(:node)} in Consul"
    modified += 1
    deregister actual.fetch(:node), actual.fetch(:service_id)
  end

  modified
end