diff --git a/pkg/harvester/components/health/__tests__/health.test.js b/pkg/harvester/components/health/__tests__/health.test.js index 450ff136..7a406fff 100644 --- a/pkg/harvester/components/health/__tests__/health.test.js +++ b/pkg/harvester/components/health/__tests__/health.test.js @@ -156,7 +156,9 @@ const actionsOf = (props = {}, storeProps = {}) => { }; }; -const mountRuleModal = ({ rule, mode, save = () => {} } = {}) => { +const mountRuleModal = ({ + rule, mode, save = () => {}, row = CHECK +} = {}) => { createRule.mockClear(); cloneRule.mockClear(); saveRule.mockReset().mockImplementation(save); @@ -167,7 +169,7 @@ const mountRuleModal = ({ rule, mode, save = () => {} } = {}) => { const w = vtuMount(IgnoreRuleModal, { ...opts(), props: { - row: CHECK, rule, mode, modal: { show: true, onClose } + row, rule, mode, modal: { show: true, onClose } }, }); @@ -408,6 +410,10 @@ describe('health components', () => { it('names the rule of a check after it', () => { expect(ignoreRuleName('harvester-controller-vmimage', 'ImageRetryLimitExceeded')).toBe('harvester-controller-vmimage.imageretrylimitexceeded'); }); + it('turns what a name can not have in a check into hyphens', () => { + expect(ignoreRuleName('harvester-controller-schedulevmbackup', 'Proactive Schedule Suspend')).toBe('harvester-controller-schedulevmbackup.proactive-schedule-suspend'); + expect(ignoreRuleName('h', ' Reach_Max Failure! ')).toBe('h.reach-max-failure'); + }); it('tells the ignored resources apart, and all of them when the check is ignored', () => { const table = { props: ['rows'], template: '
' }; const row = { @@ -634,6 +640,15 @@ describe('health components', () => { expect(createRule.mock.calls[0][1].metadata).toStrictEqual({ name: 'h.a', labels: { 'health.harvesterhci.io/source': 'user' } }); }); + it('gives a check with spaces a valid name, and keeps the check as it is', async() => { + const { confirm } = mountRuleModal({ row: { ...CHECK, checkName: 'Proactive Schedule Suspend' } }); + + await confirm().trigger('click'); + await flushPromises(); + + expect(createRule.mock.calls[0][1].metadata.name).toBe('h.proactive-schedule-suspend'); + expect(newRule.spec.checkKey).toBe('Proactive Schedule Suspend'); + }); it('says when the rule will expire, from 7 days on', async() => { const { confirm, duration, currentExpiry, newExpiry diff --git a/pkg/harvester/utils/component-health.js b/pkg/harvester/utils/component-health.js index 030a9d46..0b5e4a43 100644 --- a/pkg/harvester/utils/component-health.js +++ b/pkg/harvester/utils/component-health.js @@ -86,9 +86,12 @@ export function ignoredCounts(checks) { }, { checks: 0, resources: 0 }); } -// the UI keeps one rule per check under this name, so Kubernetes refuses a second one for the same check +// the UI keeps one rule per check under this name, so Kubernetes refuses a second one for the same check. +// Some checks are named after a condition reason with spaces, like "Proactive Schedule Suspend", which a name can't have export function ignoreRuleName(componentHealthName, checkName) { - return `${ componentHealthName }.${ checkName.toLowerCase() }`; + const check = checkName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''); + + return `${ componentHealthName }.${ check }`; } export function affectedResourceKind(row) {