Skip to content

Commit

Permalink
Refs #37785 - Race condition during container push
Browse files Browse the repository at this point in the history
  • Loading branch information
sjha4 committed Sep 27, 2024
1 parent 9456160 commit d9293eb
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ def create_container_repo_if_needed
container_push_name: @container_path_input,
container_push_name_format: @container_push_name_format
)
sync_task(::Actions::Katello::Repository::CreateRoot, root, @container_path_input)
sync_task(::Actions::Katello::Repository::CreateContainerPushRoot, root, @container_path_input)
end
end

Expand Down
44 changes: 44 additions & 0 deletions app/lib/actions/katello/repository/create_container_push_root.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Actions
module Katello
module Repository
class CreateContainerPushRoot < Actions::EntryAction
def plan(root, relative_path = nil)
repository = ::Katello::Repository.new(:environment => root.organization.library, :content_view_version => root.organization.library.default_content_view_version, :root => root)
#Container push may concurrently call root add several times before the db can update.
# If the root already exists, we can skip the creation of the root and repository.
# We acquire a lock on the product to ensure that the root is not created multiple times by different workers.

root.product.with_lock do
begin
root.save!
rescue ActiveRecord::RecordInvalid => e
if root.is_container_push && e.message.include?("Name has already been taken for this product")
Rails.logger.debug("Skipping root repository creation as container push root repository already exists: #{root.container_push_name}")
return
end
raise e
end
repository.container_repository_name = relative_path if root.docker? && root.is_container_push
repository.relative_path = relative_path || repository.custom_repo_path
begin
repository.save!
rescue ActiveRecord::RecordInvalid => e
if root.is_container_push && e.message.include?("Container Repository Name") && e.message.include?("conflicts with an existing repository")
Rails.logger.debug("Skipping repository creation as container push repository already exists: #{root.container_push_name}")
return
end
raise e
end
end

action_subject(repository)
plan_action(::Actions::Katello::Repository::Create, repository)
end

def humanized_name
_("Create Container Push Repository Root")
end
end
end
end
end
20 changes: 5 additions & 15 deletions app/lib/actions/katello/repository/create_root.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,13 @@ module Actions
module Katello
module Repository
class CreateRoot < Actions::EntryAction
def plan(root, relative_path = nil)
begin
root.save!
rescue ActiveRecord::RecordInvalid => e
if root.is_container_push && e.message.include?("Container Repository Name") && e.message.include?("conflicts with an existing repository")
logger.warn("Skipping repository creation as container push repository already exists: #{root.container_push_name}")
return
end
raise e
end
def plan(root)
root.save!
repository = ::Katello::Repository.new(:environment => root.organization.library,
:content_view_version => root.organization.library.default_content_view_version,
:root => root)
repository.container_repository_name = relative_path if root.docker? && root.is_container_push
repository.relative_path = relative_path || repository.custom_repo_path
:content_view_version => root.organization.library.default_content_view_version,
:root => root)
repository.relative_path = repository.custom_repo_path
repository.save!

action_subject(repository)
plan_action(::Actions::Katello::Repository::Create, repository)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ def setup_permissions
@controller.instance_variable_set(:@container_path_input, container_push_name)
@controller.instance_variable_set(:@container_push_name_format, container_push_name_format)
@controller.expects(:sync_task).with(
::Actions::Katello::Repository::CreateRoot,
::Actions::Katello::Repository::CreateContainerPushRoot,
mock_root_repo,
container_push_name
).returns(true)
Expand Down

0 comments on commit d9293eb

Please sign in to comment.