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

Expose refreshInterval input field for cluster repos #12759

Merged
merged 9 commits into from
Dec 12, 2024
4 changes: 4 additions & 0 deletions cypress/e2e/po/components/unit-input.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ export default class UnitInputPo extends ComponentPo {
setValue(value: string): Cypress.Chainable {
return new LabeledInputPo(this.self().find('input')).set(value);
}

clear() {
return this.self().clear();
}
}
9 changes: 5 additions & 4 deletions cypress/e2e/po/edit/catalog.cattle.io.clusterrepo.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import NameNsDescription from '@/cypress/e2e/po/components/name-ns-description.p
import ResourceDetailPo from '@/cypress/e2e/po/edit/resource-detail.po';
import RadioGroupInputPo from '@/cypress/e2e/po/components/radio-group-input.po';
import LabeledInputPo from '@/cypress/e2e/po/components/labeled-input.po';
import UnitInputPo from '@/cypress/e2e/po/components/unit-input.po';
import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po';
import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po';
import SelectOrCreateAuthPo from '@/cypress/e2e/po/components/select-or-create-auth.po';
Expand Down Expand Up @@ -92,19 +93,19 @@ export default class AppClusterRepoEditPo extends PagePo {
}

ociMinWait() {
return this.self().get('[data-testid="clusterrepo-oci-min-wait-input"]').invoke('val');
return this.self().get('[data-testid="clusterrepo-oci-min-wait-input"] input').invoke('val');
}

enterOciMinWait(value: string) {
return new LabeledInputPo('[data-testid="clusterrepo-oci-min-wait-input"]').set(value);
return new UnitInputPo('[data-testid="clusterrepo-oci-min-wait-input"]').setValue(value);
}

ociMaxWait() {
return this.self().get('[data-testid="clusterrepo-oci-max-wait-input"]').invoke('val');
return this.self().get('[data-testid="clusterrepo-oci-max-wait-input"] input').invoke('val');
}

enterOciMaxWait(value: string) {
return new LabeledInputPo('[data-testid="clusterrepo-oci-max-wait-input"]').set(value);
return new UnitInputPo('[data-testid="clusterrepo-oci-max-wait-input"]').setValue(value);
}

ociMaxRetries() {
Expand Down
9 changes: 7 additions & 2 deletions cypress/e2e/po/edit/chart-repositories.po.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import LabeledInputPo from '@/cypress/e2e/po/components/labeled-input.po';
import UnitInputPo from '@/cypress/e2e/po/components/unit-input.po';
import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po';
import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po';
import RadioGroupInputPo from '@/cypress/e2e/po/components/radio-group-input.po';
Expand Down Expand Up @@ -38,11 +39,11 @@ export default class ChartRepositoriesCreateEditPo extends PagePo {
}

ociMinWaitInput() {
return new LabeledInputPo('[data-testid="clusterrepo-oci-min-wait-input"]');
return new UnitInputPo('[data-testid="clusterrepo-oci-min-wait-input"]');
}

ociMaxWaitInput() {
return new LabeledInputPo('[data-testid="clusterrepo-oci-max-wait-input"]');
return new UnitInputPo('[data-testid="clusterrepo-oci-max-wait-input"]');
}

authentication(): LabeledSelectPo {
Expand All @@ -65,6 +66,10 @@ export default class ChartRepositoriesCreateEditPo extends PagePo {
return this.authSelectOrCreate('[data-testid="clusterrepo-auth-secret"]');
}

refreshIntervalInput() {
return new UnitInputPo('[data-testid="clusterrepo-refresh-interval"]');
}

saveAndWaitForRequests(method: string, url: string) {
cy.intercept(method, url).as('request');
this.saveCreateForm().click();
Expand Down
11 changes: 7 additions & 4 deletions cypress/e2e/tests/pages/manager/repositories.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,18 @@ describe('Cluster Management Helm Repositories', { testIsolation: 'off', tags: [
repositoriesPage.createEditRepositories().waitForPage();
const ociUrl = 'oci://test.rancher.io/charts/mychart';
const ociMinWait = '2';
const expectedOciMinWaitInPayload = 2;
const ociMaxWait = '7';
const refreshInterval = '12';

repositoriesPage.createEditRepositories().nameNsDescription().name().set(this.repoName);
repositoriesPage.createEditRepositories().nameNsDescription().description().set(`${ this.repoName }-description`);
repositoriesPage.createEditRepositories().repoRadioBtn().set(2);
repositoriesPage.createEditRepositories().ociUrl().set(ociUrl);
repositoriesPage.createEditRepositories().refreshIntervalInput().setValue(refreshInterval);
repositoriesPage.createEditRepositories().clusterRepoAuthSelectOrCreate().createBasicAuth('test', 'test');
repositoriesPage.createEditRepositories().ociMinWaitInput().set(ociMinWait);
repositoriesPage.createEditRepositories().ociMinWaitInput().setValue(ociMinWait);
// setting a value and removing it so in the intercept we test that the key(e.g. maxWait) is not included in the request
repositoriesPage.createEditRepositories().ociMaxWaitInput().set(ociMaxWait);
repositoriesPage.createEditRepositories().ociMaxWaitInput().setValue(ociMaxWait);
repositoriesPage.createEditRepositories().ociMaxWaitInput().clear();

cy.intercept('POST', '/v1/catalog.cattle.io.clusterrepos').as('createRepository');
Expand All @@ -227,10 +228,12 @@ describe('Cluster Management Helm Repositories', { testIsolation: 'off', tags: [
cy.wait('@createRepository', { requestTimeout: 10000 }).then((req) => {
expect(req.response?.statusCode).to.equal(201);
expect(req.request?.body?.spec.url).to.equal(ociUrl);
expect(req.request?.body?.spec.exponentialBackOffValues.minWait).to.equal(expectedOciMinWaitInPayload);
expect(req.request?.body?.spec.exponentialBackOffValues.minWait).to.equal(Number(ociMinWait));
expect(req.request?.body?.spec.exponentialBackOffValues.maxWait).to.equal(undefined);
// insecurePlainHttp should always be included in the payload for oci repo creation
expect(req.request?.body?.spec.insecurePlainHttp).to.equal(false);
// check refreshInterval
expect(req.request?.body?.spec.refreshInterval).to.equal(Number(refreshInterval));
});

repositoriesPage.waitForPage();
Expand Down
13 changes: 8 additions & 5 deletions shell/assets/translations/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1079,14 +1079,17 @@ catalog:
exponentialBackOff:
label: Exponential Back Off
minWait:
label: Min Wait Time (in Seconds)
placeholder: 1 (default)
label: Min Wait Time
placeholder: 'default: 1'
maxWait:
label: Max Wait Time (in Seconds)
placeholder: 5 (default)
label: Max Wait Time
placeholder: 'default: 5'
maxRetries:
label: Max Number of Retries
placeholder: 5 (default)
placeholder: 'default: 5'
refreshInterval:
label: Refresh Interval
placeholder: 'default: {hours}'
tools:
header: Cluster Tools
noTools: "No Cluster Tools found"
Expand Down
147 changes: 95 additions & 52 deletions shell/edit/catalog.cattle.io.clusterrepo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthS
import InfoBox from '@shell/components/InfoBox';
import { Checkbox } from '@components/Form/Checkbox';
import { MANAGEMENT, NAMESPACE, CLUSTER_REPO_TYPES } from '@shell/config/types';
import UnitInput from '@shell/components/form/UnitInput.vue';

export default {
name: 'CruCatalogRepo',
Expand All @@ -23,7 +24,8 @@ export default {
Labels,
SelectOrCreateAuthSecret,
InfoBox,
Checkbox
Checkbox,
UnitInput
},

mixins: [CreateEditView],
Expand Down Expand Up @@ -83,23 +85,35 @@ export default {
this.value.spec['exponentialBackOffValues'] = {};
}
// when user removes the value we remove the key too, backend will set the default value
if (newVal === '') {
if (newVal === '' || newVal === null) {
delete this.value.spec.exponentialBackOffValues[key];

return;
}

this.value.spec.exponentialBackOffValues[key] = Number(newVal);
},
updateRefreshInterval(newVal) {
// when user removes the value we don't send refreshInterval along with the payload
if (newVal === null) {
delete this.value.spec.refreshInterval;

return;
}

this.value.spec.refreshInterval = newVal;
},
resetGitRepoValues() {
delete this.value.spec['gitRepo'];
delete this.value.spec['gitBranch'];
delete this.value.spec['refreshInterval'];
},
resetOciValues() {
delete this.value.spec['url'];
delete this.value.spec['insecurePlainHttp'];
delete this.value.spec['insecureSkipTLSVerify'];
delete this.value.spec['caBundle'];
delete this.value.spec['refreshInterval'];
delete this.value.spec['exponentialBackOffValues'];
this.ociMinWait = undefined;
this.ociMaxWait = undefined;
Expand Down Expand Up @@ -139,55 +153,80 @@ export default {
</div>
</div>

<div
v-if="clusterRepoType === CLUSTER_REPO_TYPES.GIT_REPO"
class="row mb-10"
<InfoBox
v-if="clusterRepoType === CLUSTER_REPO_TYPES.OCI_URL"
class="p-10"
>
<div class="col span-6">
{{ t('catalog.repo.oci.info', null, true) }}
</InfoBox>

<div class="row mb-10">
<template v-if="clusterRepoType === CLUSTER_REPO_TYPES.GIT_REPO">
<div class="col span-6">
<LabeledInput
v-model:value.trim="value.spec.gitRepo"
:required="true"
:label="t('catalog.repo.gitRepo.label')"
:placeholder="t('catalog.repo.gitRepo.placeholder', null, true)"
:mode="mode"
data-testid="clusterrepo-git-repo-input"
/>
</div>
<div class="col span-3">
<LabeledInput
v-model:value.trim="value.spec.gitBranch"
:sub-label="!value.spec.gitBranch ? t('catalog.repo.gitBranch.defaultMessage', null, true) : undefined"
:label="t('catalog.repo.gitBranch.label')"
:placeholder="t('catalog.repo.gitBranch.placeholder', null, true)"
:mode="mode"
data-testid="clusterrepo-git-branch-input"
/>
</div>
</template>

<template v-else-if="clusterRepoType === CLUSTER_REPO_TYPES.OCI_URL">
<div class="col span-6">
<LabeledInput
v-model:value.trim="value.spec.url"
:required="true"
:label="t('catalog.repo.oci.urlLabel')"
:placeholder="t('catalog.repo.oci.placeholder', null, true)"
:mode="mode"
data-testid="clusterrepo-oci-url-input"
/>
</div>
</template>

<div
v-else
class="col span-6"
>
<LabeledInput
v-model:value.trim="value.spec.gitRepo"
v-model:value.trim="value.spec.url"
:required="true"
:label="t('catalog.repo.gitRepo.label')"
:placeholder="t('catalog.repo.gitRepo.placeholder', null, true)"
:label="t('catalog.repo.url.label')"
:placeholder="t('catalog.repo.url.placeholder', null, true)"
:mode="mode"
data-testid="clusterrepo-git-repo-input"
data-testid="clusterrepo-helm-url-input"
/>
</div>
<div class="col span-6">
<LabeledInput
v-model:value.trim="value.spec.gitBranch"
:sub-label="!value.spec.gitBranch ? t('catalog.repo.gitBranch.defaultMessage', null, true) : undefined"
:label="t('catalog.repo.gitBranch.label')"
:placeholder="t('catalog.repo.gitBranch.placeholder', null, true)"

<div
class="col span-3"
data-testid="clusterrepo-refresh-interval"
>
<UnitInput
v-model:value.trim="value.spec.refreshInterval"
:label="t('catalog.repo.refreshInterval.label')"
:mode="mode"
data-testid="clusterrepo-git-branch-input"
min="0"
:suffix="t('unit.hour', { count: value.spec.refreshInterval })"
:placeholder="t('catalog.repo.refreshInterval.placeholder', { hours: clusterRepoType === CLUSTER_REPO_TYPES.OCI_URL ? 24 : 6 })"
@update:value="updateRefreshInterval($event)"
/>
</div>
</div>

<div v-else-if="clusterRepoType === CLUSTER_REPO_TYPES.OCI_URL">
<InfoBox class="p-10">
{{ t('catalog.repo.oci.info', null, true) }}
</InfoBox>
<LabeledInput
v-model:value.trim="value.spec.url"
:required="true"
:label="t('catalog.repo.oci.urlLabel')"
:placeholder="t('catalog.repo.oci.placeholder', null, true)"
:mode="mode"
data-testid="clusterrepo-oci-url-input"
/>
</div>

<LabeledInput
v-else
v-model:value.trim="value.spec.url"
:required="true"
:label="t('catalog.repo.url.label')"
:placeholder="t('catalog.repo.url.placeholder', null, true)"
:mode="mode"
data-testid="clusterrepo-helm-url-input"
/>
<SelectOrCreateAuthSecret
v-model:value="value.spec.clientSecret"
:mode="mode"
Expand Down Expand Up @@ -231,36 +270,40 @@ export default {
<h4 class="mb-10 mt-20">
{{ t('catalog.repo.oci.exponentialBackOff.label') }}
</h4>
<div class="row mb-10 mt-10">
<div class="col span-4">
<LabeledInput
<div class="row mb-40 mt-10">
<div
class="col span-4"
data-testid="clusterrepo-oci-min-wait-input"
>
<UnitInput
v-model:value.trim="ociMinWait"
:label="t('catalog.repo.oci.exponentialBackOff.minWait.label')"
:placeholder="!ociMinWait ? t('catalog.repo.oci.exponentialBackOff.minWait.placeholder') : undefined"
:placeholder="t('catalog.repo.oci.exponentialBackOff.minWait.placeholder')"
:mode="mode"
type="number"
min="1"
data-testid="clusterrepo-oci-min-wait-input"
:suffix="t('suffix.seconds', { count: ociMinWait })"
@update:value="updateExponentialBackOffValues('minWait', $event)"
/>
</div>
<div class="col span-4">
<LabeledInput
<div
class="col span-4"
data-testid="clusterrepo-oci-max-wait-input"
>
<UnitInput
v-model:value.trim="ociMaxWait"
:label="t('catalog.repo.oci.exponentialBackOff.maxWait.label')"
:placeholder="!ociMaxWait ? t('catalog.repo.oci.exponentialBackOff.maxWait.placeholder') : undefined"
:placeholder="t('catalog.repo.oci.exponentialBackOff.maxWait.placeholder')"
:mode="mode"
type="number"
min="1"
data-testid="clusterrepo-oci-max-wait-input"
:suffix="t('suffix.seconds', { count: ociMaxWait })"
@update:value="updateExponentialBackOffValues('maxWait', $event)"
/>
</div>
<div class="col span-4">
<LabeledInput
v-model:value.trim="ociMaxRetries"
:label="t('catalog.repo.oci.exponentialBackOff.maxRetries.label')"
:placeholder="!ociMaxRetries ? t('catalog.repo.oci.exponentialBackOff.maxRetries.placeholder') : undefined"
:placeholder="t('catalog.repo.oci.exponentialBackOff.maxRetries.placeholder')"
:mode="mode"
type="number"
min="0"
Expand Down
Loading