Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan
- [#91](https://github.com/kobsio/kobs/pull/91): Add force delete option for Kubernetes resources.
- [#92](https://github.com/kobsio/kobs/pull/92): Preparation to build a own version of kobs using the [kobsio/app](https://github.com/kobsio/app) template.
- [#93](https://github.com/kobsio/kobs/pull/93): Show status of Kubernetes resource in the table of the resources plugin.
- [#97](https://github.com/kobsio/kobs/pull/97): Add support for Kiali metrics.

### Fixed

Expand Down
1 change: 0 additions & 1 deletion docs/plugins/kiali.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ The following options can be used for a panel with the Kiali plugin:
| Field | Type | Description | Required |
| ----- | ---- | ----------- | -------- |
| namespaces | string | A list of namespaces for which the topology graph should be shown. | Yes |
| duration | number | The duration for the metrics in the topology chart in seconds (e.g. `900`). If no duration is provided the duration will be calculated be the selected time range in the dashboard. | No |
24 changes: 23 additions & 1 deletion plugins/kiali/kiali.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (router *Router) getGraph(w http.ResponseWriter, r *http.Request) {
appenders := r.URL.Query()["appender"]
namespaces := r.URL.Query()["namespace"]

log.WithFields(logrus.Fields{"name": name}).Tracef("getNamespaces")
log.WithFields(logrus.Fields{"name": name}).Tracef("getGraph")

i := router.getInstance(name)
if i == nil {
Expand Down Expand Up @@ -104,6 +104,27 @@ func (router *Router) getGraph(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, graph)
}

func (router *Router) getMetrics(w http.ResponseWriter, r *http.Request) {
name := chi.URLParam(r, "name")
url := r.URL.Query().Get("url")

log.WithFields(logrus.Fields{"name": name, "url": url}).Tracef("getMetrics")

i := router.getInstance(name)
if i == nil {
errresponse.Render(w, r, nil, http.StatusBadRequest, "Could not find instance name")
return
}

metrics, err := i.GetMetrics(r.Context(), url)
if err != nil {
errresponse.Render(w, r, err, http.StatusInternalServerError, "Could not get metrics")
return
}

render.JSON(w, r, metrics)
}

// Register returns a new router which can be used in the router for the kobs rest api.
func Register(clusters *clusters.Clusters, plugins *plugin.Plugins, config Config) chi.Router {
var instances []*instance.Instance
Expand Down Expand Up @@ -132,6 +153,7 @@ func Register(clusters *clusters.Clusters, plugins *plugin.Plugins, config Confi

router.Get("/namespaces/{name}", router.getNamespaces)
router.Get("/graph/{name}", router.getGraph)
router.Get("/metrics/{name}", router.getMetrics)

return router
}
1 change: 1 addition & 0 deletions plugins/kiali/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@kobsio/plugin-core": "*",
"@nivo/line": "^0.73.0",
"@patternfly/react-core": "^4.128.2",
"@patternfly/react-icons": "^4.10.11",
"@types/cytoscape": "^3.14.17",
Expand Down
16 changes: 16 additions & 0 deletions plugins/kiali/pkg/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,22 @@ func (i *Instance) GetGraph(ctx context.Context, duration int64, graphType, grou
return &graph, nil
}

// GetMetrics returns the metrics for an edge or node in the Kiali topology graph.
func (i *Instance) GetMetrics(ctx context.Context, url string) (*map[string]interface{}, error) {
body, err := i.doRequest(ctx, url)
if err != nil {
return nil, err
}

var metrics map[string]interface{}
err = json.Unmarshal(body, &metrics)
if err != nil {
return nil, err
}

return &metrics, nil
}

// New returns a new Kiali instance for the given configuration.
func New(config Config) (*Instance, error) {
roundTripper := roundtripper.DefaultRoundTripper
Expand Down
19 changes: 8 additions & 11 deletions plugins/kiali/src/components/page/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,27 @@ import React, { useEffect, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';

import GraphWrapper from '../panel/GraphWrapper';
import { IPanelOptions } from '../../utils/interfaces';
import { IOptions } from '../../utils/interfaces';
import { IPluginPageProps } from '@kobsio/plugin-core';
import PageToolbar from './PageToolbar';
import { getOptionsFromSearch } from '../../utils/helpers';

const Page: React.FunctionComponent<IPluginPageProps> = ({ name, displayName, description }: IPluginPageProps) => {
const location = useLocation();
const history = useHistory();
const [options, setOptions] = useState<IPanelOptions>(getOptionsFromSearch(location.search));
const [options, setOptions] = useState<IOptions>(getOptionsFromSearch(location.search));
const [details, setDetails] = useState<React.ReactNode>(undefined);

// changeOptions is used to change the options to get a list of traces from Jaeger. Instead of directly modifying the
// options state we change the URL parameters.
const changeOptions = (opts: IPanelOptions): void => {
const changeOptions = (opts: IOptions): void => {
const namespaces = opts.namespaces ? opts.namespaces.map((namespace) => `&namespace=${namespace}`) : [];

history.push({
pathname: location.pathname,
search: `?duration=${opts.duration}${namespaces.length > 0 ? namespaces.join('') : ''}`,
search: `?time=${opts.times.time}&timeStart=${opts.times.timeStart}&timeEnd=${opts.times.timeEnd}${
namespaces.length > 0 ? namespaces.join('') : ''
}`,
});
};

Expand All @@ -45,12 +47,7 @@ const Page: React.FunctionComponent<IPluginPageProps> = ({ name, displayName, de
{displayName}
</Title>
<p>{description}</p>
<PageToolbar
name={name}
duration={options.duration}
namespaces={options.namespaces}
setOptions={changeOptions}
/>
<PageToolbar name={name} times={options.times} namespaces={options.namespaces} setOptions={changeOptions} />
</PageSection>

<Drawer isExpanded={details !== undefined}>
Expand All @@ -61,7 +58,7 @@ const Page: React.FunctionComponent<IPluginPageProps> = ({ name, displayName, de
<GraphWrapper
name={name}
namespaces={options.namespaces}
duration={options.duration || 900}
times={options.times}
setDetails={setDetails}
/>
) : null}
Expand Down
44 changes: 34 additions & 10 deletions plugins/kiali/src/components/page/PageToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ import {
import { FilterIcon, SearchIcon } from '@patternfly/react-icons';
import React, { useState } from 'react';

import { IPanelOptions } from '../../utils/interfaces';
import PageToolbarDuration from './PageToolbarDuration';
import { IOptionsAdditionalFields, Options, TTime } from '@kobsio/plugin-core';
import { IOptions } from '../../utils/interfaces';
import PageToolbarNamespaces from './PageToolbarNamespaces';

interface IPageToolbarProps extends IPanelOptions {
interface IPageToolbarProps extends IOptions {
name: string;
setOptions: (data: IPanelOptions) => void;
setOptions: (data: IOptions) => void;
}

const PageToolbar: React.FunctionComponent<IPageToolbarProps> = ({
name,
duration,
times,
namespaces,
setOptions,
}: IPageToolbarProps) => {
const [data, setData] = useState<IPanelOptions>({
duration: duration,
const [data, setData] = useState<IOptions>({
namespaces: namespaces,
times: times,
});

// selectNamespace adds/removes the given namespace to the list of selected namespaces. When the namespace value is an
Expand All @@ -48,6 +48,28 @@ const PageToolbar: React.FunctionComponent<IPageToolbarProps> = ({
}
};

const changeOptions = (
refresh: boolean,
additionalFields: IOptionsAdditionalFields[] | undefined,
time: TTime,
timeEnd: number,
timeStart: number,
): void => {
const tmpData = { ...data };

if (refresh) {
setOptions({
...tmpData,
times: { time: time, timeEnd: timeEnd, timeStart: timeStart },
});
}

setData({
...tmpData,
times: { time: time, timeEnd: timeEnd, timeStart: timeStart },
});
};

return (
<Toolbar id="kiali-toolbar" style={{ paddingBottom: '0px', zIndex: 300 }}>
<ToolbarContent style={{ padding: '0px' }}>
Expand All @@ -57,9 +79,11 @@ const PageToolbar: React.FunctionComponent<IPageToolbarProps> = ({
<PageToolbarNamespaces name={name} namespaces={data.namespaces || []} selectNamespace={selectNamespace} />
</ToolbarItem>
<ToolbarItem>
<PageToolbarDuration
duration={data.duration || 900}
setDuration={(d: number): void => setData({ ...data, duration: d })}
<Options
time={data.times.time}
timeEnd={data.times.timeEnd}
timeStart={data.times.timeStart}
setOptions={changeOptions}
/>
</ToolbarItem>
<ToolbarItem>
Expand Down
65 changes: 0 additions & 65 deletions plugins/kiali/src/components/page/PageToolbarDuration.tsx

This file was deleted.

22 changes: 16 additions & 6 deletions plugins/kiali/src/components/panel/Graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import cytoscape from 'cytoscape';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
import dagre from 'cytoscape-dagre';

import { INodeData, INodeWrapper } from '../../utils/interfaces';
import { IEdgeWrapper, INodeData, INodeWrapper } from '../../utils/interfaces';
import Edge from './details/Edge';
import { IPluginTimes } from '@kobsio/plugin-core';
import Node from './details/Node';

cytoscape.use(dagre);
Expand Down Expand Up @@ -179,13 +180,13 @@ const nodeLabel = (node: INodeData): string => {

interface IGraphProps {
name: string;
duration: number;
times: IPluginTimes;
edges: cytoscape.ElementDefinition[];
nodes: cytoscape.ElementDefinition[];
setDetails?: (details: React.ReactNode) => void;
}

const Graph: React.FunctionComponent<IGraphProps> = ({ name, duration, edges, nodes, setDetails }: IGraphProps) => {
const Graph: React.FunctionComponent<IGraphProps> = ({ name, times, edges, nodes, setDetails }: IGraphProps) => {
const [width, setWidth] = useState<number>(0);
const [height, setHeight] = useState<number>(0);
const containerRef = useRef<HTMLDivElement>(null);
Expand All @@ -200,14 +201,23 @@ const Graph: React.FunctionComponent<IGraphProps> = ({ name, duration, edges, no
const data = ele.data();

if (data.nodeType && setDetails) {
setDetails(<Node duration={duration} name={name} node={data} close={(): void => setDetails(undefined)} />);
setDetails(
<Node
name={name}
times={times}
node={data}
nodes={nodes as INodeWrapper[]}
edges={edges as IEdgeWrapper[]}
close={(): void => setDetails(undefined)}
/>,
);
}

if (data.edgeType && setDetails) {
setDetails(
<Edge
name={name}
duration={duration}
times={times}
edge={data}
nodes={nodes as INodeWrapper[]}
close={(): void => setDetails(undefined)}
Expand All @@ -216,7 +226,7 @@ const Graph: React.FunctionComponent<IGraphProps> = ({ name, duration, edges, no
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[name, duration, nodes, setDetails],
[name, times, nodes, setDetails],
);

const cyCallback = useCallback(
Expand Down
16 changes: 13 additions & 3 deletions plugins/kiali/src/components/panel/GraphActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import { CardActions, Dropdown, DropdownItem, KebabToggle } from '@patternfly/re
import React, { useState } from 'react';
import { Link } from 'react-router-dom';

import { IPluginTimes } from '@kobsio/plugin-core';

interface IGraphActionsProps {
name: string;
namespaces: string[];
duration: number;
times: IPluginTimes;
}

export const GraphActions: React.FunctionComponent<IGraphActionsProps> = ({
name,
namespaces,
duration,
times,
}: IGraphActionsProps) => {
const [show, setShow] = useState<boolean>(false);
const namespaceParams = namespaces ? namespaces.map((namespace) => `&namespace=${namespace}`) : [];
Expand All @@ -26,7 +28,15 @@ export const GraphActions: React.FunctionComponent<IGraphActionsProps> = ({
dropdownItems={[
<DropdownItem
key={0}
component={<Link to={`/${name}?duration=${duration}${namespaceParams.join('')}`}>Explore</Link>}
component={
<Link
to={`/${name}?time=${times.time}&timeStart=${times.timeStart}&timeEnd${
times.timeEnd
}${namespaceParams.join('')}`}
>
Explore
</Link>
}
/>,
]}
/>
Expand Down
Loading