@rancher/shell 3.0.5-rc.9 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/assets/translations/en-us.yaml +11 -5
  2. package/components/FilterPanel.vue +8 -1
  3. package/components/PaginatedResourceTable.vue +7 -2
  4. package/components/PodSecurityAdmission.vue +2 -0
  5. package/components/PromptRemove.vue +5 -0
  6. package/components/ResourceTable.vue +30 -20
  7. package/components/form/ProjectMemberEditor.vue +2 -0
  8. package/components/nav/Header.vue +6 -5
  9. package/config/product/explorer.js +5 -5
  10. package/config/store.js +2 -0
  11. package/config/uiplugins.js +1 -1
  12. package/core/plugin.ts +15 -3
  13. package/core/types.ts +30 -7
  14. package/dialog/SloDialog.vue +1 -1
  15. package/edit/auth/oidc.vue +106 -6
  16. package/edit/auth/saml.vue +5 -5
  17. package/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest.vue +1 -0
  18. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +1 -0
  19. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +1 -0
  20. package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +1 -0
  21. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -0
  22. package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +6 -0
  23. package/initialize/install-plugins.js +1 -3
  24. package/list/catalog.cattle.io.clusterrepo.vue +2 -2
  25. package/mixins/__tests__/auth-config.test.ts +4 -6
  26. package/mixins/__tests__/chart.test.ts +1 -1
  27. package/mixins/auth-config.js +33 -10
  28. package/mixins/chart.js +1 -1
  29. package/models/management.cattle.io.cluster.js +1 -1
  30. package/models/workload.js +1 -1
  31. package/package.json +2 -2
  32. package/pages/auth/login.vue +8 -3
  33. package/pages/auth/logout.vue +6 -5
  34. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +6 -0
  35. package/pages/c/_cluster/apps/charts/StatusLabel.vue +4 -3
  36. package/pages/c/_cluster/apps/charts/index.vue +12 -11
  37. package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +1 -1
  38. package/pages/c/_cluster/explorer/tools/index.vue +1 -1
  39. package/plugins/axios.js +3 -2
  40. package/plugins/dashboard-store/resource-class.js +12 -1
  41. package/plugins/ember-cookie.js +7 -3
  42. package/plugins/steve/steve-pagination-utils.ts +14 -22
  43. package/plugins/steve/subscribe.js +4 -2
  44. package/scripts/test-plugins-build.sh +4 -6
  45. package/scripts/typegen.sh +2 -0
  46. package/store/__tests__/cookies.test.ts +72 -0
  47. package/store/auth.js +34 -11
  48. package/store/cookies.ts +30 -0
  49. package/store/prefs.js +10 -5
  50. package/types/shell/index.d.ts +183 -11
  51. package/types/store/vuex.d.ts +2 -1
  52. package/types/vue-shim.d.ts +2 -5
  53. package/utils/auth.js +1 -1
  54. package/utils/pagination-utils.ts +11 -2
  55. package/utils/cookie-universal.js +0 -10
@@ -165,6 +165,7 @@ export default {
165
165
  <LabeledInput
166
166
  v-if="!config.skipSSLVerify"
167
167
  v-model:value="config.endpointCA"
168
+ :mode="mode"
168
169
  type="multiline"
169
170
  :label="t('cluster.rke2.etcd.s3config.endpointCA.label')"
170
171
  :placeholder="ccData.defaultEndpointCA"
@@ -78,6 +78,7 @@ export default {
78
78
  <div class="row">
79
79
  <Checkbox
80
80
  :value="showCustomRegistryInput"
81
+ :mode="mode"
81
82
  :label="t('cluster.privateRegistry.label')"
82
83
  data-testid="registries-enable-checkbox"
83
84
  @update:value="$emit('custom-registry-changed', $event)"
@@ -90,6 +91,7 @@ export default {
90
91
  <div class="col span-6">
91
92
  <LabeledInput
92
93
  :value="registryHost"
94
+ :mode="mode"
93
95
  label-key="catalog.chart.registry.custom.inputLabel"
94
96
  placeholder-key="catalog.chart.registry.custom.placeholder"
95
97
  :min-height="30"
@@ -102,6 +102,7 @@ export default {
102
102
  <div class="mt-20">
103
103
  <Checkbox
104
104
  v-model:value="deleteEmptyDirData"
105
+ :mode="mode"
105
106
  label-key="cluster.rke2.drain.deleteEmptyDir.label"
106
107
  tooltip-key="cluster.rke2.drain.deleteEmptyDir.tooltip"
107
108
  @update:value="update"
@@ -110,6 +111,7 @@ export default {
110
111
  <div>
111
112
  <Checkbox
112
113
  v-model:value="force"
114
+ :mode="mode"
113
115
  label="Delete standalone pods"
114
116
  label-key="cluster.rke2.drain.force.label"
115
117
  tooltip="Delete standalone pods which are not managed by a Workload controller (Deployment, Job, etc). Draining will fail if this is not set and there are standalone pods."
@@ -120,12 +122,14 @@ export default {
120
122
  <div>
121
123
  <Checkbox
122
124
  v-model:value="customGracePeriod"
125
+ :mode="mode"
123
126
  label-key="cluster.rke2.drain.gracePeriod.checkboxLabel"
124
127
  @update:value="update"
125
128
  />
126
129
  <UnitInput
127
130
  v-if="customGracePeriod"
128
131
  v-model:value="gracePeriod"
132
+ :mode="mode"
129
133
  label-key="cluster.rke2.drain.gracePeriod.inputLabel"
130
134
  :suffix="t('suffix.seconds', {count: timeout})"
131
135
  class="mb-10"
@@ -135,12 +139,14 @@ export default {
135
139
  <div>
136
140
  <Checkbox
137
141
  v-model:value="customTimeout"
142
+ :mode="mode"
138
143
  label-key="cluster.rke2.drain.timeout.checkboxLabel"
139
144
  @update:value="update"
140
145
  />
141
146
  <UnitInput
142
147
  v-if="customTimeout"
143
148
  v-model:value="timeout"
149
+ :mode="mode"
144
150
  label-key="cluster.rke2.drain.timeout.inputLabel"
145
151
  :suffix="t('suffix.seconds', {count: timeout})"
146
152
  class="drain-timeout"
@@ -12,7 +12,6 @@ import i18n from '@shell/plugins/i18n';
12
12
  import globalFormatters from '@shell/plugins/global-formatters';
13
13
 
14
14
  import axios from '@shell/utils/axios';
15
- import cookieUniversal from '@shell/utils/cookie-universal';
16
15
  import config from '@shell/utils/config';
17
16
  import axiosShell from '@shell/plugins/axios';
18
17
  import codeMirror from '@shell/plugins/codemirror-loader';
@@ -47,7 +46,7 @@ export async function installPlugins(vueApp) {
47
46
  }
48
47
 
49
48
  export async function installInjectedPlugins(app, vueApp) {
50
- const pluginDefinitions = [config, cookieUniversal, axios, plugins, pluginsLoader, axiosShell, intNumber, codeMirror, nuxtClientInit, replaceAll, plugin, steveCreateWorker, emberCookie, internalApiPlugin];
49
+ const pluginDefinitions = [config, axios, plugins, pluginsLoader, axiosShell, intNumber, codeMirror, nuxtClientInit, replaceAll, plugin, steveCreateWorker, emberCookie, internalApiPlugin];
51
50
 
52
51
  const installations = pluginDefinitions.map(async(pluginDefinition) => {
53
52
  if (typeof pluginDefinition === 'function') {
@@ -64,7 +63,6 @@ export async function installInjectedPlugins(app, vueApp) {
64
63
  // If there's any performance reasons this can be done concurrently with all of the installation promises above but I felt it was organizationally better to keep both i18n items together.
65
64
  await app.store.dispatch('i18n/init');
66
65
 
67
- // Order matters here. This is coming after the other plugins specifically so $cookies can be installed. i18n/init relies on prefs/get which relies on $cookies.
68
66
  vueApp.use(i18n, { store: app.store });
69
67
  }
70
68
 
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import PaginatedResourceTable from '@shell/components/PaginatedResourceTable.vue';
3
3
  import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
4
- import ClusterRepo from '@shell/models/catalog.cattle.io.clusterrepo';
4
+ import { RancherKubeMetadata } from '@shell/types/kube/kube-api';
5
5
  import { PaginationArgs, PaginationParamFilter } from '@shell/types/store/pagination.types';
6
6
  import { defineComponent } from 'vue';
7
7
 
@@ -25,7 +25,7 @@ export default defineComponent({
25
25
  /**
26
26
  * Filter out hidden repos from list of all repos
27
27
  */
28
- filterRowsLocal(rows: ClusterRepo[]) {
28
+ filterRowsLocal(rows: { metadata: RancherKubeMetadata}[]) {
29
29
  return rows.filter((repo) => !(repo?.metadata?.annotations?.[CATALOG_ANNOTATIONS.HIDDEN_REPO] === 'true'));
30
30
  },
31
31
 
@@ -1,6 +1,7 @@
1
1
  import { mount } from '@vue/test-utils';
2
2
  import authConfigMixin from '@shell/mixins/auth-config';
3
-
3
+ import childHook from '@shell/mixins/child-hook';
4
+ //
4
5
  describe('mixin: authConfigMixin', () => {
5
6
  describe('method: save', () => {
6
7
  const componentMock = (model: any) => ({
@@ -11,10 +12,7 @@ describe('mixin: authConfigMixin', () => {
11
12
  computed: { principal: () => ({ me: {} }) },
12
13
  global: {
13
14
  mocks: {
14
- $store: {
15
- dispatch: () => model,
16
- commit: () => ({ 'auth/loggedInAs': jest.fn() }),
17
- },
15
+ $store: { dispatch: () => model },
18
16
  $route: {
19
17
  params: { id: '123' },
20
18
  query: { mode: 'edit' },
@@ -24,7 +22,7 @@ describe('mixin: authConfigMixin', () => {
24
22
  });
25
23
  const FakeComponent = {
26
24
  render() {},
27
- mixins: [authConfigMixin],
25
+ mixins: [authConfigMixin, childHook],
28
26
  methods: { applyHooks: jest.fn() },
29
27
  };
30
28
 
@@ -235,7 +235,7 @@ describe('chartMixin', () => {
235
235
  expect(wrapper.vm.action).toStrictEqual({
236
236
  name: 'downgrade',
237
237
  tKey: 'downgrade',
238
- icon: 'icon-history',
238
+ icon: 'icon-downgrade-alt',
239
239
  });
240
240
  });
241
241
  });
@@ -1,7 +1,7 @@
1
1
  import { _EDIT } from '@shell/config/query-params';
2
2
  import { NORMAN, MANAGEMENT } from '@shell/config/types';
3
3
  import { AFTER_SAVE_HOOKS, BEFORE_SAVE_HOOKS } from '@shell/mixins/child-hook';
4
- import { BASE_SCOPES } from '@shell/store/auth';
4
+ import { BASE_SCOPES, SLO_AUTH_PROVIDERS } from '@shell/store/auth';
5
5
  import { addObject, findBy } from '@shell/utils/array';
6
6
  import { exceptionToErrorsArray } from '@shell/utils/error';
7
7
  import difference from 'lodash/difference';
@@ -30,6 +30,10 @@ export default {
30
30
  }
31
31
  },
32
32
 
33
+ created() {
34
+ this.registerAfterHook(this.updateAuthProviders, 'force-update-auth-providers');
35
+ },
36
+
33
37
  async fetch() {
34
38
  await this.mixinFetch();
35
39
  },
@@ -88,6 +92,23 @@ export default {
88
92
  },
89
93
 
90
94
  methods: {
95
+ updateAuthProviders() {
96
+ // we need to forcefully re-fetch the authProviders list so that we can update the logout method
97
+ // this is to satisfy the SLO usecase where after setting an auth provider the logout method
98
+ // wasn't being updated because the resource is not watchable
99
+ this.$store.dispatch('auth/getAuthProviders', { force: true });
100
+ },
101
+
102
+ setSloType(selectedModel) {
103
+ if (!selectedModel.logoutAllEnabled && !selectedModel.logoutAllForced) {
104
+ this.sloType = SLO_OPTION_VALUES.rancher;
105
+ } else if (selectedModel.logoutAllEnabled && selectedModel.logoutAllForced) {
106
+ this.sloType = SLO_OPTION_VALUES.all;
107
+ } else if (selectedModel.logoutAllEnabled && !selectedModel.logoutAllForced) {
108
+ this.sloType = SLO_OPTION_VALUES.both;
109
+ }
110
+ },
111
+
91
112
  async mixinFetch() {
92
113
  this.authConfigName = this.$route.params.id;
93
114
 
@@ -115,20 +136,16 @@ export default {
115
136
  if (this.model.openLdapConfig) {
116
137
  this.showLdap = true;
117
138
  }
118
- if (this.value.configType === 'saml') {
139
+
140
+ // Logic for Single Logout/SLO for auth providers
141
+ if (this.value?.configType && SLO_AUTH_PROVIDERS.includes(this.value?.configType)) {
119
142
  if (!this.model.rancherApiHost || !this.model.rancherApiHost.length) {
120
143
  this.model['rancherApiHost'] = this.serverUrl;
121
144
  }
122
145
 
123
146
  // setting data for SLO
124
147
  if (this.model && Object.keys(this.model).includes('logoutAllSupported')) {
125
- if (!this.model.logoutAllEnabled && !this.model.logoutAllForced) {
126
- this.sloType = SLO_OPTION_VALUES.rancher;
127
- } else if (this.model.logoutAllEnabled && this.model.logoutAllForced) {
128
- this.sloType = SLO_OPTION_VALUES.all;
129
- } else if (this.model.logoutAllEnabled && !this.model.logoutAllForced) {
130
- this.sloType = SLO_OPTION_VALUES.both;
131
- }
148
+ this.setSloType(this.model);
132
149
  }
133
150
  }
134
151
 
@@ -220,7 +237,7 @@ export default {
220
237
  addObject(this.model.allowedPrincipalIds, this.principal.id);
221
238
  }
222
239
  // Session has switched to new 'me', ensure we react
223
- this.$store.commit('auth/loggedInAs', this.principal.id);
240
+ this.$store.dispatch('auth/loggedInAs', this.principal.id);
224
241
  } else {
225
242
  console.warn(`Unable to find principal marked as 'me'`); // eslint-disable-line no-console
226
243
  }
@@ -292,6 +309,12 @@ export default {
292
309
  // must be cancelling edit of an enabled config; reset any changes and return to add users/groups view for that config
293
310
  this.$store.dispatch(`rancher/clone`, { resource: this.originalModel }).then((cloned) => {
294
311
  this.model = cloned;
312
+
313
+ // reset SLO type (radio option)
314
+ if (cloned && Object.keys(cloned).includes('logoutAllSupported')) {
315
+ this.setSloType(cloned);
316
+ }
317
+
295
318
  this.editConfig = false;
296
319
  });
297
320
  }
package/mixins/chart.js CHANGED
@@ -247,7 +247,7 @@ export default {
247
247
  }
248
248
 
249
249
  return {
250
- name: 'downgrade', tKey: 'downgrade', icon: 'icon-history'
250
+ name: 'downgrade', tKey: 'downgrade', icon: 'icon-downgrade-alt'
251
251
  };
252
252
  },
253
253
 
@@ -278,7 +278,7 @@ export default class MgmtCluster extends SteveModel {
278
278
 
279
279
  // Color to use as the underline for the icon in the app bar
280
280
  get iconColor() {
281
- return this.metadata?.annotations[CLUSTER_BADGE.COLOR];
281
+ return this.metadata?.annotations?.[CLUSTER_BADGE.COLOR];
282
282
  }
283
283
 
284
284
  // Custom badge to show for the Cluster (if the appropriate annotations are set)
@@ -43,7 +43,7 @@ export default class Workload extends WorkloadService {
43
43
  insertAt(out, 0, {
44
44
  action: 'toggleRollbackModal',
45
45
  label: this.t('action.rollback'),
46
- icon: 'icon icon-history',
46
+ icon: 'icon icon-downgrade-alt',
47
47
  enabled: !!this.links.update,
48
48
  });
49
49
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "3.0.5-rc.9",
3
+ "version": "3.0.6",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -93,7 +93,7 @@
93
93
  "express": "4.17.1",
94
94
  "file-saver": "2.0.2",
95
95
  "floating-vue": "5.2.2",
96
- "focus-trap": "7.6.2",
96
+ "focus-trap": "7.6.5",
97
97
  "frontmatter-markdown-loader": "3.7.0",
98
98
  "identicon.js": "2.3.3",
99
99
  "intl-messageformat": "7.8.4",
@@ -134,7 +134,8 @@ export default {
134
134
  },
135
135
 
136
136
  async fetch() {
137
- const username = this.$cookies.get(USERNAME, { parseJSON: false }) || '';
137
+ const cookie = this.$store.getters['cookies/get']({ key: USERNAME, options: { parseJSON: false } });
138
+ const username = cookie || '';
138
139
 
139
140
  this.username = username;
140
141
  this.remember = !!username;
@@ -272,15 +273,19 @@ export default {
272
273
  }
273
274
 
274
275
  if ( this.remember ) {
275
- this.$cookies.set(USERNAME, this.username, {
276
+ const options = {
276
277
  encode: (x) => x,
277
278
  maxAge: 86400 * 365,
278
279
  path: '/',
279
280
  sameSite: true,
280
281
  secure: true,
282
+ };
283
+
284
+ this.$store.commit('cookies/set', {
285
+ key: USERNAME, value: this.username, options
281
286
  });
282
287
  } else {
283
- this.$cookies.remove(USERNAME);
288
+ this.$store.commit('cookies/remove', { key: USERNAME });
284
289
  }
285
290
 
286
291
  // User logged with local login - we don't do any redirect/reload, so the boot-time plugin will not run again to laod the plugins
@@ -1,19 +1,20 @@
1
1
  <script>
2
2
  import { configType } from '@shell/models/management.cattle.io.authconfig';
3
+ import { SLO_AUTH_PROVIDERS } from '@shell/store/auth';
3
4
 
4
5
  export default {
5
6
  async fetch() {
6
7
  const publicAuthProviders = await this.$store.dispatch('auth/getAuthProviders');
7
8
 
8
- const samlAuthProvider = publicAuthProviders.find((authProvider) => configType[authProvider.id] === 'saml');
9
+ const sloAuthProvider = publicAuthProviders.find((authProvider) => SLO_AUTH_PROVIDERS.includes(configType[authProvider?.id]));
9
10
 
10
- if (!!samlAuthProvider) {
11
- const { logoutAllSupported, logoutAllEnabled, logoutAllForced } = samlAuthProvider;
11
+ if (!!sloAuthProvider) {
12
+ const { logoutAllSupported, logoutAllEnabled, logoutAllForced } = sloAuthProvider;
12
13
 
13
14
  if (logoutAllSupported && logoutAllEnabled && logoutAllForced) {
14
- // SAML - force SLO (logout from all apps)
15
+ // force SLO (logout from all apps)
15
16
  await this.$store.dispatch('auth/logout', {
16
- force: true, slo: true, provider: samlAuthProvider
17
+ force: true, slo: true, provider: sloAuthProvider
17
18
  }, { root: true });
18
19
  } else {
19
20
  // simple logout
@@ -80,6 +80,12 @@ function onClickItem(type: string, label: string) {
80
80
  &-text {
81
81
  text-transform: capitalize;
82
82
  margin-right: 8px;
83
+ display: -webkit-box;
84
+ -webkit-line-clamp: 1;
85
+ -webkit-box-orient: vertical;
86
+ overflow: hidden;
87
+ text-overflow: ellipsis;
88
+ word-break: break-all;
83
89
  }
84
90
 
85
91
  &-icon {
@@ -2,9 +2,9 @@
2
2
 
3
3
  defineProps<{
4
4
  label: string;
5
- icon: string;
5
+ icon?: string;
6
6
  iconColor?: string;
7
- tooltip?: string;
7
+ iconTooltip?: string;
8
8
  }>();
9
9
 
10
10
  </script>
@@ -13,7 +13,8 @@ defineProps<{
13
13
  <div class="status-label">
14
14
  {{ label }}
15
15
  <i
16
- v-clean-tooltip.right="tooltip"
16
+ v-if="!!icon"
17
+ v-clean-tooltip.right="iconTooltip"
17
18
  :class="['icon', icon, iconColor]"
18
19
  />
19
20
  </div>
@@ -82,10 +82,10 @@ export default {
82
82
  label: {
83
83
  component: markRaw(StatusLabel),
84
84
  componentProps: {
85
- label: this.t('generic.installed'),
86
- icon: 'icon-warning',
87
- iconColor: 'warning',
88
- tooltip: this.t('catalog.charts.statusFilterCautions.installation')
85
+ label: this.t('generic.installed'),
86
+ icon: 'icon-warning',
87
+ iconColor: 'warning',
88
+ iconTooltip: this.t('catalog.charts.statusFilterCautions.installation')
89
89
  }
90
90
  }
91
91
  },
@@ -98,10 +98,10 @@ export default {
98
98
  label: {
99
99
  component: markRaw(StatusLabel),
100
100
  componentProps: {
101
- label: this.t('generic.upgradeable'),
102
- icon: 'icon-warning',
103
- iconColor: 'warning',
104
- tooltip: this.t('catalog.charts.statusFilterCautions.upgradeable')
101
+ label: this.t('generic.upgradeable'),
102
+ icon: 'icon-warning',
103
+ iconColor: 'warning',
104
+ iconTooltip: this.t('catalog.charts.statusFilterCautions.upgradeable')
105
105
  }
106
106
  }
107
107
  }
@@ -125,9 +125,10 @@ export default {
125
125
  repoOptions() {
126
126
  let out = this.$store.getters['catalog/repos'].map((r) => {
127
127
  return {
128
- value: r._key,
129
- label: r.nameDisplay,
130
- weight: ( r.isRancher ? 1 : ( r.isPartner ? 2 : 3 ) ),
128
+ value: r._key,
129
+ label: r.nameDisplay,
130
+ labelTooltip: r.nameDisplay,
131
+ weight: ( r.isRancher ? 1 : ( r.isPartner ? 2 : 3 ) ),
131
132
  };
132
133
  });
133
134
 
@@ -117,7 +117,7 @@ describe('page: cluster tools', () => {
117
117
  });
118
118
  expect(actions[2]).toStrictEqual({
119
119
  label: 'catalog.tools.action.downgrade',
120
- icon: 'icon-history',
120
+ icon: 'icon-downgrade-alt',
121
121
  action: 'downgrade'
122
122
  });
123
123
  expect(actions[3]).toStrictEqual({ divider: true });
@@ -158,7 +158,7 @@ export default {
158
158
  if (currentIndex !== -1 && currentIndex < versions.length - 1) {
159
159
  actions.push({
160
160
  label: this.t('catalog.tools.action.downgrade'),
161
- icon: 'icon-history',
161
+ icon: 'icon-downgrade-alt',
162
162
  action: 'downgrade',
163
163
  });
164
164
  }
package/plugins/axios.js CHANGED
@@ -2,13 +2,14 @@ import https from 'https';
2
2
  import { CSRF } from '@shell/config/cookies';
3
3
 
4
4
  export default function({
5
- $axios, $cookies, isDev, req
5
+ $axios, store, isDev, req
6
6
  }) {
7
7
  $axios.defaults.headers.common['Accept'] = 'application/json';
8
8
  $axios.defaults.withCredentials = true;
9
9
 
10
10
  $axios.onRequest((config) => {
11
- const csrf = $cookies.get(CSRF, { parseJSON: false });
11
+ const options = { parseJSON: false };
12
+ const csrf = store.getters['cookies/get']({ key: CSRF, options });
12
13
 
13
14
  if ( csrf ) {
14
15
  config.headers['x-api-csrf'] = csrf;
@@ -1,4 +1,7 @@
1
1
  import { NORMAN_NAME } from '@shell/config/labels-annotations';
2
+ import { getVersionData } from '@shell/config/version';
3
+ import { parseRancherVersion } from '@shell/config/uiplugins';
4
+ import semver from 'semver';
2
5
  import {
3
6
  _CLONE,
4
7
  _CONFIG,
@@ -929,12 +932,20 @@ export default class Resource {
929
932
  const currentRoute = this.currentRouter().currentRoute.value;
930
933
  const extensionMenuActions = getApplicableExtensionEnhancements(this.$rootState, ExtensionPoint.ACTION, ActionLocation.TABLE, currentRoute, this);
931
934
 
935
+ const currRancherVersionData = getVersionData();
936
+ const parsedRancherVersion = parseRancherVersion(currRancherVersionData.Version);
937
+
938
+ // "showConfiguration" table action is only compatible with Rancher 2.13 and onwards
939
+ // defence against extension issue https://github.com/rancher/dashboard/issues/15564
940
+ // where mostly likely extension CRD model is extending from resource-class
941
+ const isResourceDetailDrawerCompatibleWithRancherSystem = semver.satisfies(parsedRancherVersion, '>= 2.13.0');
942
+
932
943
  const all = [
933
944
  {
934
945
  action: 'showConfiguration',
935
946
  label: this.t('action.showConfiguration'),
936
947
  icon: 'icon icon-document',
937
- enabled: this.disableResourceDetailDrawer !== true && (this.canCustomEdit || this.canYaml), // If the resource can't show an edit or a yaml we don't want to show the configuration drawer
948
+ enabled: isResourceDetailDrawerCompatibleWithRancherSystem && this.disableResourceDetailDrawer !== true && (this.canCustomEdit || this.canYaml), // If the resource can't show an edit or a yaml we don't want to show the configuration drawer
938
949
  },
939
950
  { divider: true },
940
951
  {
@@ -1,13 +1,17 @@
1
1
  import { REDIRECTED } from '@shell/config/cookies';
2
2
 
3
- export default function({ $cookies }) {
3
+ export default function({ store }) {
4
4
  // This tells Ember not to redirect back to us once you've already been to dashboard once.
5
5
  // TODO: Remove this once the ember portion of the app is no longer needed
6
- if ( !$cookies.get(REDIRECTED) ) {
7
- $cookies.set(REDIRECTED, 'true', {
6
+ if ( !store.getters['cookies/get']({ key: REDIRECTED })) {
7
+ const options = {
8
8
  path: '/',
9
9
  sameSite: true,
10
10
  secure: true,
11
+ };
12
+
13
+ store.commit('cookies/set', {
14
+ key: REDIRECTED, value: 'true', options
11
15
  });
12
16
  }
13
17
  }
@@ -15,9 +15,7 @@ import {
15
15
  HPA,
16
16
  SECRET
17
17
  } from '@shell/config/types';
18
- import {
19
- CAPI as CAPI_LAB_AND_ANO, CATTLE_PUBLIC_ENDPOINTS, STORAGE, UI_PROJECT_SECRET, UI_PROJECT_SECRET_COPY
20
- } from '@shell/config/labels-annotations';
18
+ import { CAPI as CAPI_LAB_AND_ANO, CATTLE_PUBLIC_ENDPOINTS, STORAGE, UI_PROJECT_SECRET_COPY } from '@shell/config/labels-annotations';
21
19
  import { Schema } from '@shell/plugins/steve/schema';
22
20
  import { PaginationSettingsStore } from '@shell/types/resources/settings';
23
21
  import paginationUtils from '@shell/utils/pagination-utils';
@@ -158,6 +156,7 @@ class StevePaginationUtils extends NamespaceProjectFilters {
158
156
  { field: 'id' },
159
157
  { field: 'metadata.state.name' },
160
158
  { field: 'metadata.creationTimestamp' },
159
+ { field: 'metadata.labels', startsWith: true },
161
160
  ],
162
161
  [NODE]: [
163
162
  { field: 'status.nodeInfo.kubeletVersion' },
@@ -180,18 +179,12 @@ class StevePaginationUtils extends NamespaceProjectFilters {
180
179
  { field: 'spec.internal' },
181
180
  { field: 'spec.displayName' },
182
181
  { field: `status.provider` },
183
- { field: `metadata.labels["${ CAPI_LAB_AND_ANO.PROVIDER }]` },
184
182
  { field: `status.connected` },
185
183
  ],
186
- [CONFIG_MAP]: [
187
- { field: 'metadata.labels[harvesterhci.io/cloud-init-template]' }
188
- ],
189
184
  [SECRET]: [
190
- { field: `metadata.labels[${ UI_PROJECT_SECRET }]` },
191
185
  { field: `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]` },
192
186
  ],
193
187
  [NAMESPACE]: [
194
- { field: 'metadata.labels[field.cattle.io/projectId]' }
195
188
  ],
196
189
  [CAPI.MACHINE]: [
197
190
  { field: 'spec.clusterName' }
@@ -214,7 +207,6 @@ class StevePaginationUtils extends NamespaceProjectFilters {
214
207
  { field: 'status.releaseName' },
215
208
  ],
216
209
  [CAPI.RANCHER_CLUSTER]: [
217
- { field: `metadata.labels[${ CAPI_LAB_AND_ANO.PROVIDER }]` },
218
210
  { field: `status.provider` },
219
211
  { field: 'status.clusterName' },
220
212
  { field: `metadata.annotations[${ CAPI_LAB_AND_ANO.HUMAN_NAME }]` }
@@ -224,14 +216,14 @@ class StevePaginationUtils extends NamespaceProjectFilters {
224
216
  { field: 'spec.clusterIP' },
225
217
  ],
226
218
  [INGRESS]: [
227
- { field: 'spec.rules.host' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
219
+ { field: 'spec.rules.host' },
228
220
  { field: 'spec.ingressClassName' },
229
221
  ],
230
222
  [HPA]: [
231
- { field: 'spec.scaleTargetRef.name' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
232
- { field: 'spec.minReplicas' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
233
- { field: 'spec.maxReplicas' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
234
- { field: 'spec.currentReplicas' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
223
+ { field: 'spec.scaleTargetRef.name' },
224
+ { field: 'spec.minReplicas' },
225
+ { field: 'spec.maxReplicas' },
226
+ { field: 'spec.currentReplicas' },
235
227
  ],
236
228
  [PVC]: [
237
229
  { field: 'spec.volumeName' },
@@ -249,29 +241,29 @@ class StevePaginationUtils extends NamespaceProjectFilters {
249
241
  ],
250
242
  [WORKLOAD_TYPES.CRON_JOB]: [
251
243
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
252
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
244
+ { field: 'spec.template.spec.containers.image' },
253
245
  ],
254
246
  [WORKLOAD_TYPES.DAEMON_SET]: [
255
247
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
256
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
248
+ { field: 'spec.template.spec.containers.image' },
257
249
  ],
258
250
  [WORKLOAD_TYPES.DEPLOYMENT]: [
259
251
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
260
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
252
+ { field: 'spec.template.spec.containers.image' },
261
253
  ],
262
254
  [WORKLOAD_TYPES.JOB]: [
263
255
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
264
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
256
+ { field: 'spec.template.spec.containers.image' },
265
257
  ],
266
258
  [WORKLOAD_TYPES.STATEFUL_SET]: [
267
259
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
268
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
260
+ { field: 'spec.template.spec.containers.image' },
269
261
  ],
270
262
  [WORKLOAD_TYPES.REPLICA_SET]: [
271
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
263
+ { field: 'spec.template.spec.containers.image' },
272
264
  ],
273
265
  [WORKLOAD_TYPES.REPLICATION_CONTROLLER]: [
274
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
266
+ { field: 'spec.template.spec.containers.image' },
275
267
  ],
276
268
  }
277
269
 
@@ -369,13 +369,15 @@ const sharedActions = {
369
369
  if (!this.$workers[getters.storeName]) {
370
370
  await createWorker(this, ctx);
371
371
  }
372
+ const options = { parseJSON: false };
373
+ const csrf = rootGetters['cookies/get']({ key: CSRF, options });
372
374
 
373
375
  // if the worker is in advanced mode then it'll contain it's own socket which it calls a 'watcher'
374
376
  this.$workers[getters.storeName].postMessage({
375
377
  createWatcher: {
376
378
  metadata,
377
- url: `${ state.config.baseUrl }/subscribe`,
378
- csrf: this.$cookies.get(CSRF, { parseJSON: false }),
379
+ url: `${ state.config.baseUrl }/subscribe`,
380
+ csrf,
379
381
  maxTries
380
382
  }
381
383
  });