Project

General

Profile

« Previous | Next » 

Revision 26f9f557

Added by Ivan Necas almost 10 years ago

Fixes #6297 - dynflowize after-sync callbacks

Ability to trigger the sync action for already run action to finish the rest
of the orchestration.

View differences:

app/controllers/katello/api/v2/repositories_controller.rb
repo_id = params['payload']['repo_id']
task_id = params['call_report']['task_id']
task = TaskStatus.find_by_uuid(task_id)
User.current = (task && task.user) ? task.user : User.anonymous_admin
User.current = User.anonymous_admin
repo = Repository.where(:pulp_id => repo_id).first
fail _("Couldn't find repository '%s'") % repo_id if repo.nil?
Rails.logger.info("Sync_complete called for #{repo.name}, running after_sync.")
repo.async(:organization => repo.environment.organization).after_sync(task_id)
unless repo.dynflow_handled_last_sync?(task_id)
async_task(::Actions::Katello::Repository::Sync, repo, task_id)
end
render :json => {}
end
app/lib/actions/katello/repository/sync.rb
param :sync_result, Hash
end
def plan(repo)
# @param repo
# @param pulp_sync_task_id in case the sync was triggered outside
# of Katello and we just need to finish the rest of the orchestration
def plan(repo, pulp_sync_task_id = nil)
sync_task = nil
action_subject(repo)
......
end
sequence do
sync_task = plan_action(Pulp::Repository::Sync, pulp_id: repo.pulp_id)
sync_task = plan_action(Pulp::Repository::Sync, pulp_id: repo.pulp_id, task_id: pulp_sync_task_id)
concurrence do
plan_action(Katello::Repository::NodeMetadataGenerate, repo, sync_task.output[:pulp_tasks])
......
def pulp_task_id
pulp_action = planned_actions(Pulp::Repository::Sync).first
pulp_action.output[:pulp_task] &&
pulp_action.output[:pulp_task][:task_id]
if pulp_task = Array(pulp_action.external_task).first
pulp_task.fetch(:task_id)
end
end
end
end
app/lib/actions/pulp/repository/sync.rb
input_format do
param :pulp_id
param :task_id # In case we need just pair this action with existing sync task
end
def invoke_external_task
sync_options = {}
if input[:task_id]
# don't initiate, just load the existing task
task_resource.poll(input[:task_id])
else
sync_options = {}
if ::Katello.config.pulp.sync_KBlimit
# set bandwidth limit
sync_options[:max_speed] ||= ::Katello.config.pulp.sync_KBlimit
end
if ::Katello.config.pulp.sync_threads
# set threads per sync
sync_options[:num_threads] ||= ::Katello.config.pulp.sync_threads
end
if ::Katello.config.pulp.sync_KBlimit
# set bandwidth limit
sync_options[:max_speed] ||= ::Katello.config.pulp.sync_KBlimit
end
if ::Katello.config.pulp.sync_threads
# set threads per sync
sync_options[:num_threads] ||= ::Katello.config.pulp.sync_threads
end
output[:pulp_tasks] = pulp_tasks =
pulp_resources.repository.sync(input[:pulp_id], { override_config: sync_options })
pulp_tasks
output[:pulp_tasks] = pulp_tasks =
pulp_resources.repository.sync(input[:pulp_id], { override_config: sync_options })
pulp_tasks
end
end
def run_progress
app/models/katello/glue/pulp/repo.rb
return [task]
end
# Returns true if the pulp_task_id was triggered by the last synchronization
# action for the repository. Dynflow action handles the synchronization
# by it's own so no need to synchronize it again in this callback. Since the
# callbacks are run just after synchronization is finished, it should be enough
# to check for the last synchronization task.
def dynflow_handled_last_sync?(pulp_task_id)
task = ForemanTasks::Task::DynflowTask.for_action(::Actions::Katello::Repository::Sync).
for_resource(self).order(:started_at).last
return task && task.main_action.pulp_task_id == pulp_task_id
end
def handle_sync_complete_task(pulp_task_id, notifier_service = Notify)
return if dynflow_handled_last_sync?(pulp_task_id)
pulp_task = Katello.pulp_server.resources.task.poll(pulp_task_id)
if pulp_task.nil?
Rails.logger.error("Sync_complete called for #{pulp_task_id}, but no task found.")
return
end
task = PulpSyncStatus.using_pulp_task(pulp_task)
task.user ||= User.current
task.organization ||= organization
task.save!
notify = task.parameters.try(:[], :options).try(:[], :notify)
user = task.user
if task.state == TaskStatus::Status::FINISHED.to_s && task.progress.error_details[:messages].blank?
if user && notify
notifier_service.success _("Repository '%s' finished syncing successfully.") % [self.name],
:user => user, :organization => self.organization
end
else
details = []
if task.progress.error_details.present?
details = task.progress.error_details[:details].map do |error|
error[:error_message].to_s
end
else
details = task.result[:errors].flatten.map(&:chomp)
end
details = details.join("\n")
Rails.logger.error("*** Sync error: " + details)
if user && notify
notifier_service.error _("There were errors syncing repository '%s'. See notices page for more details.") % self.name,
:details => details, :user => user, :organization => self.organization
end
end
end
def clone_contents_by_filter(to_repo, content_type, filter_clauses, override_config = {})
content_classes = {
Katello::Package::CONTENT_TYPE => :rpm,
app/models/katello/repository.rb
end
end
def after_sync(pulp_task_id)
self.handle_sync_complete_task(pulp_task_id)
#don't publish as auto_publish should be enabled
self.trigger_contents_changed(:wait => false, :publish => false, :reindex => true)
Medium.update_media(self)
# Returns true if the pulp_task_id was triggered by the last synchronization
# action for the repository. Dynflow action handles the synchronization
# by it's own so no need to synchronize it again in this callback. Since the
# callbacks are run just after synchronization is finished, it should be enough
# to check for the last synchronization task.
def dynflow_handled_last_sync?(pulp_task_id)
task = ForemanTasks::Task::DynflowTask.for_action(::Actions::Katello::Repository::Sync).
for_resource(self).order(:started_at).last
return task && task.main_action.pulp_task_id == pulp_task_id
end
def as_json(*args)
test/controllers/api/v2/repositories_controller_test.rb
def test_sync_complete
token = 'imalittleteapotshortandstout'
Katello.config[:post_sync_url] = "http://foo.com/foo?token=#{token}"
TaskStatus.stubs(:find_by_uuid).returns(TaskStatus.new(:user => User.first))
Repository.stubs(:where).returns([@repository])
post :sync_complete, :token => token, :payload => {:repo_id => @repository.pulp_id}, :call_report => {}
assert_async_task ::Actions::Katello::Repository::Sync do |repo, task_id|
repo.id == @repository.id && task_id == '1234'
end
post(:sync_complete,
:token => token,
:payload => {:repo_id => @repository.pulp_id},
:call_report => {:task_id => '1234'})
assert_response :success
end
......
def test_upload_content
test_document = File.join(Engine.root, "test", "fixtures", "files", "puppet_module.tar.gz")
puppet_module = Rack::Test::UploadedFile.new(test_document, '')
Repository.any_instance.stubs(:upload_content)
post :upload_content, :id => @repository.id, :content => [puppet_module]
assert_sync_task ::Actions::Katello::Repository::UploadFiles do |repo, files|
repo.id == @repository.id &&
files.size == 1 && files.first.include?("puppet_module.tar.gz")
end
post :upload_content, :id => @repository.id, :content => [puppet_module]
assert_response :success
end
test/glue/pulp/repository_test.rb
@fedora_17_x86_64 = @@fedora_17_x86_64
@fedora_17_x86_64.relative_path = '/test_path/'
end
def test_handle_sync_complete_task
mock_notifier = Minitest::Mock.new
mock_notifier.expect(:success, nil)
task_list = @fedora_17_x86_64.sync
TaskSupport.wait_on_tasks(task_list)
@fedora_17_x86_64.handle_sync_complete_task(task_list.first.uuid, mock_notifier)
assert PulpTaskStatus.where(:uuid => task_list.first.uuid).length > 0
end
end
......
assert @@fedora_17_x86_64.last_sync
end
def test_generate_metadata
::ForemanTasks.stubs(:sync_task).returns({})
refute_empty @@fedora_17_x86_64.generate_metadata
end
def test_sync_status
assert_kind_of PulpSyncStatus, @@fedora_17_x86_64.sync_status
end
......
refute_empty categories.select { |category| category['name'] == 'all' }
end
def test_trigger_contents_changed_index_units
Katello.config.stubs(:use_elasticsearch).returns(:true)
pkg = @@fedora_17_x86_64.find_packages_by_nvre('elephant', '0.3', '0.8', '0')[0]
@@fedora_17_x86_64.expects(:generate_metadata).returns([])
Package.expects(:index_packages).with([pkg['_id']])
unit = {:checksumtype => pkg['checksumtype'], :checksum => pkg['checksum'] }
@@fedora_17_x86_64.trigger_contents_changed(:publish => true, :reindex => false, :index_units => [{:unit => unit}])
end
end

Also available in: Unified diff