mirror of https://github.com/rancher/dashboard.git
Merge pull request #1364 from westlywright/bugs.monitoring.alerting
Monitoring/Alerting V2 Bugs
This commit is contained in:
commit
e780574fb8
|
|
@ -155,27 +155,27 @@ backupRestoreOperator:
|
|||
label: Prune
|
||||
tip: Delete all resources that match the ResourceSet used, but are not present in the backup. (Recommended)
|
||||
encryption: Encryption
|
||||
encryptionConfigName:
|
||||
encryptionConfigName:
|
||||
label: Encryption Config Secret
|
||||
tip: If the backup was performed with encryption enabled, a Secret containing the same encryption-provider-config should be used during restore.
|
||||
options:
|
||||
none: Store the contents of the backup unencrypted
|
||||
secret: Encrypt backups using an <a target="_blank" rel='noopener nofollow' href="https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/#understanding-the-encryption-at-rest-configuration">Encryption Config Secret</a> (Recommended)
|
||||
deleteTimeout:
|
||||
deleteTimeout:
|
||||
label: Delete Timeout
|
||||
tip: Seconds to wait for a resource delete to succeed before removing finalizers to force deletion.
|
||||
resourceSetName: Resource Set
|
||||
schedule:
|
||||
schedule:
|
||||
label: Schedule
|
||||
placeholder: e.g. @midnight or 0 0 * * *
|
||||
options:
|
||||
options:
|
||||
disabled: One-Time Backup
|
||||
enabled: Recurring Backups
|
||||
restoreFrom:
|
||||
existing: An existing backup config
|
||||
default: The default storage target
|
||||
s3: An S3-compatible object store
|
||||
retentionCount:
|
||||
retentionCount:
|
||||
label: Retention Count
|
||||
units: |-
|
||||
{count, plural,
|
||||
|
|
@ -586,7 +586,7 @@ istio:
|
|||
customOverlayFile:
|
||||
label: Custom Overlay File
|
||||
tip: 'The <a target="_blank" rel="noopener noreferrer nofollow" href="https://istio.io/latest/docs/setup/install/istioctl/#customizing-the-configuration">overlay file</a> allows for additional configuration on top of the base Rancher Istio installation. You can utilize the <a href="https://istio.io/latest/docs/reference/config/istio.operator.v1alpha1/" target="_blank" rel="noopener noreferrer nofollow" >IstioOperator API</a> to make changes and additions for all components and apply those changes via this overlay YAML file.'
|
||||
description: 'Rancher Istio helm chart installs a minimal Istio configuration for you to get started integrating with your applications.
|
||||
description: 'Rancher Istio helm chart installs a minimal Istio configuration for you to get started integrating with your applications.
|
||||
If you would like to get additional information about Istio, visit <a target="_blank" href="https://istio.io/latest/docs/concepts/what-is-istio" rel="noopener nofollow">https://istio.io/latest/docs/concepts/what-is-istio/</a>'
|
||||
egressGateway: Enabled Egress Gateway
|
||||
ingressGateway: Enabled Ingress Gateway
|
||||
|
|
@ -623,7 +623,7 @@ logging:
|
|||
indexName: Index Name
|
||||
user: User
|
||||
password: Password
|
||||
caFile:
|
||||
caFile:
|
||||
label: Certificate Authority File
|
||||
clientCert:
|
||||
label: Client Cert
|
||||
|
|
@ -740,20 +740,17 @@ monitoring:
|
|||
subtitle: "Powered By: <a href='https://github.com/coreos/prometheus-operator' target='_blank' rel='noopener nofollow' >Prometheus</a>"
|
||||
linkedList:
|
||||
alertManager:
|
||||
label: 'AlertManager'
|
||||
tooltip: 'View Active Alerts'
|
||||
label: 'AlertManager - Active Alerts'
|
||||
grafana:
|
||||
label: 'Grafana'
|
||||
tooltip: 'View Metrics Dashboards'
|
||||
label: 'Grafana - Metrics Dashboards'
|
||||
na: Resource Unavailable
|
||||
prometheusPromQl:
|
||||
label: 'Prometheus PromQL Graph'
|
||||
tooltip: 'View PromQL Graph'
|
||||
label: 'Prometheus - PromQL Graph'
|
||||
prometheusRules:
|
||||
label: 'Prometheus Rules'
|
||||
tooltip: 'View Configured Rules'
|
||||
label: 'Prometheus - Configured Rules'
|
||||
prometheusTargets:
|
||||
label: 'Prometheus Targets'
|
||||
tooltip: 'View Configured Targets'
|
||||
label: 'Prometheus - Configured Targets'
|
||||
warning: Monitoring V1 is currently deployed. If you are migrating from an older version of Rancher with Monitoring enabled, please disable Monitoring on this cluster completely before attempting to install the new Rancher Monitoring chart.
|
||||
prometheus:
|
||||
config:
|
||||
adminApi: Admin API
|
||||
|
|
@ -1382,7 +1379,7 @@ workload:
|
|||
parallelism:
|
||||
label: Parallelism
|
||||
tip: The maximum number of pods the job should run at any given time.
|
||||
startingDeadlineSeconds:
|
||||
startingDeadlineSeconds:
|
||||
label: Starting Deadline Seconds
|
||||
tip: The deadline in seconds for starting the job if it misses scheduled time
|
||||
successfulJobsHistoryLimit:
|
||||
|
|
@ -1560,8 +1557,8 @@ workload:
|
|||
volumeName: Volume Name
|
||||
volumePath: Volume Path
|
||||
typeDescriptions:
|
||||
apps.daemonset: DaemonSets run exactly one pod on every eligible node. When new nodes are added to the cluster, DaemonSets automatically deploy to them. Recommended for system-wide or vertically-scalable workloads that never need more than one pod per node. <a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/" target="_blank" rel="noopener nofollow">More Info <i class="icon icon-external-link" /></a>
|
||||
apps.deployment: Deployments run a scalable number of replicas of a pod distributed among the eligible nodes. Changes are rolled out incrementally and can be rolled back to the previous revision when needed. Recommended for stateless & horizontally-scalable workloads. <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" target="_blank" rel="noopener nofollow">More Info <i class="icon icon-external-link" /></a>
|
||||
apps.daemonset: DaemonSets run exactly one pod on every eligible node. When new nodes are added to the cluster, DaemonSets automatically deploy to them. Recommended for system-wide or vertically-scalable workloads that never need more than one pod per node. <a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/" target="_blank" rel="noopener nofollow">More Info <i class="icon icon-external-link" /></a>
|
||||
apps.deployment: Deployments run a scalable number of replicas of a pod distributed among the eligible nodes. Changes are rolled out incrementally and can be rolled back to the previous revision when needed. Recommended for stateless & horizontally-scalable workloads. <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" target="_blank" rel="noopener nofollow">More Info <i class="icon icon-external-link" /></a>
|
||||
apps.statefulset: StatefulSets manage stateful applications and provide guarantees about the ordering and uniqueness of the pods created. Recommended for workloads with persistent storage or strict identity, quorum, or upgrade order requirements. <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/" target="_blank" rel="noopener nofollow">More Info <i class="icon icon-external-link" /></a>
|
||||
batch.cronjob: CronJobs create Jobs, which then run Pods, on a repeating schedule. The schedule is expressed in standard Unix cron format, and uses the timezone of the Kubernetes control plane (typically UTC). <a href="https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/" target="_blank" rel="noopener nofollow">More Info <i class="icon icon-external-link" /></a>
|
||||
batch.job: Jobs create one or more pods to reliably perform a one-time task by running a pod until it exits successfully. Failed pods are automatically replaced until the specified number of completed runs has been reached. Jobs can also run multiple pods in parallel or function as a batch work queue. <a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/" target="_blank" rel="noopener nofollow">More Info <i class="icon icon-external-link" /></a>
|
||||
|
|
@ -1653,7 +1650,7 @@ typeDescription:
|
|||
# Map of
|
||||
# type: Description to be shown on the top of list view describing the type.
|
||||
# Should fit on one line.
|
||||
# If you link to anything external, it must have
|
||||
# If you link to anything external, it must have
|
||||
# target="_blank" rel="noopener noreferrer nofollow"
|
||||
cis.cattle.io.clusterscanbenchmark: A benchmark version is the name of benchmark to run using kube-bench as well as the valid configuration parameters for that benchmark.
|
||||
cis.cattle.io.clusterscanprofile: A profile is the configuration for the CIS scan, which is the benchmark versions to use and any specific tests to skip in that benchmark.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import Grafana from '@/chart/monitoring/grafana';
|
|||
import Prometheus from '@/chart/monitoring/prometheus';
|
||||
|
||||
import { allHash } from '@/utils/promise';
|
||||
import { STORAGE_CLASS, PVC, SECRET, POD } from '@/config/types';
|
||||
import { STORAGE_CLASS, PVC, SECRET, WORKLOAD_TYPES } from '@/config/types';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -56,13 +56,19 @@ export default {
|
|||
},
|
||||
],
|
||||
pvcs: [],
|
||||
prometheusResources: [],
|
||||
secrets: [],
|
||||
storageClasses: [],
|
||||
targetNamespace: null,
|
||||
warnPrometheusInstalled: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
workloads() {
|
||||
return Object.values(WORKLOAD_TYPES).flatMap(type => this.$store.getters['cluster/all'](type));
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
if (this.mode === 'create') {
|
||||
const extendedDefaults = {
|
||||
|
|
@ -98,12 +104,13 @@ export default {
|
|||
const { $store } = this;
|
||||
const hash = await allHash({
|
||||
namespaces: $store.getters['namespaces'](),
|
||||
pods: $store.dispatch('cluster/findAll', { type: POD }),
|
||||
pvcs: $store.dispatch('cluster/findAll', { type: PVC }),
|
||||
secrets: $store.dispatch('cluster/findAll', { type: SECRET }),
|
||||
storageClasses: $store.dispatch('cluster/findAll', { type: STORAGE_CLASS }),
|
||||
});
|
||||
|
||||
await Promise.all(Object.values(WORKLOAD_TYPES).map(type => this.$store.dispatch('cluster/findAll', { type })));
|
||||
|
||||
this.targetNamespace = hash.namespaces[this.chart.targetNamespace] || false;
|
||||
|
||||
if (!isEmpty(hash.storageClasses)) {
|
||||
|
|
@ -117,17 +124,6 @@ export default {
|
|||
if (!isEmpty(hash.secrets)) {
|
||||
this.secrets = hash.secrets;
|
||||
}
|
||||
|
||||
if (!isEmpty(hash.pods)) {
|
||||
hash.pods.find((pod) => {
|
||||
if (
|
||||
!isEmpty(pod.spec?.containers) &&
|
||||
pod.spec.containers.find(p => p.image.includes('quay.io/coreos/prometheus-operator') || p.image.includes('rancher/coreos-prometheus-operator') )
|
||||
) {
|
||||
this.warnPrometheusInstalled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -161,7 +157,8 @@ export default {
|
|||
:access-modes="accessModes"
|
||||
:mode="mode"
|
||||
:storage-classes="storageClasses"
|
||||
:warn-user="warnPrometheusInstalled"
|
||||
:prometheus-pods="prometheusResources"
|
||||
:workloads="workloads"
|
||||
/>
|
||||
</section>
|
||||
<section class="config-grafana-container">
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
<script>
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import Banner from '@/components/Banner';
|
||||
import Checkbox from '@/components/form/Checkbox';
|
||||
import KeyValue from '@/components/form/KeyValue';
|
||||
import LabeledInput from '@/components/form/LabeledInput';
|
||||
import LabeledSelect from '@/components/form/LabeledSelect';
|
||||
import StorageClassSelector from '@/chart/monitoring/StorageClassSelector';
|
||||
import { POD } from '@/config/types';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -15,6 +19,7 @@ export default {
|
|||
LabeledSelect,
|
||||
StorageClassSelector,
|
||||
},
|
||||
|
||||
props: {
|
||||
accessModes: {
|
||||
type: Array,
|
||||
|
|
@ -26,24 +31,25 @@ export default {
|
|||
default: 'create',
|
||||
},
|
||||
|
||||
prometheusPods: {
|
||||
type: Array,
|
||||
default: () => ([]),
|
||||
},
|
||||
|
||||
storageClasses: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
type: Array,
|
||||
default: () => ([]),
|
||||
},
|
||||
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
warnUser: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
workloads: {
|
||||
type: Array,
|
||||
default: () => ([]),
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
@ -59,9 +65,67 @@ export default {
|
|||
},
|
||||
],
|
||||
enablePersistantStorage: false,
|
||||
warnUser: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['currentCluster']),
|
||||
filteredWorkloads() {
|
||||
let { workloads } = this;
|
||||
|
||||
workloads = workloads.filter((workload) => {
|
||||
if (
|
||||
!isEmpty(workload?.spec?.template?.spec?.containers) &&
|
||||
(workload.spec.template.spec.containers.find(c => c.image.includes('quay.io/coreos/prometheus-operator') ||
|
||||
c.image.includes('rancher/coreos-prometheus-operator'))
|
||||
)
|
||||
) {
|
||||
if (!this.warnUser) {
|
||||
this.warnUser = true;
|
||||
}
|
||||
|
||||
return workload;
|
||||
}
|
||||
});
|
||||
|
||||
return workloads.map((wl) => {
|
||||
return {
|
||||
label: wl.id,
|
||||
link: {
|
||||
name: 'c-cluster-product-resource-namespace-id',
|
||||
params: {
|
||||
cluster: this.currentCluster.id,
|
||||
product: 'explorer',
|
||||
resource: wl.type,
|
||||
namespace: wl.metadata.namespace,
|
||||
id: wl.metadata.name
|
||||
},
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
podsAndNamespaces() {
|
||||
const { prometheusPods } = this;
|
||||
const pods = [];
|
||||
|
||||
prometheusPods.forEach((pod) => {
|
||||
pods.push({
|
||||
label: pod.id,
|
||||
link: {
|
||||
name: 'c-cluster-product-resource-namespace-id',
|
||||
params: {
|
||||
cluster: this.currentCluster.id, product: 'explorer', resource: POD, namespace: pod.metadata.namespace, id: pod.metadata.name
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return pods;
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
enablePersistantStorage(enabled) {
|
||||
if (!!enabled) {
|
||||
|
|
@ -86,9 +150,14 @@ export default {
|
|||
<div class="title">
|
||||
<h3>{{ t('monitoring.prometheus.title') }}</h3>
|
||||
</div>
|
||||
<Banner v-if="warnUser" color="warning">
|
||||
<Banner v-if="filteredWorkloads && warnUser" color="warning">
|
||||
<template #default>
|
||||
<t k="monitoring.prometheus.warningInstalled" :raw="true" />
|
||||
<div v-for="wl in filteredWorkloads" :key="wl.id" class="mt-10">
|
||||
<nuxt-link :to="wl.link" class="btn role-tertiary">
|
||||
{{ wl.label }}
|
||||
</nuxt-link>
|
||||
</div>
|
||||
</template>
|
||||
</Banner>
|
||||
<div class="prometheus-config">
|
||||
|
|
|
|||
|
|
@ -8,11 +8,25 @@ export function init(store) {
|
|||
const {
|
||||
product, basicType, virtualType, weightType
|
||||
} = DSL(store, NAME);
|
||||
const { SERVICEMONITOR, PODMONITOR, PROMETHEUSRULE } = MONITORING;
|
||||
const {
|
||||
ALERTMANAGER,
|
||||
SERVICEMONITOR,
|
||||
PODMONITOR,
|
||||
PROMETHEUSRULE,
|
||||
PROMETHEUSE,
|
||||
THANOSRULER,
|
||||
} = MONITORING;
|
||||
|
||||
product({
|
||||
ifHaveType: PODMONITOR,
|
||||
icon: 'prometheus'
|
||||
ifHaveType: [
|
||||
ALERTMANAGER,
|
||||
SERVICEMONITOR,
|
||||
PODMONITOR,
|
||||
PROMETHEUSRULE,
|
||||
PROMETHEUSE,
|
||||
THANOSRULER,
|
||||
],
|
||||
// icon: 'prometheus'
|
||||
});
|
||||
|
||||
virtualType({
|
||||
|
|
@ -27,7 +41,7 @@ export function init(store) {
|
|||
|
||||
basicType('monitoring-overview');
|
||||
|
||||
basicType([SERVICEMONITOR, PODMONITOR, PROMETHEUSRULE]);
|
||||
basicType([SERVICEMONITOR, PODMONITOR, PROMETHEUSRULE, ALERTMANAGER, PROMETHEUSE]);
|
||||
|
||||
weightType(SERVICEMONITOR, 104, true);
|
||||
weightType(PODMONITOR, 103, true);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export const API_GROUP = 'apiGroups';
|
|||
export const CONFIG_MAP = 'configmap';
|
||||
export const COUNT = 'count';
|
||||
export const EVENT = 'event';
|
||||
export const ENDPOINTS = 'endpoints';
|
||||
export const HPA = 'autoscaling.horizontalpodautoscaler';
|
||||
export const INGRESS = 'networking.k8s.io.ingress';
|
||||
export const NAMESPACE = 'namespace';
|
||||
|
|
|
|||
|
|
@ -1,73 +1,108 @@
|
|||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
import InstallRedirect from '@/utils/install-redirect';
|
||||
|
||||
import { NAME, CHART_NAME } from '@/config/product/monitoring';
|
||||
import { MONITORING } from '@/config/types';
|
||||
import { ENDPOINTS, MONITORING } from '@/config/types';
|
||||
import { allHash } from '@/utils/promise';
|
||||
import { findBy } from '@/utils/array';
|
||||
|
||||
import LazyImage from '@/components/LazyImage';
|
||||
import ResourceGauge from '@/components/ResourceGauge';
|
||||
|
||||
const CATTLE_MONITORING_NAMESPACE = 'cattle-monitoring-system';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LazyImage,
|
||||
ResourceGauge,
|
||||
},
|
||||
components: { LazyImage },
|
||||
|
||||
middleware: InstallRedirect(NAME, CHART_NAME),
|
||||
|
||||
data() {
|
||||
return {
|
||||
externalLinks: [],
|
||||
grafanaSrc: require('~/assets/images/white-grafana.svg'),
|
||||
prometheusSrc: require('~/assets/images/white-prometheus.svg'),
|
||||
resources: [MONITORING.ALERTMANAGER, MONITORING.PROMETHEUSE],
|
||||
externalLinks: [],
|
||||
grafanaSrc: require('~/assets/images/white-grafana.svg'),
|
||||
prometheusSrc: require('~/assets/images/white-prometheus.svg'),
|
||||
resources: [MONITORING.ALERTMANAGER, MONITORING.PROMETHEUSE],
|
||||
availableLinks: {
|
||||
alertmanager: false,
|
||||
grafana: false,
|
||||
prometheus: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['currentCluster']),
|
||||
|
||||
accessibleResources() {
|
||||
return this.resources.filter(resource => this.$store.getters['cluster/schemaFor'](resource));
|
||||
},
|
||||
},
|
||||
computed: { ...mapGetters(['currentCluster']) },
|
||||
|
||||
mounted() {
|
||||
this.externalLinks = [
|
||||
{
|
||||
enabled: false,
|
||||
group: 'alertmanager',
|
||||
iconSrc: this.prometheusSrc,
|
||||
label: 'monitoring.overview.linkedList.alertManager.label',
|
||||
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-alertmanager:9093/proxy`,
|
||||
tooltip: 'monitoring.overview.linkedList.alertManager.tooltip',
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
group: 'grafana',
|
||||
iconSrc: this.grafanaSrc,
|
||||
label: 'monitoring.overview.linkedList.grafana.label',
|
||||
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy`,
|
||||
tooltip: 'monitoring.overview.linkedList.grafana.tooltip',
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
group: 'prometheus',
|
||||
iconSrc: this.prometheusSrc,
|
||||
label: 'monitoring.overview.linkedList.prometheusPromQl.label',
|
||||
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/graph`,
|
||||
tooltip: 'monitoring.overview.linkedList.prometheusPromQl.tooltip',
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
group: 'prometheus',
|
||||
iconSrc: this.prometheusSrc,
|
||||
label: 'monitoring.overview.linkedList.prometheusRules.label',
|
||||
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/rules`,
|
||||
tooltip: 'monitoring.overview.linkedList.prometheusRules.tooltip',
|
||||
},
|
||||
{
|
||||
enabled: false,
|
||||
group: 'prometheus',
|
||||
iconSrc: this.prometheusSrc,
|
||||
label: 'monitoring.overview.linkedList.prometheusTargets.label',
|
||||
link: `/k8s/clusters/${ this.currentCluster.id }/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-prometheus:9090/proxy/targets`,
|
||||
tooltip: 'monitoring.overview.linkedList.prometheusTargets.tooltip',
|
||||
},
|
||||
];
|
||||
|
||||
this.fetchDeps();
|
||||
},
|
||||
|
||||
methods: {
|
||||
async fetchDeps() {
|
||||
const { $store, externalLinks } = this;
|
||||
const hash = await allHash({ endpoints: $store.dispatch('cluster/findAll', { type: ENDPOINTS }) });
|
||||
|
||||
if (!isEmpty(hash.endpoints)) {
|
||||
const amMatch = findBy(externalLinks, 'group', 'alertmanager');
|
||||
const grafanaMatch = findBy(externalLinks, 'group', 'grafana');
|
||||
const promeMatch = externalLinks.filter(el => el.group === 'prometheus');
|
||||
const alertmanager = findBy(hash.endpoints, 'id', `${ CATTLE_MONITORING_NAMESPACE }/rancher-monitoring-alertmanager`);
|
||||
const grafana = findBy(hash.endpoints, 'id', `${ CATTLE_MONITORING_NAMESPACE }/rancher-monitoring-grafana`);
|
||||
const prometheus = findBy(hash.endpoints, 'id', `${ CATTLE_MONITORING_NAMESPACE }/rancher-monitoring-prometheus`);
|
||||
|
||||
if (!isEmpty(alertmanager) && !isEmpty(alertmanager.subsets)) {
|
||||
amMatch.enabled = true;
|
||||
}
|
||||
if (!isEmpty(grafana) && !isEmpty(grafana.subsets)) {
|
||||
grafanaMatch.enabled = true;
|
||||
}
|
||||
if (!isEmpty(prometheus) && !isEmpty(prometheus.subsets)) {
|
||||
promeMatch.forEach((match) => {
|
||||
match.enabled = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -84,21 +119,27 @@ export default {
|
|||
</div>
|
||||
</header>
|
||||
<div class="links">
|
||||
<div v-for="el in externalLinks" :key="el.label" class="link-container">
|
||||
<a v-tooltip="t(el.tooltip)" :href="el.link" target="_blank" rel="noopener noreferrer">
|
||||
<div v-for="fel in externalLinks" :key="fel.label" class="link-container">
|
||||
<a v-if="fel.enabled" :href="fel.link" target="_blank" rel="noopener noreferrer">
|
||||
<div class="link-logo">
|
||||
<LazyImage class="round-image" :src="el.iconSrc" />
|
||||
<LazyImage class="round-image" :src="fel.iconSrc" />
|
||||
</div>
|
||||
<div class="link-content">
|
||||
<t :k="el.label" />
|
||||
<t :k="fel.label" />
|
||||
<i class="icon icon-external-link pull-right" />
|
||||
</div>
|
||||
</a>
|
||||
<a v-else v-tooltip="t('monitoring.overview.linkedList.na')" href="javascript:void(0)" :disabled="!fel.enabled">
|
||||
<div class="link-logo">
|
||||
<LazyImage class="round-image" :src="fel.iconSrc" />
|
||||
</div>
|
||||
<div class="link-content">
|
||||
<t :k="fel.label" />
|
||||
<i class="icon icon-external-link pull-right" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-gauges">
|
||||
<ResourceGauge v-for="(resource, i) in accessibleResources" :key="resource" :resource="resource" :primary-color-var="`--sizzle-${i}`" />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
|
@ -118,6 +159,11 @@ export default {
|
|||
max-width: 325px;
|
||||
min-height: 100px;
|
||||
|
||||
a[disabled] {
|
||||
cursor: not-allowed;
|
||||
background-color: var(---disabled-bg);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0px 0px 1px var(--outline-width) var(--outline);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ export function createYaml(schemas, type, data, processAlwaysAdd = true, depth =
|
|||
if ( SIMPLE_TYPES.includes(arrayOf) ) {
|
||||
out += `\n# - ${ arrayOf }`;
|
||||
} else {
|
||||
const chunk = createYaml(schemas, arrayOf, null, processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key));
|
||||
const chunk = createYaml(schemas, arrayOf, null, false, depth + 1, (path ? `${ path }.${ key }` : key));
|
||||
let indented = indent(chunk, 2);
|
||||
|
||||
indented = indented.replace(/^(#)?\s*\s\s([^\s])/, '$1 - $2');
|
||||
|
|
|
|||
Loading…
Reference in New Issue