[deploy] Add App, Database, and Search Health Check Endpoints (#8071)
This commit is contained in:
parent
0edca1fe2c
commit
8a4c2c1cb4
5 changed files with 122 additions and 1 deletions
37
app/controllers/api/v0/health_checks_controller.rb
Normal file
37
app/controllers/api/v0/health_checks_controller.rb
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
module Api
|
||||
module V0
|
||||
class HealthChecksController < ApiController
|
||||
before_action :authenticate_with_token
|
||||
|
||||
def app
|
||||
render json: { message: "App is up!" }, status: :ok
|
||||
end
|
||||
|
||||
def search
|
||||
if Search::Client.ping
|
||||
render json: { message: "Search ping succeeded!" }, status: :ok
|
||||
else
|
||||
render json: { message: "Search ping failed!" }, status: :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
def database
|
||||
if ActiveRecord::Base.connected?
|
||||
render json: { message: "Database connected" }, status: :ok
|
||||
else
|
||||
render json: { message: "Database NOT connected!" }, status: :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authenticate_with_token
|
||||
key = request.headers["health-check-token"]
|
||||
|
||||
return if key == SiteConfig.health_check_token
|
||||
|
||||
error_unauthorized
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -116,4 +116,7 @@ class SiteConfig < RailsSettings::Base
|
|||
|
||||
# Shop
|
||||
field :shop_url, type: :string, default: "https://shop.dev.to"
|
||||
|
||||
# Special API tokens
|
||||
field :health_check_token, type: :string, default: "secret"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -293,7 +293,6 @@
|
|||
<div class="alert alert-info">URL campaign sidebar image will link to</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<%= f.label :campaign_featured_tags %>
|
||||
<%= f.text_field :campaign_featured_tags,
|
||||
|
|
@ -596,6 +595,27 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
<%= render partial: "card_header",
|
||||
locals: {
|
||||
header: "API",
|
||||
state: "collapse",
|
||||
target: "apiBodyContainer",
|
||||
expanded: "false"
|
||||
} %>
|
||||
<div id="apiBodyContainer" class="card-body collapse hide" aria-labelledby="apiBodyContainer">
|
||||
<div class="form-group">
|
||||
<%= f.label :health_check_token, "Health Check Token" %>
|
||||
<%= f.text_field :health_check_token,
|
||||
class: "form-control",
|
||||
value: SiteConfig.health_check_token,
|
||||
placeholder: "a secure token" %>
|
||||
<div class="alert alert-info">Used to authenticate with your health check endpoints.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if current_user.has_role?(:single_resource_admin, Config) %>
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">Confirm and Submit</div>
|
||||
|
|
|
|||
|
|
@ -143,6 +143,14 @@ Rails.application.routes.draw do
|
|||
get "/analytics/historical", to: "analytics#historical"
|
||||
get "/analytics/past_day", to: "analytics#past_day"
|
||||
get "/analytics/referrers", to: "analytics#referrers"
|
||||
|
||||
resources :health_checks, only: [] do
|
||||
collection do
|
||||
get :app
|
||||
get :search
|
||||
get :database
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
53
spec/requests/api/v0/health_checks_spec.rb
Normal file
53
spec/requests/api/v0/health_checks_spec.rb
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe "HealthCheck", type: :request do
|
||||
let(:token) { "secret" }
|
||||
let(:headers) { { "health-check-token" => token } }
|
||||
|
||||
before { SiteConfig.health_check_token = token }
|
||||
|
||||
context "without a token" do
|
||||
it "returns an unauthorized request" do
|
||||
get app_api_health_checks_path
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/health_checks/app" do
|
||||
it "returns json success" do
|
||||
get app_api_health_checks_path, headers: headers
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.parsed_body["message"]).to eq("App is up!")
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/health_checks/search" do
|
||||
it "returns json success if ping succeeds" do
|
||||
get search_api_health_checks_path, headers: headers
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.parsed_body["message"]).to eq("Search ping succeeded!")
|
||||
end
|
||||
|
||||
it "returns json failure if ping fails" do
|
||||
allow(Search::Client).to receive(:ping).and_return(false)
|
||||
get search_api_health_checks_path, headers: headers
|
||||
expect(response.status).to eq(500)
|
||||
expect(response.parsed_body["message"]).to eq("Search ping failed!")
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/health_checks/database" do
|
||||
it "returns json success if connection check succeeds" do
|
||||
get database_api_health_checks_path, headers: headers
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.parsed_body["message"]).to eq("Database connected")
|
||||
end
|
||||
|
||||
it "returns json failure if connection check fails" do
|
||||
allow(ActiveRecord::Base).to receive(:connected?).and_return(false)
|
||||
get database_api_health_checks_path, headers: headers
|
||||
expect(response.status).to eq(500)
|
||||
expect(response.parsed_body["message"]).to eq("Database NOT connected!")
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue