181 lines
4.0 KiB
Ruby
181 lines
4.0 KiB
Ruby
require 'oj'
|
|
require 'httparty'
|
|
require 'pry'
|
|
require 'erb'
|
|
require 'time'
|
|
require 'sinatra/base'
|
|
require 'sinatra/cross_origin'
|
|
|
|
class CraneOp < Sinatra::Base
|
|
register Sinatra::CrossOrigin
|
|
|
|
configure do
|
|
enable :cross_origin
|
|
mime_type :javascript, 'application/javascript'
|
|
mime_type :javascript, 'text/javascript'
|
|
set :logging, true
|
|
set :static, true
|
|
set :allow_origin, :any
|
|
set :allow_methods, [:get, :post, :options]
|
|
set :allow_credentials, true
|
|
set :max_age, "1728000"
|
|
set :expose_headers, ['Content-Type']
|
|
set :json_encoder, :to_json
|
|
end
|
|
|
|
## Setup ##
|
|
|
|
def registry_host
|
|
ENV['REGISTRY_HOST'] || 'localhost'
|
|
end
|
|
|
|
def registry_port
|
|
ENV['REGISTRY_PORT'] || '5000'
|
|
end
|
|
|
|
def registry_proto
|
|
ENV['REGISTRY_PROTO'] || 'https'
|
|
end
|
|
|
|
def registry_ssl_verify
|
|
ENV['REGISTRY_SSL_VERIFY'] || 'true'
|
|
end
|
|
|
|
def registry_public_url
|
|
ENV['REGISTRY_PUBLIC_URL'] || "#{registry_host}:#{registry_port}"
|
|
end
|
|
|
|
def registry_username
|
|
ENV['REGISTRY_USERNAME']
|
|
end
|
|
|
|
def registry_password
|
|
ENV['REGISTRY_PASSWORD']
|
|
end
|
|
|
|
## Authentication ##
|
|
|
|
if ENV['USERNAME']
|
|
use Rack::Auth::Basic, "Please Authenticate to View" do |username, password|
|
|
username == ENV['USERNAME'] and password == ( ENV['PASSWORD'] || '' )
|
|
end
|
|
end
|
|
|
|
## Helpers ##
|
|
|
|
def to_bool(str)
|
|
str.downcase == 'true'
|
|
end
|
|
|
|
def html(view)
|
|
File.read(File.join('public', "#{view.to_s}.html"))
|
|
end
|
|
|
|
def sort_versions(ary)
|
|
valid_version_numbers = ary.select { |i| i if i.match(/(0-9|\.|\-)/)}
|
|
non_valid_version_numbers = ary - valid_version_numbers
|
|
(valid_version_numbers.sort_by {|v| Gem::Version.new( v ) } + non_valid_version_numbers)
|
|
end
|
|
|
|
def registry_url
|
|
url_parts = []
|
|
|
|
url_parts << registry_proto
|
|
url_parts << "://"
|
|
if registry_username
|
|
url_parts << "#{registry_username}:#{registry_password}@"
|
|
end
|
|
url_parts << registry_host
|
|
url_parts << ":"
|
|
url_parts << registry_port
|
|
|
|
url_parts.join
|
|
end
|
|
|
|
## Registry API Methods ##
|
|
|
|
def containers
|
|
response = HTTParty.get( "#{registry_url}/v2/_catalog", verify: to_bool(registry_ssl_verify) )
|
|
json = Oj.load response.body
|
|
json['repositories']
|
|
end
|
|
|
|
def container_tags(repo)
|
|
response = HTTParty.get( "#{registry_url}/v2/#{repo}/tags/list", verify: to_bool(registry_ssl_verify) )
|
|
json = Oj.load response.body
|
|
tags = json['tags'] || []
|
|
tags = sort_versions(tags).reverse
|
|
end
|
|
|
|
def container_info(repo, manifest)
|
|
response = HTTParty.get( "#{registry_url}/v2/#{repo}/manifests/#{manifest}", verify: to_bool(registry_ssl_verify) )
|
|
json = Oj.load response.body
|
|
|
|
# Add extra fields for easy display
|
|
json['information'] = Oj.load(json['history'].first['v1Compatibility'])
|
|
|
|
created_at = Time.parse(json['information']['created'])
|
|
json['information']['created_formatted'] = created_at.to_s
|
|
json['information']['created_millis'] = (created_at.to_f * 1000).to_i
|
|
return json
|
|
end
|
|
|
|
## Endpoints ##
|
|
|
|
get '/' do
|
|
html :index
|
|
end
|
|
|
|
get '/containers.json' do
|
|
content_type :json
|
|
|
|
containers.to_json
|
|
end
|
|
|
|
get '/container/*/tags.json' do |container|
|
|
content_type :json
|
|
|
|
tags = container_tags(container)
|
|
halt 404 if tags.nil?
|
|
tags.to_json
|
|
end
|
|
|
|
get /container\/(.*\/)(.*.json)/ do |container, tag|
|
|
|
|
# This is here because we need to handle slashes in container names
|
|
container.chop!
|
|
tag.gsub!('.json', '')
|
|
|
|
content_type :json
|
|
|
|
info = container_info(container, tag)
|
|
|
|
halt 404 if info['errors']
|
|
halt 404 if info['fsLayers'].nil?
|
|
|
|
info.to_json
|
|
end
|
|
|
|
get '/registryinfo' do
|
|
content_type :json
|
|
{
|
|
host: registry_host,
|
|
public_url: registry_public_url,
|
|
port: registry_port,
|
|
protocol: registry_proto,
|
|
ssl_verify: registry_ssl_verify
|
|
}.to_json
|
|
end
|
|
|
|
# Error Handlers
|
|
error do
|
|
File.read(File.join('public', '500.html'))
|
|
end
|
|
|
|
not_found do
|
|
status 404
|
|
File.read(File.join('public', '404.html'))
|
|
end
|
|
|
|
end
|