diff --git a/shell/assets/translations/en-us.yaml b/shell/assets/translations/en-us.yaml index 23bae1d138a..b02660dd08e 100644 --- a/shell/assets/translations/en-us.yaml +++ b/shell/assets/translations/en-us.yaml @@ -888,6 +888,13 @@ catalog: appReadmeMissing: This chart doesn't have any additional chart information. appReadmeTitle: Chart Information (Helm README) chart: Chart + warning: + managed: + Warning, Rancher manages deployment and upgrade of the {name} app. Upgrading this app is not supported.
+ {version, select, + null { } + other { Under most circumstances, no user intervention should be needed to ensure that the {version} version is compatible with the version of Rancher that you are running.} + } error: requiresFound: '{name} must be installed before you can install this chart.' requiresMissing: 'This chart requires another chart that provides {name}, but none was was found.' @@ -981,6 +988,9 @@ catalog: current: '{ver} (Current)' linux: '{ver} (Linux-only)' windows: '{ver} (Windows-only)' + delete: + warning: + managed: Warning, Rancher manages deployment and upgrade of the {name} app. Deleting this app is not supported. operation: tableHeaders: action: Action diff --git a/shell/mixins/__tests__/chart.test.ts b/shell/mixins/__tests__/chart.test.ts index 3699a2eae11..a9d8a8139e7 100644 --- a/shell/mixins/__tests__/chart.test.ts +++ b/shell/mixins/__tests__/chart.test.ts @@ -4,15 +4,27 @@ import ChartMixin from '@shell/mixins/chart'; import { OPA_GATE_KEEPER_ID } from '@shell/pages/c/_cluster/gatekeeper/index.vue'; describe('chartMixin', () => { - const testCases = [[null, 0], [OPA_GATE_KEEPER_ID, 1], ['any_other_id', 0]]; + const testCases = { + opa: [ + [null, 0], + [OPA_GATE_KEEPER_ID, 1], + ['any_other_id', 0] + ], + managedApps: [ + [false, false, 0], + [true, null, 0], + [true, true, 0], + [true, false, 1], + ], + }; - it.each(testCases)( - 'should add OPA deprecation warning properly', (chartId, expected) => { - const localVue = createLocalVue(); + const localVue = createLocalVue(); - localVue.use(Vuex); - localVue.mixin(ChartMixin); + localVue.use(Vuex); + localVue.mixin(ChartMixin); + it.each(testCases.opa)( + 'should add OPA deprecation warning properly', (chartId, expected) => { const store = new Vuex.Store({ getters: { currentCluster: () => {}, @@ -37,4 +49,34 @@ describe('chartMixin', () => { expect(warnings).toHaveLength(expected); } ); + + it.each(testCases.managedApps)( + 'should add managed apps warning properly', (isEdit, upgradeAvailable, expected) => { + const id = 'cattle-fleet-local-system/fleet-agent-local'; + const data = isEdit ? { existing: { id, upgradeAvailable } } : undefined; + + const store = new Vuex.Store({ + getters: { + currentCluster: () => {}, + isRancher: () => true, + 'catalog/repo': () => { + return () => 'repo'; + }, + 'catalog/chart': () => { + return () => ({ id }); + }, + 'i18n/t': () => jest.fn() + } + }); + + const vm = localVue.extend({}); + const instance = new vm({ store, data }); + + instance.$route = { query: { chart: 'chart_name' } }; + + const warnings = instance.warnings; + + expect(warnings).toHaveLength(expected as number); + } + ); }); diff --git a/shell/mixins/chart.js b/shell/mixins/chart.js index 78d9e19001a..9803cad350b 100644 --- a/shell/mixins/chart.js +++ b/shell/mixins/chart.js @@ -190,6 +190,13 @@ export default { warnings.unshift(this.t('gatekeeperIndex.deprecated', {}, true)); } + if (this.existing && this.existing.upgradeAvailable === false) { + warnings.unshift(this.t('catalog.install.warning.managed', { + name: this.existing.name, + version: this.chart ? this.query.versionName : null + }, true)); + } + return warnings; }, diff --git a/shell/models/catalog.cattle.io.app.js b/shell/models/catalog.cattle.io.app.js index cf423bba1af..233a1e6153b 100644 --- a/shell/models/catalog.cattle.io.app.js +++ b/shell/models/catalog.cattle.io.app.js @@ -39,6 +39,14 @@ export default class CatalogApp extends SteveModel { return out; } + get warnDeletionMessage() { + if (this.upgradeAvailable === false) { + return this.t('catalog.delete.warning.managed', { name: this.name }); + } + + return null; + } + matchingChart(includeHidden) { const chart = this.spec?.chart;