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

Restrict installed apps upgrade #13086

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions shell/assets/translations/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,8 @@ catalog:
label: Resources
busy: The related resources will appear when {app} is fully installed.
values: Values YAML
upgrade:
uncertainUpgradeWarningTooltip: Unable to identify source chart and repository for this application in order to determine if an upgrade is available
chart:
registry:
label: Container Registry
Expand Down
25 changes: 21 additions & 4 deletions shell/list/catalog.cattle.io.app.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script>
import PaginatedResourceTable from '@shell/components/PaginatedResourceTable';
import { APP_UPGRADE_STATUS } from '@shell/store/catalog';

export default {
name: 'ListApps',
Expand All @@ -21,6 +22,10 @@ export default {
}
},

data() {
return { APP_UPGRADE_STATUS };
},

async fetch() {
await this.$store.dispatch('catalog/load');
},
Expand All @@ -36,18 +41,30 @@ export default {
>
<template #cell:upgrade="{row}">
<span
v-if="row.upgradeAvailable"
v-if="row.upgradeAvailable === APP_UPGRADE_STATUS.SINGLE_UPGRADE"
class="badge-state bg-warning hand"
@click="row.goToUpgrade(row.upgradeAvailable)"
@click="row.goToUpgrade(row.upgradeAvailableVersion)"
>
{{ row.upgradeAvailable }}
{{ row.upgradeAvailableVersion }}
<i class="icon icon-upload" />
</span>
<span
v-else-if="row.upgradeAvailable === false"
v-else-if="row.upgradeAvailable === APP_UPGRADE_STATUS.NOT_APPLICABLE"
v-t="'catalog.app.managed'"
class="text-muted"
/>
<span
v-else-if="row.upgradeAvailable === APP_UPGRADE_STATUS.NO_UPGRADE"
class="text-muted"
/>
<span
v-else-if="row.upgradeAvailable === APP_UPGRADE_STATUS.MULTIPLE_UPGRADES"
>
<i
v-clean-tooltip="t('catalog.app.upgrade.uncertainUpgradeWarningTooltip')"
class="icon icon-info"
/>
</span>
</template>
</PaginatedResourceTable>
</template>
Expand Down
9 changes: 5 additions & 4 deletions shell/mixins/__tests__/chart.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ChartMixin from '@shell/mixins/chart';
import { OPA_GATE_KEEPER_ID } from '@shell/pages/c/_cluster/gatekeeper/index.vue';
import { mount } from '@vue/test-utils';
import { APP_UPGRADE_STATUS } from '@shell/store/catalog';

describe('chartMixin', () => {
const testCases = {
Expand All @@ -10,10 +11,10 @@ describe('chartMixin', () => {
['any_other_id', 0]
],
managedApps: [
[false, false, 0],
[true, null, 0],
[true, true, 0],
[true, false, 1],
[false, APP_UPGRADE_STATUS.NOT_APPLICABLE, 0],
[true, APP_UPGRADE_STATUS.NO_UPGRADE, 0],
[true, 'some-version', 0],
[true, APP_UPGRADE_STATUS.NOT_APPLICABLE, 1],
],
};

Expand Down
4 changes: 2 additions & 2 deletions shell/mixins/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { formatSi, parseSi } from '@shell/utils/units';
import { CAPI, CATALOG } from '@shell/config/types';
import { isPrerelease } from '@shell/utils/version';
import difference from 'lodash/difference';
import { LINUX } from '@shell/store/catalog';
import { LINUX, APP_UPGRADE_STATUS } from '@shell/store/catalog';
import { clone } from '@shell/utils/object';
import { merge } from 'lodash';

Expand Down Expand Up @@ -181,7 +181,7 @@ export default {
warnings.unshift(this.t('gatekeeperIndex.deprecated', {}, true));
}

if (this.existing && this.existing.upgradeAvailable === false) {
if (this.existing && this.existing.upgradeAvailable === APP_UPGRADE_STATUS.NOT_APPLICABLE) {
warnings.unshift(this.t('catalog.install.warning.managed', {
name: this.existing.name,
version: this.chart ? this.query.versionName : null
Expand Down
145 changes: 145 additions & 0 deletions shell/models/__tests__/catalog.cattle.io.app.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import CatalogApp from '@shell/models/catalog.cattle.io.app';
import { APP_UPGRADE_STATUS } from '@shell/store/catalog';

const latestVersion = '1.16.2';
const secondLatestVersion = '1.16.1';
const chartName = 'cert-manager';

const appCo = {
repoName: 'appCo',
home: 'https://apps.rancher.io/applications/cert-manager'
};

const certManagerOfficial = {
repoName: 'certManagerOfficial',
home: 'https://cert-manager.io',
oldHome: 'https://github.com/jetstack/cert-manager' // older versions of cert-manager used to have this home url(e.g. 1.7.1)
};

// cert-manager chart from application collection OCI repo
const appCoMatchingChart1 = {
name: chartName,
repoName: appCo.repoName,
versions: [{
version: latestVersion,
home: appCo.home,
repoName: appCo.repoName,
annotations: {}
},
{
version: secondLatestVersion,
home: appCo.home,
repoName: appCo.repoName,
annotations: {}
}]
};

const appCoMatchingChart2 = {
name: chartName,
repoName: appCo.repoName,
versions: [{
version: latestVersion,
home: appCo.home,
repoName: appCo.repoName,
annotations: {}
},
{
version: secondLatestVersion,
home: appCo.home,
repoName: appCo.repoName,
annotations: {}
}]
};

// cert-manager chart from its official helm repo 'https://cert-manager.io' added to Rancher UI repositories
const certManagerOfficialMatchingChart1 = {
name: chartName,
repoName: certManagerOfficial.repoName,
versions: [{
version: latestVersion,
home: certManagerOfficial.home,
repoName: certManagerOfficial.repoName,
annotations: {},
},
{
version: secondLatestVersion,
home: certManagerOfficial.oldHome,
repoName: certManagerOfficial.repoName,
annotations: {},
}]
};

const certManagerOfficialMatchingChart2 = {
name: chartName,
repoName: certManagerOfficial.repoName,
versions: [{
version: latestVersion,
home: certManagerOfficial.home,
repoName: certManagerOfficial.repoName,
annotations: {},
},
{
version: secondLatestVersion,
home: certManagerOfficial.oldHome,
repoName: certManagerOfficial.repoName,
annotations: {},
}]
};

const installedCertManagerAppCoFromRancherUI = {
metadata: {
name: chartName,
home: appCo.home,
version: secondLatestVersion
}
};

const installedCertManagerOfficialFromCli = {
metadata: {
name: chartName,
home: certManagerOfficial.oldHome,
version: secondLatestVersion
}
};

const installedCertManagerOfficialFromRancherUI = {
metadata: {
name: chartName,
home: certManagerOfficial.oldHome,
version: secondLatestVersion
}
};

describe('class CatalogApp', () => {
describe('upgradeAvailable', () => {
const testCases = [
// when you follow Rancher Installation docs to install cert-manager through CLI
[installedCertManagerOfficialFromCli, [], APP_UPGRADE_STATUS.NO_UPGRADE],
[installedCertManagerOfficialFromCli, [appCoMatchingChart1], APP_UPGRADE_STATUS.NO_UPGRADE],
[installedCertManagerOfficialFromCli, [appCoMatchingChart1, appCoMatchingChart2], APP_UPGRADE_STATUS.NO_UPGRADE],
[installedCertManagerOfficialFromCli, [appCoMatchingChart1, appCoMatchingChart2, certManagerOfficialMatchingChart1], APP_UPGRADE_STATUS.SINGLE_UPGRADE],
// when you add application collection OCI repo through UI
[installedCertManagerAppCoFromRancherUI, [], APP_UPGRADE_STATUS.NO_UPGRADE],
[installedCertManagerAppCoFromRancherUI, [appCoMatchingChart1], APP_UPGRADE_STATUS.SINGLE_UPGRADE],
[installedCertManagerAppCoFromRancherUI, [appCoMatchingChart1, certManagerOfficialMatchingChart1], APP_UPGRADE_STATUS.SINGLE_UPGRADE],
[installedCertManagerAppCoFromRancherUI, [appCoMatchingChart1, appCoMatchingChart2], APP_UPGRADE_STATUS.MULTIPLE_UPGRADES],
// when you add cert-manager official helm repo through UI
[installedCertManagerOfficialFromRancherUI, [], APP_UPGRADE_STATUS.NO_UPGRADE],
[installedCertManagerOfficialFromRancherUI, [certManagerOfficialMatchingChart1], APP_UPGRADE_STATUS.SINGLE_UPGRADE],
[installedCertManagerOfficialFromRancherUI, [certManagerOfficialMatchingChart1, appCoMatchingChart1], APP_UPGRADE_STATUS.SINGLE_UPGRADE],
[installedCertManagerOfficialFromRancherUI, [certManagerOfficialMatchingChart1, certManagerOfficialMatchingChart2], APP_UPGRADE_STATUS.MULTIPLE_UPGRADES]
];

it.each(testCases)('should return the correct upgrade status', (installedChart: Object, matchingCharts: any, expected: any) => {
const catalogApp = new CatalogApp({ spec: { chart: installedChart } }, {
rootGetters: {
'catalog/chart': () => matchingCharts,
currentCluster: { workerOSs: ['linux'] },
'prefs/get': () => false
}
});

expect(catalogApp.upgradeAvailable).toBe(expected);
});
});
});
Loading
Loading