diff --git a/Gemfile b/Gemfile index 19ceae4ce331..d4a5634a9671 100644 --- a/Gemfile +++ b/Gemfile @@ -4,29 +4,28 @@ require File.expand_path('../lib/regexp_extensions', FOREMAN_GEMFILE) source 'https://rubygems.org' -gem 'rails', '3.2.22' -gem 'rack-cache', '< 1.3.0' +gem 'rails', '4.1.5' gem 'json', '~> 1.5' gem 'rest-client', '~> 1.6.0', :require => 'rest_client' -gem 'audited-activerecord', '3.0.0' +gem 'audited-activerecord', '~> 4.0' gem 'will_paginate', '~> 3.0' gem 'ancestry', '~> 2.0' -gem 'scoped_search', '~> 3.0' +gem 'scoped_search', '>= 3.2.2', '< 4' gem 'ldap_fluff', '>= 0.3.5', '< 1.0' gem 'net-ldap', '>= 0.8.0' -gem 'apipie-rails', '~> 0.2.5' +gem 'apipie-rails', '~> 0.3.4' gem 'rabl', '~> 0.11' gem 'oauth', '~> 0.4' gem 'deep_cloneable', '~> 2.0' gem 'foreigner', '~> 1.4' gem 'validates_lengths_from_database', '~> 0.2' -gem 'friendly_id', '~> 4.0' +gem 'friendly_id', '~> 5.0' gem 'secure_headers', '~> 1.3' gem 'safemode', '~> 1.2' gem 'fast_gettext', '~> 0.8' gem 'gettext_i18n_rails', '~> 1.0' gem 'i18n', '~> 0.6.4' -gem 'rails-i18n', '~> 3.0.0' +gem 'rails-i18n', '~> 4.0.0' gem 'turbolinks', '~> 2.5' gem 'logging', '>= 1.8.0', '< 3.0.0' gem 'fog-core', '1.34.0' @@ -36,6 +35,9 @@ if RUBY_VERSION.start_with? '1.9.' else gem 'net-ssh' end +gem 'activerecord-session_store', '~> 0.1.1' +gem 'rails-observers', '~> 0.1' +gem 'protected_attributes', '~> 1.1.1' Dir["#{File.dirname(FOREMAN_GEMFILE)}/bundler.d/*.rb"].each do |bundle| self.instance_eval(Bundler.read_file(bundle)) diff --git a/app/assets/javascripts/topbar.js b/app/assets/javascripts/topbar.js index 4499eb3ad4a0..dc85785638b2 100644 --- a/app/assets/javascripts/topbar.js +++ b/app/assets/javascripts/topbar.js @@ -50,7 +50,7 @@ $(document).on('mouseleave','.loc-submenu', function(){ function mark_active_menu() { var menus = $('.menu_tab_dropdown'), path = window.location.pathname + window.location.search, - link = $("[href='%s'".replace('%s', path)); + link = $("[href='%s']".replace('%s', path)); menus.removeClass('active'); $("[class^='menu_tab_']").removeClass('active'); diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index eaa8fa59e201..5165a6a21566 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -36,7 +36,7 @@ def destroy param :id, :identifier, :required => true def last - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + conditions = { :host_id => Host.authorized(:view_hosts).friendly.find(params[:host_id]).try(:id) } if params[:host_id].present? max_id = resource_scope.where(conditions).maximum(:id) @report = resource_scope.includes(:logs => [:message, :source]).find(max_id) render :show diff --git a/app/controllers/api/v2/config_reports_controller.rb b/app/controllers/api/v2/config_reports_controller.rb index 46e4c8f7508a..1da7141d6737 100644 --- a/app/controllers/api/v2/config_reports_controller.rb +++ b/app/controllers/api/v2/config_reports_controller.rb @@ -54,7 +54,9 @@ def destroy param :id, :identifier, :required => true def last - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + if params[:host_id].present? + conditions = { :host_id => resource_finder(Host.authorized(:view_hosts), params[:host_id]).try(:id) } + end max_id = resource_scope.where(conditions).maximum(:id) @config_report = resource_scope.includes(:logs => [:message, :source]).find(max_id) render :show diff --git a/app/controllers/api/v2/host_classes_controller.rb b/app/controllers/api/v2/host_classes_controller.rb index 28c4b82bcad8..ff8dcdf38a11 100644 --- a/app/controllers/api/v2/host_classes_controller.rb +++ b/app/controllers/api/v2/host_classes_controller.rb @@ -35,8 +35,10 @@ def destroy # overwrite resource_name so it's host and and not host_class, since we want to return @host def find_host not_found and return false if params[:host_id].blank? - @host = Host.find(params[:host_id]) if Host::Managed.respond_to?(:authorized) && - Host::Managed.authorized("view_host", Host::Managed) + if Host::Managed.respond_to?(:authorized) && + Host::Managed.authorized("view_host", Host::Managed) + @host = resource_finder(Host.authorized(:view_hosts), params[:host_id]) + end end end end diff --git a/app/controllers/api/v2/models_controller.rb b/app/controllers/api/v2/models_controller.rb index 9554fe389592..1a288ab6e3b4 100644 --- a/app/controllers/api/v2/models_controller.rb +++ b/app/controllers/api/v2/models_controller.rb @@ -47,6 +47,12 @@ def update def destroy process_response @model.destroy end + + private + + def find_resource + @model = Model.friendly.find(params[:id]) || super + end end end end diff --git a/app/controllers/api/v2/parameters_controller.rb b/app/controllers/api/v2/parameters_controller.rb index 0d3f536396b1..fd0ebae7b489 100644 --- a/app/controllers/api/v2/parameters_controller.rb +++ b/app/controllers/api/v2/parameters_controller.rb @@ -165,8 +165,9 @@ def allowed_nested_id def find_parameter # nested_obj is required, so no need to check here @parameters = nested_obj.send(parameters_method) - @parameter = @parameters.find(params[:id]) - return @parameter if @parameter + @parameter = @parameters.from_param(params[:id]) + @parameter ||= @parameters.friendly.find(params[:id]) + return @parameter if @parameter.present? not_found end end diff --git a/app/controllers/api/v2/reports_controller.rb b/app/controllers/api/v2/reports_controller.rb index b432de0b0fde..ca5006c20cb3 100644 --- a/app/controllers/api/v2/reports_controller.rb +++ b/app/controllers/api/v2/reports_controller.rb @@ -54,7 +54,7 @@ def destroy param :id, :identifier, :required => true def last - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + conditions = { :host_id => resource_finder(Host.authorized(:view_hosts), params[:host_id]).try(:id) } if params[:host_id].present? max_id = resource_scope.where(conditions).maximum(:id) @report = resource_scope.includes(:logs => [:message, :source]).find(max_id) render :show diff --git a/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb b/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb index 009eef9d15ff..5e76e13f01e5 100644 --- a/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb +++ b/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb @@ -19,22 +19,6 @@ module Api::V2::LookupKeysCommonController before_filter :return_if_smart_mismatch, :only => [:show, :update, :destroy] end - def puppetclass_id? - params.keys.include?('puppetclass_id') - end - - def environment_id? - params.keys.include?('environment_id') - end - - def host_id? - params.keys.include?('host_id') - end - - def hostgroup_id? - params.keys.include?('hostgroup_id') - end - def smart_variable_id? params.keys.include?('smart_variable_id') || controller_name.match(/smart_variables/) end @@ -43,28 +27,22 @@ def smart_class_parameter_id? params.keys.include?('smart_class_parameter_id') || controller_name.match(/smart_class_parameters/) end - def find_puppetclass - @puppetclass = Puppetclass.authorized(:view_puppetclasses).find(params['puppetclass_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Puppet class with id '%{id}' was not found") % { :id => params['puppetclass_id'] }) } }) - end + [Puppetclass, Environment, Host::Base, Hostgroup].each do |model| + model_string = model.to_s.split('::').first.downcase - def find_environment - @environment = Environment.authorized(:view_environments).find(params['environment_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Environment with id '%{id}' was not found") % { :id => params['environment_id'] }) } }) - end - - def find_host - @host = Host::Base.authorized(:view_hosts).find(params['host_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Host with id '%{id}' was not found") % { :id => params['host_id'] }) } }) - end + define_method("#{model_string}_id?") do + params.keys.include?("#{model_string}_id") + end - def find_hostgroup - @hostgroup = Hostgroup.authorized(:view_hostgroups).find(params['hostgroup_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Hostgroup with id '%{id}' was not found") % { :id => params['hostgroup_id'] }) } }) + define_method("find_#{model_string}") do + scope = model.authorized(:"view_#{model_string.pluralize}") + begin + instance_variable_set("@#{model_string}", + resource_finder(scope, params["#{model_string}_id"])) + rescue ActiveRecord::RecordNotFound + model_not_found(model_string) + end + end end def find_smart_variable @@ -144,4 +122,13 @@ def return_if_smart_mismatch not_found "#{obj} not found by id '#{id}'" end end + + private + + def model_not_found(model) + error_message = ( + _("%{model} with id '%{id}' was not found") % + { :id => params["#{model}_id"], :model => model.capitalize } ) + not_found(:error => { :message => error_message } ) + end end diff --git a/app/controllers/concerns/find_common.rb b/app/controllers/concerns/find_common.rb index 5d8a5a30edd9..a037251e7627 100644 --- a/app/controllers/concerns/find_common.rb +++ b/app/controllers/concerns/find_common.rb @@ -1,12 +1,18 @@ -# this mixin is used by both ApplicationController and Api::BaseController -# searches for an object based on its id, name, label, etc and assign it to an instance variable +# This mixin is used by both ApplicationController and Api::BaseController +# Searches for an object based on its id, name, label, etc and assign it to an instance variable # friendly_id performs the logic if params[:id] is 'id' or 'id-name' or 'name' module FindCommon - # example: @host = Host.find(params[:id]) def find_resource - not_found and return if params[:id].blank? - instance_variable_set("@#{resource_name}", resource_scope.find(params[:id])) + instance_variable_set("@#{resource_name}", + resource_finder(resource_scope, params[:id])) + end + + def resource_finder(scope, id) + raise ActiveRecord::RecordNotFound if scope.empty? + result = scope.from_param(id) if scope.respond_to?(:from_param) + result ||= scope.friendly.find(id) if scope.respond_to?(:friendly) + result || scope.find(id) end def resource_name(resource = controller_name) diff --git a/app/controllers/config_reports_controller.rb b/app/controllers/config_reports_controller.rb index 436cf0b9a850..8b404ca971d8 100644 --- a/app/controllers/config_reports_controller.rb +++ b/app/controllers/config_reports_controller.rb @@ -10,7 +10,7 @@ def index def show # are we searching for the last report? if params[:id] == "last" - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + conditions = { :host_id => resource_finder(Host.authorized(:view_hosts), params[:host_id]).try(:id) } if params[:host_id].present? params[:id] = resource_base.where(conditions).maximum(:id) end diff --git a/app/controllers/hosts_controller.rb b/app/controllers/hosts_controller.rb index aeca21fc36ea..e4e1f07dcca0 100644 --- a/app/controllers/hosts_controller.rb +++ b/app/controllers/hosts_controller.rb @@ -169,7 +169,7 @@ def puppetclass_parameters def externalNodes certname = params[:name] @host ||= resource_base.find_by_certname certname - @host ||= resource_base.find certname + @host ||= resource_base.friendly.find certname not_found and return unless @host begin @@ -352,7 +352,7 @@ def update_multiple_parameters skipped = [] params[:name].each do |name, value| next if value.empty? - if (host_param = host.host_parameters.find(name)) + if (host_param = host.host_parameters.friendly.find(name)) counter += 1 if host_param.update_attribute(:value, value) else skipped << name @@ -698,7 +698,7 @@ def taxonomy_scope # overwrite application_controller def find_resource not_found and return false if (id = params[:id]).blank? - @host = resource_base.find(id) + @host = resource_base.friendly.find(id) @host ||= resource_base.find_by_mac params[:host][:mac] if params[:host] && params[:host][:mac] not_found and return(false) unless @host diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index ef4133685ef5..57d7bd6686ed 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -13,7 +13,7 @@ def index end def update - @setting = Setting.find(params[:id]) + @setting = Setting.friendly.find(params[:id]) if @setting.parse_string_value(params[:setting][:value]) && @setting.save render :json => @setting else diff --git a/app/controllers/unattended_controller.rb b/app/controllers/unattended_controller.rb index 0678436c17f2..4d14e53198c1 100644 --- a/app/controllers/unattended_controller.rb +++ b/app/controllers/unattended_controller.rb @@ -44,8 +44,8 @@ def built def template return head(:not_found) unless (params.has_key?("id") and params.has_key?(:hostgroup)) - template = ProvisioningTemplate.find(params['id']) - @host = Hostgroup.find(params['hostgroup']) + template = ProvisioningTemplate.find_by_name(params['id']) + @host = Hostgroup.find_by_name(params['hostgroup']) return head(:not_found) unless template and @host @@ -107,7 +107,7 @@ def get_host_details def find_host_by_spoof host = Nic::Base.primary.find_by_ip(params.delete('spoof')).try(:host) if params['spoof'].present? - host ||= Host.find(params.delete('hostname')) if params['hostname'].present? + host ||= Host.find_by_name(params.delete('hostname')) if params['hostname'].present? @spoof = host.present? host end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b29f756a73d2..887d3fb1d8f6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -32,6 +32,14 @@ def link_to(*args, &block) end end + def link_to_function(name, function, html_options = {}) + onclick_tag = "#{html_options[:onclick]}; " if html_options[:onclick] + onclick = "#{onclick_tag}#{function}; return false;" + href = html_options[:href] || '#' + + content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick)) + end + protected def contract(model) diff --git a/app/models/bookmark.rb b/app/models/bookmark.rb index ffed9d221d6c..1cccd037abde 100644 --- a/app/models/bookmark.rb +++ b/app/models/bookmark.rb @@ -7,7 +7,7 @@ class Bookmark < ActiveRecord::Base validates_lengths_from_database belongs_to :owner, :polymorphic => true - attr_accessible :name, :controller, :query, :public + attr_accessible :name, :query, :public, :controller audited :allow_mass_assignment => true validates :name, :uniqueness => {:scope => :controller}, :unless => Proc.new{|b| Bookmark.my_bookmarks.where(:name => b.name).empty?} diff --git a/app/models/compute_profile.rb b/app/models/compute_profile.rb index d30cc211f1ee..20864e463d8d 100644 --- a/app/models/compute_profile.rb +++ b/app/models/compute_profile.rb @@ -6,6 +6,7 @@ class ComputeProfile < ActiveRecord::Base validates_lengths_from_database attr_accessible :name + audited has_associated_audits diff --git a/app/models/concerns/audit_extensions.rb b/app/models/concerns/audit_extensions.rb index a1ec3226f7ab..aef24f0a0232 100644 --- a/app/models/concerns/audit_extensions.rb +++ b/app/models/concerns/audit_extensions.rb @@ -5,7 +5,8 @@ module AuditExtensions included do belongs_to :user, :class_name => 'User' belongs_to :search_users, :class_name => 'User', :foreign_key => :user_id - belongs_to :search_hosts, :class_name => 'Host', :foreign_key => :auditable_id, :conditions => { :audits => { :auditable_type => 'Host' } } + belongs_to :search_hosts, -> { where(:audits => { :auditable_type => 'Host' }) }, + :class_name => 'Host', :foreign_key => :auditable_id belongs_to :search_hostgroups, :class_name => 'Hostgroup', :foreign_key => :auditable_id belongs_to :search_parameters, :class_name => 'Parameter', :foreign_key => :auditable_id belongs_to :search_templates, :class_name => 'ProvisioningTemplate', :foreign_key => :auditable_id diff --git a/app/models/concerns/has_many_common.rb b/app/models/concerns/has_many_common.rb index 9b013d829cb3..2fc55e62907e 100644 --- a/app/models/concerns/has_many_common.rb +++ b/app/models/concerns/has_many_common.rb @@ -41,8 +41,9 @@ class << self; self end end #### has_many #### - def has_many(association, options = {}) - has_many_names_for(association, options) + def has_many(*args) + options = args.last.is_a?(Hash) ? args.last : {} + has_many_names_for(args.first, options) super end @@ -69,8 +70,9 @@ def has_many_names_for(association, options) end #### belongs_to #### - def belongs_to(association, options = {}) - belongs_to_name_for(association, options) + def belongs_to(*args) + options = args.last.is_a?(Hash) ? args.last : {} + belongs_to_name_for(args.first, options) super end diff --git a/app/models/concerns/host_common.rb b/app/models/concerns/host_common.rb index 69d9b606ec5a..c7fadfeb5851 100644 --- a/app/models/concerns/host_common.rb +++ b/app/models/concerns/host_common.rb @@ -209,7 +209,7 @@ def individual_puppetclasses end def available_puppetclasses - return Puppetclass.where(nil) if environment_id.blank? + return Puppetclass.where(nil) if environment.blank? environment.puppetclasses - parent_classes end diff --git a/app/models/concerns/host_params.rb b/app/models/concerns/host_params.rb index ff3f685bea2d..37c0afedab40 100644 --- a/app/models/concerns/host_params.rb +++ b/app/models/concerns/host_params.rb @@ -7,6 +7,7 @@ module HostParams accepts_nested_attributes_for :host_parameters, :allow_destroy => true include ParameterValidators attr_reader :cached_host_params + attr_accessible :host_parameters_attributes def params host_params.update(lookup_keys_params) @@ -58,7 +59,7 @@ def host_inherited_params_objects def host_params_objects # Host parameters should always be first for the uniq order - (host_parameters + host_inherited_params_objects.reverse!).uniq {|param| param.name} + (host_parameters + host_inherited_params_objects.to_a.reverse!).uniq {|param| param.name} end end end diff --git a/app/models/concerns/parameterizable.rb b/app/models/concerns/parameterizable.rb index 4a0c63e36487..0fb27066e476 100644 --- a/app/models/concerns/parameterizable.rb +++ b/app/models/concerns/parameterizable.rb @@ -12,7 +12,7 @@ def to_param end def self.from_param(id) - self.find(id.to_i) + self.find_by_id(id.to_i) end end end @@ -27,7 +27,7 @@ def to_param end def self.from_param(id_name) - self.find(id_name.to_i) + self.find_by_id(id_name.to_i) end end end diff --git a/app/models/concerns/taxonomix.rb b/app/models/concerns/taxonomix.rb index 45019c254cd2..75f116a14c67 100644 --- a/app/models/concerns/taxonomix.rb +++ b/app/models/concerns/taxonomix.rb @@ -3,12 +3,14 @@ module Taxonomix include DirtyAssociations included do - taxonomy_join_table = "taxable_taxonomies" - has_many taxonomy_join_table, :dependent => :destroy, :as => :taxable - has_many :locations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Location'", :validate => false - has_many :organizations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Organization'", :validate => false + taxonomy_join_table = :taxable_taxonomies + has_many taxonomy_join_table.to_sym, :dependent => :destroy, :as => :taxable + has_many :locations, -> { where(:type => 'Location') }, + :through => taxonomy_join_table, :source => :taxonomy, + :validate => false + has_many :organizations, -> { where(:type => 'Organization') }, + :through => taxonomy_join_table, :source => :taxonomy, + :validate => false after_initialize :set_current_taxonomy scoped_search :in => :locations, :on => :name, :rename => :location, :complete_value => true diff --git a/app/models/config_group_class.rb b/app/models/config_group_class.rb index 904d58fd4a4f..2e22eb5f9b37 100644 --- a/app/models/config_group_class.rb +++ b/app/models/config_group_class.rb @@ -9,7 +9,7 @@ class ConfigGroupClass < ActiveRecord::Base belongs_to :puppetclass belongs_to :config_group, :counter_cache => true - validates :puppetclass_id, :presence => true - validates :config_group_id, :presence => true, - :uniqueness => {:scope => :puppetclass_id} + validates :puppetclass, :presence => true + validates :config_group, :presence => true, + :uniqueness => {:scope => :puppetclass} end diff --git a/app/models/domain.rb b/app/models/domain.rb index be367e0c178c..2ea9fa2cb0ef 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -21,7 +21,7 @@ class Domain < ActiveRecord::Base has_many :domain_parameters, :dependent => :destroy, :foreign_key => :reference_id, :inverse_of => :domain has_many :parameters, :dependent => :destroy, :foreign_key => :reference_id, :class_name => "DomainParameter" has_many :interfaces, :class_name => 'Nic::Base' - has_many :primary_interfaces, :class_name => 'Nic::Base', :conditions => { :primary => true } + has_many :primary_interfaces, -> { where(:primary => true) }, :class_name => 'Nic::Base' has_many :hosts, :through => :interfaces has_many :primary_hosts, :through => :primary_interfaces, :source => :host diff --git a/app/models/environment.rb b/app/models/environment.rb index fdf3007b88af..045abe5c05a7 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -11,12 +11,12 @@ class Environment < ActiveRecord::Base before_destroy EnsureNotUsedBy.new(:hosts, :hostgroups) has_many :environment_classes, :dependent => :destroy - has_many :puppetclasses, :through => :environment_classes, :uniq => true + has_many :puppetclasses, -> { uniq }, :through => :environment_classes has_many_hosts has_many :hostgroups - has_many :trends, :as => :trendable, :class_name => "ForemanTrend" validates :name, :uniqueness => true, :presence => true, :alphanumeric => true + has_many :trends, :as => :trendable, :class_name => "ForemanTrend" has_many :template_combinations, :dependent => :destroy has_many :provisioning_templates, :through => :template_combinations diff --git a/app/models/host/base.rb b/app/models/host/base.rb index 41d3c1a2d8df..9b41c504f9fd 100644 --- a/app/models/host/base.rb +++ b/app/models/host/base.rb @@ -39,12 +39,10 @@ class Base < ActiveRecord::Base belongs_to :model, :counter_cache => :hosts_count has_many :fact_values, :dependent => :destroy, :foreign_key => :host_id has_many :fact_names, :through => :fact_values - has_many :interfaces, :dependent => :destroy, :inverse_of => :host, :class_name => 'Nic::Base', - :foreign_key => :host_id, :order => 'identifier' - has_one :primary_interface, :class_name => 'Nic::Base', :foreign_key => 'host_id', - :conditions => { :primary => true } - has_one :provision_interface, :class_name => 'Nic::Base', :foreign_key => 'host_id', - :conditions => { :provision => true } + has_many :interfaces, -> { order(:identifier) }, :dependent => :destroy, :inverse_of => :host, :class_name => 'Nic::Base', + :foreign_key => :host_id + has_one :primary_interface, -> { where(:primary => true) }, :class_name => 'Nic::Base', :foreign_key => 'host_id' + has_one :provision_interface, -> { where(:provision => true) }, :class_name => 'Nic::Base', :foreign_key => 'host_id' has_one :domain, :through => :primary_interface has_one :subnet, :through => :primary_interface accepts_nested_attributes_for :interfaces, :allow_destroy => true diff --git a/app/models/host/managed.rb b/app/models/host/managed.rb index 4e7969496ba6..d16c36e844be 100644 --- a/app/models/host/managed.rb +++ b/app/models/host/managed.rb @@ -12,10 +12,8 @@ class Host::Managed < Host::Base belongs_to :owner, :polymorphic => true belongs_to :compute_resource belongs_to :image - has_many :host_statuses, :class_name => 'HostStatus::Status', :foreign_key => 'host_id', :inverse_of => :host, - :dependent => :destroy + has_many :host_statuses, :class_name => 'HostStatus::Status', :foreign_key => 'host_id', :inverse_of => :host, :dependent => :destroy has_one :configuration_status_object, :class_name => 'HostStatus::ConfigurationStatus', :foreign_key => 'host_id' - has_one :token, :foreign_key => :host_id, :dependent => :destroy before_destroy :remove_reports @@ -155,7 +153,8 @@ class Jail < ::Safemode::Jail audited :except => [:last_report, :puppet_status, :last_compile, :lookup_value_matcher], :allow_mass_assignment => true has_associated_audits #redefine audits relation because of the type change (by default the relation will look for auditable_type = 'Host::Managed') - has_many :audits, :foreign_key => :auditable_id, :class_name => Audited.audit_class.name, :conditions => { :auditable_type => 'Host' } + has_many :audits, -> { where(:auditable_type => 'Host') }, :foreign_key => :auditable_id, + :class_name => Audited.audit_class.name # some shortcuts alias_attribute :os, :operatingsystem @@ -589,7 +588,7 @@ def apply_inherited_attributes(attributes, initialized = true) new_hostgroup = self.hostgroup if initialized unless [new_hostgroup.try(:id), new_hostgroup.try(:friendly_id)].include? new_hostgroup_id - new_hostgroup = Hostgroup.find(new_hostgroup_id) + new_hostgroup = Hostgroup.friendly.find(new_hostgroup_id) end return attributes unless new_hostgroup @@ -814,11 +813,11 @@ def available_template_kinds(provisioning = nil) cr = ComputeResource.find_by_id(self.compute_resource_id) images = cr.try(:images) if images.blank? - [TemplateKind.find('finish')] + [TemplateKind.friendly.find('finish')] else uuid = self.compute_attributes[cr.image_param_name] image_kind = images.find_by_uuid(uuid).try(:user_data) ? 'user_data' : 'finish' - [TemplateKind.find(image_kind)] + [TemplateKind.friendly.find(image_kind)] end else TemplateKind.all diff --git a/app/models/host_class.rb b/app/models/host_class.rb index e1d078b94c25..e6f8953dcf6c 100644 --- a/app/models/host_class.rb +++ b/app/models/host_class.rb @@ -7,7 +7,6 @@ class HostClass < ActiveRecord::Base belongs_to_host belongs_to :puppetclass - validates :host, :presence => true validates :puppetclass_id, :presence => true, :uniqueness => {:scope => :host_id} def name diff --git a/app/models/hostgroup_class.rb b/app/models/hostgroup_class.rb index 26efa1074b53..ca1203a5f7d6 100644 --- a/app/models/hostgroup_class.rb +++ b/app/models/hostgroup_class.rb @@ -8,7 +8,6 @@ class HostgroupClass < ActiveRecord::Base belongs_to :puppetclass, :counter_cache => :hostgroups_count attr_accessible :hostgroup_id, :hostgroup, :puppetclass_id, :puppetclass - validates :hostgroup, :presence => true validates :puppetclass_id, :presence => true, :uniqueness => {:scope => :hostgroup_id} diff --git a/app/models/lookup_keys/puppetclass_lookup_key.rb b/app/models/lookup_keys/puppetclass_lookup_key.rb index ffb1f8ead157..6cfd122e8a46 100644 --- a/app/models/lookup_keys/puppetclass_lookup_key.rb +++ b/app/models/lookup_keys/puppetclass_lookup_key.rb @@ -1,6 +1,6 @@ class PuppetclassLookupKey < LookupKey has_many :environment_classes, :dependent => :destroy - has_many :environments, :through => :environment_classes, :uniq => true + has_many :environments, -> { uniq }, :through => :environment_classes has_many :param_classes, :through => :environment_classes, :source => :puppetclass scoped_search :in => :param_classes, :on => :name, :rename => :puppetclass, :complete_value => true diff --git a/app/models/operatingsystem.rb b/app/models/operatingsystem.rb index 3678045511b3..382521033e5c 100644 --- a/app/models/operatingsystem.rb +++ b/app/models/operatingsystem.rb @@ -34,6 +34,7 @@ class Operatingsystem < ActiveRecord::Base accepts_nested_attributes_for :os_parameters, :allow_destroy => true include ParameterValidators has_many :trends, :as => :trendable, :class_name => "ForemanTrend" + attr_name :to_label validates :minor, :numericality => {:greater_than_or_equal_to => 0}, :allow_nil => true, :allow_blank => true validates :name, :presence => true, :no_whitespace => true, diff --git a/app/models/puppetclass.rb b/app/models/puppetclass.rb index cc4fbe0d1869..7a5f9cc5fa56 100644 --- a/app/models/puppetclass.rb +++ b/app/models/puppetclass.rb @@ -8,7 +8,7 @@ class Puppetclass < ActiveRecord::Base validates_lengths_from_database before_destroy EnsureNotUsedBy.new(:hosts, :hostgroups) has_many :environment_classes, :dependent => :destroy - has_many :environments, :through => :environment_classes, :uniq => true + has_many :environments, -> { uniq }, :through => :environment_classes has_and_belongs_to_many :operatingsystems has_many :hostgroup_classes has_many :hostgroups, :through => :hostgroup_classes, :dependent => :destroy @@ -19,8 +19,8 @@ class Puppetclass < ActiveRecord::Base has_many :lookup_keys, :inverse_of => :puppetclass, :dependent => :destroy, :class_name => 'VariableLookupKey' accepts_nested_attributes_for :lookup_keys, :reject_if => ->(a) { a[:key].blank? }, :allow_destroy => true # param classes - has_many :class_params, :through => :environment_classes, :uniq => true, - :source => :puppetclass_lookup_key, :conditions => 'environment_classes.puppetclass_lookup_key_id is NOT NULL' + has_many :class_params, -> { where('environment_classes.puppetclass_lookup_key_id is NOT NULL').uniq }, + :through => :environment_classes, :source => :puppetclass_lookup_key accepts_nested_attributes_for :class_params, :reject_if => ->(a) { a[:key].blank? }, :allow_destroy => true validates :name, :uniqueness => true, :presence => true, :no_whitespace => true @@ -202,7 +202,7 @@ def self.prepare_rdoc(root) def self.search_by_host(key, operator, value) conditions = sanitize_sql_for_conditions(["hosts.name #{operator} ?", value_to_sql(operator, value)]) - direct = Puppetclass.joins(:hosts).where(conditions).uniq.pluck('puppetclasses.id') + direct = Puppetclass.joins(:hosts).where(conditions).pluck('puppetclasses.id').uniq hostgroup = Hostgroup.joins(:hosts).where(conditions).first indirect = hostgroup.blank? ? [] : HostgroupClass.where(:hostgroup_id => hostgroup.path_ids).uniq.pluck('puppetclass_id') return { :conditions => "1=0" } if direct.blank? && indirect.blank? diff --git a/app/models/report.rb b/app/models/report.rb index 806fe34a073c..9d5b7484b344 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -31,7 +31,7 @@ class Report < ActiveRecord::Base # returns reports for hosts in the User's filter set scope :my_reports, lambda { if !User.current.admin? || Organization.expand(Organization.current).present? || Location.expand(Location.current).present? - joins_authorized(Host, :view_hosts, :where => Host.taxonomy_conditions) + joins_authorized(Host, :view_hosts) end } diff --git a/app/models/subnet.rb b/app/models/subnet.rb index 735ba11cedd8..9b5d709e0160 100644 --- a/app/models/subnet.rb +++ b/app/models/subnet.rb @@ -23,7 +23,7 @@ class Subnet < ActiveRecord::Base has_many :subnet_domains, :dependent => :destroy has_many :domains, :through => :subnet_domains has_many :interfaces, :class_name => 'Nic::Base' - has_many :primary_interfaces, :class_name => 'Nic::Base', :conditions => { :primary => true } + has_many :primary_interfaces, -> { where(:primary => true) }, :class_name => 'Nic::Base' has_many :hosts, :through => :interfaces has_many :primary_hosts, :through => :primary_interfaces, :source => :host validates :network, :mask, :name, :presence => true diff --git a/app/models/user.rb b/app/models/user.rb index 29e2616d055e..cd5ce4c5a28e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,10 +25,10 @@ class User < ActiveRecord::Base has_many :auditable_changes, :class_name => '::Audit', :as => :user has_many :direct_hosts, :class_name => 'Host', :as => :owner has_many :usergroup_member, :dependent => :destroy, :as => :member - has_many :user_roles, :dependent => :destroy, :foreign_key => 'owner_id', :conditions => {:owner_type => self.to_s} + has_many :user_roles, -> { where(:owner_type => 'User') }, :dependent => :destroy, :foreign_key => 'owner_id' has_many :cached_user_roles, :dependent => :destroy has_many :cached_usergroups, :through => :cached_usergroup_members, :source => :usergroup - has_many :cached_roles, :through => :cached_user_roles, :source => :role, :uniq => true + has_many :cached_roles, -> { uniq }, :through => :cached_user_roles, :source => :role has_many :usergroups, :through => :usergroup_member, :dependent => :destroy has_many :roles, :through => :user_roles, :dependent => :destroy has_many :filters, :through => :cached_roles @@ -393,7 +393,7 @@ def self.random_password(size = 16) end def expire_topbar_cache(sweeper) - sweeper.expire_fragment(TopbarSweeper.fragment_name(id)) + ActionController::Base.new.expire_fragment(TopbarSweeper.fragment_name(id)) end def external_usergroups diff --git a/app/models/user_mail_notification.rb b/app/models/user_mail_notification.rb index b3869fb43d19..041b2122e34c 100644 --- a/app/models/user_mail_notification.rb +++ b/app/models/user_mail_notification.rb @@ -4,7 +4,7 @@ class UserMailNotification < ActiveRecord::Base belongs_to :user belongs_to :mail_notification - validates :user_id, :presence => true + validates :user, :presence => true validates :mail_notification, :presence => true scope :daily, -> { where(:interval => 'Daily') } diff --git a/app/models/user_role.rb b/app/models/user_role.rb index 5478a528c40d..b49180c46ebd 100644 --- a/app/models/user_role.rb +++ b/app/models/user_role.rb @@ -59,7 +59,7 @@ def cache_user_roles! end def build_user_role_cache - [ self.cached_user_roles.build(:user => owner, :role => role) ] + [ self.cached_user_roles.build(:user_id => owner.id, :role_id => role.id) ] end def build_user_group_role_cache(owner) diff --git a/app/models/usergroup.rb b/app/models/usergroup.rb index 1570670d78ba..c255fd15f203 100644 --- a/app/models/usergroup.rb +++ b/app/models/usergroup.rb @@ -11,7 +11,7 @@ class Usergroup < ActiveRecord::Base validates_lengths_from_database before_destroy EnsureNotUsedBy.new(:hosts), :ensure_last_admin_group_is_not_deleted - has_many :user_roles, :dependent => :destroy, :foreign_key => 'owner_id', :conditions => {:owner_type => self.to_s} + has_many :user_roles, -> { where(:owner_type => 'Usergroup') }, :dependent => :destroy, :foreign_key => 'owner_id' has_many :roles, :through => :user_roles, :dependent => :destroy has_many :usergroup_members, :dependent => :destroy @@ -19,12 +19,14 @@ class Usergroup < ActiveRecord::Base has_many :usergroups, :through => :usergroup_members, :source => :member, :source_type => 'Usergroup', :dependent => :destroy has_many :external_usergroups, :dependent => :destroy, :inverse_of => :usergroup - has_many :cached_usergroup_members - has_many :usergroup_parents, :dependent => :destroy, :foreign_key => 'member_id', - :conditions => "member_type = 'Usergroup'", :class_name => 'UsergroupMember' + has_many :cached_usergroups, :through => :cached_usergroup_members, :source => :usergroup + has_many :cached_usergroup_members, :foreign_key => 'usergroup_id' + has_many :usergroup_parents, -> { where("member_type = 'Usergroup'") }, :dependent => :destroy, + :foreign_key => 'member_id', :class_name => 'UsergroupMember' has_many :parents, :through => :usergroup_parents, :source => :usergroup, :dependent => :destroy has_many_hosts :as => :owner + validates :name, :uniqueness => true, :presence => true # The text item to see in a select dropdown menu diff --git a/app/models/usergroup_member.rb b/app/models/usergroup_member.rb index e27c25c99dd5..781bf438f35d 100644 --- a/app/models/usergroup_member.rb +++ b/app/models/usergroup_member.rb @@ -100,7 +100,7 @@ def find_all_user_roles end def find_all_user_roles_for(usergroup) - usergroup.user_roles + usergroup.parents.map { |g| find_all_user_roles_for(g) } + (UserRole.where(:owner => usergroup )+ usergroup.parents.map { |g| find_all_user_roles_for(g) }).flatten end def find_all_usergroups diff --git a/app/services/foreman/plugin.rb b/app/services/foreman/plugin.rb index 0899b1fc33fe..853a57b45158 100644 --- a/app/services/foreman/plugin.rb +++ b/app/services/foreman/plugin.rb @@ -176,6 +176,9 @@ def delete_menu_item(menu, item) end def tests_to_skip(hash) + Rails.logger.warn "Minitest 5 deprecated the runner API and plugin tests \ +can't be skipped right now. Future versions of Foreman might bring back this \ +feature" # Format is { "testclass" => [ "skip1", "skip2" ] } hash.each do |testclass,tests| if self.class.tests_to_skip[testclass].nil? @@ -219,8 +222,12 @@ def role(name, permissions) end def pending_migrations - migrations = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations_paths).pending_migrations - migrations.size > 0 + migration_paths = ActiveRecord::Migrator.migrations( + ActiveRecord::Migrator.migrations_paths) + pending_migrations = ActiveRecord::Migrator.new(:up, migration_paths). + pending_migrations + + pending_migrations.size > 0 end # List of helper methods allowed for templates in safe mode diff --git a/app/services/tax_host.rb b/app/services/tax_host.rb index 010b40d03726..11c8a1ec17f7 100644 --- a/app/services/tax_host.rb +++ b/app/services/tax_host.rb @@ -154,8 +154,9 @@ def non_inherited_ids(v1 = self.selected_ids, v2 = self.inherited_ids) # populate used_ids for 3 non-standard_id's def user_ids(hosts = self.hosts) - #TODO: when migrating to rails 3.1+ switch to inner select on users. - User.unscoped.joins(:direct_hosts).where({ :hosts => { :id => hosts }, :users => { :admin => false } }).pluck('DISTINCT users.id') + User.unscoped.except_admin. + eager_load(:direct_hosts).where(:hosts => { :id => hosts.map(&:id) }). + pluck('DISTINCT users.id') end def provisioning_template_ids(hosts = self.hosts) diff --git a/app/views/api/v2/interfaces/base.json.rabl b/app/views/api/v2/interfaces/base.json.rabl index 43dcaf324f2c..2181267775cf 100644 --- a/app/views/api/v2/interfaces/base.json.rabl +++ b/app/views/api/v2/interfaces/base.json.rabl @@ -2,5 +2,6 @@ object @interface attributes :id, :name, :ip, :mac, :identifier, :primary, :provision node :type do |i| + next if i.is_a? Symbol i.class.humanized_name.downcase end diff --git a/bundler.d/assets.rb b/bundler.d/assets.rb index 319985db1447..dc90498e1c8a 100644 --- a/bundler.d/assets.rb +++ b/bundler.d/assets.rb @@ -1,21 +1,18 @@ group :assets do gem 'ace-rails-ap', '~> 4.0.0' - gem 'sass-rails', '~> 3.2' + gem 'sass-rails', '~> 4.0' gem 'uglifier', '>= 1.0.3' gem 'execjs', '>= 1.4.0', '<2.5.0' - gem 'jquery-rails', '2.0.3' + gem 'jquery-rails', '~> 3.1' gem 'jquery-ui-rails', '< 5.0.0' gem 'bootstrap-sass', '3.0.3.0' - gem 'spice-html5-rails', '~> 0.1.4' + gem 'spice-html5-rails', '~> 0.1.5' gem 'flot-rails', '0.0.3' gem 'quiet_assets', '~> 1.0' - gem 'gettext_i18n_rails_js', '~> 0.0', '>= 0.0.8' - # unspecified dep of gettext_i18n_rails_js - # https://github.com/nubis/gettext_i18n_rails_js/pull/23 - gem 'gettext', '~> 3.1', :require => false + gem 'gettext_i18n_rails_js', '~> 1.0' gem 'multi-select-rails', '~> 0.9' - gem 'gridster-rails', '~> 0.5' - gem 'jquery_pwstrength_bootstrap', '~> 1.2' + gem 'gridster-rails', '0.5.6' + gem 'jquery_pwstrength_bootstrap', github: "unorthodoxgeek/jquery_pwstrength_bootstrap-gem" #TODO gem 'jquery-turbolinks', '~> 2.1' gem 'select2-rails', '~> 3.5' gem 'underscore-rails', '~> 1.8' diff --git a/bundler.d/console.rb b/bundler.d/console.rb index 40d40e295c27..1affb5c30be3 100644 --- a/bundler.d/console.rb +++ b/bundler.d/console.rb @@ -2,7 +2,4 @@ gem 'wirb', '~> 1.0' gem 'hirb-unicode', '~> 0.0.5' gem 'awesome_print', '~> 1.0', :require => 'ap' - - # minitest - workaround until Rails 4.0 (#2650) - gem 'minitest', '~> 4.7', :require => 'minitest/unit' end diff --git a/bundler.d/test.rb b/bundler.d/test.rb index 526ad8b9f412..7a819a37f270 100644 --- a/bundler.d/test.rb +++ b/bundler.d/test.rb @@ -3,13 +3,13 @@ gem 'simplecov', '~> 0.9' gem 'spork-minitest', '0.0.3' gem 'single_test', '~> 0.6' - gem 'minitest', '~> 4.7' - gem 'minitest-spec-rails', '~> 4.7' - gem 'ci_reporter', '>= 1.6.3', '< 2.0.0', :require => false + gem 'minitest', '~> 5.1.0' + gem 'minitest-spec-rails', '~> 5.3' + gem 'ci_reporter_minitest', :require => false gem 'capybara', '~> 2.0' gem 'database_cleaner', '~> 1.3' gem 'launchy', '~> 2.4' - gem 'spork', '~> 0.9' + gem 'spork-rails', '~> 4.0.0' gem 'factory_girl_rails', '~> 4.5', :require => false gem 'rubocop-checkstyle_formatter', '~> 0.2' gem "poltergeist" diff --git a/config/application.rb b/config/application.rb index 8734ca1a7cec..83aef6f4eddd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,8 @@ +if defined?(Rake.application) && Rake.application.top_level_tasks.grep(/jenkins/).any? + ENV['RAILS_ENV'] ||= 'test' +end require File.expand_path('../boot', __FILE__) require 'apipie/middleware/checksum_in_headers' - require 'rails/all' require File.expand_path('../../config/settings', __FILE__) @@ -85,7 +87,9 @@ module Foreman class Application < Rails::Application # Setup additional routes by loading all routes file from routes directory - config.paths["config/routes"] += Dir[Rails.root.join("config/routes/**/*.rb")] + Dir["#{Rails.root}/config/routes/**/*.rb"].each do |route_file| + config.paths['config/routes.rb'] << route_file + end # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers diff --git a/config/environments/development.rb b/config/environments/development.rb index dee9b93b32e4..ca568635f000 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -24,19 +24,12 @@ # Should ANSI color codes be used when logging information config.colorize_logging = Foreman::Logging.config[:colorize] - # Do not compress assets - config.assets.compress = false - # Expands the lines which load the assets config.assets.debug = true # Raise exception on mass assignment protection for Active Record models config.active_record.mass_assignment_sanitizer = :strict - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - config.active_record.auto_explain_threshold_in_seconds = 0.5 - config.after_initialize do Bullet.enable = true Bullet.bullet_logger = true diff --git a/config/environments/production.rb b/config/environments/production.rb index a024ffb0ecaf..e3cbed2eecb4 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -42,6 +42,7 @@ # Eager load all classes under lib directory config.eager_load_paths += ["#{config.root}/lib"] + config.eager_load = true # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) @@ -51,11 +52,11 @@ config.active_support.deprecation = :notify # Compress JavaScripts and CSS - config.assets.compress = true + config.assets.js_compressor = :uglifier # Fallback to assets pipeline if a precompiled asset is missed: # that's the case when an engine with it's own assets is added to Foreman later in production. - config.assets.compile = true + config.assets.compile = false # Generate digests for assets URLs config.assets.digest = true diff --git a/config/environments/test.rb b/config/environments/test.rb index 8f97d032ef29..90336477a3c2 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -49,4 +49,8 @@ # Use separate cache stores for parallel_tests config.cache_store = :file_store, Rails.root.join("tmp", "cache", "paralleltests#{ENV['TEST_ENV_NUMBER']}") + + # Disables automatic creation of the test DB so that it has to be explicitly + # generated before running tests. + config.active_record.maintain_test_schema = false end diff --git a/config/initializers/1_fast_gettext.rb b/config/initializers/1_fast_gettext.rb index c2014cf84444..ead96f4a80bc 100644 --- a/config/initializers/1_fast_gettext.rb +++ b/config/initializers/1_fast_gettext.rb @@ -7,6 +7,9 @@ Foreman::Gettext::Support.register_available_locales locale_domain, locale_dir Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir +I18n.config.enforce_available_locales = false +I18n.config.available_locales = FastGettext.default_available_locales + FastGettext.default_text_domain = locale_domain FastGettext.locale = "en" diff --git a/config/initializers/routing_hash_for.rb b/config/initializers/routing_hash_for.rb new file mode 100644 index 000000000000..9c163e265bf4 --- /dev/null +++ b/config/initializers/routing_hash_for.rb @@ -0,0 +1,29 @@ +module ActionDispatch + module Routing + class RouteSet + class NamedRouteCollection + def define_url_helper(route, name, options) + helper = UrlHelper.create(route, options.dup) + + @module.remove_possible_method name + @module.module_eval do + define_method(name) do |*args| + helper.call self, args + end + + #because we heavily rely on the removed hash_for method in routes, we must add this monkey patch. + define_method("hash_for_#{name}") do |*args| + unless args.first.is_a? Hash + id = args.first.try(:to_param) + options[:id] = id if id.present? + end + helper.send(:handle_positional_args, self, args, options, []) + end + end + + helpers << name + end + end + end + end +end diff --git a/db/migrate/20110616080444_add_look_up_key_id_to_puppet_class.rb b/db/migrate/20110616080444_add_look_up_key_id_to_puppet_class.rb index e38216b4bb5b..0aa75dad8b88 100644 --- a/db/migrate/20110616080444_add_look_up_key_id_to_puppet_class.rb +++ b/db/migrate/20110616080444_add_look_up_key_id_to_puppet_class.rb @@ -11,7 +11,6 @@ def up add_column :lookup_keys, :validator_type, :string add_column :lookup_keys, :validator_rule, :string rename_column :lookup_values, :priority, :match - add_index :lookup_values, :match end def down diff --git a/db/migrate/20140219183343_migrate_permissions.rb b/db/migrate/20140219183343_migrate_permissions.rb index 08efe504367f..f15d3509f75d 100644 --- a/db/migrate/20140219183343_migrate_permissions.rb +++ b/db/migrate/20140219183343_migrate_permissions.rb @@ -22,12 +22,12 @@ def resource_type @resource_type ||= permissions.first.try(:resource_type) end - taxonomy_join_table = "taxable_taxonomies" + taxonomy_join_table = :taxable_taxonomies has_many taxonomy_join_table, :dependent => :destroy, :as => :taxable, :foreign_key => 'taxable_id' - has_many :locations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Location'", :validate => false - has_many :organizations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Organization'", :validate => false + has_many :locations, -> { where(:type => 'Location') }, :through => taxonomy_join_table, :source => :taxonomy, + :validate => false + has_many :organizations, -> { where(:type => 'Organization') }, :through => taxonomy_join_table, :source => :taxonomy, + :validate => false end class FakeUserRole < ActiveRecord::Base @@ -61,15 +61,15 @@ def self.name has_many :hostgroups, :through => :user_hostgroups has_many :user_facts, :dependent => :destroy, :foreign_key => 'user_id' has_many :facts, :through => :user_facts, :source => :fact_name - has_many :user_roles, :dependent => :destroy, :foreign_key => 'owner_id', - :conditions => {:owner_type => 'User'}, :class_name => 'FakeUserRole' + has_many :user_roles, -> { where(:owner_type => 'User') }, :dependent => :destroy, :foreign_key => 'owner_id', + :class_name => 'FakeUserRole' has_many :roles, :through => :user_roles, :dependent => :destroy, :class_name => 'FakeRole' - taxonomy_join_table = "taxable_taxonomies" + taxonomy_join_table = :taxable_taxonomies has_many taxonomy_join_table, :dependent => :destroy, :as => :taxable, :foreign_key => 'taxable_id' - has_many :locations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Location'", :validate => false - has_many :organizations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Organization'", :validate => false + has_many :locations, -> { where(:type => 'Location') }, :through => taxonomy_join_table, :source => :taxonomy, + :validate => false + has_many :organizations, -> { where(:type => 'Organization') }, :through => taxonomy_join_table, :source => :taxonomy, + :validate => false has_many :cached_usergroup_members, :foreign_key => 'user_id' has_many :cached_usergroups, :through => :cached_usergroup_members, :source => :usergroup end diff --git a/lib/foreman/logging.rb b/lib/foreman/logging.rb index d554b00427e1..9ff7ec521695 100644 --- a/lib/foreman/logging.rb +++ b/lib/foreman/logging.rb @@ -1,6 +1,8 @@ require 'logging' require 'fileutils' +::Logging::Logger.send(:include, ActiveRecord::SessionStore::Extension::LoggerSilencer) + module Foreman class LoggingImpl private_class_method :new diff --git a/lib/middleware/catch_json_parse_errors.rb b/lib/middleware/catch_json_parse_errors.rb index 1fbab51cad62..9a5bdf591f6d 100644 --- a/lib/middleware/catch_json_parse_errors.rb +++ b/lib/middleware/catch_json_parse_errors.rb @@ -7,7 +7,7 @@ def initialize(app) def call(env) begin @app.call(env) - rescue MultiJson::LoadError, MultiJson::ParseError => error + rescue ActionDispatch::ParamsParser::ParseError => error if env['HTTP_ACCEPT'] =~ /application\/json/ || env['CONTENT_TYPE'] =~ /application\/json/ error_output = "There was a problem in the JSON you submitted: #{error}" Rails.logger.debug(error_output) diff --git a/lib/tasks/jenkins.rake b/lib/tasks/jenkins.rake index a653b592be9f..c5a3b14b70ac 100644 --- a/lib/tasks/jenkins.rake +++ b/lib/tasks/jenkins.rake @@ -1,25 +1,24 @@ begin require "ci/reporter/rake/minitest" - namespace :foreman do - task :set_test_runner do - ENV['TESTOPTS'] = "#{ENV['TESTOPTS']} #{Rails.root}/test/test_runner.rb" - end - end - namespace :jenkins do - task :unit => ["jenkins:setup:minitest", 'rake:test:units', 'rake:test:lib', 'rake:test:functionals'] - task :integration => ["jenkins:setup:minitest", 'rake:test:integration'] - task :lib => ["jenkins:setup:minitest", 'rake:test:lib'] - task :functionals => ["jenkins:setup:minitest", 'rake:test:functionals'] - task :units => ["jenkins:setup:minitest", 'rake:test:units'] + task :unit => ['jenkins:db', 'jenkins:setup:minitest', + 'rake:test:units', 'rake:test:lib', 'rake:test:functionals'] + task :integration => ['jenkins:db', 'jenkins:setup:minitest', 'rake:test:integration'] + task :lib => ['jenkins:db', 'jenkins:setup:minitest', 'rake:test:lib'] + task :functionals => ['jenkins:db', 'jenkins:setup:minitest', 'rake:test:functionals'] + task :units => ['jenkins:db', 'jenkins:setup:minitest', 'rake:test:units'] namespace :setup do task :pre_ci do ENV["CI_REPORTS"] = 'jenkins/reports/unit/' gem 'ci_reporter' end - task :minitest => [:pre_ci, "ci:setup:minitest", "foreman:set_test_runner"] + task :minitest => [:pre_ci, "ci:setup:minitest"] + end + + task :db do + system('rake db:test:prepare RAILS_ENV=test') end task :rubocop do @@ -33,4 +32,3 @@ begin rescue LoadError # ci/reporter/rake/rspec not present, skipping this definition end - diff --git a/lib/tasks/plugin_assets.rake b/lib/tasks/plugin_assets.rake index 757d252ec44e..ef8e7083b5ee 100644 --- a/lib/tasks/plugin_assets.rake +++ b/lib/tasks/plugin_assets.rake @@ -1,5 +1,5 @@ desc 'Compile engine assets - called via rake plugin:assets:precompile[plugin_name]' -task 'plugin:assets:precompile', :engine do |t, args| +task 'plugin:assets:precompile', [:engine] do |t, args| # This task will generate assets for a plugin and namespace them in # plugin_name/public/assets/. The generated manifest.yaml found # in the assets directory of the plugin is used to add the asset digest paths @@ -34,60 +34,51 @@ task 'plugin:assets:precompile', :engine do |t, args| # } # } - def compile_assets(args = {}) - _ = ActionView::Base + module Foreman + class PluginAssetsTask < Sprockets::Rails::Task + attr_accessor :engine - app = Rails.application - assets = app.config.assets - env = app.assets - target = File.join(@engine_root, 'public', 'assets') + def initialize(engine_name) + @engine = "#{engine_name.camelize}::Engine".constantize + Rails.application.config.assets.precompile = SETTINGS[@engine.engine_name.to_sym][:assets][:precompile] + Rails.application.assets.js_compressor = :uglifier + super(Rails.application) + end - assets.digests = {} - assets.manifest = File.join(target, @engine.engine_name) - assets.compile = SETTINGS[@engine.engine_name.to_sym][:assets][:compile] || assets.compile - assets.compress = SETTINGS[@engine.engine_name.to_sym][:assets][:compress] || assets.compress - assets.digest = args.fetch(:digest, true) - assets.js_compressor = SETTINGS[@engine.engine_name.to_sym][:assets][:js_compressor] + def compile + with_logger do + manifest.compile(assets) + end + end - precompile = SETTINGS[@engine.engine_name.to_sym][:assets][:precompile] - precompile = fix_indexes(precompile) + def environment + env = Rails.application.assets + Rails.application.config.assets.paths.each do |path| + env.append_path path + end + env + end - Sprockets::Bootstrap.new(Rails.application).run - compiler = Sprockets::StaticCompiler.new(env, - target, - precompile, - :manifest_path => assets.manifest, - :digest => assets.digest, - :manifest => true) - compiler.compile - end + def output + File.join(@engine.root, 'public', 'assets') + end - # Used to add index manifest files to the paths for - # proper resolution and addition when running Rails 3.2.8 - # in the SCL - def fix_indexes(precompile) - if Rails.version == '3.2.8' - precompile.each do |asset| - if File.basename(asset)[/[^\.]+/, 0] == 'index' - asset.sub!(/\/index\./, '.') - precompile << asset - end + def manifest_path + File.join(output, @engine.engine_name, "#{@engine.engine_name}.json") end - end - precompile + def manifest + Sprockets::Manifest.new(index, output, manifest_path) + end + end end if args[:engine] # Partially load the Rails environment to avoid # the need of a database being setup Rails.application.initialize!(:assets) - - @engine = "#{args[:engine].camelize}::Engine".constantize - @engine_root = @engine.root - - compile_assets(:digest => false) - compile_assets + task = Foreman::PluginAssetsTask.new(args[:engine]) + task.compile else puts "You must specify the name of the plugin (e.g. rake plugin:assets:precompile['my_plugin'])" end diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake index 03ae8123f07f..b9ec3fb4f289 100644 --- a/lib/tasks/test.rake +++ b/lib/tasks/test.rake @@ -19,10 +19,3 @@ end Rake::Task[:test].enhance do Rake::Task['test:lib'].invoke end - -Rake::Task[:test].enhance ['foreman:set_test_runner'] -Rake::Task['test:units'].enhance ['foreman:set_test_runner'] -Rake::Task['test:functionals'].enhance ['foreman:set_test_runner'] -Rake::Task['test:integration'].enhance ['foreman:set_test_runner'] -Rake::Task['test:lib'].enhance ['foreman:set_test_runner'] -Rake::Task['test:api'].enhance ['foreman:set_test_runner'] diff --git a/test/functional/api/base_controller_subclass_test.rb b/test/functional/api/base_controller_subclass_test.rb index 989b6ba8ac86..ed5a3b3e8059 100644 --- a/test/functional/api/base_controller_subclass_test.rb +++ b/test/functional/api/base_controller_subclass_test.rb @@ -211,48 +211,42 @@ class Api::TestableControllerTest < ActionController::TestCase assert_equal @response.status, 200 end - it 'should return nested resource for unauthorized resource' do - child_associacion = mock('child_associacion') - testable_scope1 = mock('testable_scope1') - testable_scope2 = mock('testable_scope2') - testable_obj = mock('testable1') - - Testable.stubs(:joins).returns(child_associacion) - Testable.stubs(:where).returns(testable_scope2) - Testable.stubs(:scoped).returns(testable_scope2) - testable_scope2.stubs(:merge).returns(testable_scope1) - child_associacion.stubs(:merge).returns(testable_scope1) - testable_scope1.stubs(:readonly).returns(testable_scope1) + context 'nested resource permissions' do + setup do + @child_associacion = mock('child_associacion') + @testable_scope1 = mock('testable_scope1') + @testable_scope2 = mock('testable_scope2') + @testable_obj = mock('testable1') + @testable_scope2.stubs(:merge).returns(@testable_scope1) + @child_associacion.stubs(:merge).returns(@testable_scope1) + @testable_scope1.stubs(:readonly).returns(@testable_scope1) + @testable_scope1.expects(:find).with('1').returns(@testable_obj) + @testable_scope1.expects(:empty?).returns(false) + Testable.stubs(:joins).returns(@child_associacion) + end - testable_scope1.expects(:find).with('1').returns(testable_obj) + it 'should return nested resource for unauthorized resource' do + Testable.stubs(:where).returns(@testable_scope2) + Testable.stubs(:scoped).returns(@testable_scope2) - get :nested_values, :domain_id => 1, :id => 1 + get :nested_values, :domain_id => 1, :id => 1 - assert_equal testable_obj, @controller.instance_variable_get('@testable') - assert_equal @nested_obj, @controller.instance_variable_get('@nested_obj') - end - - it 'should return nested resource scope for authorized resource' do - child_auth_scope = mock('child_auth_scope') - child_associacion = mock('child_associacion') - testable_scope1 = mock('testable_scope1') - testable_scope2 = mock('testable_scope2') - testable_obj = mock('testable1') + assert_equal @testable_obj, @controller.instance_variable_get('@testable') + assert_equal @nested_obj, @controller.instance_variable_get('@nested_obj') + end - Testable.stubs(:authorized).returns(child_auth_scope) - Testable.stubs(:joins).returns(child_associacion) - testable_scope2.stubs(:merge).returns(testable_scope1) - child_associacion.stubs(:merge).returns(testable_scope1) - child_auth_scope.stubs(:where).returns(testable_scope2) - child_auth_scope.stubs(:scoped).returns(testable_scope2) - testable_scope1.stubs(:readonly).returns(testable_scope1) + it 'should return nested resource scope for authorized resource' do + child_auth_scope = mock('child_auth_scope') - testable_scope1.expects(:find).with('1').returns(testable_obj) + Testable.stubs(:authorized).returns(child_auth_scope) + child_auth_scope.stubs(:where).returns(@testable_scope2) + child_auth_scope.stubs(:scoped).returns(@testable_scope2) - get :nested_values, :domain_id => 1, :id => 1 + get :nested_values, :domain_id => 1, :id => 1 - assert_equal testable_obj, @controller.instance_variable_get('@testable') - assert_equal @nested_obj, @controller.instance_variable_get('@nested_obj') + assert_equal @testable_obj, @controller.instance_variable_get('@testable') + assert_equal @nested_obj, @controller.instance_variable_get('@nested_obj') + end end end diff --git a/test/functional/api/v2/smart_class_parameters_controller_test.rb b/test/functional/api/v2/smart_class_parameters_controller_test.rb index c757be0acadc..a153155648ca 100644 --- a/test/functional/api/v2/smart_class_parameters_controller_test.rb +++ b/test/functional/api/v2/smart_class_parameters_controller_test.rb @@ -64,7 +64,7 @@ class Api::V2::SmartClassParametersControllerTest < ActionController::TestCase get :index, {:puppetclass_id => non_existing_id} assert_response :not_found results = ActiveSupport::JSON.decode(@response.body) - assert_equal "Puppet class with id '#{non_existing_id}' was not found", results["error"]["message"] + assert_equal "Puppetclass with id '#{non_existing_id}' was not found", results["error"]["message"] end test "should get smart class parameters for a specific environment" do diff --git a/test/functional/api/v2/smart_proxies_controller_test.rb b/test/functional/api/v2/smart_proxies_controller_test.rb index 8e5a48a773c5..48c48e6f195a 100644 --- a/test/functional/api/v2/smart_proxies_controller_test.rb +++ b/test/functional/api/v2/smart_proxies_controller_test.rb @@ -181,7 +181,7 @@ def setup_import_classes test "should obsolete puppetclasses" do setup_import_classes as_admin do - assert_difference('Environment.find("env1").puppetclasses.count', -2) do + assert_difference('Environment.find_by_name("env1").puppetclasses.count', -2) do post :import_puppetclasses, {:id => smart_proxies(:puppetmaster).id}, set_session_user end end diff --git a/test/functional/provisioning_templates_controller_test.rb b/test/functional/provisioning_templates_controller_test.rb index 7c5dd5088d45..680f3f61ee53 100644 --- a/test/functional/provisioning_templates_controller_test.rb +++ b/test/functional/provisioning_templates_controller_test.rb @@ -103,7 +103,7 @@ class ProvisioningTemplatesControllerTest < ActionController::TestCase Setting[:unattended_url] = "http://foreman.unattended.url" @request.env['HTTP_REFERER'] = provisioning_templates_path - ProxyAPI::TFTP.any_instance.expects(:create_default).with(has_entry(:menu, regexp_matches(/ks=http:\/\/foreman.unattended.url:80\/unattended\/template/))).returns(true) + ProxyAPI::TFTP.any_instance.expects(:create_default).with(has_entry(:menu, regexp_matches(/ks=http:\/\/foreman.unattended.url\/unattended\/template/))).returns(true) get :build_pxe_default, {}, set_session_user assert_redirected_to provisioning_templates_path diff --git a/test/functional/unattended_controller_test.rb b/test/functional/unattended_controller_test.rb index e8580f2528b7..171f19f7759e 100644 --- a/test/functional/unattended_controller_test.rb +++ b/test/functional/unattended_controller_test.rb @@ -243,7 +243,7 @@ class UnattendedControllerTest < ActionController::TestCase @request.env["REMOTE_ADDR"] = @ub_host.ip @ub_host.create_token(:value => token, :expires => Time.now + 5.minutes) get :provision, {'token' => @ub_host.token.value } - assert @response.body.include?("#{Setting[:unattended_url]}:443/unattended/finish?token=#{token}") + assert @response.body.include?("#{Setting[:unattended_url]}/unattended/finish?token=#{token}") end test "hosts with unknown ip and valid token should render a template" do @@ -314,7 +314,7 @@ class UnattendedControllerTest < ActionController::TestCase @request.env["REMOTE_ADDR"] = @ub_host.ip @ub_host.create_token(:value => "aaaaaa", :expires => Time.now + 5.minutes) get :provision - assert @response.body.include?("http://test.host:80/unattended/finish?token=aaaaaa") + assert @response.body.include?("http://test.host/unattended/finish?token=aaaaaa") end end # end of context "location or organizations are not enabled" diff --git a/test/lib/custom_runner.rb b/test/lib/custom_runner_test.rb similarity index 74% rename from test/lib/custom_runner.rb rename to test/lib/custom_runner_test.rb index bedb2d87085d..3b0b2a959654 100644 --- a/test/lib/custom_runner.rb +++ b/test/lib/custom_runner_test.rb @@ -1,6 +1,8 @@ require 'test_helper' class CustomRunnerTest < ActiveSupport::TestCase + setup { skip 'Temporarily disabled since Minitest 5 deprecated runner API'} + test "custom runner is working" do # This should always be skipped if the runner is working assert false, "Custom runner has failed" diff --git a/test/test_helper.rb b/test/test_helper.rb index 551b9a139b0d..929790352b9e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,7 +1,5 @@ require 'rubygems' require 'spork' -# $LOAD_PATH required for testdrb party of spork-minitest -$LOAD_PATH << "test" require 'simplecov' SimpleCov.start 'rails' do @@ -84,7 +82,9 @@ def clear_current_user alias_method :assert_no_match, :refute_match alias_method :assert_not_nil, :refute_nil alias_method :assert_not_equal, :refute_equal - alias_method :assert_raise, :assert_raises + alias_method :assert_raise, :assert_raises + alias_method :assert_include, :assert_includes + alias_method :assert_not_include, :assert_not_includes class < "test_0010_foo" and string => "foo" - if test[string] - puts "skipping #{self}##{test}" - string - end - end - end - end - end - end - end - - super(suites, type) - end - end -end - -MiniTest::Unit.runner = ForemanMiniTestRunner::Unit.new diff --git a/test/unit/application_mailer_test.rb b/test/unit/application_mailer_test.rb index ffc37f4e2e5f..7d84dda404ff 100644 --- a/test/unit/application_mailer_test.rb +++ b/test/unit/application_mailer_test.rb @@ -3,10 +3,16 @@ class ApplicationMailerTest < ActiveSupport::TestCase setup { ActionMailer::Base.deliveries = [] } + class TestMailer < ::ApplicationMailer + def test + mail(:to => 'nobody@example.com', :subject => 'Danger, Will Robinson!') do |format| + format.text { render :plain => "This is a test mail." } + end + end + end + def mail - ApplicationMailer.mail(:to => 'nobody@example.com', :subject => 'Danger, Will Robinson!') do |mail| - format.text "This is a test mail." - end.deliver + TestMailer.test.deliver ActionMailer::Base.deliveries.last end diff --git a/test/unit/compute_resource_test.rb b/test/unit/compute_resource_test.rb index f177eee86f58..360629fc4f09 100644 --- a/test/unit/compute_resource_test.rb +++ b/test/unit/compute_resource_test.rb @@ -20,7 +20,6 @@ def setup test "password is saved encrypted when created" do Fog.mock! - teardown { Fog.unmock! } ComputeResource.any_instance.expects(:encryption_key).at_least_once.returns('25d224dd383e92a7e0c82b8bf7c985e815f34cf5') compute_resource = ComputeResource.new_provider(:name => "new12345", :provider => "EC2", :url => "eu-west-1", :user => "username", :password => "abcdef") @@ -29,6 +28,7 @@ def setup end assert_equal compute_resource.password, "abcdef" refute_equal compute_resource.password_in_db, "abcdef" + Fog.unmock! end test "random_password should return nil when set_console_password is false" do diff --git a/test/unit/fact_value_test.rb b/test/unit/fact_value_test.rb index be7ab60b6a27..cce8b2e897c2 100644 --- a/test/unit/fact_value_test.rb +++ b/test/unit/fact_value_test.rb @@ -122,22 +122,22 @@ def setup end test "only return facts from host in user's taxonomies" do - user_role = FactoryGirl.create(:user_user_role) - FactoryGirl.create(:filter, :role => user_role.role, :permissions => Permission.where(:name => 'view_hosts'), :search => "hostgroup_id = #{target_host.hostgroup_id}") + setup_user('view', 'hosts', "hostgroup_id = #{target_host.hostgroup_id}") orgs = FactoryGirl.create_pair(:organization) locs = FactoryGirl.create_pair(:location) - target_host.update_attributes(:location => locs.last, :organization => orgs.last) - - user_role.owner.update_attributes(:locations => [locs.first], :organizations => [orgs.first]) - as_user user_role.owner do - assert_equal [], FactValue.my_facts.map(&:id).sort + as_admin do + [orgs, locs].map { |taxonomy| taxonomy.map { |t| t.update_attributes(:users => []) } } + users(:one).update_attributes(:locations => [], :organizations => []) + target_host.update_attributes(:location => locs.last, :organization => orgs.last) + Hostgroup.find(target_host.hostgroup_id).update_attributes(:organizations => [orgs.last], :locations => [locs.last]) end - user_role.owner.update_attributes(:locations => [locs.last], :organizations => [orgs.last]) - as_user user_role.owner do - assert_equal target_host.fact_values.map(&:id).sort, FactValue.my_facts.map(&:id).sort - end + users(:one).update_attributes(:locations => [locs.first], :organizations => [orgs.first]) + assert_equal [], FactValue.my_facts.map(&:id).sort + + users(:one).update_attributes(:locations => [locs.last], :organizations => [orgs.last]) + assert_equal target_host.fact_values.map(&:id).sort, FactValue.my_facts.map(&:id).sort end test "only return facts from host in admin's currently selected taxonomy" do diff --git a/test/unit/helpers/layout_helper_test.rb b/test/unit/helpers/layout_helper_test.rb index cf0658accbe9..e54ab03182c5 100644 --- a/test/unit/helpers/layout_helper_test.rb +++ b/test/unit/helpers/layout_helper_test.rb @@ -15,12 +15,12 @@ class LayoutHelperTest < ActionView::TestCase end test "is_required?(f, attr) method returns true if attribute is required and false if not required" do - f = ActionView::Helpers::FormBuilder.new(:hostgroup, Hostgroup.new, @hostgroup, {}, {}) + f = ActionView::Helpers::FormBuilder.new(:hostgroup, Hostgroup.new, @hostgroup, {}) assert is_required?(f, :name) assert is_required?(f, :title) refute is_required?(f, :environment_id) refute is_required?(f, :parent_id) - f = ActionView::Helpers::FormBuilder.new(:host, Host::Managed.new, @host, {}, {}) + f = ActionView::Helpers::FormBuilder.new(:host, Host::Managed.new, @host, {}) refute is_required?(f, :architecture_id) # not required because of :if refute is_required?(f, :mac) # not required because of :unless end diff --git a/test/unit/host_test.rb b/test/unit/host_test.rb index 38f5b60ef2ba..5efd960f1962 100644 --- a/test/unit/host_test.rb +++ b/test/unit/host_test.rb @@ -780,7 +780,7 @@ def teardown test "available_template_kinds finds templates for a PXE host" do os_dt = FactoryGirl.create(:os_default_template, - :template_kind=> TemplateKind.find('finish')) + :template_kind=> TemplateKind.friendly.find('finish')) host = FactoryGirl.create(:host, :operatingsystem => os_dt.operatingsystem) assert_equal [os_dt.provisioning_template], host.available_template_kinds('build') @@ -788,7 +788,7 @@ def teardown test "available_template_kinds finds templates for an image host" do os_dt = FactoryGirl.create(:os_default_template, - :template_kind=> TemplateKind.find('finish')) + :template_kind=> TemplateKind.friendly.find('finish')) host = FactoryGirl.create(:host, :on_compute_resource, :operatingsystem => os_dt.operatingsystem) FactoryGirl.create(:image, :uuid => 'abcde', @@ -802,7 +802,7 @@ def teardown provision_template = @host.provisioning_template({:kind => "provision"}) @host.expects(:load_template_vars) rendered_template = @host.render_template(provision_template) - assert(rendered_template.include?("http://foreman.some.host.fqdn:80/unattended/finish"), "rendred template should parse foreman_url") + assert(rendered_template.include?("http://foreman.some.host.fqdn/unattended/finish"), "rendred template should parse foreman_url") end end @@ -1824,6 +1824,8 @@ def teardown test "test tokens are not created until host is saved" do class Host::Test < Host::Base + attr_accessible :interfaces + def lookup_value_match 'no_match' end @@ -2547,7 +2549,9 @@ def to_managed! test 'should accept non-existing hostgroup' do host = FactoryGirl.build(:host, :managed, :with_hostgroup) - Hostgroup.expects(:find).with(1111).returns(nil) + hostgroup_friendly_scope = stub + hostgroup_friendly_scope.stubs(:find).with(1111).returns(nil) + Hostgroup.stubs(:friendly).returns(hostgroup_friendly_scope) attributes = { 'hostgroup_id' => 1111 } actual_attr = host.apply_inherited_attributes(attributes)