Skip to content

Commit 41e73ec

Browse files
authored
Add Flux Plugin (#119)
The Flux plugin can be used to view and reconcile all Flux resources like Git Repositories, Helm Repositories, Kustomizations and Helm Releases. These resources can be accessed via the Flux page or they can be embedded into a dashboard via the Flux panel. To use the panel a user must set the "type" for the resources which should be displayed. He also can set the optional values for the cluster, namespace and selector. The selector will select the Flux resources by the specified label "lable=value". We also added a fix for the Kiali documentation, which indicated a wrong status of the Kiali plugin. The Kiali plugin is production ready and all planned features are implemented.
1 parent 92bae35 commit 41e73ec

35 files changed

+1388
-11
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan
1616
- [#112](https://github.com/kobsio/kobs/pull/112): Allow mapping values in Prometheus table panel.
1717
- [#113](https://github.com/kobsio/kobs/pull/113): Allow and improve customization of axis scaling.
1818
- [#116](https://github.com/kobsio/kobs/pull/116): Open details when clicking on Jaeger chart nodes.
19+
- [#119](https://github.com/kobsio/kobs/pull/119): Add Flux plugin to view and reconcile [Flux](https://fluxcd.io) resources.
1920

2021
### Fixed
2122

@@ -24,8 +25,8 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan
2425
- [#110](https://github.com/kobsio/kobs/pull/110): Fix Dashboard tabs showing wrong variables.
2526
- [#111](https://github.com/kobsio/kobs/pull/111): Fix usage of `memo` in Dashboards and fix resources table for CRDs when a value is undefined.
2627
- [#114](https://github.com/kobsio/kobs/pull/114): Fix span order and additional fields for Jaeger plugin.
27-
- [#118](https://github.com/kobsio/kobs/pull/118): Fix `null is not an object (evaluating 'e[Symbol.iterator]')` error for Prometheus charts.
2828
- [#115](https://github.com/kobsio/kobs/pull/115): Fix maximum node size of the Jaeger chart and utilize `useMemo` to cache computation for it.
29+
- [#118](https://github.com/kobsio/kobs/pull/118): Fix `null is not an object (evaluating 'e[Symbol.iterator]')` error for Prometheus charts.
2930

3031
### Changed
3132

CODE_OF_CONDUCT.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
4040

4141
## Attribution
4242

43-
This Code of Conduct is adapted from the [Contributor Covenant][https://www.contributor-covenant.org], version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).
43+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).
4444

4545
For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq).

app/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"@kobsio/plugin-core": "*",
99
"@kobsio/plugin-dashboards": "*",
1010
"@kobsio/plugin-elasticsearch": "*",
11+
"@kobsio/plugin-flux": "*",
1112
"@kobsio/plugin-jaeger": "*",
1213
"@kobsio/plugin-kiali": "*",
1314
"@kobsio/plugin-markdown": "*",

app/src/index.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import prometheusPlugin from '@kobsio/plugin-prometheus';
1414
import elasticsearchPlugin from '@kobsio/plugin-elasticsearch';
1515
import jaegerPlugin from '@kobsio/plugin-jaeger';
1616
import kialiPlugin from '@kobsio/plugin-kiali';
17-
import markdownPlugin from '@kobsio/plugin-markdown';
17+
import fluxPlugin from '@kobsio/plugin-flux';
1818
import opsgeniePlugin from '@kobsio/plugin-opsgenie';
19+
import markdownPlugin from '@kobsio/plugin-markdown';
1920
import rssPlugin from '@kobsio/plugin-rss';
2021

2122
ReactDOM.render(
@@ -29,8 +30,9 @@ ReactDOM.render(
2930
...elasticsearchPlugin,
3031
...jaegerPlugin,
3132
...kialiPlugin,
32-
...markdownPlugin,
33+
...fluxPlugin,
3334
...opsgeniePlugin,
35+
...markdownPlugin,
3436
...rssPlugin,
3537
}} />
3638
</React.StrictMode>,

cmd/kobs/plugins/plugins.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/kobsio/kobs/plugins/applications"
1515
"github.com/kobsio/kobs/plugins/dashboards"
1616
"github.com/kobsio/kobs/plugins/elasticsearch"
17+
"github.com/kobsio/kobs/plugins/flux"
1718
"github.com/kobsio/kobs/plugins/jaeger"
1819
"github.com/kobsio/kobs/plugins/kiali"
1920
"github.com/kobsio/kobs/plugins/markdown"
@@ -33,9 +34,10 @@ type Config struct {
3334
Prometheus prometheus.Config `json:"prometheus"`
3435
Elasticsearch elasticsearch.Config `json:"elasticsearch"`
3536
Jaeger jaeger.Config `json:"jaeger"`
36-
Markdown markdown.Config `json:"markdown"`
3737
Kiali kiali.Config `json:"kiali"`
38+
Flux flux.Config `json:"flux"`
3839
Opsgenie opsgenie.Config `json:"opsgenie"`
40+
Markdown markdown.Config `json:"markdown"`
3941
RSS rss.Config `json:"rss"`
4042
}
4143

@@ -68,9 +70,10 @@ func Register(clusters *clusters.Clusters, config Config) chi.Router {
6870
router.Mount(prometheus.Route, prometheus.Register(clusters, router.plugins, config.Prometheus))
6971
router.Mount(elasticsearch.Route, elasticsearch.Register(clusters, router.plugins, config.Elasticsearch))
7072
router.Mount(jaeger.Route, jaeger.Register(clusters, router.plugins, config.Jaeger))
71-
router.Mount(markdown.Route, markdown.Register(clusters, router.plugins, config.Markdown))
7273
router.Mount(kiali.Route, kiali.Register(clusters, router.plugins, config.Kiali))
74+
router.Mount(flux.Route, flux.Register(clusters, router.plugins, config.Flux))
7375
router.Mount(opsgenie.Route, opsgenie.Register(clusters, router.plugins, config.Opsgenie))
76+
router.Mount(markdown.Route, markdown.Register(clusters, router.plugins, config.Markdown))
7477
router.Mount(rss.Route, rss.Register(clusters, router.plugins, config.RSS))
7578

7679
return router

docs/plugins/assets/flux.png

157 KB
Loading

docs/plugins/assets/kiali.png

194 KB
Loading

docs/plugins/flux.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Flux
2+
3+
The Flux plugin can be used to retrieve, display and reconcile [Flux](https://fluxcd.io) resources.
4+
5+
![Flux](assets/flux.png)
6+
7+
## Options
8+
9+
The following options can be used for a panel with the Flux plugin:
10+
11+
| Field | Type | Description | Required |
12+
| ----- | ---- | ----------- | -------- |
13+
| type | string | The Flux resource which should be displayed. This must be `gitrepositories.source.toolkit.fluxcd.io/v1beta1`, `helmrepositories.source.toolkit.fluxcd.io/v1beta1`, `buckets.source.toolkit.fluxcd.io/v1beta1`, `kustomizations.kustomize.toolkit.fluxcd.io/v1beta1` or `helmreleases.helm.toolkit.fluxcd.io/v2beta1`. | Yes |
14+
| cluster | string | The cluster for which the resources should be displayed. If this is empty the cluster from the Application or Team, where the dashboard is used will be used. | No |
15+
| namespace | string | The namespace for which the resources should be displayed. If this is empty the resources will from all namespaces will be displayed. | No |
16+
| selector | string | An optional selector for the selection of Flux resources. | No |
17+
18+
For example the following dashboard shows all Kustomizations, Helm Releases, Git Repositories and Helm Repositories:
19+
20+
```yaml
21+
---
22+
apiVersion: kobs.io/v1beta1
23+
kind: Dashboard
24+
spec:
25+
rows:
26+
- size: -1
27+
panels:
28+
- title: Kustomizations
29+
plugin:
30+
name: flux
31+
options:
32+
type: kustomizations.kustomize.toolkit.fluxcd.io/v1beta1
33+
- size: -1
34+
panels:
35+
- title: Helm Releases
36+
plugin:
37+
name: flux
38+
options:
39+
type: helmreleases.helm.toolkit.fluxcd.io/v2beta1
40+
- size: -1
41+
panels:
42+
- title: Git Repositories
43+
plugin:
44+
name: flux
45+
options:
46+
type: gitrepositories.source.toolkit.fluxcd.io/v1beta1
47+
- size: -1
48+
panels:
49+
- title: Helm Repositories
50+
plugin:
51+
name: flux
52+
options:
53+
type: helmrepositories.source.toolkit.fluxcd.io/v1beta1
54+
```

docs/plugins/kiali.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# Kiali
22

3-
The Kiali plugin can be used to visualize your Istio service mesh within kobs.
3+
The Kiali plugin can be used to visualize your Istio service mesh within kobs. You can select a list of namespaces for which the topology graph from [Kiali](https://kiali.io) should be retrieved. When you select a node or edge in the topology graph you can view the detailed metrics for the selected edge or node.
44

5-
!!! note
6-
The Kiali plugin is currently under development, so that it only supports displaying the topology graph from Kiali. In the future we also want to display the charts for the traffic metrics.
5+
![Kiali](assets/kiali.png)
76

87
## Options
98

109
The following options can be used for a panel with the Kiali plugin:
1110

1211
| Field | Type | Description | Required |
1312
| ----- | ---- | ----------- | -------- |
14-
| namespaces | string | A list of namespaces for which the topology graph should be shown. | Yes |
13+
| namespaces | []string | A list of namespaces for which the topology graph should be shown. | Yes |

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ nav:
3737
- Applications: plugins/applications.md
3838
- Dashboards: plugins/dashboards.md
3939
- Elasticsearch: plugins/elasticsearch.md
40+
- Flux: plugins/flux.md
4041
- Jaeger: plugins/jaeger.md
4142
- Kiali: plugins/kiali.md
4243
- Markdown: plugins/markdown.md

plugins/flux/flux.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package flux
2+
3+
import (
4+
"github.com/kobsio/kobs/pkg/api/clusters"
5+
"github.com/kobsio/kobs/pkg/api/plugins/plugin"
6+
7+
"github.com/go-chi/chi/v5"
8+
"github.com/sirupsen/logrus"
9+
)
10+
11+
// Route is the route under which the plugin should be registered in our router for the rest api.
12+
const Route = "/flux"
13+
14+
var (
15+
log = logrus.WithFields(logrus.Fields{"package": "flux"})
16+
)
17+
18+
// Config is the structure of the configuration for the Flux plugin.
19+
type Config struct{}
20+
21+
// Router implements the router for the flux plugin, which can be registered in the router for our rest api.
22+
type Router struct {
23+
*chi.Mux
24+
clusters *clusters.Clusters
25+
config Config
26+
}
27+
28+
// Register returns a new router which can be used in the router for the kobs rest api.
29+
func Register(clusters *clusters.Clusters, plugins *plugin.Plugins, config Config) chi.Router {
30+
plugins.Append(plugin.Plugin{
31+
Name: "flux",
32+
DisplayName: "Flux",
33+
Description: "Flux is a set of continuous and progressive delivery solutions for Kubernetes.",
34+
Type: "flux",
35+
})
36+
37+
router := Router{
38+
chi.NewRouter(),
39+
clusters,
40+
config,
41+
}
42+
43+
return router
44+
}

plugins/flux/package.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "@kobsio/plugin-flux",
3+
"version": "0.0.0",
4+
"license": "MIT",
5+
"private": false,
6+
"main": "./lib/index.js",
7+
"module": "./lib-esm/index.js",
8+
"types": "./lib/index.d.ts",
9+
"scripts": {
10+
"plugin": "tsc && tsc --build tsconfig.esm.json && cp -r src/assets lib && cp -r src/assets lib-esm"
11+
},
12+
"dependencies": {
13+
"@kobsio/plugin-core": "*",
14+
"@patternfly/react-core": "^4.128.2",
15+
"@patternfly/react-icons": "^4.10.11",
16+
"@patternfly/react-table": "^4.27.24",
17+
"@types/react": "^17.0.0",
18+
"@types/react-dom": "^17.0.0",
19+
"@types/react-router-dom": "^5.1.7",
20+
"react": "^17.0.2",
21+
"react-dom": "^17.0.2",
22+
"react-query": "^3.17.2",
23+
"react-router-dom": "^5.2.0",
24+
"typescript": "^4.3.4"
25+
}
26+
}

plugins/flux/src/assets/icon.png

140 KB
Loading
+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import {
2+
Alert,
3+
AlertVariant,
4+
Drawer,
5+
DrawerContent,
6+
DrawerContentBody,
7+
PageSection,
8+
PageSectionVariants,
9+
Title,
10+
} from '@patternfly/react-core';
11+
import React, { useEffect, useState } from 'react';
12+
import { useHistory, useLocation } from 'react-router-dom';
13+
14+
import { IOptions, TType } from '../../utils/interfaces';
15+
import { IPluginPageProps } from '@kobsio/plugin-core';
16+
import PageList from './PageList';
17+
import PageToolbar from './PageToolbar';
18+
import { getOptionsFromSearch } from '../../utils/helpers';
19+
20+
const Page: React.FunctionComponent<IPluginPageProps> = ({ name, displayName, description }: IPluginPageProps) => {
21+
const history = useHistory();
22+
const location = useLocation();
23+
const [options, setOptions] = useState<IOptions>(getOptionsFromSearch(location.search));
24+
const [details, setDetails] = useState<React.ReactNode>(undefined);
25+
26+
const changeOptions = (type: TType, cluster: string): void => {
27+
history.push({
28+
pathname: location.pathname,
29+
search: `?type=${type}&cluster=${cluster}`,
30+
});
31+
};
32+
33+
// useEffect is used to change the resources state everytime the location.search parameter changes.
34+
useEffect(() => {
35+
setOptions(getOptionsFromSearch(location.search));
36+
}, [location.search]);
37+
38+
return (
39+
<React.Fragment>
40+
<PageSection variant={PageSectionVariants.light}>
41+
<Title headingLevel="h6" size="xl">
42+
{displayName}
43+
</Title>
44+
<p>{description}</p>
45+
<PageToolbar options={options} setOptions={changeOptions} />
46+
</PageSection>
47+
48+
<Drawer isExpanded={details !== undefined}>
49+
<DrawerContent panelContent={details}>
50+
<DrawerContentBody>
51+
<PageSection style={{ minHeight: '100%' }} variant={PageSectionVariants.default}>
52+
{!options || !options.cluster ? (
53+
<Alert variant={AlertVariant.info} title="Select a cluster and type">
54+
<p>Select a cluster and type from the toolbar.</p>
55+
</Alert>
56+
) : (
57+
<React.Fragment>
58+
{options.type === 'sources' ? (
59+
<React.Fragment>
60+
<PageList
61+
name={name}
62+
cluster={options.cluster}
63+
type="gitrepositories.source.toolkit.fluxcd.io/v1beta1"
64+
title="Git Repos"
65+
showDetails={setDetails}
66+
/>
67+
<p>&nbsp;</p>
68+
<PageList
69+
name={name}
70+
cluster={options.cluster}
71+
type="helmrepositories.source.toolkit.fluxcd.io/v1beta1"
72+
title="Helm Repos"
73+
showDetails={setDetails}
74+
/>
75+
<p>&nbsp;</p>
76+
<PageList
77+
name={name}
78+
cluster={options.cluster}
79+
type="buckets.source.toolkit.fluxcd.io/v1beta1"
80+
title="Buckets"
81+
showDetails={setDetails}
82+
/>
83+
</React.Fragment>
84+
) : options.type === 'kustomizations' ? (
85+
<PageList
86+
name={name}
87+
cluster={options.cluster}
88+
type="kustomizations.kustomize.toolkit.fluxcd.io/v1beta1"
89+
title="Kustomizations"
90+
showDetails={setDetails}
91+
/>
92+
) : options.type === 'helmreleases' ? (
93+
<PageList
94+
name={name}
95+
cluster={options.cluster}
96+
type="helmreleases.helm.toolkit.fluxcd.io/v2beta1"
97+
title="Helm Releases"
98+
showDetails={setDetails}
99+
/>
100+
) : null}
101+
</React.Fragment>
102+
)}
103+
</PageSection>
104+
</DrawerContentBody>
105+
</DrawerContent>
106+
</Drawer>
107+
</React.Fragment>
108+
);
109+
};
110+
111+
export default Page;

0 commit comments

Comments
 (0)