dyntool 0.0.2

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.
Files changed (2) hide show
  1. data/lib/dyntool.rb +769 -0
  2. metadata +62 -0
data/lib/dyntool.rb ADDED
@@ -0,0 +1,769 @@
1
+ #!/usr/bin/ruby
2
+ require 'rubygems'
3
+ require 'net/https'
4
+ require 'uri'
5
+ require 'json'
6
+ require 'ipaddr'
7
+ require 'highline/import'
8
+ ### class for loading and retrieving configuration from dyn.yml
9
+ class LoadConfig
10
+ def SetConfFile=( confFile )
11
+ @confFile = confFile
12
+ end
13
+ def GetHandler
14
+ @conf = YAML.load_file(@confFile)
15
+ end
16
+ def GetDcs
17
+ @dcs = @conf['sites']['names']
18
+ end
19
+ def GetRegions
20
+ @regions = @conf['regions']['names']
21
+ end
22
+ def GetIPs(provider)
23
+ @ips = @conf['providers'][provider]
24
+ end
25
+ def GetProviders
26
+ @providers = @conf['providers']['names']
27
+ end
28
+ def GetDcProviders(dc)
29
+ @dcproviders = @conf['sites'][dc]
30
+ end
31
+ def GetProvierIP(provider)
32
+ @providerip = @conf['providers'][provider]
33
+ end
34
+ def GetCountries(region)
35
+ @countries = @conf['regions'][region]
36
+ end
37
+ def GetDcsEnabled(region)
38
+ @dcs = @conf['enable'][region]
39
+ end
40
+ def GetIpLabel(ip)
41
+ @iplabel = @conf['ips'][ip]['label']
42
+ end
43
+ def GetIpWeight(ip,region)
44
+ @weight = @conf['ips'][ip]['weight'][region]
45
+ end
46
+ end
47
+ ## Getting authentication creds from users
48
+ class Authentication
49
+ # Getting creds from user to authenticate upon dyn
50
+ def AuthUser()
51
+ @creds = []
52
+ @username = ask("Enter your username: ") { |q| q.echo = true }
53
+ @password = ask("Enter your password: ") { |q| q.echo = "*" }
54
+ @creds << @username
55
+ @creds << @password
56
+ return(@creds)
57
+ end
58
+ # check if dyn.yaml configuration is same as commited in svn
59
+ def SvnChk()
60
+ @svn_chk=`svn stat dyn.yaml`
61
+ if @svn_chk != ""
62
+ puts "Your dyn.yaml is not identical to the svn copy, or not exist."
63
+ puts "Run \"svn up\" before using this tool"
64
+ exit 2
65
+ end
66
+ end
67
+ end
68
+ ### class for validating command line parameters and direct to relevant action
69
+ class Parameters
70
+ def SetArgs=( argv )
71
+ @ARGV = argv
72
+ @sconf = LoadConfig.new()
73
+ @sconf.SetConfFile = "dyn.yml"
74
+ @sconf.GetHandler
75
+ end
76
+ # Opening Session to dyn using creds from the command line
77
+ def OpenTheSession(customer,user,password)
78
+ puts "opening a session to DYN"
79
+ @session = Restcall.new()
80
+ @session.OpenSession(customer,user,password)
81
+ end
82
+ # closing dyn session
83
+ def CloseTheSession()
84
+ puts "Closing DYN session"
85
+ @session.CloseSession()
86
+ end
87
+ # Routing the validation upon the relevant operation
88
+ def Parameters(type)
89
+ @operate = OperateDyn.new()
90
+ @params = case type
91
+ when "main_operation" then @operations = [ "add", "del", "shift", "generate", "get", "change", "revert" ]
92
+ when "add" then ValidateAdd()
93
+ when "change" then ValidateChange()
94
+ when "del" then ValidateDel()
95
+ when "shift" then ValidateShift()
96
+ when "generate" then ValidateGenerate()
97
+ when "get" then ValidateGet()
98
+ when "revert" then ValidateRevert()
99
+ end
100
+ end
101
+ # validating revert to current yml configuration
102
+ def ValidateRevert()
103
+ @services = @session.GetServices()
104
+ ValidateServiceExist(@services,@ARGV[2])
105
+ CompareGeo(@ARGV[2])
106
+ AskUser()
107
+ ValidateZone(@ARGV[1])
108
+ @operate.SetOperation("RevertGeo")
109
+ @operate.SetSession(@session)
110
+ @operate.SetArgs(@ARGV[1],@ARGV[2])
111
+
112
+ end
113
+ # Get approval from user to revert/shift after reviewing the changes
114
+ def AskUser()
115
+ HighLine.track_eof = false
116
+ @answer = ask("Are you sure you want to revert? (yes) ") { |q| q.echo = true }
117
+ if @answer != "yes"
118
+ exit 2
119
+ end
120
+ end
121
+ # Checking if the parameter is valid, if not return usage
122
+ def ValidateParams(arg)
123
+ if ! @operations.include? arg
124
+ DisplayUsage()
125
+ else
126
+ @valid = arg
127
+ end
128
+ end
129
+ # Validating the get operation, and setting the relevant arguments in OperateDyn object
130
+ def ValidateGet()
131
+ case @ARGV[1]
132
+ when "services" then @operate.SetOperation("GetServices")
133
+ @operate.SetSession(@session)
134
+ when "node" then @operate.SetOperation("GetNodeService")
135
+ @operate.SetArgs(@ARGV[2])
136
+ @operate.SetSession(@session)
137
+ when "cname" then ValidateZone(@ARGV[2])
138
+ ValidateFqdn(@ARGV[2],@ARGV[3],"true")
139
+ @operate.SetOperation("GetCnameService")
140
+ @operate.SetArgs(@ARGV[2],@ARGV[3])
141
+ @operate.SetSession(@session)
142
+ end
143
+ end
144
+ # Check type of record to add, the zone exist, then upon type, check arguments and set the required add operation
145
+ def ValidateAdd
146
+ ValidateType(@ARGV[1])
147
+ ValidateZone(@ARGV[2])
148
+ case @ARGV[1]
149
+ when "a" then ValidateFqdn(@ARGV[2],@ARGV[3],"false")
150
+ ValidateIP(@ARGV[4])
151
+ @operate.SetOperation("AddARecord")
152
+ @operate.SetSession(@session)
153
+ @operate.SetArgs(@ARGV[2],@ARGV[3],@ARGV[4])
154
+ when "cname" then ValidateFqdn(@ARGV[2],@ARGV[3],"true")
155
+ ValidateFqdn(@ARGV[2],@ARGV[4],"false")
156
+ @operate.SetOperation("AddCnameRecord")
157
+ @operate.SetSession(@session)
158
+ @operate.SetArgs(@ARGV[2],@ARGV[3],@ARGV[4])
159
+ when "txt" then ValidateFqdn(@ARGV[2],@ARGV[3],"true")
160
+ @operate.SetOperation("AddTxtRecord")
161
+ @operate.SetSession(@session)
162
+ @operate.SetArgs(@ARGV[2],@ARGV[3],@ARGV[4])
163
+ end
164
+ end
165
+ def ValidateChange
166
+ ValidateType(@ARGV[1])
167
+ ValidateZone(@ARGV[2])
168
+ case @ARGV[1]
169
+ when "cname" then ValidateFqdn(@ARGV[2],@ARGV[3],"true")
170
+ ValidateFqdn(@ARGV[2],@ARGV[4],"true")
171
+ @operate.SetOperation("ChangeCnameRecord")
172
+ @operate.SetSession(@session)
173
+ @operate.SetArgs(@ARGV[2],@ARGV[3],@ARGV[4])
174
+ end
175
+ end
176
+ # Validating the delete arguments: zone and fqdn exist, in case of service that the service exist
177
+ def ValidateDel
178
+ case @ARGV[1]
179
+ when "node" then ValidateZone(@ARGV[2])
180
+ ValidateFqdn(@ARGV[2],@ARGV[3],"true")
181
+ @operate.SetOperation("DeleteNode")
182
+ @operate.SetSession(@session)
183
+ @operate.SetArgs(@ARGV[2],@ARGV[3])
184
+ when "service" then ValidateZone(@ARGV[3])
185
+ @services = @session.GetServices()
186
+ ValidateServiceExist(@services,@ARGV[2])
187
+ @operate.SetOperation("DeleteService")
188
+ @operate.SetSession(@session)
189
+ @operate.SetArgs(@ARGV[2],@ARGV[3])
190
+ end
191
+ end
192
+ def ValidateShift
193
+ @sdcs = @sconf.GetDcs
194
+ @sproviders = @sconf
195
+ @services = @session.GetServices()
196
+ ValidateServiceExist(@services,@ARGV[1])
197
+ ValidateZone(@ARGV[2])
198
+ @resource = ValidateShiftArgs(@ARGV[3],@ARGV[6],@ARGV[4])
199
+ case @resource
200
+ when "dc" then @dcs = GetArgsDcs(@ARGV[5],@sdcs)
201
+ @dcs_list = @dcs.join("-")
202
+ @operate.SetOperation("ShiftTraffic")
203
+ @operate.SetSession(@session)
204
+ @operate.SetArgs(@ARGV[1],@ARGV[4],@ARGV[5],@dcs_list,@ARGV[2])
205
+ when "provider" then ValidateProvider(@ARGV[5],@ARGV[7])
206
+ @operate.SetOperation("ShiftTraffic")
207
+ @operate.SetSession(@session)
208
+ @operate.SetArgs(@ARGV[1],@ARGV[4],@ARGV[5],@ARGV[7],@ARGV[2])
209
+ end
210
+ end
211
+ # Get dcs list from arguments
212
+ def GetArgsDcs(from,sdcs)
213
+ @c = 0
214
+ @dcs = []
215
+ @sdcs = sdcs
216
+ @ARGV.each do |arg|
217
+ @c += 1
218
+ if (@c > 7)
219
+ if (! @sdcs.include? "#{arg}")
220
+ abort("The dcs is not in the configuration dcs list")
221
+ else
222
+ @dcs << "#{arg}"
223
+ end
224
+ end
225
+ end
226
+ if @dcs.include? "#{from}"
227
+ abort("destination dc/s cant include source dc")
228
+ end
229
+ if @dcs.empty?
230
+ abort("List of dcs cant be empty")
231
+ end
232
+ return (@dcs)
233
+ end
234
+ # checking arguments for shift traffic
235
+ def ValidateShiftArgs(from,to,resource)
236
+ if (("#{from}" != "from") || ("#{to}" != "to") || (("#{resource}" != "dc") && ("#{resource}" != "provider")))
237
+ DisplayUsage()
238
+ else
239
+ return("#{resource}")
240
+ end
241
+ end
242
+ # check that service given as argument exist in dyn
243
+ def ValidateServiceExist(services,geo)
244
+ @services = services
245
+ if ! @services.include? "#{geo}"
246
+ abort("The geo services list does not include the geo entered")
247
+ end
248
+ end
249
+ def ValidateGenerate
250
+ ValidateServiceFormat(@ARGV[1])
251
+ ValidateZone(@ARGV[2])
252
+ ValidateFqdn(@ARGV[2],@ARGV[3],"false")
253
+ @operate.SetOperation("GenerateGeoNode")
254
+ @operate.SetSession(@session)
255
+ @operate.SetArgs(@ARGV[1],@ARGV[2],@ARGV[3])
256
+ end
257
+ def ValidateServiceFormat(service)
258
+ @service = service
259
+ if ! (@service.match /geo[0][1-9]|geo[1-4][0-9]/)
260
+ puts "service name must match geo(01-49) structure"
261
+ DisplayUsage()
262
+ end
263
+ end
264
+ def ValidateZone(zone)
265
+ puts "Validating zone: " + zone
266
+ @session.CheckZone(zone)
267
+ end
268
+ def ValidateFqdn(zone,node,state)
269
+ puts "Validating the host: " + node + " in zone: " + zone
270
+ @session.CheckNodes(zone,node,state)
271
+ end
272
+ # checking that ip is in a valid format
273
+ def ValidateIP(ip)
274
+ puts "Validating the IP address: " + ip
275
+ if (IPAddr.new(ip) rescue nil).nil?
276
+ puts "IP Address is not valid"
277
+ DisplayUsage()
278
+ end
279
+ end
280
+ # validate that site exist in yaml
281
+ def ValidateDC(site)
282
+ if ! @conf.GetDcs.include? site
283
+ puts "The DC does not exist"
284
+ DisplayUsage()
285
+ end
286
+ end
287
+ # validate that provider given as argument actually exist in yaml
288
+ def ValidateProvider(srcprovider,dstprovider)
289
+ @providers = @sconf.GetProviders
290
+ @dcsrc = srcprovider.split('_')
291
+ @dcdst = dstprovider.split('_')
292
+ if ((! @providers.include? srcprovider) || (! @providers.include? dstprovider))
293
+ abort("The Provider does not exist")
294
+ end
295
+ if (srcprovider == dstprovider)
296
+ abort("Source providers cant be same as destination provider")
297
+ end
298
+ if (@dcsrc[1] != @dcdst[1])
299
+ abort("Cant shift traffic between providers in different dcs")
300
+ end
301
+ end
302
+ # check that record type is in the allow list
303
+ def ValidateType(type)
304
+ @types = [ "a", "cname", "txt" ]
305
+ if ! @types.include? type
306
+ puts "Not a valid record type"
307
+ DisplayUsage()
308
+ end
309
+ end
310
+ # display script usage
311
+ def DisplayUsage
312
+ puts "Usage of dynamo.rb cmd"
313
+ puts "**********************"
314
+ puts "**********************"
315
+ puts "(add)"
316
+ puts "********************"
317
+ puts "- a zone fqdn(a) ip , example: dynamo.rb add a example.com mynode.example.com 11.12.13.14"
318
+ puts "- cname zone fqdn(a) fqdn(cname) , example: dynamo.rb add cname example.com mynode.example.com mycnamenode.example.com"
319
+ puts "- txt zone fqdn(a) \"some text\" , example: dynamo.rb add txt example.com mynode.example.com \"this is some text\""
320
+ puts "(del)"
321
+ puts "********************"
322
+ puts "- del zone node fqdn(node) - node can be a,cname,txt,geonode,etc , example: dynamo.rb del node example.com mynode.example.com"
323
+ puts "- del service geoservice zone, example: dynamo.rb del service geo17 example.com"
324
+ puts "(change)"
325
+ puts "********************"
326
+ puts "- change cname zone cname newfqdn, example: dynamo.rb change cname example.com mycnamenode.example.com test19.example.com"
327
+ puts "(generate)"
328
+ puts "geo service from yaml"
329
+ puts "********************"
330
+ puts "- generate geoservice zone geonode, example: dynamo.rb generate geo11 example.com test11.example.com"
331
+ puts "(shift)"
332
+ puts "********************"
333
+ puts " - shift geoservice zone from dc/provider to dc/dcs/provider(in same dc)"
334
+ puts "example1(shift traffic from chidc1 to nydc1): dynamo.rb shift geo11 example.com from dc chidc1 to nydc1"
335
+ puts "example1(shift traffic from chidc1 to nydc1 and ladc1): dynamo.rb shift geo11 example.com from dc chidc1 to nydc1 ladc1"
336
+ puts "example3(shift traffic from amc_chi to inap_chi): dynamo.rb shift geo15 example.com from provider amc_chi to inap_chi"
337
+ puts "(revert)"
338
+ puts "go back to state of yaml configuration"
339
+ puts "*******************"
340
+ puts "- revert zone geoservice, example: dynamo.rb revert example.com geo15"
341
+ puts "(get)"
342
+ puts " - get services (get all geo services), example: dynamo.rb get services"
343
+ puts " - get node geonode, example: dynamo.rb get node test1.example.com"
344
+ puts " - get cname zone cname, example: dynamo.rb get cname example.com mycnamenode.example.com"
345
+ exit(2)
346
+ end
347
+ # compare service geo data of current state vs yaml file
348
+ def CompareGeo(service)
349
+ @current_data = @session.GetGeoData(service)
350
+ @current_groups = []
351
+ @yaml_groups = []
352
+ @yaml_total_groups = []
353
+ @current_total_groups = []
354
+ @current_data['data']['groups'].each do |group|
355
+ @current_groups << group['name']
356
+ end
357
+ @yaml_groups = @sconf.GetRegions
358
+ @current_total_groups = @current_groups - @yaml_groups
359
+ @yaml_total_groups = @yaml_groups - @current_groups
360
+ if (! @yaml_total_groups.empty?)
361
+ puts "Diffrence in regions list:"
362
+ puts "+Yaml #{@yaml_total_groups}"
363
+ end
364
+ if (! @current_total_groups.empty?)
365
+ puts "Diffrence in regions list:"
366
+ puts "+Current #{@current_total_groups}"
367
+ end
368
+ @current_data['data']['groups'].each do |region|
369
+ @yaml_ips = []
370
+ @current_ips = []
371
+ @yaml_total_ips = []
372
+ @current_total_ips = []
373
+ @name = region['name']
374
+ region['rdata']['a_rdata'].each do |rdata|
375
+ @current_ips << rdata['address']
376
+ end
377
+ @sconf.GetDcsEnabled(@name).each do |dc|
378
+ @providers = @sconf.GetDcProviders(dc)
379
+ @providers.each do |provider|
380
+ @sconf.GetIPs(provider).each do |ips|
381
+ ips.each do |ip|
382
+ @yaml_ips << ip
383
+ end
384
+ end
385
+ end
386
+ end
387
+ @current_total_ips = @current_ips - @yaml_ips
388
+ @yaml_total_ips = @yaml_ips - @current_ips
389
+ if ! @yaml_total_ips.empty?
390
+ PrintDiff(@name,@yaml_total_ips,"IP","Yaml")
391
+ end
392
+ if ! @current_total_ips.empty?
393
+ PrintDiff(@name,@current_total_ips,"IP","Current")
394
+ end
395
+ @yaml_countries = []
396
+ @current_countries = []
397
+ @yaml_total_countries = []
398
+ @current_total_countries = []
399
+ region['countries'].each do |country|
400
+ @current_countries << country
401
+ end
402
+ @sconf.GetCountries(@name).each do |country|
403
+ @yaml_countries << country
404
+ end
405
+ @yaml_total_countries = @yaml_countries - @current_countries
406
+ @current_total_countries = @current_countries - @yaml_countries
407
+ if ! @yaml_total_countries.empty?
408
+ PrintDiff(@name,@yaml_total_countries,"Countries","Yaml")
409
+ end
410
+ if ! @current_total_countries.empty?
411
+ PrintDiff(@name,@current_total_countries,"Countries","Current")
412
+ end
413
+ @current_weights = []
414
+ @yaml_weights = []
415
+ region['weight']['a_weight'].each do |weight|
416
+ @current_weights << weight
417
+ end
418
+ @i = 0
419
+ @yaml_ips.each do |ip|
420
+ @yaml_weights << @sconf.GetIpWeight(ip,@name)
421
+ end
422
+ @yaml_weights.each do |weight|
423
+ if weight.to_s != @current_weights[@i].to_s
424
+ puts "##############################################################################"
425
+ puts "There is weight difference in region #{@name}, IP: #{@yaml_ips[@i]}"
426
+ puts "Yaml weight is: #{weight}"
427
+ puts "Current weight is: #{@current_weights[@i]}"
428
+ puts "##############################################################################"
429
+ @i += 1
430
+ end
431
+ end
432
+ end
433
+ end
434
+ # gets region, list of differencesm, what is different and where and print it out
435
+ def PrintDiff(region,list,name,symbol)
436
+ puts "Diffrence in #{name} list:"
437
+ puts "Region #{region}:"
438
+ puts "+#{symbol} #{name}:"
439
+ list.each do |item|
440
+ puts "#{item}"
441
+ end
442
+ end
443
+ end
444
+ class OperateDyn
445
+ # set the relevant operation
446
+ def SetOperation(op)
447
+ @@op=op
448
+ end
449
+ # set the arguments
450
+ def SetArgs(*args)
451
+ @@args=args
452
+ end
453
+ # set the session to dyn
454
+ def SetSession(session)
455
+ @@session=session
456
+ end
457
+ # run the operation set by setoperation method in the validation phase
458
+ def RunOP
459
+ case(@@op)
460
+ when "AddARecord" then @@session.AddARecord(@@args[0],@@args[1],@@args[2])
461
+ when "DeleteNode" then @@session.DeleteNode(@@args[0],@@args[1])
462
+ when "DeleteService" then @@session.DeleteService(@@args[0],@@args[1])
463
+ when "AddCnameRecord" then @@session.AddCnameRecord(@@args[0],@@args[1],@@args[2],"post")
464
+ when "AddTxtRecord" then @@session.AddTxtRecord(@@args[0],@@args[1],@@args[2])
465
+ when "ChangeCnameRecord" then @@session.AddCnameRecord(@@args[0],@@args[1],@@args[2],"put")
466
+ when "GenerateGeoNode" then @record_data = BuildService(@@args[0],"","","")
467
+ @@session.GenerateGeoService(@@args[0],@@args[1],@record_data,"create")
468
+ @@session.GenerateGeoNode(@@args[0],@@args[1],@@args[2])
469
+ when "GetServices" then @services = @@session.GetServices()
470
+ puts "Here is the list of Geo services:"
471
+ puts @services
472
+ when "GetNodeService" then @services = @@session.GetServices()
473
+ GetGeoNodeService(@services,@@args[0])
474
+ when "GetCnameService" then @services = @@session.GetServices()
475
+ @geonode = @@session.GetCnameService(@@args[1],@@args[0])
476
+ GetGeoNodeService(@services,@geonode)
477
+ when "ShiftTraffic" then @record_data = BuildService(@@args[0],@@args[1],@@args[2],@@args[3])
478
+ @@session.GenerateGeoService(@@args[0],@@args[4],@record_data,"update")
479
+ when "RevertGeo" then @record_data = BuildService(@@args[0],"","","")
480
+ @@session.GenerateGeoService(@@args[1],@@args[0],@record_data,"update")
481
+ end
482
+ end
483
+ def GetOP
484
+ return(@@op)
485
+ end
486
+ def GetArgs
487
+ return(@@args)
488
+ end
489
+ def GetGeoNodeService(services,node)
490
+ @services = services
491
+ @services.each do |service|
492
+ puts "Checking If node #{node} is attached to service #{service}"
493
+ @result = @@session.CheckNodeService(service,node)
494
+ end
495
+ end
496
+ # building the record_data hash for generating geo service in dyn API
497
+ def BuildService(service,flag,shiftfrom,shifto)
498
+ puts "Generating the geo service data"
499
+ @@conf = LoadConfig.new()
500
+ @@conf.SetConfFile = "dyn.yml"
501
+ @@conf.GetHandler
502
+ @regions = @@conf.GetRegions
503
+ @dcs = @@conf.GetDcs
504
+ @shiftfrom = []
505
+ @shifto = []
506
+ @shiftfrom << shiftfrom
507
+ @shifto = shifto.split("-")
508
+ @region_hash = []
509
+ @i = 0
510
+ @regions.each do |region|
511
+ @ips = []
512
+ @labels = []
513
+ @weights = []
514
+ @countries = @@conf.GetCountries(region)
515
+ @dcs = @@conf.GetDcsEnabled(region)
516
+ if (flag == "dc")
517
+ if @dcs.include? "#{shiftfrom}"
518
+ @dcs = @dcs - @shiftfrom
519
+ @dcs = @dcs + @shifto
520
+ end
521
+ end
522
+ @dcs.each do |dc|
523
+ @providers = @@conf.GetDcProviders(dc)
524
+ if (flag == "provider")
525
+ if @providers.include? "#{shiftfrom}"
526
+ @providers = @providers - @shiftfrom
527
+ @providers = @providers + @shifto
528
+ end
529
+ end
530
+ @providers.each do |provider|
531
+ @ips += @@conf.GetProvierIP(provider)
532
+ end
533
+ @ips = @ips.uniq
534
+ end
535
+ @ips_len = @ips.size
536
+ if @ips_len == 0
537
+ abort("The region #{region}, has empty ip list. aborting....")
538
+ end
539
+ @ips_hash = BuildIPs(@ips)
540
+ @i += 1
541
+ @ips.each do |ip|
542
+ @label = @@conf.GetIpLabel(ip)
543
+ @weight = @@conf.GetIpWeight(ip,region)
544
+ @labels << "#{@label}"
545
+ @weights << "#{@weight}"
546
+ end
547
+ @labels = @labels.uniq
548
+ @region_hash[@i] = { :name => "#{region}", :label => { :a_label => @labels}, :weight => { :a_weight => @weights }, :serve_count => { :a_serve_count => @ips_len }, :countries => @countries, :rdata => @ips_hash }
549
+ end
550
+ @record_data = { :name => "#{service}", :groups => [ @region_hash[1],@region_hash[2],@region_hash[3],@region_hash[4],@region_hash[5],@region_hash[6],@region_hash[7],@region_hash[8],@region_hash[9] ]}
551
+ return(@record_data)
552
+ end
553
+ # building the ip hash
554
+ def BuildIPs(ips)
555
+ @ips_hash = "{ :a_rdata => ["
556
+ ips.each do |ip|
557
+ @ips_hash << "{ :address => \"#{ip}\"},"
558
+ end
559
+ @ips_hash = @ips_hash.chop
560
+ @ips_hash << "]}"
561
+ @ips_hash = eval(@ips_hash)
562
+ return(@ips_hash)
563
+ end
564
+
565
+ end
566
+ # contains restcalls to get and set data upon dyn API
567
+ class Restcall
568
+ # Open a session to syn Restful API
569
+ def OpenSession(customer,username,password)
570
+ # Set up our HTTP object with the required host and path
571
+ @url = URI.parse('https://api2.dynect.net/REST/Session/')
572
+ @headers = { "Content-Type" => 'application/json' }
573
+ @http = Net::HTTP.new(@url.host, @url.port)
574
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
575
+ @http.use_ssl = true
576
+ @session_data = { :customer_name => customer, :user_name => username, :password => password }
577
+ @resp, @data = @http.post(@url.path, @session_data.to_json, @headers)
578
+ @result = JSON.parse(@data)
579
+ if @result['status'] == 'success'
580
+ @auth_token = @result['data']['token']
581
+ else
582
+ puts "Command Failed:\n"
583
+ # the messages returned from a failed command are a list
584
+ @result['msgs'][0].each{|key, value| print key, " : ", value, "\n"}
585
+ exit(2)
586
+ end
587
+ return(@result)
588
+ end
589
+ # closing dyn session
590
+ def CloseSession
591
+ @url = URI.parse('https://api2.dynect.net/REST/Session/')
592
+ @resp, @data = @http.delete(@url.path, @headers)
593
+ end
594
+ # Check if the zone exist in dyn configuration
595
+ def CheckZone(zone)
596
+ @url = URI.parse("https://api2.dynect.net/REST/Zone/#{zone}/")
597
+ GetDyn()
598
+ if @result['status'] != "success"
599
+ abort("The zone name is invalid")
600
+ end
601
+ end
602
+ # Get List of nodes to compare with given node
603
+ def CheckNodes(zone,node,state)
604
+ @url = URI.parse("https://api2.dynect.net/REST/NodeList/#{zone}/")
605
+ GetDyn()
606
+ @nodes = []
607
+ @result['data'].each do |fqdn|
608
+ @nodes << fqdn
609
+ end
610
+ if state == "true"
611
+ if ! @nodes.include? node
612
+ abort("The node you entered does not exist")
613
+ end
614
+ elsif state == "false"
615
+ if @nodes.include? node
616
+ abort("The node you entered already exist")
617
+ end
618
+ end
619
+ end
620
+ def CheckARecord(zone,arecord)
621
+ @dynquery = URI.parse("https://api2.dynect.net/REST/ARecord/#{zone}/#{arecord}")
622
+ GetDyn()
623
+ end
624
+ def CheckCnameRecord(zone,cname)
625
+ @dynquery = URI.parse("https://api2.dynect.net/REST/CNAMERecord/#{zone}/#{cname}")
626
+ GetDyn()
627
+ end
628
+ # Adding new A record
629
+ def AddARecord(zone,arecord,ip)
630
+ @url = URI.parse("https://api2.dynect.net/REST/ARecord/#{zone}/#{arecord}")
631
+ @record_data = { :rdata => { :address => "#{ip}" }, :ttl => "0" }
632
+ PostDyn()
633
+ PublishDyn(zone)
634
+ end
635
+ # Generating or modifying Geo service
636
+ def GenerateGeoService(service,zone,record_data,flag)
637
+ @record_data = record_data
638
+ @url = URI.parse("https://api2.dynect.net/REST/Geo/#{service}/")
639
+ if flag == "create"
640
+ puts "Creating geo service"
641
+ PostDyn()
642
+ else
643
+ puts "Changing geo service"
644
+ PutDyn()
645
+ end
646
+ PublishDyn(zone)
647
+ end
648
+ # Generating geo node and attaching to service
649
+ def GenerateGeoNode(service,zone,geonode)
650
+ puts "Creating geo node"
651
+ @url = URI.parse("https://api2.dynect.net/REST/GeoNode/#{service}")
652
+ @record_data = { :fqdn => "#{geonode}", :zone => "#{zone}" }
653
+ PostDyn()
654
+ PublishDyn(zone)
655
+ end
656
+ # Adding Cname record
657
+ def AddCnameRecord(zone,cname,arecord,flag)
658
+ @url = URI.parse("https://api2.dynect.net/REST/CNAMERecord/#{zone}/#{cname}")
659
+ @record_data = { :rdata => { :cname => "#{arecord}" }, :ttl => "0" }
660
+ if (flag == "post")
661
+ puts "Adding cname record"
662
+ PostDyn()
663
+ elsif (flag == "put")
664
+ puts "Changing cname record"
665
+ PutDyn()
666
+ end
667
+ PublishDyn(zone)
668
+ end
669
+ # Adding txt record
670
+ def AddTxtRecord(zone,arecord,txt)
671
+ @url = URI.parse("https://api2.dynect.net/REST/TXTRecord/#{zone}/#{arecord}")
672
+ @record_data = { :rdata => { :txtdata => "#{txt}" }, :ttl => "0" }
673
+ PostDyn()
674
+ PublishDyn(zone)
675
+ end
676
+ # deleting node
677
+ def DeleteNode(zone,fqdn)
678
+ @url = URI.parse("https://api2.dynect.net/REST/Node/#{zone}/#{fqdn}")
679
+ DeleteDyn()
680
+ PublishDyn(zone)
681
+ end
682
+ # deleting service
683
+ def DeleteService(service,zone)
684
+ @url = URI.parse("https://api2.dynect.net/REST/Geo/#{service}/")
685
+ DeleteDyn()
686
+ PublishDyn(zone)
687
+ end
688
+ # get method to dyn
689
+ def GetDyn()
690
+ puts "Getting data from dyn"
691
+ @headers = { "Content-Type" => 'application/json', 'Auth-Token' => @auth_token }
692
+ @resp, @data = @http.get(@url.path, @headers)
693
+ @result = JSON.parse(@data)
694
+ return(@result)
695
+ end
696
+ # post method to dyn
697
+ def PostDyn()
698
+ @headers = { "Content-Type" => 'application/json', 'Auth-Token' => @auth_token }
699
+ @resp, @data = @http.post(@url.path, @record_data.to_json, @headers)
700
+ end
701
+ # put method to dyn
702
+ def PutDyn()
703
+ @headers = { "Content-Type" => 'application/json', 'Auth-Token' => @auth_token }
704
+ @resp, @data = @http.put(@url.path, @record_data.to_json, @headers)
705
+ end
706
+ def DeleteDyn()
707
+ @headers = { "Content-Type" => 'application/json', 'Auth-Token' => @auth_token }
708
+ @resp, @data = @http.delete(@url.path, @headers)
709
+ puts @data
710
+ end
711
+ # publishing data to dyn
712
+ def PublishDyn(zone)
713
+ puts "Publishing to Dyn"
714
+ @url = URI.parse("https://api2.dynect.net/REST/Zone/#{zone}/")
715
+ @publish_data = { "publish" => "true" }
716
+ @resp, @data = @http.put(@url.path, @publish_data.to_json, @headers)
717
+ @result = JSON.parse(@data)
718
+ puts @result['status']
719
+ end
720
+ # return list of geo service defined for the account
721
+ def GetServices()
722
+ puts "Getting the list of geo services"
723
+ @url = URI.parse("https://api2.dynect.net/REST/Geo/")
724
+ @result = GetDyn()
725
+ @services = @result['data']
726
+ @gservices = []
727
+ @services.each do |service|
728
+ @gservices << service.gsub(/\/REST\/Geo\/|\//,"")
729
+ end
730
+ return(@gservices)
731
+ end
732
+ def GetGeoData(service)
733
+ puts "Getting geo data"
734
+ @url = URI.parse("https://api2.dynect.net/REST/Geo/#{service}")
735
+ @result = GetDyn()
736
+ return(@result)
737
+ end
738
+ # checking to which gee service geo node is attached
739
+ def CheckNodeService(service,fqdn)
740
+ @url = URI.parse("https://api2.dynect.net/REST/Geo/#{service}")
741
+ @result = GetDyn()
742
+ @nodes = @result['data']['nodes']
743
+ @nodes.each do |node|
744
+ if (node['fqdn'] == "#{fqdn}")
745
+ puts "Yes!!!"
746
+ puts "here are all the nodes that linked to that service:"
747
+ PrintNodes(@nodes)
748
+ exit(0)
749
+ end
750
+ end
751
+ end
752
+ # Gets cname and zone and return the geo node that the cname point to
753
+ def GetCnameService(cname,zone)
754
+ @url = URI.parse("https://api2.dynect.net/REST/CNAMERecord/#{zone}/#{cname}/")
755
+ @result = GetDyn()
756
+ @cn_data = @result['data']
757
+ @cn_array = @cn_data[0].split("/")
758
+ @id = @cn_array.last
759
+ @url = URI.parse("https://api2.dynect.net/REST/CNAMERecord/#{zone}/#{cname}/#{@id}")
760
+ @result = GetDyn()
761
+ @geonode = @result['data']['rdata']['cname'].chomp('.')
762
+ return(@geonode)
763
+ end
764
+ def PrintNodes(nodes)
765
+ nodes.each do |node|
766
+ puts node['fqdn']
767
+ end
768
+ end
769
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dyntool
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Ariel Moskovich
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-07-23 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Tool for manipulation dyn dns records
22
+ email: ariel@outbrain.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/dyntool.rb
31
+ has_rdoc: true
32
+ homepage: http://rubygems.org/gems/dyntool
33
+ licenses: []
34
+
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.6
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Dyn tools
61
+ test_files: []
62
+