Skip to content

Commit

Permalink
Merge pull request rancher#10054 from richard-cox/squash-findAll-secr…
Browse files Browse the repository at this point in the history
…et-monitoring-chart

Avoid fetching all secrets and workloads when installing Monitoring Chart
  • Loading branch information
richard-cox authored Dec 12, 2023
2 parents e92b039 + 18989a8 commit 8f0c769
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 91 deletions.
4 changes: 2 additions & 2 deletions shell/assets/translations/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3161,9 +3161,9 @@ monitoring:
label: Additional Secrets
existing: Choose an existing config secret
info: |
<span class="text-bold">Create default config</span>: A Secret containing your Alertmanager Config will be created in the <pre class='inline-block m-0'>cattle-monitoring-system</pre> namespace on deploying this chart under the name <pre class='inline-block m-0'>alertmanager-rancher-monitoring-alertmanager</pre>. By default, this Secret will never be modified on an uninstall or upgrade of this chart. <br />
<span class="text-bold">Create default config</span>:<br>A Secret containing your Alertmanager Config will be created in the <pre class='inline-block m-0'>cattle-monitoring-system</pre> namespace on deploying this chart under the name <pre class='inline-block m-0'>alertmanager-rancher-monitoring-alertmanager</pre>. By default, this Secret will never be modified on an uninstall or upgrade of this chart. <br /><br />
Once you have deployed this chart, you should edit the Secret via the UI in order to add your custom notification configurations that will be used by Alertmanager to send alerts. <br /> <br />
<span class="text-bold">Choose an existing config secret</span>: You must specify a Secret that exists in the <pre class='inline-block m-0'>cattle-monitoring-system</pre> namespace. If the namespace does not exist, you will not be able to select an existing secret.
<span class="text-bold">Choose an existing config secret</span>:<br>You must specify a Secret that exists in the <pre class='inline-block m-0'>cattle-monitoring-system</pre> namespace. If the namespace does not exist, you will not be able to select an existing secret.
label: Alertmanager Secret
new: Create default config
radio:
Expand Down
28 changes: 7 additions & 21 deletions shell/chart/monitoring/alerting/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { Checkbox } from '@components/Form/Checkbox';
import LabeledSelect from '@shell/components/form/LabeledSelect';
import { RadioGroup } from '@components/Form/Radio';
const DEFAULT_MONITORING_NAMESPACE = 'cattle-monitoring-system';
export default {
components: {
Checkbox,
Expand All @@ -20,7 +18,7 @@ export default {
default: 'create',
},
secrets: {
monitoringSecrets: {
type: Array,
default: () => [],
},
Expand All @@ -43,12 +41,7 @@ export default {
computed: {
allSecrets() {
const { secrets } = this;
return secrets
.filter(
(sec) => sec.metadata.namespace === DEFAULT_MONITORING_NAMESPACE
)
return this.monitoringSecrets
.map((sec) => ({ label: sec.metadata.name, value: sec.metadata.name }));
},
Expand All @@ -62,22 +55,15 @@ export default {
},
existingSecret() {
return this.secrets.find(
(sec) => sec?.metadata?.name ===
'alertmanager-rancher-monitoring-alertmanager' &&
sec?.metadata?.namespace === DEFAULT_MONITORING_NAMESPACE
);
return this.monitoringSecrets
.find((sec) => sec?.metadata?.name === 'alertmanager-rancher-monitoring-alertmanager');
},
filteredSecrets() {
const { secrets } = this;
const filtered = [];
secrets.forEach((secret) => {
if (
secret.metadata.name &&
secret.metadata.namespace === DEFAULT_MONITORING_NAMESPACE
) {
this.monitoringSecrets.forEach((secret) => {
if ( secret.metadata.name ) {
filtered.push(secret.metadata.name);
}
});
Expand All @@ -93,7 +79,7 @@ export default {
},
watch: {
filteredSecrets(newValue, oldValue) {
filteredSecrets(newValue) {
if (isEmpty(newValue)) {
this.$set(
this.value.alertmanager.alertmanagerSpec,
Expand Down
69 changes: 52 additions & 17 deletions shell/chart/monitoring/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Tab from '@shell/components/Tabbed/Tab';
import { allHash } from '@shell/utils/promise';
import { STORAGE_CLASS, PVC, SECRET, WORKLOAD_TYPES } from '@shell/config/types';
import { CATTLE_MONITORING_NAMESPACE } from '@shell/utils/monitoring';
export default {
components: {
Expand Down Expand Up @@ -52,17 +53,41 @@ export default {
async fetch() {
const { $store } = this;
const hash = await allHash({
namespaces: $store.getters['namespaces'](),
pvcs: $store.dispatch('cluster/findAll', { type: PVC }),
secrets: $store.dispatch('cluster/findAll', { type: SECRET }),
// Fetch all the resources required for all the tabs asyncronously up front
const hashPromises = {
namespaces: $store.getters['namespaces'](),
pvcs: $store.dispatch('cluster/findAll', { type: PVC }),
// Used in Alerting tab
monitoringSecrets: $store.dispatch('cluster/findAll', {
type: SECRET,
opt: { namespaced: CATTLE_MONITORING_NAMESPACE }
}),
storageClasses: $store.dispatch('cluster/findAll', { type: STORAGE_CLASS }),
};
// Are we editing an existing chart?
// (ported from shell/chart/monitoring/prometheus/index.vue)
// const { existing = false } = this.$attrs; // TODO: RC
const existing = false;
// If needed, fetch all the workloads that have prometheus operator like containers
this.workloadTypes = !existing ? Object.values(WORKLOAD_TYPES) : [];
this.workloadTypes.forEach((type) => {
// We'll use a filter to fetch the results. Atm there's no neat way to differentiate between ALL results and JUST filtered
// So to avoid calls to all getting these filtered (and vice-versa) forget type before and after
$store.dispatch('cluster/forgetType', type);
hashPromises[type] = $store.dispatch('cluster/findAll', {
type,
opt: {
watch: false,
// We're only interested in images with operator like names (note: these will match partial strings)
filter: { 'spec.template.spec.containers.image': ['quay.io/coreos/prometheus-operator', 'rancher/coreos-prometheus-operator'] }
}
});
});
await Promise.all(
Object.values(WORKLOAD_TYPES).map((type) => this.$store.dispatch('cluster/findAll', { type })
)
);
const hash = await allHash(hashPromises);
this.targetNamespace = hash.namespaces[this.chart.targetNamespace] || false;
Expand All @@ -74,9 +99,21 @@ export default {
this.pvcs = hash.pvcs;
}
if (!isEmpty(hash.secrets)) {
this.secrets = hash.secrets;
if (!isEmpty(hash.monitoringSecrets)) {
this.monitoringSecrets = hash.monitoringSecrets;
}
this.workloadTypes.forEach((type) => {
if (hash[type]) {
this.filteredWorkloads.push(...hash[type]);
}
});
},
beforeDestroy() {
this.workloadTypes.forEach((type) => {
this.$store.dispatch('cluster/forgetType', type);
});
},
data() {
Expand All @@ -99,9 +136,11 @@ export default {
disableAggregateRoles: false,
prometheusResources: [],
pvcs: [],
secrets: [],
monitoringSecrets: [],
storageClasses: [],
targetNamespace: null,
filteredWorkloads: [],
workloadTypes: []
};
},
Expand All @@ -110,10 +149,6 @@ export default {
provider() {
return this.currentCluster.status.provider.toLowerCase();
},
workloads() {
return Object.values(WORKLOAD_TYPES).flatMap((type) => this.$store.getters['cluster/all'](type)
);
},
},
watch: {
Expand Down Expand Up @@ -278,7 +313,7 @@ export default {
:mode="mode"
:storage-classes="storageClasses"
:prometheus-pods="prometheusResources"
:workloads="workloads"
:filteredWorkloads="filteredWorkloads"
/>
</div>
</Tab>
Expand All @@ -291,7 +326,7 @@ export default {
<Alerting
v-model="value"
:mode="mode"
:secrets="secrets"
:monitoringSecrets="monitoringSecrets"
/>
</div>
</Tab>
Expand Down
63 changes: 20 additions & 43 deletions shell/chart/monitoring/prometheus/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<script>
import isEmpty from 'lodash/isEmpty';
import { mapGetters } from 'vuex';
import { Banner } from '@components/Banner';
Expand Down Expand Up @@ -51,21 +50,19 @@ export default {
default: () => ({}),
},
workloads: {
filteredWorkloads: {
type: Array,
default: () => ([]),
},
},
data() {
return {
enablePersistentStorage: !!this.value?.prometheus?.prometheusSpec?.storageSpec?.volumeClaimTemplate?.spec,
warnUser: false,
};
return { enablePersistentStorage: !!this.value?.prometheus?.prometheusSpec?.storageSpec?.volumeClaimTemplate?.spec };
},
computed: {
...mapGetters(['currentCluster']),
matchExpressions: {
get() {
const selector = this.value?.prometheus?.prometheusSpec?.storageSpec?.volumeClaimTemplate?.spec?.selector;
Expand All @@ -80,42 +77,21 @@ export default {
}
}
},
filteredWorkloads() {
let { workloads } = this;
const { existing = false } = this.$attrs;
if (!existing) {
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
},
}
};
});
mappedFilteredWorkloads() {
return this.filteredWorkloads.map((wl) => ({
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() {
Expand Down Expand Up @@ -189,8 +165,9 @@ export default {
<div class="title">
<h3>{{ t('monitoring.prometheus.title') }}</h3>
</div>
<!-- https://github.com/rancher/dashboard/issues/1167 -->
<Banner
v-if="filteredWorkloads && warnUser"
v-if="mappedFilteredWorkloads.length"
color="warning"
>
<template #default>
Expand All @@ -199,7 +176,7 @@ export default {
:raw="true"
/>
<div
v-for="wl in filteredWorkloads"
v-for="wl in mappedFilteredWorkloads"
:key="wl.id"
class="mt-10"
>
Expand Down
8 changes: 6 additions & 2 deletions shell/plugins/dashboard-store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export async function loadSchemas(ctx, watch = true) {
return all;
}

const findAllGetter = (getters, type, opt) => {
return opt.namespaced ? getters.matching(type, null, opt.namespaced, { skipSelector: true }) : getters.all(type);
};

export default {
request() {
throw new Error('Not Implemented');
Expand Down Expand Up @@ -163,7 +167,7 @@ export default {
dispatch('watch', args);
}

return getters.all(type);
return findAllGetter(getters, type, opt);
}

let load = (opt.load === undefined ? _ALL : opt.load);
Expand Down Expand Up @@ -328,7 +332,7 @@ export default {
dispatch('watch', args);
}

const all = getters.all(type);
const all = findAllGetter(getters, type, opt);

if (!opt.incremental && opt.hasManualRefresh) {
dispatch('resource-fetch/updateManualRefreshIsLoading', false, { root: true });
Expand Down
15 changes: 10 additions & 5 deletions shell/plugins/dashboard-store/getters.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,24 @@ export default {
return state.types[type].list;
},

matching: (state, getters, rootState) => (type, selector, namespace) => {
let all = getters['all'](type);
matching: (state, getters, rootState) => (type, selector, namespace, config = { skipSelector: false }) => {
let matching = getters['all'](type);

// Filter first by namespace if one is provided, since this is efficient
if (namespace) {
all = all.filter((obj) => obj.namespace === namespace);
if (namespace && typeof namespace === 'string') {
matching = matching.filter((obj) => obj.namespace === namespace);
}

garbageCollect.gcUpdateLastAccessed({
state, getters, rootState
}, type);

return all.filter((obj) => {
// Looks like a falsy selector is a thing, so if we're not interested in filtering by the selector... explicitly avoid it
if (config.skipSelector) {
return matching;
}

return matching.filter((obj) => {
return matches(obj, selector);
});
},
Expand Down
2 changes: 1 addition & 1 deletion shell/utils/monitoring.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function haveV1Monitoring(getters) {
return !!cluster?.status?.monitoringStatus;
}

const CATTLE_MONITORING_NAMESPACE = 'cattle-monitoring-system';
export const CATTLE_MONITORING_NAMESPACE = 'cattle-monitoring-system';

export async function haveV1MonitoringWorkloads(store) {
const workloadsByType = await Promise.all(
Expand Down

0 comments on commit 8f0c769

Please sign in to comment.