From c430825fbe9e9f7cd5be9c50c6d1ad2e4f2780cb Mon Sep 17 00:00:00 2001 From: Daniel Lobato Date: Tue, 15 Sep 2015 11:51:40 +0200 Subject: [PATCH] Fixes #7230, #12021 - Upgrade to Rails 4.1.5 This commits upgrades Rails to Rails 4.1.5. See a description of the changes included here, and go to the pull request in GitHub to see more detailed explanations: * Update gems to a Rails 4 compatible version, including dependencies * Fix counter cache columns * Remove conditions, order, limit from has_many relations * Remove test runner On minitest 5, the runner API was deprecated, so our custom test runner is no longer working. * Remove useless add_index on lookup_values match An index is added previously on lookup_values :priority, and on Rails 4 rename_column changes 'priority' to 'match' already changes the name of the index. * Alias assert_include to assert_includes. * Expire topbar cache * Subclass ApplicationMailer in test to avoid 'missing template' error * Fixes #12021 - Use .to_param to find parent object in LookupKeys controller On Rails 4, .find will not default to .friendly.find so find_hostgroup, find_environment and find_host will fail for non numeric IDs. However, we can use from_param to find these objects. This is something we can do both on Rails 3 and Rails 4, whereas using .friendly isn't an option until friendly_id 5.0, which depends on Rails 4. * Use explicit friendly ID search. * find_common finder uses from_param -> friendly -> find The finder needed to be refactored because with the new Friendly ID we have to use .friendly explicitely. It currently follows the strategy of searching like this: - from_param -> .friendly -> regular find * Remove RecordNotFound errors from parameterizable in rails 4 * Protect attributes using attr_accessible and protected_attributes * url_for doesn't append port when protocol is specified Some of our tests are checking if port 80 or 443 is included in the URL generated by lib/foreman/renderer.rb. However url_for has changed in Rails 4 and now it does not append the port even if explicitly added. If the protocol is specified, as it is in this case, then the url generated will just have the protocol (http or https) but not the port (80 or 443) * Validate object instead of _id column in join tables On Rails 4 such validations will fail when we try to create objects without explicitely assigning the id. Puppetclass.new(:config_group => config_group) would fail even for a valid config group, :config_group_id => config_group.id should be used instead. To avoid that, we validate the object, not the ID column * Rails 4 non backwards compatible syntax changes Changes that have to deal with how some of the internal Rails objects need a new syntax, like generating routes, exceptions, form builders. None of these are Rails 3 compatible. * Fixes #12199 - rails 4 migration errors There are actually two parts to the issue of not being able to migrate with this branch. The first is https://gist.github.com/eLobato/0f5db50b5c93cc6c277c and can be temporarily fixed with rails/sass-rails#136 (comment) I am not sure of a long term fix for that atm. Once that is patched, this error https://gist.github.com/johnpmitsch/96e5ba3629890931193a happens on a migration. This will fix that error by changing the Migrator class initializer arguments which have changed from rails 3 to rails 4 * Refactor fact value test to not modify user_roles directly * Return external usergroupsas an array * Use eager_load to preload associations to be used in where Fixes #7230, #12021 - Upgrade to Rails 4.1.5 This commits upgrades Rails to Rails 4.1.5. See a description of the changes included here, and go to the pull request in GitHub to see more detailed explanations: * Update gems to a Rails 4 compatible version, including dependencies * Fix counter cache columns * Remove conditions, order, limit from has_many relations * Remove test runner On minitest 5, the runner API was deprecated, so our custom test runner is no longer working. * Remove useless add_index on lookup_values match An index is added previously on lookup_values :priority, and on Rails 4 rename_column changes 'priority' to 'match' already changes the name of the index. * Alias assert_include to assert_includes. * Expire topbar cache * Subclass ApplicationMailer in test to avoid 'missing template' error * Fixes #12021 - Use .to_param to find parent object in LookupKeys controller On Rails 4, .find will not default to .friendly.find so find_hostgroup, find_environment and find_host will fail for non numeric IDs. However, we can use from_param to find these objects. This is something we can do both on Rails 3 and Rails 4, whereas using .friendly isn't an option until friendly_id 5.0, which depends on Rails 4. * Use explicit friendly ID search. * find_common finder uses from_param -> friendly -> find The finder needed to be refactored because with the new Friendly ID we have to use .friendly explicitely. It currently follows the strategy of searching like this: - from_param -> .friendly -> regular find * Remove RecordNotFound errors from parameterizable in rails 4 * Protect attributes using attr_accessible and protected_attributes * url_for doesn't append port when protocol is specified Some of our tests are checking if port 80 or 443 is included in the URL generated by lib/foreman/renderer.rb. However url_for has changed in Rails 4 and now it does not append the port even if explicitly added. If the protocol is specified, as it is in this case, then the url generated will just have the protocol (http or https) but not the port (80 or 443) * Validate object instead of _id column in join tables On Rails 4 such validations will fail when we try to create objects without explicitely assigning the id. Puppetclass.new(:config_group => config_group) would fail even for a valid config group, :config_group_id => config_group.id should be used instead. To avoid that, we validate the object, not the ID column * Rails 4 non backwards compatible syntax changes Changes that have to deal with how some of the internal Rails objects need a new syntax, like generating routes, exceptions, form builders. None of these are Rails 3 compatible. * Fixes #12199 - rails 4 migration errors There are actually two parts to the issue of not being able to migrate with this branch. The first is https://gist.github.com/eLobato/0f5db50b5c93cc6c277c and can be temporarily fixed with rails/sass-rails#136 (comment) I am not sure of a long term fix for that atm. Once that is patched, this error https://gist.github.com/johnpmitsch/96e5ba3629890931193a happens on a migration. This will fix that error by changing the Migrator class initializer arguments which have changed from rails 3 to rails 4 * Refactor fact value test to not modify user_roles directly * Return external usergroupsas an array * Use eager_load to preload associations to be used in where * Auto detect jenkins rake task in application.rb and set test RAILS_ENV in that case --- Gemfile | 16 ++-- app/assets/javascripts/topbar.js | 2 +- app/controllers/api/v1/reports_controller.rb | 2 +- .../api/v2/config_reports_controller.rb | 4 +- .../api/v2/host_classes_controller.rb | 6 +- app/controllers/api/v2/models_controller.rb | 6 ++ .../api/v2/parameters_controller.rb | 5 +- app/controllers/api/v2/reports_controller.rb | 2 +- .../api/v2/lookup_keys_common_controller.rb | 59 ++++++--------- app/controllers/concerns/find_common.rb | 16 ++-- app/controllers/config_reports_controller.rb | 2 +- app/controllers/hosts_controller.rb | 6 +- app/controllers/settings_controller.rb | 2 +- app/controllers/unattended_controller.rb | 6 +- app/helpers/application_helper.rb | 8 ++ app/models/bookmark.rb | 2 +- app/models/compute_profile.rb | 1 + app/models/concerns/audit_extensions.rb | 3 +- app/models/concerns/has_many_common.rb | 10 ++- app/models/concerns/host_common.rb | 2 +- app/models/concerns/host_params.rb | 3 +- app/models/concerns/parameterizable.rb | 4 +- app/models/concerns/taxonomix.rb | 14 ++-- app/models/config_group_class.rb | 6 +- app/models/domain.rb | 2 +- app/models/environment.rb | 4 +- app/models/host/base.rb | 10 +-- app/models/host/managed.rb | 13 ++-- app/models/host_class.rb | 1 - app/models/hostgroup_class.rb | 1 - .../lookup_keys/puppetclass_lookup_key.rb | 2 +- app/models/operatingsystem.rb | 1 + app/models/puppetclass.rb | 8 +- app/models/report.rb | 2 +- app/models/subnet.rb | 2 +- app/models/user.rb | 5 +- app/models/user_mail_notification.rb | 2 +- app/models/user_role.rb | 2 +- app/models/usergroup.rb | 10 ++- app/models/usergroup_member.rb | 2 +- app/services/foreman/plugin.rb | 11 ++- app/services/tax_host.rb | 5 +- app/views/api/v2/interfaces/base.json.rabl | 1 + bundler.d/assets.rb | 15 ++-- bundler.d/console.rb | 3 - bundler.d/test.rb | 8 +- config/application.rb | 8 +- config/environments/development.rb | 12 +-- config/environments/production.rb | 5 +- config/environments/test.rb | 3 + config/initializers/0_maintain_test_schema.rb | 1 + config/initializers/1_fast_gettext.rb | 3 + config/initializers/routing_hash_for.rb | 29 +++++++ ...0444_add_look_up_key_id_to_puppet_class.rb | 1 - .../20140219183343_migrate_permissions.rb | 24 +++--- lib/foreman/logging.rb | 2 + lib/middleware/catch_json_parse_errors.rb | 2 +- lib/tasks/jenkins.rake | 11 +-- lib/tasks/plugin_assets.rake | 75 ++++++++----------- lib/tasks/test.rake | 7 -- .../api/base_controller_subclass_test.rb | 64 +++++++--------- .../smart_class_parameters_controller_test.rb | 2 +- .../api/v2/smart_proxies_controller_test.rb | 2 +- .../provisioning_templates_controller_test.rb | 2 +- test/functional/unattended_controller_test.rb | 4 +- ...custom_runner.rb => custom_runner_test.rb} | 2 + test/test_helper.rb | 6 +- test/test_runner.rb | 35 --------- test/unit/application_mailer_test.rb | 12 ++- test/unit/compute_resource_test.rb | 2 +- test/unit/fact_value_test.rb | 73 +++++++++++------- test/unit/helpers/layout_helper_test.rb | 4 +- test/unit/host_test.rb | 12 ++- 73 files changed, 366 insertions(+), 334 deletions(-) create mode 100644 config/initializers/0_maintain_test_schema.rb create mode 100644 config/initializers/routing_hash_for.rb rename test/lib/{custom_runner.rb => custom_runner_test.rb} (74%) delete mode 100644 test/test_runner.rb 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..ebc5af10c90b 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,6 +393,7 @@ def self.random_password(size = 16) end def expire_topbar_cache(sweeper) + return if sweeper.controller.nil? sweeper.expire_fragment(TopbarSweeper.fragment_name(id)) end 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..fdad5db1f00b 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_4', :require => 'jquery_pwstrength_bootstrap' 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..70af5cf3158c 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -24,18 +24,18 @@ # 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 + # Force Rails to not create an initial schema automatically. + # This is necessary to avoid Jenkins throwing an error 'schema.rb does not + # exist yet' when there is no db and it tries to run: + # bundle exec rake db:drop db:create db:migrate + # + #config.active_record.maintain_test_schema = false config.after_initialize do Bullet.enable = 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..475dc8eafe12 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -49,4 +49,7 @@ # Use separate cache stores for parallel_tests config.cache_store = :file_store, Rails.root.join("tmp", "cache", "paralleltests#{ENV['TEST_ENV_NUMBER']}") + + # Enable automatic creation/migration of the test DB when running tests + config.active_record.maintain_test_schema = true end diff --git a/config/initializers/0_maintain_test_schema.rb b/config/initializers/0_maintain_test_schema.rb new file mode 100644 index 000000000000..e487072b7399 --- /dev/null +++ b/config/initializers/0_maintain_test_schema.rb @@ -0,0 +1 @@ +ActiveRecord::Migration.maintain_test_schema! if Rails.env.test? 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..6a4d5ba88036 100644 --- a/lib/tasks/jenkins.rake +++ b/lib/tasks/jenkins.rake @@ -1,14 +1,8 @@ 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 :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'] @@ -19,7 +13,7 @@ begin 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 :rubocop do @@ -33,4 +27,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..120585c16489 100644 --- a/test/unit/fact_value_test.rb +++ b/test/unit/fact_value_test.rb @@ -121,41 +121,60 @@ def setup end 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}") + context 'taxonomies' do + setup do + @orgs = FactoryGirl.create_pair(:organization) + @locs = FactoryGirl.create_pair(:location) + end - orgs = FactoryGirl.create_pair(:organization) - locs = FactoryGirl.create_pair(:location) - target_host.update_attributes(:location => locs.last, :organization => orgs.last) + context 'limited view permissions' do + setup do + setup_user('view', 'hosts', + "hostgroup_id = #{target_host.hostgroup_id}") - 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 - end + as_admin do + target_host.location = @locs.last + target_host.organization = @orgs.last + target_host.save - 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 + hostgroup = Hostgroup.find(target_host.hostgroup_id) + hostgroup.organizations = [@orgs.last] + hostgroup.locations = [@locs.last] + hostgroup.save + end + end + + test 'user cannot view host taxonomy, my_facts is empty' do + users(:one).locations = [@locs.first] + users(:one).organizations = [@orgs.first] + + assert_equal [], FactValue.my_facts.map(&:id).sort + end + + test 'user can view host taxonomy, my_facts contains host facts' do + users(:one).locations = [@locs.last] + users(:one).organizations = [@orgs.last] + + assert_equal target_host.fact_values.map(&:id).sort, + FactValue.my_facts.map(&:id).sort + end end - end - test "only return facts from host in admin's currently selected taxonomy" do - user = as_admin { FactoryGirl.create(:user, :admin) } - orgs = FactoryGirl.create_pair(:organization) - locs = FactoryGirl.create_pair(:location) - target_host.update_attributes(:location => locs.last, :organization => orgs.last) + test "only return facts from host in admin's currently selected taxonomy" do + user = as_admin { FactoryGirl.create(:user, :admin) } + target_host.update_attributes(:location => @locs.last, :organization => @orgs.last) - as_user user do - in_taxonomy(orgs.first) do - in_taxonomy(locs.first) do - refute_includes FactValue.my_facts, target_host.fact_values.first + as_user user do + in_taxonomy(@orgs.first) do + in_taxonomy(@locs.first) do + refute_includes FactValue.my_facts, target_host.fact_values.first + end end - end - in_taxonomy(orgs.last) do - in_taxonomy(locs.last) do - assert_includes FactValue.my_facts, target_host.fact_values.first + in_taxonomy(@orgs.last) do + in_taxonomy(@locs.last) do + assert_includes FactValue.my_facts, target_host.fact_values.first + end end end end 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)