etcd 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTQyMjkyOGM4NDVjZDUxZjkxZTBlYmMyMzdlMjYwMDAyOGJiZGEwYg==
4
+ NGE5YmE0ZDk3MDJmNjQzZDJkMWJhOTg2ZDNiODM4NGEyYzFlNDg0Yw==
5
5
  data.tar.gz: !binary |-
6
- ZGY4MjJlZGJhODY1NTQ0YTA1YjkxYmNhYmJiNDI2ZGVhMDMxMTZhYQ==
6
+ NTM0MzMyY2RlZWFlYjAxYTc2OGU3Mjk5YmEwOTlmYmJkN2NiZTJlNg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NDc5NmZkOTAwZGNhZjNkMjBmMTM3NWRmYTViYzE3YTkyMWY3Yzc3NjcxYjRi
10
- OWVmZDZkNWE3MzdjNWJhODgzN2RhZDg0NThhZWFiOTUxY2Y5ODU5MGE5NzJj
11
- NWRhZWJjZmNlM2IyNDJlNjBkZDVkZjYwZjgzNzEwMTY1NzhiOGE=
9
+ MGM0YzhmZDdmYmJmY2IyZmViYTEwMDlkNmNkMDQ2ZDhlNjE0Nzg4MDA0MjUw
10
+ MDcwY2QyNzA1MDEwN2IwZmMwMThlN2MxNTNmOGRiNDIyNTU5ZjcyY2I2NWQ5
11
+ ODI5MWU2ZDVjZjQxMDFhNTkyY2QzMWExMDYwNjBmNDk1OTJhYmE=
12
12
  data.tar.gz: !binary |-
13
- Njc1NGI2NWUyZGEzMWZhMmU0M2JkYjdiNDFmMWNkNzUxYTQ2YzI4NjFiNmVh
14
- NjBjYjcyNDBlMzczODg3YzcyNmZkNTllZTY0Y2UxMWM1ODU2ZDBlNzI5Y2M1
15
- NDJkNzAzYTZjYzlmNzRkY2E1OWI4NWI3ZmZkNjI3YWY3MTg4NDM=
13
+ YmM3ZWU4NDUzOWQwY2U2MzM0ZWI2YTM2MDMxOTJhOGE2OTJmNzUyNGM3Mzgw
14
+ OWViNGFmNDc3MjA5MWFkODQxYWI5YTQyMzlhMmFmM2RhYTIwOGI5NTI5NzI4
15
+ NDMzNjBmNmIwM2VlM2FlNWY4YjViOGY4MmRiZTI3NGYyODQ3MDI=
@@ -11,6 +11,8 @@ module Etcd
11
11
  # directly
12
12
  # If +opts+ is not passed default options are used, defined by Etcd::Client.new
13
13
  def self.client(opts = {})
14
- Etcd::Client.new(opts)
14
+ Etcd::Client.new(opts) do |config|
15
+ yield config if block_given?
16
+ end
15
17
  end
16
18
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'openssl'
4
4
  require 'net/http'
5
+ require 'net/https'
5
6
  require 'json'
6
7
  require 'etcd/log'
7
8
  require 'etcd/stats'
@@ -17,6 +18,9 @@ module Etcd
17
18
  # etcd api, like Etcd::Client#lock and Etcd::Client#eternal_watch, they
18
19
  # are defined in separate modules and included in this class
19
20
  class Client
21
+
22
+ extend Forwardable
23
+
20
24
  HTTP_REDIRECT = ->(r) { r.is_a? Net::HTTPRedirection }
21
25
  HTTP_SUCCESS = ->(r) { r.is_a? Net::HTTPSuccess }
22
26
  HTTP_CLIENT_ERROR = ->(r) { r.is_a? Net::HTTPClientError }
@@ -26,9 +30,14 @@ module Etcd
26
30
  include Mod::Lock
27
31
  include Mod::Leader
28
32
 
29
- attr_reader :host, :port, :http, :allow_redirect
30
- attr_reader :use_ssl, :verify_mode, :read_timeout
31
- attr_reader :user_name, :password
33
+ Config = Struct.new(:use_ssl, :verify_mode, :read_timeout, :ssl_key, :ca_file,
34
+ :user_name, :password, :allow_redirect, :ssl_cert)
35
+
36
+ def_delegators :@config, :use_ssl, :verify_mode, :read_timeout
37
+ def_delegators :@config, :user_name, :password, :allow_redirect
38
+
39
+
40
+ attr_reader :host, :port, :http, :config
32
41
 
33
42
  ##
34
43
  # Creates an Etcd::Client object. It accepts a hash +opts+ as argument
@@ -41,12 +50,15 @@ module Etcd
41
50
  def initialize(opts = {})
42
51
  @host = opts[:host] || '127.0.0.1'
43
52
  @port = opts[:port] || 4001
44
- @read_timeout = opts[:read_timeout] || 60
45
- @allow_redirect = opts.key?(:allow_redirect) ? opts[:allow_redirect] : true
46
- @use_ssl = opts[:use_ssl] || false
47
- @verify_mode = opts.key?(:verify_mode) ? opts[:verify_mode] : OpenSSL::SSL::VERIFY_PEER
48
- @user_name = opts[:user_name] || nil
49
- @password = opts[:password] || nil
53
+ @config = Config.new
54
+ @config.read_timeout = opts[:read_timeout] || 60
55
+ @config.allow_redirect = opts.key?(:allow_redirect) ? opts[:allow_redirect] : true
56
+ @config.use_ssl = opts[:use_ssl] || false
57
+ @config.verify_mode = opts.key?(:verify_mode) ? opts[:verify_mode] : OpenSSL::SSL::VERIFY_PEER
58
+ @config.user_name = opts[:user_name] || nil
59
+ @config.password = opts[:password] || nil
60
+ @config.allow_redirect = opts.key?(:allow_redirect) ? opts[:allow_redirect] : true
61
+ yield @config if block_given?
50
62
  end
51
63
  # rubocop:enable CyclomaticComplexity
52
64
 
@@ -94,8 +106,7 @@ module Etcd
94
106
  timeout = options[:timeout] || @read_timeout
95
107
  http = Net::HTTP.new(host, port)
96
108
  http.read_timeout = timeout
97
- http.use_ssl = use_ssl
98
- http.verify_mode = verify_mode
109
+ setup_https(http)
99
110
  req.basic_auth(user_name, password) if [user_name, password].all?
100
111
  Log.debug("Invoking: '#{req.class}' against '#{path}")
101
112
  res = http.request(req)
@@ -103,6 +114,23 @@ module Etcd
103
114
  process_http_request(res, req, params)
104
115
  end
105
116
 
117
+ def setup_https(http)
118
+ http.use_ssl = use_ssl
119
+ http.verify_mode = verify_mode
120
+ unless config.ssl_cert.nil?
121
+ Log.debug('Setting up ssl cert')
122
+ http.cert = config.ssl_cert
123
+ end
124
+ unless config.ssl_key.nil?
125
+ Log.debug('Setting up ssl key')
126
+ http.key = config.ssl_key
127
+ end
128
+ unless config.ca_file.nil?
129
+ Log.debug('Setting up ssl ca file to :' + config.ca_file)
130
+ http.ca_file = config.ca_file
131
+ end
132
+ end
133
+
106
134
  # need to ahve original request to process the response when it redirects
107
135
  def process_http_request(res, req = nil, params = nil)
108
136
  case res
@@ -5,7 +5,7 @@ module Etcd
5
5
  class Node
6
6
  include Comparable
7
7
 
8
- attr_reader :created_index, :modified_index, :expiration, :ttl, :key, :value
8
+ attr_reader :created_index, :modified_index, :expiration, :ttl, :key, :value, :dir
9
9
  alias_method :createdIndex, :created_index
10
10
  alias_method :modifiedIndex, :modified_index
11
11
 
@@ -1,5 +1,5 @@
1
1
  # Encoding: utf-8
2
2
  # Version const
3
3
  module Etcd
4
- VERSION = '0.2.2'
4
+ VERSION = '0.2.3'
5
5
  end
@@ -0,0 +1,23 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDxzCCAq+gAwIBAgIJAOHnywsV/TrCMA0GCSqGSIb3DQEBBQUAMHoxCzAJBgNV
3
+ BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtGb3N0ZXIgQ2l0
4
+ eTESMBAGA1UECgwJZXRjZC1ydWJ5MQswCQYDVQQDDAJDQTEfMB0GCSqGSIb3DQEJ
5
+ ARYQcmFuamliQGxpbnV4LmNvbTAeFw0xNDAzMTYwMjM2MjVaFw0xOTAzMTUwMjM2
6
+ MjVaMHoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQH
7
+ DAtGb3N0ZXIgQ2l0eTESMBAGA1UECgwJZXRjZC1ydWJ5MQswCQYDVQQDDAJDQTEf
8
+ MB0GCSqGSIb3DQEJARYQcmFuamliQGxpbnV4LmNvbTCCASIwDQYJKoZIhvcNAQEB
9
+ BQADggEPADCCAQoCggEBANf6jqt488XVaHDnXFT3KwXRuzs4fglJacRSXCjgfowN
10
+ QXgMawcycaX2/IZVk0FbQqiWZmS76ho5yaFny/GEHxKmeBchbLfciBbTWT6aJ5Kx
11
+ jDlLbMS9qZB+flV7dcUS+XYtNyDMAz52CnD5IvZSAXT0HADeATtZd49y9K6KE5Gc
12
+ 2Mff2Rco6Fs1+r5Pg3LPitqq4xU56ezb8TM+bDlG0czrhrGCm4IuwspYDJYFhWk5
13
+ v85d9s5WxenJsJaGfAwV3+XbSRymr/JHWHUd/UR+iMvQ4qGd7JBI5UJU9IpM0zuT
14
+ EgZRptBoZfLolqArqZbbWhif5+qRRtjkpiVfNMqSsksCAwEAAaNQME4wHQYDVR0O
15
+ BBYEFPIzKQ+nceGu6RbzP9jCNaIPZvNKMB8GA1UdIwQYMBaAFPIzKQ+nceGu6Rbz
16
+ P9jCNaIPZvNKMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJfbp690
17
+ nlbxr68RhAMtufqU9a+wBgh/U/Vlp5XlToCaDitdQToDkONuLnSx+sa2bnSg+gKs
18
+ dVNDYAat8jlJ6U3mIoC8zS7MPF0BCr9gXk7BQW/p0zZf0I62CbTkucBh5yE8WFB9
19
+ r7Z2UgpaJ6j95IVSRoVZ1gCbhKvN0o9dts4P8WD8ow3+kJ8n1wcPlZ5qvCzoDQNX
20
+ hJFE+vPN9UMP/oo4p/xzHJUysJcDwQ5k+Jqnl6wY289RibGaTfIFFWxqAKUVmxno
21
+ Ybkq5mZiXj0cs2lqw3zWYQ4xP6b50uECik+KZnBqYSmLP9s7d0qFgoA4ChFh5S1L
22
+ KY5mizc88rgPhlc=
23
+ -----END CERTIFICATE-----
@@ -0,0 +1,85 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number: 1 (0x1)
5
+ Signature Algorithm: sha1WithRSAEncryption
6
+ Issuer: C=US, ST=California, L=Foster City, O=etcd-ruby, CN=CA/emailAddress=ranjib@linux.com
7
+ Validity
8
+ Not Before: Mar 17 04:27:53 2014 GMT
9
+ Not After : Mar 17 04:27:53 2015 GMT
10
+ Subject: C=US, ST=California, L=Foster City, O=etcd-ruby-client, CN=localhost/emailAddress=ranjib@linux.com
11
+ Subject Public Key Info:
12
+ Public Key Algorithm: rsaEncryption
13
+ Public-Key: (2048 bit)
14
+ Modulus:
15
+ 00:dc:79:2c:aa:a0:6d:dd:09:72:29:6e:a2:67:a5:
16
+ 15:dd:b6:27:e2:e1:4a:ae:4c:2e:19:52:b3:31:2c:
17
+ 2b:8e:0b:62:bf:83:62:0e:a3:41:22:4c:6a:f1:84:
18
+ 4d:8f:18:22:13:53:56:79:44:df:9f:b8:e1:05:a4:
19
+ 7b:50:35:14:0c:9c:7c:40:ef:c3:27:1c:84:77:7c:
20
+ 0a:5e:ef:e7:ac:97:85:3c:ec:aa:32:5b:30:37:10:
21
+ 7b:2b:ab:ac:96:53:79:42:47:ff:5e:22:19:bb:c3:
22
+ 50:da:3d:75:ae:14:fa:68:f7:e6:e0:d5:a0:2d:60:
23
+ 0e:71:0b:a9:9f:ff:13:b7:d1:0f:e6:b9:e9:12:fa:
24
+ fb:ff:d7:a7:33:73:15:f7:1b:37:f1:2f:d7:4a:96:
25
+ 46:c8:30:b9:4a:a6:29:9b:c5:7c:c4:a6:e2:b7:08:
26
+ 74:2c:8f:25:0b:a9:a5:13:4f:03:e3:ae:d6:12:56:
27
+ 1d:b5:9b:b0:32:f4:84:f9:59:1e:10:30:a9:7a:c0:
28
+ f2:75:6d:44:c1:2d:9a:f2:4e:1e:59:af:f2:30:8e:
29
+ 12:8e:da:85:00:c3:c8:28:96:1e:59:98:49:a4:93:
30
+ 87:0f:b5:e8:0c:95:90:a8:20:3d:43:26:67:4e:9a:
31
+ ee:ac:5e:0a:40:53:2b:99:4c:db:9d:72:20:25:04:
32
+ d4:ab
33
+ Exponent: 65537 (0x10001)
34
+ X509v3 extensions:
35
+ X509v3 Basic Constraints:
36
+ CA:FALSE
37
+ Netscape Comment:
38
+ OpenSSL Generated Certificate
39
+ X509v3 Subject Key Identifier:
40
+ 3D:DA:77:1F:F0:A1:13:50:B4:CD:74:B3:45:90:F9:20:CB:EC:A1:79
41
+ X509v3 Authority Key Identifier:
42
+ keyid:F2:33:29:0F:A7:71:E1:AE:E9:16:F3:3F:D8:C2:35:A2:0F:66:F3:4A
43
+
44
+ X509v3 Extended Key Usage:
45
+ TLS Web Client Authentication
46
+ Signature Algorithm: sha1WithRSAEncryption
47
+ 3e:a5:65:e2:2d:95:d0:1f:56:d4:07:67:37:fb:f4:e0:30:95:
48
+ fd:a0:d0:a0:29:2d:2b:c1:33:d8:76:02:c7:17:e0:4e:88:30:
49
+ 26:4f:ec:99:b8:a6:0e:c4:e3:9f:3d:ce:fa:29:0b:58:51:a4:
50
+ 14:9f:1b:5b:ce:91:72:04:ed:f9:ac:55:6e:72:fe:81:2f:30:
51
+ c1:3b:6f:75:9d:56:af:d6:12:66:4d:95:24:c1:b9:c7:da:98:
52
+ 3f:9f:b1:ce:22:ba:f7:16:6a:37:e2:57:d1:b7:01:3b:30:7b:
53
+ 30:60:f6:f6:10:37:ef:8e:d8:fa:13:33:dd:d1:99:b7:65:07:
54
+ b0:e4:b9:04:2f:28:3d:b1:cf:6b:01:1b:8c:fe:ac:f3:db:6e:
55
+ e9:86:19:de:2a:c9:eb:f4:ae:d0:93:72:14:03:4a:63:dc:8e:
56
+ c6:76:fa:0e:4f:be:91:3b:3c:7e:44:f0:07:b1:06:4d:a6:d5:
57
+ 3b:c8:e3:4b:92:8f:43:1c:8b:e0:44:51:a0:55:1e:d9:33:23:
58
+ 77:83:6e:90:4b:aa:3b:d5:57:ed:73:bd:7b:f6:be:0c:d5:76:
59
+ 8e:ee:00:2d:ee:71:b5:f4:e0:ef:f5:2f:34:6e:25:ac:d2:2d:
60
+ 9d:50:ec:df:b9:fd:39:4b:b7:60:85:24:45:ca:0e:54:73:92:
61
+ a7:d0:62:d8
62
+ -----BEGIN CERTIFICATE-----
63
+ MIIEEDCCAvigAwIBAgIBATANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJVUzET
64
+ MBEGA1UECAwKQ2FsaWZvcm5pYTEUMBIGA1UEBwwLRm9zdGVyIENpdHkxEjAQBgNV
65
+ BAoMCWV0Y2QtcnVieTELMAkGA1UEAwwCQ0ExHzAdBgkqhkiG9w0BCQEWEHJhbmpp
66
+ YkBsaW51eC5jb20wHhcNMTQwMzE3MDQyNzUzWhcNMTUwMzE3MDQyNzUzWjCBiDEL
67
+ MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAcMC0Zvc3Rl
68
+ ciBDaXR5MRkwFwYDVQQKDBBldGNkLXJ1YnktY2xpZW50MRIwEAYDVQQDDAlsb2Nh
69
+ bGhvc3QxHzAdBgkqhkiG9w0BCQEWEHJhbmppYkBsaW51eC5jb20wggEiMA0GCSqG
70
+ SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDceSyqoG3dCXIpbqJnpRXdtifi4UquTC4Z
71
+ UrMxLCuOC2K/g2IOo0EiTGrxhE2PGCITU1Z5RN+fuOEFpHtQNRQMnHxA78MnHIR3
72
+ fApe7+esl4U87KoyWzA3EHsrq6yWU3lCR/9eIhm7w1DaPXWuFPpo9+bg1aAtYA5x
73
+ C6mf/xO30Q/muekS+vv/16czcxX3GzfxL9dKlkbIMLlKpimbxXzEpuK3CHQsjyUL
74
+ qaUTTwPjrtYSVh21m7Ay9IT5WR4QMKl6wPJ1bUTBLZryTh5Zr/IwjhKO2oUAw8go
75
+ lh5ZmEmkk4cPtegMlZCoID1DJmdOmu6sXgpAUyuZTNudciAlBNSrAgMBAAGjgZEw
76
+ gY4wCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg
77
+ Q2VydGlmaWNhdGUwHQYDVR0OBBYEFD3adx/woRNQtM10s0WQ+SDL7KF5MB8GA1Ud
78
+ IwQYMBaAFPIzKQ+nceGu6RbzP9jCNaIPZvNKMBMGA1UdJQQMMAoGCCsGAQUFBwMC
79
+ MA0GCSqGSIb3DQEBBQUAA4IBAQA+pWXiLZXQH1bUB2c3+/TgMJX9oNCgKS0rwTPY
80
+ dgLHF+BOiDAmT+yZuKYOxOOfPc76KQtYUaQUnxtbzpFyBO35rFVucv6BLzDBO291
81
+ nVav1hJmTZUkwbnH2pg/n7HOIrr3Fmo34lfRtwE7MHswYPb2EDfvjtj6EzPd0Zm3
82
+ ZQew5LkELyg9sc9rARuM/qzz227phhneKsnr9K7Qk3IUA0pj3I7GdvoOT76ROzx+
83
+ RPAHsQZNptU7yONLko9DHIvgRFGgVR7ZMyN3g26QS6o71Vftc7179r4M1XaO7gAt
84
+ 7nG19ODv9S80biWs0i2dUOzfuf05S7dghSRFyg5Uc5Kn0GLY
85
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDceSyqoG3dCXIp
3
+ bqJnpRXdtifi4UquTC4ZUrMxLCuOC2K/g2IOo0EiTGrxhE2PGCITU1Z5RN+fuOEF
4
+ pHtQNRQMnHxA78MnHIR3fApe7+esl4U87KoyWzA3EHsrq6yWU3lCR/9eIhm7w1Da
5
+ PXWuFPpo9+bg1aAtYA5xC6mf/xO30Q/muekS+vv/16czcxX3GzfxL9dKlkbIMLlK
6
+ pimbxXzEpuK3CHQsjyULqaUTTwPjrtYSVh21m7Ay9IT5WR4QMKl6wPJ1bUTBLZry
7
+ Th5Zr/IwjhKO2oUAw8golh5ZmEmkk4cPtegMlZCoID1DJmdOmu6sXgpAUyuZTNud
8
+ ciAlBNSrAgMBAAECggEAAeTcmF6mcvaoz2hO5tsJNA1jjFRpItQutTL7rRl3ClJY
9
+ t9J2HjAS2CuV45tCW09Ww5m8rXAFB8c7z6OZF5hNIsqZWql0oLpi/O/I2wXulJH8
10
+ qAhUcfhMkryGglqIMgZnjUU3EWTzmaRU5nsOrr8pY4t1pUrQhHNFzHzQKTq0vah/
11
+ CGWU4vd/F4P6NAuIhaWFbjkPJcKc/bNjGaoo/mh0JVlHzlA7soPmRr3Ki2ucHVsy
12
+ n24QApG+XULuJCUOV6EhaUFvKkCziId4xFoMqwAzzZ2sUiYt9+ftpZ9fB7Q6KcW0
13
+ MftW0P6ox3cTL/6HJ8gdHoQVDo/692kJAfWwaoKEyQKBgQDxRzx8OfCcXtMrB1D0
14
+ +dT9Do0sbaXY5MY59S1maCvbpDL/jApttSMM+R0BugKtTQjYykLYSKrRhp8JDOPO
15
+ L/XJ+7azfw01IduVvRE5auKwJohS1DJx1NexDF2OMKBOLVffbBdweHIwKDNde9ki
16
+ +ws1PJTrNcXTr+uoZ0BBDtg33wKBgQDp7PcoZHYcyBdBgUiFZdZWSLjHl3pRjcJY
17
+ qQT3sHDomweYx9kwafbf2iKPs0KLzfsHdFMvT/Og1Ks9mD9vZMoWVxia9J3/mlD5
18
+ 66imnXfcuN432kIqxwY2PArLsUOGJs9zCTr6Yed1XBHdBNEQWVmox+g8TdTyVZlk
19
+ xu3zANUstQKBgG+/D3t1lkPGA0VteQhM4WFmqOnHysUeh9R2AlXor09lyBzlLjtL
20
+ ZnVutwmCrhS3lf5aBwWG+l5aXDPj3Wo0ekDXLPILSQGvsbSzQVP3dhAheIfsMYTZ
21
+ ECC22mmticFLbORUerKjhjdZlxiX8KQr4y//4/TgDcSSOLHhSDgZePi/AoGAE6j6
22
+ zMZEtv6KFdNLyQpaDT5naT7t5NTJNLJf3IFTu/jrloeVVWBSg1XN+c3TFfTl2CaK
23
+ pztM+oNlMPQOwMnzwhTn2H4emVDa5WZM8lPhswdGheMuFHJNr1k0fxIS3r98R+rK
24
+ rih0T4TBa5XwDDO2OV0zw323G/bdwX6GmRnE0NECgYAZL+Nyz6kTvRhv4o68hubR
25
+ 3XmxgtGA8mQWq88aYN9xBvO4S5ixxV5qqWDVrKf7qdTerDkvTcEeDQ4ERdojQau5
26
+ HSppZrGs7ARsGvWOvSInXE2SNl8YjKKNqOD4SEAQy2xjblP9EAFmTaAG9RtUQFn9
27
+ MO7HMeev/i1iRK6q7OXZeg==
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,83 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number: 2 (0x2)
5
+ Signature Algorithm: sha1WithRSAEncryption
6
+ Issuer: C=US, ST=California, L=Foster City, O=etcd-ruby, CN=CA/emailAddress=ranjib@linux.com
7
+ Validity
8
+ Not Before: Mar 16 02:48:04 2014 GMT
9
+ Not After : Mar 16 02:48:04 2015 GMT
10
+ Subject: C=US, ST=California, L=Foster City, O=Default Company Ltd, CN=localhost/emailAddress=ranjib@linux.com
11
+ Subject Public Key Info:
12
+ Public Key Algorithm: rsaEncryption
13
+ Public-Key: (2048 bit)
14
+ Modulus:
15
+ 00:d3:d7:3f:b2:88:6b:48:c3:1f:ae:70:cf:a5:ec:
16
+ 71:1a:f0:3c:82:4f:29:84:d4:f9:01:d1:4e:b4:ba:
17
+ cf:72:88:06:55:01:c5:f6:83:d1:34:cf:3c:8b:40:
18
+ 1c:eb:0e:36:93:d4:08:2a:b3:1b:55:42:a2:12:40:
19
+ b5:c0:a1:51:22:9c:95:19:22:3e:a6:52:b9:5f:d9:
20
+ 04:45:bb:e6:95:13:61:7c:54:8e:17:07:f8:23:4c:
21
+ e7:dd:61:bc:71:78:5a:7e:c6:ae:1a:ec:05:b4:02:
22
+ 96:b4:ca:16:5a:50:25:e1:9d:df:ae:41:39:ff:64:
23
+ d3:33:87:53:36:51:68:8f:fe:92:9d:a7:02:53:be:
24
+ c8:be:bd:13:c0:34:d6:d4:a9:0a:84:9d:53:4e:37:
25
+ 42:57:70:5b:eb:5f:97:36:3c:1b:30:77:83:61:d9:
26
+ 43:ee:9a:8f:c4:40:13:ef:b2:d2:42:d2:85:f5:ca:
27
+ bb:92:8e:a6:85:9d:b5:fd:7b:6e:a9:46:33:35:5c:
28
+ 13:8d:71:9d:dd:7e:96:a2:da:98:c4:cc:33:00:aa:
29
+ a4:fc:41:b0:cb:80:13:57:19:d7:36:06:bc:d3:58:
30
+ 3c:ab:31:e6:db:3d:8b:52:bb:c2:97:22:72:8e:c2:
31
+ b8:9e:4a:a8:22:96:6f:9f:9d:a4:f5:8f:15:7d:9f:
32
+ 91:2b
33
+ Exponent: 65537 (0x10001)
34
+ X509v3 extensions:
35
+ X509v3 Basic Constraints:
36
+ CA:FALSE
37
+ Netscape Comment:
38
+ OpenSSL Generated Certificate
39
+ X509v3 Subject Key Identifier:
40
+ B1:24:B6:2E:99:A8:14:D8:86:84:FB:0B:26:A7:64:3B:29:59:B6:D9
41
+ X509v3 Authority Key Identifier:
42
+ keyid:F2:33:29:0F:A7:71:E1:AE:E9:16:F3:3F:D8:C2:35:A2:0F:66:F3:4A
43
+
44
+ Signature Algorithm: sha1WithRSAEncryption
45
+ 0e:a1:12:ce:cb:db:64:d3:61:a2:0e:0b:93:ea:16:7b:91:6f:
46
+ af:a6:0a:e8:bf:b5:a7:4a:60:41:fc:cc:d6:bb:8b:4c:00:f3:
47
+ 08:c6:31:41:57:7e:66:53:1e:41:93:e7:e2:62:e5:d6:9a:93:
48
+ ca:ef:b6:d1:1e:3d:ec:e4:fe:8e:1b:ac:4d:ef:16:56:09:8c:
49
+ d5:1a:30:c9:2f:13:1d:47:17:6e:67:26:9d:75:a1:9d:94:41:
50
+ f9:3e:b6:de:f5:e9:76:87:dc:c7:a9:d6:37:47:52:bf:2a:59:
51
+ 48:72:56:f0:89:d5:83:9c:35:f3:37:48:02:52:4a:a0:52:92:
52
+ fe:65:6b:7b:ce:57:0c:9b:93:56:48:86:c5:db:4f:df:dd:d4:
53
+ ac:9f:31:39:77:7b:3a:aa:f5:d8:95:db:28:e6:1b:47:9d:18:
54
+ c5:b2:38:88:2a:8a:5d:11:9d:aa:26:aa:8c:06:8a:20:b1:70:
55
+ 7e:2b:dd:fa:12:7b:32:64:c6:5b:54:d6:4a:aa:fb:a4:22:35:
56
+ 6b:69:9f:c6:c2:58:e7:79:6f:a6:4b:f5:25:64:55:ce:2f:69:
57
+ 52:76:1c:33:9e:97:3d:f5:f7:2c:67:29:30:55:86:65:5a:9a:
58
+ 7c:9c:79:80:f6:14:e3:8b:35:fb:7d:c9:a8:c0:86:24:07:9d:
59
+ 0d:c2:69:70
60
+ -----BEGIN CERTIFICATE-----
61
+ MIID/DCCAuSgAwIBAgIBAjANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJVUzET
62
+ MBEGA1UECAwKQ2FsaWZvcm5pYTEUMBIGA1UEBwwLRm9zdGVyIENpdHkxEjAQBgNV
63
+ BAoMCWV0Y2QtcnVieTELMAkGA1UEAwwCQ0ExHzAdBgkqhkiG9w0BCQEWEHJhbmpp
64
+ YkBsaW51eC5jb20wHhcNMTQwMzE2MDI0ODA0WhcNMTUwMzE2MDI0ODA0WjCBizEL
65
+ MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAcMC0Zvc3Rl
66
+ ciBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMRIwEAYDVQQDDAls
67
+ b2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEHJhbmppYkBsaW51eC5jb20wggEiMA0G
68
+ CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDT1z+yiGtIwx+ucM+l7HEa8DyCTymE
69
+ 1PkB0U60us9yiAZVAcX2g9E0zzyLQBzrDjaT1AgqsxtVQqISQLXAoVEinJUZIj6m
70
+ Urlf2QRFu+aVE2F8VI4XB/gjTOfdYbxxeFp+xq4a7AW0Apa0yhZaUCXhnd+uQTn/
71
+ ZNMzh1M2UWiP/pKdpwJTvsi+vRPANNbUqQqEnVNON0JXcFvrX5c2PBswd4Nh2UPu
72
+ mo/EQBPvstJC0oX1yruSjqaFnbX9e26pRjM1XBONcZ3dfpai2pjEzDMAqqT8QbDL
73
+ gBNXGdc2BrzTWDyrMebbPYtSu8KXInKOwrieSqgilm+fnaT1jxV9n5ErAgMBAAGj
74
+ ezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
75
+ IENlcnRpZmljYXRlMB0GA1UdDgQWBBSxJLYumagU2IaE+wsmp2Q7KVm22TAfBgNV
76
+ HSMEGDAWgBTyMykPp3HhrukW8z/YwjWiD2bzSjANBgkqhkiG9w0BAQUFAAOCAQEA
77
+ DqESzsvbZNNhog4Lk+oWe5Fvr6YK6L+1p0pgQfzM1ruLTADzCMYxQVd+ZlMeQZPn
78
+ 4mLl1pqTyu+20R497OT+jhusTe8WVgmM1RowyS8THUcXbmcmnXWhnZRB+T623vXp
79
+ dofcx6nWN0dSvypZSHJW8InVg5w18zdIAlJKoFKS/mVre85XDJuTVkiGxdtP393U
80
+ rJ8xOXd7Oqr12JXbKOYbR50YxbI4iCqKXRGdqiaqjAaKILFwfivd+hJ7MmTGW1TW
81
+ Sqr7pCI1a2mfxsJY53lvpkv1JWRVzi9pUnYcM56XPfX3LGcpMFWGZVqafJx5gPYU
82
+ 44s1+33JqMCGJAedDcJpcA==
83
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDT1z+yiGtIwx+u
3
+ cM+l7HEa8DyCTymE1PkB0U60us9yiAZVAcX2g9E0zzyLQBzrDjaT1AgqsxtVQqIS
4
+ QLXAoVEinJUZIj6mUrlf2QRFu+aVE2F8VI4XB/gjTOfdYbxxeFp+xq4a7AW0Apa0
5
+ yhZaUCXhnd+uQTn/ZNMzh1M2UWiP/pKdpwJTvsi+vRPANNbUqQqEnVNON0JXcFvr
6
+ X5c2PBswd4Nh2UPumo/EQBPvstJC0oX1yruSjqaFnbX9e26pRjM1XBONcZ3dfpai
7
+ 2pjEzDMAqqT8QbDLgBNXGdc2BrzTWDyrMebbPYtSu8KXInKOwrieSqgilm+fnaT1
8
+ jxV9n5ErAgMBAAECggEAMExdK3lK7JYAPSdfUHct+nRXd2ZREwXzl+R+y1nkPjqh
9
+ JvR2jBPVuPKe3SjK7xSYgO/QxNt9Gd1NUlgKmFavRvLoU4ipPAaUWTQDc1q54bc/
10
+ fLdShhG9E19PZfwImN5V0528yEqTqk0Ey0df/UtUt7Hk87fPX1k/hfoOkM3SxzFb
11
+ SUF+KjwGfUj1uY0s4mFjrikAtITU+fZWiC3yw4V3BaeISxuArXtwvd6j1Pr7UUQI
12
+ p6TAI8Xo49ZbvD7z/QxlOZM/FdvcZiW/74sxyOAP/e0bsQ0mzfTW3pFE1y2UHGyD
13
+ RQPJoUzbcl2OyjjCPLT9bgBj+HMXo8nrkW774apggQKBgQDt8eUo0Pc7OV4C/Yyp
14
+ dJ8QI2+7sROPweIa8thnzcX/bdBASelsUfs/neTgCUCXlXkrXyoVPZKSvyZg7fWU
15
+ w3uYspoC2m3Lr3XEqfRqeVaYO9AtAgYdbkfSmg63WOgalcckJDnGlvRKm/Sh+QRj
16
+ 1MwGZDTnTflecTtPpLxmdxIdCwKBgQDj6kdtgnfFAlknidQqx0++AsxdgdZnDHhH
17
+ 6vweSML1Ft6IpGVgsUhXszvSAlvh/jF4RKO8xGHNFtUXRNzqp1F4G781uMFgCkrq
18
+ 5UecLx/Jv2LjMUiQmpiPWruANitbyjeiC0knV1RgWsqIwVm02zb5/y9icrKnLpAf
19
+ mRSFJEGwYQKBgQC/AO5zVUsgv2w3+lBvtq34xnlqsTqCq6BVAZu1t/i4ke4ZrTsz
20
+ OJv29UhEjyjKhbI+nqWpZ0PBiK/GHz6DrGgKq1P19mEsoCxpMgSBc+WPTnRNrNI7
21
+ zcrZw9EMXNH0hUbWPD4krAht28MEQmDDwo4Ek2vkQTNsHHj/9b1Gg06HAQKBgQDB
22
+ YrBowyNNDskHO3PDOIr49vbhAKIjnfkRTNnP+H0z6Mu5tYQvnz167KH9d/LutvjS
23
+ y6sDKL6zfoQg0lWA5afC+ggsVS//hbw7w4AXjgSy8qm9jLu9tu9r89jU2SHBKLw7
24
+ ysevkfIOL/taPnUXeEoVpelW52ufX2r65LD8p971AQKBgQCJan1QX94RnThqPocH
25
+ NHQ2o20AV6vX/NZs4ydHADTrl+Kl2tK5ipfANe+iKZ54uSiPQRGQUFNA7+M3xcCU
26
+ 2Us+bS8/E06NADQlIAuVSCOVmRDLDDXwhr3brjxZ/Xq/WjLyWim0HNZq+W6HhL25
27
+ 149bGRGW4+GuqMEBR0jihvMh4A==
28
+ -----END PRIVATE KEY-----
@@ -4,8 +4,18 @@ require 'spec_helper'
4
4
 
5
5
  describe 'Etcd basic auth client' do
6
6
 
7
+ before(:all) do
8
+ start_daemon(2)
9
+ end
10
+ after(:all) do
11
+ stop_daemon
12
+ end
13
+
7
14
  let(:client) do
8
- Etcd.client(user_name: 'test', password: 'pwd')
15
+ Etcd.client(host: 'localhost') do |config|
16
+ config.user_name = 'test'
17
+ config.password = 'pwd'
18
+ end
9
19
  end
10
20
 
11
21
  it '#user_name' do
@@ -2,8 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  describe Etcd::Client do
4
4
 
5
+ before(:all) do
6
+ start_daemon(3)
7
+ end
8
+
9
+ after(:all) do
10
+ stop_daemon
11
+ end
12
+
5
13
  let(:client) do
6
- Etcd.client
14
+ etcd_client
7
15
  end
8
16
 
9
17
  it 'should return the leader address' do
@@ -32,8 +40,7 @@ describe Etcd::Client do
32
40
  it 'should redirect api request when allow_redirect is set' do
33
41
  key = random_key
34
42
  value = uuid.generate
35
- rd_client = Etcd.client host: 'localhost', port: 4003
36
- resp = rd_client.set(key, value: value)
43
+ resp = client.set(key, value: value)
37
44
  resp.node.key.should eql key
38
45
  resp.node.value.should eql value
39
46
  client.get(key).value.should eql resp.value
@@ -44,7 +51,7 @@ describe Etcd::Client do
44
51
  before(:all) do
45
52
  key = random_key
46
53
  value = uuid.generate
47
- @response = Etcd.client.set(key, value: value)
54
+ @response = etcd_client.set(key, value: value)
48
55
  end
49
56
 
50
57
  it '#etcd_index' do
@@ -2,67 +2,105 @@ require 'spec_helper'
2
2
 
3
3
  describe Etcd::Keys do
4
4
 
5
- let(:client) do
6
- Etcd.client
7
- end
8
-
9
- it '#set/#get' do
10
- key = random_key
11
- value = uuid.generate
12
- client.set(key, value: value)
13
- expect(client.get(key).value).to eq(value)
14
- end
5
+ shared_examples 'basic key operation' do
15
6
 
16
- context '#exists?' do
17
- it 'should be true for existing keys' do
7
+ it '#set/#get' do
18
8
  key = random_key
19
- client.create(key, value: 10)
20
- expect(client.exists?(key)).to be_true
21
- end
22
- it 'should be true for existing keys' do
23
- expect(client.exists?(random_key)).to be_false
9
+ value = uuid.generate
10
+ client.set(key, value: value)
11
+ expect(client.get(key).value).to eq(value)
24
12
  end
25
- end
26
13
 
27
- context 'directory' do
28
- it 'should be able to create a directory' do
29
- d = random_key
30
- client.create(d, dir: true)
31
- expect(client.get(d)).to be_true
32
- end
33
- context 'empty' do
34
- it 'should be able to delete with dir flag' do
35
- d = random_key
36
- client.create(d, dir: true)
37
- expect(client.delete(d, dir: true)).to be_true
14
+ context '#exists?' do
15
+ it 'should be true for existing keys' do
16
+ key = random_key
17
+ client.create(key, value: 10)
18
+ expect(client.exists?(key)).to be_true
38
19
  end
39
-
40
- it 'should not be able to delete without dir flag' do
41
- d = random_key
42
- client.create(d, dir: true)
43
- client.create("#{d}/foobar", value: 10)
44
- expect do
45
- client.delete(d)
46
- end.to raise_error(Etcd::NotFile)
20
+ it 'should be true for existing keys' do
21
+ expect(client.exists?(random_key)).to be_false
47
22
  end
48
23
  end
49
- context 'not empty' do
50
- it 'should be able to delete with recursive flag' do
24
+
25
+ context 'directory' do
26
+ it 'should be able to create a directory' do
51
27
  d = random_key
52
28
  client.create(d, dir: true)
53
- client.create("#{d}/foobar")
54
- expect do
55
- client.delete(d, dir: true, recursive: true)
56
- end.to_not raise_error
29
+ expect(client.get(d)).to be_true
57
30
  end
58
- it 'should be not able to delete without recursive flag' do
59
- d = random_key
60
- client.create(d, dir: true)
61
- client.create("#{d}/foobar")
62
- expect do
63
- client.delete(d, dir: true)
64
- end.to raise_error(Etcd::DirNotEmpty)
31
+ context 'empty' do
32
+ it 'should be able to delete with dir flag' do
33
+ d = random_key
34
+ client.create(d, dir: true)
35
+ expect(client.delete(d, dir: true)).to be_true
36
+ end
37
+
38
+ it 'should not be able to delete without dir flag' do
39
+ d = random_key
40
+ client.create(d, dir: true)
41
+ client.create("#{d}/foobar", value: 10)
42
+ expect do
43
+ client.delete(d)
44
+ end.to raise_error(Etcd::NotFile)
45
+ end
46
+ end
47
+ context 'not empty' do
48
+ it 'should be able to delete with recursive flag' do
49
+ d = random_key
50
+ client.create(d, dir: true)
51
+ client.create("#{d}/foobar")
52
+ expect do
53
+ client.delete(d, dir: true, recursive: true)
54
+ end.to_not raise_error
55
+ end
56
+ it 'should be not able to delete without recursive flag' do
57
+ d = random_key
58
+ client.create(d, dir: true)
59
+ client.create("#{d}/foobar")
60
+ expect do
61
+ client.delete(d, dir: true)
62
+ end.to raise_error(Etcd::DirNotEmpty)
63
+ end
65
64
  end
66
65
  end
67
66
  end
67
+
68
+ context 'without ssl' do
69
+ before(:all) do
70
+ start_daemon
71
+ end
72
+ after(:all) do
73
+ stop_daemon
74
+ end
75
+ let(:client) do
76
+ etcd_client
77
+ end
78
+ it_should_behave_like 'basic key operation'
79
+ end
80
+
81
+ context 'with ssl' do
82
+ before(:all) do
83
+ start_daemon(1, use_ssl: true)
84
+ end
85
+ after(:all) do
86
+ stop_daemon
87
+ end
88
+ let(:client) do
89
+ etcd_ssl_client
90
+ end
91
+ it_should_behave_like 'basic key operation'
92
+ end
93
+
94
+ context 'with ssl and client certificate' do
95
+ before(:all) do
96
+ start_daemon(1, use_ssl: true, check_client_cert: true )
97
+ end
98
+ after(:all) do
99
+ stop_daemon
100
+ end
101
+ let(:client) do
102
+ etcd_ssl_client_with_cert
103
+ end
104
+ it_should_behave_like 'basic key operation'
105
+ end
68
106
  end
@@ -4,8 +4,16 @@ require 'spec_helper'
4
4
 
5
5
  describe 'mod leader' do
6
6
 
7
+ before(:all) do
8
+ start_daemon
9
+ end
10
+
11
+ after(:all) do
12
+ stop_daemon
13
+ end
14
+
7
15
  let(:client) do
8
- Etcd.client
16
+ etcd_client
9
17
  end
10
18
 
11
19
  it 'should allow setting a key value with ttl' do
@@ -4,8 +4,16 @@ require 'spec_helper'
4
4
 
5
5
  describe 'lock' do
6
6
 
7
+ before(:all) do
8
+ start_daemon
9
+ end
10
+
11
+ after(:all) do
12
+ stop_daemon
13
+ end
14
+
7
15
  let(:client) do
8
- Etcd.client
16
+ etcd_client
9
17
  end
10
18
 
11
19
  it 'should be able to acquire a lock' do
@@ -2,8 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  describe Etcd::Node do
4
4
 
5
+ before(:all) do
6
+ start_daemon
7
+ end
8
+
9
+ after(:all) do
10
+ stop_daemon
11
+ end
12
+
5
13
  let(:client) do
6
- Etcd.client
14
+ etcd_client
7
15
  end
8
16
 
9
17
  it 'should create a directory with parent key when nested keys are set' do
@@ -4,8 +4,15 @@ require 'spec_helper'
4
4
 
5
5
  describe 'Etcd read only client' do
6
6
 
7
+ before(:all) do
8
+ start_daemon(3)
9
+ end
10
+ after(:all) do
11
+ stop_daemon
12
+ end
13
+
7
14
  let(:client) do
8
- Etcd.client
15
+ etcd_client
9
16
  end
10
17
 
11
18
  it 'should not allow write' do
@@ -4,6 +4,14 @@ require 'spec_helper'
4
4
 
5
5
  describe 'Etcd specs for the main etcd README examples' do
6
6
 
7
+ before(:all) do
8
+ start_daemon
9
+ end
10
+
11
+ after(:all) do
12
+ stop_daemon
13
+ end
14
+
7
15
  let(:client) do
8
16
  Etcd.client
9
17
  end
@@ -55,7 +63,7 @@ describe 'Etcd specs for the main etcd README examples' do
55
63
  context 'set a key named "/message"' do
56
64
 
57
65
  before(:all) do
58
- @response = Etcd.client.set('/message', value: 'PinkFloyd')
66
+ @response = etcd_client.set('/message', value: 'PinkFloyd')
59
67
  end
60
68
 
61
69
  it_should_behave_like 'response with valid http headers'
@@ -69,8 +77,8 @@ describe 'Etcd specs for the main etcd README examples' do
69
77
  context 'get a key named "/message"' do
70
78
 
71
79
  before(:all) do
72
- Etcd.client.set('/message', value: 'PinkFloyd')
73
- @response = Etcd.client.get('/message')
80
+ etcd_client.set('/message', value: 'PinkFloyd')
81
+ @response = etcd_client.get('/message')
74
82
  end
75
83
 
76
84
  it_should_behave_like 'response with valid http headers'
@@ -84,8 +92,8 @@ describe 'Etcd specs for the main etcd README examples' do
84
92
  context 'change the value of a key named "/message"' do
85
93
 
86
94
  before(:all) do
87
- Etcd.client.set('/message', value: 'World')
88
- @response = Etcd.client.set('/message', value: 'PinkFloyd')
95
+ etcd_client.set('/message', value: 'World')
96
+ @response = etcd_client.set('/message', value: 'PinkFloyd')
89
97
  end
90
98
 
91
99
  it_should_behave_like 'response with valid http headers'
@@ -99,9 +107,9 @@ describe 'Etcd specs for the main etcd README examples' do
99
107
  context 'delete a key named "/message"' do
100
108
 
101
109
  before(:all) do
102
- Etcd.client.set('/message', value: 'World')
103
- Etcd.client.set('/message', value: 'PinkFloyd')
104
- @response = Etcd.client.delete('/message')
110
+ etcd_client.set('/message', value: 'World')
111
+ etcd_client.set('/message', value: 'PinkFloyd')
112
+ @response = etcd_client.delete('/message')
105
113
  end
106
114
 
107
115
  it 'should set the return action to SET' do
@@ -115,9 +123,9 @@ describe 'Etcd specs for the main etcd README examples' do
115
123
  context 'using ttl a key named "/message"' do
116
124
 
117
125
  before(:all) do
118
- Etcd.client.set('/message', value: 'World')
126
+ etcd_client.set('/message', value: 'World')
119
127
  @set_time = Time.now
120
- @response = Etcd.client.set('/message', value: 'PinkFloyd', ttl: 5)
128
+ @response = etcd_client.set('/message', value: 'PinkFloyd', ttl: 5)
121
129
  end
122
130
 
123
131
  it_should_behave_like 'response with valid http headers'
@@ -138,7 +146,7 @@ describe 'Etcd specs for the main etcd README examples' do
138
146
  it 'should throw exception after the expiration time' do
139
147
  sleep 8
140
148
  expect do
141
- Etcd.client.get('/message')
149
+ client.get('/message')
142
150
  end.to raise_error
143
151
  end
144
152
 
@@ -147,11 +155,12 @@ describe 'Etcd specs for the main etcd README examples' do
147
155
  context 'waiting for a change against a key named "/message"' do
148
156
 
149
157
  before(:all) do
150
- Etcd.client.set('/message', value: 'foo')
158
+ etcd_client.set('/message', value: 'foo')
151
159
  thr = Thread.new do
152
- @response = Etcd.client.watch('/message')
160
+ @response = etcd_client.watch('/message')
153
161
  end
154
- Etcd.client.set('/message', value: 'PinkFloyd')
162
+ sleep 1
163
+ etcd_client.set('/message', value: 'PinkFloyd')
155
164
  thr.join
156
165
  end
157
166
 
@@ -172,7 +181,7 @@ describe 'Etcd specs for the main etcd README examples' do
172
181
  context 'atomic in-order keys' do
173
182
 
174
183
  before(:all) do
175
- @response = Etcd.client.create_in_order('/queue', value: 'PinkFloyd')
184
+ @response = etcd_client.create_in_order('/queue', value: 'PinkFloyd')
176
185
  end
177
186
 
178
187
  it_should_behave_like 'response with valid http headers'
@@ -212,7 +221,7 @@ describe 'Etcd specs for the main etcd README examples' do
212
221
  context 'directory with ttl' do
213
222
 
214
223
  before(:all) do
215
- @response = Etcd.client.set('/directory', dir: true, ttl: 4)
224
+ @response = etcd_client.set('/directory', dir: true, ttl: 4)
216
225
  end
217
226
 
218
227
  it 'should create a directory' do
@@ -300,8 +309,8 @@ describe 'Etcd specs for the main etcd README examples' do
300
309
  context 'hidden nodes' do
301
310
 
302
311
  before(:all) do
303
- Etcd.client.set('/_message', value: 'Hello Hidden World')
304
- Etcd.client.set('/message', value: 'Hello World')
312
+ etcd_client.set('/_message', value: 'Hello Hidden World')
313
+ etcd_client.set('/message', value: 'Hello World')
305
314
  end
306
315
 
307
316
  it 'should not be visible in directory listing' do
@@ -4,8 +4,16 @@ require 'spec_helper'
4
4
 
5
5
  describe Etcd::Stats do
6
6
 
7
+ before(:all) do
8
+ start_daemon(5)
9
+ end
10
+
11
+ after(:all) do
12
+ stop_daemon
13
+ end
14
+
7
15
  let(:client) do
8
- Etcd.client
16
+ etcd_client
9
17
  end
10
18
 
11
19
  describe 'of leader' do
@@ -4,8 +4,16 @@ require 'spec_helper'
4
4
 
5
5
  describe 'Etcd test_and_set' do
6
6
 
7
+ before(:all) do
8
+ start_daemon
9
+ end
10
+
11
+ after(:all) do
12
+ stop_daemon
13
+ end
14
+
7
15
  let(:client) do
8
- Etcd.client
16
+ etcd_client
9
17
  end
10
18
 
11
19
  it 'should pass when prev value is correct' do
@@ -4,8 +4,16 @@ require 'spec_helper'
4
4
 
5
5
  describe 'Etcd watch' do
6
6
 
7
+ before(:all) do
8
+ start_daemon
9
+ end
10
+
11
+ after(:all) do
12
+ stop_daemon
13
+ end
14
+
7
15
  let(:client) do
8
- Etcd.client
16
+ etcd_client
9
17
  end
10
18
 
11
19
  it 'without index, returns the value at a particular index' do
@@ -27,6 +35,7 @@ describe 'Etcd watch' do
27
35
  thr = Thread.new do
28
36
  response = client.watch(key)
29
37
  end
38
+ sleep 2
30
39
  client.set(key, value: value)
31
40
  thr.join
32
41
  expect(response.node.value).to eq(value)
@@ -6,12 +6,51 @@ $LOAD_PATH.unshift(File.expand_path('../spec', __FILE__))
6
6
  require 'coco'
7
7
  require 'uuid'
8
8
  require 'etcd'
9
+ require 'singleton'
9
10
 
10
11
  module Etcd
11
- module SpecHelper
12
- @@pids = []
12
+ class Spawner
13
+
14
+ include Singleton
15
+
16
+ def initialize
17
+ @pids = []
18
+ @cert_file = File.expand_path('../data/server.crt', __FILE__)
19
+ @key_file = File.expand_path('../data/server.key', __FILE__)
20
+ @ca_cert = File.expand_path('../data/ca.crt', __FILE__)
21
+ end
22
+
23
+ def etcd_servers
24
+ @pids.size.times.inject([]){|servers, n| servers << "http://127.0.0.1:700#{n}" }
25
+ end
26
+
27
+ def start(numbers = 1, opts={})
28
+ raise "Already running etcd servers(#{@pids.inspect})" unless @pids.empty?
29
+ @tmpdir = Dir.mktmpdir
30
+ ssl_args = ""
31
+ ssl_args << " -cert-file=#{@cert_file} -key-file=#{@key_file}" if opts[:use_ssl]
32
+ ssl_args << " -ca-file=#{@ca_cert}" if opts[:check_client_cert]
33
+ @pids << daemonize(@tmpdir, ssl_args)
34
+ (numbers - 1).times do |n|
35
+ @pids << daemonize(@tmpdir, ssl_args)
36
+ end
37
+ end
13
38
 
14
- def self.etcd_binary
39
+ def daemonize(dir, ssl_args)
40
+ client_port = 4001 + @pids.size
41
+ server_port = 7001 + @pids.size
42
+ leader = '127.0.0.1:7001'
43
+ args = " -addr 127.0.0.1:#{client_port} -peer-addr 127.0.0.1:#{server_port}"
44
+ args << " -data-dir #{dir + client_port.to_s} -name node_#{client_port}"
45
+ command = etcd_binary + args + ssl_args
46
+ command << " -peers #{leader}" unless @pids.empty? # if pids are not empty, theres a daemon already
47
+ pid = spawn(command, out: '/dev/null')
48
+ sleep 1
49
+ Process.detach(pid)
50
+ pid
51
+ end
52
+
53
+ def etcd_binary
15
54
  if File.exists? './etcd/bin/etcd'
16
55
  './etcd/bin/etcd'
17
56
  elsif !!ENV['ETCD_BIN']
@@ -21,37 +60,23 @@ module Etcd
21
60
  end
22
61
  end
23
62
 
24
- def self.start_etcd_servers
25
- @@tmpdir = Dir.mktmpdir
26
- pid = spawn_etcd_server(@@tmpdir + '/leader')
27
- @@pids = Array(pid)
28
- leader = '127.0.0.1:7001'
29
- 4.times do |n|
30
- client_port = 4002 + n
31
- server_port = 7002 + n
32
- pid = spawn_etcd_server(@@tmpdir + client_port.to_s, client_port, server_port, leader)
33
- @@pids << pid
63
+ def stop
64
+ @pids.each do |pid|
65
+ Process.kill('TERM', pid)
34
66
  end
67
+ FileUtils.remove_entry_secure(@tmpdir, true)
68
+ @pids.clear
35
69
  end
70
+ end
36
71
 
37
- def self.stop_etcd_servers
38
- @@pids.each do |pid|
39
- Process.kill('TERM', pid)
40
- end
41
- FileUtils.remove_entry_secure(@@tmpdir, true)
72
+ module SpecHelper
73
+
74
+ def start_daemon(numbers = 1, opts={})
75
+ Spawner.instance.start(numbers, opts)
42
76
  end
43
77
 
44
- def self.spawn_etcd_server(dir, client_port = 4001, server_port = 7001, leader = nil)
45
- args = " -addr 127.0.0.1:#{client_port} -peer-addr 127.0.0.1:#{server_port} -data-dir #{dir} -name node_#{client_port}"
46
- command = if leader.nil?
47
- etcd_binary + args
48
- else
49
- etcd_binary + args + " -peers #{leader}"
50
- end
51
- pid = spawn(command, out: '/dev/null')
52
- Process.detach(pid)
53
- sleep 1
54
- pid
78
+ def stop_daemon
79
+ Spawner.instance.stop
55
80
  end
56
81
 
57
82
  def uuid
@@ -66,27 +91,41 @@ module Etcd
66
91
  key
67
92
  end
68
93
 
69
- def etcd_servers
70
- (1..5).map { |n| "http://127.0.0.1:700#{n}" }
94
+ def etcd_ssl_client
95
+ Etcd.client(host: 'localhost') do |config|
96
+ config.use_ssl = true
97
+ config.ca_file = File.expand_path('../data/ca.crt', __FILE__)
98
+ end
71
99
  end
72
100
 
73
- def other_client
101
+ def etcd_ssl_client
102
+ Etcd.client(host: 'localhost') do |config|
103
+ config.use_ssl = true
104
+ config.ca_file = File.expand_path('../data/ca.crt', __FILE__)
105
+ end
106
+ end
107
+
108
+ def etcd_ssl_client_with_cert
109
+ client_cert = File.expand_path('../data/client.crt', __FILE__)
110
+ client_key = File.expand_path('../data/client.key', __FILE__)
111
+ Etcd.client(host: 'localhost') do |config|
112
+ config.use_ssl = true
113
+ config.ca_file = File.expand_path('../data/ca.crt', __FILE__)
114
+ config.ssl_cert = OpenSSL::X509::Certificate.new(File.read(client_cert))
115
+ config.ssl_key = OpenSSL::PKey::RSA.new(File.read(client_key))
116
+ end
117
+ end
118
+
119
+ def etcd_client
74
120
  Etcd.client
75
121
  end
76
122
 
77
123
  def read_only_client
78
- Etcd.client(allow_redirect: false, port: 4004)
124
+ Etcd.client(allow_redirect: false, port: 4002, host: 'localhost')
79
125
  end
80
126
  end
81
127
  end
82
128
 
83
129
  RSpec.configure do |c|
84
-
85
130
  c.include Etcd::SpecHelper
86
- c.before(:suite) do
87
- Etcd::SpecHelper.start_etcd_servers
88
- end
89
- c.after(:suite) do
90
- Etcd::SpecHelper.stop_etcd_servers
91
- end
92
131
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etcd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ranjib Dey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-13 00:00:00.000000000 Z
11
+ date: 2014-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-log
@@ -110,6 +110,11 @@ files:
110
110
  - lib/etcd/response.rb
111
111
  - lib/etcd/stats.rb
112
112
  - lib/etcd/version.rb
113
+ - spec/data/ca.crt
114
+ - spec/data/client.crt
115
+ - spec/data/client.key
116
+ - spec/data/server.crt
117
+ - spec/data/server.key
113
118
  - spec/etcd/basic_auth_client_spec.rb
114
119
  - spec/etcd/client_spec.rb
115
120
  - spec/etcd/keys_spec.rb
@@ -147,6 +152,11 @@ signing_key:
147
152
  specification_version: 4
148
153
  summary: Ruby client library for etcd
149
154
  test_files:
155
+ - spec/data/ca.crt
156
+ - spec/data/client.crt
157
+ - spec/data/client.key
158
+ - spec/data/server.crt
159
+ - spec/data/server.key
150
160
  - spec/etcd/basic_auth_client_spec.rb
151
161
  - spec/etcd/client_spec.rb
152
162
  - spec/etcd/keys_spec.rb