zonesync 0.14.2 → 0.14.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/README.md +16 -0
- data/lib/zonesync/provider.rb +7 -0
- data/lib/zonesync/record.rb +5 -10
- data/lib/zonesync/route53.rb +76 -32
- data/lib/zonesync/sync.rb +4 -3
- data/lib/zonesync/validator.rb +9 -0
- data/lib/zonesync/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 413d039b491283ed46fa0b03a08a5bbd8c02489798850119b27372f8017ea30e
|
|
4
|
+
data.tar.gz: 2ffb50fce0dc89cbf955d5528e280a167b5170bc994d17ed7d02495a9b53e337
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '09fe6fd394d6ae175c9c0a5325206b3fc0c5fef6523fb8802a14d6e4b90d95d5282fb58de35bc6fceac4642df87021ac352b50368a2308fc0db8c7b0e190f350'
|
|
7
|
+
data.tar.gz: 1cb14bf843af73c34dd1c49205438e2e62e4d8e5f810932ff410dce2e5d7ab36768ef2c429852ce7f1b858958ab958839db0a0cdabc4bb707d54ceae1f3ff02b
|
data/README.md
CHANGED
|
@@ -110,6 +110,22 @@ Zonesync.call(source: "Zonefile", destination: "zonesync", dry_run: true)
|
|
|
110
110
|
Zonesync.generate(source: "zonesync", destination: "Zonefile")
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
### Cloudflare proxy status
|
|
114
|
+
|
|
115
|
+
When using the Cloudflare provider, you can control whether a record is proxied through Cloudflare's CDN by adding a `cf_tags` comment to the record in your zone file:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
www IN A 192.0.2.1 ; cf_tags=cf-proxied:true
|
|
119
|
+
mail IN A 192.0.2.2 ; cf_tags=cf-proxied:false
|
|
120
|
+
api IN A 192.0.2.3
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- `cf_tags=cf-proxied:true` — enable Cloudflare proxy (orange cloud)
|
|
124
|
+
- `cf_tags=cf-proxied:false` — explicitly disable proxy (grey cloud)
|
|
125
|
+
- No `cf_tags` — don't touch the proxied setting (use Cloudflare's default)
|
|
126
|
+
|
|
127
|
+
When generating a zone file with `zonesync generate`, proxied records will automatically include the `cf_tags=cf-proxied:true` tag in their comments.
|
|
128
|
+
|
|
113
129
|
### Managing or avoiding conflicts with other people making edits to the DNS records
|
|
114
130
|
|
|
115
131
|
Zonesync writes two additional TXT records: `zonesync_manifest` and `zonesync_checksum`. These two records together try to handle the situation where someone else makes edits directly to the DNS records managed by zonesync.
|
data/lib/zonesync/provider.rb
CHANGED
data/lib/zonesync/record.rb
CHANGED
|
@@ -53,17 +53,12 @@ module Zonesync
|
|
|
53
53
|
|
|
54
54
|
def conflicts_with?(other)
|
|
55
55
|
return false unless name == other.name && type == other.type
|
|
56
|
+
Record.single_record_per_name?(type)
|
|
57
|
+
end
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
when "MX"
|
|
61
|
-
existing_priority = rdata.split(' ').first
|
|
62
|
-
new_priority = other.rdata.split(' ').first
|
|
63
|
-
existing_priority == new_priority
|
|
64
|
-
else
|
|
65
|
-
false
|
|
66
|
-
end
|
|
59
|
+
# A CNAME cannot coexist with any other data at its owner name.
|
|
60
|
+
def excludes?(other)
|
|
61
|
+
name == other.name && type != other.type && [type, other.type].include?("CNAME")
|
|
67
62
|
end
|
|
68
63
|
|
|
69
64
|
def self.single_record_per_name?(type)
|
data/lib/zonesync/route53.rb
CHANGED
|
@@ -33,46 +33,35 @@ module Zonesync
|
|
|
33
33
|
*(remaining_records.any? ? [[remaining_records, "CREATE"]] : [])
|
|
34
34
|
]
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
38
|
-
<ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2013-04-01/">
|
|
39
|
-
<ChangeBatch>
|
|
40
|
-
<Changes>
|
|
41
|
-
<%- grouped.each do |records_list, action| -%>
|
|
42
|
-
<%- records_grouped = records_list.group_by { |r| [r.name, r.type, r.ttl] } -%>
|
|
43
|
-
<%- records_grouped.each do |(name, type, ttl), group_records| -%>
|
|
44
|
-
<Change>
|
|
45
|
-
<Action><%= action %></Action>
|
|
46
|
-
<ResourceRecordSet>
|
|
47
|
-
<Name><%= name %></Name>
|
|
48
|
-
<Type><%= type %></Type>
|
|
49
|
-
<TTL><%= ttl %></TTL>
|
|
50
|
-
<ResourceRecords>
|
|
51
|
-
<%- group_records.each do |group_record| -%>
|
|
52
|
-
<ResourceRecord>
|
|
53
|
-
<Value><%= rdata_for_api(group_record) %></Value>
|
|
54
|
-
</ResourceRecord>
|
|
55
|
-
<%- end -%>
|
|
56
|
-
</ResourceRecords>
|
|
57
|
-
</ResourceRecordSet>
|
|
58
|
-
</Change>
|
|
59
|
-
<%- end -%>
|
|
60
|
-
<%- end -%>
|
|
61
|
-
</Changes>
|
|
62
|
-
</ChangeBatch>
|
|
63
|
-
</ChangeResourceRecordSetsRequest>
|
|
64
|
-
XML
|
|
36
|
+
post_changes(grouped)
|
|
65
37
|
|
|
66
38
|
invalidate_cache!
|
|
67
39
|
end
|
|
68
40
|
end
|
|
69
41
|
|
|
42
|
+
def apply(operations, &block)
|
|
43
|
+
names = type_change_names(operations)
|
|
44
|
+
batched, rest = operations.partition do |method, (record)|
|
|
45
|
+
method != :change && names.include?(record.name)
|
|
46
|
+
end
|
|
47
|
+
batched.group_by { |_, (record)| record.name }.each do |name, ops|
|
|
48
|
+
ops.each(&block)
|
|
49
|
+
replace_at_name(name, ops)
|
|
50
|
+
end
|
|
51
|
+
super(rest, &block)
|
|
52
|
+
end
|
|
53
|
+
|
|
70
54
|
def change(old_record, new_record)
|
|
71
|
-
|
|
72
|
-
|
|
55
|
+
new_set = if old_record.manifest? || old_record.checksum?
|
|
56
|
+
# our metadata records are singletons, always replace
|
|
57
|
+
[new_record]
|
|
58
|
+
else
|
|
59
|
+
existing_records = records.select do |r|
|
|
60
|
+
r.name == old_record.name && r.type == old_record.type
|
|
61
|
+
end
|
|
62
|
+
(existing_records.reject { |r| r.identical_to?(old_record) } + [new_record]).uniq
|
|
73
63
|
end
|
|
74
64
|
|
|
75
|
-
new_set = (existing_records.reject { |r| r == old_record } + [new_record]).uniq
|
|
76
65
|
change_records("UPSERT", new_set)
|
|
77
66
|
invalidate_cache!
|
|
78
67
|
end
|
|
@@ -106,6 +95,61 @@ module Zonesync
|
|
|
106
95
|
@zonefile = nil
|
|
107
96
|
end
|
|
108
97
|
|
|
98
|
+
def type_change_names(operations)
|
|
99
|
+
removed = operations.filter_map { |method, (record)| record if method == :remove }
|
|
100
|
+
added = operations.filter_map { |method, (record)| record if method == :add }
|
|
101
|
+
added.select { |a| removed.any? { |r| r.excludes?(a) } }.map(&:name).uniq
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def replace_at_name(name, ops)
|
|
105
|
+
removed = ops.filter_map { |method, (record)| record if method == :remove }
|
|
106
|
+
added = ops.filter_map { |method, (record)| record if method == :add }
|
|
107
|
+
|
|
108
|
+
deletes, creates = [], []
|
|
109
|
+
(removed + added).map(&:type).uniq.each do |type|
|
|
110
|
+
before = records.select { |r| r.name == name && r.type == type }
|
|
111
|
+
after = before.reject { |r| removed.any? { |x| x.identical_to?(r) } }
|
|
112
|
+
after += added.select { |r| r.type == type && after.none? { |x| x.identical_to?(r) } }
|
|
113
|
+
deletes.concat(before)
|
|
114
|
+
creates.concat(after)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
post_changes([[deletes, "DELETE"], [creates, "CREATE"]])
|
|
118
|
+
invalidate_cache!
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def post_changes(grouped)
|
|
122
|
+
http.post("", ERB.new(<<~XML, trim_mode: "-").result(binding))
|
|
123
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
124
|
+
<ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2013-04-01/">
|
|
125
|
+
<ChangeBatch>
|
|
126
|
+
<Changes>
|
|
127
|
+
<%- grouped.each do |records_list, action| -%>
|
|
128
|
+
<%- records_grouped = records_list.group_by { |r| [r.name, r.type, r.ttl] } -%>
|
|
129
|
+
<%- records_grouped.each do |(name, type, ttl), group_records| -%>
|
|
130
|
+
<Change>
|
|
131
|
+
<Action><%= action %></Action>
|
|
132
|
+
<ResourceRecordSet>
|
|
133
|
+
<Name><%= name %></Name>
|
|
134
|
+
<Type><%= type %></Type>
|
|
135
|
+
<TTL><%= ttl %></TTL>
|
|
136
|
+
<ResourceRecords>
|
|
137
|
+
<%- group_records.each do |group_record| -%>
|
|
138
|
+
<ResourceRecord>
|
|
139
|
+
<Value><%= rdata_for_api(group_record) %></Value>
|
|
140
|
+
</ResourceRecord>
|
|
141
|
+
<%- end -%>
|
|
142
|
+
</ResourceRecords>
|
|
143
|
+
</ResourceRecordSet>
|
|
144
|
+
</Change>
|
|
145
|
+
<%- end -%>
|
|
146
|
+
<%- end -%>
|
|
147
|
+
</Changes>
|
|
148
|
+
</ChangeBatch>
|
|
149
|
+
</ChangeResourceRecordSetsRequest>
|
|
150
|
+
XML
|
|
151
|
+
end
|
|
152
|
+
|
|
109
153
|
def change_record(action, record)
|
|
110
154
|
http.post("", <<~XML)
|
|
111
155
|
<?xml version="1.0" encoding="UTF-8"?>
|
data/lib/zonesync/sync.rb
CHANGED
|
@@ -38,9 +38,10 @@ module Zonesync
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
Logger.log(method, records, dry_run:
|
|
43
|
-
|
|
41
|
+
if dry_run
|
|
42
|
+
operations.each { |method, records| Logger.log(method, records, dry_run: true) }
|
|
43
|
+
else
|
|
44
|
+
destination.apply(operations) { |method, records| Logger.log(method, records) }
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
end
|
data/lib/zonesync/validator.rb
CHANGED
|
@@ -89,6 +89,8 @@ module Zonesync
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
def validate_addition(record, force: false)
|
|
92
|
+
excluded_record = find_excluded_record(record)
|
|
93
|
+
return [excluded_record, record] if excluded_record
|
|
92
94
|
return nil if manifest.matches?(record)
|
|
93
95
|
return nil if force
|
|
94
96
|
|
|
@@ -106,6 +108,13 @@ module Zonesync
|
|
|
106
108
|
[conflicting_record, record]
|
|
107
109
|
end
|
|
108
110
|
|
|
111
|
+
def find_excluded_record(record)
|
|
112
|
+
removed = operations.filter_map { |method, (r)| r if method == :remove }
|
|
113
|
+
destination.records.find do |r|
|
|
114
|
+
r.excludes?(record) && removed.none? { |x| x.identical_to?(r) }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
109
118
|
def find_v2_conflict(record, expected_hashes)
|
|
110
119
|
destination.records.find do |r|
|
|
111
120
|
next if r.manifest? || r.checksum?
|
data/lib/zonesync/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zonesync
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.14.
|
|
4
|
+
version: 0.14.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Micah Geisel
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: exe
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2026-
|
|
12
|
+
date: 2026-09-23 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: thor
|