etcd-tools 0.1.4 → 0.2.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 +8 -8
- data/bin/etcd-erb +2 -2
- data/bin/etcd-watchdog-vip +2 -2
- data/bin/etcd2yaml +3 -0
- data/bin/yaml2etcd +2 -2
- data/lib/etcd-tools/cli/etcd2yaml.rb +62 -0
- data/lib/etcd-tools/{etcd_erb/options.rb → cli/etcd_erb.rb} +27 -2
- data/lib/etcd-tools/{yaml2etcd/options.rb → cli/yaml2etcd.rb} +35 -3
- data/lib/etcd-tools/erb.rb +37 -0
- data/lib/etcd-tools/etcd.rb +50 -0
- data/lib/etcd-tools/watchdog/haproxy.rb +18 -2
- data/lib/etcd-tools/watchdog/init.rb +16 -21
- data/lib/etcd-tools/watchdog/threads/icmp.rb +2 -0
- data/lib/etcd-tools/watchdog/util/config.rb +43 -0
- data/lib/etcd-tools/watchdog/util/etcd.rb +34 -0
- data/lib/etcd-tools/watchdog/util/helpers.rb +25 -0
- data/lib/etcd-tools/watchdog/util/logger.rb +44 -0
- data/lib/etcd-tools/watchdog/vip.rb +88 -16
- data/lib/etcd_tools.rb +5 -0
- metadata +16 -16
- data/lib/etcd-tools/etcd_erb/erb.rb +0 -26
- data/lib/etcd-tools/etcd_erb.rb +0 -38
- data/lib/etcd-tools/etcd_watchdog_haproxy.rb +0 -20
- data/lib/etcd-tools/etcd_watchdog_vip.rb +0 -82
- data/lib/etcd-tools/watchdog/config.rb +0 -38
- data/lib/etcd-tools/watchdog/etcd.rb +0 -30
- data/lib/etcd-tools/watchdog/helpers.rb +0 -23
- data/lib/etcd-tools/watchdog/logger.rb +0 -42
- data/lib/etcd-tools/yaml2etcd/import.rb +0 -23
- data/lib/etcd-tools/yaml2etcd.rb +0 -44
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjJmMWFjMTQ0ZTg4YTU1ZWYzODEyNzFkMTcxMzlkNzljYjM0ZTMyMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NTY4ZDgzNWM2MWNhNDhmZTc4MzYzOGZjNWQ4YTNiZWMwMzU0NmE2OA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
M2NkMGYxZjRlYTNkMDM3MGIxZjk4ZmQ5ZTBmMzA4NjhmZGZkNGJjMjFiMGM0
|
10
|
+
YjFjNTc3MDdjMTk5MmQ5ZTUyNjcyMjQ3NTQyMTRlNmI0ZDcwN2Y3NWZjZmJm
|
11
|
+
NmY5ODkzMTA5NTdjOTkzNTQ4OTE1MTJiZDNkOGI0ZmY1ZmZmM2U=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjU0OWE3ODM1MTM1MDM1Njk3MmYzYWZlNTZmMDk1NGU0MTQ5NzdhY2EzZWI1
|
14
|
+
OTEyNDlmZmExYzJlZWQzNThjMGE4ZjAxM2JjOTJjOWQyOGRmZDJkYWNkNGEy
|
15
|
+
Mjk0NTY4MDllMzRjNjk2YTc1Yzk0ZGU1NDExOWJiMjdlNzE3ZTA=
|
data/bin/etcd-erb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require 'etcd-tools/etcd_erb'
|
3
|
-
EtcdTools::EtcdERB.new
|
2
|
+
require 'etcd-tools/cli/etcd_erb'
|
3
|
+
EtcdTools::Cli::EtcdERB.new
|
data/bin/etcd-watchdog-vip
CHANGED
data/bin/etcd2yaml
ADDED
data/bin/yaml2etcd
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require 'etcd-tools/yaml2etcd'
|
3
|
-
EtcdTools::Yaml2Etcd.new
|
2
|
+
require 'etcd-tools/cli/yaml2etcd'
|
3
|
+
EtcdTools::Cli::Yaml2Etcd.new
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'yaml'
|
3
|
+
require 'etcd-tools/etcd'
|
4
|
+
|
5
|
+
module EtcdTools
|
6
|
+
module Cli
|
7
|
+
class Etcd2Yaml
|
8
|
+
include EtcdTools::Etcd
|
9
|
+
|
10
|
+
def optparse
|
11
|
+
@options = Hash.new
|
12
|
+
|
13
|
+
@options[:url] = ENV['ETCDCTL_ENDPOINT']
|
14
|
+
@options[:url] ||= "http://127.0.0.1:4001"
|
15
|
+
@options[:root_path] = "/config"
|
16
|
+
|
17
|
+
OptionParser.new do |opts|
|
18
|
+
opts.banner = "Parses ETCD tree into structured YAML\n\nUsage: #{$0} [OPTIONS]"
|
19
|
+
opts.separator ""
|
20
|
+
opts.separator "Connection options:"
|
21
|
+
opts.on("-u", "--url HOST", "URL endpoint of the ETCD service (ETCDCTL_ENDPOINT envvar also applies) [DEFAULT: http://127.0.0.1:4001]") do |param|
|
22
|
+
@options[:url] = param
|
23
|
+
end
|
24
|
+
opts.separator ""
|
25
|
+
opts.separator "Common options:"
|
26
|
+
opts.on("-r", "--root-path PATH", "root PATH of ETCD tree to extract the data from [DEFAULT: /config]") do |param|
|
27
|
+
@options[:root_path] = param
|
28
|
+
end
|
29
|
+
opts.on("-v", "--verbose", "run verbosely") do |param|
|
30
|
+
@options[:verbose] = param
|
31
|
+
end
|
32
|
+
opts.on_tail("-h", "--help", "show usage") do |param|
|
33
|
+
puts opts;
|
34
|
+
exit! 0
|
35
|
+
end
|
36
|
+
end.parse!
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
self.optparse
|
41
|
+
|
42
|
+
begin
|
43
|
+
@etcd = etcd_connect @options[:url]
|
44
|
+
rescue Exception => e
|
45
|
+
$stderr.puts "Failed to connect to ETCD!"
|
46
|
+
$stderr.puts e.message
|
47
|
+
exit! 1
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
hash = etcd2hash @etcd, @options[:root_path]
|
52
|
+
puts hash.to_yaml
|
53
|
+
rescue Exception => e
|
54
|
+
$stderr.puts "Import failed"
|
55
|
+
$stderr.puts e.message
|
56
|
+
exit! 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,8 +1,12 @@
|
|
1
1
|
require 'optparse'
|
2
|
+
require 'etcd-tools/etcd'
|
3
|
+
require 'etcd-tools/erb'
|
2
4
|
|
3
5
|
module EtcdTools
|
4
|
-
module
|
5
|
-
|
6
|
+
module Cli
|
7
|
+
class EtcdERB
|
8
|
+
include EtcdTools::Etcd
|
9
|
+
|
6
10
|
def optparse
|
7
11
|
@options = Hash.new
|
8
12
|
|
@@ -24,6 +28,27 @@ module EtcdTools
|
|
24
28
|
end
|
25
29
|
end.parse!
|
26
30
|
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
self.optparse
|
34
|
+
|
35
|
+
begin
|
36
|
+
@etcd = etcd_connect @options[:url]
|
37
|
+
rescue Exception => e
|
38
|
+
$stderr.puts "Failed to connect to ETCD!"
|
39
|
+
$stderr.puts e.message
|
40
|
+
exit! 1
|
41
|
+
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
template = EtcdTools::Erb.new @etcd, ARGF.read
|
45
|
+
puts template.result
|
46
|
+
rescue Exception => e
|
47
|
+
$stderr.puts "Failed to parse ERB template!"
|
48
|
+
$stderr.puts e.message
|
49
|
+
exit! 1
|
50
|
+
end
|
51
|
+
end
|
27
52
|
end
|
28
53
|
end
|
29
54
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'optparse'
|
2
|
+
require 'etcd-tools/etcd'
|
2
3
|
|
3
4
|
module EtcdTools
|
4
|
-
module
|
5
|
-
|
5
|
+
module Cli
|
6
|
+
class Yaml2Etcd
|
7
|
+
include EtcdTools::Etcd
|
8
|
+
|
6
9
|
def optparse
|
7
10
|
@options = Hash.new
|
8
11
|
|
@@ -10,7 +13,6 @@ module EtcdTools
|
|
10
13
|
@options[:url] ||= "http://127.0.0.1:4001"
|
11
14
|
@options[:root_path] = "/config"
|
12
15
|
|
13
|
-
|
14
16
|
OptionParser.new do |opts|
|
15
17
|
opts.banner = "Reads YAML file and imports the data into ETCD\n\nUsage: #{$0} [OPTIONS] < config.yaml"
|
16
18
|
opts.separator ""
|
@@ -32,6 +34,36 @@ module EtcdTools
|
|
32
34
|
end
|
33
35
|
end.parse!
|
34
36
|
end
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
self.optparse
|
40
|
+
|
41
|
+
begin
|
42
|
+
@hash = YAML.load ARGF.read
|
43
|
+
rescue
|
44
|
+
$stderr.puts "Failed to parse YAML!"
|
45
|
+
$stderr.puts e.message
|
46
|
+
exit! 1
|
47
|
+
end
|
48
|
+
|
49
|
+
begin
|
50
|
+
@etcd = etcd_connect @options[:url]
|
51
|
+
rescue Exception => e
|
52
|
+
$stderr.puts "Failed to connect to ETCD!"
|
53
|
+
$stderr.puts e.message
|
54
|
+
exit! 1
|
55
|
+
end
|
56
|
+
|
57
|
+
begin
|
58
|
+
hash2etcd @hash, @options[:root_path]
|
59
|
+
puts "OK"
|
60
|
+
rescue Exception => e
|
61
|
+
$stderr.puts "Import failed"
|
62
|
+
$stderr.puts e.message
|
63
|
+
exit! 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
35
67
|
end
|
36
68
|
end
|
37
69
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'etcd-tools/etcd'
|
3
|
+
|
4
|
+
module EtcdTools
|
5
|
+
class Erb < ::ERB
|
6
|
+
include EtcdTools::Etcd
|
7
|
+
|
8
|
+
attr_reader :etcd
|
9
|
+
|
10
|
+
def initialize (etcd, template)
|
11
|
+
@etcd = etcd
|
12
|
+
super template
|
13
|
+
end
|
14
|
+
|
15
|
+
def result
|
16
|
+
super binding
|
17
|
+
end
|
18
|
+
|
19
|
+
def value path
|
20
|
+
return @etcd.get('/' + path.sub(/^\//, '')).value
|
21
|
+
end
|
22
|
+
|
23
|
+
def keys path
|
24
|
+
path.sub!(/^\//, '')
|
25
|
+
if @etcd.get('/' + path).directory?
|
26
|
+
return @etcd.get('/' + path).children.map { |key| key.key }
|
27
|
+
else
|
28
|
+
return []
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def members
|
33
|
+
@etcd.members
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'etcd'
|
2
|
+
require 'etcd-tools/mixins'
|
3
|
+
|
4
|
+
module EtcdTools
|
5
|
+
module Etcd
|
6
|
+
def etcd_connect (url)
|
7
|
+
(host, port) = url.gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
8
|
+
etcd = ::Etcd.client(host: host, port: port)
|
9
|
+
begin
|
10
|
+
etcd.version
|
11
|
+
return etcd
|
12
|
+
rescue Exception => e
|
13
|
+
raise e #fixme
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash2etcd (etcd, hash, path="")
|
18
|
+
begin
|
19
|
+
hash.each do |key, value|
|
20
|
+
etcd_key = path + "/" + key.to_s
|
21
|
+
case value
|
22
|
+
when Hash
|
23
|
+
hash2etcd(value, etcd_key)
|
24
|
+
else
|
25
|
+
etcd.set(etcd_key, value: value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
rescue Exception => e
|
29
|
+
raise e #fixme
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def etcd2hash (etcd, path="")
|
34
|
+
begin
|
35
|
+
hash = Hash.new
|
36
|
+
etcd.get(path).children.each do |child|
|
37
|
+
if etcd.get(child.key).directory?
|
38
|
+
hash[child.key.split('/').last.to_sym] = etcd2hash etcd, child.key
|
39
|
+
else
|
40
|
+
hash[child.key.split('/').last.to_sym] = child.value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
return hash.sort.to_h
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -1,7 +1,23 @@
|
|
1
|
+
require 'etcd-tools/watchdog/init'
|
2
|
+
# require 'etcd-tools/watchdogthreads/haproxy'
|
3
|
+
require 'etcd-tools/erb'
|
4
|
+
|
1
5
|
module EtcdTools
|
2
6
|
module Watchdog
|
3
|
-
|
4
|
-
|
7
|
+
class HAproxy < EtcdTools::Watchdog::Init
|
8
|
+
|
9
|
+
def run
|
10
|
+
while @etcd.watch(@config[:haproxy_cfg]) do
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate_config
|
16
|
+
end
|
17
|
+
|
18
|
+
def reload_haproxy
|
19
|
+
end
|
20
|
+
|
5
21
|
end
|
6
22
|
end
|
7
23
|
end
|
@@ -1,47 +1,42 @@
|
|
1
|
-
require 'ipaddr'
|
2
1
|
require 'timeout'
|
3
|
-
require 'yaml'
|
4
2
|
require 'json'
|
5
3
|
require 'time'
|
6
|
-
require 'etcd'
|
7
4
|
require 'etcd-tools/mixins'
|
8
|
-
require 'etcd-tools/watchdog/config'
|
9
|
-
require 'etcd-tools/watchdog/logger'
|
10
|
-
require 'etcd-tools/watchdog/helpers'
|
11
|
-
require 'etcd-tools/watchdog/etcd'
|
5
|
+
require 'etcd-tools/watchdog/util/config'
|
6
|
+
require 'etcd-tools/watchdog/util/logger'
|
7
|
+
require 'etcd-tools/watchdog/util/helpers'
|
8
|
+
require 'etcd-tools/watchdog/util/etcd'
|
12
9
|
require 'etcd-tools/watchdog/threads/etcd'
|
13
10
|
|
14
11
|
module EtcdTools
|
15
12
|
module Watchdog
|
16
13
|
class Init
|
17
14
|
|
18
|
-
include EtcdTools::Watchdog::Config
|
19
|
-
include EtcdTools::Watchdog::Logger
|
20
|
-
include EtcdTools::Watchdog::Helpers
|
21
|
-
include EtcdTools::Watchdog::Etcd
|
15
|
+
include EtcdTools::Watchdog::Util::Config
|
16
|
+
include EtcdTools::Watchdog::Util::Logger
|
17
|
+
include EtcdTools::Watchdog::Util::Helpers
|
18
|
+
include EtcdTools::Watchdog::Util::Etcd
|
22
19
|
include EtcdTools::Watchdog::Threads
|
23
20
|
|
24
21
|
def initialize
|
25
|
-
@semaphore = {
|
26
|
-
log: Mutex.new,
|
27
|
-
etcd: Mutex.new
|
28
|
-
}
|
29
22
|
@config = { debug: false }
|
30
23
|
@config = config
|
31
24
|
@exit = false
|
32
|
-
# handle various signals
|
33
25
|
@exit_sigs = ['INT', 'TERM']
|
34
26
|
@exit_sigs.each { |sig| Signal.trap(sig) { @exit = true } }
|
35
27
|
Signal.trap('USR1') { @config[:debug] = false }
|
36
28
|
Signal.trap('USR2') { @config[:debug] = true }
|
37
|
-
Signal.trap('HUP')
|
29
|
+
Signal.trap('HUP') { @config = config }
|
30
|
+
end
|
31
|
+
|
32
|
+
def setup(proc_name, nice = -20)
|
38
33
|
if RUBY_VERSION >= '2.1'
|
39
|
-
Process.setproctitle(
|
34
|
+
Process.setproctitle(proc_name)
|
40
35
|
else
|
41
|
-
$0 =
|
36
|
+
$0 = proc_name
|
42
37
|
end
|
43
|
-
|
44
|
-
# Process.daemon
|
38
|
+
Process.setpriority(Process::PRIO_PROCESS, 0, nice)
|
39
|
+
# TODO: Process.daemon ...
|
45
40
|
end
|
46
41
|
end
|
47
42
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'etcd-tools/mixins'
|
3
|
+
|
4
|
+
module EtcdTools
|
5
|
+
module Watchdog
|
6
|
+
module Util
|
7
|
+
module Config
|
8
|
+
private
|
9
|
+
def default_config
|
10
|
+
{ debug: false,
|
11
|
+
parameters: { interface: 'eth0',
|
12
|
+
vip: '192.168.0.168',
|
13
|
+
mask: '255.255.255.0',
|
14
|
+
interval: 1,
|
15
|
+
etcd_endpoint: 'http://127.0.0.1:4001',
|
16
|
+
etcd_interval: 1,
|
17
|
+
etcd_timeout: 5,
|
18
|
+
icmp_count: 2,
|
19
|
+
icmp_interval: 1,
|
20
|
+
arping_count: 1,
|
21
|
+
arping_wait: 1 },
|
22
|
+
commands: { arping: `which arping`.chomp,
|
23
|
+
iproute: `which ip`.chomp,
|
24
|
+
arp: `which arp`.chomp } }
|
25
|
+
end
|
26
|
+
|
27
|
+
def config
|
28
|
+
cfg = default_config
|
29
|
+
if File.exist? '/etc/etcd-watchdog.yaml'
|
30
|
+
cfg = cfg.deep_merge YAML.load_file('/etc/etcd-watchdog.yaml')
|
31
|
+
puts 'loaded config from /etc/etcd-watchdog.yaml'
|
32
|
+
elsif File.exist? './etcd-watchdog.yaml'
|
33
|
+
cfg = cfg.deep_merge YAML.load_file('./etcd-watchdog.yaml')
|
34
|
+
puts 'loaded config from ./etcd-watchdog.yaml'
|
35
|
+
else
|
36
|
+
puts 'no config file loaded, using defaults'
|
37
|
+
end
|
38
|
+
cfg
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'etcd'
|
2
|
+
|
3
|
+
module EtcdTools
|
4
|
+
module Watchdog
|
5
|
+
module Util
|
6
|
+
module Etcd
|
7
|
+
# connect to ETCD
|
8
|
+
def etcd_connect!
|
9
|
+
(host, port) = @config[:parameters][:etcd_endpoint].gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
10
|
+
etcd = ::Etcd.client(host: host, port: port)
|
11
|
+
begin
|
12
|
+
versions = JSON.parse(etcd.version)
|
13
|
+
info "<etcd> conncted to ETCD at #{@config[:parameters][:etcd_endpoint]}"
|
14
|
+
info "<etcd> server version: #{versions['etcdserver']}"
|
15
|
+
info "<etcd> cluster version: #{versions['etcdcluster']}"
|
16
|
+
info "<etcd> healthy: #{etcd.healthy?}"
|
17
|
+
return etcd
|
18
|
+
rescue Exception => e
|
19
|
+
err "<etcd> couldn't connect to etcd at #{host}:#{port}"
|
20
|
+
err "<etcd> #{e.message}"
|
21
|
+
@exit = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# is my ETCD the leader?
|
26
|
+
# <IMPLEMENTED>
|
27
|
+
def leader?(etcd)
|
28
|
+
etcd.stats(:self)['id'] == etcd.stats(:self)['leaderInfo']['leader']
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module EtcdTools
|
4
|
+
module Watchdog
|
5
|
+
module Util
|
6
|
+
module Helpers
|
7
|
+
def hostname
|
8
|
+
@hostname ||= Socket.gethostname
|
9
|
+
end
|
10
|
+
|
11
|
+
def arping
|
12
|
+
@config[:commands][:arping]
|
13
|
+
end
|
14
|
+
|
15
|
+
def iproute
|
16
|
+
@config[:commands][:iproute]
|
17
|
+
end
|
18
|
+
|
19
|
+
def arp
|
20
|
+
@config[:commands][:arp]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module EtcdTools
|
4
|
+
module Watchdog
|
5
|
+
module Util
|
6
|
+
module Logger
|
7
|
+
def info(message)
|
8
|
+
if @config[:debug]
|
9
|
+
@semaphore[:log].synchronize do
|
10
|
+
$stdout.puts(Time.now.to_s + ' INFO (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
11
|
+
$stdout.flush
|
12
|
+
end
|
13
|
+
else
|
14
|
+
@semaphore[:log].synchronize do
|
15
|
+
$stdout.puts(Time.now.to_s + ' INFO ' + message.to_s)
|
16
|
+
$stdout.flush
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def err(message)
|
22
|
+
if @config[:debug]
|
23
|
+
@semaphore[:log].synchronize do
|
24
|
+
$stdout.puts(Time.now.to_s + ' ERROR (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
25
|
+
$stdout.flush
|
26
|
+
end
|
27
|
+
else
|
28
|
+
@semaphore[:log].synchronize do
|
29
|
+
$stdout.puts(Time.now.to_s + ' ERROR ' + message.to_s)
|
30
|
+
$stdout.flush
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def debug(message)
|
36
|
+
@semaphore[:log].synchronize do
|
37
|
+
$stdout.puts(Time.now.to_s + ' DEBUG (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
38
|
+
$stdout.flush
|
39
|
+
end if @config[:debug]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,6 +1,85 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
require 'etcd-tools/watchdog/init'
|
3
|
+
require 'etcd-tools/watchdog/threads/icmp'
|
4
|
+
|
1
5
|
module EtcdTools
|
2
6
|
module Watchdog
|
3
|
-
|
7
|
+
class Vip < EtcdTools::Watchdog::Init
|
8
|
+
|
9
|
+
def run
|
10
|
+
if Process.euid != 0
|
11
|
+
$stderr.puts 'Must run under root user!'
|
12
|
+
exit! 1
|
13
|
+
end
|
14
|
+
setup
|
15
|
+
@semaphore = {
|
16
|
+
log: Mutex.new,
|
17
|
+
etcd: Mutex.new,
|
18
|
+
icmp: Mutex.new
|
19
|
+
}
|
20
|
+
@thread = { icmp: thread_icmp, etcd: thread_etcd }
|
21
|
+
@status_etcd = false
|
22
|
+
@status_icmp = false
|
23
|
+
@thread.each_value(&:run)
|
24
|
+
sleep @config[:parameters][:interval]
|
25
|
+
first_cycle = true
|
26
|
+
while !@exit do
|
27
|
+
status_etcd = status_icmp = false # FIXME: introduce CVs...
|
28
|
+
@semaphore[:icmp].synchronize { status_icmp = @status_icmp }
|
29
|
+
@semaphore[:etcd].synchronize { status_etcd = @status_etcd }
|
30
|
+
if status_etcd
|
31
|
+
if got_vip?
|
32
|
+
debug '<main> i am the leader with VIP, that is OK'
|
33
|
+
else
|
34
|
+
info '<main> i am the leader without VIP, checking whether it is free'
|
35
|
+
if status_icmp
|
36
|
+
info '<main> VIP is still up! (ICMP)'
|
37
|
+
# FIXME: notify by sensu client socket
|
38
|
+
else
|
39
|
+
info '<main> VIP is unreachable by ICMP, checking for duplicates on L2'
|
40
|
+
if vip_dup?
|
41
|
+
info '<main> VIP is still assigned! (ARP)'
|
42
|
+
# FIXME: notify by sensu client socket
|
43
|
+
else
|
44
|
+
info '<main> VIP is free, assigning'
|
45
|
+
vip_handle! status_etcd
|
46
|
+
info '<main> updating other hosts about change'
|
47
|
+
vip_update_arp!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
else
|
52
|
+
if got_vip?
|
53
|
+
info '<main> i got VIP and should not, removing'
|
54
|
+
vip_handle! status_etcd
|
55
|
+
info '<main> updating other hosts about change'
|
56
|
+
vip_update_arp!
|
57
|
+
else
|
58
|
+
debug '<main> i am not a leader and i do not have the VIP, that is OK'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
sleep @config[:parameters][:interval]
|
62
|
+
if first_cycle
|
63
|
+
@semaphore[:icmp].synchronize { status_icmp = @status_icmp }
|
64
|
+
@semaphore[:etcd].synchronize { status_etcd = @status_etcd }
|
65
|
+
info "<main> i #{status_etcd ? 'AM' : 'am NOT'} the leader"
|
66
|
+
info "<main> i #{got_vip? ? 'DO' : 'do NOT'} have the VIP"
|
67
|
+
info "<main> i #{status_icmp ? 'CAN' : 'CANNOT'} see the VIP"
|
68
|
+
end
|
69
|
+
first_cycle = false
|
70
|
+
end
|
71
|
+
info '<main> terminated!'
|
72
|
+
if got_vip?
|
73
|
+
info '<main> removing VIP'
|
74
|
+
vip_handle! false
|
75
|
+
vip_update_arp!
|
76
|
+
end
|
77
|
+
info '<main> stopping threads...'
|
78
|
+
@thread.each_value(&:join)
|
79
|
+
info '<main> exiting...'
|
80
|
+
exit 0
|
81
|
+
end
|
82
|
+
|
4
83
|
# add or remove VIP on interface
|
5
84
|
# <IMPLEMENTED>
|
6
85
|
def vip_handle!(leader)
|
@@ -16,17 +95,12 @@ module EtcdTools
|
|
16
95
|
@config[:parameters][:interface] + '-vip',
|
17
96
|
'>/dev/null 2>&1'
|
18
97
|
]
|
19
|
-
|
20
|
-
|
21
|
-
cmd[2] = 'add'
|
22
|
-
when false
|
23
|
-
cmd[2] = 'delete'
|
24
|
-
end
|
25
|
-
debug "CMD #{cmd.join(' ')}"
|
98
|
+
leader ? cmd[2] = 'add' : cmd[2] = 'delete'
|
99
|
+
debug "<shell> #{cmd.join(' ')}"
|
26
100
|
if system(cmd.join(' '))
|
27
|
-
|
101
|
+
return true
|
28
102
|
else
|
29
|
-
|
103
|
+
return false
|
30
104
|
end
|
31
105
|
end
|
32
106
|
|
@@ -37,12 +111,10 @@ module EtcdTools
|
|
37
111
|
'-c', @config[:parameters][:arping_count],
|
38
112
|
'-I', @config[:parameters][:interface],
|
39
113
|
@config[:parameters][:vip] ]
|
40
|
-
debug "
|
114
|
+
debug "<shell> #{cmd.join(' ')}"
|
41
115
|
if system(cmd.join(' '))
|
42
|
-
info 'gratuitous ARP packet sent'
|
43
116
|
return true
|
44
117
|
else
|
45
|
-
err 'gratuitous ARP packet failed to send'
|
46
118
|
return false
|
47
119
|
end
|
48
120
|
end
|
@@ -60,7 +132,7 @@ module EtcdTools
|
|
60
132
|
'-q',
|
61
133
|
"#{@config[:parameters][:interface]}-vip"
|
62
134
|
]
|
63
|
-
debug "
|
135
|
+
debug "<shell> #{cmd.join(' ')}"
|
64
136
|
if system(cmd.join(' '))
|
65
137
|
return true
|
66
138
|
else
|
@@ -84,9 +156,9 @@ module EtcdTools
|
|
84
156
|
'-w', @config[:parameters][:arping_wait],
|
85
157
|
'-I', @config[:parameters][:interface],
|
86
158
|
@config[:parameters][:vip] ]
|
87
|
-
debug "
|
159
|
+
debug "<shell> #{cmd_arp.join(' ')}"
|
88
160
|
system(cmd_arp.join(' '))
|
89
|
-
debug "
|
161
|
+
debug "<shell> #{cmd_arping.join(' ')}"
|
90
162
|
if system(cmd_arping.join(' '))
|
91
163
|
return false
|
92
164
|
else
|
data/lib/etcd_tools.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: etcd-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Radek 'blufor' Slavicinsky
|
@@ -50,10 +50,12 @@ dependencies:
|
|
50
50
|
- - ! '>='
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: 1.7.8
|
53
|
-
description: A set of handful
|
53
|
+
description: A set of handful daemons and command-line utils for ETCD (is part of
|
54
|
+
PortAuthority)
|
54
55
|
email: radek.slavicinsky@gmail.com
|
55
56
|
executables:
|
56
57
|
- etcd-watchdog-haproxy
|
58
|
+
- etcd2yaml
|
57
59
|
- etcd-watchdog-vip
|
58
60
|
- etcd-erb
|
59
61
|
- yaml2etcd
|
@@ -63,27 +65,25 @@ files:
|
|
63
65
|
- bin/etcd-erb
|
64
66
|
- bin/etcd-watchdog-haproxy
|
65
67
|
- bin/etcd-watchdog-vip
|
68
|
+
- bin/etcd2yaml
|
66
69
|
- bin/yaml2etcd
|
67
|
-
- lib/etcd-tools/
|
68
|
-
- lib/etcd-tools/etcd_erb
|
69
|
-
- lib/etcd-tools/
|
70
|
-
- lib/etcd-tools/
|
71
|
-
- lib/etcd-tools/
|
70
|
+
- lib/etcd-tools/cli/etcd2yaml.rb
|
71
|
+
- lib/etcd-tools/cli/etcd_erb.rb
|
72
|
+
- lib/etcd-tools/cli/yaml2etcd.rb
|
73
|
+
- lib/etcd-tools/erb.rb
|
74
|
+
- lib/etcd-tools/etcd.rb
|
72
75
|
- lib/etcd-tools/mixins.rb
|
73
|
-
- lib/etcd-tools/watchdog/config.rb
|
74
|
-
- lib/etcd-tools/watchdog/etcd.rb
|
75
76
|
- lib/etcd-tools/watchdog/haproxy.rb
|
76
|
-
- lib/etcd-tools/watchdog/helpers.rb
|
77
77
|
- lib/etcd-tools/watchdog/init.rb
|
78
|
-
- lib/etcd-tools/watchdog/logger.rb
|
79
78
|
- lib/etcd-tools/watchdog/threads/etcd.rb
|
80
79
|
- lib/etcd-tools/watchdog/threads/icmp.rb
|
80
|
+
- lib/etcd-tools/watchdog/util/config.rb
|
81
|
+
- lib/etcd-tools/watchdog/util/etcd.rb
|
82
|
+
- lib/etcd-tools/watchdog/util/helpers.rb
|
83
|
+
- lib/etcd-tools/watchdog/util/logger.rb
|
81
84
|
- lib/etcd-tools/watchdog/vip.rb
|
82
|
-
- lib/etcd-tools/yaml2etcd.rb
|
83
|
-
- lib/etcd-tools/yaml2etcd/import.rb
|
84
|
-
- lib/etcd-tools/yaml2etcd/options.rb
|
85
85
|
- lib/etcd_tools.rb
|
86
|
-
homepage:
|
86
|
+
homepage: https://github.com/blufor/etcd-tools
|
87
87
|
licenses:
|
88
88
|
- GPLv2
|
89
89
|
metadata: {}
|
@@ -106,5 +106,5 @@ rubyforge_project:
|
|
106
106
|
rubygems_version: 2.4.3
|
107
107
|
signing_key:
|
108
108
|
specification_version: 4
|
109
|
-
summary:
|
109
|
+
summary: ETCD tools
|
110
110
|
test_files: []
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module EtcdTools
|
2
|
-
module EtcdERB
|
3
|
-
module Erb
|
4
|
-
def result
|
5
|
-
super binding
|
6
|
-
end
|
7
|
-
|
8
|
-
def value path
|
9
|
-
return @etcd.get('/' + path.sub(/^\//, '')).value
|
10
|
-
end
|
11
|
-
|
12
|
-
def keys path
|
13
|
-
path.sub!(/^\//, '')
|
14
|
-
if @etcd.get('/' + path).directory?
|
15
|
-
return @etcd.get('/' + path).children.map { |key| key.key }
|
16
|
-
else
|
17
|
-
return []
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def template
|
22
|
-
ARGF.read
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/etcd-tools/etcd_erb.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'erb'
|
3
|
-
require 'etcd'
|
4
|
-
require 'etcd-tools/etcd_erb/options'
|
5
|
-
require 'etcd-tools/etcd_erb/erb'
|
6
|
-
|
7
|
-
module EtcdTools
|
8
|
-
class EtcdERB < ERB
|
9
|
-
|
10
|
-
include EtcdTools::EtcdERB::Options
|
11
|
-
include EtcdTools::EtcdERB::Erb
|
12
|
-
|
13
|
-
attr_reader :etcd
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
self.optparse
|
17
|
-
@etcd = self.class.connect(@options[:url])
|
18
|
-
super self.class.template
|
19
|
-
puts self.result
|
20
|
-
end
|
21
|
-
|
22
|
-
class << self
|
23
|
-
def connect (url)
|
24
|
-
(host, port) = url.gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
25
|
-
etcd = Etcd.client(host: host, port: port)
|
26
|
-
begin
|
27
|
-
etcd.version
|
28
|
-
return etcd
|
29
|
-
rescue Exception => e
|
30
|
-
$stderr.puts "Couldn't connect to etcd at #{host}:#{port}"
|
31
|
-
$stderr.puts e.message
|
32
|
-
exit! 1
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'net/ping'
|
4
|
-
|
5
|
-
module EtcdTools
|
6
|
-
module Watchdog
|
7
|
-
class HAproxy < EtcdTools::Watchdog::Init
|
8
|
-
|
9
|
-
include EtcdTools::Watchdog::HAproxy
|
10
|
-
|
11
|
-
def run
|
12
|
-
@thread = {
|
13
|
-
etcd: thread_etcd
|
14
|
-
}
|
15
|
-
@status_etcd = false
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'net/ping'
|
4
|
-
require 'etcd-tools/watchdog/init'
|
5
|
-
require 'etcd-tools/watchdog/vip'
|
6
|
-
require 'etcd-tools/watchdog/threads/icmp'
|
7
|
-
|
8
|
-
module EtcdTools
|
9
|
-
class VipWatchdog < EtcdTools::Watchdog::Init
|
10
|
-
|
11
|
-
include EtcdTools::Watchdog::Vip
|
12
|
-
|
13
|
-
def run
|
14
|
-
if Process.euid != 0
|
15
|
-
err 'Must run under root user!'
|
16
|
-
exit! 1
|
17
|
-
end
|
18
|
-
@semaphore.merge!({ icmp: Mutex.new })
|
19
|
-
@thread = { icmp: thread_icmp, etcd: thread_etcd }
|
20
|
-
@status_etcd = false
|
21
|
-
@status_icmp = false
|
22
|
-
@thread.each_value(&:run)
|
23
|
-
sleep @config[:parameters][:interval]
|
24
|
-
first_cycle = true
|
25
|
-
while !@exit do
|
26
|
-
status_etcd = status_icmp = false # FIXME: introduce CVs...
|
27
|
-
@semaphore[:icmp].synchronize { status_icmp = @status_icmp }
|
28
|
-
@semaphore[:etcd].synchronize { status_etcd = @status_etcd }
|
29
|
-
if status_etcd
|
30
|
-
if got_vip?
|
31
|
-
debug '<main> i am the leader with VIP, that is OK'
|
32
|
-
else
|
33
|
-
info '<main> i am the leader without VIP, checking whether it is free'
|
34
|
-
if status_icmp
|
35
|
-
info '<main> VIP is still up! (ICMP)'
|
36
|
-
# FIXME: notify by sensu client socket
|
37
|
-
else
|
38
|
-
info '<main> VIP is unreachable by ICMP, checking for duplicates on L2'
|
39
|
-
if vip_dup?
|
40
|
-
info '<main> VIP is still assigned! (ARP)'
|
41
|
-
# FIXME: notify by sensu client socket
|
42
|
-
else
|
43
|
-
info '<main> VIP is free, assigning'
|
44
|
-
vip_handle! status_etcd
|
45
|
-
info '<main> updating other hosts about change'
|
46
|
-
vip_update_arp!
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
else
|
51
|
-
if got_vip?
|
52
|
-
info '<main> i got VIP and should not, removing'
|
53
|
-
vip_handle! status_etcd
|
54
|
-
info '<main> updating other hosts about change'
|
55
|
-
vip_update_arp!
|
56
|
-
else
|
57
|
-
debug '<main> i am not a leader and i do not have the VIP, that is OK'
|
58
|
-
end
|
59
|
-
end
|
60
|
-
sleep @config[:parameters][:interval]
|
61
|
-
if first_cycle
|
62
|
-
@semaphore[:icmp].synchronize { status_icmp = @status_icmp }
|
63
|
-
@semaphore[:etcd].synchronize { status_etcd = @status_etcd }
|
64
|
-
info "<main> i #{status_etcd ? 'AM' : 'am NOT'} the leader"
|
65
|
-
info "<main> i #{got_vip? ? 'DO' : 'do NOT'} have the VIP"
|
66
|
-
info "<main> i #{status_icmp ? 'CAN' : 'CANNOT'} see the VIP"
|
67
|
-
end
|
68
|
-
first_cycle = false
|
69
|
-
end
|
70
|
-
info '<main> terminated!'
|
71
|
-
if got_vip?
|
72
|
-
info '<main> removing VIP'
|
73
|
-
vip_handle! false
|
74
|
-
vip_update_arp!
|
75
|
-
end
|
76
|
-
info '<main> stopping threads...'
|
77
|
-
@thread.each_value(&:join)
|
78
|
-
info '<main> exiting...'
|
79
|
-
exit 0
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module EtcdTools
|
2
|
-
module Watchdog
|
3
|
-
module Config
|
4
|
-
private
|
5
|
-
def default_config
|
6
|
-
{ debug: false,
|
7
|
-
parameters: { interface: 'eth0',
|
8
|
-
vip: '192.168.0.168',
|
9
|
-
mask: '255.255.255.0',
|
10
|
-
interval: 1,
|
11
|
-
etcd_endpoint: 'http://127.0.0.1:4001',
|
12
|
-
etcd_interval: 1,
|
13
|
-
etcd_timeout: 5,
|
14
|
-
icmp_count: 2,
|
15
|
-
icmp_interval: 1,
|
16
|
-
arping_count: 1,
|
17
|
-
arping_wait: 1 },
|
18
|
-
commands: { arping: `which arping`.chomp,
|
19
|
-
iproute: `which ip`.chomp,
|
20
|
-
arp: `which arp`.chomp } }
|
21
|
-
end
|
22
|
-
|
23
|
-
def config
|
24
|
-
cfg = default_config
|
25
|
-
if File.exist? '/etc/etcd-watchdog.yaml'
|
26
|
-
cfg = cfg.deep_merge YAML.load_file('/etc/etcd-watchdog.yaml')
|
27
|
-
info '<main> loaded config from /etc/etcd-watchdog.yaml'
|
28
|
-
elsif File.exist? './etcd-watchdog.yaml'
|
29
|
-
cfg = cfg.deep_merge YAML.load_file('./etcd-watchdog.yaml')
|
30
|
-
info '<main> loaded config from ./etcd-watchdog.yaml'
|
31
|
-
else
|
32
|
-
info '<main> no config file loaded, using defaults'
|
33
|
-
end
|
34
|
-
cfg
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module EtcdTools
|
2
|
-
module Watchdog
|
3
|
-
module Etcd
|
4
|
-
# connect to ETCD
|
5
|
-
def etcd_connect!
|
6
|
-
(host, port) = @config[:parameters][:etcd_endpoint].gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
7
|
-
etcd = ::Etcd.client(host: host, port: port)
|
8
|
-
begin
|
9
|
-
versions = JSON.parse(etcd.version)
|
10
|
-
info "<etcd> conncted to ETCD at #{@config[:parameters][:etcd_endpoint]}"
|
11
|
-
info "<etcd> server version: #{versions['etcdserver']}"
|
12
|
-
info "<etcd> cluster version: #{versions['etcdcluster']}"
|
13
|
-
info "<etcd> healthy: #{etcd.healthy?}"
|
14
|
-
return etcd
|
15
|
-
rescue Exception => e
|
16
|
-
err "<etcd> couldn't connect to etcd at #{host}:#{port}"
|
17
|
-
err "<etcd> #{e.message}"
|
18
|
-
@exit = true
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# is my ETCD the leader?
|
23
|
-
# <IMPLEMENTED>
|
24
|
-
def leader?(etcd)
|
25
|
-
etcd.stats(:self)['id'] == etcd.stats(:self)['leaderInfo']['leader']
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
|
3
|
-
module EtcdTools
|
4
|
-
module Watchdog
|
5
|
-
module Helpers
|
6
|
-
def hostname
|
7
|
-
@hostname ||= Socket.gethostname
|
8
|
-
end
|
9
|
-
|
10
|
-
def arping
|
11
|
-
@config[:commands][:arping]
|
12
|
-
end
|
13
|
-
|
14
|
-
def iproute
|
15
|
-
@config[:commands][:iproute]
|
16
|
-
end
|
17
|
-
|
18
|
-
def arp
|
19
|
-
@config[:commands][:arp]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
|
3
|
-
module EtcdTools
|
4
|
-
module Watchdog
|
5
|
-
module Logger
|
6
|
-
def info(message)
|
7
|
-
if @config[:debug]
|
8
|
-
@semaphore[:log].synchronize do
|
9
|
-
$stdout.puts(Time.now.to_s + ' INFO (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
10
|
-
$stdout.flush
|
11
|
-
end
|
12
|
-
else
|
13
|
-
@semaphore[:log].synchronize do
|
14
|
-
$stdout.puts(Time.now.to_s + ' INFO ' + message.to_s)
|
15
|
-
$stdout.flush
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def err(message)
|
21
|
-
if @config[:debug]
|
22
|
-
@semaphore[:log].synchronize do
|
23
|
-
$stdout.puts(Time.now.to_s + ' ERROR (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
24
|
-
$stdout.flush
|
25
|
-
end
|
26
|
-
else
|
27
|
-
@semaphore[:log].synchronize do
|
28
|
-
$stdout.puts(Time.now.to_s + ' ERROR ' + message.to_s)
|
29
|
-
$stdout.flush
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def debug(message)
|
35
|
-
@semaphore[:log].synchronize do
|
36
|
-
$stdout.puts(Time.now.to_s + ' DEBUG (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
37
|
-
$stdout.flush
|
38
|
-
end if @config[:debug]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module EtcdTools
|
2
|
-
module Yaml2Etcd
|
3
|
-
module Methods
|
4
|
-
def import_structure (hash, path="")
|
5
|
-
begin
|
6
|
-
hash.each do |k, v|
|
7
|
-
etcd_key = path + "/" + k.to_s
|
8
|
-
case v
|
9
|
-
when Hash
|
10
|
-
import_structure(v, etcd_key)
|
11
|
-
else
|
12
|
-
@etcd.set(etcd_key, value: v)
|
13
|
-
puts("SET: " + etcd_key + ": " + v.to_json) if @options[:verbose]
|
14
|
-
end
|
15
|
-
end
|
16
|
-
rescue Exception => e
|
17
|
-
$stderr.puts "Configuration import failed"
|
18
|
-
$stderr.puts e.message
|
19
|
-
exit! 1
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/etcd-tools/yaml2etcd.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'etcd'
|
3
|
-
require_relative 'etcd_tools/yaml2etcd/options'
|
4
|
-
require_relative 'etcd_tools/yaml2etcd/import'
|
5
|
-
|
6
|
-
module EtcdTools
|
7
|
-
class Yaml2Etcd
|
8
|
-
|
9
|
-
include EtcdTools::Yaml2Etcd::Options
|
10
|
-
include EtcdTools::Yaml2Etcd::Import
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
self.optparse
|
14
|
-
@etcd = self.class.connect(@options[:url], @options[:verbose])
|
15
|
-
@hash = self.class.read_yaml
|
16
|
-
import_structure @hash, @options[:root_path]
|
17
|
-
end
|
18
|
-
|
19
|
-
class << self
|
20
|
-
def read_yaml
|
21
|
-
begin
|
22
|
-
return YAML.load(ARGF.read)
|
23
|
-
rescue
|
24
|
-
$stderr.puts "Couldn't parse YAML"
|
25
|
-
exit! 1
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def connect (url, verbose=false)
|
30
|
-
(host, port) = url.gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
31
|
-
etcd = Etcd.client(host: host, port: port)
|
32
|
-
begin
|
33
|
-
etcd.version
|
34
|
-
puts "Connected to ETCD on #{host}:#{port}" if verbose
|
35
|
-
return etcd
|
36
|
-
rescue Exception => e
|
37
|
-
$stderr.puts "Couldn't connect to etcd at #{host}:#{port}"
|
38
|
-
$stderr.puts e.message
|
39
|
-
exit! 1
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|