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 #30129 - Improve experience around expired manifest identity certs #8774

Merged
merged 5 commits into from Jun 29, 2020

Conversation

jturel
Copy link
Member

@jturel jturel commented Jun 15, 2020

This PR improves the Subscriptions UI by:

  • removing row selection when manifest is expired (Delete is the only action done through selection)
  • disabled: add subscriptions, remove subscriptions, update subscription quantity, refresh manifest
  • adding a tooltip to the Add Subscriptions and Refresh button
  • sending a notification to the UI explaining what happened

The API now raises a 400 when performing any manifest action listed above.

It also extends the existing subs expiration notifications to include checking the upstream RHSM connection with updated messaging too.

To test you'll need an older manifest with expired identity certs, and one without expired certs to make sure I didn't break anything..

For the notifications:

bundle exec rake db:seed
bundle exec rails c
Notification.destroy_all
Katello::UINotifications::Subscriptions::ManifestExpiredWarning.deliver!

@theforeman-bot
Copy link

Issues: #30129

@@ -22,7 +22,7 @@
{
group: N_('Subscriptions'),
name: 'manifest_expired_warning',
message: N_('The manifest imported within Organization %{subject} is no longer valid. Attempted CDN access returned Forbidden. Refreshing the manifest may resolve this issue.'),
message: N_('The manifest imported within Organization %{subject} is no longer valid. Check the end date of any attached subscriptions and import a new manifest.'),
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 tried to make the message little more general since there are now two scenarios when this message sent

Copy link
Member

@ianballou ianballou left a comment

Choose a reason for hiding this comment

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

I've imported an older manifest of mine that I believe is expired. I'm seeing the following behavior with and without this PR checkout out:

  1. 401 Unauthorized pop-up after refreshing the page
  2. Katello::Errors::CandlepinError: Invalid credentials. during Actions::Candlepin::Owner::UpstreamUpdate when refreshing the manifest.
  3. Katello::UINotifications::Subscriptions::ManifestExpiredWarning.deliver! is running fine in the console but I'm not seeing a notification.

Let me know if you want to see this manifest that I'm using.

@jturel
Copy link
Member Author

jturel commented Jun 22, 2020

I've imported an older manifest of mine that I believe is expired. I'm seeing the following behavior with and without this PR checkout out:

  1. 401 Unauthorized pop-up after refreshing the page
  2. Katello::Errors::CandlepinError: Invalid credentials. during Actions::Candlepin::Owner::UpstreamUpdate when refreshing the manifest.
  3. Katello::UINotifications::Subscriptions::ManifestExpiredWarning.deliver! is running fine in the console but I'm not seeing a notification.

Let me know if you want to see this manifest that I'm using.

Sounds like you don't have the PR checked out. Assuming you do, then try restarting your rails server and killing any running Spring processes

Copy link
Member

@ianballou ianballou left a comment

Choose a reason for hiding this comment

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

Is something supposed to happen if you put in a bad CDN url? If I put google.com as my CDN I don't see any errors during a refresh. Might not be related to this PR but I did see the code was changed.

@@ -76,10 +74,6 @@ export const loadSubscriptions = (extendedParams = {}) => async (dispatch) => {
response: data,
search: extendedParams.search,
});
const poolIds = filterRHSubscriptions(data.results).map(subs => subs.id);
if (poolIds.length > 0) {
dispatch(loadAvailableQuantities({ poolIds }));
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 wanted to avoid making this API request if we already knew that making a connection to upstream RHSM would not be successful. Rather than hacking this method (my first approach) I decided to decouple loadAvailableQuantities and call it directly from SubscriptionsPage.

@@ -56,14 +65,27 @@ class SubscriptionsPage extends Component {
this.loadData();
}
}

if (hasUpstreamConnection && !prevProps.hasUpstreamConnection) {
Copy link
Member Author

Choose a reason for hiding this comment

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

When the page loads it issues a 'ping' (see new method in UpstreamSubscriptionsController) to see if we can reach the upstream. If that API fails, then we won't hit this block. That failure will bubble up as a single UI notification.

PING_UPSTREAM_SUBSCRIPTIONS_FAILURE,
} from './UpstreamSubscriptionsConstants';

export const pingUpstreamSubscriptions = () => async (dispatch) => {
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 debated whether or not to have this function do anything with redux, but it seemed to fit in nicely and it is consistent with all other actions

@ianballou
Copy link
Member

I noticed the tool-tip for refresh is blank when the manifest has been deleted upstream.

Screenshot from 2020-06-24 12-01-27

@jturel
Copy link
Member Author

jturel commented Jun 25, 2020

@ianballou this is ready to test now. I was running into some issues (merge conflicts..) and there was a Foreman change which broke the interval middleware that the Subscriptions page uses, so you'll need this PR checked out to test: theforeman/foreman#7771

The most important aspect of testing this change is making sure that the page behaves like you would expect once importing/deleting/refreshing a manifest. ie you should not be able to 'add subscriptions' if you don't have a manifest imported, or you're in disconnected mode, or you imported an expired or deleted manifest. Err on the side of caution and let me know if you see anything 'off'!

Copy link
Member

@ianballou ianballou left a comment

Choose a reason for hiding this comment

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

If the manifest is bad, should we not block uploading a new one? I have to delete my manifest before uploading the good one.

Granted, the new manifest is a completely different manifest from the old one. Maybe that doesn't have to matter?

@ianballou
Copy link
Member

I haven't seen any weird behavior during my testing, so I'll read through the code tomorrow and finish up my review.

@jturel
Copy link
Member Author

jturel commented Jun 25, 2020

If the manifest is bad, should we not block uploading a new one? I have to delete my manifest before uploading the good one.

Granted, the new manifest is a completely different manifest from the old one. Maybe that doesn't have to matter?

None of the possible manifest states prevent you from uploading a new manifest, and the only way to correct any manifest problem is to upload a new manifest (or refresh, but we're mostly talking about cases where RHSM cannot be reached in order to refresh). Not sure if I answered your question - lemme know

@ianballou
Copy link
Member

ianballou commented Jun 25, 2020

@jturel my question came from noticing that, when I tried to upload a new manifest, it failed with this warning: "Import is older than existing data". It's a different manifest, but I do know that it's not expired at least. I had to delete my old manifest first. But perhaps since it's an unrelated manifest this use case doesn't matter.

@jturel
Copy link
Member Author

jturel commented Jun 26, 2020

@jturel my question came from noticing that, when I tried to upload a new manifest, it failed with this warning: "Import is older than existing data". It's a different manifest, but I do know that it's not expired at least. I had to delete my old manifest first. But perhaps since it's an unrelated manifest this use case doesn't matter.

Ah ok, this is not Katello behavior but Candlepin behavior. Candlepin thinks that the manifest you're trying to import is older than the currently imported one though I'm not 100% sure what that is triggered by. I'm guessing that they have some overlap in subscription data, and the data in the working manifest is older than what you already have imported.

@ianballou
Copy link
Member

@jturel that makes sense, so that was my last question functionality-wise then.

@jturel
Copy link
Member Author

jturel commented Jun 26, 2020

@ianballou i pushed one (hopefully) final separate commit to handle a non-obvious problem. There was a race condition where we'd try to load the 'available quantities' (this data is used when modifying the 'Entitlements' value of a Red Hat subscription on /subscriptions) before the subscriptions have loaded. Now it will load on any change in the subscriptions data (any manifest action or changing the table page) or if we haven't loaded the quantities before. However the API call is only issued if we have subscription data in the first place.

It didn't happen every page load, but you can see the problem sometimes if you watch your network tab and refresh the page with a valid manifest imported. there should be a request to to /upstream_subscriptions (vs /upstream_subscriptions/ping) but sometimes it never fired.

Copy link
Member

@ianballou ianballou left a comment

Choose a reason for hiding this comment

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

Everything is looking okay to me! Functionally it's working how I expect and the code looks fine. I'm not as great at judging the JavaScript, so not sure if we need a second opinion on that. Otherwise, ACK.

@jturel
Copy link
Member Author

jturel commented Jun 29, 2020

Everything is looking okay to me! Functionally it's working how I expect and the code looks fine. I'm not as great at judging the JavaScript, so not sure if we need a second opinion on that. Otherwise, ACK.

Awesome! @jeremylenz would you mind giving the react code here a quick glance? SubscriptionsPage has the interesting part of the js changes

@@ -56,6 +70,24 @@ class SubscriptionsPage extends Component {
if (!prevProps.organization || prevProps.organization.id !== organization.id) {
this.loadData();
}

if (disconnected === false && disconnected !== prevProps.settings.disconnected) {
Copy link
Contributor

Choose a reason for hiding this comment

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

any reason to not use !disconnected here? if (!disconnected && disconnected !== prevProps.settings.disconnected)

Copy link
Member Author

Choose a reason for hiding this comment

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

When I wrote it that way I saw that disconnected was coming through as undefined (i didn't want the conditional to evaluate true when disconnected changed from undefined to false). I also had to rebase this PR on some recent changes you made which changed how the disconnected setting got loaded and where in the props it came from. I also have to cherry-pick this back into 3.16 which has the 'old' disconnected prop. For those reasons I chose to be as explicit as possible.

In order for disconnected to not start as undefined I think it needs a default state set since it's coming from redux and the default prop is basically ignored, is that right? If so, I'm hesitant to make that change here since I want to avoid more merge conflicts when I pick it to 3.16

Bet you weren't expecting such a long answer to this question! 😄

Copy link
Contributor

Choose a reason for hiding this comment

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

In order for disconnected to not start as undefined I think it needs a default state set since it's coming from redux and the default prop is basically ignored, is that right?

Ya that sounds likely.

Ok, that is fine, I don't see an issue checking it explicitly, we care about a boolean false value rather than a falsey one. Thanks for the explanation! 👍

Copy link
Member

Choose a reason for hiding this comment

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

@jturel Default prop-types will get set on the component regardless of Redux, so they wouldn't be ignored.

  1. When making the connected component, Redux runs mapStateToProps and assigns props from the Redux store accordingly.
  2. If one of those values from the Redux store isn't defined, the component won't receive that prop, and so will look to prop-types.
  3. If prop-types has a default PropType value for that prop, it will get assigned to the component.

Even so I don't see any harm in being explicit with disconnected === false.

Copy link
Member Author

Choose a reason for hiding this comment

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

that makes sense. weird though - i definitely saw that disconnected was undefined. at least it works fine regardless :)

@johnpmitsch
Copy link
Contributor

Just one small comment but the rest of the React changes look good 👍

@jturel
Copy link
Member Author

jturel commented Jun 29, 2020

Thanks @ianballou and @johnpmitsch ! merging

@jturel jturel merged commit 70ae87c into Katello:master Jun 29, 2020
@jturel jturel deleted the expired_manifest branch June 29, 2020 15:00
jturel added a commit to jturel/katello that referenced this pull request Jun 29, 2020
…rts (Katello#8774)

* Fixes #30129 - Improve experience around expired and deleted manifests

* Refs #30129 - catch all errors from upstream connection checker for notifications

* Refs #30129 - ensure available quantities get loaded

* Refs #30129 - don't deliver notifications to orgs without a manifest

* Refs #30129 - fix candlepin resource test
(cherry picked from commit 70ae87c)

Conflicts:
	webpack/scenes/Subscriptions/SubscriptionsPage.js
	webpack/scenes/Subscriptions/SubscriptionsSelectors.js
	webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap
	webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap
jturel added a commit to jturel/katello that referenced this pull request Jul 1, 2020
…rts (Katello#8774)

* Fixes #30129 - Improve experience around expired and deleted manifests

* Refs #30129 - catch all errors from upstream connection checker for notifications

* Refs #30129 - ensure available quantities get loaded

* Refs #30129 - don't deliver notifications to orgs without a manifest

* Refs #30129 - fix candlepin resource test
(cherry picked from commit 70ae87c)

Conflicts:
	webpack/scenes/Subscriptions/SubscriptionsPage.js
	webpack/scenes/Subscriptions/SubscriptionsSelectors.js
	webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap
	webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap
jturel added a commit that referenced this pull request Jul 1, 2020
…rts (#8774)

* Fixes #30129 - Improve experience around expired and deleted manifests

* Refs #30129 - catch all errors from upstream connection checker for notifications

* Refs #30129 - ensure available quantities get loaded

* Refs #30129 - don't deliver notifications to orgs without a manifest

* Refs #30129 - fix candlepin resource test
(cherry picked from commit 70ae87c)

Conflicts:
	webpack/scenes/Subscriptions/SubscriptionsPage.js
	webpack/scenes/Subscriptions/SubscriptionsSelectors.js
	webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap
	webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap
lhellebr added a commit to lhellebr/robottelo that referenced this pull request Oct 14, 2020
Changes and their source:
/api/hosts/:host_id/subscriptions/events is marked as deprecated in 6.7;
reports dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791658;
scap_content_profiles in https://github.com/theforeman/foreman_openscap/pull/431/files;
override_values is in 6.7 already;
template=>templates is https://projects.theforeman.org/issues/28750/ (only category name changed, path is same);
status dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791656;
available_virtual_machines added in https://projects.theforeman.org/issues/28548;
recurring logics bulk_destroy added in theforeman/foreman-tasks#501;
bulk_cancel added in theforeman/foreman-tasks#516;
bulk_stop added in theforeman/foreman-tasks#543;
ansible_inventories endpoints added in https://github.com/theforeman/foreman_ansible/pull/265/files;
added /ansible/ prefix to ansible_inventory in https://bugzilla.redhat.com/show_bug.cgi?id=1677907;
docker_tags/:id/repositories added in Katello/katello#8658;
/api/hosts/:host_id/traces/resolve added in Katello/katello#8945;
autoattach_subscriptions marked as deprecated in 6.7;
/katello/api/subscriptions was there in 6.7;
template_combinations deprecated and changed to different paths;
upstream_subscriptions added in Katello/katello#8774;
https://bugzilla.redhat.com/show_bug.cgi?id=1887932 workarounded;
mail_notifications added in theforeman/foreman#7549
lhellebr added a commit to lhellebr/robottelo that referenced this pull request Oct 14, 2020
Changes and their source:
/api/hosts/:host_id/subscriptions/events is marked as deprecated in 6.7;
reports dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791658;
scap_content_profiles in https://github.com/theforeman/foreman_openscap/pull/431/files;
override_values is in 6.7 already;
template=>templates is https://projects.theforeman.org/issues/28750/ (only category name changed, path is same);
status dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791656;
available_virtual_machines added in https://projects.theforeman.org/issues/28548;
recurring logics bulk_destroy added in theforeman/foreman-tasks#501;
bulk_cancel added in theforeman/foreman-tasks#516;
bulk_stop added in theforeman/foreman-tasks#543;
ansible_inventories endpoints added in https://github.com/theforeman/foreman_ansible/pull/265/files;
added /ansible/ prefix to ansible_inventory in https://bugzilla.redhat.com/show_bug.cgi?id=1677907;
docker_tags/:id/repositories added in Katello/katello#8658;
/api/hosts/:host_id/traces/resolve added in Katello/katello#8945;
autoattach_subscriptions marked as deprecated in 6.7;
/katello/api/subscriptions was there in 6.7;
template_combinations deprecated and changed to different paths;
upstream_subscriptions added in Katello/katello#8774;
https://bugzilla.redhat.com/show_bug.cgi?id=1887932 workarounded;
mail_notifications added in theforeman/foreman#7549
lhellebr added a commit to lhellebr/robottelo that referenced this pull request Oct 19, 2020
Changes and their source:
/api/hosts/:host_id/subscriptions/events is marked as deprecated in 6.7;
reports dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791658;
scap_content_profiles in https://github.com/theforeman/foreman_openscap/pull/431/files;
override_values is in 6.7 already;
template=>templates is https://projects.theforeman.org/issues/28750/ (only category name changed, path is same);
status dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791656;
available_virtual_machines added in https://projects.theforeman.org/issues/28548;
recurring logics bulk_destroy added in theforeman/foreman-tasks#501;
bulk_cancel added in theforeman/foreman-tasks#516;
bulk_stop added in theforeman/foreman-tasks#543;
ansible_inventories endpoints added in https://github.com/theforeman/foreman_ansible/pull/265/files;
added /ansible/ prefix to ansible_inventory in https://bugzilla.redhat.com/show_bug.cgi?id=1677907;
docker_tags/:id/repositories added in Katello/katello#8658;
/api/hosts/:host_id/traces/resolve added in Katello/katello#8945;
autoattach_subscriptions marked as deprecated in 6.7;
/katello/api/subscriptions was there in 6.7;
template_combinations deprecated and changed to different paths;
upstream_subscriptions added in Katello/katello#8774;
https://bugzilla.redhat.com/show_bug.cgi?id=1887932 workarounded;
mail_notifications added in theforeman/foreman#7549
lhellebr added a commit to lhellebr/robottelo that referenced this pull request Oct 19, 2020
Changes and their source:
/api/hosts/:host_id/subscriptions/events is marked as deprecated in 6.7;
reports dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791658;
scap_content_profiles in https://github.com/theforeman/foreman_openscap/pull/431/files;
override_values is in 6.7 already;
template=>templates is https://projects.theforeman.org/issues/28750/ (only category name changed, path is same);
status dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791656;
available_virtual_machines added in https://projects.theforeman.org/issues/28548;
recurring logics bulk_destroy added in theforeman/foreman-tasks#501;
bulk_cancel added in theforeman/foreman-tasks#516;
bulk_stop added in theforeman/foreman-tasks#543;
ansible_inventories endpoints added in https://github.com/theforeman/foreman_ansible/pull/265/files;
added /ansible/ prefix to ansible_inventory in https://bugzilla.redhat.com/show_bug.cgi?id=1677907;
docker_tags/:id/repositories added in Katello/katello#8658;
/api/hosts/:host_id/traces/resolve added in Katello/katello#8945;
autoattach_subscriptions marked as deprecated in 6.7;
/katello/api/subscriptions was there in 6.7;
template_combinations deprecated and changed to different paths;
upstream_subscriptions added in Katello/katello#8774;
https://bugzilla.redhat.com/show_bug.cgi?id=1887932 workarounded;
mail_notifications added in theforeman/foreman#7549
mirekdlugosz pushed a commit to SatelliteQE/robottelo that referenced this pull request Oct 20, 2020
Changes and their source:
/api/hosts/:host_id/subscriptions/events is marked as deprecated in 6.7;
reports dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791658;
scap_content_profiles in https://github.com/theforeman/foreman_openscap/pull/431/files;
override_values is in 6.7 already;
template=>templates is https://projects.theforeman.org/issues/28750/ (only category name changed, path is same);
status dropped in https://bugzilla.redhat.com/show_bug.cgi?id=1791656;
available_virtual_machines added in https://projects.theforeman.org/issues/28548;
recurring logics bulk_destroy added in theforeman/foreman-tasks#501;
bulk_cancel added in theforeman/foreman-tasks#516;
bulk_stop added in theforeman/foreman-tasks#543;
ansible_inventories endpoints added in https://github.com/theforeman/foreman_ansible/pull/265/files;
added /ansible/ prefix to ansible_inventory in https://bugzilla.redhat.com/show_bug.cgi?id=1677907;
docker_tags/:id/repositories added in Katello/katello#8658;
/api/hosts/:host_id/traces/resolve added in Katello/katello#8945;
autoattach_subscriptions marked as deprecated in 6.7;
/katello/api/subscriptions was there in 6.7;
template_combinations deprecated and changed to different paths;
upstream_subscriptions added in Katello/katello#8774;
https://bugzilla.redhat.com/show_bug.cgi?id=1887932 workarounded;
mail_notifications added in theforeman/foreman#7549
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants