record_store 5.5.3 → 5.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +1027 -0
- data/.rubocop.yml +19 -0
- data/.travis.yml +1 -0
- data/bin/console +2 -2
- data/bin/record-store +1 -1
- data/bin/rubocop +29 -0
- data/dev.yml +4 -0
- data/lib/record_store.rb +4 -1
- data/lib/record_store/changeset.rb +8 -4
- data/lib/record_store/cli.rb +50 -48
- data/lib/record_store/provider.rb +11 -13
- data/lib/record_store/provider/dnsimple.rb +1 -2
- data/lib/record_store/provider/dynect.rb +6 -6
- data/lib/record_store/provider/google_cloud_dns.rb +5 -6
- data/lib/record_store/provider/ns1.rb +13 -9
- data/lib/record_store/provider/ns1/client.rb +3 -4
- data/lib/record_store/record.rb +27 -9
- data/lib/record_store/record/a.rb +4 -6
- data/lib/record_store/record/aaaa.rb +4 -6
- data/lib/record_store/record/alias.rb +5 -1
- data/lib/record_store/record/caa.rb +7 -3
- data/lib/record_store/record/cname.rb +5 -1
- data/lib/record_store/record/mx.rb +11 -3
- data/lib/record_store/record/ns.rb +5 -1
- data/lib/record_store/record/srv.rb +20 -4
- data/lib/record_store/record/txt.rb +1 -1
- data/lib/record_store/version.rb +1 -1
- data/lib/record_store/zone.rb +22 -16
- data/lib/record_store/zone/config.rb +1 -1
- data/lib/record_store/zone/yaml_definitions.rb +3 -2
- data/record_store.gemspec +4 -3
- data/template/bin/record-store +1 -1
- metadata +19 -2
|
@@ -3,7 +3,7 @@ require 'google/cloud/dns'
|
|
|
3
3
|
module RecordStore
|
|
4
4
|
class Provider::GoogleCloudDNS < Provider
|
|
5
5
|
class << self
|
|
6
|
-
def apply_changeset(changeset,
|
|
6
|
+
def apply_changeset(changeset, _stdout = nil)
|
|
7
7
|
zone = session.zone(convert_to_name(changeset.zone))
|
|
8
8
|
|
|
9
9
|
deletions = convert_records_to_gcloud_record_sets(zone, changeset.current_records)
|
|
@@ -45,10 +45,10 @@ module RecordStore
|
|
|
45
45
|
|
|
46
46
|
def session
|
|
47
47
|
@dns ||= begin
|
|
48
|
-
Google::Cloud::Dns.new(
|
|
48
|
+
Google::Cloud::Dns.new(
|
|
49
49
|
project_id: secrets.fetch('project_id'),
|
|
50
50
|
credentials: Google::Cloud::Dns::Credentials.new(secrets),
|
|
51
|
-
|
|
51
|
+
)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
@@ -72,9 +72,8 @@ module RecordStore
|
|
|
72
72
|
[record.type, record.fqdn]
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
|
|
76
75
|
record_sets.map do |(rr_type, rr_fqdn), records_for_set|
|
|
77
|
-
zone.record(rr_fqdn, rr_type, records_for_set[0].ttl, records_for_set.map(&:rdata_txt))
|
|
76
|
+
zone.record(rr_fqdn, rr_type, records_for_set[0].ttl, Record.long_quote(records_for_set.map(&:rdata_txt)))
|
|
78
77
|
end
|
|
79
78
|
end
|
|
80
79
|
|
|
@@ -109,7 +108,7 @@ module RecordStore
|
|
|
109
108
|
when 'NS'
|
|
110
109
|
record_params.merge!(nsdname: record.data[0])
|
|
111
110
|
when 'SPF', 'TXT'
|
|
112
|
-
txtdata = Record.
|
|
111
|
+
txtdata = Record.unlong_quote(record.data[0]).gsub(';', '\;')
|
|
113
112
|
record_params.merge!(txtdata: txtdata)
|
|
114
113
|
when 'SRV'
|
|
115
114
|
priority, weight, port, target = record.data[0].split(' ')
|
|
@@ -12,7 +12,7 @@ module RecordStore
|
|
|
12
12
|
# Downloads all the records from the provider.
|
|
13
13
|
#
|
|
14
14
|
# Returns: an array of `Record` for each record in the provider's zone
|
|
15
|
-
def retrieve_current_records(zone:, stdout: $stdout)
|
|
15
|
+
def retrieve_current_records(zone:, stdout: $stdout) # rubocop:disable Lint/UnusedMethodArgument
|
|
16
16
|
full_api_records = records_for_zone(zone).map do |short_record|
|
|
17
17
|
client.record(
|
|
18
18
|
zone: zone,
|
|
@@ -22,7 +22,7 @@ module RecordStore
|
|
|
22
22
|
)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
full_api_records.map { |r| build_from_api(r
|
|
25
|
+
full_api_records.map { |r| build_from_api(r) }.flatten.compact
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
# Returns an array of the zones managed by provider as strings
|
|
@@ -129,7 +129,11 @@ module RecordStore
|
|
|
129
129
|
answer["answer"] = build_api_answer_from_record(record)
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
unless updated
|
|
133
|
+
error = +'while trying to update a record, could not find answer with fqdn: '
|
|
134
|
+
error << "#{record.fqdn}, type; #{record.type}, id: #{id}"
|
|
135
|
+
raise Error, error
|
|
136
|
+
end
|
|
133
137
|
|
|
134
138
|
client.modify_record(
|
|
135
139
|
zone: zone,
|
|
@@ -139,7 +143,7 @@ module RecordStore
|
|
|
139
143
|
)
|
|
140
144
|
end
|
|
141
145
|
|
|
142
|
-
def build_from_api(api_record
|
|
146
|
+
def build_from_api(api_record)
|
|
143
147
|
fqdn = Record.ensure_ends_with_dot(api_record["domain"])
|
|
144
148
|
|
|
145
149
|
record_type = api_record["type"]
|
|
@@ -150,7 +154,7 @@ module RecordStore
|
|
|
150
154
|
record = {
|
|
151
155
|
ttl: api_record["ttl"],
|
|
152
156
|
fqdn: fqdn.downcase,
|
|
153
|
-
record_id: api_answer["id"]
|
|
157
|
+
record_id: api_answer["id"],
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
case record_type
|
|
@@ -179,7 +183,7 @@ module RecordStore
|
|
|
179
183
|
when 'NS'
|
|
180
184
|
record.merge!(nsdname: answer.first)
|
|
181
185
|
when 'SPF', 'TXT'
|
|
182
|
-
record.merge!(txtdata: Record.unescape(answer.first).gsub(';', '\;'))
|
|
186
|
+
record.merge!(txtdata: Record.unlong_quote(Record.unescape(answer.first).gsub(';', '\;')))
|
|
183
187
|
when 'SRV'
|
|
184
188
|
priority, weight, port, host = answer
|
|
185
189
|
|
|
@@ -197,8 +201,8 @@ module RecordStore
|
|
|
197
201
|
def build_api_answer_from_record(record)
|
|
198
202
|
if record.is_a?(Record::MX)
|
|
199
203
|
[record.preference, record.exchange]
|
|
200
|
-
elsif record.is_a?(Record::TXT)
|
|
201
|
-
[record.txtdata]
|
|
204
|
+
elsif record.is_a?(Record::TXT) || record.is_a?(Record::SPF)
|
|
205
|
+
[Record.long_quote(record.txtdata)]
|
|
202
206
|
elsif record.is_a?(Record::CAA)
|
|
203
207
|
[record.flags, record.tag, record.value]
|
|
204
208
|
elsif record.is_a?(Record::SRV)
|
|
@@ -209,7 +213,7 @@ module RecordStore
|
|
|
209
213
|
end
|
|
210
214
|
|
|
211
215
|
def symbolize_keys(hash)
|
|
212
|
-
hash.map{ |key, value| [key.to_sym, value] }.to_h
|
|
216
|
+
hash.map { |key, value| [key.to_sym, value] }.to_h
|
|
213
217
|
end
|
|
214
218
|
|
|
215
219
|
def secrets
|
|
@@ -26,22 +26,21 @@ module RecordStore
|
|
|
26
26
|
|
|
27
27
|
def create_record(zone:, fqdn:, type:, params:)
|
|
28
28
|
result = super(zone, fqdn, type, params)
|
|
29
|
-
raise(Error, result.to_s) if result.is_a?
|
|
29
|
+
raise(Error, result.to_s) if result.is_a?(NS1::Response::Error)
|
|
30
30
|
nil
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def modify_record(zone:, fqdn:, type:, params:)
|
|
34
34
|
result = super(zone, fqdn, type, params)
|
|
35
|
-
raise(Error, result.to_s) if result.is_a?
|
|
35
|
+
raise(Error, result.to_s) if result.is_a?(NS1::Response::Error)
|
|
36
36
|
nil
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def delete_record(zone:, fqdn:, type:)
|
|
40
40
|
result = super(zone, fqdn, type)
|
|
41
|
-
raise(Error, result.to_s) if result.is_a?
|
|
41
|
+
raise(Error, result.to_s) if result.is_a?(NS1::Response::Error)
|
|
42
42
|
nil
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
|
-
|
|
47
46
|
end
|
data/lib/record_store/record.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module RecordStore
|
|
2
2
|
class Record
|
|
3
3
|
FQDN_REGEX = /\A(\*\.)?([a-z0-9_]+(-[a-z0-9]+)*\._?)+[a-z]{2,}\.\Z/i
|
|
4
|
-
CNAME_REGEX =
|
|
4
|
+
CNAME_REGEX = /\A(\*\.)?([a-z0-9_]+((-|--)?[a-z0-9]+)*\._?)+[a-z]{2,}\.\Z/i
|
|
5
5
|
|
|
6
6
|
include ActiveModel::Validations
|
|
7
7
|
|
|
@@ -17,7 +17,21 @@ module RecordStore
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def quote(value)
|
|
20
|
-
|
|
20
|
+
result = escape(value)
|
|
21
|
+
%("#{result}")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def long_quote(value)
|
|
25
|
+
result = value
|
|
26
|
+
if needs_long_quotes?(value)
|
|
27
|
+
result = unquote(value).scan(/.{1,255}/).join('" "')
|
|
28
|
+
result = %("#{result}")
|
|
29
|
+
end
|
|
30
|
+
result
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def unlong_quote(value)
|
|
34
|
+
value.length > 255 ? value.scan(/.{1,258}/).map { |x| x.sub(/^\"/, "").sub(/\" ?$/, "") }.join : unquote(value)
|
|
21
35
|
end
|
|
22
36
|
|
|
23
37
|
def unescape(value)
|
|
@@ -27,6 +41,14 @@ module RecordStore
|
|
|
27
41
|
def unquote(value)
|
|
28
42
|
unescape(value.sub(/\A"(.*)"\z/, '\1'))
|
|
29
43
|
end
|
|
44
|
+
|
|
45
|
+
def ensure_ends_with_dot(fqdn)
|
|
46
|
+
fqdn.end_with?(".") ? fqdn : "#{fqdn}."
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def needs_long_quotes?(value)
|
|
50
|
+
value.length > 255 && value !~ /^((\\)?"((\\"|[^"])){1,255}(\\)?"\s*)+$/
|
|
51
|
+
end
|
|
30
52
|
end
|
|
31
53
|
|
|
32
54
|
def initialize(record)
|
|
@@ -40,7 +62,7 @@ module RecordStore
|
|
|
40
62
|
Record.const_get(record_type).new(yaml_definition)
|
|
41
63
|
end
|
|
42
64
|
|
|
43
|
-
def log!(logger=STDOUT)
|
|
65
|
+
def log!(logger = STDOUT)
|
|
44
66
|
logger.puts to_s
|
|
45
67
|
end
|
|
46
68
|
|
|
@@ -48,7 +70,7 @@ module RecordStore
|
|
|
48
70
|
{
|
|
49
71
|
type: type,
|
|
50
72
|
fqdn: fqdn,
|
|
51
|
-
ttl: ttl
|
|
73
|
+
ttl: ttl,
|
|
52
74
|
}.merge(rdata)
|
|
53
75
|
end
|
|
54
76
|
|
|
@@ -57,7 +79,7 @@ module RecordStore
|
|
|
57
79
|
end
|
|
58
80
|
|
|
59
81
|
def ==(other)
|
|
60
|
-
other.class == self.class && other.to_hash ==
|
|
82
|
+
other.class == self.class && other.to_hash == to_hash
|
|
61
83
|
end
|
|
62
84
|
|
|
63
85
|
alias_method :eql?, :==
|
|
@@ -93,9 +115,5 @@ module RecordStore
|
|
|
93
115
|
errors.add(:fqdn, "A label should be at most 63 characters")
|
|
94
116
|
end
|
|
95
117
|
end
|
|
96
|
-
|
|
97
|
-
def self.ensure_ends_with_dot(fqdn)
|
|
98
|
-
fqdn.end_with?(".") ? fqdn : "#{fqdn}."
|
|
99
|
-
end
|
|
100
118
|
end
|
|
101
119
|
end
|
|
@@ -21,12 +21,10 @@ module RecordStore
|
|
|
21
21
|
private
|
|
22
22
|
|
|
23
23
|
def valid_address?
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
errors.add(:address, 'is invalid')
|
|
29
|
-
end
|
|
24
|
+
ip = IPAddr.new(address)
|
|
25
|
+
errors.add(:address, 'is not an IPv4 address') unless ip.ipv4?
|
|
26
|
+
rescue IPAddr::InvalidAddressError
|
|
27
|
+
errors.add(:address, 'is invalid')
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
end
|
|
@@ -21,12 +21,10 @@ module RecordStore
|
|
|
21
21
|
private
|
|
22
22
|
|
|
23
23
|
def valid_address?
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
errors.add(:address, 'is invalid')
|
|
29
|
-
end
|
|
24
|
+
ip = IPAddr.new(address)
|
|
25
|
+
errors.add(:address, 'is not an IPv6 address') unless ip.ipv6?
|
|
26
|
+
rescue IPAddr::InvalidAddressError
|
|
27
|
+
errors.add(:address, 'is invalid')
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
end
|
|
@@ -2,7 +2,11 @@ module RecordStore
|
|
|
2
2
|
class Record::ALIAS < Record
|
|
3
3
|
attr_accessor :alias
|
|
4
4
|
|
|
5
|
-
validates :alias, presence: true, format:
|
|
5
|
+
validates :alias, presence: true, format:
|
|
6
|
+
{
|
|
7
|
+
with: Record::CNAME_REGEX,
|
|
8
|
+
message: 'is not a fully qualified domain name',
|
|
9
|
+
}
|
|
6
10
|
validate :validate_circular_reference
|
|
7
11
|
|
|
8
12
|
def initialize(record)
|
|
@@ -5,10 +5,14 @@ module RecordStore
|
|
|
5
5
|
LABEL_REGEX = '[a-z0-9](?:-*[a-z0-9])*'
|
|
6
6
|
DOMAIN_REGEX = /\A#{LABEL_REGEX}(?:\.#{LABEL_REGEX})\z/i
|
|
7
7
|
|
|
8
|
-
validates :flags,
|
|
8
|
+
validates :flags, presence: true, numericality:
|
|
9
|
+
{
|
|
10
|
+
only_integer: true, greater_than_or_equal_to: 0,
|
|
11
|
+
less_than_or_equal_to: 255
|
|
12
|
+
}
|
|
9
13
|
validates :tag, inclusion: { in: %w(issue issuewild iodef) }, presence: true
|
|
10
14
|
validate :validate_uri_value, if: :iodef?
|
|
11
|
-
validates :value, format: { with: DOMAIN_REGEX, message: 'is not a fully qualified domain name'}, unless: :iodef?
|
|
15
|
+
validates :value, format: { with: DOMAIN_REGEX, message: 'is not a fully qualified domain name' }, unless: :iodef?
|
|
12
16
|
|
|
13
17
|
def initialize(record)
|
|
14
18
|
super
|
|
@@ -37,7 +41,7 @@ module RecordStore
|
|
|
37
41
|
|
|
38
42
|
def validate_uri_value
|
|
39
43
|
uri = URI(value)
|
|
40
|
-
return if uri.
|
|
44
|
+
return if uri.is_a?(URI::MailTo) || uri.is_a?(URI::HTTP)
|
|
41
45
|
errors.add(:value, "URL scheme should be mailto, http, or https")
|
|
42
46
|
rescue URI::Error
|
|
43
47
|
errors.add(:value, "Value should be a valid URI")
|
|
@@ -2,7 +2,11 @@ module RecordStore
|
|
|
2
2
|
class Record::CNAME < Record
|
|
3
3
|
attr_accessor :cname
|
|
4
4
|
|
|
5
|
-
validates :cname, presence: true, format:
|
|
5
|
+
validates :cname, presence: true, format:
|
|
6
|
+
{
|
|
7
|
+
with: Record::CNAME_REGEX,
|
|
8
|
+
message: 'is not a fully qualified domain name',
|
|
9
|
+
}
|
|
6
10
|
validate :validate_circular_reference
|
|
7
11
|
|
|
8
12
|
def initialize(record)
|
|
@@ -2,8 +2,16 @@ module RecordStore
|
|
|
2
2
|
class Record::MX < Record
|
|
3
3
|
attr_accessor :exchange, :preference
|
|
4
4
|
|
|
5
|
-
validates :preference,
|
|
6
|
-
|
|
5
|
+
validates :preference, presence: true, numericality:
|
|
6
|
+
{
|
|
7
|
+
only_integer: true,
|
|
8
|
+
greater_than_or_equal_to: 0,
|
|
9
|
+
}
|
|
10
|
+
validates :exchange, presence: true, format:
|
|
11
|
+
{
|
|
12
|
+
with: Record::FQDN_REGEX,
|
|
13
|
+
message: 'is not a fully qualified domain name',
|
|
14
|
+
}
|
|
7
15
|
|
|
8
16
|
def initialize(record)
|
|
9
17
|
super
|
|
@@ -14,7 +22,7 @@ module RecordStore
|
|
|
14
22
|
def rdata
|
|
15
23
|
{
|
|
16
24
|
preference: preference,
|
|
17
|
-
exchange: exchange
|
|
25
|
+
exchange: exchange,
|
|
18
26
|
}
|
|
19
27
|
end
|
|
20
28
|
|
|
@@ -2,7 +2,11 @@ module RecordStore
|
|
|
2
2
|
class Record::NS < Record
|
|
3
3
|
attr_accessor :nsdname
|
|
4
4
|
|
|
5
|
-
validates :nsdname, presence: true, format:
|
|
5
|
+
validates :nsdname, presence: true, format:
|
|
6
|
+
{
|
|
7
|
+
with: Record::FQDN_REGEX,
|
|
8
|
+
message: 'is not a fully qualified domain name',
|
|
9
|
+
}
|
|
6
10
|
|
|
7
11
|
def initialize(record)
|
|
8
12
|
super
|
|
@@ -2,10 +2,26 @@ module RecordStore
|
|
|
2
2
|
class Record::SRV < Record
|
|
3
3
|
attr_accessor :priority, :port, :weight, :target
|
|
4
4
|
|
|
5
|
-
validates :priority, presence: true, numericality:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
validates :priority, presence: true, numericality:
|
|
6
|
+
{
|
|
7
|
+
only_integer: true,
|
|
8
|
+
greater_than_or_equal_to: 0,
|
|
9
|
+
}
|
|
10
|
+
validates :port, presence: true, numericality:
|
|
11
|
+
{
|
|
12
|
+
only_integer: true,
|
|
13
|
+
greater_than_or_equal_to: 0,
|
|
14
|
+
}
|
|
15
|
+
validates :weight, presence: true, numericality:
|
|
16
|
+
{
|
|
17
|
+
only_integer: true,
|
|
18
|
+
greater_than_or_equal_to: 0,
|
|
19
|
+
}
|
|
20
|
+
validates :target, presence: true, format:
|
|
21
|
+
{
|
|
22
|
+
with: Record::CNAME_REGEX,
|
|
23
|
+
message: 'is not a fully qualified domain name',
|
|
24
|
+
}
|
|
9
25
|
|
|
10
26
|
def initialize(record)
|
|
11
27
|
super
|
data/lib/record_store/version.rb
CHANGED
data/lib/record_store/zone.rb
CHANGED
|
@@ -6,7 +6,11 @@ module RecordStore
|
|
|
6
6
|
attr_accessor :name
|
|
7
7
|
attr_reader :config
|
|
8
8
|
|
|
9
|
-
validates :name, presence: true, format:
|
|
9
|
+
validates :name, presence: true, format:
|
|
10
|
+
{
|
|
11
|
+
with: Record::FQDN_REGEX,
|
|
12
|
+
message: 'is not a fully qualified domain name',
|
|
13
|
+
}
|
|
10
14
|
validate :validate_records
|
|
11
15
|
validate :validate_config
|
|
12
16
|
validate :validate_all_records_are_unique
|
|
@@ -18,14 +22,14 @@ module RecordStore
|
|
|
18
22
|
|
|
19
23
|
class << self
|
|
20
24
|
def download(name, provider_name, **write_options)
|
|
21
|
-
zone = Zone.new(name: name, config: {providers: [provider_name]})
|
|
25
|
+
zone = Zone.new(name: name, config: { providers: [provider_name] })
|
|
22
26
|
raise ArgumentError, zone.errors.full_messages.join("\n") unless zone.valid?
|
|
23
27
|
|
|
24
28
|
zone.records = zone.providers.first.retrieve_current_records(zone: name)
|
|
25
29
|
|
|
26
30
|
zone.config = Zone::Config.new(
|
|
27
31
|
providers: [provider_name],
|
|
28
|
-
ignore_patterns: [{type: "NS", fqdn: "#{name}."}],
|
|
32
|
+
ignore_patterns: [{ type: "NS", fqdn: "#{name}." }],
|
|
29
33
|
supports_alias: (zone.records.map(&:type).include?('ALIAS') || nil)
|
|
30
34
|
)
|
|
31
35
|
|
|
@@ -41,13 +45,15 @@ module RecordStore
|
|
|
41
45
|
end
|
|
42
46
|
|
|
43
47
|
MAX_PARALLEL_THREADS = 10
|
|
44
|
-
def modified(verbose: false)
|
|
45
|
-
modified_zones
|
|
48
|
+
def modified(verbose: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
49
|
+
modified_zones = []
|
|
50
|
+
mutex = Mutex.new
|
|
51
|
+
zones = all
|
|
46
52
|
|
|
47
53
|
(1..MAX_PARALLEL_THREADS).map do
|
|
48
54
|
Thread.new do
|
|
49
55
|
current_zone = nil
|
|
50
|
-
while
|
|
56
|
+
while zones.any?
|
|
51
57
|
mutex.synchronize { current_zone = zones.shift }
|
|
52
58
|
mutex.synchronize { modified_zones << current_zone } unless current_zone.unchanged?
|
|
53
59
|
end
|
|
@@ -147,15 +153,15 @@ module RecordStore
|
|
|
147
153
|
cname_records = records.select { |record| record.is_a?(Record::CNAME) }
|
|
148
154
|
cname_records.each do |cname_record|
|
|
149
155
|
records.each do |record|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
next unless record.fqdn == cname_record.fqdn && record != cname_record
|
|
157
|
+
case record.type
|
|
158
|
+
when 'SIG', 'NXT', 'KEY'
|
|
159
|
+
# this is fine
|
|
160
|
+
when 'CNAME'
|
|
161
|
+
errors.add(:records, "Multiple CNAME records are defined for #{record.fqdn}: #{record}")
|
|
162
|
+
else
|
|
163
|
+
cname_error = "A CNAME record is defined for #{cname_record.fqdn}, so this record is not allowed: #{record}"
|
|
164
|
+
errors.add(:records, cname_error)
|
|
159
165
|
end
|
|
160
166
|
end
|
|
161
167
|
end
|
|
@@ -175,7 +181,7 @@ module RecordStore
|
|
|
175
181
|
|
|
176
182
|
providers.each do |provider|
|
|
177
183
|
(record_types - provider.record_types).each do |record_type|
|
|
178
|
-
errors.add(:records, "#{record_type} is a not a supported record type in #{provider
|
|
184
|
+
errors.add(:records, "#{record_type} is a not a supported record type in #{provider}")
|
|
179
185
|
end
|
|
180
186
|
end
|
|
181
187
|
end
|