Run a bunch of processes (e.g. Python-based web services), and bind an additional server to port 80 that encapsulates a list of "bookmark" urls.
Last active
October 26, 2015 06:20
-
-
Save hx/2f02b8aef9c999297971 to your computer and use it in GitHub Desktop.
Bookmarks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'rubygems' | |
gem 'thin' | |
gem 'foreman' | |
require 'shellwords' | |
require 'pathname' | |
require 'yaml' | |
require 'thin' | |
require 'erb' | |
require 'cgi' | |
class Bookmarks | |
HEIGHT = 30 | |
HTML = <<-EOF | |
<!doctype html> | |
<html> | |
<head> | |
<title><%= render data['title'] %></title> | |
<style> | |
<%= CSS %> | |
</style> | |
</head> | |
<body> | |
<nav> | |
<ul> | |
<% data['links'].each do |name, link| %> | |
<li> | |
<a href="<%= render link %>" target="viewport"><%= render name %></a> | |
</li> | |
<% end %> | |
</ul> | |
</nav> | |
<iframe frameborder="0" name="viewport"/> | |
</body> | |
</html> | |
EOF | |
CSS = <<-EOF | |
* { | |
margin: 0; | |
padding: 0; | |
text-decoration: none; | |
} | |
html, body, iframe, ul, li { | |
height: 100%; | |
} | |
iframe { | |
position: fixed; | |
top: #{HEIGHT}px; | |
left: 0; | |
bottom: 0; | |
width: 100%; | |
border: none; | |
} | |
nav { | |
position: fixed; | |
top: 0; | |
height: #{HEIGHT}px; | |
left: 0; | |
right: 0; | |
background: black; | |
font: 14px/1 "Helvetica Neue", Helvetica, Arial, sans-serif; | |
padding: 0 8px; | |
} | |
li { | |
display: inline-block; | |
} | |
a { | |
color: #aaa; | |
display: block; | |
padding: 8px; | |
} | |
a:hover { | |
background: #222; | |
color: #eee; | |
} | |
EOF | |
def self.run | |
new.run | |
end | |
def run | |
make_data_file | |
if `whoami`.chomp != 'root' | |
escalate | |
elsif ARGV.first == 'server' | |
run_server | |
else | |
run_foreman | |
end | |
end | |
def escalate | |
puts 'Escalating to root; password may be requested.' | |
system 'sudo', '-E', $0, *ARGV | |
end | |
def run_foreman | |
system "echo #{Shellwords.escape procfile_contents} | foreman start -f /dev/stdin" | |
end | |
def procfile_contents | |
{'bookmarks' => "#{File.expand_path __FILE__} server 2>&1"}.merge(data['processes']).map { |line| line.join(':') << "\n" }.join | |
end | |
def make_data_file | |
data_path.write YAML.dump(data) unless data_path.exist? | |
end | |
def data | |
@data ||= data_path.exist? ? YAML.load(data_path.read) : default_data | |
end | |
def data_path | |
@data_path ||= Pathname(__FILE__).parent + 'bookmarks.yml' | |
end | |
def default_data | |
{ | |
'title' => 'Give your bookmarks server a title!', | |
'processes' => { | |
'sample' => 'echo Replace this with something you want to keep running' | |
}, | |
'links' => { | |
'Home' => 'javascript:alert("Put your links here, or numbers for local ports")' | |
} | |
} | |
end | |
def run_server | |
Thin::Logging.logger = Logger.new(STDOUT) | |
Thin::Server.start '0.0.0.0', 80 do | |
run Bookmarks.new | |
end | |
end | |
def render(str) | |
case str | |
when Fixnum | |
render "http://#{host}:#{str}" | |
else | |
CGI.escapeHTML str | |
end | |
end | |
def host | |
@env['SERVER_NAME'] | |
end | |
def body | |
@body ||= ERB.new(HTML).result binding | |
end | |
def call(env) | |
@env = env | |
[200, {'Content-Type' => 'text/html;charset=utf8'}, [body]] | |
end | |
end | |
Bookmarks.run if $0 == __FILE__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment