moneypools-right_api 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+ moneypools-right_api.gemspec
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "#{ENV['GITHUB'] ? 'moneypools-' : ''}right_api"
8
+ gem.summary = %Q{A ruby wrapper for the RightScale api}
9
+ gem.description = "A ruby wrapper for the RightScale api"
10
+ gem.email = "mpdev@businesslogic.com"
11
+ gem.homepage = "http://github.com/moneypools/right_api"
12
+ gem.authors = ["MoneyPools"]
13
+ gem.add_dependency('hpricot')
14
+ gem.add_dependency('activesupport')
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'rake/rdoctask'
23
+ Rake::RDocTask.new do |rdoc|
24
+ if File.exist?('VERSION.yml')
25
+ config = YAML.load(File.read('VERSION.yml'))
26
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
27
+ else
28
+ version = ""
29
+ end
30
+
31
+ rdoc.rdoc_dir = 'rdoc'
32
+ rdoc.title = "right_api #{version}"
33
+ rdoc.rdoc_files.include('README*')
34
+ rdoc.rdoc_files.include('lib/**/*.rb')
35
+ end
36
+
37
+ task :default => ['gemspec', 'build']
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 1
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,19 @@
1
+ module AccessibleFragment
2
+ def initialize(data, connection)
3
+ @data = data
4
+ @connection = connection
5
+ end
6
+
7
+ def has_element?(elem)
8
+ !@data.search(elem).size.zero?
9
+ end
10
+
11
+ def get_element(elem)
12
+ @data.search(elem).first.inner_text
13
+ end
14
+
15
+ def method_missing(method_name, *args)
16
+ name_with_dashes = method_name.to_s.gsub('_', '-')
17
+ has_element?(name_with_dashes) ? get_element(name_with_dashes) : super
18
+ end
19
+ end
@@ -0,0 +1,141 @@
1
+ class HttpServer
2
+ attr_accessor :response_error_checker, :handle_errors, :headers
3
+ attr_reader :last_response
4
+
5
+ def initialize(server_config, timeout)
6
+ @server_url, @port, @username, @password = server_config['server_url'], server_config['port'], server_config['username'], server_config['password']
7
+ @timeout = timeout
8
+ raise 'No configuration for timeout length' if @timeout.nil?
9
+
10
+ @handle_errors = true
11
+ @response_error_checker = Proc.new do |response, path|
12
+ response.include? 'errors' if response
13
+ end
14
+
15
+ @headers = {
16
+ 'User-Agent' => 'Mozilla/4.0',
17
+ 'Content-Type' => 'application/x-www-form-urlencoded',
18
+ 'Connection' => 'Keep-Alive',
19
+ 'X-API-VERSION' => RightScale::API_VERSION
20
+ }
21
+ end
22
+
23
+ def delete(resource, &block)
24
+ connect(resource, Net::HTTP::Delete, &block)
25
+ end
26
+
27
+ def get(resource, &block)
28
+ connect(resource, Net::HTTP::Get, &block)
29
+ end
30
+
31
+ def get_with_params(resource, params={}, &block)
32
+ connect(resource, Net::HTTP::Get, encode_params(params), &block)
33
+ end
34
+
35
+ def post(resource, params={}, &block)
36
+ connect(resource, Net::HTTP::Post, encode_params(params), &block)
37
+ end
38
+
39
+ def put(resource, params={}, &block)
40
+ connect(resource, Net::HTTP::Put, encode_params(params), &block)
41
+ end
42
+
43
+ def with_error_handling_disabled
44
+ original_handle_errors = handle_errors
45
+ self.handle_errors = false
46
+
47
+ result = yield
48
+ ensure
49
+ self.handle_errors = original_handle_errors
50
+ end
51
+
52
+ private
53
+
54
+ def connect(resource, request_object, *args, &block)
55
+ uri = URI.parse url(resource)
56
+ req = request_object.new(uri.path, @headers)
57
+ req.basic_auth @username, @password if @username
58
+
59
+ response_data = nil
60
+
61
+ begin
62
+ create_http(uri).start do |http|
63
+ response, data = http.request(req, *args)
64
+
65
+ block.call(self, response) if block
66
+
67
+ @last_response = response_data = data_from(response)
68
+ end
69
+ rescue Timeout::Error
70
+ raise "A timeout error occured when connecting to #{resource}.\nThe timeout is currently set to #{@timeout} seconds."
71
+ rescue Errno::ECONNREFUSED
72
+ raise "Could not connect when connecting to #{resource} - the server (#{@server_url}) is down."
73
+ end
74
+
75
+ check_response_for_errors(response_data, uri.path) if handle_errors
76
+
77
+ response_data
78
+ end
79
+
80
+ def data_from(response)
81
+ case response
82
+ when Net::HTTPSuccess
83
+ response.body
84
+ when Net::HTTPRedirection
85
+ response['location']
86
+ end
87
+ end
88
+
89
+ def create_http(uri)
90
+ http = Net::HTTP.new(uri.host, uri.port)
91
+ http.use_ssl = true if uri.port == 443
92
+ http.read_timeout = @timeout
93
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
94
+
95
+ # http.set_debug_output $stderr
96
+
97
+ http
98
+ end
99
+
100
+ def url(resource)
101
+ "#{server_path}/#{resource.sub /^\//, ''}"
102
+ end
103
+
104
+ def server_path
105
+ @port ? "#{@server_url}:#{@port}" : @server_url
106
+ end
107
+
108
+ def encode_params(hash)
109
+ params = transform_params(hash)
110
+ stringify_params(params)
111
+ end
112
+
113
+ def transform_params(hash)
114
+ params = []
115
+
116
+ hash.each do |key, value|
117
+ if value.instance_of? Hash
118
+ params.concat transform_params(value).each{|elements| elements[0].unshift key}
119
+ else
120
+ params.push [[key], value]
121
+ end
122
+ end
123
+
124
+ params
125
+ end
126
+
127
+ def stringify_params(params)
128
+ params.map do |keys, value|
129
+ left = keys.join('[') + (']' * (keys.length - 1))
130
+ "#{left}=#{CGI::escape(value.to_s)}"
131
+ end.join('&')
132
+ end
133
+
134
+ def check_response_for_errors(response, path)
135
+ if response && response.include?('No connection could be made')
136
+ raise Errno::ECONNREFUSED
137
+ elsif @response_error_checker.call(response, path)
138
+ raise "An error occured requesting #{path} - please check the XML response:\n #{response}\nCurrent data:\n#{@data}"
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,148 @@
1
+ require 'hpricot'
2
+ require 'active_support'
3
+
4
+ require 'right_api/http_server'
5
+ require 'right_api/accessible_fragment'
6
+
7
+ # Rightscale
8
+ module RightScale
9
+ API_VERSION = '1.0'
10
+
11
+ class Base
12
+ include AccessibleFragment
13
+
14
+ def initialize(data)
15
+ raise "You must first establish a connection via Base.establish_connection" unless @@connection
16
+ @data = data
17
+ end
18
+
19
+ def id
20
+ @id ||= href.split('/').last
21
+ end
22
+
23
+ def data
24
+ @data ||= @@connection.get("/#{plural_name}/#{id}")
25
+ end
26
+
27
+ def update_attribute(attribute, value)
28
+ @@connection.put("/#{self.class.plural_name}/#{id}", "#{self.class.class_name}[#{attribute}]" => value)
29
+ end
30
+
31
+ def self.class_name
32
+ name.split("::").last.underscore
33
+ end
34
+
35
+ def self.plural_name
36
+ class_name.pluralize
37
+ end
38
+
39
+ def self.xml_name
40
+ class_name.dasherize
41
+ end
42
+
43
+
44
+ def self.establish_connection(user, password, account_id)
45
+ url = "https://my.rightscale.com/api/acct/#{account_id}"
46
+ params = {'server_url' => url, 'username' => user, 'password' => password}
47
+
48
+ @@connection = HttpServer.new(params, 60)
49
+ @@connection.get('/login')
50
+
51
+ params = {'server_url' => "https://my.rightscale.com"}
52
+
53
+ @@non_api_connection = HttpServer.new(params, 60)
54
+ @@non_api_connection.post('/sessions', 'email' => user, 'password' => password) do |server, response|
55
+ cookies = response.response.get_fields('set-cookie')
56
+ session_cookie = cookies.detect { |cookie| cookie =~ /_session_id/ }
57
+ cookie_header_for_request = session_cookie.split(';').first
58
+ server.headers = server.headers.merge('cookie' => cookie_header_for_request, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
59
+ end
60
+
61
+ end
62
+
63
+ def self.all(opts={})
64
+ find_with_options(opts)
65
+ end
66
+
67
+ def self.first(opts={})
68
+ find_first_with_options(opts)
69
+ end
70
+
71
+ def self.find(opts=nil)
72
+ if opts.nil?
73
+ raise "Find requires a hash of options or an id"
74
+ elsif opts.is_a?(Hash)
75
+ find_with_options(opts)
76
+ else
77
+ find(:id => opts)
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def self.find_with_options(opts)
84
+ find_all
85
+
86
+ @all.select do |member|
87
+ opts.all? {|k, v| member.send(k) == v }
88
+ end
89
+ end
90
+
91
+ def self.find_first_with_options(opts)
92
+ find_all
93
+
94
+ @all.detect do |member|
95
+ opts.all? {|k, v| member.send(k) == v }
96
+ end
97
+ end
98
+
99
+ def self.find_all
100
+ return unless @all.nil?
101
+
102
+ response = @@connection.get("/#{plural_name}")
103
+ doc = Hpricot::XML(response)
104
+ @all = (doc / xml_name).map {|data| new(data)}
105
+ end
106
+ end
107
+
108
+ class Deployment < Base
109
+ def self.find_by_nickname(nickname)
110
+ deployments = all.select { |deployment| deployment.nickname == nickname }
111
+
112
+ if deployments.size != 1
113
+ raise "Found #{deployments.size} deployments matching #{nickname}. Double check your nickname, it should be exact to avoid hitting the deployment."
114
+ end
115
+
116
+ deployments.first
117
+ end
118
+
119
+ def servers
120
+ (@data / 'server').map {|data| Server.new(data)}
121
+ end
122
+ end
123
+
124
+ class Server < Base
125
+ attr_accessor :aws_id
126
+
127
+ def deployment
128
+ @deployment ||= Deployment.all.detect {|deployment| deployment.id == deployment_href.split('/').last}
129
+ end
130
+
131
+ def aws_id
132
+ @aws_id ||= @@non_api_connection.get("/servers/#{id}").scan(/i-[a-f0-9]{8}/i).first
133
+ end
134
+
135
+ def volume_rightscale_ids
136
+ puts @@non_api_connection.get("/servers/#{id}/volumes").scan(/(?=ec2_ebs_volumes\/)\d+/).inspect
137
+ end
138
+ end
139
+
140
+ class RightScript < Base
141
+ end
142
+
143
+ class Ec2EbsVolume < Base
144
+ end
145
+
146
+ class Ec2EbsSnapshot < Base
147
+ end
148
+ end
data/lib/right_api.rb ADDED
@@ -0,0 +1 @@
1
+ # require 'right_api/rightscale'
data/right_api.gemspec ADDED
@@ -0,0 +1,49 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{right_api}
5
+ s.version = "0.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["MoneyPools"]
9
+ s.date = %q{2009-08-07}
10
+ s.description = %q{A ruby wrapper for the RightScale api}
11
+ s.email = %q{mpdev@businesslogic.com}
12
+ s.extra_rdoc_files = [
13
+ "README"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "README",
18
+ "Rakefile",
19
+ "VERSION.yml",
20
+ "install.rb",
21
+ "lib/right_api.rb",
22
+ "lib/right_api/accessible_fragment.rb",
23
+ "lib/right_api/http_server.rb",
24
+ "lib/right_api/rightscale.rb",
25
+ "right_api.gemspec",
26
+ "uninstall.rb"
27
+ ]
28
+ s.homepage = %q{http://github.com/moneypools/right_api}
29
+ s.rdoc_options = ["--charset=UTF-8"]
30
+ s.require_paths = ["lib"]
31
+ s.rubygems_version = %q{1.3.4}
32
+ s.summary = %q{A ruby wrapper for the RightScale api}
33
+
34
+ if s.respond_to? :specification_version then
35
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
39
+ s.add_runtime_dependency(%q<hpricot>, [">= 0"])
40
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
41
+ else
42
+ s.add_dependency(%q<hpricot>, [">= 0"])
43
+ s.add_dependency(%q<activesupport>, [">= 0"])
44
+ end
45
+ else
46
+ s.add_dependency(%q<hpricot>, [">= 0"])
47
+ s.add_dependency(%q<activesupport>, [">= 0"])
48
+ end
49
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moneypools-right_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - MoneyPools
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-07 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hpricot
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: A ruby wrapper for the RightScale api
36
+ email: mpdev@businesslogic.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README
43
+ files:
44
+ - .gitignore
45
+ - README
46
+ - Rakefile
47
+ - VERSION.yml
48
+ - install.rb
49
+ - lib/right_api.rb
50
+ - lib/right_api/accessible_fragment.rb
51
+ - lib/right_api/http_server.rb
52
+ - lib/right_api/rightscale.rb
53
+ - right_api.gemspec
54
+ - uninstall.rb
55
+ has_rdoc: false
56
+ homepage: http://github.com/moneypools/right_api
57
+ licenses:
58
+ post_install_message:
59
+ rdoc_options:
60
+ - --charset=UTF-8
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.3.5
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: A ruby wrapper for the RightScale api
82
+ test_files: []
83
+