record_store 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,157 +2,147 @@ require 'fog/dnsimple'
2
2
 
3
3
  module RecordStore
4
4
  class Provider::DNSimple < Provider
5
- def self.supports_alias?
6
- true
7
- end
8
-
9
- def add(record)
10
- record_hash = api_hash(record)
11
- res = session.create_record(
12
- @zone_name,
13
- record_hash.fetch(:name),
14
- record.type,
15
- record_hash.fetch(:content),
16
- ttl: record_hash.fetch(:ttl),
17
- priority: record_hash.fetch(:prio, nil)
18
- )
19
-
20
- if record.type == 'ALIAS'
21
- txt_alias = retrieve_current_records.detect do |rr|
22
- rr.type == 'TXT' && rr.fqdn == record.fqdn && rr.txtdata == "ALIAS for #{record.alias.chomp('.')}"
23
- end
24
- remove(txt_alias)
5
+ class << self
6
+ def supports_alias?
7
+ true
25
8
  end
26
9
 
27
- res
28
- end
29
-
30
- def remove(record)
31
- session.delete_record(@zone_name, record.id)
32
- end
33
-
34
- def update(id, record)
35
- record_hash = api_hash(record)
36
- session.update_record(@zone_name, id, api_hash(record))
37
- end
38
-
39
- # returns an array of Record objects that match the records which exist in the provider
40
- def retrieve_current_records(stdout = $stdout)
41
- session.list_records(@zone_name).body.map do |record|
42
- record_body = record.fetch('record')
10
+ def add(record, zone)
11
+ record_hash = api_hash(record, zone)
12
+ res = session.create_record(
13
+ zone,
14
+ record_hash.fetch(:name),
15
+ record.type,
16
+ record_hash.fetch(:content),
17
+ ttl: record_hash.fetch(:ttl),
18
+ priority: record_hash.fetch(:prio, nil)
19
+ )
43
20
 
44
- begin
45
- build_from_api(record_body)
46
- rescue StandardError
47
- stdout.puts "Cannot build record: #{record_body}"
48
- raise
21
+ if record.type == 'ALIAS'
22
+ txt_alias = retrieve_current_records(zone: zone).detect do |rr|
23
+ rr.type == 'TXT' && rr.fqdn == record.fqdn && rr.txtdata == "ALIAS for #{record.alias.chomp('.')}"
24
+ end
25
+ remove(txt_alias, zone)
49
26
  end
50
- end.select(&:present?)
51
- end
52
27
 
53
- # Returns an array of the zones managed by provider as strings
54
- def zones
55
- session.zones.map(&:domain)
56
- end
28
+ res
29
+ end
57
30
 
58
- private
31
+ def remove(record, zone)
32
+ session.delete_record(zone, record.id)
33
+ end
59
34
 
60
- def discard_change_set
61
- session.request(expects: 200, method: :delete, path: "ZoneChanges/#{@zone_name}")
62
- end
35
+ def update(id, record, zone)
36
+ record_hash = api_hash(record, zone)
37
+ session.update_record(zone, id, api_hash(record, zone))
38
+ end
63
39
 
64
- def session
65
- @dns ||= Fog::DNS.new(session_params)
66
- end
40
+ # returns an array of Record objects that match the records which exist in the provider
41
+ def retrieve_current_records(zone:, stdout: $stdout)
42
+ session.list_records(zone).body.map do |record|
43
+ record_body = record.fetch('record')
44
+
45
+ begin
46
+ build_from_api(record_body, zone)
47
+ rescue StandardError
48
+ stdout.puts "Cannot build record: #{record_body}"
49
+ raise
50
+ end
51
+ end.select(&:present?)
52
+ end
67
53
 
68
- def session_params
69
- {
70
- provider: 'DNSimple',
71
- dnsimple_email: secrets.fetch('email'),
72
- dnsimple_token: secrets.fetch('api_token'),
73
- }
74
- end
54
+ # Returns an array of the zones managed by provider as strings
55
+ def zones
56
+ session.zones.map(&:domain)
57
+ end
75
58
 
76
- def secrets
77
- super.fetch('dnsimple')
78
- end
59
+ private
79
60
 
80
- def build_from_api(api_record)
81
- record_type = api_record.fetch('record_type')
82
- record = {
83
- record_id: api_record.fetch('id'),
84
- ttl: api_record.fetch('ttl'),
85
- fqdn: api_record.fetch('name').present? ? "#{api_record.fetch('name')}.#{@zone_name}" : @zone_name,
86
- }
87
-
88
- return if record_type == 'SOA'
89
-
90
- case record_type
91
- when 'A'
92
- record.merge!(address: api_record.fetch('content'))
93
- when 'AAAA'
94
- record.merge!(address: api_record.fetch('content'))
95
- when 'ALIAS'
96
- record.merge!(alias: api_record.fetch('content'))
97
- when 'CNAME'
98
- record.merge!(cname: api_record.fetch('content'))
99
- when 'MX'
100
- record.merge!(preference: api_record.fetch('prio'), exchange: api_record.fetch('content'))
101
- when 'NS'
102
- record.merge!(nsdname: api_record.fetch('content'))
103
- when 'SPF'
104
- record.merge!(txtdata: api_record.fetch('content'))
105
- when 'SRV'
106
- weight, port, host = api_record.fetch('content').split(' ')
107
-
108
- record.merge!(
109
- priority: api_record.fetch('prio'),
110
- weight: weight,
111
- port: port,
112
- target: Record.ensure_ends_with_dot(host),
113
- )
114
- when 'TXT'
115
- record.merge!(txtdata: api_record.fetch('content'))
61
+ def session
62
+ @dns ||= Fog::DNS.new(session_params)
116
63
  end
117
64
 
118
- unless record.fetch(:fqdn).ends_with?('.')
119
- record[:fqdn] += '.'
65
+ def session_params
66
+ {
67
+ provider: 'DNSimple',
68
+ dnsimple_email: secrets.fetch('email'),
69
+ dnsimple_token: secrets.fetch('api_token'),
70
+ }
120
71
  end
121
72
 
122
- Record.const_get(record_type).new(record)
123
- end
73
+ def secrets
74
+ super.fetch('dnsimple')
75
+ end
124
76
 
125
- def api_hash(record)
126
- record_hash = {
127
- name: record.fqdn.gsub("#{Record.ensure_ends_with_dot(@zone_name)}", '').chomp('.'),
128
- ttl: record.ttl,
129
- type: record.type,
130
- }
131
-
132
- case record.type
133
- when 'A'
134
- record_hash[:content] = record.address
135
- when 'AAAA'
136
- record_hash[:content] = record.address
137
- when 'ALIAS'
138
- record_hash[:content] = record.alias.chomp('.')
139
- when 'CNAME'
140
- record_hash[:content] = record.cname.chomp('.')
141
- when 'MX'
142
- record_hash[:prio] = record.preference
143
- record_hash[:content] = record.exchange.chomp('.')
144
- when 'NS'
145
- record_hash[:content] = record.nsdname.chomp('.')
146
- when 'SPF'
147
- record_hash[:content] = record.txtdata
148
- when 'SRV'
149
- record_hash[:content] = "#{record.weight} #{record.port} #{record.target.chomp('.')}"
150
- record_hash[:prio] = record.priority
151
- when 'TXT'
152
- record_hash[:content] = record.txtdata
77
+ def build_from_api(api_record, zone)
78
+ record_type = api_record.fetch('record_type')
79
+ record = {
80
+ record_id: api_record.fetch('id'),
81
+ ttl: api_record.fetch('ttl'),
82
+ fqdn: api_record.fetch('name').present? ? "#{api_record.fetch('name')}.#{zone}" : zone,
83
+ }
84
+
85
+ return if record_type == 'SOA'
86
+
87
+ case record_type
88
+ when 'A', 'AAAA'
89
+ record.merge!(address: api_record.fetch('content'))
90
+ when 'ALIAS'
91
+ record.merge!(alias: api_record.fetch('content'))
92
+ when 'CNAME'
93
+ record.merge!(cname: api_record.fetch('content'))
94
+ when 'MX'
95
+ record.merge!(preference: api_record.fetch('prio'), exchange: api_record.fetch('content'))
96
+ when 'NS'
97
+ record.merge!(nsdname: api_record.fetch('content'))
98
+ when 'SPF', 'TXT'
99
+ record.merge!(txtdata: api_record.fetch('content'))
100
+ when 'SRV'
101
+ weight, port, host = api_record.fetch('content').split(' ')
102
+
103
+ record.merge!(
104
+ priority: api_record.fetch('prio'),
105
+ weight: weight,
106
+ port: port,
107
+ target: Record.ensure_ends_with_dot(host),
108
+ )
109
+ end
110
+
111
+ unless record.fetch(:fqdn).ends_with?('.')
112
+ record[:fqdn] += '.'
113
+ end
114
+
115
+ Record.const_get(record_type).new(record)
153
116
  end
154
117
 
155
- record_hash
118
+ def api_hash(record, zone)
119
+ record_hash = {
120
+ name: record.fqdn.gsub("#{Record.ensure_ends_with_dot(zone)}", '').chomp('.'),
121
+ ttl: record.ttl,
122
+ type: record.type,
123
+ }
124
+
125
+ case record.type
126
+ when 'A', 'AAAA'
127
+ record_hash[:content] = record.address
128
+ when 'ALIAS'
129
+ record_hash[:content] = record.alias.chomp('.')
130
+ when 'CNAME'
131
+ record_hash[:content] = record.cname.chomp('.')
132
+ when 'MX'
133
+ record_hash[:prio] = record.preference
134
+ record_hash[:content] = record.exchange.chomp('.')
135
+ when 'NS'
136
+ record_hash[:content] = record.nsdname.chomp('.')
137
+ when 'SPF', 'TXT'
138
+ record_hash[:content] = record.txtdata
139
+ when 'SRV'
140
+ record_hash[:content] = "#{record.weight} #{record.port} #{record.target.chomp('.')}"
141
+ record_hash[:prio] = record.priority
142
+ end
143
+
144
+ record_hash
145
+ end
156
146
  end
157
147
  end
158
148
  end
@@ -2,96 +2,98 @@ require 'fog/dynect'
2
2
 
3
3
  module RecordStore
4
4
  class Provider::DynECT < Provider
5
- def freeze_zone
6
- session.put_zone(@zone_name, freeze: true)
7
- end
5
+ class << self
6
+ def freeze_zone(zone)
7
+ session.put_zone(zone, freeze: true)
8
+ end
8
9
 
9
- def thaw
10
- session.put_zone(@zone_name, thaw: true)
11
- end
10
+ def thaw_zone(zone)
11
+ session.put_zone(zone, thaw: true)
12
+ end
12
13
 
13
- def add(record)
14
- session.post_record(record.type, @zone_name, record.fqdn, record.rdata, ttl: record.ttl)
15
- end
14
+ def add(record, zone)
15
+ session.post_record(record.type, zone, record.fqdn, record.rdata, ttl: record.ttl)
16
+ end
16
17
 
17
- def remove(record)
18
- session.delete_record(record.type, @zone_name, record.fqdn, record.id)
19
- end
18
+ def remove(record, zone)
19
+ session.delete_record(record.type, zone, record.fqdn, record.id)
20
+ end
20
21
 
21
- def update(id, record)
22
- session.put_record(record.type, @zone_name, record.fqdn, record.rdata, ttl: record.ttl, record_id: id)
23
- end
22
+ def update(id, record, zone)
23
+ session.put_record(record.type, zone, record.fqdn, record.rdata, ttl: record.ttl, record_id: id)
24
+ end
24
25
 
25
- def publish
26
- session.put_zone(@zone_name, publish: true)
27
- end
26
+ def publish(zone)
27
+ session.put_zone(zone, publish: true)
28
+ end
28
29
 
29
- # Applies changeset to provider
30
- def apply_changeset(changeset, stdout = $stdout)
31
- begin
32
- thaw
33
- super
34
- publish
35
- rescue StandardError
36
- puts "An exception occurred while applying DNS changes, deleting changeset"
37
- discard_change_set
38
- raise
39
- ensure
40
- freeze_zone
30
+ # Applies changeset to provider
31
+ def apply_changeset(changeset, stdout = $stdout)
32
+ begin
33
+ thaw_zone(changeset.zone)
34
+ super
35
+ publish(changeset.zone)
36
+ rescue StandardError
37
+ puts "An exception occurred while applying DNS changes, deleting changeset"
38
+ discard_change_set(changeset.zone)
39
+ raise
40
+ ensure
41
+ freeze_zone(changeset.zone)
42
+ end
41
43
  end
42
- end
43
44
 
44
- # returns an array of Record objects that match the records which exist in the provider
45
- def retrieve_current_records(stdout = $stdout)
46
- session.get_all_records(@zone_name).body.fetch('data').flat_map do |type, records|
47
- records.map do |record_body|
48
- begin
49
- build_from_api(record_body)
50
- rescue StandardError => e
51
- stdout.puts "Cannot build record: #{record_body}"
45
+ # returns an array of Record objects that match the records which exist in the provider
46
+ def retrieve_current_records(zone:, stdout: $stdout)
47
+ session.get_all_records(zone).body.fetch('data').flat_map do |type, records|
48
+ records.map do |record_body|
49
+ begin
50
+ build_from_api(record_body)
51
+ rescue StandardError => e
52
+ stdout.puts "Cannot build record: #{record_body}"
53
+ end
52
54
  end
53
- end
54
- end.select(&:present?)
55
- end
55
+ end.select(&:present?)
56
+ end
56
57
 
57
- # Returns an array of the zones managed by provider as strings
58
- def zones
59
- session.zones.map(&:domain)
60
- end
58
+ # Returns an array of the zones managed by provider as strings
59
+ def zones
60
+ session.zones.map(&:domain)
61
+ end
61
62
 
62
- private
63
+ private
63
64
 
64
- def discard_change_set
65
- session.request(expects: 200, method: :delete, path: "ZoneChanges/#{@zone_name}")
66
- end
65
+ def discard_change_set(zone)
66
+ session.request(expects: 200, method: :delete, path: "ZoneChanges/#{zone}")
67
+ end
67
68
 
68
- def session
69
- @dns ||= Fog::DNS.new(session_params)
70
- end
69
+ def session
70
+ @dns ||= Fog::DNS.new(session_params)
71
+ end
71
72
 
72
- def session_params
73
- {
74
- provider: 'Dynect',
75
- dynect_customer: secrets.fetch('customer'),
76
- dynect_username: secrets.fetch('username'),
77
- dynect_password: secrets.fetch('password')
78
- }
79
- end
73
+ def session_params
74
+ {
75
+ provider: 'Dynect',
76
+ dynect_customer: secrets.fetch('customer'),
77
+ dynect_username: secrets.fetch('username'),
78
+ dynect_password: secrets.fetch('password')
79
+ }
80
+ end
80
81
 
81
- def secrets
82
- super.fetch('dynect')
83
- end
82
+ def secrets
83
+ super.fetch('dynect')
84
+ end
84
85
 
85
- def build_from_api(api_record)
86
- record = api_record.merge(api_record.fetch('rdata')).slice!('rdata').symbolize_keys
86
+ def build_from_api(api_record)
87
+ record = api_record.merge(api_record.fetch('rdata')).slice!('rdata').symbolize_keys
87
88
 
88
- return if record.fetch(:record_type) == 'SOA'
89
+ return if record.fetch(:record_type) == 'SOA'
89
90
 
90
- unless record.fetch(:fqdn).ends_with?('.')
91
- record[:fqdn] = "#{record.fetch(:fqdn)}."
92
- end
91
+ unless record.fetch(:fqdn).ends_with?('.')
92
+ record[:fqdn] = "#{record.fetch(:fqdn)}."
93
+ end
93
94
 
94
- Record.const_get(record.fetch(:record_type)).new(record)
95
+ Record.const_get(record.fetch(:record_type)).new(record)
96
+ end
95
97
  end
96
98
  end
97
99
  end
@@ -19,6 +19,7 @@ module RecordStore
19
19
 
20
20
  def self.build_from_yaml_definition(yaml_definition)
21
21
  record_type = yaml_definition.fetch(:type)
22
+
22
23
  # TODO: remove backward compatibility support for ALIAS records using cname attribute instead of alias
23
24
  # REMOVE after merging https://github.com/Shopify/record-store/pull/781
24
25
  case record_type