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

logic for deprecated images #1872

Merged

Conversation

Gkrumbach07
Copy link
Member

@Gkrumbach07 Gkrumbach07 commented Sep 27, 2023

closes: #1370

Description

Added a new annotation to workbenches called opendatahub.io/image-display-name which stores the display name of the selected image. this gets used when displaying the image on the notebook table if the image itself could not be found. if it is not found it will also include the wording (deprecated).

When you got to edit this workbench with a deprecated image. the image will be unselected and require you to select a new one

image image image

How Has This Been Tested?

  1. create a custom notebook image
  2. create a workbench with that custom image
  3. delete the custom image
  4. verify that deprecated wording is on the workbench table
  5. verify that on edit, the image selection is required
  6. remove the annotation (opendatahub.io/image-display-name) from the notebook resource, and notice that the image becomes unknown on the table row

Test Impact

I added tests to check the use cases of unknown and deprecated. In doing this i felt the need to implement a few helpers for mocks. namely a opts: RecursivePartial<k8sKindType> and then lodash _.merge the base mock with the opts. this gives you the option for fine grained control without having to make a large amount of of options to feed in.

Request review criteria:

Self checklist (all need to be checked):

  • The developer has manually tested the changes and verified that the changes work
  • Commits have been squashed into descriptive, self-contained units of work (e.g. 'WIP' and 'Implements feedback' style messages have been removed)
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has added tests or explained why testing cannot be added (unit tests & storybook for related changes)

If you have UI changes:

  • Included any necessary screenshots or gifs if it was a UI change.
  • Included tags to the UX team if it was a UI/UX change (find relevant UX in the SMEs section).

After the PR is posted & before it merges:

  • The developer has tested their solution on a cluster by using the image produced by the PR to main

@Gkrumbach07
Copy link
Member Author

Gkrumbach07 commented Sep 27, 2023

UX context

This bug fixes the edge case where a user has a already created workbench, but the image tag or the entire image is removed from ODH. an example would be that an admin deleted a custom notebook image but a workbench was using it.

@kywalker-rh @xianli123 See screenshots for how it would look in the row. For edit, the image selector appears as empty and you are required to select a new image.

@kaedward In the issue you signed off on the wording Image Name (deprecated), but just a fyi in case it looks odd to you

@kywalker-rh
Copy link

Looks good to me, thanks for updating it @Gkrumbach07!

@DaoDaoNoCode
Copy link
Member

I found an issue that's not caused by your PR, but it will affect the result of your PR so you may want to update it as well here.
In useNotebookImage hook, it gets the tagSoftware here, however, this is the wrong function to use. We should use getImageVersionSoftwareString instead of getRelatedVersionDescription. When there is only one version for an image, these 2 functions get the same result. However, if there are more than one version, the second function (getRelatedVersionDescription) could return an undefined because it's only used to show the software string in the image selection dropdown.
So it you want to get a correct and exact software string of a specific image version, you might want to replace it with getImageVersionSoftwareString(imageVersion).
FYI @Gkrumbach07 because if you don't update this hook here, you will get (deprecated) tag for those multi-version images.

@Gkrumbach07
Copy link
Member Author

@DaoDaoNoCode

because if you don't update this hook here, you will get (deprecated) tag for those multi-version images.

I saw this in testing so i used an or operator here to prevent the text from only showing (deprecated). It will fall back to using the display name or in the last case Unknown

const imageDisplayName =
    notebookImage?.imageName ||
    obj.notebook.metadata.annotations['opendatahub.io/image-display-name'] ||
    'Unknown';

However that doesn't fix the case where deprecated will show even if it is not because tag software is undefined. I updated how tag software is fetched based on your comment and adjusted how deprecated is calculated

@andrewballantyne
Copy link
Member

Needs a rebase

@Gkrumbach07 Gkrumbach07 force-pushed the notebook-name-store branch 2 times, most recently from 398ee66 to 784fb70 Compare October 4, 2023 19:19
@Gkrumbach07
Copy link
Member Author

Gkrumbach07 commented Oct 5, 2023

Update

  • I have added a new state for disabled: This required me add an additional includeDisabled option for getting imagestreams because we didnt do that by default.
  • on edit of a workbench using a disabled image, I allow the user to make edits without forcing them to select a new image: This was a bit odd to do, but i just drilled down an additional prop called oringalImage which will track the disabled image option in the select field for the spawner page

These changes came from conversations in an other issue that is merging with this one

context on the merge: #1520 (comment)

Updated Images (OUTDATED)

Screenshot 2023-10-04 at 5 50 41 PM Screenshot 2023-10-05 at 7 37 54 AM

@xianli123
Copy link

@Gkrumbach07 Thanks for invloving me. I left some comments in the issue #1520 , please refer to my comments.

@DaoDaoNoCode
Copy link
Member

When the notebook image is deleted, should we also disable the toggle button so the users cannot toggle it anymore? It doesn't make sense when we tell the user they need to select another image to start the notebook while we still allow them to start it and get Error: ImagePullBackOff later.

Screenshot 2023-11-02 at 10 43 03 AM

Copy link
Member

@DaoDaoNoCode DaoDaoNoCode left a comment

Choose a reason for hiding this comment

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

Overall it's working as expected. Just left some small comments as well as the question above. Otherwise it looks good!

@kywalker-rh
Copy link

When the notebook image is deleted, should we also disable the toggle button so the users cannot toggle it anymore? It doesn't make sense when we tell the user they need to select another image to start the notebook while we still allow them to start it and get Error: ImagePullBackOff later.

Screenshot 2023-11-02 at 10 43 03 AM

I think that's a great idea... good catch @DaoDaoNoCode !

@Gkrumbach07 Gkrumbach07 force-pushed the notebook-name-store branch 2 times, most recently from 84d0ed1 to 926d69b Compare November 6, 2023 13:48
@Gkrumbach07
Copy link
Member Author

@DaoDaoNoCode everything should be addressed

Copy link
Member

@DaoDaoNoCode DaoDaoNoCode left a comment

Choose a reason for hiding this comment

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

/lgtm

@Gkrumbach07
Copy link
Member Author

@christianvogt this PR is ready for your final review

): [imageStreams: ImageStreamKind[], loaded: boolean, loadError: Error | undefined] => {
const [imageStreams, setImageStreams] = React.useState<ImageStreamKind[]>([]);
const [loaded, setLoaded] = React.useState(false);
const [loadError, setLoadError] = React.useState<Error | undefined>(undefined);

React.useEffect(() => {
if (namespace) {
getNotebookImageStreams(namespace)
getNotebookImageStreams(namespace, includeDisabled)
Copy link
Contributor

Choose a reason for hiding this comment

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

If an error occurs when includeDisabled changes and we have previously loaded data, setImageStreams will remain the old value as the catch clause does not reset the data. Also I don't think we should be setting loaded to true if we have an error. The typical pattern here sets loaded to true when data is available. Loaded state should be unaffected by error state.

Copy link
Member Author

Choose a reason for hiding this comment

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

previous logic set loaded to true regardless of the outcome. This was so we can have a state where the api is settled or not. and then error and data represent the outcome. If we only set loaded to true on success, then loaded has not value because we no longer can use it to determine if we are loading or not.

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 can however set the state back to an empty array to stop previous loaded data from lingering on error

Copy link
Member Author

Choose a reason for hiding this comment

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

actually i am just going to switch this over to useFetchState if i can so it uses that common logic

if (!loaded) {
return [null, false];
if (loadError) {
return [null, true, loadError];
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think loaded should be set to true here because this pattern would suggests that data is available.

Suggested change
return [null, true, loadError];
return [null, false, loadError];

Comment on lines 15 to 20
if (!notebook || !loaded) {
return [null, false, undefined];
}

if (!loaded) {
return [null, false];
if (loadError) {
return [null, true, loadError];
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you should handle error state before loaded state or combine all together if you allow error state to occur when loaded is 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.

now handling like this

    if (!loaded || !notebook) {
      return [null, false, loadError];
    }

return [null, false, undefined];
}
if (loadError) {
return [null, true, loadError];
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar comment elsewhere:

Suggested change
return [null, true, loadError];
return [null, false, loadError];

Comment on lines 19 to 23
if (!notebook || !loaded) {
return [null, false, undefined];
}
if (loadError) {
return [null, true, loadError];
Copy link
Contributor

Choose a reason for hiding this comment

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

Should handle error state before loaded state. But likely can combine all together if you allow error state to occur when loaded is false.

Comment on lines 14 to 15
| [notebookImage: null, loaded: false, loadError: undefined]
| [notebookImage: null, loaded: true, loadError: Error]
| [notebookImage: NotebookImage, loaded: true, loadError: undefined] => {
Copy link
Contributor

Choose a reason for hiding this comment

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

The typical pattern suggests that loaded=true implies data is available, but error state is not related to loaded state. In more generic cases, error can be present while data is available if an error occurred on an update.

Suggested change
| [notebookImage: null, loaded: false, loadError: undefined]
| [notebookImage: null, loaded: true, loadError: Error]
| [notebookImage: NotebookImage, loaded: true, loadError: undefined] => {
| [notebookImage: null, loaded: false, loadError: Error | undefined]
| [notebookImage: NotebookImage, loaded: true, loadError: undefined] => {

Comment on lines 23 to 24
| [data: null, loaded: false, loadError: undefined]
| [data: null, loaded: true, loadError: Error]
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that this traces down to useImageSteams which sets loaded to true along with an error. So the logic around this tyoe would work but I believe the pattern is to typically return an error with any value of loaded. useFetchState can return a subsequent error on refresh while loaded was previously set to true.

Suggested change
| [data: null, loaded: false, loadError: undefined]
| [data: null, loaded: true, loadError: Error]
| [data: null, loaded: false, loadError: Error | undefined]

@Gkrumbach07
Copy link
Member Author

@christianvogt i switched the logic around to use useFetchState and have loaded = true to mean there is always some data defined

@christianvogt
Copy link
Contributor

latest changes to use useFetchState look good.
/lgtm
/approve

@openshift-ci openshift-ci bot added the lgtm label Nov 8, 2023
Copy link
Contributor

openshift-ci bot commented Nov 8, 2023

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: christianvogt, DaoDaoNoCode

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

logic for deprecated images

added tests

fix annotations

made annotations land labels optional

supported disabled wording

unknown state will not use a label

Updated tests, updated UI

fix tests

small fixes

added deleted disabled

loaded always signifies data exists

moved popover
Copy link
Contributor

openshift-ci bot commented Nov 8, 2023

New changes are detected. LGTM label has been removed.

@openshift-ci openshift-ci bot added the approved label Nov 8, 2023
@openshift-merge-bot openshift-merge-bot bot merged commit 152b672 into opendatahub-io:main Nov 8, 2023
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants