Skip to content

Add yum_repos to slice #1053

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

ShimShtein
Copy link
Member

@ShimShtein ShimShtein commented Jul 31, 2025

What are the changes introduced in this pull request?

This PR adds yum_repos node to the report, only in IoP case.

Considerations taken when implementing this change?

I did not want to disrupt the hosted use case, so added the node only if we are in IoP mode

What are the testing steps for this pull request?

Generate and upload an rh_cloud report and observe the yum_repos node under system_profile.

Summary by Sourcery

Add yum_repos reporting to the system_profile slice generator in IoP mode and update tests and factories accordingly

New Features:

  • Include a yum_repos array under system_profile when with_local_advisor_engine? is true

Enhancements:

  • Remove outdated Katello factory definitions and fix the subscription_facet factory to generate valid UUIDs

Tests:

  • Add a unit test to verify yum_repos entries in the slice generator output
  • Update existing tests to build hosts with content_facet instead of using content_view_environments directly

Copy link

sourcery-ai bot commented Jul 31, 2025

Reviewer's Guide

This PR conditionally adds a yum_repos node to system_profile in IoP mode by extending the slice generator with new reporting methods, adds a corresponding unit test, refactors Katello factories for valid UUIDs, and updates related tests to use the content_facet factory.

Sequence diagram for conditional yum_repos node addition in IoP mode

sequenceDiagram
  participant Slice
  participant Host
  participant ForemanRhCloud
  participant Stream
  participant Repo
  participant Content
  participant ContentSource

  Slice->>Host: access content_facet.bound_repositories
  alt bound_repositories present
    Slice->>ForemanRhCloud: with_local_advisor_engine?
    alt IoP mode
      Slice->>Stream: array_field('yum_repos')
      loop for each repo
        Slice->>ContentSource: load_balancer_pulp_content_url
        Slice->>Repo: generate_repo_path(content_url)
        Slice->>Stream: object()
        Slice->>Stream: simple_field('name', repo.content.name)
        Slice->>Stream: simple_field('id', repo.content.label)
        Slice->>Stream: simple_field('base_url', ...)
        Slice->>Stream: simple_field('enabled', true)
        Slice->>Stream: simple_field('gpgcheck', true, :last)
        opt not last repo
          Slice->>Stream: comma()
        end
      end
    end
  end
Loading

Class diagram for updated Slice generator with yum_repos reporting

classDiagram
  class Slice {
    +report_system_profile(host, host_ips_cache)
    +report_yum_repos(host)
    +report_yum_repo(url_prefix, repo)
    ...
  }
  Slice --> Stream : uses
  class Stream {
    +array_field(name)
    +object()
    +simple_field(name, value, last?)
    +comma()
    ...
  }
  class Host {
    +content_facet
    +content_source
    ...
  }
  Host --> ContentFacet : has
  Host --> ContentSource : has
  class ContentFacet {
    +bound_repositories
    ...
  }
  class ContentSource {
    +load_balancer_pulp_content_url
    ...
  }
  class Repo {
    +content
    +generate_repo_path(content_url)
    ...
  }
  class Content {
    +name
    +label
    +content_url
    ...
  }
  ContentFacet --> Repo : has many
  Repo --> Content : has
  Slice ..> ForemanRhCloud : calls with_local_advisor_engine?
Loading

File-Level Changes

Change Details Files
Implement yum_repos reporting in slice generator
  • Added report_yum_repos method with IoP mode guard
  • Invoked report_yum_repos in report_system_profile
  • Defined report_yum_repo to stream repository fields (name, id, base_url, enabled, gpgcheck)
lib/foreman_inventory_upload/generators/slice.rb
Add slice generator unit test for yum_repos
  • Stub with_local_advisor_engine? to simulate IoP mode
  • Build and attach a katello repository to host.content_facet
  • Render generator output and assert yum_repos array and its fields
test/unit/slice_generator_test.rb
Refactor and fix Katello factories for valid UUID
  • Removed obsolete Katello factory definitions
  • Modified subscription_facet factory under FactoryBot.modify to generate valid UUIDs
test/factories/inventory_upload_factories.rb
Update controller, service, and tag tests to use content_facet factory
  • Replaced direct content_view_environments attribute with a content_facet factory build in tests
test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb
test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb
test/unit/tags_generator_test.rb

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @ShimShtein - I've reviewed your changes - here's some feedback:

  • Consider splitting the large Katello factory clean‐up into a separate PR to keep the yum_repos feature changes focused and easier to review.
  • Add a guard for missing content_source in report_yum_repos to prevent a potential NoMethodError when bound_repositories exist but content_source is nil.
  • You could cache the load_balancer_pulp_content_url outside the loop in report_yum_repos to avoid calling it repeatedly for each repository.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider splitting the large Katello factory clean‐up into a separate PR to keep the yum_repos feature changes focused and easier to review.
- Add a guard for missing content_source in report_yum_repos to prevent a potential NoMethodError when bound_repositories exist but content_source is nil.
- You could cache the load_balancer_pulp_content_url outside the loop in report_yum_repos to avoid calling it repeatedly for each repository.

## Individual Comments

### Comment 1
<location> `lib/foreman_inventory_upload/generators/slice.rb:260` </location>
<code_context>
+
+        @stream.array_field('yum_repos') do
+          host.content_facet.bound_repositories.each_with_index do |repo, index|
+            report_yum_repo(host.content_source.load_balancer_pulp_content_url, repo)
+            @stream.comma unless index == host.content_facet.bound_repositories.count - 1
+          end
</code_context>

<issue_to_address>
Potential for nil host.content_source could cause errors.

Add a check to handle cases where `host.content_source` is nil before calling `load_balancer_pulp_content_url`. This will prevent potential runtime errors when processing hosts without a content source.
</issue_to_address>

### Comment 2
<location> `lib/foreman_inventory_upload/generators/slice.rb:270` </location>
<code_context>
+        @stream.object do
+          @stream.simple_field('name', repo.content.name)
+          @stream.simple_field('id', repo.content.label)
+          @stream.simple_field('base_url', "#{url_prefix}/#{repo.generate_repo_path(repo.content.content_url)}")
+          @stream.simple_field('enabled', true)
+          @stream.simple_field('gpgcheck', true, :last)
</code_context>

<issue_to_address>
String interpolation for base_url may result in double slashes.

Normalize `url_prefix` and the path from `generate_repo_path` to prevent double slashes in the final URL.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        @stream.object do
          @stream.simple_field('name', repo.content.name)
          @stream.simple_field('id', repo.content.label)
          @stream.simple_field('base_url', "#{url_prefix}/#{repo.generate_repo_path(repo.content.content_url)}")
          @stream.simple_field('enabled', true)
          @stream.simple_field('gpgcheck', true, :last)
        end
=======
        @stream.object do
          @stream.simple_field('name', repo.content.name)
          @stream.simple_field('id', repo.content.label)
          normalized_url_prefix = url_prefix.to_s.sub(%r{/*\z}, '')
          repo_path = repo.generate_repo_path(repo.content.content_url).to_s.sub(%r{\A/+}, '')
          @stream.simple_field('base_url', "#{normalized_url_prefix}/#{repo_path}")
          @stream.simple_field('enabled', true)
          @stream.simple_field('gpgcheck', true, :last)
        end
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `test/unit/slice_generator_test.rb:1001` </location>
<code_context>
+  test 'reports yum repos' do
</code_context>

<issue_to_address>
Missing negative and edge case tests for yum_repos reporting

Please add tests for cases where ForemanRhCloud.with_local_advisor_engine? returns false, the host has no bound repositories, and bound_repositories is empty, to ensure correct behavior in these edge scenarios.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


@stream.array_field('yum_repos') do
host.content_facet.bound_repositories.each_with_index do |repo, index|
report_yum_repo(host.content_source.load_balancer_pulp_content_url, repo)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Potential for nil host.content_source could cause errors.

Add a check to handle cases where host.content_source is nil before calling load_balancer_pulp_content_url. This will prevent potential runtime errors when processing hosts without a content source.

Comment on lines +267 to +273
@stream.object do
@stream.simple_field('name', repo.content.name)
@stream.simple_field('id', repo.content.label)
@stream.simple_field('base_url', "#{url_prefix}/#{repo.generate_repo_path(repo.content.content_url)}")
@stream.simple_field('enabled', true)
@stream.simple_field('gpgcheck', true, :last)
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): String interpolation for base_url may result in double slashes.

Normalize url_prefix and the path from generate_repo_path to prevent double slashes in the final URL.

Suggested change
@stream.object do
@stream.simple_field('name', repo.content.name)
@stream.simple_field('id', repo.content.label)
@stream.simple_field('base_url', "#{url_prefix}/#{repo.generate_repo_path(repo.content.content_url)}")
@stream.simple_field('enabled', true)
@stream.simple_field('gpgcheck', true, :last)
end
@stream.object do
@stream.simple_field('name', repo.content.name)
@stream.simple_field('id', repo.content.label)
normalized_url_prefix = url_prefix.to_s.sub(%r{/*\z}, '')
repo_path = repo.generate_repo_path(repo.content.content_url).to_s.sub(%r{\A/+}, '')
@stream.simple_field('base_url', "#{normalized_url_prefix}/#{repo_path}")
@stream.simple_field('enabled', true)
@stream.simple_field('gpgcheck', true, :last)
end

Comment on lines +1001 to +1010
test 'reports yum repos' do
ForemanRhCloud.stubs(:with_local_advisor_engine?).returns(true)
FactoryBot.create(:katello_content, cp_content_id: '1', organization: @host.organization, name: 'Test Content', label: 'test-content')
repo = FactoryBot.build(
:katello_repository,
:fedora_17_x86_64_dev,
:with_content_view,
product: FactoryBot.create(:katello_product, :redhat, :with_provider, organization: @host.organization)
)
# force-save the root repo to avoid validation errors
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Missing negative and edge case tests for yum_repos reporting

Please add tests for cases where ForemanRhCloud.with_local_advisor_engine? returns false, the host has no bound repositories, and bound_repositories is empty, to ensure correct behavior in these edge scenarios.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ShimShtein did you want to add that kind of test^

@chris1984
Copy link
Member

Starting to look at this one

Copy link
Contributor

@vkrizan vkrizan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants