etcd-tools 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|