Skip to content

Commit

Permalink
added exceptions / error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
movitto committed Apr 7, 2010
1 parent 9f9e191 commit 029c8e4
Show file tree
Hide file tree
Showing 14 changed files with 776 additions and 146 deletions.
23 changes: 17 additions & 6 deletions db/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Event < ActiveRecord::Base

# TODO right mow just returning a fixed list, at some point dynamically generate
def self.processes
["create_package", "update_repo", "run_test_suite", "notify_subscribers"]
["create_rpm_package", "update_yum_repo", "run_test_suite", "notify_subscribers"]
end

# XXX FIXME we need this for security
Expand All @@ -49,10 +49,12 @@ def self.processes

# determine if event applies to specified version
def applies_to_version?(version)
raise ArgumentError, "valid event version #{gem_version} and version #{version} required" unless gem_version.class == String && version.class == String

# XXX remove any non-numeric chars from the version number (eg if a version has a '-beta' or whatnot, not pretty but works for now
version.gsub(/[a-zA-Z]*/, '')

# TODO this will evaluate to false "1.1" = "1.1.0" here, is this correct? (implement this in a more robust way)
# TODO this will evaluate to false "1.1" = "1.1.0" here, is this correct? (implement this in a more robust way, eg split version into array around delims, compare each array elements w/ special case handling)
gv, ev = version, gem_version
return (["", nil].include? version_qualifier ) ||
(version_qualifier == "=" && gv == ev) ||
Expand All @@ -64,16 +66,25 @@ def applies_to_version?(version)

# run the event
def run(params = {})
# covert process to method name
handler = method(process.intern)
handler = nil
begin
# covert process to method name
handler = method(process.intern)
rescue NameError => e
raise ArgumentError, "could not find event handler #{process}"
end

entity = gem
entity = project if entity.nil?

# generate array of event params from gem/project, semi-colon seperated process options, and options params
event_params = [entity, (process_options.nil? ? [] : process_options.split(';')), params]

# invoke
handler.call *event_params
begin
# invoke
handler.call *event_params
rescue Exception => e
raise RuntimeError, "error when running event handler #{process}: #{e}"
end
end
end
71 changes: 52 additions & 19 deletions db/models/managed_gem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,51 +39,76 @@ def self.uri_to_source_uri(gem_uri)
def subscribe(args = {})
callback_url = args[:callback_url]
api_key = POLISHER_CONFIG["gem_api_key"]
raise ArgumentError, "must specify valid callback url and api key" unless callback_url.class == String && api_key.class == String

subscribe_path = '/api/v1/web_hooks'
headers = { 'Authorization' => api_key }
data = "gem_name=#{name}&url=#{callback_url}"

http = Net::HTTP.new(URI.parse(gem_source.uri).host, 80)
res = http.post(subscribe_path, data, headers)
# TODO handle res = #<Net::HTTPNotFound:0x7f1df8319e40> This gem could not be found
begin
http = Net::HTTP.new(URI.parse(gem_source.uri).host, 80)
res = http.post(subscribe_path, data, headers)
raise RuntimeError if res.class == Net::HTTPNotFound
rescue Exception => e
raise RuntimeError, "could not subscribe to gem #{name} at #{gem_source.uri}#{subscribe_path}"
end
end

# determine if we are subscribed to gem
def subscribed?
api_key = POLISHER_CONFIG["gem_api_key"]
raise ArgumentError, "must specify valid api key" unless api_key.class == String

subscribe_path = '/api/v1/web_hooks.json'
headers = { 'Authorization' => api_key }

http = Net::HTTP.new(URI.parse(gem_source.uri).host, 80)
res = http.get(subscribe_path, headers).body
res = JSON.parse(res)
return res.has_key?(name)
begin
http = Net::HTTP.new(URI.parse(gem_source.uri).host, 80)
res = http.get(subscribe_path, headers).body
raise RuntimeError if res.class == Net::HTTPNotFound
res = JSON.parse(res)
return res.has_key?(name)

rescue Exception => e
raise RuntimeError, "could not connect to gem source at #{gem_source.uri}#{subscribe_path}"
end
end

# unsubscribe to updates to this gem from associated gem source
def unsubscribe(args = {})
return unless subscribed?
callback_url = args[:callback_url]
api_key = POLISHER_CONFIG["gem_api_key"]
raise ArgumentError, "must specify valid callback url and api key" unless callback_url.class == String && api_key.class == String

subscribe_path = "/api/v1/web_hooks/remove?gem_name=#{name}&url=#{callback_url}"
headers = { 'Authorization' => api_key }

http = Net::HTTP.new(URI.parse(gem_source.uri).host, 80)
res = http.delete(subscribe_path, headers)
begin
http = Net::HTTP.new(URI.parse(gem_source.uri).host, 80)
res = http.delete(subscribe_path, headers)
raise RuntimeError if res.class == Net::HTTPNotFound
rescue Exception => e
raise RuntimeError, "could not delete gem #{name} via #{gem_source.uri}#{subscribe_path}"
end
end

# return hash of gem attributes/values retreived from remote source
def get_info
info = nil
source_uri = URI.parse(gem_source.uri).host
get_path = "/api/v1/gems/#{name}.json"
info = nil
source_uri = URI.parse(gem_source.uri).host
get_path = "/api/v1/gems/#{name}.json"
begin
Net::HTTP.start(source_uri, 80) { |http|
info = JSON.parse(http.get(get_path).body)
res = http.get(get_path).body
raise RuntimeError if res.class == Net::HTTPNotFound
info = JSON.parse(res)
}
return info
rescue Exception => e
raise RuntimeError, "could not get info for gem #{name} via #{source_uri}#{get_path}"
end

return info
end

def download_to(args = {})
Expand All @@ -99,12 +124,20 @@ def download_to(args = {})
else
gem_uri = source.uri + "/gems/#{name}-#{version}.gem"
end
path = dir + "/#{name}-#{version}.gem" if path.nil?

curl = Curl::Easy.new(gem_uri)
curl.follow_location = true # follow redirects
curl.perform
File.write path, curl.body_str
begin
path = dir + "/#{name}-#{version}.gem" if path.nil?
dir = File.dirname(path)
raise ArgumentError unless File.writable?(dir)

curl = Curl::Easy.new(gem_uri)
curl.follow_location = true # follow redirects
curl.perform
File.write path, curl.body_str

rescue Exception => e
raise RuntimeError, "could not download gem from #{gem_uri} to #{path}"
end

return path
end
Expand Down
25 changes: 16 additions & 9 deletions db/models/project_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,22 @@ def download_to(args = {})
turi = uri
variables.each { |k,v| turi.gsub!("%{#{k}}", v.to_s) }

# generate path which to d/l the file to
urio = URI::parse(turi)
path = dir + "/" + urio.path.split('/').last if path.nil?

# d/l the file
curl = Curl::Easy.new(turi)
curl.follow_location = true # follow redirects
curl.perform
File.write path, curl.body_str
begin
# generate path which to d/l the file to
urio = URI::parse(turi)
path = dir + "/" + urio.path.split('/').last if path.nil?
dir = File.dirname(path)
raise ArgumentError unless File.writable?(dir)

# d/l the file
curl = Curl::Easy.new(turi)
curl.follow_location = true # follow redirects
curl.perform
File.write path, curl.body_str

rescue Exception => e
raise RuntimeError, "could not download project source from #{turi} to #{path}"
end

return path
end
Expand Down
30 changes: 19 additions & 11 deletions lib/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@

module Polisher

# helper method to handle (print) xml status response
def handle_response(operation, response)
rr = LibXML::XML::Document.string(response.body).root
success = rr.children.find { |c| c.name == "success" }.content.strip
msg = rr.children.find { |c| c.name == "message" }.content.strip
puts "#{operation} returned w/ success = #{success} and the message: #{msg}"
end
module_function :handle_response

# DSL representations of model classes (so as to not require db connection on client side)

# DSL Managed Gem
Expand Down Expand Up @@ -56,19 +65,19 @@ def on_version(*args)

RestClient.post("#{$polisher_uri}/events/create",
:managed_gem_id => id, :process => process, :gem_version => version,
:version_qualifier => version_qualifier, :process_options => process_options) { |response| }
:version_qualifier => version_qualifier, :process_options => process_options) { |response| Polisher.handle_response('create gem event', response) }
end

# Delete managed gem
def delete
RestClient.delete("#{$polisher_uri}/gems/destroy/#{id}"){ |response| }
RestClient.delete("#{$polisher_uri}/gems/destroy/#{id}"){ |response| Polisher.handle_response('delete gem', response)}
end

# Test fire gem released event for specified version
def released(version)
RestClient.post("#{$polisher_uri}/gems/released",
:name => name, :version => version,
:gem_uri => source.uri + "/gems/#{name}-#{version}.gem" ) { |response| }
:gem_uri => source.uri + "/gems/#{name}-#{version}.gem" ) { |response| Polisher.handle_response('release gem', response)}
end
end

Expand Down Expand Up @@ -135,24 +144,24 @@ def on_version(*args)

RestClient.post("#{$polisher_uri}/events/create",
:project_id => id, :process => process, :gem_version => version,
:version_qualifier => version_qualifier, :process_options => process_options) { |response| }
:version_qualifier => version_qualifier, :process_options => process_options) { |response| Polisher.handle_response('create project event', response) }
end

# Delete project
def delete
RestClient.delete("#{$polisher_uri}/projects/destroy/#{id}") { |response| }
RestClient.delete("#{$polisher_uri}/projects/destroy/#{id}") { |response| Polisher.handle_response('delete project', response) }
end

# Add new Project source w/ specified uri
def add_source(uri)
sources << uri
RestClient.post("#{$polisher_uri}/project_sources/create", :project_id => id, :uri => uri) { |response| }
RestClient.post("#{$polisher_uri}/project_sources/create", :project_id => id, :uri => uri) { |response| Polisher.handle_response('add project source', response) }
end

# Test fire project released event for specified version
def released(version, params = {})
rparams = { :name => name, :version => version}.merge!(params)
RestClient.post("#{$polisher_uri}/projects/released", rparams ) { |response| }
RestClient.post("#{$polisher_uri}/projects/released", rparams ) { |response| Polisher.handle_response('released project', response) }
end
end

Expand Down Expand Up @@ -192,7 +201,7 @@ def gem(args = {})
return nil if src.nil? || args[:name].nil?
args[:gem_source_id] = src.id

RestClient.post("#{$polisher_uri}/gems/create", args) { |response| }
RestClient.post("#{$polisher_uri}/gems/create", args) { |response| Polisher.handle_response('create gem', response) }
gem = gem(args)
yield gem if block_given?
return gem
Expand Down Expand Up @@ -222,7 +231,7 @@ def source(args = {})
return source
end
}
RestClient.post("#{$polisher_uri}/gem_sources/create", args) { |response| }
RestClient.post("#{$polisher_uri}/gem_sources/create", args) { |response| Polisher.handle_response('create gem source', response) }
source = source(args)
yield source if block_given?
return source
Expand Down Expand Up @@ -251,9 +260,8 @@ def project(args = {})
return project
end
}
RestClient.post("#{$polisher_uri}/projects/create", args) { |response| }
RestClient.post("#{$polisher_uri}/projects/create", args) { |response| Polisher.handle_response('create project', response)}
project = project(args)
yield project if block_given?
return project
end

11 changes: 6 additions & 5 deletions lib/event_handlers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@
require 'gem2rpm'
require 'net/smtp'

# TODO raise some exceptions of our own here (though not neccessary as event.run will rescue everything raised, it might help w/ debugging)

module EventHandlers

# Convert entity (gem, project) into another package format.
# TODO rename to create_rpm_package
def create_package(entity, process_options = [''], optional_params = {})
def create_rpm_package(entity, process_options = [''], optional_params = {})
template_file = process_options[0]
spec_file = nil

if entity.class == ManagedGem
# d/l gem into artifacts/gems dir, link it into the artifacts/SOURCES dir
gem_file_path = File.expand_path(entity.download_to(:dir => ARTIFACTS_DIR + "/gems", :version => optional_params[:version]))
gem_file_path = entity.download_to(:dir => ARTIFACTS_DIR + "/gems", :version => optional_params[:version])
gem_file_path = File.expand_path(gem_file_path)
gem_file = gem_file_path.split('/').last
link_file = ARTIFACTS_DIR + '/SOURCES/' + gem_file
FileUtils.rm_f(link_file) if File.symlink?(link_file)
Expand Down Expand Up @@ -76,8 +78,7 @@ def create_package(entity, process_options = [''], optional_params = {})
end

# Update specified repository w/ latest entity (gem, project) artifact.
# TODO rename to update_yum_repo
def update_repo(entity, process_options, optional_params = {})
def update_yum_repo(entity, process_options, optional_params = {})
repository = process_options[0]
version = optional_params[:version]

Expand Down
Loading

0 comments on commit 029c8e4

Please sign in to comment.