right_api 0.1.2

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
+ :minor: 1
3
+ :patch: 2
4
+ :major: 0
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,144 @@
1
+ require 'net/https'
2
+ require 'cgi'
3
+
4
+ class HttpServer
5
+ attr_accessor :response_error_checker, :handle_errors, :headers
6
+ attr_reader :last_response
7
+
8
+ def initialize(server_config, timeout)
9
+ @server_url, @port, @username, @password = server_config['server_url'], server_config['port'], server_config['username'], server_config['password']
10
+ @timeout = timeout
11
+ raise 'No configuration for timeout length' if @timeout.nil?
12
+
13
+ @handle_errors = true
14
+ @response_error_checker = Proc.new do |response, path|
15
+ false
16
+ end
17
+
18
+ @headers = {
19
+ 'User-Agent' => 'Mozilla/4.0',
20
+ 'Content-Type' => 'application/x-www-form-urlencoded',
21
+ 'Connection' => 'Keep-Alive',
22
+ 'X-API-VERSION' => RightScale::API_VERSION
23
+ }
24
+ end
25
+
26
+ def delete(resource, &block)
27
+ connect(resource, Net::HTTP::Delete, &block)
28
+ end
29
+
30
+ def get(resource, &block)
31
+ connect(resource, Net::HTTP::Get, &block)
32
+ end
33
+
34
+ def get_with_params(resource, params={}, &block)
35
+ connect(resource, Net::HTTP::Get, encode_params(params), &block)
36
+ end
37
+
38
+ def post(resource, params={}, &block)
39
+ connect(resource, Net::HTTP::Post, encode_params(params), &block)
40
+ end
41
+
42
+ def put(resource, params={}, &block)
43
+ connect(resource, Net::HTTP::Put, encode_params(params), &block)
44
+ end
45
+
46
+ def with_error_handling_disabled
47
+ original_handle_errors = handle_errors
48
+ self.handle_errors = false
49
+
50
+ result = yield
51
+ ensure
52
+ self.handle_errors = original_handle_errors
53
+ end
54
+
55
+ private
56
+
57
+ def connect(resource, request_object, *args, &block)
58
+ uri = URI.parse url(resource)
59
+ req = request_object.new(uri.path, @headers)
60
+ req.basic_auth @username, @password if @username
61
+
62
+ response_data = nil
63
+
64
+ begin
65
+ create_http(uri).start do |http|
66
+ response, data = http.request(req, *args)
67
+
68
+ block.call(self, response) if block
69
+
70
+ @last_response = response_data = data_from(response)
71
+ end
72
+ rescue Timeout::Error
73
+ raise "A timeout error occured when connecting to #{resource}.\nThe timeout is currently set to #{@timeout} seconds."
74
+ rescue Errno::ECONNREFUSED
75
+ raise "Could not connect when connecting to #{resource} - the server (#{@server_url}) is down."
76
+ end
77
+
78
+ check_response_for_errors(response_data, uri.path) if handle_errors
79
+
80
+ response_data
81
+ end
82
+
83
+ def data_from(response)
84
+ case response
85
+ when Net::HTTPSuccess
86
+ response.body
87
+ when Net::HTTPRedirection
88
+ response['location']
89
+ end
90
+ end
91
+
92
+ def create_http(uri)
93
+ http = Net::HTTP.new(uri.host, uri.port)
94
+ http.use_ssl = true if uri.port == 443
95
+ http.read_timeout = @timeout
96
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
97
+
98
+ # http.set_debug_output $stderr
99
+
100
+ http
101
+ end
102
+
103
+ def url(resource)
104
+ "#{server_path}/#{resource.sub /^\//, ''}"
105
+ end
106
+
107
+ def server_path
108
+ @port ? "#{@server_url}:#{@port}" : @server_url
109
+ end
110
+
111
+ def encode_params(hash)
112
+ params = transform_params(hash)
113
+ stringify_params(params)
114
+ end
115
+
116
+ def transform_params(hash)
117
+ params = []
118
+
119
+ hash.each do |key, value|
120
+ if value.instance_of? Hash
121
+ params.concat transform_params(value).each{|elements| elements[0].unshift key}
122
+ else
123
+ params.push [[key], value]
124
+ end
125
+ end
126
+
127
+ params
128
+ end
129
+
130
+ def stringify_params(params)
131
+ params.map do |keys, value|
132
+ left = keys.join('[') + (']' * (keys.length - 1))
133
+ "#{left}=#{CGI::escape(value.to_s)}"
134
+ end.join('&')
135
+ end
136
+
137
+ def check_response_for_errors(response, path)
138
+ if response && response.include?('No connection could be made')
139
+ raise Errno::ECONNREFUSED
140
+ elsif @response_error_checker.call(response, path)
141
+ raise "An error occured requesting #{path} - please check the XML response:\n #{response}\nCurrent data:\n#{@data}"
142
+ end
143
+ end
144
+ 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,52 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{right_api}
8
+ s.version = "0.1.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["MoneyPools"]
12
+ s.date = %q{2009-08-24}
13
+ s.description = %q{A ruby wrapper for the RightScale api}
14
+ s.email = %q{mpdev@businesslogic.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "README",
21
+ "Rakefile",
22
+ "VERSION.yml",
23
+ "install.rb",
24
+ "lib/right_api.rb",
25
+ "lib/right_api/accessible_fragment.rb",
26
+ "lib/right_api/http_server.rb",
27
+ "lib/right_api/rightscale.rb",
28
+ "right_api.gemspec",
29
+ "uninstall.rb"
30
+ ]
31
+ s.homepage = %q{http://github.com/moneypools/right_api}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.3}
35
+ s.summary = %q{A ruby wrapper for the RightScale api}
36
+
37
+ if s.respond_to? :specification_version then
38
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
39
+ s.specification_version = 3
40
+
41
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
42
+ s.add_runtime_dependency(%q<hpricot>, [">= 0"])
43
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
44
+ else
45
+ s.add_dependency(%q<hpricot>, [">= 0"])
46
+ s.add_dependency(%q<activesupport>, [">= 0"])
47
+ end
48
+ else
49
+ s.add_dependency(%q<hpricot>, [">= 0"])
50
+ s.add_dependency(%q<activesupport>, [">= 0"])
51
+ end
52
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: right_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - MoneyPools
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-27 00:00:00 -05: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: true
56
+ homepage: http://github.com/moneypools/right_api
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.5
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: A ruby wrapper for the RightScale api
83
+ test_files: []
84
+