consul-ruby-client 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -3
- data/bin/build_install.sh +5 -0
- data/build/.gitignore +9 -0
- data/build/CODE_OF_CONDUCT.md +13 -0
- data/build/Gemfile +4 -0
- data/build/LICENSE.txt +21 -0
- data/build/README.md +39 -0
- data/build/Rakefile +1 -0
- data/build/bin/console +14 -0
- data/build/bin/setup +7 -0
- data/build/build.gemspec +32 -0
- data/build/lib/build/version.rb +3 -0
- data/build/lib/build.rb +5 -0
- data/lib/consul/client/agent.rb +2 -5
- data/lib/consul/client/base.rb +21 -8
- data/lib/consul/client/key_value.rb +36 -44
- data/lib/consul/client/session.rb +3 -3
- data/lib/consul/client/version.rb +1 -1
- data/lib/consul/extensions/base.rb +15 -3
- data/lib/consul/extensions/uid.rb +84 -19
- data/lib/setup.rb +8 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 892b1008577e86cdd860d5fd19b89d0baf32e79d
|
4
|
+
data.tar.gz: cb395d778d0cbd68ab6d1e219bb7e0563e78a239
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffdbe76cafaca0b747f969595253c2138e32f0ab7ae61721403ac5687c134cd6d80272ae1441b5abea96f04f6224025fae22ca58cac74a3b0f99144bafe05c60
|
7
|
+
data.tar.gz: 4c8081a66dd8fb5937de79d42e4cea7ff8316c7300243ec1f1bd209b28d94d9f29a526314f8ffb408e4655a5748a21c741252b3d415f6a08973c9f8b9e3845f6
|
data/README.md
CHANGED
@@ -42,9 +42,8 @@ kvs.get('cat')
|
|
42
42
|
### Agent
|
43
43
|
|
44
44
|
```
|
45
|
-
|
46
|
-
|
47
|
-
agent.services
|
45
|
+
# Register a service named 'my_service'
|
46
|
+
Consul::Client::Agent.new.register(Agent::Service.for_name('my_service'))
|
48
47
|
```
|
49
48
|
|
50
49
|
### Catalog
|
data/build/.gitignore
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/build/Gemfile
ADDED
data/build/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Michael Hotan
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/build/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Build
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/build`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'build'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install build
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
1. Fork it ( https://github.com/[my-github-username]/build/fork )
|
36
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
37
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
39
|
+
5. Create a new Pull Request
|
data/build/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/build/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "build"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/build/bin/setup
ADDED
data/build/build.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'build/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "build"
|
8
|
+
spec.version = Build::VERSION
|
9
|
+
spec.authors = ["Michael Hotan"]
|
10
|
+
spec.email = ["michael.hotan@socrata.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{TODO: Write a short summary, because Rubygems requires one.}
|
13
|
+
spec.description = %q{TODO: Write a longer description or delete this line.}
|
14
|
+
spec.homepage = "TODO: Put your gem's website or public repo URL here."
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
+
end
|
data/build/lib/build.rb
ADDED
data/lib/consul/client/agent.rb
CHANGED
@@ -127,7 +127,7 @@ module Consul
|
|
127
127
|
|
128
128
|
# Public: deregisters an existing ConsulHealthCheck or ConsulService
|
129
129
|
#
|
130
|
-
# entity -
|
130
|
+
# entity - Consul::Model::HealthCheck or Consul::Model::ConsulService to unregister from this
|
131
131
|
#
|
132
132
|
# Returns - the HTTP Response
|
133
133
|
def deregister(entity)
|
@@ -273,15 +273,12 @@ module Consul
|
|
273
273
|
end
|
274
274
|
end
|
275
275
|
|
276
|
-
# Public: Creates a health check meant to be used when registering a service.
|
277
|
-
#
|
278
|
-
#
|
279
|
-
#
|
280
276
|
# Returns: Consul::Model::HealthCheck instance that represents a script
|
281
277
|
def self.script_health_check(script, interval)
|
282
278
|
Consul::Model::HealthCheck.new(script: script, interval: interval)
|
283
279
|
end
|
284
280
|
|
281
|
+
# Returns: Consul::Model::HealthCheck instance that represents a http health check.
|
285
282
|
def self.http_health_check(http, interval)
|
286
283
|
Consul::Model::HealthCheck.new(http: http, interval: interval)
|
287
284
|
end
|
data/lib/consul/client/base.rb
CHANGED
@@ -50,7 +50,14 @@ module Consul
|
|
50
50
|
opts[:params] = params unless params.nil?
|
51
51
|
opts[:accept] = :json if json_only
|
52
52
|
begin
|
53
|
-
|
53
|
+
resp = RestClient.get url, opts
|
54
|
+
success = (resp.code == 200 or resp.code == 201)
|
55
|
+
if success
|
56
|
+
logger.debug("Successful GET at endpoint #{url}")
|
57
|
+
else
|
58
|
+
logger.warn("Unable to GET from endpoint #{url} returned code: #{resp.code}")
|
59
|
+
end
|
60
|
+
return resp
|
54
61
|
rescue Exception => e
|
55
62
|
# Unable to communicate with consul agent.
|
56
63
|
logger.warn(e.message)
|
@@ -71,16 +78,22 @@ module Consul
|
|
71
78
|
# Validation
|
72
79
|
validate_url(url)
|
73
80
|
|
74
|
-
|
75
|
-
|
81
|
+
# If possible, Convert value to json
|
82
|
+
unless Consul::Utils.valid_json?(value)
|
83
|
+
value = value.to_json if value.respond_to?(:to_json)
|
84
|
+
end
|
85
|
+
|
86
|
+
opts = {}
|
87
|
+
opts[:params] = params unless params.nil?
|
76
88
|
begin
|
77
|
-
if Consul::Utils.valid_json?(value)
|
78
|
-
|
89
|
+
opts[:content_type] = :json if Consul::Utils.valid_json?(value)
|
90
|
+
resp = RestClient.put(url, value, opts) {|response, req, res| response }
|
91
|
+
success = (resp.code == 200 or resp.code == 201)
|
92
|
+
if success
|
93
|
+
logger.debug("Successful PUT #{value} at endpoint #{url}")
|
79
94
|
else
|
80
|
-
|
95
|
+
logger.warn("Unable to PUT #{value} at endpoint #{url} returned code: #{resp.code}")
|
81
96
|
end
|
82
|
-
success = (resp.code == 200 or resp.code == 201)
|
83
|
-
logger.warn("Unable to send #{value} to endpoint #{url} returned code: #{resp.code}") unless success
|
84
97
|
return success, resp.body
|
85
98
|
rescue Exception => e
|
86
99
|
logger.error('RestClient.put Error: Unable to reach consul agent')
|
@@ -25,24 +25,22 @@ module Consul
|
|
25
25
|
#
|
26
26
|
# Reference: https://www.consul.io/docs/agent/http/kv.html
|
27
27
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
28
|
+
# Params:
|
29
|
+
# key - Key to get value for
|
30
|
+
# params - Parameter hash for Consul
|
31
|
+
# params[:recurse] - existence of any value with tell consul to remove all keys
|
32
|
+
# with the same prefix
|
33
|
+
# params[:index] - Existence of :index, indicates to use a blocking call
|
34
|
+
# params[:keys] - Existence of :keys, indicates to only return keys
|
35
|
+
# params[:separator] - List only up to a given separator
|
33
36
|
#
|
34
37
|
# Returns: An array of Consul::Model::KeyValue objects, if only
|
35
|
-
def get(key,
|
36
|
-
recurse = false,
|
37
|
-
index = false,
|
38
|
-
only_keys = false,
|
39
|
-
separator = nil)
|
38
|
+
def get(key, params = {})
|
40
39
|
key = sanitize(key)
|
41
|
-
params = {}
|
42
|
-
params[:recurse] = nil if recurse
|
43
|
-
params[:index] = nil if index
|
44
|
-
params[:keys] = nil if
|
45
|
-
params[:separator] = separator unless separator.nil?
|
40
|
+
params = {} if params.nil?
|
41
|
+
params[:recurse] = nil if params.has_key?(:recurse)
|
42
|
+
params[:index] = nil if params.has_key?(:index)
|
43
|
+
params[:keys] = nil if params.has_key?(:keys)
|
46
44
|
begin
|
47
45
|
resp = _get build_url(compose_key(key)), params
|
48
46
|
rescue Exception => e
|
@@ -51,10 +49,10 @@ module Consul
|
|
51
49
|
end
|
52
50
|
return nil if resp.code == 404
|
53
51
|
json = JSON.parse(resp)
|
54
|
-
return json if
|
52
|
+
return json if params.has_key?(:keys)
|
55
53
|
json.map { |kv|
|
56
54
|
kv = Consul::Model::KeyValue.new.extend(Consul::Model::KeyValue::Representer).from_hash(kv)
|
57
|
-
kv.value = Base64.decode64(kv.value)
|
55
|
+
kv.value = Base64.decode64(kv.value) unless kv.value.nil?
|
58
56
|
kv
|
59
57
|
}
|
60
58
|
end
|
@@ -65,46 +63,39 @@ module Consul
|
|
65
63
|
#
|
66
64
|
# Reference: https://www.consul.io/docs/agent/http/kv.html
|
67
65
|
#
|
68
|
-
# key
|
69
|
-
# value
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
66
|
+
# key - Key
|
67
|
+
# value - Value to assign for Key
|
68
|
+
# params - Consul Parameter Hash
|
69
|
+
# params[:flags] - Unsigned value between 0 and 2^(64-1). General purpose parameter.
|
70
|
+
# params[:cas] - Modify index for Check and set operation.
|
71
|
+
# params[:acquire] - session id to use to lock.
|
72
|
+
# params[:release] - session id to use to unlock.
|
74
73
|
#
|
75
74
|
# Returns: True on success, False on failure
|
76
75
|
# Throws: IOError: Unable to contact Consul Agent.
|
77
|
-
def put(key,
|
78
|
-
value,
|
79
|
-
flags = nil,
|
80
|
-
cas = nil,
|
81
|
-
acquire_session = nil,
|
82
|
-
release_session = nil)
|
76
|
+
def put(key, value, params = {})
|
83
77
|
key = sanitize(key)
|
84
|
-
params = {}
|
85
|
-
params[:flags] = flags unless flags.nil?
|
86
|
-
params[:cas] = cas unless cas.nil?
|
87
|
-
params[:acquire] = acquire_session unless acquire_session.nil?
|
88
|
-
params[:release_session] = release_session unless release_session.nil?
|
78
|
+
params = {} if params.nil?
|
89
79
|
begin
|
90
80
|
value = JSON.generate(value)
|
91
81
|
rescue JSON::GeneratorError
|
92
|
-
logger.debug("Using non-JSON value for key #{key}")
|
82
|
+
logger.debug("Using non-JSON value: #{value} for key #{key}")
|
93
83
|
end
|
94
|
-
_put build_url(compose_key(key)), value,
|
84
|
+
_put build_url(compose_key(key)), value, params
|
95
85
|
end
|
96
86
|
|
97
87
|
# Public: Delete the Key Value pair in consul.
|
98
88
|
#
|
99
|
-
# key
|
100
|
-
#
|
101
|
-
#
|
102
|
-
|
89
|
+
# key - Key
|
90
|
+
# params - Parameter Hash
|
91
|
+
# params[:recurse] - Existence of key notifies that all sub keys will be deleted
|
92
|
+
# params[:cas] - Modify index for Check and set operation.
|
93
|
+
#
|
94
|
+
def delete(key, params = {})
|
103
95
|
key = sanitize(key)
|
104
96
|
params = {}
|
105
|
-
params[:recurse] = nil if recurse
|
106
|
-
|
107
|
-
RestClient.delete build_url(key), {:params => params}
|
97
|
+
params[:recurse] = nil if params.has_key?(:recurse)
|
98
|
+
RestClient.delete build_url(compose_key(key)), {:params => params}
|
108
99
|
end
|
109
100
|
|
110
101
|
# Public: Returns the name space of this KeyValue Store. This allows you to
|
@@ -131,10 +122,11 @@ module Consul
|
|
131
122
|
key[key.length - 1] = ''
|
132
123
|
end
|
133
124
|
end
|
125
|
+
key
|
134
126
|
end
|
135
127
|
|
136
128
|
def compose_key(key)
|
137
|
-
ns = namespace.strip
|
129
|
+
ns = sanitize(namespace.strip)
|
138
130
|
return "#{key}" if ns.empty?
|
139
131
|
"#{ns}/#{key}"
|
140
132
|
end
|
@@ -42,14 +42,14 @@ module Consul
|
|
42
42
|
# session - Session to create.
|
43
43
|
# dc - Consul data center
|
44
44
|
#
|
45
|
-
# Returns The Session ID
|
45
|
+
# Returns The Session ID
|
46
46
|
def create(session, dc = nil)
|
47
47
|
raise TypeError, 'Session must be of type Consul::Model::Session' unless session.kind_of? Consul::Model::Session
|
48
48
|
params = {}
|
49
49
|
params[:dc] = dc unless dc.nil?
|
50
50
|
success, body = _put(build_url('create'), session.extend(Consul::Model::Session::Representer).to_json, params)
|
51
51
|
return Consul::Model::Session.new.extend(Consul::Model::Service::Representer).from_json(body) if success
|
52
|
-
logger.warn("Unable to create session with #{session}")
|
52
|
+
logger.warn("Unable to create session with #{session} reason: #{body}")
|
53
53
|
nil
|
54
54
|
end
|
55
55
|
|
@@ -98,7 +98,7 @@ module Consul
|
|
98
98
|
session = extract_session_id(session)
|
99
99
|
params = {}
|
100
100
|
params[:dc] = dc unless dc.nil?
|
101
|
-
success, _ = _put build_url("renew/#{session
|
101
|
+
success, _ = _put build_url("renew/#{session}"), session.to_json
|
102
102
|
success
|
103
103
|
end
|
104
104
|
|
@@ -1,8 +1,12 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require_relative '../../../lib/consul/client/agent'
|
3
|
+
require_relative '../../../lib/consul/client/key_value'
|
4
|
+
require_relative '../../../lib/consul/client/session'
|
1
5
|
|
2
6
|
module Consul
|
3
7
|
module Extensions
|
4
8
|
class Base
|
5
|
-
|
9
|
+
include Consul::Client
|
6
10
|
# Public: Constructor for this extension. Ensures a global unique ID for this client for a given namespace.
|
7
11
|
#
|
8
12
|
# options - (Optional) Hash of Consul Client and extension options.
|
@@ -27,12 +31,20 @@ module Consul
|
|
27
31
|
|
28
32
|
# The Consul Agent Client to use
|
29
33
|
def agent
|
30
|
-
@agent
|
34
|
+
@agent ||= Agent.new(options)
|
31
35
|
end
|
32
36
|
|
33
37
|
# The Key Value Store to use.
|
34
38
|
def key_value_store
|
35
|
-
@kvs
|
39
|
+
@kvs ||= KeyValue.new(options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def session
|
43
|
+
@session || Session.new(options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def logger
|
47
|
+
@logger ||= options[:logger] || Logger.new(STDOUT)
|
36
48
|
end
|
37
49
|
|
38
50
|
# TODO Add other clients here.
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative 'base'
|
2
2
|
require_relative '../../consul/client/key_value'
|
3
|
+
require_relative '../model/member'
|
3
4
|
|
4
5
|
module Consul
|
5
6
|
module Extensions
|
@@ -11,6 +12,8 @@ module Consul
|
|
11
12
|
class UID < Base
|
12
13
|
include Consul::Client
|
13
14
|
|
15
|
+
MAX_ATTEMPTS = 10
|
16
|
+
|
14
17
|
# Public: Constructor for this extension. Ensures a global unique ID for this client for a given namespace.
|
15
18
|
#
|
16
19
|
# options - (Required) Hash of Consul Client and extension options.
|
@@ -28,44 +31,106 @@ module Consul
|
|
28
31
|
# Extension instance capable of generating GUID.
|
29
32
|
def initialize(options)
|
30
33
|
raise TypeError.new "Options must not be a Hash that contains \":name\"" unless options.is_a?(Hash)
|
31
|
-
if options.
|
34
|
+
if options[:name].nil? or options[:name].strip.empty?
|
32
35
|
raise ArgumentError.new "Illegal GUID Name: \"#{options[:name]}\". Must not be nil or empty"
|
33
36
|
end
|
34
|
-
raise ArgumentError.new "GUID Name cannot start with special character"
|
37
|
+
raise ArgumentError.new "GUID Name cannot start with special character" unless /^[^0-9A-Za-z].*/.match(options[:name]).nil?
|
38
|
+
@name = options[:name]
|
35
39
|
options[:namespace] = namespace
|
36
40
|
@options = options.clone
|
37
41
|
end
|
38
42
|
|
39
|
-
# Public: Generate a global unique id
|
40
|
-
def
|
43
|
+
# Public: Generate a global unique id synchronously with other
|
44
|
+
def get
|
41
45
|
# TODO Generation implementation
|
42
46
|
# Create a Consul Session the the underlying namespace
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
#
|
47
|
-
|
48
|
-
|
47
|
+
cur_session = session.create(Session.for_name(namespace))
|
48
|
+
raise 'Unable to create session to generate UID.' if cur_session.nil?
|
49
|
+
|
50
|
+
# Check if there is already an UID associated with this client_id.
|
51
|
+
existing_uid = key_value_store.get(client_uid_path)
|
52
|
+
unless existing_uid.nil? or (existing_uid.respond_to?(:empty?) and existing_uid.empty?)
|
53
|
+
return existing_uid[0].value.to_i
|
54
|
+
end
|
55
|
+
|
56
|
+
# No existing UID so let provision one for this node.
|
57
|
+
for i in 1..MAX_ATTEMPTS
|
58
|
+
session.renew cur_session # Renew the current session so we can obtain a lock
|
59
|
+
|
60
|
+
# Get the current available uid with
|
61
|
+
auid = key_value_store.get(available_uid_path, {:index => nil})
|
62
|
+
if auid.nil? # Key does not exists. Which also means its the first ever UID.
|
63
|
+
logger.debug("First ever UID for #{namespace}")
|
64
|
+
auid = 0
|
65
|
+
else
|
66
|
+
auid = auid[0].value.to_i
|
67
|
+
logger.debug("Found available UID for #{namespace} value: #{auid}")
|
68
|
+
end
|
69
|
+
# Acquire the lock
|
70
|
+
member = agent.describe.member.to_json
|
71
|
+
acquire_lock_success, body = key_value_store.put(available_lock_path,
|
72
|
+
member,
|
73
|
+
{:acquire => cur_session.id})
|
74
|
+
unless acquire_lock_success
|
75
|
+
logger.warn("Attempt: #{i} Unable to acquire lock for #{namespace} reason: #{body}")
|
76
|
+
next
|
77
|
+
end
|
78
|
+
|
79
|
+
# Update the available uid with the next value
|
80
|
+
available_uid_update_success, body = key_value_store.put(available_uid_path, auid + 1)
|
81
|
+
unless available_uid_update_success
|
82
|
+
logger.warn("Attempt: #{i} Unable to update available uid for #{namespace} reason: #{body}")
|
83
|
+
next
|
84
|
+
end
|
85
|
+
|
86
|
+
# Release the lock
|
87
|
+
release_lock_success, body = key_value_store.put(available_lock_path,
|
88
|
+
member,
|
89
|
+
{:release => cur_session.id})
|
90
|
+
logger.warn("Unable to release lock for #{namespace} reason: #{body}. Resorting to Timeout.") unless release_lock_success
|
91
|
+
|
92
|
+
# Update the Key Value store for this client id so we don't provision another one.
|
93
|
+
client_id_update_success, body = key_value_store.put(client_uid_path, auid.to_s)
|
94
|
+
unless client_id_update_success
|
95
|
+
logger.warn("Attempt: #{i} Unable to update id for client #{client_id} with value #{auid} due to #{body}")
|
96
|
+
next
|
97
|
+
end
|
98
|
+
|
99
|
+
# After successfully and synchronously updating available universal id and this client id continue
|
100
|
+
return auid
|
101
|
+
end
|
102
|
+
logger.error("Unable to generate key after #{MAX_ATTEMPTS} attempts")
|
103
|
+
nil
|
49
104
|
end
|
50
105
|
|
51
|
-
|
106
|
+
# Path to getting the next available UID.
|
107
|
+
def available_uid_path
|
108
|
+
'.available.uid'
|
109
|
+
end
|
52
110
|
|
53
|
-
|
54
|
-
|
55
|
-
@namespace ||= "#{extensions_namespace}/uid/#{@options[:name]}"
|
111
|
+
def available_lock_path
|
112
|
+
'.available.lock'
|
56
113
|
end
|
57
114
|
|
58
|
-
|
59
|
-
|
115
|
+
# Path to this specific Client UID.
|
116
|
+
def client_uid_path
|
117
|
+
client_id
|
60
118
|
end
|
61
119
|
|
62
120
|
# The individual client id for this uid generator
|
63
121
|
def client_id
|
64
|
-
|
122
|
+
c_id = nil
|
65
123
|
unless @options[:client_id].nil? or @options[:client_id].strip.empty?
|
66
|
-
|
124
|
+
c_id = @options[:client_id].strip
|
67
125
|
end
|
68
|
-
@client_id ||=
|
126
|
+
@client_id ||= c_id || agent.describe.member.name
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
# The FQ namespace for this GUID
|
132
|
+
def namespace
|
133
|
+
@namespace ||= "#{extensions_namespace}/uid/#{@name}"
|
69
134
|
end
|
70
135
|
|
71
136
|
end
|
data/lib/setup.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Convenience Script for testing in IRB
|
2
|
+
#
|
3
|
+
# To run in local IRB and preload some namespaces run the following command from project root.
|
4
|
+
# bin/build_install.sh && irb -Ilib -rsetup.rb
|
5
|
+
|
6
|
+
require 'consul/client'
|
7
|
+
include Consul::Client
|
8
|
+
include Consul::Extensions
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: consul-ruby-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Hotan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -127,7 +127,8 @@ description: |-
|
|
127
127
|
layer.
|
128
128
|
email:
|
129
129
|
- michael.hotan@socrata.com
|
130
|
-
executables:
|
130
|
+
executables:
|
131
|
+
- build_install.sh
|
131
132
|
extensions: []
|
132
133
|
extra_rdoc_files: []
|
133
134
|
files:
|
@@ -137,6 +138,18 @@ files:
|
|
137
138
|
- LICENSE.txt
|
138
139
|
- README.md
|
139
140
|
- Rakefile
|
141
|
+
- bin/build_install.sh
|
142
|
+
- build/.gitignore
|
143
|
+
- build/CODE_OF_CONDUCT.md
|
144
|
+
- build/Gemfile
|
145
|
+
- build/LICENSE.txt
|
146
|
+
- build/README.md
|
147
|
+
- build/Rakefile
|
148
|
+
- build/bin/console
|
149
|
+
- build/bin/setup
|
150
|
+
- build/build.gemspec
|
151
|
+
- build/lib/build.rb
|
152
|
+
- build/lib/build/version.rb
|
140
153
|
- consul-ruby-client.gemspec
|
141
154
|
- lib/consul/client.rb
|
142
155
|
- lib/consul/client/agent.rb
|
@@ -157,6 +170,7 @@ files:
|
|
157
170
|
- lib/consul/model/service.rb
|
158
171
|
- lib/consul/model/session.rb
|
159
172
|
- lib/consul/util/utils.rb
|
173
|
+
- lib/setup.rb
|
160
174
|
- spec/base_client_spec.rb
|
161
175
|
- spec/spec_helper.rb
|
162
176
|
homepage: https://github.com/mhotan-s/consul-ruby-client
|