Commit 3f5f93e

mo khan <mo@mokhan.ca>
2014-11-11 04:55:30
add api endpoint for recording failures.
1 parent 9c93c84
app/controllers/api/v1/api_controller.rb
@@ -0,0 +1,17 @@
+module Api
+  module V1
+    class ApiController < ApplicationController
+      before_action :authenticate
+      skip_before_action :ensure_valid_session
+      attr_reader :current_environment
+
+      private
+
+      def authenticate
+        authenticate_or_request_with_http_token do |token, options|
+          @current_environment = Environment.find_by(api_key: token)
+        end
+      end
+    end
+  end
+end
app/controllers/api/v1/errors_controller.rb
@@ -0,0 +1,18 @@
+module Api
+  module V1
+    class ErrorsController < ApiController
+      def create
+        failure = current_environment.failures.build(error_params)
+        failure.backtrace = params[:error][:backtrace]
+        failure.save!
+        render nothing: true
+      end
+
+      private
+
+      def error_params
+        params.require(:error).permit(:message, :hostname, :error_type, :backtrace)
+      end
+    end
+  end
+end
app/controllers/application_controller.rb
@@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base
   # Prevent CSRF attacks by raising an exception.
   # For APIs, you may want to use :null_session instead.
   protect_from_forgery with: :exception
-  before_filter :ensure_valid_session
+  before_action :ensure_valid_session
 
   def resolve(key)
     Spank::IOC.resolve(key)
app/models/environment.rb
@@ -1,5 +1,6 @@
 class Environment < ActiveRecord::Base
   belongs_to :service
+  has_many :failures
   before_create :create_api_key
 
   private
app/models/failure.rb
@@ -0,0 +1,2 @@
+class Failure < ActiveRecord::Base
+end
config/routes.rb
@@ -5,7 +5,15 @@ Erkell::Application.routes.draw do
   resources :environments, only: [:index, :show, :create, :destroy]
 
   get 'dashboard', to: 'dashboard#index'
+
+  namespace :api do
+    namespace :v1 do
+      resources :errors, only: [:create]
+    end
+  end
+
   root 'dashboard#index'
+
   # The priority is based upon order of creation: first created -> highest priority.
   # See how all your routes lay out with "rake routes".
 
db/migrate/20141111043011_create_failures.rb
@@ -0,0 +1,13 @@
+class CreateFailures < ActiveRecord::Migration
+  def change
+    create_table :failures do |t|
+      t.references :environment, index: true
+      t.string :message
+      t.string :hostname
+      t.string :error_type
+      t.text :backtrace, array: true, default: []
+
+      t.timestamps
+    end
+  end
+end
db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20141110181704) do
+ActiveRecord::Schema.define(version: 20141111043011) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -26,6 +26,18 @@ ActiveRecord::Schema.define(version: 20141110181704) do
 
   add_index "environments", ["service_id"], name: "index_environments_on_service_id", using: :btree
 
+  create_table "failures", force: true do |t|
+    t.integer  "environment_id"
+    t.string   "message"
+    t.string   "hostname"
+    t.string   "error_type"
+    t.text     "backtrace",      default: [], array: true
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "failures", ["environment_id"], name: "index_failures_on_environment_id", using: :btree
+
   create_table "services", force: true do |t|
     t.string   "name"
     t.datetime "created_at"
spec/controllers/api/v1/errors_controller_spec.rb
@@ -0,0 +1,38 @@
+require 'rails_helper'
+
+module Api
+  module V1
+    describe ErrorsController do
+      describe "#create" do
+        let(:service) { create(:service) }
+        let(:environment) { create(:environment, service: service) }
+        let(:token) { ActionController::HttpAuthentication::Token.encode_credentials(environment.api_key) }
+        let(:error) do
+          begin
+            1/0
+          rescue StandardError => error
+            error
+          end
+        end
+        let(:hostname) { Socket.gethostname }
+
+        before :each do
+          request.env['HTTP_AUTHORIZATION'] = token
+        end
+
+        it 'saves a new error' do
+          xhr :post, :create, error: { message: error.message, hostname: hostname, error_type: error.class, backtrace: error.backtrace }
+          environment.reload
+
+          expect(response.status).to eql(200)
+          expect(environment.failures.count).to eql(1)
+          failure = Failure.last
+          expect(failure.message).to eql(error.message)
+          expect(failure.hostname).to eql(hostname)
+          expect(failure.error_type).to eql(error.class.to_s)
+          expect(failure.backtrace).to eql(error.backtrace)
+        end
+      end
+    end
+  end
+end
spec/models/failure_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe Failure, :type => :model do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
spec/factories.rb
@@ -23,4 +23,11 @@ FactoryGirl.define do
   factory :environment do
     name Faker::Lorem.word
   end
+
+  factory :failure do
+    environment
+    message "heck"
+    hostname "local"
+    type ""
+  end
 end