Revision 35c14172
Added by Ivan Necas over 7 years ago
app/controllers/api/base_controller.rb | ||
---|---|---|
end
|
||
end
|
||
|
||
def process_success(response = nil, render_status = nil)
|
||
render_status ||= request.post? ? :created : :ok
|
||
def process_success(response = nil)
|
||
render_status = request.post? ? :created : :ok
|
||
response ||= get_resource
|
||
respond_with response, :responder => ApiResponder, :status => render_status
|
||
end
|
app/controllers/api/v2/config_reports_controller.rb | ||
---|---|---|
param_group :config_report, :as => :create
|
||
|
||
def create
|
||
import_params = { :report => params[:config_report] }
|
||
task = ForemanTasks.async_task Actions::Foreman::Report::Import, import_params, ConfigReport, detected_proxy.try(:id)
|
||
@message = _('Report import has been enqueued, please see the task %s for more details') % url_for(task)
|
||
process_success @message, :accepted
|
||
@config_report = ConfigReport.import(params[:config_report], detected_proxy.try(:id))
|
||
process_response @config_report.errors.empty?
|
||
rescue ::Foreman::Exception => e
|
||
render_message(e.to_s, :status => :unprocessable_entity)
|
||
end
|
app/controllers/api/v2/reports_controller.rb | ||
---|---|---|
param_group :report, :as => :create
|
||
|
||
def create
|
||
import_params = { :report => params[:report] }
|
||
task = ForemanTasks.async_task Actions::Foreman::Report::Import, import_params, resource_class, detected_proxy.try(:id)
|
||
@message = _('Report import has been enqueued, please see the task %s for more details') % url_for(task)
|
||
process_success @message, :accepted
|
||
@report = resource_class.import(params[:report], detected_proxy.try(:id))
|
||
process_response @report.errors.empty?
|
||
rescue ::Foreman::Exception => e
|
||
render_message(e.to_s, :status => :unprocessable_entity)
|
||
end
|
app/controllers/concerns/api/import_puppetclasses_common_controller.rb | ||
---|---|---|
param :smart_proxy_id, String, :required => false
|
||
param :environment_id, String, :required => false
|
||
param :dryrun, :bool, :required => false
|
||
param :background, :bool, :required => false
|
||
param :except, String, :required => false, :desc => N_("Optional comma-delimited string containing either 'new', 'updated', or 'obsolete' that is used to limit the imported Puppet classes")
|
||
|
||
def import_puppetclasses
|
||
... | ... | |
end
|
||
|
||
# RUN PuppetClassImporter
|
||
background = params.key?(:background) && !['false', false].include?(params[:background])
|
||
begin
|
||
task = ForemanTasks.trigger_task(background, ::Actions::Foreman::PuppetClass::Import, :changed => @changed)
|
||
if background
|
||
process_success task
|
||
else
|
||
render("api/v#{api_version}/import_puppetclasses/#{rabl_template}", :layout => "api/layouts/import_puppetclasses_layout")
|
||
end
|
||
rescue ForemanTasks::TaskError => e
|
||
render :json => { :message => _("Failed to update the environments and Puppet classes from the on-disk puppet installation: %s") % e.to_s }, :status => :internal_server_error
|
||
if (errors = ::PuppetClassImporter.new.obsolete_and_new(@changed)).empty?
|
||
render("api/v#{api_version}/import_puppetclasses/#{rabl_template}", :layout => "api/layouts/import_puppetclasses_layout")
|
||
else
|
||
render :json => {:message => _("Failed to update the environments and Puppet classes from the on-disk puppet installation: %s") % errors.join(", ")}, :status => :internal_server_error
|
||
end
|
||
end
|
||
|
app/controllers/concerns/foreman/controller/environments.rb | ||
---|---|---|
end
|
||
|
||
def obsolete_and_new
|
||
import_params = { :changed => params[:changed] }
|
||
if params[:commit] == _("Update on background")
|
||
ForemanTasks.async_task(::Actions::Foreman::PuppetClass::Import, import_params)
|
||
notice _("Added import task to the queue, it will be run shortly")
|
||
if (errors = ::PuppetClassImporter.new.obsolete_and_new(params[:changed])).empty?
|
||
notice _("Successfully updated environments and Puppet classes from the on-disk Puppet installation")
|
||
else
|
||
ForemanTasks.sync_task(::Actions::Foreman::PuppetClass::Import, import_params)
|
||
begin
|
||
notice _('Successfully updated environments and Puppet classes from the on-disk Puppet installation')
|
||
rescue ForemanTasks::TaskError
|
||
error _('Failed to update environments and Puppet classes from the Puppet installation')
|
||
end
|
||
error _("Failed to update environments and Puppet classes from the on-disk Puppet installation: %s") % errors.to_sentence
|
||
end
|
||
rescue ::Foreman::Exception => e
|
||
error _("Failed to add task to queue: %s") % e.to_s
|
||
ensure
|
||
redirect_to :controller => controller_path
|
||
end
|
||
|
app/models/config_report.rb | ||
---|---|---|
"status"
|
||
end
|
||
|
||
def self.humanized_name
|
||
N_('Config report')
|
||
end
|
||
|
||
# a method that save the report values (e.g. values from METRIC)
|
||
# it is not supported to edit status values after it has been written once.
|
||
def status=(st)
|
app/models/report.rb | ||
---|---|---|
class Report < ActiveRecord::Base
|
||
LOG_LEVELS = %w[debug info notice warning err alert emerg crit]
|
||
DEFAULT_EXPIRATION = 1.week
|
||
|
||
include Foreman::STI
|
||
include Authorizable
|
||
... | ... | |
# with_changes
|
||
scope :interesting, -> { where("status <> 0") }
|
||
|
||
def self.humanized_name
|
||
N_('Report')
|
||
end
|
||
|
||
# extracts serialized metrics and keep them as a hash_with_indifferent_access
|
||
def metrics
|
||
return {} if read_attribute(:metrics).nil?
|
||
... | ... | |
# Expire reports based on time and status
|
||
# Defaults to expire reports older than a week regardless of the status
|
||
def self.expire(conditions = {})
|
||
timerange = conditions[:timerange] || DEFAULT_EXPIRATION
|
||
timerange = conditions[:timerange] || 1.week
|
||
status = conditions[:status]
|
||
cond = "reports.created_at < \'#{(Time.now.utc - timerange).to_formatted_s(:db)}\'"
|
||
cond += " and reports.status = #{status}" unless status.nil?
|
app/services/actions/foreman/puppet_class/import.rb | ||
---|---|---|
module Actions
|
||
module Foreman
|
||
module PuppetClass
|
||
class Import < Actions::EntryAction
|
||
def resource_locks
|
||
:import_puppetclasses
|
||
end
|
||
|
||
def run
|
||
# #obsolete_and_new can return nil if there's no change so we have to be careful with to_sentence
|
||
output[:errors] = ::PuppetClassImporter.new.obsolete_and_new(input[:changed]).try(:to_sentence)
|
||
end
|
||
|
||
def humanized_output
|
||
return nil if input[:changed].nil?
|
||
|
||
humanized_output = []
|
||
humanized_output << _('Add') + ' ' + format_env_and_classes_input(input[:changed][:new]) if input[:changed][:new].present?
|
||
humanized_output << _('Remove') + ' ' + format_env_and_classes_input(input[:changed][:obsolete]) if input[:changed][:obsolete].present?
|
||
humanized_output << _('Update') + ' ' + format_env_and_classes_input(input[:changed][:updated]) if input[:changed][:updated].present?
|
||
humanized_output.join("\n")
|
||
end
|
||
|
||
def rescue_strategy
|
||
::Dynflow::Action::Rescue::Skip
|
||
end
|
||
|
||
def humanized_name
|
||
_("Import Environments and Puppet classes")
|
||
end
|
||
|
||
# default value for cleaning up the tasks, it can be overriden by settings
|
||
def self.cleanup_after
|
||
'30d'
|
||
end
|
||
|
||
private
|
||
|
||
def format_env_and_classes_input(selection)
|
||
selection.map do |environment, classes|
|
||
result = _('environment') + " #{environment}"
|
||
classes = JSON.parse(classes)
|
||
no_classes_info = classes.include?('_destroy_')
|
||
result += " (#{classes.size} " + _('classes') + ")" unless no_classes_info
|
||
result
|
||
end.join(', ')
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
app/services/actions/foreman/report/import.rb | ||
---|---|---|
module Actions
|
||
module Foreman
|
||
module Report
|
||
class Import < Actions::EntryAction
|
||
def resource_locks
|
||
:import_reports
|
||
end
|
||
|
||
def plan(params, report_class, detected_proxy_id)
|
||
plan_self :params => params, :report_class => report_class.to_s, :detected_proxy_id => detected_proxy_id
|
||
end
|
||
|
||
def run
|
||
report_class = input[:report_class].constantize
|
||
report = report_class.import(input[:params][:report], SmartProxy.find_by_id(input[:detected_proxy_id]))
|
||
if report.errors.any?
|
||
raise _('Failed importing of report: %s') % report.errors.full_messages
|
||
else
|
||
output[:report_id] = report.id
|
||
end
|
||
end
|
||
|
||
def rescue_strategy
|
||
::Dynflow::Action::Rescue::Skip
|
||
end
|
||
|
||
def humanized_name
|
||
N_("Import")
|
||
end
|
||
|
||
def humanized_input
|
||
input[:report_class].constantize.humanized_name
|
||
end
|
||
|
||
def self.cleanup_after
|
||
"#{::Report::DEFAULT_EXPIRATION / 1.day}d"
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
app/validators/bookmark_controller_validator.rb | ||
---|---|---|
class BookmarkControllerValidator < ActiveModel::EachValidator
|
||
@@active_record_tables = ActiveRecord::Base.connection.tables.map(&:to_s)
|
||
def validate_each(record, attribute, value)
|
||
controllers = ["dashboard"] + (active_record_tables + Permission.resources.map {|x| x.tableize }).uniq
|
||
controllers = ["dashboard"] + (@@active_record_tables + Permission.resources.map {|x| x.tableize }).uniq
|
||
record.errors[attribute] << _("%{value} is not a valid controller") % {:value => value } unless controllers.include?(value)
|
||
end
|
||
|
||
private
|
||
|
||
def active_record_tables
|
||
ActiveRecord::Base.connection.tables.map(&:to_s)
|
||
end
|
||
end
|
app/views/api/v2/config_reports/create.json.rabl | ||
---|---|---|
object @config_report
|
||
|
||
extends "api/v2/config_reports/show"
|
||
node(:message) { @message }
|
app/views/api/v2/reports/create.json.rabl | ||
---|---|---|
object @report
|
||
|
||
extends "api/v2/reports/show"
|
||
node(:message) { @message }
|
app/views/common/_puppetclasses_or_envs_changed.html.erb | ||
---|---|---|
<div>
|
||
<%= link_to _("Cancel"), send("#{controller_name}_path"), :class => "btn btn-default" %>
|
||
<%= submit_tag _("Update"), :class => "btn btn-primary" %>
|
||
<%= submit_tag _("Update on background"), :class => "btn btn-primary" %>
|
||
</div>
|
||
<% end %>
|
bundler.d/foreman_tasks.rb | ||
---|---|---|
group :foreman_tasks do
|
||
gem 'foreman-tasks', '>= 0.8.5'
|
||
gem 'concurrent-ruby-edge', '0.2.3'
|
||
end
|
config/application.rb | ||
---|---|---|
end
|
||
end
|
||
end
|
||
begin
|
||
Bundler.require(:foreman_tasks)
|
||
rescue LoadError => e
|
||
warn "Could not load foreman tasks, async processing will not be available: #{e.message}"
|
||
end
|
||
end
|
||
end
|
||
|
test/controllers/api/v1/smart_proxies_controller_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class Api::V1::SmartProxiesControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
valid_attrs = { :name => 'master02', :url => 'http://server:8443' }
|
||
|
||
setup do
|
test/controllers/api/v2/config_reports_controller_test.rb | ||
---|---|---|
require 'controllers/shared/report_host_permissions_test'
|
||
|
||
class Api::V2::ConfigReportsControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
include ::ReportHostPermissionsTest
|
||
|
||
describe "Non Admin User" do
|
||
... | ... | |
def test_create_invalid
|
||
User.current=nil
|
||
post :create, {:config_report => ["not a hash", "throw an error"] }, set_session_user
|
||
assert_response :success
|
||
assert_response :unprocessable_entity
|
||
end
|
||
|
||
def test_create_duplicate
|
||
... | ... | |
post :create, {:config_report => create_a_puppet_transaction_report }, set_session_user
|
||
assert_response :success
|
||
post :create, {:config_report => create_a_puppet_transaction_report }, set_session_user
|
||
assert_response :success
|
||
assert_response :unprocessable_entity
|
||
end
|
||
|
||
test 'when ":restrict_registered_smart_proxies" is false, HTTP requests should be able to create a report' do
|
||
... | ... | |
Resolv.any_instance.stubs(:getnames).returns(['else.where'])
|
||
post :create, {:config_report => create_a_puppet_transaction_report }
|
||
assert_nil @controller.detected_proxy
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
|
||
test 'hosts with a registered smart proxy on should create a report successfully' do
|
||
... | ... | |
Resolv.any_instance.stubs(:getnames).returns([host])
|
||
post :create, {:config_report => create_a_puppet_transaction_report }
|
||
assert_equal proxy, @controller.detected_proxy
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
|
||
test 'hosts without a registered smart proxy on should not be able to create a report' do
|
||
... | ... | |
@request.env['SSL_CLIENT_S_DN'] = 'CN=else.where'
|
||
@request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
|
||
post :create, {:config_report => create_a_puppet_transaction_report }
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
|
||
test 'hosts without a registered smart proxy but with an SSL cert should not be able to create a report' do
|
||
... | ... | |
|
||
Resolv.any_instance.stubs(:getnames).returns(['else.where'])
|
||
post :create, {:config_report => create_a_puppet_transaction_report }
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
end
|
||
|
test/controllers/api/v2/reports_controller_test.rb | ||
---|---|---|
require 'controllers/shared/report_host_permissions_test'
|
||
|
||
class Api::V2::ReportsControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
include ::ReportHostPermissionsTest
|
||
|
||
setup do
|
||
... | ... | |
def test_create_valid
|
||
User.current=nil
|
||
post :create, {:report => create_a_puppet_transaction_report }, set_session_user
|
||
assert_response :accepted
|
||
assert_response :success
|
||
end
|
||
|
||
def test_create_invalid
|
||
User.current=nil
|
||
post :create, {:report => ["not a hash", "throw an error"] }, set_session_user
|
||
assert_response :accepted
|
||
assert_response :unprocessable_entity
|
||
end
|
||
|
||
def test_create_duplicate
|
||
User.current=nil
|
||
post :create, {:report => create_a_puppet_transaction_report }, set_session_user
|
||
assert_response :accepted
|
||
assert_response :success
|
||
Foreman::Deprecation.expects(:api_deprecation_warning)
|
||
post :create, {:report => create_a_puppet_transaction_report }, set_session_user
|
||
assert_response :accepted
|
||
assert_response :unprocessable_entity
|
||
end
|
||
|
||
test 'when ":restrict_registered_smart_proxies" is false, HTTP requests should be able to create a report' do
|
||
... | ... | |
Resolv.any_instance.stubs(:getnames).returns(['else.where'])
|
||
post :create, {:report => create_a_puppet_transaction_report }
|
||
assert_nil @controller.detected_proxy
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
|
||
test 'hosts with a registered smart proxy on should create a report successfully' do
|
||
... | ... | |
Resolv.any_instance.stubs(:getnames).returns([host])
|
||
post :create, {:report => create_a_puppet_transaction_report }
|
||
assert_equal proxy, @controller.detected_proxy
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
|
||
test 'hosts without a registered smart proxy on should not be able to create a report' do
|
||
... | ... | |
@request.env['SSL_CLIENT_S_DN'] = 'CN=else.where'
|
||
@request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
|
||
post :create, {:report => create_a_puppet_transaction_report }
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
|
||
test 'hosts without a registered smart proxy but with an SSL cert should not be able to create a report' do
|
||
... | ... | |
|
||
Resolv.any_instance.stubs(:getnames).returns(['else.where'])
|
||
post :create, {:report => create_a_puppet_transaction_report }
|
||
assert_response :accepted
|
||
assert_response :created
|
||
end
|
||
end
|
||
|
test/controllers/api/v2/smart_proxies_controller_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class Api::V2::SmartProxiesControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
valid_attrs = { :name => 'master02', :url => 'http://server:8443' }
|
||
|
||
setup do
|
test/controllers/api/v2/template_combinations_controller_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class Api::V2::TemplateCombinationsControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
context 'with provisioning_template_id' do
|
||
setup do
|
||
Foreman::Deprecation.expects(:api_deprecation_warning).never
|
test/controllers/config_reports_controller_test.rb | ||
---|---|---|
require 'controllers/shared/report_host_permissions_test'
|
||
|
||
class ConfigReportsControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
include ::ReportHostPermissionsTest
|
||
|
||
def test_index
|
test/controllers/environments_controller_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class EnvironmentsControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
setup do
|
||
@model = Environment.first
|
||
end
|
test/controllers/puppetclasses_controller_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class PuppetclassesControllerTest < ActionController::TestCase
|
||
include ForemanTasks::TestHelpers::WithInThreadExecutor
|
||
include LookupKeysHelper
|
||
|
||
def host_attributes(host)
|
test/integration_test_helper.rb | ||
---|---|---|
|
||
class IntegrationTestWithJavascript < ActionDispatch::IntegrationTest
|
||
def login_admin
|
||
DatabaseCleaner.strategy = :truncation, { :except => ['dynflow_schema_info'] }
|
||
DatabaseCleaner.strategy = :truncation
|
||
DatabaseCleaner.start
|
||
Capybara.current_driver = Capybara.javascript_driver
|
||
super
|
test/test_helper.rb | ||
---|---|---|
require 'controllers/shared/basic_rest_response_test'
|
||
require 'facet_test_helper'
|
||
require 'active_support_test_case_helper'
|
||
require 'foreman_tasks/test_helpers'
|
||
|
||
ForemanTasks.dynflow.require!
|
||
ForemanTasks.dynflow.config.disable_active_record_actions = true
|
||
|
||
Shoulda::Matchers.configure do |config|
|
||
config.integrate do |with|
|
test/unit/actions/report/import_test.rb | ||
---|---|---|
require 'test_helper'
|
||
require 'dynflow/testing'
|
||
|
||
module Actions
|
||
module Foreman
|
||
module Report
|
||
class ImportTest < ActiveSupport::TestCase
|
||
class DummyReportClass
|
||
def self.import(*args)
|
||
end
|
||
end
|
||
|
||
include Dynflow::Testing
|
||
|
||
let(:action) do
|
||
create_action(Actions::Foreman::Report::Import)
|
||
end
|
||
|
||
let(:planned) do
|
||
plan_action action, {}, DummyReportClass, FactoryGirl.create(:smart_proxy).id
|
||
end
|
||
|
||
describe 'importing' do
|
||
it 'calls import on report class' do
|
||
DummyReportClass.expects(:import).returns(OpenStruct.new(:errors => []))
|
||
run_action planned
|
||
end
|
||
|
||
it 'raises exception if some error exists' do
|
||
DummyReportClass.expects(:import).returns(OpenStruct.new(:errors => OpenStruct.new(:any? => true, :full_messages => 'custom string')))
|
||
exception = assert_raises(RuntimeError) { run_action planned }
|
||
assert_includes exception.message, 'custom string'
|
||
end
|
||
end
|
||
end
|
||
|
||
describe 'cleanup' do
|
||
it 'derive the number of dates based on Report::DEFAULT_EXPIRATION' do
|
||
assert_equal '7d', Actions::Foreman::Report::Import.cleanup_after
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
test/unit/tasks/seeds_test.rb | ||
---|---|---|
self.use_transactional_fixtures = false
|
||
|
||
setup do
|
||
DatabaseCleaner.clean_with :truncation, :except => ['dynflow_schema_info']
|
||
DatabaseCleaner.clean_with :truncation
|
||
Setting.stubs(:[]).with(:administrator).returns("root@localhost")
|
||
Setting.stubs(:[]).with(:send_welcome_email).returns(false)
|
||
Foreman.stubs(:in_rake?).returns(true)
|
Also available in: Unified diff
Refs #15779 - make background processing unavailable for now (#4217)
The original PR got vetted in the packaging phase and including
foreman-task as dependency of Foreman was refused. We need to rethink
our approach for getting the foreman-tasks functionality available
inside the core and take less obtrusive approach by making the
transition in several steps, until the foreman core will get on
future-parity with foreman-tasks which would effectively mean tasks in
core.
To clean the tasks that were created while using the original changes,
you can run:
This reverts commits