diff --git a/app/controllers/jobs_controller.rb b/app/controllers/jobs_controller.rb
index c6af6b8..8894b78 100644
--- a/app/controllers/jobs_controller.rb
+++ b/app/controllers/jobs_controller.rb
@@ -1,67 +1,66 @@
class JobsController < ApplicationController
before_action :fetch_host, only: [:new, :edit, :show, :create, :update,
:toggle_enable, :backup_now]
before_action :fetch_job, only: [:show, :edit, :update, :destroy, :toggle_enable, :backup_now]
# GET /jobs
def new
@job = @host.job_templates.new
end
# POST /jobs
def create
@job = @host.job_templates.new(fetch_params)
- @restore_location = params[:job_template][:restore_location]
- if @restore_location && @job.save_and_create_restore_job(@restore_location)
+ if @job.save
redirect_to host_path(@host)
else
render :new
end
end
# GET /jobs/1
def show; end
# GET /jobs/1/edit
def edit;end
# PUT /jobs/1
def update
if @job.update_attributes(fetch_params)
redirect_to host_job_path(@host, @job)
else
render :edit
end
end
# DELETE /jobs/1
def destroy
end
# PATCH /hosts/1/jobs/1/enable
def toggle_enable
@job.enabled = !@job.enabled
@job.save
redirect_to host_path(@host)
end
# POST /hosts/1/jobs/1/backup_now
def backup_now
@job.backup_now
redirect_to client_path(@host.client)
end
private
def fetch_job
@job = @host.job_templates.find(params[:id])
end
def fetch_host
@host = current_user.hosts.find(params[:host_id])
end
def fetch_params
params.require(:job_template).permit(:name, :fileset_id, :schedule_id)
end
end
diff --git a/app/models/job_template.rb b/app/models/job_template.rb
index b3460c4..6b7bbfb 100644
--- a/app/models/job_template.rb
+++ b/app/models/job_template.rb
@@ -1,94 +1,82 @@
class JobTemplate < ActiveRecord::Base
establish_connection Baas::settings[:local_db]
enum job_type: { backup: 0, restore: 1, verify: 2, admin: 3 }
belongs_to :host
belongs_to :fileset
belongs_to :schedule
validates :name, :fileset_id, presence: true
validates :schedule_id, presence: true, unless: :restore?
validates :name, uniqueness: { scope: :host }
before_save :set_job_type
after_save :notify_host
scope :enabled, -> { where(enabled: true) }
# configurable
DEFAULT_OPTIONS = {
storage: :File,
pool: :Default,
messages: :Standard,
priority: 10,
:'Write Bootstrap' => '"/var/lib/bacula/%c.bsr"'
}
def to_bacula_config_array
['Job {'] +
options_array.map { |x| " #{x}" } +
DEFAULT_OPTIONS.map { |k,v| " #{k.capitalize} = #{v}" } +
['}']
end
def priority
DEFAULT_OPTIONS[:priority]
end
def enabled_human
enabled? ? 'yes' : 'no'
end
def schedule_human
schedule.present? ? schedule.name : '-'
end
def name_for_config
"#{host.name} #{name}"
end
# Sends a hot backup request to Bacula via BaculaHandler
def backup_now
return false if not (enabled? && baculized? && backup?)
BaculaHandler.new(host).backup_now(name)
end
- def save_and_create_restore_job(location)
- if save_status = save
- restore_job = JobTemplate.new(
- host: host, job_type: :restore,
- fileset: fileset, name: 'Restore ' + name,
- restore_location: location
- )
- restore_job.save
- end
- save_status
- end
-
private
def notify_host
host.recalculate
end
# Sets the default job_type as backup
def set_job_type
self.job_type = :backup if job_type.nil?
end
def options_array
result = [
"Name = \"#{name_for_config}\"",
"FileSet = \"#{fileset.name_for_config}\"",
"Client = \"#{host.name}\"",
"Type = \"#{job_type.capitalize}\""
]
if restore?
result += ["Where = \"#{restore_location}\""]
else
result += ["Schedule = \"#{schedule.name_for_config}\""]
end
result
end
end
diff --git a/app/views/jobs/_form.html.erb b/app/views/jobs/_form.html.erb
index a07e4b4..c2151fb 100644
--- a/app/views/jobs/_form.html.erb
+++ b/app/views/jobs/_form.html.erb
@@ -1,27 +1,25 @@
<%= bootstrap_form_for(@job, url: @job.new_record? ? host_jobs_path : host_job_path(@host, @job), layout: :horizontal, label_col: 'col-xs-4', control_col: 'col-xs-6') do |f| %>
<%= f.text_field :name %>
<%= select_with_errors_and_button(
@job, :job_template, :fileset_id, 'Fileset',
options_from_collection_for_select(@host.filesets, :id, :name,
params[:fileset_id] || @job.fileset_id),
new_host_fileset_path(@host, job_id: @job.id))
%>
<% if !@job.restore? %>
<%= select_with_errors_and_button(
@job, :job_template, :schedule_id,
'Schedule', options_from_collection_for_select(@host.schedules, :id, :name,
params[:schedule_id] || @job.schedule_id),
new_host_schedule_path(@host, job_id: @job.id))
%>
<% end %>
- <%= f.text_field :restore_location, label: 'Restore Location', placeholder: '/tmp/bacula' %>
-
<% end %>
diff --git a/spec/controllers/jobs_controller_spec.rb b/spec/controllers/jobs_controller_spec.rb
index 7632c50..f31fc08 100644
--- a/spec/controllers/jobs_controller_spec.rb
+++ b/spec/controllers/jobs_controller_spec.rb
@@ -1,76 +1,70 @@
require 'spec_helper'
describe JobsController do
let!(:host) { FactoryGirl.create(:host) }
let(:user) { FactoryGirl.create(:user) }
before do
host.users << user
controller.stub(:current_user) { user }
end
describe 'GET #new' do
before { get :new, host_id: host.id }
it 'initializes a job' do
expect(assigns(:job)).to be
end
it 'renders' do
expect(response).to render_template(:new)
end
end
describe 'POST #create' do
context 'with valid params' do
let(:params) do
{
host_id: host.id,
job_template: FactoryGirl.build(:job_template, restore_location: '/foo').
attributes.symbolize_keys.slice(:name, :schedule_id, :fileset_id, :restore_location)
}
end
- it 'creates the jobs (:backup, :restore)' do
+ it 'creates the backup job' do
expect { post :create, params }.
- to change { JobTemplate.count }.by(2)
+ to change { JobTemplate.count }.by(1)
end
it 'redirects to host' do
post :create, params
expect(response).to redirect_to(host_path(host))
end
-
- it 'calls save_and_create_restore_job' do
- JobTemplate.any_instance.
- should_receive(:save_and_create_restore_job).with('/foo')
- post :create, params
- end
end
context 'with invalid params' do
let(:params) do
{
host_id: host.id,
job_template: FactoryGirl.build(:job_template).attributes.symbolize_keys.
slice(:name, :fileset_id)
}
end
it 'initializes a job with errors' do
post :create, params
expect(assigns(:job)).to be
end
it 'does not create the job' do
expect { post :create, params }.
to_not change { JobTemplate.count }
end
it 'renders :new' do
post :create, params
expect(response).to render_template(:new)
end
end
end
end
diff --git a/spec/models/job_template_spec.rb b/spec/models/job_template_spec.rb
index d2019fe..a183b64 100644
--- a/spec/models/job_template_spec.rb
+++ b/spec/models/job_template_spec.rb
@@ -1,185 +1,156 @@
require 'spec_helper'
describe JobTemplate do
context 'validates' do
it 'name must be present' do
expect(JobTemplate.new).to have(1).errors_on(:name)
end
it 'name must be unique on host\'s scope' do
job_1 = FactoryGirl.create(:job_template, name: 'a name')
job_2 = FactoryGirl.build(:job_template, name: 'a name')
job_3 = FactoryGirl.build(:job_template, name: 'a name', host: job_1.host)
expect(job_2).to be_valid
expect(job_3).to_not be_valid
end
it 'fileset_id must be present' do
expect(JobTemplate.new).to have(1).errors_on(:fileset_id)
end
it 'schedule_id must be present' do
expect(JobTemplate.new).to have(1).errors_on(:schedule_id)
end
it 'schedule_id must NOT be present for :restore jobs' do
expect(JobTemplate.new(job_type: :restore)).to have(0).errors_on(:schedule_id)
end
end
# automatic assignments
context 'when no job_type is given' do
let(:job_template) { FactoryGirl.create(:job_template) }
it 'sets the job_type to :backup' do
expect(job_template).to be_backup
end
end
context 'when enabling a job' do
[:pending, :dispatched].each do |status|
context "of a #{status} host" do
let(:host) { FactoryGirl.create(:host) }
let!(:job) { FactoryGirl.create(:job_template, host: host) }
before { host.update_column(:status, Host::STATUSES[status]) }
it 'becomes configured' do
expect {
job.enabled = true
job.save
}.to change {
host.reload.human_status_name
}.from(status.to_s).to('configured')
end
end
end
context 'of a configured host' do
let(:host) { FactoryGirl.create(:host) }
let!(:job) { FactoryGirl.create(:job_template, host: host) }
before { host.update_column(:status, Host::STATUSES[:configured]) }
it 'stays configured' do
expect {
job.enabled = true
job.save
}.to_not change { host.reload.human_status_name }
end
end
context 'of a updated host' do
let(:host) { FactoryGirl.create(:host) }
let!(:job) { FactoryGirl.create(:job_template, host: host) }
before { host.update_column(:status, Host::STATUSES[:updated]) }
it 'stays updated' do
expect {
job.enabled = true
job.save
}.to_not change { host.reload.human_status_name }
end
end
[:deployed, :redispatched].each do |status|
context "of a #{status} host" do
let(:host) { FactoryGirl.create(:host) }
let!(:job) { FactoryGirl.create(:job_template, host: host) }
before { host.update_column(:status, Host::STATUSES[status]) }
it 'becomes updated' do
expect {
job.enabled = true
job.save
}.to change {
host.reload.human_status_name
}.from(status.to_s).to('updated')
end
end
end
end
describe '#to_bacula_config_array' do
let(:job_template) { FactoryGirl.create(:job_template) }
subject { job_template.to_bacula_config_array }
it 'has a Job structure' do
expect(subject.first).to eq('Job {')
expect(subject.last).to eq('}')
end
JobTemplate::DEFAULT_OPTIONS.each do |k, v|
it "assigns #{k.capitalize} param" do
expect(subject).to include(" #{k.capitalize} = #{v}")
end
end
it 'assigns Name param prefixed with the host\'s name' do
expect(subject).to include(" Name = \"#{job_template.name_for_config}\"")
end
it 'assigns FileSet param' do
expect(subject).to include(" FileSet = \"#{job_template.fileset.name_for_config}\"")
end
it 'assigns Client param' do
expect(subject).to include(" Client = \"#{job_template.host.name}\"")
end
it 'assigns Type param' do
expect(subject).to include(" Type = \"#{job_template.job_type.capitalize}\"")
end
it 'assigns Schedule param' do
expect(subject).to include(" Schedule = \"#{job_template.schedule.name_for_config}\"")
end
context 'for a restore job' do
let(:restore_job) { FactoryGirl.create(:job_template, :restore) }
subject { restore_job.to_bacula_config_array }
it 'does not assign a Schedule param' do
expect(subject).to_not include(" Schedule = \"#{restore_job.schedule.name}\"")
end
it 'assigns Where param' do
expect(subject).to include(" Where = \"#{restore_job.restore_location}\"")
end
end
end
-
- describe '#save_and_create_restore_job' do
- let(:host) { FactoryGirl.create(:host) }
- let(:backup_job_template) do
- FactoryGirl.build(:job_template, job_type: nil, host: host)
- end
-
- it 'calls save' do
- backup_job_template.should_receive(:save)
- backup_job_template.save_and_create_restore_job('/foo')
- end
-
- it 'creates a restore job for the same host' do
- expect { backup_job_template.save_and_create_restore_job('/foo') }.
- to change { host.job_templates.restore.count }.by(1)
- end
-
- it 'creates a restore job for fileset' do
- backup_job_template.save_and_create_restore_job('/foo')
- expect(host.job_templates.restore.pluck(:fileset_id)).
- to eq([backup_job_template.fileset_id])
- end
-
- it 'sets the correct restore location' do
- backup_job_template.save_and_create_restore_job('/foo')
- expect(host.job_templates.restore.pluck(:restore_location)).
- to eq(['/foo'])
- end
- end
end