Class: Puppet::HTTP::DNS
Defined Under Namespace
Classes: CacheEntry
Instance Method Summary collapse
-
#each_srv_record(domain, service_name = :puppet, &block) ⇒ Object
Iterate through the list of records for this service and yield each server and port pair.
-
#expired?(service_name) ⇒ Boolean
Checks if the cached entry for the given service has expired.
-
#find_weighted_server(records) ⇒ Resolv::DNS::Resource::IN:SRV
Given a list of records of the same priority, chooses a random one from among them, favoring those with higher weights.
-
#initialize(resolver = Resolv::DNS.new) ⇒ DNS
constructor
A new instance of DNS.
-
#ttl(service_name) ⇒ Integer
Returns TTL for the cached records for this service.
- #weight(record) ⇒ Object
Constructor Details
#initialize(resolver = Resolv::DNS.new) ⇒ DNS
Returns a new instance of DNS.
27 28 29 30 31 32 33 34 |
# File 'lib/puppet/http/dns.rb', line 27 def initialize(resolver = Resolv::DNS.new) @resolver = resolver # Stores DNS records per service, along with their TTL # and the time at which they were resolved, for cache # eviction. @record_cache = {} end |
Instance Method Details
#each_srv_record(domain, service_name = :puppet, &block) ⇒ Object
Iterate through the list of records for this service and yield each server and port pair. Records are only fetched via DNS query the first time and cached for the duration of their service’s TTL thereafter.
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 79 80 81 |
# File 'lib/puppet/http/dns.rb', line 43 def each_srv_record(domain, service_name = :puppet, &block) if domain.nil? or domain.empty? Puppet.debug "Domain not known; skipping SRV lookup" return end Puppet.debug "Searching for SRV records for domain: #{domain}" case service_name when :puppet then service = '_x-puppet' when :file then service = '_x-puppet-fileserver' else service = "_x-puppet-#{service_name}" end record_name = "#{service}._tcp.#{domain}" if @record_cache.has_key?(service_name) && !expired?(service_name) records = @record_cache[service_name].records Puppet.debug "Using cached record for #{record_name}" else records = @resolver.getresources(record_name, Resolv::DNS::Resource::IN::SRV) if records.size > 0 @record_cache[service_name] = CacheEntry.new(records) end Puppet.debug "Found #{records.size} SRV records for: #{record_name}" end if records.size == 0 && service_name != :puppet # Try the generic :puppet service if no SRV records were found # for the specific service. each_srv_record(domain, :puppet, &block) else each_priority(records) do |recs| while next_rr = recs.delete(find_weighted_server(recs)) # rubocop:disable Lint/AssignmentInCondition Puppet.debug "Yielding next server of #{next_rr.target}:#{next_rr.port}" yield next_rr.target.to_s, next_rr.port end end end end |
#expired?(service_name) ⇒ Boolean
Checks if the cached entry for the given service has expired.
128 129 130 131 132 133 134 135 |
# File 'lib/puppet/http/dns.rb', line 128 def expired?(service_name) entry = @record_cache[service_name] if entry Time.now > (entry.resolution_time + entry.ttl) else true end end |
#find_weighted_server(records) ⇒ Resolv::DNS::Resource::IN:SRV
Given a list of records of the same priority, chooses a random one from among them, favoring those with higher weights.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/puppet/http/dns.rb', line 88 def find_weighted_server(records) return nil if records.nil? || records.empty? return records.first if records.size == 1 # Calculate the sum of all weights in the list of resource records, # This is used to then select hosts until the weight exceeds what # random number we selected. For example, if we have weights of 1 8 and 3: # # |-|--------|---| # ^ # We generate a random number 5, and iterate through the records, adding # the current record's weight to the accumulator until the weight of the # current record plus previous records is greater than the random number. total_weight = records.inject(0) { |sum, record| sum + weight(record) } current_weight = 0 chosen_weight = 1 + Kernel.rand(total_weight) records.each do |record| current_weight += weight(record) return record if current_weight >= chosen_weight end end |
#ttl(service_name) ⇒ Integer
Returns TTL for the cached records for this service.
120 121 122 |
# File 'lib/puppet/http/dns.rb', line 120 def ttl(service_name) @record_cache[service_name].ttl end |
#weight(record) ⇒ Object
113 114 115 |
# File 'lib/puppet/http/dns.rb', line 113 def weight(record) record.weight == 0 ? 1 : record.weight * 10 end |