dyntool 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+