gaff 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,35 @@
1
+ gaff : Cloud API AMQP daemon
2
+
3
+ gaff is a pub/sub system for interfacing asynchronously with cloud APIs.
4
+
5
+ License: apache 2
6
+
7
+ Features:
8
+ * Uses AMQP and the JSON-RPC (http://json-rpc.org/) format
9
+ * Easy support for any API
10
+ ** Currently supports part of the dynect, ec2 and slicehost APIs
11
+ ** Uses fog (http://github.com/geemus/fog)
12
+
13
+ Example usage:
14
+
15
+ Send a JSON-RPC formatted message to the exchange with the a routing key to perform operations on that API.
16
+
17
+ require 'rubygems'
18
+ require 'carrot'
19
+
20
+ exch = Carrot::AMQP::Exchange.new(Carrot.new, :topic, "api")
21
+
22
+ hash = {"method" => "add_a_record", "params" => {
23
+ "customer_name" => "gaff.com",
24
+ "username" => "username",
25
+ "password" => "password",
26
+ "node" => "test123",
27
+ "zone" => "gaff.com",
28
+ "address" => "127.0.0.1",
29
+ "ttl" => "300"
30
+ }
31
+ }
32
+
33
+ json = hash.to_json
34
+
35
+ exch.publish(json, :routing_key => "dynect")
data/bin/gaff ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'gaff')
3
+
4
+ class Gaff
5
+ def self.main
6
+ Gaff::Dispatch.loop
7
+ end
8
+
9
+ main
10
+ end
data/config/gaff.yml ADDED
@@ -0,0 +1,6 @@
1
+ defaults:
2
+ amqp_host: "localhost"
3
+ api:
4
+ ec2: "ec2"
5
+ slicehost: "slicehost"
6
+ dynect: "dynect"
@@ -0,0 +1,12 @@
1
+ class Gaff
2
+ class Config
3
+ gaff_config = YAML.load(File.open(ARGV[0]))
4
+ extend Mixlib::Config
5
+ configure do |c|
6
+ c[:amqp_host] = gaff_config["defaults"]["amqp_host"]
7
+ c[:ec2] = gaff_config["defaults"]["api"]["ec2"]
8
+ c[:slicehost] = gaff_config["defaults"]["api"]["slicehost"]
9
+ c[:dynect] = gaff_config["defaults"]["api"]["dynect"]
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+ class Gaff
2
+ class Dispatch
3
+
4
+ def self.loop
5
+ Signal.trap('INT') { AMQP.stop{ EM.stop } }
6
+ Signal.trap('TERM'){ AMQP.stop{ EM.stop } }
7
+
8
+ list = Array.new
9
+
10
+ Gaff::Log.info("Starting Gaff dispatch loop ...")
11
+ STDOUT.flush
12
+
13
+ EM.run do
14
+ exch = MQ::Exchange.new(MQ.new, :topic, "api", :host => Gaff::Config.amqp_host)
15
+
16
+ MQ.queue(Gaff::Config.ec2).bind(exch, :key => Gaff::Config.ec2).subscribe do |msg|
17
+ list << Thread.new { Gaff::Ec2_api.exec(msg) }
18
+ end
19
+
20
+ MQ.queue(Gaff::Config.slicehost).bind(exch, :key => Gaff::Config.slicehost).subscribe do |msg|
21
+ list << Thread.new { Gaff::Slicehost_api.exec(msg) }
22
+ end
23
+
24
+ MQ.queue(Gaff::Config.dynect).bind(exch, :key => Gaff::Config.dynect).subscribe do |msg|
25
+ list << Thread.new { Gaff::Dynect_api.exec(msg) }
26
+ end
27
+ end
28
+
29
+ list.each { |x|
30
+ x.join
31
+ }
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,71 @@
1
+ class Gaff
2
+ class Dynect_api
3
+
4
+ def self.exec(msg)
5
+ parser = Yajl::Parser.new
6
+ hash = parser.parse(msg)
7
+
8
+ Gaff::Log.debug(hash)
9
+ STDOUT.flush
10
+
11
+ dynect = Dynect.new(
12
+ hash["params"]["customer_name"],
13
+ hash["params"]["username"],
14
+ hash["params"]["password"])
15
+
16
+ Gaff::Log.debug(dynect)
17
+ STDOUT.flush
18
+
19
+ case hash["method"]
20
+ when "add_a_record"
21
+ node = dynect.add_node(
22
+ hash["params"]["node"],
23
+ hash["params"]["zone"])
24
+
25
+ record = dynect.add_a_record(
26
+ hash["params"]["zone"],
27
+ hash["params"]["address"],
28
+ {
29
+ "node" => "#{hash["params"]["node"]}.#{hash["params"]["zone"]}",
30
+ "ttl" => hash["params"]["ttl"]
31
+ })
32
+ when "add_cname_record"
33
+ node = dynect.add_node(
34
+ hash["params"]["node"],
35
+ hash["params"]["zone"])
36
+
37
+ record = dynect.add_cname_record(
38
+ hash["params"]["zone"],
39
+ hash["params"]["address"],
40
+ {
41
+ "node" => "#{hash["params"]["node"]}.#{hash["params"]["zone"]}",
42
+ "ttl" => hash["params"]["ttl"]
43
+ })
44
+ when "delete_a_record"
45
+ record_id = dynect.list_a_records(
46
+ hash["params"]["zone"],
47
+ {
48
+ "node" => "#{hash["params"]["node"]}.#{hash["params"]["zone"]}"
49
+ })
50
+
51
+ record = dynect.delete_a_record(record_id[0]["record_id"])
52
+ when "delete_cname_record"
53
+ record_id = dynect.list_cname_records(
54
+ hash["params"]["zone"],
55
+ {
56
+ "node" => "#{hash["params"]["node"]}.#{hash["params"]["zone"]}"
57
+ })
58
+
59
+ record = dynect.delete_cname_record(record_id[0]["record_id"])
60
+ end
61
+
62
+ if node
63
+ Gaff::Log.debug(node.inspect)
64
+ node = nil
65
+ end
66
+ Gaff::Log.info(record.inspect)
67
+ STDOUT.flush
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,59 @@
1
+ class Gaff
2
+ class Ec2_api
3
+
4
+ def self.exec(msg)
5
+ parser = Yajl::Parser.new
6
+ hash = parser.parse(msg)
7
+
8
+ Gaff::Log.debug(hash)
9
+ STDOUT.flush
10
+
11
+ ec2 = Fog::AWS::EC2.new(
12
+ :aws_access_key_id => hash["params"]["aws_key"],
13
+ :aws_secret_access_key => hash["params"]["aws_key_secret"])
14
+
15
+ Gaff::Log.debug(ec2)
16
+ STDOUT.flush
17
+
18
+ case hash["method"]
19
+ when "attach_volume"
20
+ result = ec2.attach_volume(
21
+ hash["params"]["volume_id"],
22
+ hash["params"]["instance_id"],
23
+ hash["params"]["device"])
24
+ when "create_volume"
25
+ result = ec2.create_volume(
26
+ hash["params"]["availability_zone"],
27
+ hash["params"]["size"].to_i,
28
+ hash["params"]["snapshot_id"])
29
+ when "delete_volume"
30
+ result = ec2.delete_volume(hash["params"]["volume_id"])
31
+ when "detach_volume"
32
+ result = ec2.detach_volume(
33
+ hash["params"]["volume_id"],
34
+ hash["params"]["instance_id"],
35
+ hash["params"]["device"],
36
+ hash["params"]["force"])
37
+ when "launch_instances"
38
+ result = ec2.run_instances(
39
+ hash["params"]["image_id"],
40
+ hash["params"]["count"],
41
+ hash["params"]["count"],
42
+ {
43
+ "SecurityGroup" => hash["params"]["group_ids"],
44
+ "KeyName" => hash["params"]["key_name"],
45
+ "Placement.AvailabilityZone" => hash["params"]["availability_zone"],
46
+ "InstanceType" => hash["params"]["instance_type"]
47
+ })
48
+ when "reboot_instances"
49
+ result = ec2.reboot_instances(hash["params"]["instance_ids"])
50
+ when "terminate_instances"
51
+ result = ec2.terminate_instances(hash["params"]["instance_ids"])
52
+ end
53
+
54
+ Gaff::Log.info(result)
55
+ STDOUT.flush
56
+ end
57
+
58
+ end
59
+ end
data/lib/gaff/log.rb ADDED
@@ -0,0 +1,6 @@
1
+ class Gaff
2
+ class Log
3
+ extend Mixlib::Log
4
+ Gaff::Log.level(:info)
5
+ end
6
+ end
@@ -0,0 +1,31 @@
1
+ class Gaff
2
+ class Slicehost_api
3
+
4
+ def self.exec(msg)
5
+ parser = Yajl::Parser.new
6
+ hash = parser.parse(msg)
7
+
8
+ Gaff::Log.debug(hash)
9
+ STDOUT.flush
10
+
11
+ slicehost = Fog::Slicehost.new({:slicehost_password => hash["params"]["password"]})
12
+
13
+ Gaff::Log.debug(slicehost)
14
+ STDOUT.flush
15
+
16
+ case hash["method"]
17
+ when "create_slice"
18
+ result = slicehost.create_slice(
19
+ hash["params"]["flavor_id"].to_i,
20
+ hash["params"]["image_id"].to_i,
21
+ hash["params"]["name"])
22
+ when "delete_slice"
23
+ result = slicehost.delete_slice(hash["params"]["slice_id"].to_i)
24
+ end
25
+
26
+ Gaff::Log.info(result)
27
+ STDOUT.flush
28
+ end
29
+
30
+ end
31
+ end
data/lib/gaff.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+
3
+ require 'mq'
4
+ require 'yajl'
5
+ require 'dynect'
6
+ require 'fog'
7
+ require 'mixlib/config'
8
+ require 'mixlib/log'
9
+ require 'yaml'
10
+
11
+ __DIR__ = File.dirname(__FILE__)
12
+
13
+ $LOAD_PATH.unshift __DIR__ unless
14
+ $LOAD_PATH.include?(__DIR__) ||
15
+ $LOAD_PATH.include?(File.expand_path(__DIR__))
16
+
17
+ require 'gaff/log'
18
+ require 'gaff/config'
19
+ require 'gaff/dispatch'
20
+ require 'gaff/ec2_api'
21
+ require 'gaff/slicehost_api'
22
+ require 'gaff/dynect_api'
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gaff
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 1
9
+ version: 0.3.1
10
+ platform: ruby
11
+ authors:
12
+ - joe williams
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-04 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: yajl-ruby
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: mixlib-config
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :runtime
43
+ version_requirements: *id002
44
+ - !ruby/object:Gem::Dependency
45
+ name: mixlib-log
46
+ prerelease: false
47
+ requirement: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ type: :runtime
55
+ version_requirements: *id003
56
+ - !ruby/object:Gem::Dependency
57
+ name: dynect
58
+ prerelease: false
59
+ requirement: &id004 !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ type: :runtime
67
+ version_requirements: *id004
68
+ - !ruby/object:Gem::Dependency
69
+ name: amqp
70
+ prerelease: false
71
+ requirement: &id005 !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ type: :runtime
79
+ version_requirements: *id005
80
+ - !ruby/object:Gem::Dependency
81
+ name: fog
82
+ prerelease: false
83
+ requirement: &id006 !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ type: :runtime
91
+ version_requirements: *id006
92
+ description:
93
+ email: joe@joetify.com
94
+ executables:
95
+ - gaff
96
+ extensions: []
97
+
98
+ extra_rdoc_files:
99
+ - README
100
+ files:
101
+ - bin/gaff
102
+ - lib/gaff/config.rb
103
+ - lib/gaff/dispatch.rb
104
+ - lib/gaff/dynect_api.rb
105
+ - lib/gaff/ec2_api.rb
106
+ - lib/gaff/log.rb
107
+ - lib/gaff/slicehost_api.rb
108
+ - lib/gaff.rb
109
+ - config/gaff.yml
110
+ - README
111
+ has_rdoc: true
112
+ homepage: http://github.com/joewilliams/gaff
113
+ licenses: []
114
+
115
+ post_install_message:
116
+ rdoc_options: []
117
+
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ segments:
125
+ - 0
126
+ version: "0"
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ requirements: []
135
+
136
+ rubyforge_project:
137
+ rubygems_version: 1.3.6
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: cloud api's via amqp and json'
141
+ test_files: []
142
+