diff --git a/app/controllers/filesets_controller.rb b/app/controllers/filesets_controller.rb index 0c4f248..a65b7f9 100644 --- a/app/controllers/filesets_controller.rb +++ b/app/controllers/filesets_controller.rb @@ -1,33 +1,35 @@ class FilesetsController < ApplicationController before_action :fetch_host, only: [:new, :create] def new @fileset = @host.filesets.new end def show end def create @fileset = @host.filesets.new(fetch_params) if @fileset.save redirect_to host_path(@host) else + @fileset.include_files = nil + @fileset.exclude_directions = nil render :new end end def destroy end private def fetch_host @host = Host.find(params[:host_id]) end def fetch_params params.require(:fileset).permit(:name, exclude_directions: [], include_files: []) end end diff --git a/app/models/fileset.rb b/app/models/fileset.rb index 6029796..d4da768 100644 --- a/app/models/fileset.rb +++ b/app/models/fileset.rb @@ -1,75 +1,89 @@ class Fileset < ActiveRecord::Base establish_connection Baas::settings[:local_db] serialize :exclude_directions serialize :include_directions, JSON attr_accessor :include_files belongs_to :host has_many :job_templates + validates :name, presence: true, uniqueness: { scope: :host } + validate :has_included_files, on: :create + before_save :sanitize_exclude_directions, :sanitize_include_directions DEFAULT_EXCLUDED = %w{/var/lib/bacula /proc /tmp /.journal /.fsck /bacula} DEFAULT_INCLUDE_OPTIONS = { signature: :SHA1, compression: :GZIP } DEFAULT_INCLUDE_FILE_LIST = ['/'] def to_bacula_config_array ['FileSet {'] + - [" Name = \"#{name}\""] + + [" Name = \"#{name_for_config}\""] + include_directions_to_config_array + exclude_directions_to_config_array + ['}'] end private + def name_for_config + [host.name, name].join(' ') + end + + def has_included_files + if include_files.blank? || include_files.all?(&:blank?) + errors.add(:include_files, :cant_be_blank) + end + end + def sanitize_include_directions - return false if include_files.blank? + files = include_files.compact.uniq.keep_if(&:present?) + return false if files.blank? - self.include_directions = { options: DEFAULT_INCLUDE_OPTIONS, file: include_files } + self.include_directions = { options: DEFAULT_INCLUDE_OPTIONS, file: files } end def sanitize_exclude_directions - self.exclude_directions = exclude_directions.keep_if(&:present?).uniq rescue [] + self.exclude_directions = exclude_directions.keep_if(&:present?).uniq rescue nil end def exclude_directions_to_config_array return [] if exclude_directions.empty? [' Exclude {'] + exclude_directions.map { |x| " File = \"#{x}\"" } + [' }'] end def include_directions_to_config_array return [] if include_directions.blank? [" Include {"] + included_options + included_files + [' }'] end def included_options formatted = [" Options {"] options = include_directions.deep_symbolize_keys[:options]. reverse_merge(DEFAULT_INCLUDE_OPTIONS) options.each do |k,v| if not [:wildfile].include? k formatted << " #{k} = #{v}" else formatted << v.map { |f| " #{k} = \"#{f}\"" } end end formatted << " }" formatted end def included_files include_directions['file'].map { |f| " File = #{f}" } end def included_wildfile include_directions['wildfile'].map { |f| " wildfile = \"#{f}\"" }.join("\n") end end diff --git a/app/views/filesets/_form.html.erb b/app/views/filesets/_form.html.erb index bd2a384..8309239 100644 --- a/app/views/filesets/_form.html.erb +++ b/app/views/filesets/_form.html.erb @@ -1,29 +1,17 @@ <%= bootstrap_form_for(@fileset, url: host_filesets_path(@host, @fileset), layout: :horizontal, label_col: 'col-xs-3', control_col: 'col-xs-8') do |f| %> - <% if @fileset.errors.any? %> -
-

<%= pluralize(@fileset.errors.count, "error") %> prohibited this fileset from being saved:

- - -
- <% end %> -
<%= f.text_field :name %> <%= f.text_field :include_files, label: 'Files', placeholder: '/', multiple: true %> <%= f.text_field :include_files, label: 'Files', placeholder: '/media', multiple: true %> <%= f.text_field :exclude_directions, label: 'Exclude', placeholder: '/proc', multiple: true %> <%= f.text_field :exclude_directions, label: 'Exclude', placeholder: '/bacula', multiple: true %>
<%= f.submit class: 'btn btn-success' %>
<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 8305a70..a209adc 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,31 +1,35 @@ # Files in the config/locales directory are used for internationalization # and are automatically loaded by Rails. If you want to use locales other # than English, add the necessary files in this directory. # # To use the locales, use `I18n.t`: # # I18n.t 'hello' # # In views, this is aliased to just `t`: # # <%= t('hello') %> # # To use a different locale, set it with `I18n.locale`: # # I18n.locale = :es # # This would use the information in config/locales/es.yml. # # To learn more, please read the Rails Internationalization guide # available at http://guides.rubyonrails.org/i18n.html. en: hello: "Hello world" activerecord: errors: models: schedule: attributes: runtime: not_valid_24h_time: 'Not a valid time format, use HH:MM' + fileset: + attributes: + :include_files: + cant_be_blank: "can't be blank" diff --git a/spec/models/fileset_spec.rb b/spec/models/fileset_spec.rb index ab56e17..cecc3d3 100644 --- a/spec/models/fileset_spec.rb +++ b/spec/models/fileset_spec.rb @@ -1,40 +1,56 @@ require 'spec_helper' describe Fileset do describe '#to_bacula_config_array' do let(:fileset) do FactoryGirl.create(:fileset, name: 'Test Fileset', exclude_directions: Fileset::DEFAULT_EXCLUDED, include_directions: { options: Fileset::DEFAULT_INCLUDE_OPTIONS, file: Fileset::DEFAULT_INCLUDE_FILE_LIST } ) end subject { fileset.to_bacula_config_array } it 'is a Fileset type resource' do expect(subject.first).to eq('FileSet {') expect(subject.last).to eq('}') end it 'contains the name' do - expect(subject).to include(" Name = \"#{fileset.name}\"") + name_for_config = [fileset.host.name, fileset.name].join(' ') + expect(subject).to include(" Name = \"#{name_for_config}\"") end end context 'when duplicate exclude_directions are given' do let(:fileset) { FactoryGirl.create(:fileset, exclude_directions: [:foo, :foo, :bar]) } it 'keeps its exclude_directions uniq' do expect(fileset.exclude_directions).to eq([:foo, :bar]) end end context 'when exclude_directions are given' do let(:fileset) { FactoryGirl.create(:fileset, exclude_directions: [:foo, :foo, :bar, '']) } it 'rejects them' do expect(fileset.exclude_directions).to eq([:foo, :bar]) end end + + context 'when no include_files are given' do + let(:fileset) { FactoryGirl.build(:fileset, include_files: []) } + + it 'does not save the fileset' do + expect(fileset).to have(1).errors_on(:include_files) + end + end + + context 'when blank include_files are given' do + let(:fileset) { FactoryGirl.create(:fileset, include_files: [:foo, '']) } + it 'rejects them' do + expect(fileset.include_directions['file']).to eq(['foo']) + end + end end