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

Show csv icon in topology for operator backed services #3787

Merged
merged 5 commits into from Jan 6, 2020

Conversation

rohitkrai03
Copy link
Contributor

Jira Issue - https://issues.redhat.com/browse/ODC-2455

This PR -

  • Add support to show icons from CSV data for an operator backed service.
  • Refactors the topology-utils code to include CSV data along with other resources.
  • Refactors the code to get icon for the node. It now also checks if the node is operator backed service and gets the image from CSV spec.
  • Adds a utility function for getting icon from CSV data in @console/shared.
  • Adds new unit tests for checking the node icon in topology.
  • Also fixes failing tests and updates the snapshot.

Screenshot @openshift/team-devconsole-ux -

Screenshot from 2019-12-15 23-51-45

@openshift-ci-robot openshift-ci-robot added component/dev-console Related to dev-console component/knative Related to knative-plugin component/shared Related to console-shared size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Dec 15, 2019
@rohitkrai03
Copy link
Contributor Author

/assign @christianvogt


export const getImageForCSVIcon = (csv) =>
_.get(csv, 'spec.icon')
? `data:${_.get(csv, 'spec.icon', [])[0].mediatype};base64,${
Copy link
Member

Choose a reason for hiding this comment

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

assigning default as [] so in case of default it may break as [0] would be undefined and we would access mediatype on that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

expect((topologyTransformedData[keys[0]].data as WorkloadData).builderImage).toBe(nodejsIcon);
});

it('should return builder image icon for nodejs', () => {
Copy link
Member

Choose a reason for hiding this comment

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

nit: it would be good to use different description in it block for this one and above

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, that was because of copy paste job. Updated the description.

@@ -23,4 +23,8 @@ export type OverviewItem<T = K8sResourceKind> = {
revisions?: K8sResourceKind[];
};

export type OperatorBackedServiceKindMap = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this in shared?
Seems very specific to topology.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its being used by knative-plugin as well that's why I had to add it to console-shared.

Copy link
Contributor

Choose a reason for hiding this comment

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

But knative-plugin depends on dev-console for contributing to topology.
You should be enhancing the TopologyDataObject.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not actually part of TopologyDataObject. So, moved the type definition to topology-types.ts file.

Copy link
Contributor

Choose a reason for hiding this comment

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

You're right. I misread where it was. But topology-types.ts is a better home for it.

import * as operatorLogo from '../images/operator.svg';

export const getImageForCSVIcon = (csv) =>
_.get(csv, 'spec.icon')
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of using get at three places, probably store it as a const. And to address what Jai said you can do this or something similar

const icon =  _.get(csv, 'spec.icon', []);
!_.isEmpty(icon) ?  `data:${icon[0].mediatype};base64,${icon[0].base64data}` : operatorLogo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@rohitkrai03
Copy link
Contributor Author

/retest

@rohitkrai03
Copy link
Contributor Author

/retest

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 258.51 258.51"><defs><style>.cls-1{fill:#d1d1d1;}.cls-2{fill:#8d8d8f;}</style></defs><title>Asset 4</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M129.25,20A109.1,109.1,0,0,1,206.4,206.4,109.1,109.1,0,1,1,52.11,52.11,108.45,108.45,0,0,1,129.25,20m0-20h0C58.16,0,0,58.16,0,129.25H0c0,71.09,58.16,129.26,129.25,129.26h0c71.09,0,129.26-58.17,129.26-129.26h0C258.51,58.16,200.34,0,129.25,0Z"/><path class="cls-2" d="M177.54,103.41H141.66L154.9,65.76c1.25-4.4-2.33-8.76-7.21-8.76H102.93a7.32,7.32,0,0,0-7.4,6l-10,69.61c-.59,4.17,2.89,7.89,7.4,7.89h36.9L115.55,197c-1.12,4.41,2.48,8.55,7.24,8.55a7.58,7.58,0,0,0,6.47-3.48L184,113.85C186.86,109.24,183.29,103.41,177.54,103.41Z"/></g></g></svg>
Copy link
Contributor

Choose a reason for hiding this comment

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

There are 2 other instances of what looks to be the same file:

  • public/imgs
  • packages/operator-lifecycle-management/src

Can we consolidate and settle on a single instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have another PR that touches the same area. That's why I didn't make changes there, I plan to do that in another PR. Or if the other PR gets in first I can add that change in this one.

import * as operatorLogo from '../images/operator.svg';

export const getImageForCSVIcon = (csv) => {
const icon = _.get(csv, 'spec.icon', []);
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, I think you can do this now:

Suggested change
const icon = _.get(csv, 'spec.icon', []);
const icon = csv?.spec?.icon || [];

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion. I was not aware that typescript has been upgraded in console.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, we also need to update prettier to be able to use this feature.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah interesting, I turned off my watcher for my review version of OpenShift... does it to something crazy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its throwing an error saying expression expected after the ?.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm ... I didn't see any inline eslint errors when I wrote it :/ ah well, maybe for a future time then.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now, i've broken eslint-prettier-plugin trying to update prettier. Should look at this in another PR. I can raise one after this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't bother with it. There's already a PR up to upgrade eslint. We cannot use the feature yet.

import * as _ from 'lodash';
import * as operatorLogo from '../images/operator.svg';

export const getImageForCSVIcon = (csv) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Type csv? It's a K8sResourceKind in your tests, is there a definition shared we can use? Something like ClusterServiceVersionKind? Can we import from the operator-lifecycle-manager? Is this the right type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that is the correct type. Updated it..

Copy link
Contributor

Choose a reason for hiding this comment

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

So after talking to Christian, he suggests we do not make this dependency. It pollutes what the shared package is trying to do. So in order to keep this, he suggested putting it into dev-console. Does that seem viable?

@@ -125,25 +131,33 @@ export const createTopologyNodeData = (
const deploymentsLabels = _.get(deploymentConfig, 'metadata.labels', {});
const deploymentsAnnotations = _.get(deploymentConfig, 'metadata.annotations', {});
const nodeResourceKind = _.get(deploymentConfig, 'metadata.ownerReferences[0].kind');
const operatorBackedService = nodeResourceKind in operatorBackedServiceKindMap;
const getNodeIcon = () => {
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 this was made a function? Seems like it's only used once and lazy computing isn't helping in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No specific reason for making it a function. Just didn't want to write a big ternary operator expression.

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 you need to go to either extreme... you can just create the variables inline (instead of wrapped in a function) and just use the result from the return in the spot where you call it now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

);
});
operatorBackedServiceKindMap = installedOperators.reduce((kindMap, csv) => {
_.get(csv, 'spec.customresourcedefinitions.owned').forEach((crd) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any concern that an installed operator would not have CRDs? Is this somehow guaranteed by the spec never to be missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Based on the Operator SDK - https://github.com/operator-framework/operator-sdk#workflow, there can be operators which do not provide any CRDs.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess my question is more about your _.get doesn't handle a fallback if it is missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But, I am yet to find an operator from OperatorHub which is not providing any APIs.

Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose I am being overly cautious... defaulting it to an array saves us from a NPE if it happens. 🤷‍♂ It probably isn't needed one way or the other though. Just a recommendation for being "defensive" in programming.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added default array. It's good to be cautious. :)

@rohitkrai03 rohitkrai03 force-pushed the show-csv-icon branch 2 times, most recently from 8d806a9 to 18fe2e2 Compare December 18, 2019 17:48
Comment on lines 8 to 7
export const getImageForCSVIcon = (csv: ClusterServiceVersionKind) => {
const icon: ClusterServiceVersionIcon = _.get(csv, 'spec.icon', []);
return !_.isEmpty(icon) ? `data:${icon[0].mediatype};base64,${icon[0].base64data}` : operatorLogo;
Copy link
Contributor

Choose a reason for hiding this comment

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

Importing '@console/operator-lifecycle-manager' from @console-shared is bad.
To remove this dependency, perhaps you type the param as much simpler type to match the CSV icon:

type Icon = { base64data: string; mediatype: string };

export const getOperatorIcon = (icon: Icon[]) => {

@andrewballantyne
Copy link
Contributor

/kind feature

@openshift-ci-robot openshift-ci-robot added the kind/feature Categorizes issue or PR as related to a new feature. label Jan 2, 2020
@andrewballantyne
Copy link
Contributor

/hold

@openshift-ci-robot openshift-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jan 2, 2020
Copy link
Contributor

@andrewballantyne andrewballantyne left a comment

Choose a reason for hiding this comment

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

Just some weirdness with the API


type CSVIcon = { base64data: string; mediatype: string };

export const getImageForCSVIcon = (icon: CSVIcon[]) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
export const getImageForCSVIcon = (icon: CSVIcon[]) => {
export const getImageForCSVIcons = (icons: CSVIcon[]) => {

More importantly, why are you passing an array only to grab the first one?


const csvIcon =
operatorBackedService &&
getImageForCSVIcon(_.get(operatorBackedServiceKindMap[nodeResourceKind], 'spec.icon', []));
Copy link
Contributor

Choose a reason for hiding this comment

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

Per my other comment ... Perhaps [0] here to simplify the utility api?

@andrewballantyne
Copy link
Contributor

/hold cancel
/retest
#3847 has fixed the e2e tests

@openshift-ci-robot openshift-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jan 2, 2020
@andrewballantyne
Copy link
Contributor

@rohitkrai03 needs rebase.

@rohitkrai03
Copy link
Contributor Author

/assign

@rohitkrai03 I am getting an error only when I checkout your branch (not visible on master)... it's an odd one that I don't know how you could have caused it:

image

I debugged it a bit but I'm still quite confused... essentially allModels is not defined and this is the error that gets printed out. I think this is a webpack bundle issue, but it may also be a circular reference or something. Do you experience this issue? Just loading up any cluster with this code causes it (and whitescreens the app)

@andrewballantyne Yeah, this was because of circular dependency. I encountered this on Friday and reverted back the OLM package changes. But seems like I forgot to force push the changes. SHould work now. I've updated the PR.

Copy link
Contributor

@andrewballantyne andrewballantyne left a comment

Choose a reason for hiding this comment

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

/lgtm

I don't have the powers to give the approve label in olm and shared, so @christianvogt will have to weigh in there. But looks good to me.

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Jan 6, 2020
Comment on lines 9 to 10
const mockCSV = _.cloneDeep(sampleClusterServiceVersions.data[0]);
const icon = _.get(mockCSV, 'spec.icon.0');
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need topology test data for this unit test.
Please update to use an object that matches type CSVIcon.

Looks like there is a topology specific test added later on that captures this same data flow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@openshift-ci-robot openshift-ci-robot removed the lgtm Indicates that a PR is ready to be merged. label Jan 6, 2020
@christianvogt
Copy link
Contributor

/lgtm
/approved

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Jan 6, 2020
@openshift-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: andrewballantyne, christianvogt, rohitkrai03

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

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 6, 2020
@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

6 similar comments
@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-bot
Copy link
Contributor

/retest

Please review the full test history for this PR and help us cut down flakes.

@openshift-merge-robot openshift-merge-robot merged commit e5ec73e into openshift:master Jan 6, 2020
@spadgett spadgett added this to the v4.4 milestone Jan 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. component/dev-console Related to dev-console component/knative Related to knative-plugin component/olm Related to OLM component/shared Related to console-shared kind/feature Categorizes issue or PR as related to a new feature. lgtm Indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants