Permalink
Browse files

create projects from command line

  • Loading branch information...
1 parent 50e216d commit fcc60841658a19ad3f5d7df67f52a4dc84a30c0c @shime shime committed Oct 12, 2012
View
@@ -1,160 +1,12 @@
#!/usr/bin/env ruby
+
require "airbrake"
+require "airbrake/cli/runner"
require "net/http"
require "uri"
-class Project
- # TODO should probably be moved
- #
- attr_writer :name, :id, :api_key
-
- def to_s
- "#{@name}".rjust(20) + "(#{@id}):".rjust(10) + " #{@api_key}"
- end
-
- def valid?
- @name && @id && @api_key
- end
-end
-
-class ProjectFactory
- # TODO should probably be moved
- #
- def initialize
- @project = Project.new
- @projects = []
- end
-
- def project
- @project
- end
-
- def create_projects_from_xml(xml)
- xml.split("\n").each do |line|
- /<name[^>]*>(?<name>.*?)<\/name>/ =~ line
- project.name = name.capitalize if name
- /<id[^>]*>(?<id>.*?)<\/id>/ =~ line
- project.id = id if id
- /<api-key[^>]*>(?<api_key>.*?)<\/api-key>/ =~ line
- project.api_key = api_key if api_key
- check_project
- end
- end
-
- def check_project
- if @project.valid?
- projects << @project
- @project = Project.new
- end
- end
-
- def projects
- @projects
- end
-end
-
-def parse_options(array = [])
- opts = Hash[*array]
- opts[:error] = opts.delete("-e") || opts.delete("--error") { RuntimeError }
- opts[:message] = opts.delete("-m") || opts.delete("--message") { "I've made a huge mistake" }
- opts[:api_key] = opts.delete("-k") || opts.delete("--api-key") || config_from_file.api_key || ENV["AIRBRAKE_API_KEY"]
- opts[:host] = opts.delete("-h") || opts.delete("--host") || config_from_file.host
- opts[:port] = opts.delete("-p") || opts.delete("--port") || config_from_file.port
- opts[:auth_token] = opts.delete("-t") || opts.delete("--auth-token") || ENV["AIRBRAKE_AUTH_TOKEN"]
- opts[:account] = opts.delete("-a") || opts.delete("--account") || ENV["AIRBRAKE_ACCOUNT"]
- opts
-end
-
-def config_from_file
- begin
- load "config/initializers/airbrake.rb"
- rescue LoadError
- end
- Airbrake.configuration
-end
-
-def print_usage
- puts <<USAGE
-Usage: airbrake [COMMAND] [OPTION]...
-Commands:
- raise # Raise an exception specified by ERROR and MESSAGE.
- list # List all the projects for given AUTH_TOKEN and ACCOUNT.
-
-Options:
- -e, [--error=ERROR] # Error class to raise. Default: RuntimeError
- -m, [--message=MESSAGE] # Error message. Default: "I've made a huge mistake"
- -k, [--api-key=API_KEY] # Api key of your Airbrake application.
- -h, [--host=HOST] # URL of the Airbrake API server. Default: api.airbrake.io
- -p, [--port=PORT] # Port of the Airbrake API server. Default: 80
- -t, [--auth-token=AUTH_TOKEN] # The auth token used for API requests.
- -a, [--account=ACCOUNT] # The account used for API requests.
- -h, [--help] # Show this usage
-USAGE
-end
-
-def check_api_key
- abort "You didn't provide API_KEY so nothing was raised."\
- " Refer to usage for more info (airbrake --help)." unless options[:api_key]
-end
-
-def check_account
- abort "You didn't provide ACCOUNT "\
- "so no API request was made." unless options[:account]
-end
-
-def check_auth_token
- abort "You didn't provide AUTH_TOKEN "\
- "so no API request was made." unless options[:auth_token]
-end
-
-def fetch_projects
- uri = URI.parse "http://#{options[:account]}.airbrake.io"\
- "/data_api/v1/projects.xml?auth_token=#{options[:auth_token]}"
- http = Net::HTTP.new(uri.host,uri.port)
- request = Net::HTTP::Get.new(uri.request_uri)
- response = http.request(request)
- response.body
-end
-
-def print_projects
- factory = ProjectFactory.new
- factory.create_projects_from_xml(fetch_projects)
- puts "\nProjects\n" + "".rjust(63,"#")
- factory.projects.each do |project|
- puts project
- end
- puts
-end
-
-def options=(options)
- @options = options
-end
-
-def options
- @options
-end
-
args = ARGV.dup
command = args.shift.strip rescue nil
-self.options = parse_options(ARGV[1..-1])
+options = ARGV[1..-1]
-case command
- when 'raise'
- check_api_key
- Airbrake.configure do |c|
- c.api_key = options[:api_key]
- c.host = options[:host] if options[:host]
- c.port = options[:port] if options[:port]
- end
- exception_id = Airbrake.notify(:error_class => options[:error],
- :error_message => "#{options[:error]}: #{options[:message]}",
- :cgi_data => ENV)
- abort "Error sending exception to Airbrake server. Try again later." unless exception_id
- puts "Exception sent successfully: http://airbrake.io/locate/#{exception_id}"
- when "list"
- check_auth_token
- check_account
- print_projects
- else
- print_usage
- end
+Runner.run!(command, options)
View
@@ -0,0 +1,58 @@
+require File.expand_path( "../runner", __FILE__)
+
+module Client
+ extend self
+
+ def options
+ Runner.options
+ end
+
+ def fetch_projects
+ uri = URI.parse "http://#{options.account}.airbrake.io"\
+ "/data_api/v1/projects.xml?auth_token=#{options.auth_token}"
+ http = Net::HTTP.new(uri.host,uri.port)
+ request = Net::HTTP::Get.new(uri.request_uri)
+ response = http.request(request)
+ response.body
+ end
+
+ def create_project
+ uri = URI.parse "http://#{options.account}.airbrake.local:3000"\
+ "/data_api/v1/projects.xml"
+ http = Net::HTTP.new(uri.host,uri.port)
+ request = Net::HTTP::Post.new(uri.request_uri)
+ request.set_form_data('project[name]' => options.name,'auth_token' => options.auth_token)
+ response = http.request(request)
+ response.body
+
+ print_project_response(response.body)
+ end
+
+ def print_projects
+ factory = ProjectFactory.new
+ projects = fetch_projects
+ factory.create_projects_from_xml(projects)
+ abort "No projects were fetched. Did you provide the correct auth token?" if projects.match(/error/m)
+ puts "\nProjects\n" + "".rjust(63,"#")
+ factory.projects.each do |project|
+ puts project
+ end
+ puts
+ end
+
+ def print_project_response(response)
+ case response
+ when /errors/
+ puts "Error creating project: #{response.gsub("\n","").scan(/.*<error[^>]*>(.*?)<\/error>.*/).last.first.gsub(/\s{1,}/," ")}"
+ when /project/
+ project = Project.new(:id => response[/<id[^>]*>(.*?)<\/id>/,1],
+ :name => response[/<name[^>]*>(.*?)<\/name>/,1],
+ :api_key => response[/<api-key[^>]*>(.*?)<\/api-key>/,1])
+ puts "\nProject details\n" + "".rjust(63,"#")
+ puts project
+ else
+ puts "Unexpected error. Please try again!\n"
+ puts response
+ end
+ end
+end
@@ -0,0 +1,34 @@
+class Options
+
+ attr_reader :error, :message, :api_key, :host, :port, :auth_token, :name, :account
+
+ private
+
+ # You should not write to this from outside
+ attr_writer :error, :message, :api_key, :host, :port, :auth_token, :name, :account
+
+ public
+
+ # Parses all the options passed and stores them in attributes
+ def initialize(array = [])
+ opts = Hash[*array]
+ self.error = opts.delete("-e") || opts.delete("--error") { RuntimeError }
+ self.message = opts.delete("-m") || opts.delete("--message") { "I've made a huge mistake" }
+ self.api_key = opts.delete("-k") || opts.delete("--api-key") || config_from_file.api_key || ENV["AIRBRAKE_API_KEY"]
+ self.host = opts.delete("-h") || opts.delete("--host") || config_from_file.host
+ self.port = opts.delete("-p") || opts.delete("--port") || config_from_file.port
+ self.auth_token = opts.delete("-t") || opts.delete("--auth-token") || ENV["AIRBRAKE_AUTH_TOKEN"]
+ self.name = opts.delete("-n") || opts.delete("--name")
+ self.account = opts.delete("-a") || opts.delete("--account") || ENV["AIRBRAKE_ACCOUNT"]
+ opts
+ end
+
+ # Fallback to read from the initializer
+ def config_from_file
+ begin
+ load "config/initializers/airbrake.rb"
+ rescue LoadError
+ end
+ Airbrake.configuration
+ end
+end
@@ -0,0 +1,28 @@
+module Printer
+ def self.print(collection)
+ collection.each do |element|
+ puts element
+ end
+ end
+
+ def self.print_usage
+ puts <<-USAGE
+Usage: airbrake [COMMAND] [OPTION]...
+Commands:
+ raise # Raise an exception specified by ERROR and MESSAGE.
+ list # List all the projects for given AUTH_TOKEN and ACCOUNT.
+ create # Create a project with the given NAME.
+
+Options:
+ -e, [--error=ERROR] # Error class to raise. Default: RuntimeError
+ -m, [--message=MESSAGE] # Error message. Default: "I've made a huge mistake"
+ -k, [--api-key=API_KEY] # Api key of your Airbrake application.
+ -h, [--host=HOST] # URL of the Airbrake API server. Default: api.airbrake.io
+ -p, [--port=PORT] # Port of the Airbrake API server. Default: 80
+ -t, [--auth-token=AUTH_TOKEN] # The auth token used for API requests.
+ -a, [--account=ACCOUNT] # The account used for API requests.
+ -n, [--name=NAME] # The name of the project you're trying to create.
+ -h, [--help] # Show this usage
+ USAGE
+ end
+end
@@ -0,0 +1,17 @@
+class Project
+ attr_writer :name, :id, :api_key
+
+ def initialize(attributes = {})
+ attributes.keys.each do |key|
+ instance_variable_set("@#{key}",attributes[key])
+ end
+ end
+
+ def to_s
+ "#{@name}".rjust(20) + "(#{@id}):".rjust(10) + " #{@api_key}"
+ end
+
+ def valid?
+ @name && @id && @api_key
+ end
+end
@@ -0,0 +1,36 @@
+require File.expand_path( "../project", __FILE__)
+# Responsible for creating projects when needed.
+# Creates them from XML received.
+class ProjectFactory
+ def initialize
+ @project = Project.new
+ @projects = []
+ end
+
+ def project
+ @project
+ end
+
+ def create_projects_from_xml(xml)
+ xml.split("\n").each do |line|
+ /<name[^>]*>(?<name>.*?)<\/name>/ =~ line
+ project.name = name.capitalize if name
+ /<id[^>]*>(?<id>.*?)<\/id>/ =~ line
+ project.id = id if id
+ /<api-key[^>]*>(?<api_key>.*?)<\/api-key>/ =~ line
+ project.api_key = api_key if api_key
+ check_project
+ end
+ end
+
+ def check_project
+ if @project.valid?
+ projects << @project
+ @project = Project.new
+ end
+ end
+
+ def projects
+ @projects
+ end
+end
View
@@ -0,0 +1,41 @@
+require File.expand_path( "../project_factory", __FILE__)
+require File.expand_path( "../options", __FILE__)
+require File.expand_path( "../validator", __FILE__)
+require File.expand_path( "../printer", __FILE__)
+require File.expand_path( "../client", __FILE__)
+
+module Runner
+ extend Validator
+
+ extend self
+
+ attr_accessor :options
+
+ def run!(command, cli_options = {})
+
+ self.options = Options.new(cli_options)
+
+ case command
+ when 'raise'
+ validates :api_key
+ Airbrake.configure do |c|
+ c.api_key = options.api_key
+ c.host = options.host if options.host
+ c.port = options.port if options.port
+ end
+ exception_id = Airbrake.notify(:error_class => options.error,
+ :error_message => "#{options.error}: #{options.message}",
+ :cgi_data => ENV)
+ abort "Error sending exception to Airbrake server. Try again later." unless exception_id
+ puts "Exception sent successfully: http://airbrake.io/locate/#{exception_id}"
+ when "list"
+ validates :auth_token, :account
+ Client.print_projects
+ when "create"
+ validates :auth_token, :account
+ Client.create_project
+ else
+ Printer.print_usage
+ end
+ end
+end
@@ -0,0 +1,8 @@
+module Validator
+ def validates(*attributes)
+ attributes.each do |attribute|
+ abort "You didn't provide #{attribute.to_s.upcase}"\
+ " so no API request was made." unless Runner.options.send(attribute)
+ end
+ end
+end

0 comments on commit fcc6084

Please sign in to comment.