Skip to content
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

Fixes #33783 - Support connected Inter-Server Sync #8821

Merged
merged 13 commits into from
Nov 3, 2021

Conversation

jturel
Copy link
Member

@jturel jturel commented Jul 8, 2020

What are the changes introduced in this pull request?

This change brings back the ability to sync Red Hat content between two Katello instances. There was a way to achieve this when we were on pulp2 but that went away due to the lack of pulp3 publishing a file structure to disk that mimics the Red Hat CDN.

It works by introducing a new CdnConfiguration model which allows the user to set the necessary information to talk to the API of another Katello. That information is used to configure a new KatelloCdn resource that extends the existing CdnResource class. By providing similar (and some new) APIs, the KatelloCdn can be used by the /repository_sets/:id/available_repositories API to know which repositories are available for enablement, and properly configure any enabled repo to pull content from the upstream instance by using the org's debug certificate as the auth mechanism.

What are the testing steps for this pull request?

Testing this requires two Katello instances- a devel box and a 4.2 box for example. Only the downstream box (devel) needs to have this change applied which also makes this feature portable to older Katellos using pulp3.

I used the following script in my own testing to execute the workflow with two orgs on a single Katello instance and it could be adapted for two boxes if you want: https://gist.github.com/jturel/2e18c3784f3abeefcbfb3905f5372e66

The workflow is:

Upstream Katello setup

  • Configure some Red Hat content. => enable a small repo like satellite-tools
  • Create a personal access token for a user who would have access to the repository sets API (could be admin...)

Downstream Katello setup

  • Apply this code change, migrate DB
  • Import a manifest which provides the same repo you enabled above
  • Create a Content Credential which has the CA certificate of the upstream server
  • Update the CdnConfiguration of your downstream org to talk to the upstream server:
curl http://localhost:3000/katello/api/v2/organizations/$ORG_ID/cdn_configuration -u admin:changeme -X PUT -H 'Content-type: application/json' \
  -d '{"username": "$UPSTREAM_KATELLO_USER'", "password": "$PERSONAL_ACCESS_TOKEN", "organization_label": "'$UPSTREAM_KATELLO_ORG_LABEL", "url": "https://$UPSTREAM_KATELLO_FQDN", "ssl_ca_credential_id": "$CONTENT_CREDENTIAL_ID"}'
  • Browse the Red Hat repositories of the downstream Katello. Expanding any repo set should call back to the API of your upstream server to fetch the available paths. If you get an error the CdnConfiguration is likely wrong. If it works - good job following my instructions so far :)

  • Try enabling a repository which is not enabled on the upstream server. You should get an intelligible error.

  • Now enable the same repository that you enabled on the upstream server at the start. It should be enable-able and you should be able to sync it. Check the traffic on your upstream server to verify. Also check the repository details and note that the upstream URL uses a path from the upstream instance rather than cdn.redhat.com

What I really want you to test

  • Analyze my design and understand how it works. Where does it fail?
  • Are there any workflows you can execute that give a bad user experience or just don't work?
  • Check the inline comments I've left on the code
  • What happens when you revert the downstream CdnConfiguration ie set everything to empty? Can you successfully sync from the Red Hat CDN again?

Copy link
Member

@jeremylenz jeremylenz left a comment

Choose a reason for hiding this comment

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

Thanks for doing this investigation work @jturel

Seems really well thought-out and straightforward. Overall it really does make a lot of sense to me, nice work! After reading the doc I think I understand (mostly)

some questions:

  • The general gist of this seems to be "If we're using the RedHat CDN, carry on as normal. But if the CDN is another satellite, do lots of certificate magic and then 2 API requests." Right? Could it be done in a single API request?
  • What is a "debug" certificate normally used for? Is there something unorthodox about using them in this way?

@jturel
Copy link
Member Author

jturel commented Aug 3, 2020

Thanks for doing this investigation work @jturel

Seems really well thought-out and straightforward. Overall it really does make a lot of sense to me, nice work! After reading the doc I think I understand (mostly)

some questions:

  • The general gist of this seems to be "If we're using the RedHat CDN, carry on as normal. But if the CDN is another satellite, do lots of certificate magic and then 2 API requests." Right? Could it be done in a single API request?

Hopefully not too much magic. Just take the certs of the upstream Satellite, create Content Credentials for them, and associate to your 'CDNConfiguration' which will manifest on the Manage Manifest modal.

Technically, it could be done with a single API call, but I think that would mean we need a new API. The approach here really keeps it simple by staying true to our current API. That said, I'll give it another hard look when I pick this back up (next sprint hopefully).

  • What is a "debug" certificate normally used for? Is there something unorthodox about using them in this way?

A debug certificate (which can be retrieved over the API -> /organizations/:id/debug_certificate) provides a way for folks to get content off their Katello without registering a content host, I guess for experimental purposes. There are probably other uses I'm not thinking of. I think it's fair to say this is a bit unorthodox because we're bringing these certs into real workflow. At the same time it's a great fit, and I don't think we're getting too coupled to the certs. We could move to some other auth mechanism in the future.

Base automatically changed from master to main January 28, 2021 17:16
Base automatically changed from main to master January 29, 2021 03:46
results = []
cdn_config = product.organization.cdn_configuration

if ::Katello::Resources::CDN::CdnResource.redhat_cdn?(cdn_config.url)
Copy link
Member

Choose a reason for hiding this comment

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

One consequence of this change is that it will assume anything that isn't 'cdn.redhat.com' is another katello instance. So something like cdn.stage.redhat.com or a manually configured http:// cdn would not work i presume (although stage is maybe the better use case). I guess the user could manually set the SETTING to their url, but i'm not sure the installer supports that. Maybe having a cdn type field or other configuration would help make this clear cut?

Copy link
Member Author

Choose a reason for hiding this comment

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

This should be addressed in the latest revision. See #redhat? method on CdnConfiguration model

@jturel jturel changed the title Inter-Server Sync concept Fixes #33783 - Support connected Inter-Server Sync Oct 25, 2021
@jturel jturel marked this pull request as ready for review October 25, 2021 23:21
@@ -93,8 +109,13 @@ def get(path, _headers = {})
net = http_downloader
path = File.join(@uri.request_uri, path)
used_url = File.join("#{@uri.scheme}://#{@uri.host}:#{@uri.port}", path)
Rails.logger.debug "CDN: Requesting path #{used_url}"
Rails.logger.info "CDN: Requesting path #{used_url}"
Copy link
Member Author

Choose a reason for hiding this comment

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

I think this is used infrequently enough to warrant info level logs. It could help debugging

end

def resolve_substitutions(cdn_resource)
Copy link
Member Author

Choose a reason for hiding this comment

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

I needed to change CdnVarSubstitutor and I got looking into this code. I thought it shouldn't be aware of any CdnResource object so I refactoried it out and into CdnVarSubstitutor


# test deleting the CA Cred...
belongs_to :ssl_ca_credential, :class_name => "Katello::ContentCredential", :inverse_of => :ssl_ca_cdn_configurations

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I should definitely add some validations here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh as in fail if content credential is not Provided and its not a redhat ?

Copy link
Member Author

Choose a reason for hiding this comment

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

See below block of validations!

Copy link
Contributor

@parthaa parthaa 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 for me. ACK

url: org.redhat_provider.repository_url || ::Katello::Resources::CDN::CdnResource.redhat_cdn_url
).first_or_create!
end
end
Copy link
Member

Choose a reason for hiding this comment

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

should we drop the redhat provider url column here?

Copy link
Member Author

@jturel jturel Nov 1, 2021

Choose a reason for hiding this comment

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

Good idea, but I I'd like to file a redmine and do it separately. Reason being is that this code might get ported back to 6.9 perhaps as a hotfix for some customers who want to sync RH content from their 7.0. In order to limit the size+risk of the change, and especially because the OrganizationCreator (thing that replaced the Org::Create dynflow task) isn't in 6.9 and moved creation of providers etc. around, I'd rather have the unused field left over in the code+db than break something. Lemme know if I'm not making any sense :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Taking a look - maybe it's not so bad

@jlsherrill
Copy link
Member

overall design looks good, couple of small questions

@jturel
Copy link
Member Author

jturel commented Nov 2, 2021

[test katello]

@jturel
Copy link
Member Author

jturel commented Nov 2, 2021

@jlsherrill updated! take a look at the top few commits

@jturel
Copy link
Member Author

jturel commented Nov 2, 2021

Ooops, fixing something :)

@jturel
Copy link
Member Author

jturel commented Nov 2, 2021

Fixed!

@@ -108,8 +108,7 @@ def upload

# repository url
if (repo_url = params[:repository_url])
@provider.repository_url = repo_url
@provider.save!
@organization.cdn_configuration.update!(url: repo_url)
Copy link
Member Author

Choose a reason for hiding this comment

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

@parthaa @jlsherrill I wonder if we should remove the repository_url param from this API as part of this change? My thinking is that this code doesn't run the CdnConfiguration::Update (previously Provider::Update) action when making the change - so I don't see its purpose. Notice that the organizations controller does run the dynflow action - and that's what the existing UI uses.

Copy link
Member Author

Choose a reason for hiding this comment

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

The API param doesn't show up currently in hammer or foreman-documentation repo so it should be safe

Copy link
Member

Choose a reason for hiding this comment

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

i think it would be fine to remove it entirely, since its broken as is

@jturel
Copy link
Member Author

jturel commented Nov 2, 2021

[test katello]

Copy link
Member

@jlsherrill jlsherrill left a comment

Choose a reason for hiding this comment

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

ACK!

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