Skip to content

Instantly share code, notes, and snippets.

@skorfmann
Created April 9, 2014 06:39
Show Gist options
  • Save skorfmann/10232510 to your computer and use it in GitHub Desktop.
Save skorfmann/10232510 to your computer and use it in GitHub Desktop.
A super simple Sinatra API to expose the status of a unit / job within a CoreOS cluster.
require 'sinatra/base'
require 'etcd'
class Coffa < Sinatra::Base
get '/units/:name' do
begin
payload = fetch_payload(params[:name])
status 200
payload.value
rescue Etcd::KeyNotFound
status 404
end
end
get '/status/:name' do
begin
payload = fetch_job(params[:name])
status 200
payload.value
rescue Etcd::KeyNotFound
status 404
end
end
private
def etcd
@etcd ||= Etcd.client(host: ENV.fetch("ETCD_HOST", '127.0.0.1'), port: 4001)
end
def fetch_payload(name)
etcd.get("/_coreos.com/fleet/payload/#{name}.service")
end
def fetch_job(name)
etcd.get("/_coreos.com/fleet/job/#{name}.service")
end
end
ENV['RACK_ENV'] = 'test'
$:.push(File.expand_path(File.join(__FILE__, '..', '..')))
require 'spec_helper'
require 'rspec'
require 'coffa'
require 'rack/test'
describe 'Coffa' do
include Rack::Test::Methods
def app
Coffa
end
describe 'units' do
context 'not found' do
before do
stub_request(:get, "http://127.0.0.1:4001/v2/keys/_coreos.com/fleet/payload/no.service").
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(:status => 404, :body => '{"errorCode":100,"message":"Key not found","cause":"/_coreos.com/fleet/payload/no.service","index":6812}', :headers => {})
end
it 'handles 404' do
get '/units/no'
expect(last_response).to be_not_found
end
end
context 'found' do
before do
stub_request(:get, "http://127.0.0.1:4001/v2/keys/_coreos.com/fleet/payload/sesame.service").
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(:status => 200, :body => '{"action":"get","node":{"key":"/_coreos.com/fleet/payload/sesame.service","value":"{\"Name\":\"sesame.service\",\"Unit\":{\"Contents\":{\"Install\":{\"WantedBy\":\"local.target\"},\"Service\":{\"ExecStart\":\"/usr/bin/docker run --rm -p 8080:9292 --name sesame b17s/sesame:latest\",\"ExecStartPre\":\"/usr/bin/docker pull b17s/sesame\",\"ExecStop\":\"/usr/bin/docker kill sesame\",\"User\":\"core\"},\"Unit\":{\"After\":\"docker.service\",\"Description\":\"Sesame\",\"Requires\":\"docker.service\"}}}}","modifiedIndex":5354,"createdIndex":5354}}', :headers => {})
end
it 'has units endpoint' do
get '/units/sesame'
expect(last_response).to be_ok
end
end
end
describe 'status' do
context 'not found' do
before do
stub_request(:get, "http://127.0.0.1:4001/v2/keys/_coreos.com/fleet/job/no.service").
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(:status => 404, :body => '{"errorCode":100,"message":"Key not found","cause":"/_coreos.com/fleet/job/no.service","index":6902}', :headers => {})
end
it 'handles 404' do
get '/status/no'
expect(last_response).to be_not_found
end
end
context 'found' do
before do
stub_request(:get, "http://127.0.0.1:4001/v2/keys/_coreos.com/fleet/job/sesame.service").
with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(:status => 200, :body => '{"action":"get","node":{"key":"/_coreos.com/fleet/job/sesame.service","dir":true,"nodes":[{"key":"/_coreos.com/fleet/job/sesame.service/object","value":"{\"Name\":\"sesame.service\",\"JobRequirements\":{},\"Payload\":{\"Name\":\"sesame.service\",\"Unit\":{\"Contents\":{\"Install\":{\"WantedBy\":\"local.target\"},\"Service\":{\"ExecStart\":\"/usr/bin/docker run --rm -p 8080:9292 --name sesame b17s/sesame:latest\",\"ExecStartPre\":\"/usr/bin/docker pull b17s/sesame\",\"ExecStop\":\"/usr/bin/docker kill sesame\",\"User\":\"core\"},\"Unit\":{\"After\":\"docker.service\",\"Description\":\"Sesame\",\"Requires\":\"docker.service\"}}}},\"State\":null}","modifiedIndex":6638,"createdIndex":6638},{"key":"/_coreos.com/fleet/job/sesame.service/target","value":"398bd61a-0e09-4797-8929-f6d6ceb2c767","modifiedIndex":6646,"createdIndex":6646}],"modifiedIndex":6638,"createdIndex":6638}}', :headers => {})
end
it 'has status endpoint' do
get '/status/sesame'
expect(last_response).to be_ok
end
end
end
end
#!/usr/bin/env ruby
require 'rubygems'
require 'bundler/setup'
$: << File.expand_path(File.dirname(__FILE__))
require 'coffa'
use Coffa
run Sinatra::Application
source "https://rubygems.org"
gem 'sinatra'
gem 'etcd'
group :development do
gem 'rake'
gem 'rspec'
gem 'rack-test'
gem 'shotgun'
gem 'webmock'
end
require 'pathname'
$: << Pathname.new(__FILE__).parent.parent.to_s
require 'coffa'
require 'webmock/rspec'
RSpec.configure do |config|
# Use color in STDOUT
config.color_enabled = true
# Use color not only in STDOUT but also in pagers and files
config.tty = true
# Use the specified formatter
config.formatter = :documentation # :progress, :html, :textmate
# Rspec 3 forward compatibility
config.treat_symbols_as_metadata_keys_with_true_values = true
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment