Commit c2add876 authored by Cool Fire's avatar Cool Fire

Started work on web frontend

parents
{
"daemonize":true,
"host":"localhost",
"max_skew":1,
"user":"guest",
"pass":"rabbitmq_pass",
"channel_commands":"ServerName",
"channel_results":"Results",
"private_keyfile":"config/private.pem",
"encryption_pass":"password_for_private.pem",
"api_url":"http://localhost:3000/api/index"
"api_pass":"some_secret_key"
}
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.4'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring', group: :development
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# RabbitMQ stuff
gem 'bunny', '~> 1.3.1'
# Use unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]
== README
* Ruby version
Designed and tested with Ruby 1.9.3, should work with v2.x also
* System dependencies
RabbitMQ is assumed to be installed.
You should have a openssl public/private keypair generated.
openssl genrsa -des3 -out private.pem 4096
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
* Configuration
config/rabbitmq.conf.example shows the exmaple config for the what the rails app needs to communicate with RabbitMQ
* Database creation
Make sure to configure a database in config/database.yml
* Database initialization
Should be done by Rake
* Services (job queues, cache servers, search engines, etc.)
RabbitMQ should be running.
result_listener should be running.
worker_daemon should be running on the target host.
* Deployment instructions
Run stuff and hope for the best.
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
Rails.application.load_tasks
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
// Place all the styles related to the api controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any styles
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
* file per style scope.
*
*= require_tree .
*= require_self
*/
// Place all the styles related to the commands controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
// Place all the styles related to the jobs controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
// Place all the styles related to the login controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
// Place all the styles related to the servers controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
class ApiController < ApplicationController
def index
end
end
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
class CommandsController < ApplicationController
def new
end
def create
@command = Command.new(command_params)
@command.save
redirect_to @command
end
def show
begin
@command = Command.find(params[:id])
rescue => e
flash[:error] = "No command with that ID."
redirect_to commands_path
end
begin
@commandcount = @command.jobs.size
rescue => e
@commandcount = 0
end
end
private
def command_params
params.require(:new_command).permit(:name, :description, :command, :args)
end
end
class JobsController < ApplicationController
def new
# Check if parameters are set
begin
if params[:server_id]
@server = Server.find(params[:server_id])
else
@server = Server.find(1)
end
rescue => e
flash[:error] = "Need to create a server before you can create a job."
redirect_to new_server_path
return
end
begin
if params[:command_id]
@command = Command.find(params[:command_id])
else
@command = Command.find(1)
end
rescue => e
flash[:error] = "Need to create a command before you can create a job."
redirect_to new_command_path
return
end
@servers = Server.all
@commands = Command.all
end
def create
@job = Job.new()
@job.server_id = params[:server_id][:server_id]
@job.command_id = params[:command_id][:command_id]
@job.args = params[:new_job][:args]
@job.state = 2
@job.result = "Waiting for results"
@job.timestampstarted = DateTime.now
@job.save
# Fire job into rabbitmq
queue_job(@job)
redirect_to @job
end
def show
begin
@job = Job.find(params[:id])
rescue => e
flash[:error] = "No job with that ID."
redirect_to jobs_path
end
end
private
# Function to submit jobs to the queue
def queue_job(job)
# Load configuration
configfile = 'config/rabbitmq.conf'
if(File.exists?(configfile))
configdata = ''
File.open(configfile) do |file|
file.each do |line|
configdata << line
end
end
config = JSON.parse(configdata)
else
raise "Config file '#{configfile}' does not exist."
end
# Read encryption key
private_key = OpenSSL::PKey::RSA.new(File.read(config['private_keyfile']), config['encryption_pass'])
# Establish connection to RabbitMQ
conn = Bunny.new(
:host => config['host'],
:user => config['user'],
:password => config['pass'],
)
conn.start
ch = conn.create_channel
q = ch.queue(job.server.shortname)
# Build message
message = JSON.generate({
:id => job.id,
:timestamp => job.timestampstarted,
:command => job.command.command,
:args => job.args
})
# Encrypt message
if(message.length > 501)
raise "String too long to encrypt."
end
string = private_key.private_encrypt(message)
# Send message to the queue
ch.default_exchange.publish(string, :routing_key => q.name)
conn.close
end
end
class LoginController < ApplicationController
def index
end
end
class ServersController < ApplicationController
def index
@servers = Server.all
end
def new
end
def create
@server = Server.new(server_params)
@server.save
redirect_to @server
end
def show
begin
@server = Server.find(params[:id])
rescue => e
flash[:error] = "No server with that ID."
redirect_to servers_path
end
begin
@jobcount = @server.jobs.size
rescue => e
@jobcount = 0
end
end
private
def server_params
params.require(:new_server).permit(:shortname, :longname, :localip, :wanip, :description)
end
end
class Command < ActiveRecord::Base
has_many :jobs
end
class Job < ActiveRecord::Base
belongs_to :server
belongs_to :command
end
class Server < ActiveRecord::Base
has_many :jobs
end
<h1>Api#index</h1>
<p>Find me in app/views/api/index.html.erb</p>
Commands index.
\ No newline at end of file
<div class='pagetitle'>
New command
</div>
<div class='form'>
<table>
<%= form_for :new_command, url: commands_path do |f| %>
<tr>
<td>
<%= f.label :name, 'Name' %>
</td>
<td>
<%= f.text_field :name %>
</td>
</tr>
<tr>
<td>
<%= f.label :description, 'Description' %>
</td>
<td>
<%= f.text_field :description %>
</td>
</tr>
<tr>
<td>
<%= f.label :command, 'Command' %>
</td>
<td>
<%= f.text_field :command %>
</td>
</tr>
<tr>
<td>
<%= f.label :args, 'Default arguments' %>
</td>
<td>
<%= f.text_field :args %>
</td>
</tr>
<tr>
<td>
<%= f.submit %>
</td>
</tr>
<% end %>
</table>
</div>
\ No newline at end of file
<div class='pagetitle'>
Command: <%= @command.name %>
</div>
<div class='form'>
<table>
<tr>
<td>Name</td>
<td><%= @command.name %></td>
</tr>
<tr>
<td>Description</td>
<td><%= @command.description %></td>
</tr>
<tr>
<td>Command</td>
<td><%= @command.command %></td>
</tr>
<tr>
<td>Default arguments</td>
<td><%= @command.args%></td>
</tr>
</table>
</div>
\ No newline at end of file
Jobs index.
\ No newline at end of file
<div class='pagetitle'>
New job
</div>
<div class='form'>
<table>
<%= form_for :new_job, url: jobs_path do |f| %>
<tr>
<td>
<%= f.label :server_id, 'Server' %>
</td>
<td>
<%= collection_select(:server_id, :server_id, @servers, :id, :shortname) %>
</td>
</tr>
<tr>
<td>
<%= f.label :command_id, 'Command' %>
</td>
<td>
<%= collection_select(:command_id, :command_id, @commands, :id, :name) %>
</td>
</tr>
<tr>
<td>
<%= f.label :args, 'Arguments' %>
</td>
<td>
<%= f.text_field :args %>
</td>
</tr>
<tr>
<td>
<%= f.submit %>
</td>
</tr>
<% end %>
</table>
</div>
\ No newline at end of file
<div class='pagetitle'>
Job: <%= @job.id %>
</div>
<div class='form'>
<table>
<tr>
<td>Id</td>
<td><%= @job.id %></td>
</tr>
<tr>
<td>Server</td>
<td><%= @job.server.shortname %></td>
</tr>
<tr>
<td>Command</td>
<td><%= @job.command.name %></td>
</tr>
<tr>
<td>Arguments</td>
<td><%= @job.args %></td>
</tr>
<tr>
<td>State</td>
<td><%= @job.state %></td>
</tr>
<tr>
<td>Result</td>
<td><%= @job.result %></td>
</tr>
<tr>
<td>Start time</td>
<td><%= DateTime.strptime(@job.timestampstarted.to_s,'%s').strftime('%F %T') %></td>
</tr>
<tr>
<td>End time</td>
<td><%= @job.timestampcompleted ? DateTime.strptime(@job.timestampcompleted.to_s,'%s').strftime('%F %T') : "Not completed yet" %></td>
</tr>
</table>
</div>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Frontend</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<% if flash[:error] %>
<div class='error'>
<%= flash[:error] %>
</div>
<% end %>
<% if flash[:warning] %>
<div class='warning'>
<%= flash[:warning] %>
</div>
<% end %>
<% if flash[:notice] %>
<div class='notice'>
<%= flash[:notice] %>
</div>
<% end %>
<%= yield %>
</body>
</html>
<h1>Login#index</h1>
<p>Find me in app/views/login/index.html.erb</p>
<div class='list'>
<table>
<% @servers.each do |server| %>
<tr>
<td><%= link_to server.shortname, server %></td>
<td><%= link_to 'Edit', edit_server_path(server) %></td>
</tr>
<% end %>
</table>
</div>
\ No newline at end of file
<div class='pagetitle'>
New server
</div>
<div class='form'>
<table>
<%= form_for :new_server, url: servers_path do |f| %>
<tr>
<td>
<%= f.label :shortname, 'Short name' %>
</td>
<td>
<%= f.text_field :shortname %>
</td>
</tr>
<tr>
<td>
<%= f.label :longname, 'Full name (including domain)' %>
</td>
<td>
<%= f.text_field :longname %>
</td>
</tr>
<tr>
<td>
<%= f.label :localip, 'Local IP' %>
</td>
<td>
<%= f.text_field :localip %>
</td>
</tr>
<tr>
<td>
<%= f.label :wanip, 'WAN IP' %>
</td>
<td>
<%= f.text_field :wanip %>
</td>
</tr>
<tr>
<td>
<%= f.label :description, 'Server description' %>
</td>
<td>
<%= f.text_field :description %>
</td>
</tr>
<tr>
<td>
<%= f.submit %>
</td>
</tr>
<% end %>
</table>
</div>
\ No newline at end of file