[deploy] Add App, Database, and Search Health Check Endpoints (#8071)

This commit is contained in:
Molly Struve 2020-05-28 08:33:31 -05:00 committed by GitHub
parent 0edca1fe2c
commit 8a4c2c1cb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 122 additions and 1 deletions

View 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

View file

@ -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

View file

@ -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>

View file

@ -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

View 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