discotheque 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ .rvmrc
2
+ Gemfile.lock
3
+ *.swp
4
+ .gem
5
+ .bundle
6
+ .yardoc
7
+ *.rbc
8
+ loader.rb
9
+ config.yml
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
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -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,5 @@
1
+ module Discotheque
2
+ module Discoverable
3
+ # mixin code for making an application discoverable goes here
4
+ end
5
+ 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
@@ -0,0 +1,3 @@
1
+ module Discotheque
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ module Discotheque
2
+ end
3
+
4
+ require File.join(File.dirname(__FILE__), 'discotheque', 'version')
5
+ require File.join(File.dirname(__FILE__), 'discotheque', 'metadata')
data/test/.keep ADDED
File without changes
data/test/test_ec2.rb ADDED
File without changes
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
+