gaff 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+