Skip to content
Merged
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
15 changes: 15 additions & 0 deletions cypress/e2e/po/pages/explorer/charts/install-charts.po.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po';
import TabbedPo from '~/cypress/e2e/po/components/tabbed.po';
import CheckboxInputPo from '~/cypress/e2e/po/components/checkbox-input.po';
import LabeledInputPo from '~/cypress/e2e/po/components/labeled-input.po';
import LabeledSelectPo from '~/cypress/e2e/po/components/labeled-select.po';

export class InstallChartPage extends PagePo {
private static createPath(clusterId: string) {
Expand Down Expand Up @@ -54,4 +57,16 @@ export class InstallChartPage extends PagePo {
chartName() {
return this.self().get('[data-testid="NameNsDescriptionNameInput"]');
}

chartVersionSelector(): LabeledSelectPo {
return new LabeledSelectPo('[data-testid="chart-version-selector"]');
}

customRegistryCheckbox(): CheckboxInputPo {
return new CheckboxInputPo('[data-testid="custom-registry-checkbox"]');
}

customRegistryInput(): LabeledInputPo {
return new LabeledInputPo('[data-testid="custom-registry-input"]');
}
}
59 changes: 59 additions & 0 deletions cypress/e2e/tests/pages/charts/chart-install-wizard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { InstallChartPage } from '@/cypress/e2e/po/pages/explorer/charts/install
import { MEDIUM_TIMEOUT_OPT } from '@/cypress/support/utils/timeouts';
import TabbedPo from '@/cypress/e2e/po/components/tabbed.po';
import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po';
import ChartInstalledAppsListPagePo from '@/cypress/e2e/po/pages/chart-installed-apps.po';
import { NamespaceFilterPo } from '@/cypress/e2e/po/components/namespace-filter.po';

const configMapPayload = {
apiVersion: 'v1',
Expand Down Expand Up @@ -67,4 +69,61 @@ describe('Charts Wizard', { testIsolation: 'off', tags: ['@charts', '@adminUser'
cy.updateNamespaceFilter('local', 'none', '{"local":["all://user"]}');
});
});

describe('Custom registry', () => {
const namespacePicker = new NamespaceFilterPo();
const installChartPage = new InstallChartPage();
const chartPage = new ChartPage();
const chartName = 'Rancher Backups';
const customRegistry = 'my.custom.registry:5000';

it('should persist custom registry when changing chart version', () => {
const installedAppsPage = new ChartInstalledAppsListPagePo('local', 'apps');

// We need to install the chart first to have the versions selector show up later when we come back to the install page
ChartPage.navTo(null, chartName);
chartPage.waitForChartHeader(chartName, MEDIUM_TIMEOUT_OPT);
chartPage.goToInstall();
installChartPage.nextPage();

cy.intercept('POST', '/v1/catalog.cattle.io.clusterrepos/rancher-charts?action=install').as('installApp');
installChartPage.installChart();
namespacePicker.toggle();
namespacePicker.clickOptionByLabel('All Namespaces');
namespacePicker.isChecked('All Namespaces');
namespacePicker.closeDropdown();
installedAppsPage.waitForInstallCloseTerminal('installApp', ['rancher-backup', 'rancher-backup-crd']);

ChartPage.navTo(null, chartName);
chartPage.waitForChartHeader(chartName, MEDIUM_TIMEOUT_OPT);
chartPage.goToInstall();

// The version selector should now be visible
installChartPage.chartVersionSelector().self().should('be.visible');

installChartPage.customRegistryCheckbox().set();

// Enter custom registry
installChartPage.customRegistryInput().self().should('be.visible');
installChartPage.customRegistryInput().set(customRegistry);

// Change chart version
installChartPage.chartVersionSelector().toggle();
installChartPage.chartVersionSelector().clickOption(2);

// Verify custom registry is still there
installChartPage.customRegistryCheckbox().isChecked();
installChartPage.customRegistryInput().self().should('have.value', customRegistry);
});

after('clean up', () => {
const chartNamespace = 'cattle-resources-system';
const chartApp = 'rancher-backup';
const chartCrd = 'rancher-backup-crd';

cy.createRancherResource('v1', `catalog.cattle.io.apps/${ chartNamespace }/${ chartApp }?action=uninstall`, '{}');
cy.createRancherResource('v1', `catalog.cattle.io.apps/${ chartNamespace }/${ chartCrd }?action=uninstall`, '{}');
cy.updateNamespaceFilter('local', 'none', '{"local":["all://user"]}');
});
});
});
33 changes: 33 additions & 0 deletions shell/pages/c/_cluster/apps/charts/install.vue
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ export default {
two different Helm chart versions is a "user value," or
a user-selected customization.
*/
this.preserveCustomRegistryValue();
userValues = diff(this.loadedVersionValues, this.chartValues);
} else if ( this.existing ) {
await this.existing.fetchValues(); // In theory this has already been called, but do again to be safe
Expand Down Expand Up @@ -824,6 +825,35 @@ export default {
},

methods: {
/**
* The custom registry UI fields (checkbox and input) are not directly bound to chartValues.
* Before calculating the diff to carry over user customizations, we must
* first synchronize the state of these UI fields with chartValues. This
* ensures any user changes to the custom registry settings are
* included in the diff and preserved when changing versions.
*/
preserveCustomRegistryValue() {
if (!this.showCustomRegistry) {
return;
}

if (this.showCustomRegistryInput) {
set(this.chartValues, 'global.systemDefaultRegistry', this.customRegistrySetting);
set(this.chartValues, 'global.cattle.systemDefaultRegistry', this.customRegistrySetting);
} else {
// Note: Using `delete` here is safe because this is not a reactive property update
// that the UI needs to track. This is a one-time mutation before a diff.
if (get(this.chartValues, 'global.systemDefaultRegistry')) {
delete this.chartValues.global.systemDefaultRegistry;
}
if (get(this.chartValues, 'global.cattle.systemDefaultRegistry')) {
// It's possible `this.chartValues.global.cattle` doesn't exist,
// but `get` ensures we only proceed if the full path exists.
delete this.chartValues.global.cattle.systemDefaultRegistry;
}
}
},

async getClusterRegistry() {
const hasPermissionToSeeProvCluster = this.$store.getters[`management/schemaFor`](CAPI.RANCHER_CLUSTER);

Expand Down Expand Up @@ -1367,6 +1397,7 @@ export default {
<!-- We have a chart for the app, let the user select a new version -->
<LabeledSelect
v-if="chart"
data-testid="chart-version-selector"
:label="t('catalog.install.version')"
:value="query.versionName"
:options="filteredVersions"
Expand Down Expand Up @@ -1435,6 +1466,7 @@ export default {
v-if="showCustomRegistry"
v-model:value="showCustomRegistryInput"
class="mb-20"
data-testid="custom-registry-checkbox"
:label="t('catalog.chart.registry.custom.checkBoxLabel')"
:tooltip="t('catalog.chart.registry.tooltip')"
/>
Expand All @@ -1443,6 +1475,7 @@ export default {
<LabeledInput
v-if="showCustomRegistryInput"
v-model:value="customRegistrySetting"
data-testid="custom-registry-input"
label-key="catalog.chart.registry.custom.inputLabel"
placeholder-key="catalog.chart.registry.custom.placeholder"
:min-height="30"
Expand Down
Loading