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

visualize serverless function in topology #8233

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/packages/knative-plugin/src/const.ts
Expand Up @@ -25,3 +25,4 @@ export const KNATIVE_MAXSCALE_ANNOTATION = `${KNATIVE_AUTOSCALING_APIGROUP}/maxS
export const KNATIVE_CONCURRENCYTARGET_ANNOTATION = `${KNATIVE_AUTOSCALING_APIGROUP}/target`;
export const KNATIVE_CONCURRENCYUTILIZATION_ANNOTATION = `${KNATIVE_AUTOSCALING_APIGROUP}/targetUtilizationPercentage`;
export const KNATIVE_AUTOSCALEWINDOW_ANNOTATION = `${KNATIVE_AUTOSCALING_APIGROUP}/window`;
export const SERVERLESS_FUNCTION_LABEL = 'boson.dev/function';
Expand Up @@ -16,6 +16,10 @@
stroke-dasharray: $group-node-stroke-dasharray;
}

&.is-function &__bg {
fill: var(--pf-global--palette--purple-50);
}

&.is-filtered &__bg {
stroke: $filtered-stroke-color;
stroke-width: $group-node-filtered-stroke-width;
Expand Down
Expand Up @@ -32,9 +32,10 @@ import {
SHOW_LABELS_FILTER_ID,
} from '@console/topology/src/filters';
import SvgBoxedText from '@console/topology/src/components/svg/SvgBoxedText';
import { getNodeDecorators } from '@console/topology/src/components/graph-view/components/nodes/decorators/getNodeDecorators';
import { TYPE_KNATIVE_SERVICE, EVENT_MARKER_RADIUS } from '../../const';
import RevisionTrafficSourceAnchor from '../anchors/RevisionTrafficSourceAnchor';
import { getNodeDecorators } from '@console/topology/src/components/graph-view/components/nodes/decorators/getNodeDecorators';
import { isServerlessFunction } from '../../knative-topology-utils';

export type KnativeServiceGroupProps = {
element: Node;
Expand Down Expand Up @@ -119,6 +120,10 @@ const KnativeServiceGroup: React.FC<KnativeServiceGroupProps> = ({
height,
);

const typeIconClass: string = isServerlessFunction(element)
? 'icon-serverless-function'
: 'icon-knative';

return (
<Tooltip
content={tooltipLabel}
Expand Down Expand Up @@ -150,6 +155,7 @@ const KnativeServiceGroup: React.FC<KnativeServiceGroupProps> = ({
'is-highlight': canDrop || edgeDragging,
'is-dropTarget': canDrop && dropTarget,
'is-filtered': filtered,
'is-function': isServerlessFunction(element),
})}
>
<rect
Expand Down Expand Up @@ -189,7 +195,7 @@ const KnativeServiceGroup: React.FC<KnativeServiceGroupProps> = ({
paddingY={4}
kind={data.kind}
dragRef={dragLabelRef}
typeIconClass="icon-knative"
typeIconClass={typeIconClass}
>
{element.getLabel()}
</SvgBoxedText>
Expand Down
Expand Up @@ -26,7 +26,11 @@ import {
import { getImageForIconClass } from '@console/internal/components/catalog/catalog-item-icon';
import { DeploymentModel, PodModel } from '@console/internal/models';
import { RootState } from '@console/internal/redux';
import { FLAG_KNATIVE_EVENTING, CAMEL_SOURCE_INTEGRATION } from '../const';
import {
FLAG_KNATIVE_EVENTING,
CAMEL_SOURCE_INTEGRATION,
SERVERLESS_FUNCTION_LABEL,
} from '../const';
import { KnativeItem } from '../utils/get-knative-resources';
import {
KNATIVE_GROUP_NODE_HEIGHT,
Expand Down Expand Up @@ -1144,3 +1148,14 @@ export const createSinkPubSubConnection = (
const targetObj = getTopologyResourceObject(target);
return createEventingPubSubSink(resources.obj, targetObj);
};

export const isServerlessFunction = (element: Node): boolean => {
if (!element) {
return false;
}

const {
metadata: { labels },
} = getResource(element);
return !!labels?.[SERVERLESS_FUNCTION_LABEL];
};
Expand Up @@ -5,6 +5,7 @@ import {
TopologyListViewNode,
TypedResourceBadgeCell,
} from '@console/topology/src/components/list-view';
import { isServerlessFunction } from '../knative-topology-utils';

interface KnativeServiceListViewNodeProps {
item: Node;
Expand All @@ -20,8 +21,12 @@ const ObservedKnativeServiceListViewNode: React.FC<KnativeServiceListViewNodePro
}) => {
const kind = getResourceKind(item);

const typeIconClass: string = isServerlessFunction(item)
? 'icon-serverless-function'
: 'icon-knative';

const badgeCell = (
<TypedResourceBadgeCell key="type-icon" kind={kind} typeIconClass={'icon-knative'} />
<TypedResourceBadgeCell key="type-icon" kind={kind} typeIconClass={typeIconClass} />
);

return (
Expand Down
@@ -1,5 +1,6 @@
import * as _ from 'lodash';
import * as k8s from '@console/internal/module/k8s';
import { Node } from '@patternfly/react-topology';
import {
MockKnativeResources,
getEventSourceResponse,
Expand All @@ -17,11 +18,13 @@ import {
getSinkUriTopologyNodeItems,
getSinkUriTopologyEdgeItems,
isOperatorBackedKnResource,
isServerlessFunction,
} from '../../topology/knative-topology-utils';
import { EdgeType, NodeType } from '../../topology/topology-types';
import { mockServiceData, mockRevisions } from '../__mocks__/traffic-splitting-utils-mock';
import { EventSourceCronJobModel } from '../../models';
import * as knativefetchutils from '../fetch-dynamic-eventsources-utils';
import { SERVERLESS_FUNCTION_LABEL } from '../../const';

describe('knative topology utils', () => {
it('expect getKnativeServiceData to return knative resources', () => {
Expand Down Expand Up @@ -162,6 +165,28 @@ describe('knative topology utils', () => {
);
expect(isOperatorbacked).toBe(false);
});

it('expect isServerlessFunction to return false if node is undefined', () => {
expect(isServerlessFunction(undefined)).toBe(false);
});

it('expect isServerlessFunction to return false if a node does not have necessary labels', () => {
const sampleKnNode: Node = ({
getResource: () => MockKnativeResources.ksservices.data[0],
} as any) as Node;
expect(isServerlessFunction(sampleKnNode)).toBe(false);
});

it('expect isServerlessFunction to return true if a node has necessary labels', () => {
const sampleKnResource: k8s.K8sResourceKind = {
...MockKnativeResources.ksservices.data[0],
metadata: { labels: { [SERVERLESS_FUNCTION_LABEL]: 'true' } },
};
const sampleKnNode: Node = ({
getResource: () => sampleKnResource,
} as any) as Node;
expect(isServerlessFunction(sampleKnNode)).toBe(true);
});
});

describe('Knative Topology Utils', () => {
Expand Down
2 changes: 2 additions & 0 deletions frontend/public/components/catalog/catalog-item-icon.tsx
Expand Up @@ -46,6 +46,7 @@ import * as joomlaImg from '../../imgs/logos/joomla.svg';
import * as jrubyImg from '../../imgs/logos/jruby.svg';
import * as jsImg from '../../imgs/logos/js.svg';
import * as knativeImg from '../../imgs/logos/knative.svg';
import * as serverlessFuncImage from '../../imgs/logos/serverlessfx.png';
import * as kubevirtImg from '../../imgs/logos/kubevirt.svg';
import * as laravelImg from '../../imgs/logos/laravel.svg';
import * as loadBalancerImg from '../../imgs/logos/load-balancer.svg';
Expand Down Expand Up @@ -171,6 +172,7 @@ const logos = new Map<string, any>()
.set('icon-redis', redisImg)
.set('icon-rh-integration', rhIntegrationImg)
.set('icon-rh-spring-boot', rhSpringBoot)
.set('icon-serverless-function', serverlessFuncImage)
.set('icon-java', openjdkImg)
// Use the upstream icon.
.set('icon-redhat', redhatImg)
Expand Down
Binary file added frontend/public/imgs/logos/serverlessfx.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.