murakumo 0.3.5 → 0.3.6

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.
data/README CHANGED
@@ -19,39 +19,39 @@ https://bitbucket.org/winebarrel/murakumo
19
19
  shell> murakumo-install-init-script
20
20
  shell> /etc/init.d/murakumo configure
21
21
  shell> /etc/init.d/murakumo start
22
- shell> dig @127.0.0.1 <any_hostname>
22
+ shell> dig @127.0.0.1 <hostname>
23
23
 
24
24
  == Example
25
25
  === display of a list of a record
26
26
 
27
27
  shell> mrkmctl -L
28
- IP address TTL Priority Activity Hostname
29
- --------------- ------ -------- -------- ----------
30
- 10.11.12.13 60 Origin Active my-host
28
+ IP address TTL Priority Weight Activity Hostname
29
+ --------------- ------ -------- ------ -------- ----------
30
+ 10.11.12.13 60 Origin 0 Active my-host
31
31
 
32
32
  === addition of a record
33
33
 
34
- shell> mrkmctl -A foo.bar,300,master
34
+ shell> mrkmctl -A foo.bar,300,master,100
35
35
  shell> mrkmctl -L
36
- IP address TTL Priority Activity Hostname
37
- --------------- ------ -------- -------- ----------
38
- 10.11.12.13 60 Origin Active my-host
39
- 10.11.12.13 300 Master Active foo.bar
36
+ IP address TTL Priority Weight Activity Hostname
37
+ --------------- ------ -------- ------ -------- ----------
38
+ 10.11.12.13 60 Origin 0 Active my-host
39
+ 10.11.12.13 300 Master 100 Active foo.bar
40
40
 
41
41
  === deletion of a record
42
42
 
43
43
  shell> mrkmctl -D foo.bar
44
44
  shell> mrkmctl -L
45
- IP address TTL Priority Activity Hostname
46
- --------------- ------ -------- -------- ----------
47
- 10.11.12.13 60 Origin Active my-host
45
+ IP address TTL Priority Weight Activity Hostname
46
+ --------------- ------ -------- ------ -------- ----------
47
+ 10.11.12.13 60 Origin 0 Active my-host
48
48
 
49
49
  === addition of a node
50
50
 
51
51
  shell> mrkmctl -a 10.11.12.14
52
52
  shell> mrkmctl -L
53
- IP address TTL Priority Activity Hostname
54
- --------------- ------ -------- -------- ----------
55
- 10.11.12.13 60 Origin Active my-host
56
- 10.11.12.14 60 Origin Active other-host
53
+ IP address TTL Priority Weight Activity Hostname
54
+ --------------- ------ -------- ------ -------- ----------
55
+ 10.11.12.13 60 Origin 0 Active my-host
56
+ 10.11.12.14 60 Origin 0 Active other-host
57
57
 
@@ -72,6 +72,11 @@ max-ip-num: 8
72
72
  #domain: ap-northeast-1.compute.internal
73
73
  #enable-cache: true
74
74
 
75
+ #name-includes: ^app-\d+$, ^db-\d+$
76
+ #name-excludes:
77
+ #addr-includes: ^10\..*
78
+ #addr-excludes:
79
+
75
80
  #notification:
76
81
  # host: my.smtp.server
77
82
  # #port: 25
@@ -85,13 +90,13 @@ max-ip-num: 8
85
90
  # #open_timeout: 30
86
91
  # #read_timeout: 60
87
92
 
88
- # Ip address, hostname, ttl
93
+ # ip address, hostname, ttl
89
94
  host: $ip_addr, $hostname, 60
90
95
 
91
- # alias hostname, ttl, master/secondary/backup
96
+ # alias hostname, ttl, master/secondary/backup, weight
92
97
  #alias:
93
- # - foo,60,master
94
- # - bar,60,backup
98
+ # - foo,60,master,100
99
+ # - bar,60,backup,100
95
100
 
96
101
  #health-check:
97
102
  # foo:
@@ -12,6 +12,11 @@ max-ip-num: 8
12
12
  #domain: ap-northeast-1.compute.internal
13
13
  #enable-cache: true
14
14
 
15
+ #name-includes: ^app-\d+$, ^db-\d+$
16
+ #name-excludes:
17
+ #addr-includes: ^10\..*
18
+ #addr-excludes:
19
+
15
20
  #notification:
16
21
  # host: my.smtp.server
17
22
  # #port: 25
@@ -25,13 +30,13 @@ max-ip-num: 8
25
30
  # #open_timeout: 30
26
31
  # #read_timeout: 60
27
32
 
28
- # Ip address, hostname, ttl
33
+ # ip address, hostname, ttl
29
34
  host: 10.11.12.13, my-host, 60
30
35
 
31
- # alias hostname, ttl, master/secondary/backup
36
+ # alias hostname, ttl, master/secondary/backup, weight
32
37
  alias:
33
- - foo,60,master
34
- - bar,60,master
38
+ - foo,60,master,100
39
+ - bar,60,master,100
35
40
 
36
41
  health-check:
37
42
  foo:
@@ -35,23 +35,23 @@ begin
35
35
  end
36
36
 
37
37
  r[3] = priority
38
- r[4] = (r[4] == Murakumo::ACTIVE ? 'Active' : 'Inactive')
38
+ r[5] = (r[5] == Murakumo::ACTIVE ? 'Active' : 'Inactive')
39
39
  end
40
40
 
41
41
  if arg.kind_of?(String)
42
- # 引数がある場合はフィルタリング(TTLを除く)
43
- records = records.select {|r| r.values_at(0, 1, 3, 4).any?{|i| i.to_s =~ /\A#{arg.to_s}/i } }
42
+ # 引数がある場合はフィルタリング(TTL、weightを除く)
43
+ records = records.select {|r| r.values_at(0, 1, 3, 5).any?{|i| i.to_s =~ /\A#{arg.to_s}/i } }
44
44
  end
45
45
 
46
46
  if records.empty?
47
47
  puts 'No macth'
48
48
  else
49
49
  puts <<-EOF
50
- IP address TTL Priority Activity Hostname
51
- --------------- ------ --------- -------- ----------
50
+ IP address TTL Priority Weight Activity Hostname
51
+ --------------- ------ --------- ------ -------- ----------
52
52
  EOF
53
53
  records.each do |r|
54
- puts '%-15s %6d %-9s %-8s %s' % r.values_at(0, 2, 3, 4, 1)
54
+ puts '%-15s %6d %-9s %6d %-8s %s' % r.values_at(0, 2, 3, 4, 5, 1)
55
55
  end
56
56
  end
57
57
 
@@ -9,12 +9,12 @@ def mrkmctl_parse_args
9
9
  desc 'displays a list of a record'
10
10
  option :list, '-L', '--list [SEARCH_PHRASE]'
11
11
 
12
- desc 'adds or updates a record: <hostname>[,<TTL>[,{master|secondary|backup}]]'
12
+ desc 'adds or updates a record: <hostname>[,<TTL>[,{master|secondary|backup}[,<weight>]]]'
13
13
  option :add, '-A', '--add RECORD', :type => Array, :multiple => true do |value|
14
- (1 <= value.length and value.length <= 3) or invalid_argument
14
+ (1 <= value.length and value.length <= 4) or invalid_argument
15
15
 
16
16
  value = value.map {|i| i.strip }
17
- hostname, ttl, priority = value
17
+ hostname, ttl, priority, weight = value
18
18
 
19
19
  # hostname
20
20
  /\A[0-9a-z\.\-]+\Z/i =~ hostname or invalid_argument
@@ -26,6 +26,11 @@ def mrkmctl_parse_args
26
26
 
27
27
  # Priority
28
28
  priority.nil? or /\A(master|secondary|backup)\Z/i =~ priority or invalid_argument
29
+
30
+ # Weight
31
+ unless weight.nil? or (/\A\d+\Z/ =~ weight and weight.to_i > 0)
32
+ invalid_argument
33
+ end
29
34
  end
30
35
 
31
36
  desc 'deletes a record'
@@ -80,7 +85,7 @@ def mrkmctl_parse_args
80
85
  if options[:add]
81
86
  options[:add] = options[:add].map do |r|
82
87
  r = r.map {|i| i ? i.to_s.strip : i }
83
- [nil, 60, 'master'].each_with_index {|v, i| r[i] ||= v }
88
+ [nil, 60, 'master', 100].each_with_index {|v, i| r[i] ||= v }
84
89
 
85
90
  priority = case r[2].to_s
86
91
  when /master/i
@@ -92,9 +97,10 @@ def mrkmctl_parse_args
92
97
  end
93
98
 
94
99
  [
95
- r[0], # name
100
+ r[0], # name
96
101
  r[1].to_i, # TTL
97
102
  priority,
103
+ r[3].to_i # weight
98
104
  ]
99
105
  end
100
106
  end
@@ -47,12 +47,12 @@ def murakumo_parse_args
47
47
  end
48
48
  end # :host
49
49
 
50
- desc 'resource record of an alias: <hostname>[,<TTL>[,{master|secondary|backup}]]'
50
+ desc 'resource record of an alias: <hostname>[,<TTL>[,{master|secondary|backup}[, <weight>]]]'
51
51
  option :aliases, '-A', '--alias RECORD', :type => Array, :multiple => true do |value|
52
- (1 <= value.length and value.length <= 3) or invalid_argument
52
+ (1 <= value.length and value.length <= 4) or invalid_argument
53
53
 
54
54
  value = value.map {|i| i.strip }
55
- hostname, ttl, priority = value
55
+ hostname, ttl, priority, weight = value
56
56
 
57
57
  # hostname
58
58
  /\A[0-9a-z\.\-]+\Z/ =~ hostname or invalid_argument
@@ -64,6 +64,11 @@ def murakumo_parse_args
64
64
 
65
65
  # Priority
66
66
  priority.nil? or /\A(master|secondary|backup)\Z/i =~ priority or invalid_argument
67
+
68
+ # Weight
69
+ unless weight.nil? or (/\A\d+\Z/ =~ weight and weight.to_i > 0)
70
+ invalid_argument
71
+ end
67
72
  end # :aliases
68
73
 
69
74
  desc 'ip address of a default resolver'
@@ -153,7 +158,7 @@ def murakumo_parse_args
153
158
 
154
159
  options[:aliases] = (options[:aliases] || []).map do |r|
155
160
  r = r.map {|i| i.to_s.strip }
156
- [nil, 60, 'master'].each_with_index {|v, i| r[i] ||= v }
161
+ [nil, 60, 'master', 100].each_with_index {|v, i| r[i] ||= v }
157
162
 
158
163
  priority = case r[2].to_s
159
164
  when /master/i
@@ -165,9 +170,10 @@ def murakumo_parse_args
165
170
  end
166
171
 
167
172
  [
168
- r[0], # name
173
+ r[0], # name
169
174
  r[1].to_i, # TTL
170
175
  priority,
176
+ r[3].to_i, # weight
171
177
  ]
172
178
  end
173
179
 
@@ -204,7 +210,7 @@ def murakumo_parse_args
204
210
  end
205
211
  end
206
212
  end
207
- end
213
+ end # health check
208
214
 
209
215
  # notification
210
216
  if options.config_file and (ntfc = options.config_file['notification'])
@@ -241,8 +247,19 @@ def murakumo_parse_args
241
247
 
242
248
  ntfc_h[:open_timeout] = ntfc['open_timeout'].to_i if ntfc['open_timeout']
243
249
  ntfc_h[:read_timeout] = ntfc['read_timeout'].to_i if ntfc['read_timeout']
244
- end
245
- end
250
+ end # notification
251
+
252
+ # {name,addr}-{includes,excludes}
253
+ if options.config_file
254
+ %w(name-includes name-excludes addr-includes addr-excludes).each do |key|
255
+ unless (reg_vals = (options.config_file[key] || '').strip).empty?
256
+ reg_vals = reg_vals.split(/\s*,\s*/).select {|i| not i.empty? }.map {|i| Regexp.new(i.strip, Regexp::IGNORECASE) }
257
+ options[key.gsub('-', '_').to_sym] = reg_vals
258
+ end
259
+ end
260
+ end # {name,addr}-{includes,excludes}
261
+
262
+ end # after
246
263
 
247
264
  error do |e|
248
265
  abort(e.message)
@@ -1,5 +1,5 @@
1
1
  module Murakumo
2
- VERSION = '0.3.5'
2
+ VERSION = '0.3.6'
3
3
 
4
4
  # Priority
5
5
  MASTER = 1
@@ -22,15 +22,15 @@ module Murakumo
22
22
  # リソースレコードからホストのアドレスとデータを取り出す
23
23
  host_data = options[:host]
24
24
  @address = host_data.shift
25
- host_data.concat [ORIGIN, ACTIVE]
25
+ host_data.concat [ORIGIN, 0, ACTIVE]
26
26
  alias_datas = options[:aliases].map {|r| r + [ACTIVE] }
27
27
  @logger = options[:logger]
28
28
 
29
29
  # 名前は小文字に変換
30
30
  datas = ([host_data] + alias_datas).map do |i|
31
- name, ttl, priority, activity = i
31
+ name, ttl, priority, weight, activity = i
32
32
  name = name.downcase
33
- [name, ttl, priority, activity]
33
+ [name, ttl, priority, weight, activity]
34
34
  end
35
35
 
36
36
  # データベースを作成してレコードを更新
@@ -157,29 +157,38 @@ module Murakumo
157
157
  end
158
158
  end
159
159
 
160
- records = list_records
160
+ records = list_records.select {|r| r[0] == @address }
161
161
 
162
162
  hash['host'] = records.find {|r| r[3] == ORIGIN }[0..2].join(',')
163
163
 
164
164
  aliases = records.select {|r| r[3] != ORIGIN }.map do |r|
165
- [r[1], r[2], (r[3] == MASTER ? 'master' : 'backup')].join(',')
165
+ [r[1], r[2], (r[3] == MASTER ? 'master' : 'backup'), r[4]].join(',')
166
166
  end
167
167
 
168
168
  hash['alias'] = aliases unless aliases.empty?
169
169
 
170
- if @options.config_file and @options.config_file['health-check']
171
- hash['health-check'] = @options.config_file['health-check']
172
- end
170
+ # 設定ファイルのみの項目
171
+ if @options.config_file
172
+ if @options.config_file['health-check']
173
+ hash['health-check'] = @options.config_file['health-check']
174
+ end
173
175
 
174
- if @options.config_file and @options.config_file['notification']
175
- hash['notification'] = @options.config_file['notification']
176
- end
176
+ if @options.config_file['notification']
177
+ hash['notification'] = @options.config_file['notification']
178
+ end
179
+
180
+ %w(name-includes name-excludes addr-includes addr-excludes).each do |key|
181
+ if @options.config_file[key]
182
+ hash[key] = @options.config_file[key]
183
+ end
184
+ end
185
+ end # 設定ファイルのみの項目
177
186
 
178
187
  return hash
179
188
  end
180
189
 
181
190
  def list_records
182
- columns = %w(ip_address name ttl priority activity)
191
+ columns = %w(ip_address name ttl priority weight activity)
183
192
 
184
193
  @db.execute(<<-EOS).map {|i| i.values_at(*columns) }
185
194
  SELECT #{columns.join(', ')} FROM records ORDER BY ip_address, name
@@ -191,9 +200,9 @@ module Murakumo
191
200
 
192
201
  # 名前は小文字に変換
193
202
  records = records.map do |i|
194
- name, ttl, priority = i
203
+ name, ttl, priority, weight = i
195
204
  name = name.downcase
196
- [name, ttl, priority]
205
+ [name, ttl, priority, weight]
197
206
  end
198
207
 
199
208
  @gossip.transaction do
@@ -213,6 +222,7 @@ module Murakumo
213
222
  # データを更新
214
223
  records = records.map {|r| r + [ACTIVE] }
215
224
  @gossip.data.concat(records)
225
+
216
226
  end # transaction
217
227
 
218
228
  # データベースを更新
@@ -327,7 +337,7 @@ module Murakumo
327
337
  return unless datas
328
338
 
329
339
  datas.each do |i|
330
- name, ttl, priority, activity = i
340
+ name, ttl, priority, weight, activity = i
331
341
 
332
342
  # 名前は小文字に変換
333
343
  name = name.downcase
@@ -337,9 +347,9 @@ module Murakumo
337
347
  @logger.warn('same hostname as origin was found')
338
348
  end
339
349
 
340
- @db.execute(<<-EOS, address, name, ttl, priority, activity)
341
- REPLACE INTO records (ip_address, name, ttl, priority, activity)
342
- VALUES (?, ?, ?, ?, ?)
350
+ @db.execute(<<-EOS, address, name, ttl, priority, weight, activity)
351
+ REPLACE INTO records (ip_address, name, ttl, priority, weight, activity)
352
+ VALUES (?, ?, ?, ?, ?, ?)
343
353
  EOS
344
354
  end
345
355
 
@@ -370,6 +380,15 @@ module Murakumo
370
380
  # Search of records
371
381
 
372
382
  def address_exist?(name)
383
+ # includes、excludesのチェック
384
+ if @options[:name_excludes] and @options[:name_excludes].any? {|r| r =~ name }
385
+ return false
386
+ end
387
+
388
+ if @options[:name_includes] and not @options[:name_includes].any? {|r| r =~ name }
389
+ return false
390
+ end
391
+
373
392
  # 名前は小文字に変換
374
393
  name = name.downcase
375
394
 
@@ -379,7 +398,7 @@ module Murakumo
379
398
  if @cache.nil?
380
399
  # キャッシュを設定していないときはいつもの処理
381
400
  @address_records = @db.execute(<<-EOS, name, ACTIVE) # シングルスレッドェ…
382
- SELECT ip_address, ttl, priority FROM records
401
+ SELECT ip_address, ttl, priority, weight FROM records
383
402
  WHERE name = ? AND activity = ?
384
403
  EOS
385
404
  else
@@ -395,7 +414,7 @@ module Murakumo
395
414
 
396
415
  # 普通に検索
397
416
  @address_records = @db.execute(<<-EOS, name, ACTIVE) # シングルスレッドェ…
398
- SELECT ip_address, ttl, priority FROM records
417
+ SELECT ip_address, ttl, priority, weight FROM records
399
418
  WHERE name = ? AND activity = ?
400
419
  EOS
401
420
 
@@ -405,13 +424,13 @@ module Murakumo
405
424
 
406
425
  # レコードはハッシュに変換する
407
426
  cache_records = @address_records.map do |i|
408
- ip_address, ttl, priority = i.values_at('ip_address', 'ttl', 'priority')
427
+ ip_address, ttl, priority, weight = i.values_at('ip_address', 'ttl', 'priority', 'weight')
409
428
 
410
429
  if min_ttl.nil? or ttl < min_ttl
411
430
  min_ttl = ttl
412
431
  end
413
432
 
414
- {'ip_address' => ip_address, 'ttl' => ttl, 'priority' => priority}
433
+ {'ip_address' => ip_address, 'ttl' => ttl, 'priority' => priority, 'weight' => weight}
415
434
  end
416
435
 
417
436
  # 最小値をExpire期限として設定
@@ -458,6 +477,15 @@ module Murakumo
458
477
  def name_exist?(address)
459
478
  address = x_ip_addr(address)
460
479
 
480
+ # includes、excludesのチェック
481
+ if @options[:addr_excludes] and @options[:addr_excludes].any? {|r| r =~ address }
482
+ return false
483
+ end
484
+
485
+ if @options[:addr_includes] and not @options[:addr_includes].any? {|r| r =~ address }
486
+ return false
487
+ end
488
+
461
489
  # シングルスレッドェ…
462
490
  @name_records = @db.execute(<<-EOS, address, ACTIVE)
463
491
  SELECT name, ttl, priority FROM records
@@ -497,15 +525,32 @@ module Murakumo
497
525
 
498
526
  # 乱数でレコードをシャッフルする
499
527
  def shuffle_records(records)
500
- # レコードが一件の時はそのまま返す
501
- return records if records.length == 1
528
+ # レコードが1件以下の時はそのまま返す
529
+ return records if records.length <= 1
502
530
 
503
- # 先頭のAレコードを決定
504
531
  max_ip_num = [records.length, @options[:max_ip_num]].min
505
- first_index = rand(records.length)
506
532
 
507
- # Aレコードを返す
508
- (records + records).slice(first_index, max_ip_num)
533
+ indices = []
534
+ buf = []
535
+
536
+ # インデックスをWeight分追加
537
+ records.each_with_index do |r, i|
538
+ weight = r['weight']
539
+ weight.times { buf << i }
540
+ end
541
+
542
+ # インデックスをシャッフル
543
+ buf = buf.sort_by{ rand }
544
+
545
+ # ランダムにインデックスを取り出す
546
+ loop do
547
+ indices << buf.shift
548
+ indices.uniq!
549
+ break if (indices.size >= max_ip_num or buf.empty?)
550
+ end
551
+
552
+ # インデックスのレコードを返す
553
+ records.values_at(*indices)
509
554
  end
510
555
 
511
556
  # リソースレコードのデータベース作成
@@ -523,6 +568,7 @@ module Murakumo
523
568
  name TEXT NOT NULL,
524
569
  ttl INTEGER NOT NULL,
525
570
  priority INTEGER NOT NULL, /* MASTER:1, BACKUP:0, ORIGIN:-1 */
571
+ weight INTEGER NOT NULL, /* Origin:0, Other:>=1 */
526
572
  activity INTEGER NOT NULL, /* Active:1, Inactive:0 */
527
573
  PRIMARY KEY (ip_address, name)
528
574
  )
@@ -28,7 +28,7 @@ module Murakumo
28
28
 
29
29
  # HTTPチェッカー
30
30
  def http_get(path, statuses = [200], port = 80, host = '127.0.0.1')
31
- res = Net::HTTP.start('127.0.0.1', 80) do |http|
31
+ res = Net::HTTP.start(host, port) do |http|
32
32
  http.read_timeout = @options['timeout']
33
33
  http.get(path)
34
34
  end
@@ -73,7 +73,9 @@ module Murakumo
73
73
  sock = port_sock
74
74
  end
75
75
 
76
- my = Mysql.new(host, user, passwd, db, port, sock)
76
+ my = Mysql.init
77
+ my.options(Mysql::OPT_CONNECT_TIMEOUT, @options['timeout'])
78
+ my.connect(host, user, passwd, db, port, sock)
77
79
  !!(my.respond_to?(:ping) ? my.ping : my.stat)
78
80
  rescue => e
79
81
  @logger.debug("#{@name}: #{e.message}")
@@ -86,7 +88,7 @@ module Murakumo
86
88
  rescue LoadError
87
89
  end
88
90
 
89
- unless defined?(:mysql_check)
91
+ unless method_defined?(:mysql_check)
90
92
  begin
91
93
  require 'mysql2'
92
94
 
@@ -96,6 +98,7 @@ module Murakumo
96
98
  opts[:password] = passwd if passwd
97
99
  opts[:host] = host if host
98
100
  opts[:database] = db if db
101
+ opts[:connect_timeout] = @options['timeout']
99
102
 
100
103
  if port_sock.kind_of?(Integer)
101
104
  opts[:port] = port_sock
@@ -69,7 +69,7 @@ module Murakumo
69
69
  @cloud.gossip.transaction do
70
70
  @cloud.gossip.data.each do |i|
71
71
  # 名前の一致するデータを更新
72
- i[3] = activity if i[0] == @name
72
+ i[4] = activity if i[0] == @name
73
73
  end
74
74
  end
75
75
 
@@ -92,6 +92,7 @@ module Murakumo
92
92
  # look up PTR record
93
93
  match(@@cloud.method(:name_exist?), :PTR) do |transaction|
94
94
  name, ttl = @@cloud.lookup_name(transaction.name)
95
+ name += ".#{@@options[:domain]}" if @@options[:domain]
95
96
  transaction.respond!(Resolv::DNS::Name.create("#{name}."), :ttl => ttl)
96
97
  end
97
98
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: murakumo
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 5
10
- version: 0.3.5
9
+ - 6
10
+ version: 0.3.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - winebarrel
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-30 00:00:00 Z
18
+ date: 2011-12-04 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rubydns
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
140
  requirements: []
141
141
 
142
142
  rubyforge_project:
143
- rubygems_version: 1.8.1
143
+ rubygems_version: 1.8.11
144
144
  signing_key:
145
145
  specification_version: 3
146
146
  summary: Murakumo is the internal DNS server which manages name information using a gossip protocol.