Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate new label select filtering #12919

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion shell/components/ResourceDetail/Masthead.vue
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ export default {
class="live-date"
:value="value.creationTimestamp"
/></span>
<span v-if="value.showPodRestarts">{{ t("resourceDetail.masthead.restartCount") }}:<span class="live-data"> {{ value.restartCount }}</span></span>
<!-- <span v-if="value.showPodRestarts">{{ t("resourceDetail.masthead.restartCount") }}:<span class="live-data"> {{ value.restartCount }}</span></span> -->
</div>
</div>
<slot name="right">
Expand Down
77 changes: 54 additions & 23 deletions shell/components/form/ResourceSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import { Banner } from '@components/Banner';
import MatchExpressions from '@shell/components/form/MatchExpressions';
import ResourceTable from '@shell/components/ResourceTable';
import { allHash } from '@shell/utils/promise';
import { _EDIT } from '@shell/config/query-params';
import { convert, matching, simplify } from '@shell/utils/selector';
import { convert, simplify } from '@shell/utils/selector';
import throttle from 'lodash/throttle';
import { COUNT } from '@shell/config/types';
import { matching } from '@shell/utils/selector-typed';

export default {
name: 'ResourceSelector',
Expand Down Expand Up @@ -36,11 +37,6 @@ export default {
},

async fetch() {
// Used in conjunction with `matches/match/label selectors`. Requires https://github.com/rancher/dashboard/issues/10417 to fix
const hash = await allHash({ allResources: this.$store.dispatch('cluster/findAll', { type: this.type }) });

this.allResources = hash.allResources;

this.updateMatchingResources();
},

Expand All @@ -55,11 +51,12 @@ export default {

return {
matchingResources,
allResources: [],
allResourcesInScope: [],
tableHeaders: this.$store.getters['type-map/headersFor'](
// allResources: [],
// allResourcesInScope: [],
tableHeaders: this.$store.getters['type-map/headersFor'](
this.$store.getters['cluster/schemaFor'](this.type)
),
inStore: this.$store.getters['currentProduct'].inStore,
};
},

Expand All @@ -73,6 +70,9 @@ export default {
schema() {
return this.$store.getters['cluster/schemaFor'](this.type);
},
/**
* of type matchExpression aka `KubeLabelSelectorExpression[]`
*/
selectorExpressions: {
get() {
return convert(
Expand All @@ -87,22 +87,53 @@ export default {
this.value['matchExpressions'] = matchExpressions;
}
},
allResourcesInScope() {
const counts = this.$store.getters[`${ this.inStore }/all`](COUNT)?.[0]?.counts || {};

if (this.namespace) {
return counts?.[this.type].namespaces[this.namespace]?.count || 0;
}

return counts[this.type]?.summary?.count || 0;
}
},

methods: {
updateMatchingResources: throttle(function() {
this.allResourcesInScope = this.namespace ? this.allResources.filter((res) => res.metadata.namespace === this.namespace) : this.allResources;
const match = matching(this.allResourcesInScope, this.selectorExpressions);
const matched = match.length || 0;
const sample = match[0]?.nameDisplay;

this.matchingResources = {
matched,
matches: match,
none: matched === 0,
sample,
total: this.allResourcesInScope.length,
};
updateMatchingResources: throttle(async function() {
// TODO: RC TEST
this.matchingResources = await matching({
labelSelector: { matchExpressions: this.selectorExpressions },
type: this.type,
$store: this.$store,
inScopeCount: this.allResourcesInScope,
namespace: this.namespace,
});

// let match = [];

// if (this.selectorExpressions?.length) {
// const findPageArgs = { // Of type ActionFindPageArgs
// namespaced: this.namespace,
// pagination: new FilterArgs({ labelSelector: { matchExpressions: this.selectorExpressions } }),
// };

// const res = await this.$dispatch('findPage', { type: this.type, opt: findPageArgs });

// match = res;
// }

// // this.allResourcesInScope = this.namespace ? this.allResources.filter((res) => res.metadata.namespace === this.namespace) : this.allResources;
// // const match = matching(this.allResourcesInScope, this.selectorExpressions);
// const matched = match.length || 0;
// const sample = match[0]?.nameDisplay;

// this.matchingResources = {
// matched,
// matches: match,
// none: matched === 0,
// sample,
// total: this.allResourcesInScope.length,
// };
}, 250, { leading: true }),
}

Expand Down
7 changes: 4 additions & 3 deletions shell/detail/service.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
},

async fetch() {
await this.value.fetchPods();
// TODO: RC test (blocked given services bug in dev image)
this.matchingPods = await this.value.fetchPods();
},

data() {
Expand Down Expand Up @@ -83,7 +84,7 @@

return {
servicePortInfoHeaders,
pods: [],
matchingPods: [],

Check warning on line 87 in shell/detail/service.vue

View workflow job for this annotation

GitHub Actions / lint

Extra space before value for key 'matchingPods'
podTableHeaders: this.$store.getters['type-map/headersFor'](
this.$store.getters['cluster/schemaFor'](POD)
),
Expand Down Expand Up @@ -155,7 +156,7 @@
:weight="4"
>
<ResourceTable
:rows="value.pods"
:rows="matchingPods"
:headers="podTableHeaders"
key-field="id"
:table-actions="false"
Expand Down
130 changes: 79 additions & 51 deletions shell/detail/workload/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
import { mapGetters } from 'vuex';
import { allDashboardsExist } from '@shell/utils/grafana';
import PlusMinus from '@shell/components/form/PlusMinus';
import { matches } from '@shell/utils/selector';

Check warning on line 17 in shell/detail/workload/index.vue

View workflow job for this annotation

GitHub Actions / lint

'matches' is defined but never used
import { PROJECT } from '@shell/config/labels-annotations';
import { FilterArgs } from '@shell/types/store/pagination.types';

Check warning on line 19 in shell/detail/workload/index.vue

View workflow job for this annotation

GitHub Actions / lint

'FilterArgs' is defined but never used

const SCALABLE_TYPES = Object.values(SCALABLE_WORKLOAD_TYPES);
const WORKLOAD_METRICS_DETAIL_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-workload-pods-1/rancher-workload-pods?orgId=1';
Expand Down Expand Up @@ -48,15 +49,33 @@

const hash = {
// Used in conjunction with `matches/match/label selectors`. Requires https://github.com/rancher/dashboard/issues/10417 to fix
allPods: this.$store.dispatch('cluster/findAll', { type: POD }),
// allPods: this.$store.dispatch('cluster/findAll', { type: POD }),
// Used in conjunction with `matches/match/label selectors`. Requires https://github.com/rancher/dashboard/issues/10417 to fix
allServices: this.$store.dispatch('cluster/findAll', { type: SERVICE }),
// allServices: this.$store.dispatch('cluster/findAll', { type: SERVICE }),
allIngresses: this.$store.dispatch('cluster/findAll', { type: INGRESS }),
// Nodes should be fetched because they may be referenced in the target
// column of a service list item.
allNodes: hasNodes ? this.$store.dispatch('cluster/findAll', { type: NODE }) : []
};

if (this.podSchema) {
hash.matchingPods = this.value.fetchPods();
}

// if (this.serviceSchema) {
// const findPageArgs = { // Of type ActionFindPageArgs
// namespaced: this.value.metadata.namespace,
// pagination: new FilterArgs({
// filters: PaginationParamFilter.createSingleField({
// field: 'metadata.fields.1',
// value: TYPES.TLS
// })
// }),
// };

// hash.matchingServices = this.$store.dispatch('cluster/findPage', { type: SERVICE, opt: findPageArgs });
// }

if (this.value.type === WORKLOAD_TYPES.CRON_JOB) {
hash.jobs = this.value.matchingJobs();
}
Expand All @@ -81,17 +100,21 @@
this.showProjectMetrics = await allDashboardsExist(this.$store, this.currentCluster.id, [this.WORKLOAD_PROJECT_METRICS_DETAIL_URL, this.WORKLOAD_PROJECT_METRICS_SUMMARY_URL], 'cluster', projectId);
}
}
this.findMatchingServices();
// this.findMatchingServices();
this.findMatchingIngresses();
},

// TODO: RC https://github.com/rancher/dashboard/pull/6311

data() {
return {
allPods: [],
allServices: [],
// allPods: [],
// allServices: [],
allIngresses: [],
matchingServices: [],
matchingIngresses: [],
matchingPods: [],
allJobs: [],
allNodes: [],
WORKLOAD_METRICS_DETAIL_URL,
WORKLOAD_METRICS_SUMMARY_URL,
Expand Down Expand Up @@ -180,21 +203,22 @@
}, 0);
},

podRestarts() {
return this.value.pods.reduce((total, pod) => {
const { status:{ containerStatuses = [] } } = pod;
// Not used anywhere!
// podRestarts() {
// return this.value.pods.reduce((total, pod) => {
// const { status:{ containerStatuses = [] } } = pod;

if (containerStatuses.length) {
total += containerStatuses.reduce((tot, container) => {
tot += container.restartCount;
// if (containerStatuses.length) {
// total += containerStatuses.reduce((tot, container) => {
// tot += container.restartCount;

return tot;
}, 0);
}
// return tot;
// }, 0);
// }

return total;
}, 0);
},
// return total;
// }, 0);
// },

podHeaders() {
return this.$store.getters['type-map/headersFor'](this.podSchema).filter((h) => !h.name || h.name !== NAMESPACE_COL.name);
Expand All @@ -213,15 +237,19 @@
},

showPodGaugeCircles() {
const podGauges = Object.values(this.value.podGauges);
const total = this.value.pods.length;
const podGauges = Object.values(this.podGauges);
const total = this.matchingPods.length;

return !podGauges.find((pg) => pg.count === total);
},

podGauges() {
return this.value.calcPodGauges(this.matchingPods);
},

showJobGaugeCircles() {
const jobGauges = Object.values(this.value.jobGauges);
const total = this.isCronJob ? this.totalRuns : this.value.pods.length;
const total = this.isCronJob ? this.totalRuns : this.matchingPods.length;

return !jobGauges.find((jg) => jg.count === total);
},
Expand Down Expand Up @@ -252,30 +280,30 @@
async scaleUp() {
await this.scale(true);
},
findMatchingServices() {
if (!this.serviceSchema) {
return [];
}
const matchingPods = this.value.pods;

// Find Services that have selectors that match this
// workload's Pod(s).
const matchingServices = this.allServices.filter((service) => {
const selector = service.spec.selector;

for (let i = 0; i < matchingPods.length; i++) {
const pod = matchingPods[i];

if (service.metadata?.namespace === this.value.metadata?.namespace && matches(pod, selector)) {
return true;
}
}

return false;
});

this.matchingServices = matchingServices;
},
// findMatchingServices() {
// if (!this.serviceSchema) {
// return [];
// }
// const matchingPods = this.value.pods;

// // Find Services that have selectors that match this
// // workload's Pod(s).
// const matchingServices = this.allServices.filter((service) => {
// const selector = service.spec.selector;

// for (let i = 0; i < matchingPods.length; i++) {
// const pod = matchingPods[i];

// if (service.metadata?.namespace === this.value.metadata?.namespace && matches(pod, selector)) {
// return true;
// }
// }

// return false;
// });

// this.matchingServices = matchingServices;
// },
findMatchingIngresses() {
if (!this.ingressSchema) {
return [];
Expand Down Expand Up @@ -341,15 +369,15 @@
{{ isJob || isCronJob ? t('workload.detailTop.runs') :t('workload.detailTop.pods') }}
</h3>
<div
v-if="value.pods || value.jobGauges"
v-if="matchingPods || value.jobGauges"
class="gauges mb-20"
:class="{'gauges__pods': !!value.pods}"
:class="{'gauges__pods': !!matchingPods}"
>
<template v-if="value.jobGauges">
<CountGauge
v-for="(group, key) in value.jobGauges"
:key="key"
:total="isCronJob? totalRuns : value.pods.length"
:total="isCronJob? totalRuns : matchingPods.length"
:useful="group.count || 0"
:graphical="showJobGaugeCircles"
:primary-color-var="`--sizzle-${group.color}`"
Expand All @@ -358,9 +386,9 @@
</template>
<template v-else>
<CountGauge
v-for="(group, key) in value.podGauges"
v-for="(group, key) in podGauges"
:key="key"
:total="value.pods.length"
:total="matchingPods.length"
:useful="group.count || 0"
:graphical="showPodGaugeCircles"
:primary-color-var="`--sizzle-${group.color}`"
Expand Down Expand Up @@ -393,8 +421,8 @@
:weight="4"
>
<ResourceTable
v-if="value.pods"
:rows="value.pods"
v-if="matchingPods?.length"
:rows="matchingPods"
:headers="podHeaders"
key-field="id"
:schema="podSchema"
Expand Down
Loading
Loading