├── coverage ├── lcov.info ├── coverage-final.json ├── lcov-report │ ├── favicon.png │ ├── sort-arrow-sprite.png │ ├── prettify.css │ ├── block-navigation.js │ └── index.html └── clover.xml ├── client ├── metricspage │ └── components │ │ ├── CPUUsageByNode.js │ │ ├── BytesReceivedByNode.js │ │ ├── FreeMemoryByNode.js │ │ ├── PodMetrics │ │ ├── FreeMemoryByPod.js │ │ ├── CPUUsageByPod.js │ │ ├── BytesReceivedByPod.js │ │ ├── BytesTransmittedbyPod.js │ │ └── MemoryUsageByPod.js │ │ ├── NodeMetrics │ │ ├── CPUUsageByNode.js │ │ ├── BytesReceivedByNode.js │ │ ├── BytesTransmittedByNode.js │ │ └── MemoryUsageByNode.js │ │ └── NamespaceMetrics │ │ ├── CPUUsageByNamespace.js │ │ ├── BytesTransmittedByNamespace.js │ │ ├── BytesReceivedByNamespace.js │ │ └── MemoryUsageByNamespace.js ├── actions │ ├── constants │ │ ├── chartConstants.js │ │ └── actionTypes.js │ └── actions.js ├── .DS_Store ├── store.js ├── styles.css ├── index.js ├── utils │ ├── parseStatus.js │ ├── ComponentWrapper.js │ ├── renderAlert.js │ ├── MetricsComponentWrapper.js │ ├── constants │ │ └── index.js │ └── table │ │ └── helpers.js ├── reducers │ ├── pods.js │ ├── nodes.js │ ├── services.js │ ├── promMetrics.js │ ├── deployments.js │ ├── index.js │ └── namespace.js ├── homepage │ ├── components │ │ ├── Utilizations │ │ │ ├── CpuUtilization.js │ │ │ ├── MemoryUtilization.js │ │ │ ├── CpuTotal.js │ │ │ └── MemoryTotal.js │ │ ├── Counts │ │ │ ├── PodsCount.js │ │ │ ├── DeploymentsCount.js │ │ │ ├── ServicesCount.js │ │ │ └── NodesCount.js │ │ ├── CriticalNodes │ │ │ ├── CPUIntensiveNodes.js │ │ │ ├── BytesReceivedPerNode.js │ │ │ ├── BytesTransmittedPerNode.js │ │ │ ├── MemoryIntensiveNodes.js │ │ │ └── ProblematicItem.js │ │ ├── CriticalPods │ │ │ ├── CPUIntensivePods.js │ │ │ └── MemoryIntensivePods.js │ │ ├── Refresh.js │ │ ├── Charts │ │ │ ├── BarChartTemplate.js │ │ │ ├── GaugeChartTemplate.js │ │ │ └── LineChartTemplate.js │ │ ├── Statuses │ │ │ ├── PodsStatus.js │ │ │ └── NodesStatus.js │ │ └── Problematic │ │ │ ├── ProblematicPods.js │ │ │ └── ProblematicNodes.js │ └── containers │ │ ├── ProblematicContainer.js │ │ ├── StatusContainer.js │ │ ├── CountsContainer.js │ │ ├── CriticalPodsContainer.js │ │ ├── CriticalNodesContainer.js │ │ └── UtilizationContainer.js ├── logspage │ ├── containers │ │ └── LogsContainer.js │ └── components │ │ └── LogsTable.js ├── custompage │ └── components │ │ ├── StepBar.js │ │ ├── SearchBar.js │ │ └── TimeRangeBar.js ├── App.js ├── namespaceSelection │ └── SelectNamespace.js ├── components │ ├── Statuses │ │ └── NodesStatus.js │ └── CriticalNodes │ │ └── ProblematicNodes.js ├── demoData │ ├── rawLogs.json │ ├── logs.json │ ├── networkTransmitBytes.json │ ├── networkTransmitFormatted.json │ └── clusterFreeMemory.json └── alertspage │ └── ExpandableRow.js ├── .gitignore ├── .DS_Store ├── .dockerignore ├── assets └── Logo.png ├── server ├── .DS_Store ├── utils │ ├── constants.js │ ├── formatVectorData.js │ ├── formatLogs.js │ ├── formatTimeToAvg.js │ ├── metricsFetch.js │ └── formatChartData.js ├── PrometheusData │ └── dataSources.js ├── controllers │ ├── alertsController.js │ ├── logsController.js │ └── getLists.js └── server.js ├── manifests ├── setup │ └── namespace.yaml ├── grafana-serviceAccount.yaml ├── nodeExporter-serviceAccount.yaml ├── blackboxExporter-serviceAccount.yaml ├── kubeStateMetrics-serviceAccount.yaml ├── prometheusAdapter-serviceAccount.yaml ├── prometheusOperator-serviceAccount.yaml ├── prometheus-serviceAccount.yaml ├── alertmanager-serviceAccount.yaml ├── blackboxExporter-clusterRole.yaml ├── grafana-config.yaml ├── grafana-serviceMonitor.yaml ├── prometheus-roleConfig.yaml ├── prometheusAdapter-clusterRoleServerResources.yaml ├── grafana-service.yaml ├── prometheusAdapter-clusterRole.yaml ├── kubeStateMetrics-clusterRoleBinding.yaml ├── prometheus-clusterRole.yaml ├── nodeExporter-clusterRoleBinding.yaml ├── prometheusOperator-clusterRoleBinding.yaml ├── prometheusAdapter-apiService.yaml ├── blackboxExporter-clusterRoleBinding.yaml ├── nodeExporter-service.yaml ├── prometheusAdapter-clusterRoleBinding.yaml ├── prometheusAdapter-service.yaml ├── nodeExporter-clusterRole.yaml ├── prometheusAdapter-podDisruptionBudget.yaml ├── prometheus-clusterRoleBinding.yaml ├── prometheus-roleBindingConfig.yaml ├── prometheusOperator-service.yaml ├── prometheusAdapter-roleBindingAuthReader.yaml ├── prometheusAdapter-clusterRoleBindingDelegator.yaml ├── prometheus-podDisruptionBudget.yaml ├── blackboxExporter-service.yaml ├── alertmanager-podDisruptionBudget.yaml ├── kubeStateMetrics-service.yaml ├── kubernetesControlPlane-serviceMonitorKubeScheduler.yaml ├── kubernetesControlPlane-serviceMonitorCoreDNS.yaml ├── prometheus-serviceMonitor.yaml ├── prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml ├── alertmanager-serviceMonitor.yaml ├── prometheus-service.yaml ├── alertmanager-service.yaml ├── grafana-dashboardSources.yaml ├── blackboxExporter-serviceMonitor.yaml ├── grafana-dashboardDatasources.yaml ├── prometheusOperator-serviceMonitor.yaml ├── nodeExporter-serviceMonitor.yaml ├── prometheusAdapter-serviceMonitor.yaml ├── alertmanager-alertmanager.yaml ├── kubeStateMetrics-serviceMonitor.yaml ├── alertmanager-secret.yaml ├── prometheus-prometheus.yaml ├── blackboxExporter-configuration.yaml ├── prometheusOperator-clusterRole.yaml ├── prometheus-roleBindingSpecificNamespaces.yaml ├── kubeStateMetrics-clusterRole.yaml ├── prometheusAdapter-configMap.yaml ├── prometheusOperator-deployment.yaml ├── prometheus-roleSpecificNamespaces.yaml ├── prometheusAdapter-deployment.yaml ├── kubeStateMetrics-deployment.yaml ├── kubeStateMetrics-prometheusRule.yaml ├── blackboxExporter-deployment.yaml ├── nodeExporter-daemonset.yaml └── kubePrometheus-prometheusRule.yaml ├── infra ├── prometheus │ ├── alert.yml │ └── prometheus.yml ├── grafana │ └── provisioning │ │ └── datasources │ │ └── prometheus_ds.yml ├── alertmanager │ └── alertmanager.yml └── docker-compose.yml ├── docker-compose.yml ├── Dockerfile-kube ├── index.html ├── fabric8-rbac.yaml ├── Dockerfile ├── armada-depl.yaml ├── package.json ├── webpack.config.js └── __tests__ └── backendTests.js /coverage/lcov.info: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /coverage/coverage-final.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /client/metricspage/components/CPUUsageByNode.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | out 4 | infra -------------------------------------------------------------------------------- /client/metricspage/components/BytesReceivedByNode.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/metricspage/components/FreeMemoryByNode.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/Armada/HEAD/.DS_Store -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | infra 3 | out 4 | main.js 5 | preload.js -------------------------------------------------------------------------------- /client/actions/constants/chartConstants.js: -------------------------------------------------------------------------------- 1 | export const MAX_SERIES = 5; 2 | -------------------------------------------------------------------------------- /assets/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/Armada/HEAD/assets/Logo.png -------------------------------------------------------------------------------- /client/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/Armada/HEAD/client/.DS_Store -------------------------------------------------------------------------------- /server/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/Armada/HEAD/server/.DS_Store -------------------------------------------------------------------------------- /manifests/setup/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: monitoring 5 | -------------------------------------------------------------------------------- /coverage/lcov-report/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/Armada/HEAD/coverage/lcov-report/favicon.png -------------------------------------------------------------------------------- /coverage/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/Armada/HEAD/coverage/lcov-report/sort-arrow-sprite.png -------------------------------------------------------------------------------- /infra/prometheus/alert.yml: -------------------------------------------------------------------------------- 1 | groups: 2 | - name: DemoAlerts 3 | rules: 4 | - alert: InstanceDown 5 | expr: up{job="services"} < 1 6 | for: 5m 7 | -------------------------------------------------------------------------------- /infra/grafana/provisioning/datasources/prometheus_ds.yml: -------------------------------------------------------------------------------- 1 | datasources: 2 | - name: Prometheus 3 | access: proxy 4 | type: prometheus 5 | url: http://prometheus:9090 6 | isDefault: true 7 | -------------------------------------------------------------------------------- /client/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import reducers from "./reducers/index.js"; 3 | const store = configureStore({ 4 | reducer: reducers, 5 | }); 6 | export default store; 7 | -------------------------------------------------------------------------------- /client/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fafafa; 3 | font-family: Arial, Helvetica, sans-serif; 4 | } 5 | 6 | .card-content { 7 | display: flex; 8 | flex-wrap: wrap; 9 | } 10 | 11 | h4 { 12 | margin: 1px; 13 | } 14 | -------------------------------------------------------------------------------- /server/utils/constants.js: -------------------------------------------------------------------------------- 1 | const constants = {}; 2 | 3 | constants.TIMESTEP = '10m'; 4 | constants.prometheusURL = 'http://127.0.0.1:9090/api/v1/'; 5 | // constants.prometheusURL = 'host.docker.internal:9090/api/v1/'; 6 | 7 | module.exports = constants; 8 | -------------------------------------------------------------------------------- /server/PrometheusData/dataSources.js: -------------------------------------------------------------------------------- 1 | const PrometheusAPI = require('../controllers/promethusController') 2 | 3 | const memory = { 4 | isPrometheusUp: { check: false }, 5 | }; 6 | 7 | module.exports = () => { 8 | return { 9 | prometheusAPI: new PrometheusAPI(memory), 10 | }; 11 | }; -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | armada: 4 | image: 'armadak8s/armada' 5 | container_name: armada 6 | ports: 7 | - '3001:3001' 8 | volumes: 9 | - .:/usr/src/app 10 | - node_modules:/usr/src/app/node_modules 11 | volumes: 12 | node_modules: 13 | -------------------------------------------------------------------------------- /manifests/grafana-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: grafana 6 | app.kubernetes.io/name: grafana 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 8.3.3 9 | name: grafana 10 | namespace: monitoring 11 | -------------------------------------------------------------------------------- /manifests/nodeExporter-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: node-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 1.3.1 9 | name: node-exporter 10 | namespace: monitoring 11 | -------------------------------------------------------------------------------- /manifests/blackboxExporter-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: blackbox-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.19.0 9 | name: blackbox-exporter 10 | namespace: monitoring 11 | -------------------------------------------------------------------------------- /manifests/kubeStateMetrics-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 2.3.0 9 | name: kube-state-metrics 10 | namespace: monitoring 11 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: prometheus-adapter 10 | namespace: monitoring 11 | -------------------------------------------------------------------------------- /manifests/prometheusOperator-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: controller 6 | app.kubernetes.io/name: prometheus-operator 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.53.1 9 | name: prometheus-operator 10 | namespace: monitoring 11 | -------------------------------------------------------------------------------- /manifests/prometheus-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s 11 | namespace: monitoring 12 | -------------------------------------------------------------------------------- /manifests/alertmanager-serviceAccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: alert-router 6 | app.kubernetes.io/instance: main 7 | app.kubernetes.io/name: alertmanager 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 0.23.0 10 | name: alertmanager-main 11 | namespace: monitoring 12 | -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDom from 'react-dom/client'; 3 | import { Provider } from 'react-redux'; 4 | 5 | import store from './store'; 6 | import App from './App'; 7 | import './styles.css'; 8 | 9 | const root = ReactDom.createRoot(document.getElementById('root')); 10 | 11 | root.render( 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /manifests/blackboxExporter-clusterRole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: blackbox-exporter 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /client/utils/parseStatus.js: -------------------------------------------------------------------------------- 1 | const parseStatus = (nodes) => { 2 | const nodesObj = {}; 3 | for (let node of nodes) { 4 | nodesObj[node.metadata.name] = {}; 5 | let conditions = node.status.conditions; 6 | for (let condition of conditions) { 7 | nodesObj[node.metadata.name][condition.type] = condition.status; 8 | } 9 | } 10 | return nodesObj; 11 | }; 12 | export default parseStatus; 13 | -------------------------------------------------------------------------------- /coverage/clover.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /manifests/grafana-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: grafana 6 | app.kubernetes.io/name: grafana 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 8.3.3 9 | name: grafana-config 10 | namespace: monitoring 11 | stringData: 12 | grafana.ini: | 13 | [date_formats] 14 | default_timezone = UTC 15 | type: Opaque 16 | -------------------------------------------------------------------------------- /server/utils/formatVectorData.js: -------------------------------------------------------------------------------- 1 | // Format vector data for bar charts 2 | const formatVectorData = (arr, metricName) => { 3 | return arr 4 | .sort((a, b) => parseFloat(b.value[1]) - parseFloat(a.value[1])) 5 | .map((node) => { 6 | return { 7 | label: node.metric[metricName] ? node.metric[metricName] : 'unnamed', 8 | data: parseFloat(node.value[1]), 9 | }; 10 | }); 11 | }; 12 | 13 | module.exports = formatVectorData; 14 | -------------------------------------------------------------------------------- /client/utils/ComponentWrapper.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Paper, Typography } from '@mui/material'; 3 | 4 | function ComponentWrapper({ title, children }) { 5 | return ( 6 | 7 | 8 | {title} 9 | 10 | {children} 11 | 12 | ); 13 | } 14 | 15 | export default ComponentWrapper; 16 | -------------------------------------------------------------------------------- /server/utils/formatLogs.js: -------------------------------------------------------------------------------- 1 | // Format log data for presentation 2 | const formatLogs = (arr) => { 3 | arr.pop(); 4 | const trimmed = arr.map((el) => el.split(/[ ]{2,}/)); 5 | const headers = trimmed[0].map((el) => el.toLowerCase().replace(' ', '_')); 6 | trimmed.shift(); 7 | return trimmed.map((row) => { 8 | let obj = {}; 9 | row.forEach((r, i) => { 10 | obj[headers[i]] = row[i]; 11 | }); 12 | 13 | return obj; 14 | }); 15 | }; 16 | 17 | module.exports = formatLogs; 18 | -------------------------------------------------------------------------------- /client/reducers/pods.js: -------------------------------------------------------------------------------- 1 | import { FETCH_PODS_LIST } from '../actions/constants/actionTypes'; 2 | 3 | const initialState = { 4 | items: [], 5 | lastUpdated: null, 6 | }; 7 | 8 | const podsReducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case FETCH_PODS_LIST: { 11 | return { items: action.payload, lastUpdated: new Date().toISOString() }; 12 | } 13 | default: { 14 | return state; 15 | } 16 | } 17 | }; 18 | 19 | export default podsReducer; 20 | -------------------------------------------------------------------------------- /manifests/grafana-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: grafana 6 | app.kubernetes.io/name: grafana 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 8.3.3 9 | name: grafana 10 | namespace: monitoring 11 | spec: 12 | endpoints: 13 | - interval: 15s 14 | port: http 15 | selector: 16 | matchLabels: 17 | app.kubernetes.io/name: grafana 18 | -------------------------------------------------------------------------------- /client/reducers/nodes.js: -------------------------------------------------------------------------------- 1 | import { FETCH_NODES_LIST } from '../actions/constants/actionTypes'; 2 | 3 | const initialState = { 4 | items: [], 5 | lastUpdated: null, 6 | }; 7 | 8 | const nodesReducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case FETCH_NODES_LIST: { 11 | return { items: action.payload, lastUpdated: new Date().toISOString() }; 12 | } 13 | default: { 14 | return state; 15 | } 16 | } 17 | }; 18 | 19 | export default nodesReducer; 20 | -------------------------------------------------------------------------------- /client/utils/renderAlert.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Alert, Grid } from '@mui/material'; 3 | 4 | const renderAlert = (length, message, type) => { 5 | if (length === 0) { 6 | return ( 7 | 8 | 9 | 10 | {message} 11 | 12 | 13 | 14 | ); 15 | } else return null; 16 | }; 17 | 18 | export default renderAlert; 19 | -------------------------------------------------------------------------------- /infra/prometheus/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 30s 3 | scrape_timeout: 10s 4 | 5 | rule_files: 6 | - alert.yml 7 | 8 | scrape_configs: 9 | - job_name: services 10 | metrics_path: /metrics 11 | static_configs: 12 | - targets: 13 | - 'prometheus:9090' 14 | - 'node-exporter:9100' 15 | - 'host.docker.internal' 16 | 17 | alerting: 18 | alertmanagers: 19 | - scheme: http 20 | static_configs: 21 | - targets: ['alertmanager:9093'] 22 | -------------------------------------------------------------------------------- /manifests/prometheus-roleConfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s-config 11 | namespace: monitoring 12 | rules: 13 | - apiGroups: 14 | - "" 15 | resources: 16 | - configmaps 17 | verbs: 18 | - get 19 | -------------------------------------------------------------------------------- /Dockerfile-kube: -------------------------------------------------------------------------------- 1 | 2 | #building and adding kubectl 3 | FROM alpine:3.8 as kubectl 4 | 5 | ADD https://storage.googleapis.com/kubernetes-release/release/v1.6.4/bin/linux/amd64/kubectl /usr/local/bin/kubectl 6 | ENV HOME=/config \ 7 | KUBECONFIG=/etc/kubernetes/admin.conf 8 | RUN set -x && \ 9 | apk add --no-cache curl ca-certificates && \ 10 | chmod +x /usr/local/bin/kubectl 11 | 12 | #your app container 13 | FROM armadak8s/armada:latest 14 | 15 | COPY --from=kubectl /usr/local/bin/kubectl /usr/local/bin/kubectl -------------------------------------------------------------------------------- /client/reducers/services.js: -------------------------------------------------------------------------------- 1 | import { FETCH_SERVICES_LIST } from '../actions/constants/actionTypes'; 2 | 3 | const initialState = { 4 | items: [], 5 | lastUpdated: null, 6 | }; 7 | 8 | const servicesReducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case FETCH_SERVICES_LIST: { 11 | return { items: action.payload, lastUpdated: new Date().toISOString() }; 12 | } 13 | default: { 14 | return state; 15 | } 16 | } 17 | }; 18 | 19 | export default servicesReducer; 20 | -------------------------------------------------------------------------------- /client/reducers/promMetrics.js: -------------------------------------------------------------------------------- 1 | import { FETCH_PROM_METRICS } from '../actions/constants/actionTypes'; 2 | 3 | const initialState = { 4 | items: [], 5 | lastUpdated: null, 6 | }; 7 | 8 | const promMetricsReducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case FETCH_PROM_METRICS: { 11 | return { items: action.payload, lastUpdated: new Date().toISOString() }; 12 | } 13 | default: { 14 | return state; 15 | } 16 | } 17 | }; 18 | 19 | export default promMetricsReducer; 20 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-clusterRoleServerResources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: resource-metrics-server-resources 10 | namespace: monitoring 11 | rules: 12 | - apiGroups: 13 | - metrics.k8s.io 14 | resources: 15 | - '*' 16 | verbs: 17 | - '*' 18 | -------------------------------------------------------------------------------- /client/utils/MetricsComponentWrapper.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Box, Paper, Typography } from '@mui/material'; 3 | 4 | function MetricsComponentWrapper({ title, children }) { 5 | return ( 6 | 17 | {children} 18 | 19 | ); 20 | } 21 | 22 | export default MetricsComponentWrapper; 23 | -------------------------------------------------------------------------------- /client/reducers/deployments.js: -------------------------------------------------------------------------------- 1 | import { FETCH_DEPLOYMENTS_LIST } from '../actions/constants/actionTypes'; 2 | 3 | const initialState = { 4 | items: [], 5 | lastUpdated: null, 6 | }; 7 | 8 | const deploymentsReducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case FETCH_DEPLOYMENTS_LIST: { 11 | return { items: action.payload, lastUpdated: new Date().toISOString() }; 12 | } 13 | default: { 14 | return state; 15 | } 16 | } 17 | }; 18 | 19 | export default deploymentsReducer; 20 | -------------------------------------------------------------------------------- /client/homepage/components/Utilizations/CpuUtilization.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { Card, Typography } from '@mui/material'; 3 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 4 | import GaugeChartTemplate from '../Charts/GaugeChartTemplate'; 5 | 6 | function CpuUtilization({ cpu }) { 7 | return ( 8 | 13 | ); 14 | } 15 | 16 | export default CpuUtilization; 17 | -------------------------------------------------------------------------------- /manifests/grafana-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: grafana 6 | app.kubernetes.io/name: grafana 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 8.3.3 9 | name: grafana 10 | namespace: monitoring 11 | spec: 12 | ports: 13 | - name: http 14 | port: 3000 15 | targetPort: http 16 | selector: 17 | app.kubernetes.io/component: grafana 18 | app.kubernetes.io/name: grafana 19 | app.kubernetes.io/part-of: kube-prometheus 20 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-clusterRole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: prometheus-adapter 10 | namespace: monitoring 11 | rules: 12 | - apiGroups: 13 | - "" 14 | resources: 15 | - nodes 16 | - namespaces 17 | - pods 18 | - services 19 | verbs: 20 | - get 21 | - list 22 | - watch 23 | -------------------------------------------------------------------------------- /client/homepage/components/Utilizations/MemoryUtilization.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { Card, Typography } from '@mui/material'; 3 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 4 | import GaugeChartTemplate from '../Charts/GaugeChartTemplate'; 5 | 6 | function MemoryUtilization({ memory }) { 7 | return ( 8 | 13 | ); 14 | } 15 | 16 | export default MemoryUtilization; 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Armada 7 | 11 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /client/homepage/components/Counts/PodsCount.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { Card, Typography } from '@mui/material'; 3 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 4 | 5 | // Displays count of pods in cluster 6 | function PodsCount(props) { 7 | const { pods } = props; 8 | const podsCount = pods.length ? pods.length : '-'; 9 | return ( 10 | 11 | {podsCount} 12 | 13 | ); 14 | } 15 | 16 | export default PodsCount; 17 | -------------------------------------------------------------------------------- /manifests/kubeStateMetrics-clusterRoleBinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 2.3.0 9 | name: kube-state-metrics 10 | roleRef: 11 | apiGroup: rbac.authorization.k8s.io 12 | kind: ClusterRole 13 | name: kube-state-metrics 14 | subjects: 15 | - kind: ServiceAccount 16 | name: kube-state-metrics 17 | namespace: monitoring 18 | -------------------------------------------------------------------------------- /manifests/prometheus-clusterRole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s 11 | namespace: monitoring 12 | rules: 13 | - apiGroups: 14 | - "" 15 | resources: 16 | - nodes/metrics 17 | verbs: 18 | - get 19 | - nonResourceURLs: 20 | - /metrics 21 | verbs: 22 | - get 23 | -------------------------------------------------------------------------------- /manifests/nodeExporter-clusterRoleBinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: node-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 1.3.1 9 | name: node-exporter 10 | namespace: monitoring 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: ClusterRole 14 | name: node-exporter 15 | subjects: 16 | - kind: ServiceAccount 17 | name: node-exporter 18 | namespace: monitoring 19 | -------------------------------------------------------------------------------- /manifests/prometheusOperator-clusterRoleBinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: controller 6 | app.kubernetes.io/name: prometheus-operator 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.53.1 9 | name: prometheus-operator 10 | roleRef: 11 | apiGroup: rbac.authorization.k8s.io 12 | kind: ClusterRole 13 | name: prometheus-operator 14 | subjects: 15 | - kind: ServiceAccount 16 | name: prometheus-operator 17 | namespace: monitoring 18 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-apiService.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiregistration.k8s.io/v1 2 | kind: APIService 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: v1beta1.metrics.k8s.io 10 | spec: 11 | group: metrics.k8s.io 12 | groupPriorityMinimum: 100 13 | insecureSkipTLSVerify: true 14 | service: 15 | name: prometheus-adapter 16 | namespace: monitoring 17 | version: v1beta1 18 | versionPriority: 100 19 | -------------------------------------------------------------------------------- /manifests/blackboxExporter-clusterRoleBinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: blackbox-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.19.0 9 | name: blackbox-exporter 10 | namespace: monitoring 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: ClusterRole 14 | name: blackbox-exporter 15 | subjects: 16 | - kind: ServiceAccount 17 | name: blackbox-exporter 18 | namespace: monitoring 19 | -------------------------------------------------------------------------------- /manifests/nodeExporter-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: node-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 1.3.1 9 | name: node-exporter 10 | namespace: monitoring 11 | spec: 12 | clusterIP: None 13 | ports: 14 | - name: https 15 | port: 9100 16 | targetPort: https 17 | selector: 18 | app.kubernetes.io/component: exporter 19 | app.kubernetes.io/name: node-exporter 20 | app.kubernetes.io/part-of: kube-prometheus 21 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-clusterRoleBinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: prometheus-adapter 10 | namespace: monitoring 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: ClusterRole 14 | name: prometheus-adapter 15 | subjects: 16 | - kind: ServiceAccount 17 | name: prometheus-adapter 18 | namespace: monitoring 19 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: prometheus-adapter 10 | namespace: monitoring 11 | spec: 12 | ports: 13 | - name: https 14 | port: 443 15 | targetPort: 6443 16 | selector: 17 | app.kubernetes.io/component: metrics-adapter 18 | app.kubernetes.io/name: prometheus-adapter 19 | app.kubernetes.io/part-of: kube-prometheus 20 | -------------------------------------------------------------------------------- /manifests/nodeExporter-clusterRole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: node-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 1.3.1 9 | name: node-exporter 10 | namespace: monitoring 11 | rules: 12 | - apiGroups: 13 | - authentication.k8s.io 14 | resources: 15 | - tokenreviews 16 | verbs: 17 | - create 18 | - apiGroups: 19 | - authorization.k8s.io 20 | resources: 21 | - subjectaccessreviews 22 | verbs: 23 | - create 24 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-podDisruptionBudget.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy/v1 2 | kind: PodDisruptionBudget 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: prometheus-adapter 10 | namespace: monitoring 11 | spec: 12 | minAvailable: 1 13 | selector: 14 | matchLabels: 15 | app.kubernetes.io/component: metrics-adapter 16 | app.kubernetes.io/name: prometheus-adapter 17 | app.kubernetes.io/part-of: kube-prometheus 18 | -------------------------------------------------------------------------------- /client/homepage/components/CriticalNodes/CPUIntensiveNodes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 3 | import BarChart from '../Charts/BarChartTemplate'; 4 | 5 | // Horizontal bar chart showing CPU usage by node 6 | const CPUIntensiveNodes = ({ nodes }) => { 7 | return ( 8 | 9 | 14 | 15 | ); 16 | }; 17 | 18 | export default CPUIntensiveNodes; 19 | -------------------------------------------------------------------------------- /client/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import namespaceReducer from './namespace'; 3 | import nodesReducer from './nodes'; 4 | import podsReducer from './pods'; 5 | import deploymentsReducer from './deployments'; 6 | import servicesReducer from './services'; 7 | import promMetricsReducer from './promMetrics'; 8 | 9 | const reducers = combineReducers({ 10 | nodes: nodesReducer, 11 | pods: podsReducer, 12 | namespace: namespaceReducer, 13 | deployments: deploymentsReducer, 14 | services: servicesReducer, 15 | promMetrics: promMetricsReducer, 16 | }); 17 | 18 | export default reducers; 19 | -------------------------------------------------------------------------------- /manifests/prometheus-clusterRoleBinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s 11 | namespace: monitoring 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: prometheus-k8s 16 | subjects: 17 | - kind: ServiceAccount 18 | name: prometheus-k8s 19 | namespace: monitoring 20 | -------------------------------------------------------------------------------- /manifests/prometheus-roleBindingConfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s-config 11 | namespace: monitoring 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: Role 15 | name: prometheus-k8s-config 16 | subjects: 17 | - kind: ServiceAccount 18 | name: prometheus-k8s 19 | namespace: monitoring 20 | -------------------------------------------------------------------------------- /client/actions/constants/actionTypes.js: -------------------------------------------------------------------------------- 1 | // export const first = 'first' 2 | // export const first = 'first' 3 | // export const first = 'first' 4 | // export const first = 'first' 5 | 6 | export const FETCH_NODES_LIST = 'FETCH_NODES_LIST'; 7 | 8 | export const FETCH_PODS_LIST = 'FETCH_PODS_LIST'; 9 | 10 | export const FETCH_SERVICES_LIST = 'FETCH_SERVICES_LIST'; 11 | 12 | export const FETCH_DEPLOYMENTS_LIST = 'FETCH_DEPLOYMENTS_LIST'; 13 | 14 | export const SET_NAMESPACE = 'SET_NAMESPACE'; 15 | 16 | export const FETCH_NAMESPACES_LIST = 'FETCH_NAMESPACES_LIST'; 17 | 18 | export const FETCH_PROM_METRICS = 'FETCH_PROM_METRICS'; 19 | -------------------------------------------------------------------------------- /client/homepage/containers/ProblematicContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ProblematicNodes from '../components/Problematic/ProblematicNodes'; 3 | import ProblematicPods from '../components/Problematic/ProblematicPods'; 4 | import { Grid } from '@mui/material'; 5 | 6 | const ProblematicContainer = () => { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | }; 18 | 19 | export default ProblematicContainer; 20 | -------------------------------------------------------------------------------- /manifests/prometheusOperator-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: controller 6 | app.kubernetes.io/name: prometheus-operator 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.53.1 9 | name: prometheus-operator 10 | namespace: monitoring 11 | spec: 12 | clusterIP: None 13 | ports: 14 | - name: https 15 | port: 8443 16 | targetPort: https 17 | selector: 18 | app.kubernetes.io/component: controller 19 | app.kubernetes.io/name: prometheus-operator 20 | app.kubernetes.io/part-of: kube-prometheus 21 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-roleBindingAuthReader.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: resource-metrics-auth-reader 10 | namespace: kube-system 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: Role 14 | name: extension-apiserver-authentication-reader 15 | subjects: 16 | - kind: ServiceAccount 17 | name: prometheus-adapter 18 | namespace: monitoring 19 | -------------------------------------------------------------------------------- /client/homepage/components/Counts/DeploymentsCount.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { Card, Typography } from '@mui/material'; 3 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 4 | 5 | // Displays count of deployments in cluster 6 | function DeploymentsCount(props) { 7 | const { deployments } = props; 8 | const deploymentsCount = deployments.length ? deployments.length : '-'; 9 | return ( 10 | 11 | {deploymentsCount} 12 | 13 | ); 14 | } 15 | 16 | export default DeploymentsCount; 17 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-clusterRoleBindingDelegator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: resource-metrics:system:auth-delegator 10 | namespace: monitoring 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: ClusterRole 14 | name: system:auth-delegator 15 | subjects: 16 | - kind: ServiceAccount 17 | name: prometheus-adapter 18 | namespace: monitoring 19 | -------------------------------------------------------------------------------- /client/homepage/components/Counts/ServicesCount.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import Card from '@mui/material/Card'; 3 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 4 | import { Typography } from '@mui/material'; 5 | 6 | // Displays count of services in cluster 7 | function ServicesCount(props) { 8 | const { services } = props; 9 | const servicesCount = services.length ? services.length : '-'; 10 | return ( 11 | 12 | {servicesCount} 13 | 14 | ); 15 | } 16 | 17 | export default ServicesCount; 18 | -------------------------------------------------------------------------------- /client/homepage/components/CriticalPods/CPUIntensivePods.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import BarChart from '../Charts/BarChartTemplate'; 3 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 4 | import { MAX_SERIES } from '../../../actions/constants/chartConstants'; 5 | 6 | const CPUIntensivePods = ({ pods }) => { 7 | return ( 8 | 9 | 14 | 15 | ); 16 | }; 17 | 18 | export default CPUIntensivePods; 19 | -------------------------------------------------------------------------------- /client/reducers/namespace.js: -------------------------------------------------------------------------------- 1 | import { 2 | FETCH_NAMESPACES_LIST, 3 | SET_NAMESPACE, 4 | } from '../actions/constants/actionTypes'; 5 | 6 | const initialState = { 7 | selectedNamespace: 'All', 8 | namespacesList: [], 9 | }; 10 | 11 | const namespaceReducer = (state = initialState, action) => { 12 | switch (action.type) { 13 | case SET_NAMESPACE: { 14 | return { ...state, selectedNamespace: action.payload }; 15 | } 16 | case FETCH_NAMESPACES_LIST: { 17 | return { ...state, namespacesList: action.payload }; 18 | } 19 | default: { 20 | return state; 21 | } 22 | } 23 | }; 24 | 25 | export default namespaceReducer; 26 | -------------------------------------------------------------------------------- /manifests/prometheus-podDisruptionBudget.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy/v1 2 | kind: PodDisruptionBudget 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s 11 | namespace: monitoring 12 | spec: 13 | minAvailable: 1 14 | selector: 15 | matchLabels: 16 | app.kubernetes.io/component: prometheus 17 | app.kubernetes.io/instance: k8s 18 | app.kubernetes.io/name: prometheus 19 | app.kubernetes.io/part-of: kube-prometheus 20 | -------------------------------------------------------------------------------- /manifests/blackboxExporter-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: blackbox-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.19.0 9 | name: blackbox-exporter 10 | namespace: monitoring 11 | spec: 12 | ports: 13 | - name: https 14 | port: 9115 15 | targetPort: https 16 | - name: probe 17 | port: 19115 18 | targetPort: http 19 | selector: 20 | app.kubernetes.io/component: exporter 21 | app.kubernetes.io/name: blackbox-exporter 22 | app.kubernetes.io/part-of: kube-prometheus 23 | -------------------------------------------------------------------------------- /manifests/alertmanager-podDisruptionBudget.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy/v1 2 | kind: PodDisruptionBudget 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: alert-router 6 | app.kubernetes.io/instance: main 7 | app.kubernetes.io/name: alertmanager 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 0.23.0 10 | name: alertmanager-main 11 | namespace: monitoring 12 | spec: 13 | maxUnavailable: 1 14 | selector: 15 | matchLabels: 16 | app.kubernetes.io/component: alert-router 17 | app.kubernetes.io/instance: main 18 | app.kubernetes.io/name: alertmanager 19 | app.kubernetes.io/part-of: kube-prometheus 20 | -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /client/homepage/containers/StatusContainer.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { Grid, Box } from '@mui/material'; 3 | import NodesStatus from '../components/Statuses/NodesStatus'; 4 | import PodsStatus from '../components/Statuses/PodsStatus'; 5 | 6 | const StatusContainer = (props) => { 7 | const { nodes, pods, services } = props; 8 | 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default StatusContainer; 22 | -------------------------------------------------------------------------------- /client/metricspage/components/PodMetrics/FreeMemoryByPod.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | 4 | const FreeMemoryByPod = ({ metrics }) => { 5 | /* 6 | Renders Free Memory Per Node line chart on the Metrics Page 7 | */ 8 | return ( 9 |
10 | 11 | 17 | 18 |
19 | ); 20 | }; 21 | 22 | export default FreeMemoryByPod; 23 | -------------------------------------------------------------------------------- /client/homepage/components/CriticalNodes/BytesReceivedPerNode.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 3 | import BarChart from '../Charts/BarChartTemplate'; 4 | 5 | // Horizontal bar chart of bytes received per node 6 | const BytesReceivedPerNode = ({ promMetrics }) => { 7 | return ( 8 | 9 | 14 | 15 | ); 16 | }; 17 | 18 | export default BytesReceivedPerNode; 19 | -------------------------------------------------------------------------------- /client/homepage/components/Counts/NodesCount.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Card, Typography } from '@mui/material'; 4 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 5 | 6 | const mapStateToProps = ({ nodes }) => { 7 | return nodes; 8 | }; 9 | 10 | // Displays count of nodes in cluster 11 | function NodesCount({ items }) { 12 | const nodesCount = items.length ? items.length : '-'; 13 | return ( 14 | 15 | {nodesCount} 16 | 17 | ); 18 | } 19 | 20 | export default connect(mapStateToProps)(NodesCount); 21 | -------------------------------------------------------------------------------- /fabric8-rbac.yaml: -------------------------------------------------------------------------------- 1 | # NOTE: The service account `default:default` already exists in k8s cluster. 2 | # You can create a new account following like this: 3 | #--- 4 | #apiVersion: v1 5 | #kind: ServiceAccount 6 | #metadata: 7 | # name: 8 | # namespace: 9 | 10 | --- 11 | apiVersion: rbac.authorization.k8s.io/v1 12 | kind: ClusterRoleBinding 13 | metadata: 14 | name: fabric8-rbac 15 | subjects: 16 | - kind: ServiceAccount 17 | # Reference to upper's `metadata.name` 18 | name: default 19 | # Reference to upper's `metadata.namespace` 20 | namespace: default 21 | roleRef: 22 | kind: ClusterRole 23 | name: cluster-admin 24 | apiGroup: rbac.authorization.k8s.io 25 | -------------------------------------------------------------------------------- /client/utils/constants/index.js: -------------------------------------------------------------------------------- 1 | /** TODO: Make sure all bar charts import MAX_SERIES from this file and remove actions/constants/chartConstants.js */ 2 | export const MAX_SERIES = 5; 3 | 4 | export const POD_STATUS = { 5 | Pending: 6 | 'The pod is waiting to get scheduled on a node, or for at least one of its containers to initialize.', 7 | Running: 8 | 'The pod has been assigned to a node and has one or more running containers.', 9 | Succeeded: 'All of the pod’s containers exited without errors.', 10 | Failed: 'One or more of the pod’s containers terminated with an error.', 11 | Unknown: 12 | 'Usually occurs when the Kubernetes API server could not communicate with the pod’s node.', 13 | }; 14 | -------------------------------------------------------------------------------- /manifests/kubeStateMetrics-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 2.3.0 9 | name: kube-state-metrics 10 | namespace: monitoring 11 | spec: 12 | clusterIP: None 13 | ports: 14 | - name: https-main 15 | port: 8443 16 | targetPort: https-main 17 | - name: https-self 18 | port: 9443 19 | targetPort: https-self 20 | selector: 21 | app.kubernetes.io/component: exporter 22 | app.kubernetes.io/name: kube-state-metrics 23 | app.kubernetes.io/part-of: kube-prometheus 24 | -------------------------------------------------------------------------------- /client/homepage/components/CriticalNodes/BytesTransmittedPerNode.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 3 | import BarChart from '../Charts/BarChartTemplate'; 4 | 5 | // Horizontal bar chart of bytes transmitted per node 6 | const BytesTransmittedPerNode = ({ promMetrics }) => { 7 | return ( 8 | 9 | 14 | 15 | ); 16 | }; 17 | 18 | export default BytesTransmittedPerNode; 19 | -------------------------------------------------------------------------------- /manifests/kubernetesControlPlane-serviceMonitorKubeScheduler.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: kube-scheduler 6 | app.kubernetes.io/part-of: kube-prometheus 7 | name: kube-scheduler 8 | namespace: monitoring 9 | spec: 10 | endpoints: 11 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 12 | interval: 30s 13 | port: https-metrics 14 | scheme: https 15 | tlsConfig: 16 | insecureSkipVerify: true 17 | jobLabel: app.kubernetes.io/name 18 | namespaceSelector: 19 | matchNames: 20 | - kube-system 21 | selector: 22 | matchLabels: 23 | app.kubernetes.io/name: kube-scheduler 24 | -------------------------------------------------------------------------------- /manifests/kubernetesControlPlane-serviceMonitorCoreDNS.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: coredns 6 | app.kubernetes.io/part-of: kube-prometheus 7 | name: coredns 8 | namespace: monitoring 9 | spec: 10 | endpoints: 11 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 12 | interval: 15s 13 | metricRelabelings: 14 | - action: drop 15 | regex: coredns_cache_misses_total 16 | sourceLabels: 17 | - __name__ 18 | port: metrics 19 | jobLabel: app.kubernetes.io/name 20 | namespaceSelector: 21 | matchNames: 22 | - kube-system 23 | selector: 24 | matchLabels: 25 | k8s-app: kube-dns 26 | -------------------------------------------------------------------------------- /manifests/prometheus-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s 11 | namespace: monitoring 12 | spec: 13 | endpoints: 14 | - interval: 30s 15 | port: web 16 | - interval: 30s 17 | port: reloader-web 18 | selector: 19 | matchLabels: 20 | app.kubernetes.io/component: prometheus 21 | app.kubernetes.io/instance: k8s 22 | app.kubernetes.io/name: prometheus 23 | app.kubernetes.io/part-of: kube-prometheus 24 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-clusterRoleAggregatedMetricsReader.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | rbac.authorization.k8s.io/aggregate-to-admin: "true" 10 | rbac.authorization.k8s.io/aggregate-to-edit: "true" 11 | rbac.authorization.k8s.io/aggregate-to-view: "true" 12 | name: system:aggregated-metrics-reader 13 | namespace: monitoring 14 | rules: 15 | - apiGroups: 16 | - metrics.k8s.io 17 | resources: 18 | - pods 19 | - nodes 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | -------------------------------------------------------------------------------- /client/metricspage/components/PodMetrics/CPUUsageByPod.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const CPUUsageByPod = ({ metrics }) => { 6 | /* 7 | Renders CPU Usage % by Pod line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default CPUUsageByPod; 24 | -------------------------------------------------------------------------------- /client/homepage/components/CriticalNodes/MemoryIntensiveNodes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 3 | import BarChart from '../Charts/BarChartTemplate'; 4 | 5 | // Horizontal bar chart showing memory usage bby node 6 | const MemoryIntensiveNodes = ({ nodes }) => { 7 | const unitConverted = nodes.map((el) => { 8 | return { ...el, data: el.data / 1000000000 }; 9 | }); 10 | return ( 11 | 12 | 17 | 18 | ); 19 | }; 20 | 21 | export default MemoryIntensiveNodes; 22 | -------------------------------------------------------------------------------- /manifests/alertmanager-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: alert-router 6 | app.kubernetes.io/instance: main 7 | app.kubernetes.io/name: alertmanager 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 0.23.0 10 | name: alertmanager-main 11 | namespace: monitoring 12 | spec: 13 | endpoints: 14 | - interval: 30s 15 | port: web 16 | - interval: 30s 17 | port: reloader-web 18 | selector: 19 | matchLabels: 20 | app.kubernetes.io/component: alert-router 21 | app.kubernetes.io/instance: main 22 | app.kubernetes.io/name: alertmanager 23 | app.kubernetes.io/part-of: kube-prometheus 24 | -------------------------------------------------------------------------------- /manifests/prometheus-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: prometheus-k8s 11 | namespace: monitoring 12 | spec: 13 | ports: 14 | - name: web 15 | port: 9090 16 | targetPort: web 17 | - name: reloader-web 18 | port: 8080 19 | targetPort: reloader-web 20 | selector: 21 | app.kubernetes.io/component: prometheus 22 | app.kubernetes.io/instance: k8s 23 | app.kubernetes.io/name: prometheus 24 | app.kubernetes.io/part-of: kube-prometheus 25 | sessionAffinity: ClientIP 26 | -------------------------------------------------------------------------------- /client/metricspage/components/NodeMetrics/CPUUsageByNode.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const CPUUsageByNode = ({ metrics }) => { 6 | /* 7 | Renders the CPU Usage % Per Node line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default CPUUsageByNode; 24 | -------------------------------------------------------------------------------- /manifests/alertmanager-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: alert-router 6 | app.kubernetes.io/instance: main 7 | app.kubernetes.io/name: alertmanager 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 0.23.0 10 | name: alertmanager-main 11 | namespace: monitoring 12 | spec: 13 | ports: 14 | - name: web 15 | port: 9093 16 | targetPort: web 17 | - name: reloader-web 18 | port: 8080 19 | targetPort: reloader-web 20 | selector: 21 | app.kubernetes.io/component: alert-router 22 | app.kubernetes.io/instance: main 23 | app.kubernetes.io/name: alertmanager 24 | app.kubernetes.io/part-of: kube-prometheus 25 | sessionAffinity: ClientIP 26 | -------------------------------------------------------------------------------- /server/controllers/alertsController.js: -------------------------------------------------------------------------------- 1 | const fetch = (...args) => 2 | import('node-fetch').then(({ default: fetch }) => fetch(...args)); 3 | 4 | const { prometheusURL } = require('../utils/constants'); 5 | 6 | // const prometheusURL = 'http://127.0.0.1:9090/api/v1/'; 7 | 8 | const alertsController = {}; 9 | 10 | // fetch alerts from Prometheus for Alerts page 11 | alertsController.fetchAlerts = async (req, res, next) => { 12 | try { 13 | const data = await fetch(`${prometheusURL}/rules`); 14 | res.locals.alerts = await data.json(); 15 | return next(); 16 | } catch (err) { 17 | return next({ 18 | log: 'Error in alertsController.fetchAlerts', 19 | message: { err: err.message }, 20 | }); 21 | } 22 | }; 23 | 24 | module.exports = alertsController; 25 | -------------------------------------------------------------------------------- /client/homepage/components/CriticalPods/MemoryIntensivePods.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import BarChart from '../Charts/BarChartTemplate'; 3 | import { MAX_SERIES } from '../../../actions/constants/chartConstants'; 4 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 5 | 6 | const MemoryIntensivePods = ({ pods }) => { 7 | const unitConverted = pods.map((el) => { 8 | return { ...el, data: el.data / 1000000000 }; 9 | }); 10 | return ( 11 | 12 | 17 | 18 | ); 19 | }; 20 | 21 | export default MemoryIntensivePods; 22 | -------------------------------------------------------------------------------- /server/controllers/logsController.js: -------------------------------------------------------------------------------- 1 | const cmd = require('node-cmd'); 2 | const logsController = {}; 3 | const formatLogs = require('../utils/formatLogs'); 4 | 5 | const HEADERS = [ 6 | 'NAMESPACE', 7 | 'LAST SEEN', 8 | 'TYPE', 9 | 'REASON', 10 | 'OBJECT', 11 | 'MESSAGE', 12 | ]; 13 | 14 | // get logs for logs page through kubectl 15 | logsController.getLogs = (req, res, next) => { 16 | try { 17 | const rawLogs = cmd 18 | .runSync('kubectl get events --all-namespaces') 19 | .data.split('\n'); 20 | const formattedLogs = formatLogs(rawLogs); 21 | res.locals.logs = formattedLogs; 22 | return next(); 23 | } catch (err) { 24 | next({ logs: 'Error with getting logs', message: { err: err.message } }); 25 | } 26 | }; 27 | 28 | module.exports = logsController; 29 | -------------------------------------------------------------------------------- /client/metricspage/components/NamespaceMetrics/CPUUsageByNamespace.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const CPUUsageByNamespace = ({ metrics }) => { 6 | /* 7 | Renders CPU Usage % by Namespace line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default CPUUsageByNamespace; 24 | -------------------------------------------------------------------------------- /manifests/grafana-dashboardSources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | dashboards.yaml: |- 4 | { 5 | "apiVersion": 1, 6 | "providers": [ 7 | { 8 | "folder": "Default", 9 | "folderUid": "", 10 | "name": "0", 11 | "options": { 12 | "path": "/grafana-dashboard-definitions/0" 13 | }, 14 | "orgId": 1, 15 | "type": "file" 16 | } 17 | ] 18 | } 19 | kind: ConfigMap 20 | metadata: 21 | labels: 22 | app.kubernetes.io/component: grafana 23 | app.kubernetes.io/name: grafana 24 | app.kubernetes.io/part-of: kube-prometheus 25 | app.kubernetes.io/version: 8.3.3 26 | name: grafana-dashboards 27 | namespace: monitoring 28 | -------------------------------------------------------------------------------- /client/metricspage/components/PodMetrics/BytesReceivedByPod.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const BytesReceivedByPod = ({ metrics }) => { 6 | /* 7 | Renders the Network IO (Bps) Received by Pod line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default BytesReceivedByPod; 24 | -------------------------------------------------------------------------------- /client/metricspage/components/NodeMetrics/BytesReceivedByNode.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const BytesReceivedByNode = ({ metrics }) => { 6 | /* 7 | Renders the Network IO (Bps) Received by Node line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default BytesReceivedByNode; 24 | -------------------------------------------------------------------------------- /manifests/blackboxExporter-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: blackbox-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.19.0 9 | name: blackbox-exporter 10 | namespace: monitoring 11 | spec: 12 | endpoints: 13 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 14 | interval: 30s 15 | path: /metrics 16 | port: https 17 | scheme: https 18 | tlsConfig: 19 | insecureSkipVerify: true 20 | selector: 21 | matchLabels: 22 | app.kubernetes.io/component: exporter 23 | app.kubernetes.io/name: blackbox-exporter 24 | app.kubernetes.io/part-of: kube-prometheus 25 | -------------------------------------------------------------------------------- /client/metricspage/components/PodMetrics/BytesTransmittedbyPod.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const BytesTransmittedbyPod = ({ metrics }) => { 6 | /* 7 | Renders Network IO (Bps) Transmitted by Pod line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default BytesTransmittedbyPod; 24 | -------------------------------------------------------------------------------- /manifests/grafana-dashboardDatasources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: grafana 6 | app.kubernetes.io/name: grafana 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 8.3.3 9 | name: grafana-datasources 10 | namespace: monitoring 11 | stringData: 12 | datasources.yaml: |- 13 | { 14 | "apiVersion": 1, 15 | "datasources": [ 16 | { 17 | "access": "proxy", 18 | "editable": false, 19 | "name": "prometheus", 20 | "orgId": 1, 21 | "type": "prometheus", 22 | "url": "http://prometheus-k8s.monitoring.svc:9090", 23 | "version": 1 24 | } 25 | ] 26 | } 27 | type: Opaque 28 | -------------------------------------------------------------------------------- /client/metricspage/components/NodeMetrics/BytesTransmittedByNode.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const BytesTransmittedByNode = ({ metrics }) => { 6 | /* 7 | Renders the Network IO (Bps) Transmitted by Node line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default BytesTransmittedByNode; 24 | -------------------------------------------------------------------------------- /infra/alertmanager/alertmanager.yml: -------------------------------------------------------------------------------- 1 | route: 2 | group_by: [alertname] 3 | receiver: 'mail' # default receiver 4 | repeat_interval: 24h 5 | routes: 6 | - receiver: 'teams' 7 | repeat_interval: 12h 8 | matchers: 9 | - severity="medium" 10 | 11 | - receiver: 'teams' 12 | repeat_interval: 4h 13 | matchers: 14 | - severity="high" 15 | 16 | receivers: 17 | - name: 'mail' 18 | email_configs: 19 | - smarthost: 'yourmailhost.com:465' 20 | auth_username: 'yourmail@yourmailhost.com' 21 | auth_password: 'your mail password' 22 | from: 'yourmail@yourmailhost.com' 23 | to: 'someonesmail@yourmailhost.com' 24 | require_tls: false 25 | 26 | - name: 'teams' 27 | webhook_configs: 28 | - url: 'http://prom2teams:8089' 29 | send_resolved: true 30 | -------------------------------------------------------------------------------- /manifests/prometheusOperator-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: controller 6 | app.kubernetes.io/name: prometheus-operator 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.53.1 9 | name: prometheus-operator 10 | namespace: monitoring 11 | spec: 12 | endpoints: 13 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 14 | honorLabels: true 15 | port: https 16 | scheme: https 17 | tlsConfig: 18 | insecureSkipVerify: true 19 | selector: 20 | matchLabels: 21 | app.kubernetes.io/component: controller 22 | app.kubernetes.io/name: prometheus-operator 23 | app.kubernetes.io/part-of: kube-prometheus 24 | app.kubernetes.io/version: 0.53.1 25 | -------------------------------------------------------------------------------- /client/metricspage/components/NamespaceMetrics/BytesTransmittedByNamespace.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const BytesTransmittedByNamespace = ({ metrics }) => { 6 | /* 7 | Renders Network IO (Bps) Transmitted by Namespace line chart on the Metrics Page 8 | */ 9 | return ( 10 |
11 | 12 | 18 | 19 |
20 | ); 21 | }; 22 | 23 | export default BytesTransmittedByNamespace; 24 | -------------------------------------------------------------------------------- /client/homepage/components/Utilizations/CpuTotal.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Card, Typography } from '@mui/material'; 4 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 5 | 6 | // CPU used out of total 7 | const CpuTotal = ({ cpu, cpuusage }) => { 8 | return ( 9 | <> 10 | 11 | {cpu * (cpuusage / 100)} 12 | 13 | used 14 | 15 | {cpu} 16 | 17 | total 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default CpuTotal; 25 | -------------------------------------------------------------------------------- /client/metricspage/components/NamespaceMetrics/BytesReceivedByNamespace.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | import { Button } from '@mui/material'; 5 | 6 | const BytesReceivedByNamespace = ({ metrics }) => { 7 | /* 8 | Renders the Network IO (Bps) Received by Namespace line chart on the Metrics Page 9 | */ 10 | return ( 11 |
12 | 13 | 19 | 20 |
21 | ); 22 | }; 23 | 24 | export default BytesReceivedByNamespace; 25 | -------------------------------------------------------------------------------- /client/homepage/containers/CountsContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Grid } from '@mui/material'; 3 | import NodesCount from '../components/Counts/NodesCount'; 4 | import DeploymentsCount from '../components/Counts/DeploymentsCount'; 5 | import PodsCount from '../components/Counts/PodsCount'; 6 | import ServicesCount from '../components/Counts/ServicesCount'; 7 | 8 | const CountsContainer = (props) => { 9 | const { nodes, deployments, pods, services } = props; 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | export default CountsContainer; 29 | -------------------------------------------------------------------------------- /manifests/nodeExporter-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: node-exporter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 1.3.1 9 | name: node-exporter 10 | namespace: monitoring 11 | spec: 12 | endpoints: 13 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 14 | interval: 15s 15 | port: https 16 | relabelings: 17 | - action: replace 18 | regex: (.*) 19 | replacement: $1 20 | sourceLabels: 21 | - __meta_kubernetes_pod_node_name 22 | targetLabel: instance 23 | scheme: https 24 | tlsConfig: 25 | insecureSkipVerify: true 26 | jobLabel: app.kubernetes.io/name 27 | selector: 28 | matchLabels: 29 | app.kubernetes.io/component: exporter 30 | app.kubernetes.io/name: node-exporter 31 | app.kubernetes.io/part-of: kube-prometheus 32 | -------------------------------------------------------------------------------- /client/homepage/components/Utilizations/MemoryTotal.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Card, Typography } from '@mui/material'; 4 | import ComponentWrapper from '../../../utils/ComponentWrapper'; 5 | 6 | const MemoryTotal = ({ memory, memusage }) => { 7 | let memoryinGb; 8 | if (memory) { 9 | memoryinGb = Number((memory / 10 ** 9).toFixed(0)); 10 | } 11 | 12 | return ( 13 | <> 14 | 15 | {memoryinGb} 16 | 17 | used 18 | 19 | 20 | {(memoryinGb / (memusage / 100)).toFixed(0)} 21 | 22 | 23 | total 24 | 25 | 26 | 27 | ); 28 | }; 29 | 30 | export default MemoryTotal; 31 | -------------------------------------------------------------------------------- /server/utils/formatTimeToAvg.js: -------------------------------------------------------------------------------- 1 | const formatChartData = require('./formatChartData'); 2 | 3 | // Format time series data from Prometheus as averages over period of time 4 | function formatTimeToAvg(resp) { 5 | const formatted = formatChartData(resp.data.result); 6 | const seriesValues = formatted.seriesValues; 7 | const newValues = []; 8 | 9 | // Take an average of time series data over the length of the array 10 | seriesValues.forEach((value) => { 11 | const converted = value.map((el) => parseFloat(el)); 12 | newValues.push(converted.reduce((a, b) => a + b) / converted.length); 13 | }); 14 | formatted.seriesValues = newValues; 15 | const resultArr = []; 16 | 17 | // Reformat averaged result with label and data keys for bar graphs on client side 18 | for (let i = 0; i < formatted.seriesLabels.length; i++) { 19 | resultArr.push({ 20 | label: formatted.seriesLabels[i], 21 | data: formatted.seriesValues[i], 22 | }); 23 | } 24 | return resultArr; 25 | } 26 | 27 | module.exports = formatTimeToAvg; 28 | -------------------------------------------------------------------------------- /manifests/prometheusAdapter-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: metrics-adapter 6 | app.kubernetes.io/name: prometheus-adapter 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.9.1 9 | name: prometheus-adapter 10 | namespace: monitoring 11 | spec: 12 | endpoints: 13 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 14 | interval: 30s 15 | metricRelabelings: 16 | - action: drop 17 | regex: (apiserver_client_certificate_.*|apiserver_envelope_.*|apiserver_flowcontrol_.*|apiserver_storage_.*|apiserver_webhooks_.*|workqueue_.*) 18 | sourceLabels: 19 | - __name__ 20 | port: https 21 | scheme: https 22 | tlsConfig: 23 | insecureSkipVerify: true 24 | selector: 25 | matchLabels: 26 | app.kubernetes.io/component: metrics-adapter 27 | app.kubernetes.io/name: prometheus-adapter 28 | app.kubernetes.io/part-of: kube-prometheus 29 | -------------------------------------------------------------------------------- /client/homepage/components/CriticalNodes/ProblematicItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ListItemButton, List, Typography, ListItemText } from '@mui/material'; 3 | 4 | // Component used within ProblematicNodes and ProblematicPods to render each status element 5 | function ProblematicItem({ name, conditions }) { 6 | const conditionsText = () => { 7 | return conditions 8 | .sort( 9 | (a, b) => 10 | Date.parse(a.lastTransitionTime) - Date.parse(b.lastTransitionTime) 11 | ) 12 | .map((c) => ( 13 | {`${c.type}: ${ 14 | c.status 15 | } at ${c.lastTransitionTime.toString()}`} 16 | )); 17 | }; 18 | 19 | return ( 20 | 21 | 22 | 26 | 27 | 28 | ); 29 | } 30 | 31 | export default ProblematicItem; 32 | -------------------------------------------------------------------------------- /server/utils/metricsFetch.js: -------------------------------------------------------------------------------- 1 | const formatChartData = require('./formatChartData'); 2 | const fetch = (...args) => 3 | import('node-fetch').then(({ default: fetch }) => fetch(...args)); 4 | 5 | // Abstracted middleware function that executes metrics queries, formats response to chart data, and stores result in res.locals 6 | const metricsFetch = (query, title, req, res, next) => { 7 | try { 8 | fetch(query) 9 | .then((resp) => resp.json()) 10 | // Return formatted data and query string on res.locals 11 | .then((resp) => { 12 | res.locals[title] = {}; 13 | if (resp.data.result.length !== 0) { 14 | const formatted = formatChartData(resp.data.result); 15 | res.locals[title].data = formatted; 16 | } else res.locals[title].data = null; 17 | res.locals[title].queryString = query; 18 | }) 19 | .then(() => next()); 20 | } catch (err) { 21 | next({ 22 | log: `Error with ${title}`, 23 | message: { err: err.message }, 24 | }); 25 | } 26 | }; 27 | 28 | module.exports = metricsFetch; 29 | -------------------------------------------------------------------------------- /client/metricspage/components/PodMetrics/MemoryUsageByPod.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const MemoryUsageByPod = ({ metrics }) => { 6 | /* 7 | Converts Memory Usage from Bytes to GB 8 | */ 9 | if (metrics.data) { 10 | for (let i = 0; i < metrics.data.seriesValues.length; i++) { 11 | metrics.data.seriesValues[i] = metrics.data.seriesValues[i].map((el) => { 12 | return el / 1000000000; 13 | }); 14 | } 15 | } 16 | /* 17 | Renders Memory Usage (Gb) by Pod line chart on the Metrics Page 18 | */ 19 | return ( 20 |
21 | 22 | 28 | 29 |
30 | ); 31 | }; 32 | 33 | export default MemoryUsageByPod; 34 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16 as kubebuild 2 | RUN apt-get update && apt-get install -y apt-transport-https ca-certificates curl 3 | RUN curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg 4 | RUN echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list 5 | RUN apt-get update && apt-get install -y kubectl 6 | 7 | 8 | 9 | #ADD https://storage.googleapis.com/kubernetes-release/release/v1.6.4/bin/linux/amd64/kubectl /usr/local/bin/kubectl 10 | #ENV HOME=/config \ 11 | # KUBECONFIG=/etc/kubernetes/admin.conf 12 | #RUN set -x && \ 13 | # apk add --no-cache curl ca-certificates && \ 14 | # chmod +x /usr/local/bin/kubectl 15 | 16 | #your app container 17 | FROM kubebuild as armada 18 | 19 | WORKDIR /usr/src/app 20 | 21 | RUN npm install -g webpack nodemon 22 | 23 | COPY . /usr/src/app/ 24 | 25 | RUN npm install 26 | 27 | RUN npm run build 28 | 29 | EXPOSE 3001 30 | 31 | # CMD [ "npm", "run", "dev" ] 32 | CMD [ "npm", "run", "start" ] 33 | -------------------------------------------------------------------------------- /client/metricspage/components/NodeMetrics/MemoryUsageByNode.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const MemoryUsageByNode = ({ metrics }) => { 6 | /* 7 | Converts Memory Usage from Bytes to GB 8 | */ 9 | if (metrics.data) { 10 | for (let i = 0; i < metrics.data.seriesValues.length; i++) { 11 | metrics.data.seriesValues[i] = metrics.data.seriesValues[i].map((el) => { 12 | return el / 1000000000; 13 | }); 14 | } 15 | } 16 | 17 | /* 18 | Renders the Memory Usage (Gb) By Node line chart on the Metrics Page 19 | */ 20 | 21 | return ( 22 |
23 | 24 | 30 | 31 |
32 | ); 33 | }; 34 | 35 | export default MemoryUsageByNode; 36 | -------------------------------------------------------------------------------- /client/homepage/components/Refresh.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { Box, Typography, Button } from '@mui/material'; 3 | 4 | // Refresh omponent to refetch data. Passed down handleRefresh from MainContainer 5 | const Refresh = ({ handleRefresh, lastUpdated }) => { 6 | useEffect(() => {}, [handleRefresh, lastUpdated]); 7 | return ( 8 | 11 | 16 | Last updated at {Date(lastUpdated).toString()} 17 | 18 | 30 | 31 | ); 32 | }; 33 | 34 | export default Refresh; 35 | -------------------------------------------------------------------------------- /client/logspage/containers/LogsContainer.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import LogsTable from '../components/LogsTable'; 4 | 5 | function LogsContainer({ namespace }) { 6 | const [logs, setLogs] = useState([]); 7 | const getLogs = () => { 8 | fetch('/api/logs') 9 | .then((res) => res.json()) 10 | .then((data) => setLogs(data)) 11 | .catch((err) => console.log(err)); 12 | }; 13 | useEffect(() => { 14 | getLogs(); 15 | }, [namespace]); 16 | 17 | const filterByNamespace = () => { 18 | if (namespace !== 'All' && namespace !== '') { 19 | return logs.filter((log) => log.namespace === namespace); 20 | } 21 | return logs; 22 | }; 23 | // console.log('logs filtered', filterByNamespace()); 24 | return ; 25 | } 26 | 27 | const mapStateToProps = ({ namespace }) => { 28 | console.log('namespace', namespace); 29 | return { namespace: namespace.selectedNamespace }; 30 | }; 31 | 32 | export default connect(mapStateToProps)(LogsContainer); 33 | -------------------------------------------------------------------------------- /manifests/alertmanager-alertmanager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: Alertmanager 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: alert-router 6 | app.kubernetes.io/instance: main 7 | app.kubernetes.io/name: alertmanager 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 0.23.0 10 | name: main 11 | namespace: monitoring 12 | spec: 13 | image: quay.io/prometheus/alertmanager:v0.23.0 14 | nodeSelector: 15 | kubernetes.io/os: linux 16 | podMetadata: 17 | labels: 18 | app.kubernetes.io/component: alert-router 19 | app.kubernetes.io/instance: main 20 | app.kubernetes.io/name: alertmanager 21 | app.kubernetes.io/part-of: kube-prometheus 22 | app.kubernetes.io/version: 0.23.0 23 | replicas: 3 24 | resources: 25 | limits: 26 | cpu: 100m 27 | memory: 100Mi 28 | requests: 29 | cpu: 4m 30 | memory: 100Mi 31 | securityContext: 32 | fsGroup: 2000 33 | runAsNonRoot: true 34 | runAsUser: 1000 35 | serviceAccountName: alertmanager-main 36 | version: 0.23.0 37 | -------------------------------------------------------------------------------- /client/metricspage/components/NamespaceMetrics/MemoryUsageByNamespace.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LineChart from '../../../homepage/components/Charts/LineChartTemplate'; 3 | import MetricsComponentWrapper from '../../../utils/MetricsComponentWrapper'; 4 | 5 | const MemoryUsageByNamespace = ({ metrics }) => { 6 | /* 7 | Converts Memory Usage from Bytes to GB 8 | */ 9 | if (metrics.data) { 10 | for (let i = 0; i < metrics.data.seriesValues.length; i++) { 11 | metrics.data.seriesValues[i] = metrics.data.seriesValues[i].map((el) => { 12 | return el / 1000000000; 13 | }); 14 | } 15 | } 16 | /* 17 | Renders Memory Usage (Gb) by Namespace line chart on the Metrics Page 18 | */ 19 | return ( 20 |
21 | 22 | 28 | 29 |
30 | ); 31 | }; 32 | 33 | export default MemoryUsageByNamespace; 34 | -------------------------------------------------------------------------------- /client/actions/actions.js: -------------------------------------------------------------------------------- 1 | import { 2 | FETCH_NODES_LIST, 3 | FETCH_PODS_LIST, 4 | SET_NAMESPACE, 5 | FETCH_DEPLOYMENTS_LIST, 6 | FETCH_NAMESPACES_LIST, 7 | FETCH_SERVICES_LIST, 8 | FETCH_PROM_METRICS, 9 | } from './constants/actionTypes'; 10 | 11 | export const first = (payload) => ({ 12 | type: second, 13 | payload, 14 | }); 15 | 16 | export const fetchNodesList = (payload) => ({ 17 | type: FETCH_NODES_LIST, 18 | payload, 19 | }); 20 | 21 | export const fetchPodsList = (payload) => ({ 22 | type: FETCH_PODS_LIST, 23 | payload, 24 | }); 25 | 26 | export const setNamespace = (payload) => ({ 27 | type: SET_NAMESPACE, 28 | payload, 29 | }); 30 | 31 | export const fetchNamespacesList = (payload) => ({ 32 | type: FETCH_NAMESPACES_LIST, 33 | payload, 34 | }); 35 | 36 | export const fetchServicesList = (payload) => ({ 37 | type: FETCH_SERVICES_LIST, 38 | payload, 39 | }); 40 | 41 | export const fetchDeploymentsList = (payload) => ({ 42 | type: FETCH_DEPLOYMENTS_LIST, 43 | payload, 44 | }); 45 | 46 | export const fetchPromMetrics = (payload) => ({ 47 | type: FETCH_PROM_METRICS, 48 | payload, 49 | }); 50 | -------------------------------------------------------------------------------- /client/custompage/components/StepBar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import IconButton from '@mui/material/IconButton'; 3 | import TextField from '@mui/material/TextField'; 4 | import { Autocomplete } from '@mui/material'; 5 | import { Paper } from '@mui/material'; 6 | 7 | const optionsArray = [ 8 | { label: '30 seconds' }, 9 | { label: '1 minute' }, 10 | { label: '2 minutes' }, 11 | { label: '5 minutes' }, 12 | { label: '10 minutes' }, 13 | ]; 14 | /* Renders step range dropdown on Custom Metrics page */ 15 | 16 | const StepBar = ({ searchquerystep, setsearchquerystep }) => ( 17 | ( 21 | {children} 22 | )} 23 | options={optionsArray} 24 | sx={{ width: 200 }} 25 | renderInput={(params) => } 26 | searchquery={searchquerystep} 27 | onInputChange={(e, newInputValue) => { 28 | e.preventDefault(); 29 | setsearchquerystep(newInputValue); 30 | }} 31 | /> 32 | ); 33 | 34 | export default StepBar; 35 | -------------------------------------------------------------------------------- /infra/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | prometheus: 5 | image: prom/prometheus:v2.30.3 6 | ports: 7 | - 9090:9090 8 | volumes: 9 | - ./prometheus:/etc/prometheus 10 | - prometheus-data:/prometheus 11 | command: --web.enable-lifecycle --config.file=/etc/prometheus/prometheus.yml 12 | 13 | grafana: 14 | image: grafana/grafana:8.2.2 15 | ports: 16 | - 3000:3000 17 | restart: unless-stopped 18 | volumes: 19 | - ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources 20 | - grafana-data:/var/lib/grafana 21 | 22 | alertmanager: 23 | image: prom/alertmanager:v0.23.0 24 | restart: unless-stopped 25 | ports: 26 | - '9093:9093' 27 | volumes: 28 | - './alertmanager:/config' 29 | - alertmanager-data:/data 30 | command: --config.file=/config/alertmanager.yml --log.level=debug 31 | 32 | node-exporter: 33 | image: prom/node-exporter:latest 34 | container_name: monitoring_node_exporter 35 | restart: unless-stopped 36 | expose: 37 | - 9100 38 | 39 | volumes: 40 | prometheus-data: 41 | 42 | grafana-data: 43 | 44 | alertmanager-data: 45 | -------------------------------------------------------------------------------- /manifests/kubeStateMetrics-serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: exporter 6 | app.kubernetes.io/name: kube-state-metrics 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 2.3.0 9 | name: kube-state-metrics 10 | namespace: monitoring 11 | spec: 12 | endpoints: 13 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 14 | honorLabels: true 15 | interval: 30s 16 | port: https-main 17 | relabelings: 18 | - action: labeldrop 19 | regex: (pod|service|endpoint|namespace) 20 | scheme: https 21 | scrapeTimeout: 30s 22 | tlsConfig: 23 | insecureSkipVerify: true 24 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 25 | interval: 30s 26 | port: https-self 27 | scheme: https 28 | tlsConfig: 29 | insecureSkipVerify: true 30 | jobLabel: app.kubernetes.io/name 31 | selector: 32 | matchLabels: 33 | app.kubernetes.io/component: exporter 34 | app.kubernetes.io/name: kube-state-metrics 35 | app.kubernetes.io/part-of: kube-prometheus 36 | -------------------------------------------------------------------------------- /client/custompage/components/SearchBar.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import IconButton from '@mui/material/IconButton'; 3 | import TextField from '@mui/material/TextField'; 4 | import { Autocomplete } from '@mui/material'; 5 | import { Paper } from '@mui/material'; 6 | 7 | const SearchBar = ({ searchquery, setsearchquery, options }) => { 8 | let optionsArray = []; 9 | if (options) { 10 | for (let i = 0; i < options.length; i++) { 11 | optionsArray.push({ label: options[i] }); 12 | } 13 | } 14 | /* Renders options dropdown on Custom Metrics page */ 15 | 16 | return ( 17 | ( 21 | {children} 22 | )} 23 | options={optionsArray} 24 | sx={{ width: 500 }} 25 | renderInput={(params) => } 26 | searchquery={searchquery} 27 | onInputChange={(e, newInputValue) => { 28 | e.preventDefault(); 29 | setsearchquery(newInputValue); 30 | }} 31 | /> 32 | ); 33 | }; 34 | 35 | export default SearchBar; 36 | -------------------------------------------------------------------------------- /client/custompage/components/TimeRangeBar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import IconButton from '@mui/material/IconButton'; 3 | import TextField from '@mui/material/TextField'; 4 | import { Autocomplete } from '@mui/material'; 5 | import { Paper } from '@mui/material'; 6 | 7 | const optionsArray = [ 8 | { label: '30 minutes' }, 9 | { label: '1 hour' }, 10 | { label: '2 hours' }, 11 | { label: '5 hours' }, 12 | { label: '12 hours' }, 13 | { label: '24 hours' }, 14 | { label: '48 hours' }, 15 | ]; 16 | /* Renders time range dropdown on Custom Metrics page */ 17 | 18 | const TimeRangeBar = ({ searchquerytime, setsearchquerytime }) => ( 19 | ( 23 | {children} 24 | )} 25 | options={optionsArray} 26 | sx={{ width: 200 }} 27 | renderInput={(params) => } 28 | searchquery={searchquerytime} 29 | onInputChange={(e, newInputValue) => { 30 | e.preventDefault(); 31 | setsearchquerytime(newInputValue); 32 | }} 33 | /> 34 | ); 35 | 36 | export default TimeRangeBar; 37 | -------------------------------------------------------------------------------- /manifests/alertmanager-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: alert-router 6 | app.kubernetes.io/instance: main 7 | app.kubernetes.io/name: alertmanager 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 0.23.0 10 | name: alertmanager-main 11 | namespace: monitoring 12 | stringData: 13 | alertmanager.yaml: |- 14 | "global": 15 | "resolve_timeout": "5m" 16 | "inhibit_rules": 17 | - "equal": 18 | - "namespace" 19 | - "alertname" 20 | "source_matchers": 21 | - "severity = critical" 22 | "target_matchers": 23 | - "severity =~ warning|info" 24 | - "equal": 25 | - "namespace" 26 | - "alertname" 27 | "source_matchers": 28 | - "severity = warning" 29 | "target_matchers": 30 | - "severity = info" 31 | "receivers": 32 | - "name": "Default" 33 | - "name": "Watchdog" 34 | - "name": "Critical" 35 | "route": 36 | "group_by": 37 | - "namespace" 38 | "group_interval": "5m" 39 | "group_wait": "30s" 40 | "receiver": "Default" 41 | "repeat_interval": "12h" 42 | "routes": 43 | - "matchers": 44 | - "alertname = Watchdog" 45 | "receiver": "Watchdog" 46 | - "matchers": 47 | - "severity = critical" 48 | "receiver": "Critical" 49 | type: Opaque 50 | -------------------------------------------------------------------------------- /server/utils/formatChartData.js: -------------------------------------------------------------------------------- 1 | function formatChartData(data) { 2 | try { 3 | const res = { 4 | timestamps: [], 5 | seriesLabels: [], 6 | seriesValues: [], 7 | }; 8 | 9 | // Helper function to convert the Prometheus MS timestamp to HH:MM 10 | const timeFilter = /[0-9][0-9]:[0-9][0-9]/; 11 | const msToTimestamp = (ms) => 12 | new Date(1000 * ms).toISOString().match(timeFilter)[0]; 13 | 14 | // Pop the last series off the query response to extract timestamp and groupBy label 15 | const initialSet = data.pop(); 16 | const groupByLabel = Object.keys(initialSet.metric)[0]; 17 | 18 | // Add this last series to the response object arrays 19 | res.timestamps = initialSet.values.map((vals) => msToTimestamp(vals[0])); 20 | res.seriesLabels.push(initialSet.metric[groupByLabel] || 'Cluster'); 21 | res.seriesValues.push(initialSet.values.map((vals) => vals[1])); 22 | 23 | // For each remaining dataset, push the series label and array of datapoints onto the res object 24 | data.forEach((dataset) => { 25 | res.seriesLabels.push(dataset.metric[groupByLabel]); // add a new dataseries label to our res 26 | res.seriesValues.push(dataset.values.map((vals) => vals[1])); // add the dataseries to our res 27 | }); 28 | 29 | // Return the constructed response 30 | return res; 31 | } catch (err) { 32 | console.log(err); 33 | } 34 | } 35 | 36 | module.exports = formatChartData; 37 | -------------------------------------------------------------------------------- /manifests/prometheus-prometheus.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: Prometheus 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: prometheus 6 | app.kubernetes.io/instance: k8s 7 | app.kubernetes.io/name: prometheus 8 | app.kubernetes.io/part-of: kube-prometheus 9 | app.kubernetes.io/version: 2.32.1 10 | name: k8s 11 | namespace: monitoring 12 | spec: 13 | alerting: 14 | alertmanagers: 15 | - apiVersion: v2 16 | name: alertmanager-main 17 | namespace: monitoring 18 | port: web 19 | enableFeatures: [] 20 | externalLabels: {} 21 | image: quay.io/prometheus/prometheus:v2.32.1 22 | nodeSelector: 23 | kubernetes.io/os: linux 24 | podMetadata: 25 | labels: 26 | app.kubernetes.io/component: prometheus 27 | app.kubernetes.io/instance: k8s 28 | app.kubernetes.io/name: prometheus 29 | app.kubernetes.io/part-of: kube-prometheus 30 | app.kubernetes.io/version: 2.32.1 31 | podMonitorNamespaceSelector: {} 32 | podMonitorSelector: {} 33 | probeNamespaceSelector: {} 34 | probeSelector: {} 35 | replicas: 2 36 | resources: 37 | requests: 38 | memory: 400Mi 39 | ruleNamespaceSelector: {} 40 | ruleSelector: {} 41 | securityContext: 42 | fsGroup: 2000 43 | runAsNonRoot: true 44 | runAsUser: 1000 45 | serviceAccountName: prometheus-k8s 46 | serviceMonitorNamespaceSelector: {} 47 | serviceMonitorSelector: {} 48 | version: 2.32.1 49 | -------------------------------------------------------------------------------- /armada-depl.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: armada 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: armada 10 | template: 11 | metadata: 12 | labels: 13 | app: armada 14 | spec: 15 | containers: 16 | - name: armada 17 | image: armadak8s:latest 18 | ports: 19 | - containerPort: 80 20 | protocol: TCP 21 | imagePullPolicy: IfNotPresent 22 | --- 23 | apiVersion: v1 24 | kind: Service 25 | metadata: 26 | name: armada 27 | labels: 28 | prometheus: cluster-monitoring 29 | k8s-app: kube-state-metrics 30 | spec: 31 | selector: 32 | app: armada 33 | type: LoadBalancer 34 | ports: 35 | - name: armada 36 | protocol: TCP 37 | port: 8080 38 | targetPort: 8080 39 | # NOTE: The service account `default:default` already exists in k8s cluster. 40 | # You can create a new account following like this: 41 | #--- 42 | #apiVersion: v1 43 | #kind: ServiceAccount 44 | #metadata: 45 | # name: 46 | # namespace: 47 | 48 | --- 49 | apiVersion: rbac.authorization.k8s.io/v1 50 | kind: ClusterRoleBinding 51 | metadata: 52 | name: fabric8-rbac 53 | subjects: 54 | - kind: ServiceAccount 55 | # Reference to upper's `metadata.name` 56 | name: default 57 | # Reference to upper's `metadata.namespace` 58 | namespace: default 59 | roleRef: 60 | kind: ClusterRole 61 | name: cluster-admin 62 | apiGroup: rbac.authorization.k8s.io 63 | -------------------------------------------------------------------------------- /client/utils/table/helpers.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // filtering 3 | // default UI for filtering 4 | export function DefaultColumnFilter({ 5 | column: { filterValue, preFilteredRows, setFilter }, 6 | }) { 7 | const count = preFilteredRows.length; 8 | 9 | return ( 10 | { 13 | setFilter(e.target.value || undefined); 14 | }} 15 | placeholder={''} 16 | /> 17 | ); 18 | } 19 | 20 | //filter for selecting option from list 21 | export function SelectColumnFilter({ 22 | column: { filterValue, setFilter, preFilteredRows, id }, 23 | }) { 24 | const options = React.useMemo(() => { 25 | const options = new Set(); 26 | preFilteredRows.forEach((row) => { 27 | options.add(row.values[id]); 28 | }); 29 | return [...options.values()]; 30 | }, [id, preFilteredRows]); 31 | 32 | // render a multi-select box 33 | return ( 34 | 47 | ); 48 | } 49 | 50 | //fuzzy text filter 51 | export function fuzzyTextFilterFn(rows, id, filterValue) { 52 | return matchSorter(rows, filterValue, { keys: [(row) => row.values[id]] }); 53 | } 54 | 55 | fuzzyTextFilterFn.autoRemove = (val) => !val; 56 | -------------------------------------------------------------------------------- /manifests/blackboxExporter-configuration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | config.yml: |- 4 | "modules": 5 | "http_2xx": 6 | "http": 7 | "preferred_ip_protocol": "ip4" 8 | "prober": "http" 9 | "http_post_2xx": 10 | "http": 11 | "method": "POST" 12 | "preferred_ip_protocol": "ip4" 13 | "prober": "http" 14 | "irc_banner": 15 | "prober": "tcp" 16 | "tcp": 17 | "preferred_ip_protocol": "ip4" 18 | "query_response": 19 | - "send": "NICK prober" 20 | - "send": "USER prober prober prober :prober" 21 | - "expect": "PING :([^ ]+)" 22 | "send": "PONG ${1}" 23 | - "expect": "^:[^ ]+ 001" 24 | "pop3s_banner": 25 | "prober": "tcp" 26 | "tcp": 27 | "preferred_ip_protocol": "ip4" 28 | "query_response": 29 | - "expect": "^+OK" 30 | "tls": true 31 | "tls_config": 32 | "insecure_skip_verify": false 33 | "ssh_banner": 34 | "prober": "tcp" 35 | "tcp": 36 | "preferred_ip_protocol": "ip4" 37 | "query_response": 38 | - "expect": "^SSH-2.0-" 39 | "tcp_connect": 40 | "prober": "tcp" 41 | "tcp": 42 | "preferred_ip_protocol": "ip4" 43 | kind: ConfigMap 44 | metadata: 45 | labels: 46 | app.kubernetes.io/component: exporter 47 | app.kubernetes.io/name: blackbox-exporter 48 | app.kubernetes.io/part-of: kube-prometheus 49 | app.kubernetes.io/version: 0.19.0 50 | name: blackbox-exporter-configuration 51 | namespace: monitoring 52 | -------------------------------------------------------------------------------- /client/homepage/containers/CriticalPodsContainer.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { Grid } from '@mui/material'; 3 | import CPUIntensivePods from '../components/CriticalPods/CPUIntensivePods'; 4 | import MemoryIntensivePods from '../components/CriticalPods/MemoryIntensivePods'; 5 | 6 | const CriticalPodsContainer = (props) => { 7 | const { namespace } = props; 8 | 9 | const [cpu, setCpu] = useState([]); 10 | const [memory, setMemory] = useState([]); 11 | const fetchCpuByPod = () => { 12 | fetch(`/api/prometheus/cpubypod?namespace=${namespace}`) 13 | .then((res) => res.json()) 14 | .then((data) => { 15 | // console.log('cpu data ' + data); 16 | setCpu(data); 17 | }) 18 | .catch((err) => console.log(err)); 19 | }; 20 | 21 | const fetchMemoryByPod = () => { 22 | fetch(`/api/prometheus/memorybypod?namespace=${namespace}`) 23 | .then((res) => res.json()) 24 | .then((data) => { 25 | setMemory(data); 26 | console.log(data); 27 | }) 28 | .catch((err) => console.log(err)); 29 | }; 30 | 31 | useEffect(() => { 32 | fetchCpuByPod(); 33 | fetchMemoryByPod(); 34 | }, [namespace]); 35 | 36 | const renderCpuGraph = () => { 37 | if (cpu) { 38 | return ; 39 | } 40 | }; 41 | 42 | const renderMemory = () => { 43 | if (memory) { 44 | return ; 45 | } 46 | }; 47 | 48 | return ( 49 | 50 | 51 | {renderCpuGraph()} 52 | 53 | 54 | {renderMemory()} 55 | 56 | 57 | ); 58 | }; 59 | 60 | export default CriticalPodsContainer; 61 | -------------------------------------------------------------------------------- /client/homepage/components/Charts/BarChartTemplate.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Chart as ChartJS, 4 | CategoryScale, 5 | LinearScale, 6 | BarElement, 7 | Title, 8 | Tooltip, 9 | Legend, 10 | } from 'chart.js'; 11 | import { Bar } from 'react-chartjs-2'; 12 | 13 | ChartJS.register( 14 | CategoryScale, 15 | LinearScale, 16 | BarElement, 17 | Title, 18 | Tooltip, 19 | Legend 20 | ); 21 | 22 | const BarChart = ({ chartData, title, label }) => { 23 | const options = { 24 | indexAxis: 'y', 25 | elements: { 26 | bar: { 27 | borderWidth: 2, 28 | }, 29 | }, 30 | responsive: true, 31 | plugins: { 32 | legend: { 33 | display: false, 34 | }, 35 | title: { 36 | display: true, 37 | text: title, 38 | color: 'white', 39 | font: { weight: 'bold' }, 40 | }, 41 | datalabels: { 42 | // hide datalabels for all datasets 43 | display: false, 44 | }, 45 | }, 46 | scales: { 47 | xAxes: { 48 | display: true, 49 | ticks: { 50 | color: 'white', 51 | }, 52 | }, 53 | yAxes: { 54 | display: true, 55 | ticks: { 56 | color: 'white', 57 | }, 58 | }, 59 | }, 60 | }; 61 | const data = { 62 | labels: chartData.map((el) => el.label), 63 | datasets: [ 64 | { 65 | // label, 66 | data: chartData.map((el) => el.data), 67 | borderColor: 'transparent', 68 | backgroundColor: 'rgb(140, 92, 142)', 69 | }, 70 | ], 71 | }; 72 | 73 | return ; 74 | }; 75 | 76 | export default BarChart; 77 | 78 | // horizontal bar charts 79 | -------------------------------------------------------------------------------- /client/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter, Routes, Route } from 'react-router-dom'; 3 | import { ThemeProvider, createTheme } from '@mui/material/styles'; 4 | import MainContainer from './homepage/containers/MainContainer'; 5 | import NavBar from './homepage/containers/NavBar'; 6 | import MetricsContainer from './metricspage/containers/MetricsContainer'; 7 | import Alerts from './alertspage/Alerts'; 8 | import { Container, Box } from '@mui/material'; 9 | import { blueGrey } from '@mui/material/colors'; 10 | import LogsContainer from './logspage/containers/LogsContainer'; 11 | import CustomMetricsContainer from './custompage/containers/CustomMetricsContainer'; 12 | 13 | /* Applies MUI dark theme */ 14 | 15 | const darkTheme = createTheme({ 16 | palette: { 17 | mode: 'dark', 18 | background: { 19 | default: '#121212', 20 | paper: 'rgba(255, 255, 255, 0.08)', 21 | }, 22 | text: { 23 | primary: '#fff', 24 | }, 25 | }, 26 | }); 27 | 28 | /* Leveraging React Router to create multiple views within single page application */ 29 | function App() { 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 | } /> 37 | } /> 38 | } /> 39 | } /> 40 | } /> 41 | 42 | 43 | 44 | 45 | 46 | ); 47 | } 48 | 49 | export default App; 50 | -------------------------------------------------------------------------------- /manifests/prometheusOperator-clusterRole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/component: controller 6 | app.kubernetes.io/name: prometheus-operator 7 | app.kubernetes.io/part-of: kube-prometheus 8 | app.kubernetes.io/version: 0.53.1 9 | name: prometheus-operator 10 | rules: 11 | - apiGroups: 12 | - monitoring.coreos.com 13 | resources: 14 | - alertmanagers 15 | - alertmanagers/finalizers 16 | - alertmanagerconfigs 17 | - prometheuses 18 | - prometheuses/finalizers 19 | - thanosrulers 20 | - thanosrulers/finalizers 21 | - servicemonitors 22 | - podmonitors 23 | - probes 24 | - prometheusrules 25 | verbs: 26 | - '*' 27 | - apiGroups: 28 | - apps 29 | resources: 30 | - statefulsets 31 | verbs: 32 | - '*' 33 | - apiGroups: 34 | - "" 35 | resources: 36 | - configmaps 37 | - secrets 38 | verbs: 39 | - '*' 40 | - apiGroups: 41 | - "" 42 | resources: 43 | - pods 44 | verbs: 45 | - list 46 | - delete 47 | - apiGroups: 48 | - "" 49 | resources: 50 | - services 51 | - services/finalizers 52 | - endpoints 53 | verbs: 54 | - get 55 | - create 56 | - update 57 | - delete 58 | - apiGroups: 59 | - "" 60 | resources: 61 | - nodes 62 | verbs: 63 | - list 64 | - watch 65 | - apiGroups: 66 | - "" 67 | resources: 68 | - namespaces 69 | verbs: 70 | - get 71 | - list 72 | - watch 73 | - apiGroups: 74 | - networking.k8s.io 75 | resources: 76 | - ingresses 77 | verbs: 78 | - get 79 | - list 80 | - watch 81 | - apiGroups: 82 | - authentication.k8s.io 83 | resources: 84 | - tokenreviews 85 | verbs: 86 | - create 87 | - apiGroups: 88 | - authorization.k8s.io 89 | resources: 90 | - subjectaccessreviews 91 | verbs: 92 | - create 93 | -------------------------------------------------------------------------------- /client/namespaceSelection/SelectNamespace.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import Select from 'react-select'; 4 | import { setNamespace, fetchNamespacesList } from '../actions/actions'; 5 | 6 | function SelectNamespace({ 7 | selectedNamespace, 8 | setNamespace, 9 | fetchNamespacesList, 10 | }) { 11 | const [namespaceOptions, setNamespaceOptions] = useState([]); 12 | /* Fetch list of Namespaces from backend API endpoint that connects to prometheus*/ 13 | const getNamespaceList = () => { 14 | fetch('/api/namespaceList') 15 | .then((res) => res.json()) 16 | .then((data) => { 17 | let names = ['All']; 18 | data.items.forEach((item) => { 19 | names.push(item.metadata.name); 20 | }); 21 | fetchNamespacesList(names); 22 | return names; 23 | }) 24 | .then((list) => { 25 | const options = list.map((el) => { 26 | return { value: el, label: el }; 27 | }); 28 | setNamespaceOptions(options); 29 | }) 30 | .catch((error) => console.log(error)); 31 | }; 32 | useEffect(() => { 33 | getNamespaceList(); 34 | }, []); 35 | 36 | function handleNamespaceChange(namespace) { 37 | setNamespace(namespace.value); 38 | } 39 | 40 | return ( 41 |