google-cloud-dns 0.20.0
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 +7 -0
- data/lib/google-cloud-dns.rb +121 -0
- data/lib/google/cloud/dns.rb +290 -0
- data/lib/google/cloud/dns/change.rb +160 -0
- data/lib/google/cloud/dns/change/list.rb +176 -0
- data/lib/google/cloud/dns/credentials.rb +31 -0
- data/lib/google/cloud/dns/importer.rb +186 -0
- data/lib/google/cloud/dns/project.rb +251 -0
- data/lib/google/cloud/dns/record.rb +173 -0
- data/lib/google/cloud/dns/record/list.rb +177 -0
- data/lib/google/cloud/dns/service.rb +166 -0
- data/lib/google/cloud/dns/version.rb +22 -0
- data/lib/google/cloud/dns/zone.rb +768 -0
- data/lib/google/cloud/dns/zone/list.rb +170 -0
- data/lib/google/cloud/dns/zone/transaction.rb +180 -0
- metadata +214 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
# Copyright 2016 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Dns
|
19
|
+
VERSION = "0.20.0"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,768 @@
|
|
1
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/dns/change"
|
17
|
+
require "google/cloud/dns/zone/transaction"
|
18
|
+
require "google/cloud/dns/zone/list"
|
19
|
+
require "google/cloud/dns/record"
|
20
|
+
require "google/cloud/dns/importer"
|
21
|
+
require "time"
|
22
|
+
|
23
|
+
module Google
|
24
|
+
module Cloud
|
25
|
+
module Dns
|
26
|
+
##
|
27
|
+
# # DNS Zone
|
28
|
+
#
|
29
|
+
# The managed zone is the container for DNS records for the same DNS name
|
30
|
+
# suffix and has a set of name servers that accept and responds to
|
31
|
+
# queries. A project can have multiple managed zones, but they must each
|
32
|
+
# have a unique name.
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# require "google/cloud"
|
36
|
+
#
|
37
|
+
# gcloud = Google::Cloud.new
|
38
|
+
# dns = gcloud.dns
|
39
|
+
# zone = dns.zone "example-com"
|
40
|
+
# zone.records.each do |record|
|
41
|
+
# puts record.name
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# @see https://cloud.google.com/dns/zones/ Managing Zones
|
45
|
+
#
|
46
|
+
class Zone
|
47
|
+
##
|
48
|
+
# @private The Service object.
|
49
|
+
attr_accessor :service
|
50
|
+
|
51
|
+
##
|
52
|
+
# @private The Google API Client object.
|
53
|
+
attr_accessor :gapi
|
54
|
+
|
55
|
+
##
|
56
|
+
# @private Create an empty Zone object.
|
57
|
+
def initialize
|
58
|
+
@service = nil
|
59
|
+
@gapi = {}
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Unique identifier for the resource; defined by the server.
|
64
|
+
#
|
65
|
+
def id
|
66
|
+
@gapi.id
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# User assigned name for this resource. Must be unique within the
|
71
|
+
# project. The name must be 1-32 characters long, must begin with a
|
72
|
+
# letter, end with a letter or digit, and only contain lowercase
|
73
|
+
# letters, digits or dashes.
|
74
|
+
#
|
75
|
+
def name
|
76
|
+
@gapi.name
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# The DNS name of this managed zone, for instance "example.com.".
|
81
|
+
#
|
82
|
+
def dns
|
83
|
+
@gapi.dns_name
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# A string of at most 1024 characters associated with this resource for
|
88
|
+
# the user's convenience. Has no effect on the managed zone's function.
|
89
|
+
#
|
90
|
+
def description
|
91
|
+
@gapi.description
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Delegate your managed_zone to these virtual name servers; defined by
|
96
|
+
# the server.
|
97
|
+
#
|
98
|
+
def name_servers
|
99
|
+
Array(@gapi.name_servers)
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Optionally specifies the NameServerSet for this ManagedZone. A
|
104
|
+
# NameServerSet is a set of DNS name servers that all host the same
|
105
|
+
# ManagedZones. Most users will leave this field unset.
|
106
|
+
#
|
107
|
+
def name_server_set
|
108
|
+
@gapi.name_server_set
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# The time that this resource was created on the server.
|
113
|
+
#
|
114
|
+
def created_at
|
115
|
+
Time.parse @gapi.creation_time
|
116
|
+
rescue
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Permanently deletes the zone.
|
122
|
+
#
|
123
|
+
# @param [Boolean] force If `true`, ensures the deletion of the zone by
|
124
|
+
# first deleting all records. If `false` and the zone contains
|
125
|
+
# non-essential records, the request will fail. Default is `false`.
|
126
|
+
#
|
127
|
+
# @return [Boolean] Returns `true` if the zone was deleted.
|
128
|
+
#
|
129
|
+
# @example
|
130
|
+
# require "google/cloud"
|
131
|
+
#
|
132
|
+
# gcloud = Google::Cloud.new
|
133
|
+
# dns = gcloud.dns
|
134
|
+
# zone = dns.zone "example-com"
|
135
|
+
# zone.delete
|
136
|
+
#
|
137
|
+
# @example The zone can be forcefully deleted with the `force` option:
|
138
|
+
# require "google/cloud"
|
139
|
+
#
|
140
|
+
# gcloud = Google::Cloud.new
|
141
|
+
# dns = gcloud.dns
|
142
|
+
# zone = dns.zone "example-com"
|
143
|
+
# zone.delete force: true
|
144
|
+
#
|
145
|
+
def delete force: false
|
146
|
+
clear! if force
|
147
|
+
|
148
|
+
ensure_service!
|
149
|
+
service.delete_zone id
|
150
|
+
true
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Removes non-essential records from the zone. Only NS and SOA records
|
155
|
+
# will be kept.
|
156
|
+
#
|
157
|
+
# @example
|
158
|
+
# require "google/cloud"
|
159
|
+
#
|
160
|
+
# gcloud = Google::Cloud.new
|
161
|
+
# dns = gcloud.dns
|
162
|
+
# zone = dns.zone "example-com"
|
163
|
+
# zone.clear!
|
164
|
+
#
|
165
|
+
def clear!
|
166
|
+
non_essential = records.all.reject { |r| %w(SOA NS).include?(r.type) }
|
167
|
+
change = update [], non_essential
|
168
|
+
change.wait_until_done! unless change.nil?
|
169
|
+
end
|
170
|
+
|
171
|
+
##
|
172
|
+
# Retrieves an existing change by id.
|
173
|
+
#
|
174
|
+
# @param [String] change_id The id of a change.
|
175
|
+
#
|
176
|
+
# @return [Google::Cloud::Dns::Change, nil] Returns `nil` if the change
|
177
|
+
# does not exist.
|
178
|
+
#
|
179
|
+
# @example
|
180
|
+
# require "google/cloud"
|
181
|
+
#
|
182
|
+
# gcloud = Google::Cloud.new
|
183
|
+
# dns = gcloud.dns
|
184
|
+
# zone = dns.zone "example-com"
|
185
|
+
# change = zone.change "2"
|
186
|
+
# if change
|
187
|
+
# puts "#{change.id} - #{change.started_at} - #{change.status}"
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
def change change_id
|
191
|
+
ensure_service!
|
192
|
+
gapi = service.get_change id, change_id
|
193
|
+
Change.from_gapi gapi, self
|
194
|
+
rescue Google::Cloud::NotFoundError
|
195
|
+
nil
|
196
|
+
end
|
197
|
+
alias_method :find_change, :change
|
198
|
+
alias_method :get_change, :change
|
199
|
+
|
200
|
+
##
|
201
|
+
# Retrieves the list of changes belonging to the zone.
|
202
|
+
#
|
203
|
+
# @param [String] token A previously-returned page token representing
|
204
|
+
# part of the larger set of results to view.
|
205
|
+
# @param [Integer] max Maximum number of changes to return.
|
206
|
+
# @param [Symbol, String] order Sort the changes by change sequence.
|
207
|
+
#
|
208
|
+
# Acceptable values are:
|
209
|
+
#
|
210
|
+
# * `asc` - Sort by ascending change sequence
|
211
|
+
# * `desc` - Sort by descending change sequence
|
212
|
+
#
|
213
|
+
# @return [Array<Google::Cloud::Dns::Change>] (See
|
214
|
+
# {Google::Cloud::Dns::Change::List})
|
215
|
+
#
|
216
|
+
# @example
|
217
|
+
# require "google/cloud"
|
218
|
+
#
|
219
|
+
# gcloud = Google::Cloud.new
|
220
|
+
# dns = gcloud.dns
|
221
|
+
# zone = dns.zone "example-com"
|
222
|
+
# changes = zone.changes
|
223
|
+
# changes.each do |change|
|
224
|
+
# puts "#{change.id} - #{change.started_at} - #{change.status}"
|
225
|
+
# end
|
226
|
+
#
|
227
|
+
# @example The changes can be sorted by change sequence:
|
228
|
+
# require "google/cloud"
|
229
|
+
#
|
230
|
+
# gcloud = Google::Cloud.new
|
231
|
+
# dns = gcloud.dns
|
232
|
+
# zone = dns.zone "example-com"
|
233
|
+
# changes = zone.changes order: :desc
|
234
|
+
#
|
235
|
+
# @example Retrieve all changes: (See {Change::List#all})
|
236
|
+
# require "google/cloud"
|
237
|
+
#
|
238
|
+
# gcloud = Google::Cloud.new
|
239
|
+
# dns = gcloud.dns
|
240
|
+
# zone = dns.zone "example-com"
|
241
|
+
# changes = zone.changes
|
242
|
+
# changes.all do |change|
|
243
|
+
# puts "#{change.name} - #{change.status}"
|
244
|
+
# end
|
245
|
+
#
|
246
|
+
def changes token: nil, max: nil, order: nil
|
247
|
+
ensure_service!
|
248
|
+
# Fix the sort options
|
249
|
+
order = adjust_change_sort_order order
|
250
|
+
sort = "changeSequence" if order
|
251
|
+
# Continue with the API call
|
252
|
+
gapi = service.list_changes id, token: token, max: max,
|
253
|
+
order: order, sort: sort
|
254
|
+
Change::List.from_gapi gapi, self, max, order
|
255
|
+
end
|
256
|
+
alias_method :find_changes, :changes
|
257
|
+
|
258
|
+
##
|
259
|
+
# Retrieves the list of records belonging to the zone. Records can be
|
260
|
+
# filtered by name and type. The name argument can be a subdomain (e.g.,
|
261
|
+
# `www`) fragment for convenience, but notice that the retrieved
|
262
|
+
# record's domain name is always fully-qualified.
|
263
|
+
#
|
264
|
+
# @param [String] name Return only records with this domain or subdomain
|
265
|
+
# name.
|
266
|
+
# @param [String] type Return only records with this [record
|
267
|
+
# type](https://cloud.google.com/dns/what-is-cloud-dns). If present,
|
268
|
+
# the `name` parameter must also be present.
|
269
|
+
# @param [String] token A previously-returned page token representing
|
270
|
+
# part of the larger set of results to view.
|
271
|
+
# @param [Integer] max Maximum number of records to return.
|
272
|
+
#
|
273
|
+
# @return [Array<Google::Cloud::Dns::Record>] (See
|
274
|
+
# {Google::Cloud::Dns::Record::List})
|
275
|
+
#
|
276
|
+
# @example
|
277
|
+
# require "google/cloud"
|
278
|
+
#
|
279
|
+
# gcloud = Google::Cloud.new
|
280
|
+
# dns = gcloud.dns
|
281
|
+
# zone = dns.zone "example-com"
|
282
|
+
# records = zone.records
|
283
|
+
# records.each do |record|
|
284
|
+
# puts record.name
|
285
|
+
# end
|
286
|
+
#
|
287
|
+
# @example Records can be filtered by name and type:
|
288
|
+
# require "google/cloud"
|
289
|
+
#
|
290
|
+
# gcloud = Google::Cloud.new
|
291
|
+
# dns = gcloud.dns
|
292
|
+
# zone = dns.zone "example-com"
|
293
|
+
# records = zone.records "www", "A"
|
294
|
+
# records.first.name #=> "www.example.com."
|
295
|
+
#
|
296
|
+
# @example Retrieve all records:
|
297
|
+
# require "google/cloud"
|
298
|
+
#
|
299
|
+
# gcloud = Google::Cloud.new
|
300
|
+
# dns = gcloud.dns
|
301
|
+
# zone = dns.zone "example-com"
|
302
|
+
# records = zone.records "example.com."
|
303
|
+
#
|
304
|
+
# records.all do |record|
|
305
|
+
# puts record.name
|
306
|
+
# end
|
307
|
+
#
|
308
|
+
def records name = nil, type = nil, token: nil, max: nil
|
309
|
+
ensure_service!
|
310
|
+
|
311
|
+
name = fqdn(name) if name
|
312
|
+
|
313
|
+
gapi = service.list_records id, name, type, token: token, max: max
|
314
|
+
Record::List.from_gapi gapi, self, name, type, max
|
315
|
+
end
|
316
|
+
alias_method :find_records, :records
|
317
|
+
|
318
|
+
##
|
319
|
+
# Creates a new, unsaved Record that can be added to a Zone.
|
320
|
+
#
|
321
|
+
# @return [Google::Cloud::Dns::Record]
|
322
|
+
#
|
323
|
+
# @example
|
324
|
+
# require "google/cloud"
|
325
|
+
#
|
326
|
+
# gcloud = Google::Cloud.new
|
327
|
+
# dns = gcloud.dns
|
328
|
+
# zone = dns.zone "example-com"
|
329
|
+
# record = zone.record "example.com.", "A", 86400, ["1.2.3.4"]
|
330
|
+
# zone.add record
|
331
|
+
#
|
332
|
+
def record name, type, ttl, data
|
333
|
+
Google::Cloud::Dns::Record.new fqdn(name), type, ttl, data
|
334
|
+
end
|
335
|
+
alias_method :new_record, :record
|
336
|
+
|
337
|
+
##
|
338
|
+
# Exports the zone to a local [DNS zone
|
339
|
+
# file](https://en.wikipedia.org/wiki/Zone_file).
|
340
|
+
#
|
341
|
+
# @param [String] path The path on the local file system to write the
|
342
|
+
# data to. The path provided must be writable.
|
343
|
+
#
|
344
|
+
# @return [File] An object on the local file system.
|
345
|
+
#
|
346
|
+
# @example
|
347
|
+
# require "google/cloud"
|
348
|
+
#
|
349
|
+
# gcloud = Google::Cloud.new
|
350
|
+
# dns = gcloud.dns
|
351
|
+
# zone = dns.zone "example-com"
|
352
|
+
#
|
353
|
+
# zone.export "path/to/db.example.com"
|
354
|
+
#
|
355
|
+
def export path
|
356
|
+
File.open path, "w" do |f|
|
357
|
+
f.write to_zonefile
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# Imports resource records from a [DNS zone
|
363
|
+
# file](https://en.wikipedia.org/wiki/Zone_file), adding the new records
|
364
|
+
# to the zone, without removing any existing records from the zone.
|
365
|
+
#
|
366
|
+
# Because the Google Cloud DNS API only accepts a single resource record
|
367
|
+
# for each `name` and `type` combination (with multiple `data`
|
368
|
+
# elements), the zone file's records are merged as necessary. During
|
369
|
+
# this merge, the lowest `ttl` of the merged records is used. If none of
|
370
|
+
# the merged records have a `ttl` value, the zone file's global TTL is
|
371
|
+
# used for the record.
|
372
|
+
#
|
373
|
+
# The zone file's SOA and NS records are not imported, because the zone
|
374
|
+
# was given SOA and NS records when it was created. These generated
|
375
|
+
# records point to Cloud DNS name servers.
|
376
|
+
#
|
377
|
+
# This operation automatically updates the SOA record serial number
|
378
|
+
# unless prevented with the `skip_soa` option. See {#update} for
|
379
|
+
# details.
|
380
|
+
#
|
381
|
+
# The Google Cloud DNS service requires that record names and data use
|
382
|
+
# fully-qualified addresses. The @ symbol is not accepted, nor are
|
383
|
+
# unqualified subdomain addresses like www. If your zone file contains
|
384
|
+
# such values, you may need to pre-process it in order for the import
|
385
|
+
# operation to succeed.
|
386
|
+
#
|
387
|
+
# @param [String, IO] path_or_io The path to a zone file on the
|
388
|
+
# filesystem, or an IO instance from which zone file data can be read.
|
389
|
+
# @param [String, Array<String>] only Include only records of this type
|
390
|
+
# or types.
|
391
|
+
# @param [String, Array<String>] except Exclude records of this type or
|
392
|
+
# types.
|
393
|
+
# @param [Boolean] skip_soa Do not automatically update the SOA record
|
394
|
+
# serial number. See {#update} for details.
|
395
|
+
# @param [Integer, lambda, Proc] soa_serial A value (or a lambda or Proc
|
396
|
+
# returning a value) for the new SOA record serial number. See
|
397
|
+
# {#update} for details.
|
398
|
+
#
|
399
|
+
# @return [Google::Cloud::Dns::Change] A new change adding the imported
|
400
|
+
# Record instances.
|
401
|
+
#
|
402
|
+
# @example
|
403
|
+
# require "google/cloud"
|
404
|
+
#
|
405
|
+
# gcloud = Google::Cloud.new
|
406
|
+
# dns = gcloud.dns
|
407
|
+
# zone = dns.zone "example-com"
|
408
|
+
# change = zone.import "path/to/db.example.com"
|
409
|
+
#
|
410
|
+
def import path_or_io, only: nil, except: nil,
|
411
|
+
skip_soa: nil, soa_serial: nil
|
412
|
+
except = (Array(except).map(&:to_s).map(&:upcase) + %w(SOA NS)).uniq
|
413
|
+
importer = Google::Cloud::Dns::Importer.new self, path_or_io
|
414
|
+
additions = importer.records only: only, except: except
|
415
|
+
update additions, [], skip_soa: skip_soa, soa_serial: soa_serial
|
416
|
+
end
|
417
|
+
|
418
|
+
# rubocop:disable all
|
419
|
+
# Disabled rubocop because this complexity cannot easily be avoided.
|
420
|
+
|
421
|
+
##
|
422
|
+
# Adds and removes Records from the zone. All changes are made in a
|
423
|
+
# single API request.
|
424
|
+
#
|
425
|
+
# The best way to add, remove, and update multiple records in a single
|
426
|
+
# [transaction](https://cloud.google.com/dns/records) is with a block.
|
427
|
+
# See {Zone::Transaction}.
|
428
|
+
#
|
429
|
+
# If the SOA record for the zone is not present in `additions` or
|
430
|
+
# `deletions` (and if present in one, it should be present in the
|
431
|
+
# other), it will be added to both, and its serial number will be
|
432
|
+
# incremented by adding `1`. This update to the SOA record can be
|
433
|
+
# prevented with the `skip_soa` option. To provide your own value or
|
434
|
+
# behavior for the new serial number, use the `soa_serial` option.
|
435
|
+
#
|
436
|
+
# @param [Record, Array<Record>] additions The Record or array of
|
437
|
+
# records to add.
|
438
|
+
# @param [Record, Array<Record>] deletions The Record or array of
|
439
|
+
# records to remove.
|
440
|
+
# @param [Boolean] skip_soa Do not automatically update the SOA record
|
441
|
+
# serial number.
|
442
|
+
# @param [Integer, lambda, Proc] soa_serial A value (or a lambda or Proc
|
443
|
+
# returning a value) for the new SOA record serial number.
|
444
|
+
# @yield [tx] a block yielding a new transaction
|
445
|
+
# @yieldparam [Zone::Transaction] tx the transaction object
|
446
|
+
#
|
447
|
+
# @return [Google::Cloud::Dns::Change]
|
448
|
+
#
|
449
|
+
# @example Using a block:
|
450
|
+
# require "google/cloud"
|
451
|
+
#
|
452
|
+
# gcloud = Google::Cloud.new
|
453
|
+
# dns = gcloud.dns
|
454
|
+
# zone = dns.zone "example-com"
|
455
|
+
# change = zone.update do |tx|
|
456
|
+
# tx.add "example.com.", "A", 86400, "1.2.3.4"
|
457
|
+
# tx.remove "example.com.", "TXT"
|
458
|
+
# tx.replace "example.com.", "MX", 86400, ["10 mail1.example.com.",
|
459
|
+
# "20 mail2.example.com."]
|
460
|
+
# tx.modify "www.example.com.", "CNAME" do |cname|
|
461
|
+
# cname.ttl = 86400 # only change the TTL
|
462
|
+
# end
|
463
|
+
# end
|
464
|
+
#
|
465
|
+
# @example Or you can provide the record objects to add and remove:
|
466
|
+
# require "google/cloud"
|
467
|
+
#
|
468
|
+
# gcloud = Google::Cloud.new
|
469
|
+
# dns = gcloud.dns
|
470
|
+
# zone = dns.zone "example-com"
|
471
|
+
# new_record = zone.record "example.com.", "A", 86400, ["1.2.3.4"]
|
472
|
+
# old_record = zone.record "example.com.", "A", 18600, ["1.2.3.4"]
|
473
|
+
# change = zone.update [new_record], [old_record]
|
474
|
+
#
|
475
|
+
# @example Using a lambda or Proc to update current SOA serial number:
|
476
|
+
# require "google/cloud"
|
477
|
+
#
|
478
|
+
# gcloud = Google::Cloud.new
|
479
|
+
# dns = gcloud.dns
|
480
|
+
# zone = dns.zone "example-com"
|
481
|
+
# new_record = zone.record "example.com.", "A", 86400, ["1.2.3.4"]
|
482
|
+
# change = zone.update new_record, soa_serial: lambda { |sn| sn + 10 }
|
483
|
+
#
|
484
|
+
def update additions = [], deletions = [], skip_soa: nil, soa_serial: nil
|
485
|
+
# Handle only sending in options
|
486
|
+
if additions.is_a?(::Hash) && deletions.empty? && options.empty?
|
487
|
+
options = additions
|
488
|
+
additions = []
|
489
|
+
elsif deletions.is_a?(::Hash) && options.empty?
|
490
|
+
options = deletions
|
491
|
+
deletions = []
|
492
|
+
end
|
493
|
+
|
494
|
+
additions = Array additions
|
495
|
+
deletions = Array deletions
|
496
|
+
|
497
|
+
if block_given?
|
498
|
+
updater = Zone::Transaction.new self
|
499
|
+
yield updater
|
500
|
+
additions += updater.additions
|
501
|
+
deletions += updater.deletions
|
502
|
+
end
|
503
|
+
|
504
|
+
to_add = additions - deletions
|
505
|
+
to_remove = deletions - additions
|
506
|
+
return nil if to_add.empty? && to_remove.empty?
|
507
|
+
unless skip_soa || detect_soa(to_add) || detect_soa(to_remove)
|
508
|
+
increment_soa to_add, to_remove, soa_serial
|
509
|
+
end
|
510
|
+
create_change to_add, to_remove
|
511
|
+
end
|
512
|
+
|
513
|
+
# rubocop:enable all
|
514
|
+
|
515
|
+
##
|
516
|
+
# Adds a record to the Zone. In order to update existing records, or add
|
517
|
+
# and delete records in the same transaction, use #update.
|
518
|
+
#
|
519
|
+
# This operation automatically updates the SOA record serial number
|
520
|
+
# unless prevented with the `skip_soa` option. See {#update} for
|
521
|
+
# details.
|
522
|
+
#
|
523
|
+
# @param [String] name The owner of the record. For example:
|
524
|
+
# `example.com.`.
|
525
|
+
# @param [String] type The identifier of a [supported record
|
526
|
+
# type](https://cloud.google.com/dns/what-is-cloud-dns).
|
527
|
+
# For example: `A`, `AAAA`, `CNAME`, `MX`, or `TXT`.
|
528
|
+
# @param [Integer] ttl The number of seconds that the record can be
|
529
|
+
# cached by resolvers.
|
530
|
+
# @param [String, Array<String>] data The resource record data, as
|
531
|
+
# determined by `type` and defined in [RFC
|
532
|
+
# 1035 (section 5)](http://tools.ietf.org/html/rfc1035#section-5) and
|
533
|
+
# [RFC 1034
|
534
|
+
# (section 3.6.1)](http://tools.ietf.org/html/rfc1034#section-3.6.1).
|
535
|
+
# For example: `192.0.2.1` or `example.com.`.
|
536
|
+
# @param [Boolean] skip_soa Do not automatically update the SOA record
|
537
|
+
# serial number. See {#update} for details.
|
538
|
+
# @param [Integer+, lambda, Proc] soa_serial A value (or a lambda or
|
539
|
+
# Proc returning a value) for the new SOA record serial number. See
|
540
|
+
# {#update} for details.
|
541
|
+
#
|
542
|
+
# @return [Google::Cloud::Dns::Change]
|
543
|
+
#
|
544
|
+
# @example
|
545
|
+
# require "google/cloud"
|
546
|
+
#
|
547
|
+
# gcloud = Google::Cloud.new
|
548
|
+
# dns = gcloud.dns
|
549
|
+
# zone = dns.zone "example-com"
|
550
|
+
# change = zone.add "example.com.", "A", 86400, ["1.2.3.4"]
|
551
|
+
#
|
552
|
+
def add name, type, ttl, data, skip_soa: nil, soa_serial: nil
|
553
|
+
update [record(name, type, ttl, data)], [],
|
554
|
+
skip_soa: skip_soa, soa_serial: soa_serial
|
555
|
+
end
|
556
|
+
|
557
|
+
##
|
558
|
+
# Removes records from the Zone. The records are looked up before they
|
559
|
+
# are removed. In order to update existing records, or add and remove
|
560
|
+
# records in the same transaction, use #update.
|
561
|
+
#
|
562
|
+
# This operation automatically updates the SOA record serial number
|
563
|
+
# unless prevented with the `skip_soa` option. See {#update} for
|
564
|
+
# details.
|
565
|
+
#
|
566
|
+
# @param [String] name The owner of the record. For example:
|
567
|
+
# `example.com.`.
|
568
|
+
# @param [String] type The identifier of a [supported record
|
569
|
+
# type](https://cloud.google.com/dns/what-is-cloud-dns).
|
570
|
+
# For example: `A`, `AAAA`, `CNAME`, `MX`, or `TXT`.
|
571
|
+
# @param [Boolean] skip_soa Do not automatically update the SOA record
|
572
|
+
# serial number. See {#update} for details.
|
573
|
+
# @param [Integer+, lambda, Proc] soa_serial A value (or a lambda or
|
574
|
+
# Proc returning a value) for the new SOA record serial number. See
|
575
|
+
# {#update} for details.
|
576
|
+
#
|
577
|
+
# @return [Google::Cloud::Dns::Change]
|
578
|
+
#
|
579
|
+
# @example
|
580
|
+
# require "google/cloud"
|
581
|
+
#
|
582
|
+
# gcloud = Google::Cloud.new
|
583
|
+
# dns = gcloud.dns
|
584
|
+
# zone = dns.zone "example-com"
|
585
|
+
# change = zone.remove "example.com.", "A"
|
586
|
+
#
|
587
|
+
def remove name, type, skip_soa: nil, soa_serial: nil
|
588
|
+
update [], records(name, type).all.to_a,
|
589
|
+
skip_soa: skip_soa, soa_serial: soa_serial
|
590
|
+
end
|
591
|
+
|
592
|
+
##
|
593
|
+
# Replaces existing records on the Zone. Records matching the `name` and
|
594
|
+
# `type` are replaced. In order to update existing records, or add and
|
595
|
+
# delete records in the same transaction, use #update.
|
596
|
+
#
|
597
|
+
# This operation automatically updates the SOA record serial number
|
598
|
+
# unless prevented with the `skip_soa` option. See {#update} for
|
599
|
+
# details.
|
600
|
+
#
|
601
|
+
# @param [String] name The owner of the record. For example:
|
602
|
+
# `example.com.`.
|
603
|
+
# @param [String] type The identifier of a [supported record
|
604
|
+
# type](https://cloud.google.com/dns/what-is-cloud-dns).
|
605
|
+
# For example: `A`, `AAAA`, `CNAME`, `MX`, or `TXT`.
|
606
|
+
# @param [Integer] ttl The number of seconds that the record can be
|
607
|
+
# cached by resolvers.
|
608
|
+
# @param [String, Array<String>] data The resource record data, as
|
609
|
+
# determined by `type` and defined in [RFC 1035 (section
|
610
|
+
# 5)](http://tools.ietf.org/html/rfc1035#section-5) and [RFC 1034
|
611
|
+
# (section 3.6.1)](http://tools.ietf.org/html/rfc1034#section-3.6.1).
|
612
|
+
# For example: `192.0.2.1` or `example.com.`.
|
613
|
+
# @param [Boolean] skip_soa Do not automatically update the SOA record
|
614
|
+
# serial number. See {#update} for details.
|
615
|
+
# @param [Integer+, lambda, Proc] soa_serial A value (or a lambda or
|
616
|
+
# Proc returning a value) for the new SOA record serial number. See
|
617
|
+
# {#update} for details.
|
618
|
+
#
|
619
|
+
# @return [Google::Cloud::Dns::Change]
|
620
|
+
#
|
621
|
+
# @example
|
622
|
+
# require "google/cloud"
|
623
|
+
#
|
624
|
+
# gcloud = Google::Cloud.new
|
625
|
+
# dns = gcloud.dns
|
626
|
+
# zone = dns.zone "example-com"
|
627
|
+
# change = zone.replace "example.com.", "A", 86400, ["5.6.7.8"]
|
628
|
+
#
|
629
|
+
def replace name, type, ttl, data, skip_soa: nil, soa_serial: nil
|
630
|
+
update [record(name, type, ttl, data)],
|
631
|
+
records(name, type).all.to_a,
|
632
|
+
skip_soa: skip_soa, soa_serial: soa_serial
|
633
|
+
end
|
634
|
+
|
635
|
+
# @private
|
636
|
+
def to_zonefile
|
637
|
+
records.all.map(&:to_zonefile_records).flatten.join("\n")
|
638
|
+
end
|
639
|
+
|
640
|
+
##
|
641
|
+
# Modifies records on the Zone. Records matching the `name` and `type`
|
642
|
+
# are yielded to the block where they can be modified.
|
643
|
+
#
|
644
|
+
# This operation automatically updates the SOA record serial number
|
645
|
+
# unless prevented with the `skip_soa` option. See {#update} for
|
646
|
+
# details.
|
647
|
+
#
|
648
|
+
# @param [String] name The owner of the record. For example:
|
649
|
+
# `example.com.`.
|
650
|
+
# @param [String] type The identifier of a [supported record
|
651
|
+
# type](https://cloud.google.com/dns/what-is-cloud-dns).
|
652
|
+
# For example: `A`, `AAAA`, `CNAME`, `MX`, or `TXT`.
|
653
|
+
# @param [Boolean] skip_soa Do not automatically update the SOA record
|
654
|
+
# serial number. See {#update} for details.
|
655
|
+
# @param [Integer+, lambda, Proc] soa_serial A value (or a lambda or
|
656
|
+
# Proc returning a value) for the new SOA record serial number. See
|
657
|
+
# {#update} for details.
|
658
|
+
# @yield [record] a block yielding each matching record
|
659
|
+
# @yieldparam [Record] record the record to be modified
|
660
|
+
#
|
661
|
+
# @return [Google::Cloud::Dns::Change]
|
662
|
+
#
|
663
|
+
# @example
|
664
|
+
# require "google/cloud"
|
665
|
+
#
|
666
|
+
# gcloud = Google::Cloud.new
|
667
|
+
# dns = gcloud.dns
|
668
|
+
# zone = dns.zone "example-com"
|
669
|
+
# change = zone.modify "example.com.", "MX" do |mx|
|
670
|
+
# mx.ttl = 3600 # change only the TTL
|
671
|
+
# end
|
672
|
+
#
|
673
|
+
def modify name, type, skip_soa: nil, soa_serial: nil
|
674
|
+
existing = records(name, type).all.to_a
|
675
|
+
updated = existing.map(&:dup)
|
676
|
+
updated.each { |r| yield r }
|
677
|
+
update updated, existing, skip_soa: skip_soa, soa_serial: soa_serial
|
678
|
+
end
|
679
|
+
|
680
|
+
##
|
681
|
+
# This helper converts the given domain name or subdomain (e.g., `www`)
|
682
|
+
# fragment to a [fully qualified domain name
|
683
|
+
# (FQDN)](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) for
|
684
|
+
# the zone's #dns. If the argument is already a FQDN, it is returned
|
685
|
+
# unchanged.
|
686
|
+
#
|
687
|
+
# @param [String] domain_name The name to convert to a fully qualified
|
688
|
+
# domain name.
|
689
|
+
#
|
690
|
+
# @return [String] A fully qualified domain name.
|
691
|
+
#
|
692
|
+
# @example
|
693
|
+
# require "google/cloud"
|
694
|
+
#
|
695
|
+
# gcloud = Google::Cloud.new
|
696
|
+
# dns = gcloud.dns
|
697
|
+
# zone = dns.zone "example-com"
|
698
|
+
# zone.fqdn "www" #=> "www.example.com."
|
699
|
+
# zone.fqdn "@" #=> "example.com."
|
700
|
+
# zone.fqdn "mail.example.com." #=> "mail.example.com."
|
701
|
+
#
|
702
|
+
def fqdn domain_name
|
703
|
+
Service.fqdn domain_name, dns
|
704
|
+
end
|
705
|
+
|
706
|
+
##
|
707
|
+
# @private New Zone from a Google API Client object.
|
708
|
+
def self.from_gapi gapi, conn
|
709
|
+
new.tap do |f|
|
710
|
+
f.gapi = gapi
|
711
|
+
f.service = conn
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
protected
|
716
|
+
|
717
|
+
##
|
718
|
+
# Raise an error unless an active connection is available.
|
719
|
+
def ensure_service!
|
720
|
+
fail "Must have active connection" unless service
|
721
|
+
end
|
722
|
+
|
723
|
+
def create_change additions, deletions
|
724
|
+
ensure_service!
|
725
|
+
gapi = service.create_change id, additions.map(&:to_gapi),
|
726
|
+
deletions.map(&:to_gapi)
|
727
|
+
Change.from_gapi gapi, self
|
728
|
+
end
|
729
|
+
|
730
|
+
def increment_soa to_add, to_remove, soa_serial
|
731
|
+
current_soa = detect_soa records(dns, "SOA").all
|
732
|
+
return false if current_soa.nil?
|
733
|
+
updated_soa = current_soa.dup
|
734
|
+
updated_soa.data[0] = replace_soa_serial updated_soa.data[0],
|
735
|
+
soa_serial
|
736
|
+
to_add << updated_soa
|
737
|
+
to_remove << current_soa
|
738
|
+
end
|
739
|
+
|
740
|
+
def detect_soa records
|
741
|
+
records.detect { |r| r.type == "SOA" }
|
742
|
+
end
|
743
|
+
|
744
|
+
def replace_soa_serial soa_data, soa_serial
|
745
|
+
soa_data = soa_data.split " "
|
746
|
+
current_serial = soa_data[2].to_i
|
747
|
+
soa_data[2] = if soa_serial && soa_serial.respond_to?(:call)
|
748
|
+
soa_serial.call current_serial
|
749
|
+
elsif soa_serial
|
750
|
+
soa_serial.to_i
|
751
|
+
else
|
752
|
+
current_serial + 1
|
753
|
+
end
|
754
|
+
soa_data.join " "
|
755
|
+
end
|
756
|
+
|
757
|
+
def adjust_change_sort_order order
|
758
|
+
return nil if order.nil?
|
759
|
+
if order.to_s.downcase.start_with? "d"
|
760
|
+
"descending"
|
761
|
+
else
|
762
|
+
"ascending"
|
763
|
+
end
|
764
|
+
end
|
765
|
+
end
|
766
|
+
end
|
767
|
+
end
|
768
|
+
end
|