discotheque 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/README.md +55 -0
- data/Rakefile +8 -0
- data/discotheque.gemspec +19 -0
- data/lib/discotheque/discover.rb +54 -0
- data/lib/discotheque/discoverable.rb +5 -0
- data/lib/discotheque/metadata.rb +33 -0
- data/lib/discotheque/poll.rb +0 -0
- data/lib/discotheque/version.rb +3 -0
- data/lib/discotheque.rb +5 -0
- data/test/.keep +0 -0
- data/test/test_ec2.rb +0 -0
- data/test/test_rules.rb +0 -0
- metadata +88 -0
data/.gitignore
ADDED
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Discotheque
|
2
|
+
|
3
|
+
>> "This disco used to be a cute cathedrale" -- Steve Taylor
|
4
|
+
|
5
|
+
Discotheque is aiming to be a general purpose node discovery tool.
|
6
|
+
|
7
|
+
It was inspired by the ZenDiscovery functionality of ElasticSearch, originally the [EC2 discovery code](https://github.com/elasticsearch/elasticsearch/blob/master/plugins/cloud/aws/src/main/java/org/elasticsearch/discovery/ec2/AwsEc2UnicastHostsProvider.java)
|
8
|
+
|
9
|
+
When initially setting up our ElasticSearch clusters, I was amazed at how "magical" it was at finding other ES nodes on EC2. Curiosity got the better of me...
|
10
|
+
Originally this was going to be just a single hack for porting that logic but I've decided to go a bit further.
|
11
|
+
|
12
|
+
## The plan
|
13
|
+
Right now this is a really ghetto MVP. Given a list of any combination of these filters:
|
14
|
+
|
15
|
+
- "sg" security group
|
16
|
+
- "ami" ami id
|
17
|
+
- "az" availability zone
|
18
|
+
- "arch" architecture
|
19
|
+
|
20
|
+
You'll get back a list of matching nodes. It's up to you to decide what to do with them.
|
21
|
+
|
22
|
+
The way it currently works is by getting information about the node it's currently running on via EC2 metadata calls. From there, it uses that information to populate the filters.
|
23
|
+
|
24
|
+
So if your node is in us-east-1a, running `Discotheque::Discover` with an `az` filter, will give you all the nodes in your availability zone.
|
25
|
+
|
26
|
+
Long term, there will be mutliple different discovery methods - unicast, multicast, ec2..you name it. Additionally, you'll be able to specify a "test" criteria to further pare down the list. Also the plan is to provide a mixin when you can make your application "discoverable" - say responding to a given port request with a fingerprint.
|
27
|
+
|
28
|
+
## Example usage (kind of pointless at this early of a stage)
|
29
|
+
__Again, you'll need to be on an EC2 node. I'll resolve this in the future__
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
c = Discotheque::Discover.new
|
33
|
+
c.get_nodes :access_key_id => "YYYYYYYYYYYYYYYYYYYY", :secret_access_key => "XXXXXXXXXXXXXXXXXXXXXXXXXX"
|
34
|
+
# pretty much returns all nodes since there are no filters
|
35
|
+
# ["1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"]
|
36
|
+
c.filters << "sg"
|
37
|
+
c.get_nodes :access_key_id => "YYYYYYYYYYYYYYYYYYYY", :secret_access_key => "XXXXXXXXXXXXXXXXXXXXXXXXXX"
|
38
|
+
# ["1.1.1.1", "2.2.2.2", "3.3.3.3"]
|
39
|
+
c.filters << "ami"
|
40
|
+
# ["2.2.2.2", "3.3.3.3"]
|
41
|
+
c.filters
|
42
|
+
# ["ami", "sg"]
|
43
|
+
c.clear_filters
|
44
|
+
# []
|
45
|
+
# If you want to see what Discotheque knows about the node it's running on
|
46
|
+
m = Discotheque::Metadata.new
|
47
|
+
#<Discotheque::Metadata:0x00000000fb1008
|
48
|
+
# @availability_zone="us-east-1a",
|
49
|
+
# @group_name="default",
|
50
|
+
# @image_id="ami-221fec4b">
|
51
|
+
```
|
52
|
+
|
53
|
+
If you pass in `true` to the constructor you'll get the mock data above
|
54
|
+
|
55
|
+
|
data/Rakefile
ADDED
data/discotheque.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require 'discotheque/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "discotheque"
|
6
|
+
s.version = Discotheque::VERSION
|
7
|
+
s.authors = ["John E. Vincent"]
|
8
|
+
s.email = ["lusis.org+github.com@gmail.com"]
|
9
|
+
|
10
|
+
s.summary = "Framework for node discovery"
|
11
|
+
s.description = "Adds functionality to your application for node discovery using Amazon EC2"
|
12
|
+
s.homepage = "https://github.com/lusis/discotheque"
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.require_paths = ["lib"]
|
15
|
+
|
16
|
+
s.add_dependency("aws-sdk", "= 1.1.2")
|
17
|
+
s.add_dependency("rake", "= 0.9.2")
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Discotheque
|
2
|
+
class Discover
|
3
|
+
# NOTE
|
4
|
+
# tags are not available via metadata calls
|
5
|
+
# therefore tag will need to be an explcit value passed in
|
6
|
+
# This actually makes sense if you want to discover a tag that isn't yours
|
7
|
+
# Take the use case of a master/slave setup:
|
8
|
+
# You would tag the master node with "foo_slave"
|
9
|
+
# but you might need to find all slaves
|
10
|
+
#
|
11
|
+
VALID_FILTERS = %w[az sg tag ami arch]
|
12
|
+
FILTER_MAP = {"az" => "availability-zone",
|
13
|
+
"sg" => "group-name",
|
14
|
+
"ami" => "image-id",
|
15
|
+
"arch" => "architecture"}
|
16
|
+
|
17
|
+
attr_accessor :filters
|
18
|
+
|
19
|
+
def initialize(filters=[])
|
20
|
+
@filters = filters
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_nodes(creds={})
|
24
|
+
# creds is a hash like so
|
25
|
+
# creds = {:access_key_id => "YYYYYYYYYYYYYYYYYYYYYYYYYY", :secret_access_key => "XXXXXXXXXXXXX"}
|
26
|
+
@filters.empty? ? f="ec2.instances" : f="ec2.instances.#{build_filter}"
|
27
|
+
require 'aws-sdk'
|
28
|
+
AWS.config creds
|
29
|
+
ec2 = AWS::EC2.new
|
30
|
+
candidates = AWS.memoize do
|
31
|
+
ci = eval(f)
|
32
|
+
ci.to_a.sort_by(&:ip_address).map {|i| i.ip_address}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def clear_filters
|
37
|
+
@filters = []
|
38
|
+
end
|
39
|
+
private
|
40
|
+
def build_filter
|
41
|
+
whoami = Metadata.new
|
42
|
+
f = {}
|
43
|
+
method_text = []
|
44
|
+
@filters.each do |filter|
|
45
|
+
next if (VALID_FILTERS.member?(filter) == false)
|
46
|
+
f.merge!({"#{FILTER_MAP[filter]}" => whoami.instance_variable_get("@#{FILTER_MAP[filter].gsub(/-/,"_")}")})
|
47
|
+
end
|
48
|
+
f.each do |k,v|
|
49
|
+
method_text << "filter('#{k}','#{v}')"
|
50
|
+
end
|
51
|
+
method_text.join('.')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Discotheque
|
2
|
+
class Metadata
|
3
|
+
|
4
|
+
attr_reader :instance_id, :image_id, :group_name, :availability_zone
|
5
|
+
|
6
|
+
def initialize(mock=false)
|
7
|
+
if mock == true
|
8
|
+
@image_id = "ami-221fec4b" # amazon linux ami
|
9
|
+
@group_name = "default"
|
10
|
+
@availability_zone = "us-east-1a"
|
11
|
+
return
|
12
|
+
else
|
13
|
+
base_url = "http://169.254.169.254/latest/meta-data/"
|
14
|
+
begin
|
15
|
+
%w[instance-id ami-id security-groups availability-zone].each do |datum|
|
16
|
+
datum == "availability-zone" ? url="#{base_url}/placement/#{datum}" : url="#{base_url}#{datum}"
|
17
|
+
d = HTTParty.get("#{url}").parsed_response
|
18
|
+
if datum == "security-groups"
|
19
|
+
instance_variable_set "@group_name", d
|
20
|
+
elsif datum == "ami-id"
|
21
|
+
instance_variable_set "@image_id", d
|
22
|
+
else
|
23
|
+
instance_variable_set "@#{datum.gsub(/-/,"_")}", d
|
24
|
+
end
|
25
|
+
end
|
26
|
+
rescue Errno::EHOSTUNREACH
|
27
|
+
puts "This only makes sense on EC2 hosts"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
data/lib/discotheque.rb
ADDED
data/test/.keep
ADDED
File without changes
|
data/test/test_ec2.rb
ADDED
File without changes
|
data/test/test_rules.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: discotheque
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- John E. Vincent
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-08-26 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: aws-sdk
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.1.2
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rake
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - "="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.9.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
description: Adds functionality to your application for node discovery using Amazon EC2
|
38
|
+
email:
|
39
|
+
- lusis.org+github.com@gmail.com
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
files:
|
47
|
+
- .gitignore
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- discotheque.gemspec
|
51
|
+
- lib/discotheque.rb
|
52
|
+
- lib/discotheque/discover.rb
|
53
|
+
- lib/discotheque/discoverable.rb
|
54
|
+
- lib/discotheque/metadata.rb
|
55
|
+
- lib/discotheque/poll.rb
|
56
|
+
- lib/discotheque/version.rb
|
57
|
+
- test/.keep
|
58
|
+
- test/test_ec2.rb
|
59
|
+
- test/test_rules.rb
|
60
|
+
homepage: https://github.com/lusis/discotheque
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.8.6
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Framework for node discovery
|
87
|
+
test_files: []
|
88
|
+
|