Class: RecordStore::Zone

Inherits:
Object
  • Object
show all
Extended by:
YamlDefinitions
Includes:
ActiveModel::Validations
Defined in:
lib/record_store/zone.rb,
lib/record_store/zone/config.rb,
lib/record_store/zone/yaml_definitions.rb,
lib/record_store/zone/config/ignore_pattern.rb

Defined Under Namespace

Modules: YamlDefinitions Classes: Config

Constant Summary collapse

MAX_PARALLEL_THREADS =
10
ROOT_SERVERS =
%w(
  a.root-servers.net
  b.root-servers.net
  c.root-servers.net
  d.root-servers.net
  e.root-servers.net
  f.root-servers.net
  g.root-servers.net
  h.root-servers.net
  i.root-servers.net
  j.root-servers.net
  k.root-servers.net
  l.root-servers.net
  m.root-servers.net
)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from YamlDefinitions

[], defined, each, find, reset

Constructor Details

#initialize(name:, records: [], config: {}) ⇒ Zone

Returns a new instance of Zone.



67
68
69
70
71
# File 'lib/record_store/zone.rb', line 67

def initialize(name:, records: [], config: {})
  @name = Record.ensure_ends_with_dot(name)
  @config = RecordStore::Zone::Config.new(config.deep_symbolize_keys)
  @records = build_records(records)
end

Instance Attribute Details

#configObject

Returns the value of attribute config.



7
8
9
# File 'lib/record_store/zone.rb', line 7

def config
  @config
end

#nameObject

Returns the value of attribute name.



6
7
8
# File 'lib/record_store/zone.rb', line 6

def name
  @name
end

Class Method Details

.download(name, provider_name, **write_options) ⇒ Object

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/record_store/zone.rb', line 24

def download(name, provider_name, **write_options)
  zone = Zone.new(name: name, config: { providers: [provider_name] })
  raise ArgumentError, zone.errors.full_messages.join("\n") unless zone.valid?

  zone.records = zone.providers.first.retrieve_current_records(zone: name)

  zone.config = Zone::Config.new(
    providers: [provider_name],
    ignore_patterns: [{ type: "NS", fqdn: "#{name}." }],
    supports_alias: (zone.records.map(&:type).include?('ALIAS') || nil)
  )

  zone.write(**write_options)
end

.filter_records(current_records, ignore_patterns) ⇒ Object



39
40
41
42
43
44
45
# File 'lib/record_store/zone.rb', line 39

def filter_records(current_records, ignore_patterns)
  ignore_patterns.inject(current_records) do |remaining_records, pattern|
    remaining_records.reject do |record|
      pattern.ignore?(record)
    end
  end
end

.modified(verbose: false) ⇒ Object

rubocop:disable Lint/UnusedMethodArgument



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/record_store/zone.rb', line 48

def modified(verbose: false) # rubocop:disable Lint/UnusedMethodArgument
  modified_zones = []
  mutex = Mutex.new
  zones = all

  (1..MAX_PARALLEL_THREADS).map do
    Thread.new do
      current_zone = nil
      while zones.any?
        mutex.synchronize { current_zone = zones.shift }
        mutex.synchronize { modified_zones << current_zone } unless current_zone.unchanged?
      end
    end
  end.each(&:join)

  modified_zones
end

Instance Method Details

#allObject



89
90
91
# File 'lib/record_store/zone.rb', line 89

def all
  @records
end

#build_changesets(all: false) ⇒ Object



73
74
75
76
77
78
79
# File 'lib/record_store/zone.rb', line 73

def build_changesets(all: false)
  @changesets ||= begin
    providers.map do |provider|
      Changeset.build_from(provider: provider, zone: self, all: all)
    end
  end
end

#fetch_authority(nameserver = ROOT_SERVERS.sample) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/record_store/zone.rb', line 131

def fetch_authority(nameserver = ROOT_SERVERS.sample)
  authority = fetch_soa(nameserver) do |reply, _name|
    break if reply.answer.any?

    raise "No authority found (#{name})" unless reply.authority.any?

    break extract_authority(reply.authority)
  end

  # candidate DNS name is returned instead when NXDomain or other error
  return nil if unrooted_name.casecmp?(Array(authority).first.to_s)

  authority
end

#providersObject



107
108
109
# File 'lib/record_store/zone.rb', line 107

def providers
  @providers ||= config.providers.map { |provider| Provider.const_get(provider) }
end

#recordsObject



93
94
95
# File 'lib/record_store/zone.rb', line 93

def records
  @records_cache ||= Zone.filter_records(@records, config.ignore_patterns)
end

#records=(records) ⇒ Object



97
98
99
100
# File 'lib/record_store/zone.rb', line 97

def records=(records)
  @records_cache = nil
  @records = records
end

#unchanged?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/record_store/zone.rb', line 81

def unchanged?
  build_changesets.all?(&:empty?)
end

#unrooted_nameObject



85
86
87
# File 'lib/record_store/zone.rb', line 85

def unrooted_name
  @name.chomp('.')
end

#write(**write_options) ⇒ Object



111
112
113
# File 'lib/record_store/zone.rb', line 111

def write(**write_options)
  self.class.write(name, config: config, records: records, **write_options)
end