@rancher/shell 2.0.2-rc.1 → 2.0.2

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 (37) hide show
  1. package/assets/translations/en-us.yaml +44 -30
  2. package/components/PromptRemove.vue +8 -3
  3. package/components/ResourceDetail/Masthead.vue +1 -0
  4. package/components/fleet/FleetClusters.vue +0 -3
  5. package/components/formatter/CloudCredExpired.vue +69 -0
  6. package/components/formatter/Date.vue +1 -1
  7. package/components/nav/Header.vue +9 -5
  8. package/components/nav/TopLevelMenu.vue +115 -51
  9. package/components/nav/__tests__/TopLevelMenu.test.ts +53 -27
  10. package/config/labels-annotations.js +2 -0
  11. package/detail/catalog.cattle.io.app.vue +17 -4
  12. package/detail/fleet.cattle.io.cluster.vue +11 -9
  13. package/detail/fleet.cattle.io.gitrepo.vue +1 -1
  14. package/edit/provisioning.cattle.io.cluster/rke2.vue +13 -0
  15. package/list/provisioning.cattle.io.cluster.vue +56 -5
  16. package/mixins/chart.js +6 -2
  17. package/models/catalog.cattle.io.app.js +108 -21
  18. package/models/cloudcredential.js +159 -2
  19. package/models/fleet.cattle.io.gitrepo.js +4 -13
  20. package/models/management.cattle.io.cluster.js +13 -2
  21. package/models/provisioning.cattle.io.cluster.js +37 -3
  22. package/package.json +1 -1
  23. package/pages/c/_cluster/apps/charts/install.vue +2 -1
  24. package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
  25. package/pages/c/_cluster/explorer/index.vue +1 -2
  26. package/pages/c/_cluster/fleet/index.vue +11 -5
  27. package/pages/c/_cluster/manager/cloudCredential/index.vue +68 -4
  28. package/pages/c/_cluster/uiplugins/index.vue +4 -2
  29. package/pages/home.vue +1 -0
  30. package/scripts/extension/bundle +1 -1
  31. package/scripts/publish-shell.sh +3 -4
  32. package/scripts/typegen.sh +26 -23
  33. package/types/shell/index.d.ts +4595 -0
  34. package/utils/cluster.js +1 -1
  35. package/utils/string.js +9 -0
  36. package/utils/v-sphere.ts +251 -0
  37. package/shell/types/shell/index.d.ts +0 -2
@@ -5,7 +5,7 @@ import { mount, Wrapper } from '@vue/test-utils';
5
5
  // DISCLAIMER: This should not be added here, although we have several store requests which are irrelevant
6
6
  const defaultStore = {
7
7
  'management/byId': jest.fn(),
8
- 'management/schemaFor': jest.fn(),
8
+ 'management/schemaFor': () => ({}),
9
9
  'i18n/t': jest.fn(),
10
10
  'features/get': jest.fn(),
11
11
  'prefs/theme': jest.fn(),
@@ -20,7 +20,11 @@ describe('topLevelMenu', () => {
20
20
  mocks: {
21
21
  $store: {
22
22
  getters: {
23
- 'management/all': () => [{ name: 'whatever' }],
23
+ 'management/all': () => [{
24
+ name: 'whatever',
25
+ id: 'an-id1',
26
+ mgmt: { id: 'an-id1' },
27
+ }],
24
28
  ...defaultStore
25
29
  },
26
30
  },
@@ -48,21 +52,21 @@ describe('topLevelMenu', () => {
48
52
  'management/all': () => [
49
53
  {
50
54
  name: 'x32-cwf5-name',
51
- id: 'x32-cwf5-id',
55
+ id: 'an-id1',
52
56
  mgmt: { id: 'an-id1' },
53
57
  nameDisplay: 'c-cluster',
54
58
  isReady: true
55
59
  },
56
60
  {
57
61
  name: 'x33-cwf5-name',
58
- id: 'x33-cwf5-id',
62
+ id: 'an-id2',
59
63
  mgmt: { id: 'an-id2' },
60
64
  nameDisplay: 'a-cluster',
61
65
  isReady: true
62
66
  },
63
67
  {
64
68
  name: 'x34-cwf5-name',
65
- id: 'x34-cwf5-id',
69
+ id: 'an-id3',
66
70
  mgmt: { id: 'an-id3' },
67
71
  nameDisplay: 'b-cluster',
68
72
  isReady: true
@@ -70,7 +74,7 @@ describe('topLevelMenu', () => {
70
74
  {
71
75
  name: 'local-name',
72
76
  id: 'local',
73
- mgmt: { id: 'an-id4' },
77
+ mgmt: { id: 'local' },
74
78
  nameDisplay: 'local',
75
79
  isReady: true
76
80
  },
@@ -103,21 +107,21 @@ describe('topLevelMenu', () => {
103
107
  'management/all': () => [
104
108
  {
105
109
  name: 'x32-cwf5-name',
106
- id: 'x32-cwf5-id',
110
+ id: 'an-id1',
107
111
  mgmt: { id: 'an-id1' },
108
112
  nameDisplay: 'c-cluster',
109
113
  isReady: true
110
114
  },
111
115
  {
112
116
  name: 'x33-cwf5-name',
113
- id: 'x33-cwf5-id',
117
+ id: 'an-id2',
114
118
  mgmt: { id: 'an-id2' },
115
119
  nameDisplay: 'a-cluster',
116
120
  isReady: false
117
121
  },
118
122
  {
119
123
  name: 'x34-cwf5-name',
120
- id: 'x34-cwf5-id',
124
+ id: 'an-id3',
121
125
  mgmt: { id: 'an-id3' },
122
126
  nameDisplay: 'b-cluster',
123
127
  isReady: true
@@ -125,7 +129,7 @@ describe('topLevelMenu', () => {
125
129
  {
126
130
  name: 'local-name',
127
131
  id: 'local',
128
- mgmt: { id: 'an-id4' },
132
+ mgmt: { id: 'local' },
129
133
  nameDisplay: 'local',
130
134
  isReady: true
131
135
  },
@@ -158,7 +162,7 @@ describe('topLevelMenu', () => {
158
162
  'management/all': () => [
159
163
  {
160
164
  name: 'x32-cwf5-name',
161
- id: 'x32-cwf5-id',
165
+ id: 'an-id1',
162
166
  mgmt: { id: 'an-id1' },
163
167
  nameDisplay: 'c-cluster',
164
168
  isReady: true,
@@ -166,7 +170,7 @@ describe('topLevelMenu', () => {
166
170
  },
167
171
  {
168
172
  name: 'x33-cwf5-name',
169
- id: 'x33-cwf5-id',
173
+ id: 'an-id2',
170
174
  mgmt: { id: 'an-id2' },
171
175
  nameDisplay: 'a-cluster',
172
176
  isReady: true,
@@ -174,7 +178,7 @@ describe('topLevelMenu', () => {
174
178
  },
175
179
  {
176
180
  name: 'x34-cwf5-name',
177
- id: 'x34-cwf5-id',
181
+ id: 'an-id3',
178
182
  mgmt: { id: 'an-id3' },
179
183
  nameDisplay: 'b-cluster',
180
184
  isReady: true,
@@ -183,7 +187,7 @@ describe('topLevelMenu', () => {
183
187
  {
184
188
  name: 'local-name',
185
189
  id: 'local',
186
- mgmt: { id: 'an-id4' },
190
+ mgmt: { id: 'local' },
187
191
  nameDisplay: 'local',
188
192
  isReady: true,
189
193
  pinned: true
@@ -217,7 +221,7 @@ describe('topLevelMenu', () => {
217
221
  'management/all': () => [
218
222
  {
219
223
  name: 'x32-cwf5-name',
220
- id: 'x32-cwf5-id',
224
+ id: 'an-id1',
221
225
  mgmt: { id: 'an-id1' },
222
226
  nameDisplay: 'c-cluster',
223
227
  isReady: true,
@@ -225,7 +229,7 @@ describe('topLevelMenu', () => {
225
229
  },
226
230
  {
227
231
  name: 'x33-cwf5-name',
228
- id: 'x33-cwf5-id',
232
+ id: 'an-id2',
229
233
  mgmt: { id: 'an-id2' },
230
234
  nameDisplay: 'a-cluster',
231
235
  isReady: true,
@@ -233,7 +237,7 @@ describe('topLevelMenu', () => {
233
237
  },
234
238
  {
235
239
  name: 'x34-cwf5-name',
236
- id: 'x34-cwf5-id',
240
+ id: 'an-id3',
237
241
  mgmt: { id: 'an-id3' },
238
242
  nameDisplay: 'b-cluster',
239
243
  isReady: false,
@@ -242,7 +246,7 @@ describe('topLevelMenu', () => {
242
246
  {
243
247
  name: 'local-name',
244
248
  id: 'local',
245
- mgmt: { id: 'an-id4' },
249
+ mgmt: { id: 'local' },
246
250
  nameDisplay: 'local',
247
251
  isReady: true,
248
252
  pinned: true
@@ -333,7 +337,7 @@ describe('topLevelMenu', () => {
333
337
  it('should show description if it is available on the mgmt cluster (relevant for RKE1/ember world)', async() => {
334
338
  const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
335
339
  data: () => {
336
- return { hasProvCluster: false, showPinClusters: true };
340
+ return { hasProvCluster: true, showPinClusters: true };
337
341
  },
338
342
  mocks: {
339
343
  $store: {
@@ -347,6 +351,7 @@ describe('topLevelMenu', () => {
347
351
  {
348
352
  name: 'whatever',
349
353
  id: 'an-id1',
354
+ mgmt: { id: 'an-id1' },
350
355
  description: 'some-description1',
351
356
  nameDisplay: 'some-label',
352
357
  isReady: true,
@@ -356,6 +361,7 @@ describe('topLevelMenu', () => {
356
361
  {
357
362
  name: 'whatever',
358
363
  id: 'an-id2',
364
+ mgmt: { id: 'an-id2' },
359
365
  description: 'some-description2',
360
366
  nameDisplay: 'some-label',
361
367
  pinned: true
@@ -364,6 +370,7 @@ describe('topLevelMenu', () => {
364
370
  {
365
371
  name: 'whatever',
366
372
  id: 'an-id3',
373
+ mgmt: { id: 'an-id3' },
367
374
  description: 'some-description3',
368
375
  nameDisplay: 'some-label',
369
376
  isReady: true
@@ -372,6 +379,7 @@ describe('topLevelMenu', () => {
372
379
  {
373
380
  name: 'whatever',
374
381
  id: 'an-id4',
382
+ mgmt: { id: 'an-id4' },
375
383
  description: 'some-description4',
376
384
  nameDisplay: 'some-label'
377
385
  },
@@ -430,11 +438,15 @@ describe('topLevelMenu', () => {
430
438
  describe('should displays a no results message if have clusters but', () => {
431
439
  it('given no matching clusters', () => {
432
440
  const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
433
- data: () => ({ clusterFilter: 'whatever' }),
441
+ data: () => ({ hasProvCluster: true, clusterFilter: 'whatever' }),
434
442
  mocks: {
435
443
  $store: {
436
444
  getters: {
437
- 'management/all': () => [{ nameDisplay: 'something else' }],
445
+ 'management/all': () => [{
446
+ id: 'an-id1',
447
+ mgmt: { id: 'an-id1' },
448
+ nameDisplay: 'something else'
449
+ }],
438
450
  ...defaultStore
439
451
  },
440
452
  },
@@ -449,11 +461,16 @@ describe('topLevelMenu', () => {
449
461
 
450
462
  it('given no matched pinned clusters', () => {
451
463
  const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
452
- data: () => ({ clusterFilter: 'whatever' }),
464
+ data: () => ({ hasProvCluster: true, clusterFilter: 'whatever' }),
453
465
  mocks: {
454
466
  $store: {
455
467
  getters: {
456
- 'management/all': () => [{ nameDisplay: 'something else', pinned: true }],
468
+ 'management/all': () => [{
469
+ id: 'an-id1',
470
+ mgmt: { id: 'an-id1' },
471
+ nameDisplay: 'something else',
472
+ pinned: true
473
+ }],
457
474
  ...defaultStore
458
475
  },
459
476
  },
@@ -471,11 +488,15 @@ describe('topLevelMenu', () => {
471
488
  it('given matching clusters', () => {
472
489
  const search = 'you found me';
473
490
  const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
474
- data: () => ({ clusterFilter: search }),
491
+ data: () => ({ hasProvCluster: true, clusterFilter: search }),
475
492
  mocks: {
476
493
  $store: {
477
494
  getters: {
478
- 'management/all': () => [{ nameDisplay: search }],
495
+ 'management/all': () => [{
496
+ id: 'an-id1',
497
+ mgmt: { id: 'an-id1' },
498
+ nameDisplay: search
499
+ }],
479
500
  ...defaultStore
480
501
  },
481
502
  },
@@ -492,11 +513,16 @@ describe('topLevelMenu', () => {
492
513
  it('given clusters with status pinned', () => {
493
514
  const search = 'you found me';
494
515
  const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
495
- data: () => ({ clusterFilter: search }),
516
+ data: () => ({ hasProvCluster: true, clusterFilter: search }),
496
517
  mocks: {
497
518
  $store: {
498
519
  getters: {
499
- 'management/all': () => [{ nameDisplay: search, pinned: true }],
520
+ 'management/all': () => [{
521
+ nameDisplay: search,
522
+ pinned: true,
523
+ id: 'an-id1',
524
+ mgmt: { id: 'an-id1' },
525
+ }],
500
526
  ...defaultStore
501
527
  },
502
528
  },
@@ -172,3 +172,5 @@ export const SYSTEM_LABELS = [
172
172
  'node.kubernetes.io',
173
173
  'egress.rke2.io'
174
174
  ];
175
+
176
+ export const CLOUD_CREDENTIALS = { EXPIRATION: 'rancher.io/expiration-timestamp' };
@@ -9,7 +9,8 @@ import RelatedResources from '@shell/components/RelatedResources';
9
9
  import jsyaml from 'js-yaml';
10
10
  import merge from 'lodash/merge';
11
11
  import { CATALOG } from '@shell/config/types';
12
- import { sortBy } from '~shell/utils/sort';
12
+ import { sortBy } from '@shell/utils/sort';
13
+ import { allHash } from '@shell/utils/promise';
13
14
 
14
15
  export default {
15
16
  name: 'DetailRelease',
@@ -30,9 +31,15 @@ export default {
30
31
  },
31
32
 
32
33
  async fetch() {
33
- await this.$store.dispatch('catalog/load');
34
+ const promises = {
35
+ catalog: this.$store.dispatch('catalog/load'),
36
+ allOperations: this.$store.dispatch('cluster/findAll', { type: CATALOG.OPERATION }),
37
+ secrets: this.value.fetchValues(true),
38
+ };
34
39
 
35
- this.allOperations = await this.$store.dispatch('cluster/findAll', { type: CATALOG.OPERATION });
40
+ const res = await allHash(promises);
41
+
42
+ this.allOperations = res.allOperations;
36
43
  },
37
44
 
38
45
  computed: {
@@ -45,7 +52,7 @@ export default {
45
52
  },
46
53
 
47
54
  valuesYaml() {
48
- const combined = merge(merge({}, this.value?.spec?.chart?.values || {}), this.value?.spec?.values || {});
55
+ const combined = merge(merge({}, this.value?.chartValues || {}), this.value?.values || {});
49
56
 
50
57
  return jsyaml.dump(combined);
51
58
  },
@@ -95,6 +102,12 @@ export default {
95
102
  }
96
103
  },
97
104
  },
105
+
106
+ watch: {
107
+ 'value.secretId'(neu, old) {
108
+ this.value.fetchValues(true);
109
+ }
110
+ },
98
111
  };
99
112
  </script>
100
113
 
@@ -6,6 +6,7 @@ import ResourceTabs from '@shell/components/form/ResourceTabs';
6
6
  import Tab from '@shell/components/Tabbed/Tab';
7
7
  import { MANAGEMENT, FLEET } from '@shell/config/types';
8
8
  import { FLEET as FLEET_LABELS } from '@shell/config/labels-annotations';
9
+ import { allHash } from 'utils/promise';
9
10
 
10
11
  export default {
11
12
  name: 'FleetDetailCluster',
@@ -27,17 +28,18 @@ export default {
27
28
 
28
29
  async fetch() {
29
30
  const clusterId = this.value?.metadata?.labels[FLEET_LABELS.CLUSTER_NAME];
30
-
31
- this.rancherCluster = await this.$store.dispatch('management/find', {
32
- type: MANAGEMENT.CLUSTER,
33
- id: clusterId
31
+ const hash = await allHash({
32
+ rancherCluster: this.$store.dispatch('management/find', {
33
+ type: MANAGEMENT.CLUSTER,
34
+ id: clusterId
35
+ }),
36
+ repos: this.$store.dispatch('management/findAll', { type: FLEET.GIT_REPO }),
37
+ workspaces: this.$store.dispatch('management/findAll', { type: FLEET.WORKSPACE }),
38
+ bundleDeployments: this.$store.dispatch('management/findAll', { type: FLEET.BUNDLE_DEPLOYMENT })
34
39
  });
35
40
 
36
- this.allRepos = await this.$store.dispatch('management/findAll', { type: FLEET.GIT_REPO });
37
-
38
- await this.$store.dispatch('management/findAll', { type: FLEET.WORKSPACE });
39
-
40
- await this.$store.dispatch('management/findAll', { type: FLEET.BUNDLE_DEPLOYMENT });
41
+ this.rancherCluster = hash.rancherCluster;
42
+ this.allRepos = hash.repos;
41
43
  },
42
44
 
43
45
  data() {
@@ -40,7 +40,7 @@ export default {
40
40
  },
41
41
  computed: {
42
42
  gitRepoHasClusters() {
43
- return this.value?.clusterResourceStatus?.length;
43
+ return this.value.status.desiredReadyClusters;
44
44
  },
45
45
  clusterSchema() {
46
46
  return this.$store.getters['management/schemaFor'](FLEET.CLUSTER);
@@ -64,6 +64,7 @@ import AddOnConfig from '@shell/edit/provisioning.cattle.io.cluster/tabs/AddOnCo
64
64
  import Advanced from '@shell/edit/provisioning.cattle.io.cluster/tabs/Advanced';
65
65
  import ClusterAppearance from '@shell/components/form/ClusterAppearance';
66
66
  import AddOnAdditionalManifest from '@shell/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest';
67
+ import VsphereUtils from '@shell/utils/v-sphere';
67
68
 
68
69
  const HARVESTER = 'harvester';
69
70
  const HARVESTER_CLOUD_PROVIDER = 'harvester-cloud-provider';
@@ -892,6 +893,8 @@ export default {
892
893
  created() {
893
894
  this.registerBeforeHook(this.saveMachinePools, 'save-machine-pools', 1);
894
895
  this.registerBeforeHook(this.setRegistryConfig, 'set-registry-config');
896
+ this.registerBeforeHook(this.handleVsphereCpiSecret, 'sync-vsphere-cpi');
897
+ this.registerBeforeHook(this.handleVsphereCsiSecret, 'sync-vsphere-csi');
895
898
  this.registerAfterHook(this.cleanupMachinePools, 'cleanup-machine-pools');
896
899
  this.registerAfterHook(this.saveRoleBindings, 'save-role-bindings');
897
900
 
@@ -904,6 +907,14 @@ export default {
904
907
  methods: {
905
908
  set,
906
909
 
910
+ async handleVsphereCpiSecret() {
911
+ return VsphereUtils.handleVsphereCpiSecret(this);
912
+ },
913
+
914
+ async handleVsphereCsiSecret() {
915
+ return VsphereUtils.handleVsphereCsiSecret(this);
916
+ },
917
+
907
918
  /**
908
919
  * Initialize all the cluster specs
909
920
  */
@@ -2420,8 +2431,10 @@ export default {
2420
2431
  name="additionalmanifest"
2421
2432
  label-key="cluster.tabs.addOnAdditionalManifest"
2422
2433
  :showHeader="false"
2434
+ @active="refreshComponentWithYamls('additionalmanifest')"
2423
2435
  >
2424
2436
  <AddOnAdditionalManifest
2437
+ ref="additionalmanifest"
2425
2438
  :value="value"
2426
2439
  :mode="mode"
2427
2440
  @additional-manifest-changed="updateAdditionalManifest"
@@ -10,10 +10,11 @@ import { mapFeature, HARVESTER as HARVESTER_FEATURE } from '@shell/store/feature
10
10
  import { NAME as EXPLORER } from '@shell/config/product/explorer';
11
11
  import ResourceFetch from '@shell/mixins/resource-fetch';
12
12
  import { BadgeState } from '@components/BadgeState';
13
+ import CloudCredExpired from '@shell/components/formatter/CloudCredExpired';
13
14
 
14
15
  export default {
15
16
  components: {
16
- Banner, ResourceTable, Masthead, BadgeState
17
+ Banner, ResourceTable, Masthead, BadgeState, CloudCredExpired
17
18
  },
18
19
  mixins: [ResourceFetch],
19
20
  props: {
@@ -41,6 +42,8 @@ export default {
41
42
  mgmtClusters: this.$fetchType(MANAGEMENT.CLUSTER),
42
43
  };
43
44
 
45
+ this.$store.dispatch('rancher/findAll', { type: NORMAN.CLOUD_CREDENTIAL });
46
+
44
47
  if ( this.$store.getters['management/canList'](SNAPSHOT) ) {
45
48
  hash.etcdSnapshots = this.$fetchType(SNAPSHOT);
46
49
  }
@@ -141,6 +144,29 @@ export default {
141
144
  // This will be used when there's clusters from extension based provisioners
142
145
  // We should re-visit this for scaling reasons
143
146
  return this.filteredRows.some((c) => c.metadata.namespace !== 'fleet-local' && c.metadata.namespace !== 'fleet-default');
147
+ },
148
+
149
+ tokenExpiredData() {
150
+ const counts = this.rows.reduce((res, provCluster) => {
151
+ const expireData = provCluster.cloudCredential?.expireData;
152
+
153
+ if (expireData?.expiring) {
154
+ res.expiring++;
155
+ }
156
+ if (expireData?.expired) {
157
+ res.expired++;
158
+ }
159
+
160
+ return res;
161
+ }, {
162
+ expiring: 0,
163
+ expired: 0
164
+ });
165
+
166
+ return {
167
+ expiring: counts.expiring ? this.t('cluster.cloudCredentials.banners.expiring', { count: counts.expiring }) : '',
168
+ expired: counts.expired ? this.t('cluster.cloudCredentials.banners.expired', { count: counts.expired }) : '',
169
+ };
144
170
  }
145
171
  },
146
172
 
@@ -186,6 +212,17 @@ export default {
186
212
  </template>
187
213
  </Masthead>
188
214
 
215
+ <Banner
216
+ v-if="tokenExpiredData.expiring"
217
+ color="warning"
218
+ :label="tokenExpiredData.expiring"
219
+ />
220
+ <Banner
221
+ v-if="tokenExpiredData.expired"
222
+ color="error"
223
+ :label="tokenExpiredData.expired"
224
+ />
225
+
189
226
  <ResourceTable
190
227
  :schema="schema"
191
228
  :rows="filteredRows"
@@ -194,6 +231,7 @@ export default {
194
231
  :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
195
232
  :data-testid="'cluster-list'"
196
233
  :force-update-live-and-delayed="forceUpdateLiveAndDelayed"
234
+ :sub-rows="true"
197
235
  >
198
236
  <!-- Why are state column and subrow overwritten here? -->
199
237
  <!-- for rke1 clusters, where they try to use the mgmt cluster stateObj instead of prov cluster stateObj, -->
@@ -207,19 +245,32 @@ export default {
207
245
  </template>
208
246
  <template #sub-row="{fullColspan, row, keyField, componentTestid, i, onRowMouseEnter, onRowMouseLeave}">
209
247
  <tr
210
- v-if="row.stateDescription"
211
248
  :key="row[keyField] + '-description'"
212
249
  :data-testid="componentTestid + '-' + i + '-row-description'"
213
250
  class="state-description sub-row"
214
251
  @mouseenter="onRowMouseEnter"
215
252
  @mouseleave="onRowMouseLeave"
216
253
  >
217
- <td>&nbsp;</td>
254
+ <td v-if="row.cloudCredentialWarning || row.stateDescription">
255
+ &nbsp;
256
+ </td>
218
257
  <td
258
+ v-if="row.cloudCredentialWarning || row.stateDescription"
219
259
  :colspan="fullColspan - 1"
220
- :class="{ 'text-error' : row.stateObj.error }"
221
260
  >
222
- {{ row.stateDescription }}
261
+ <CloudCredExpired
262
+ v-if="row.cloudCredentialWarning"
263
+ :value="row.cloudCredential.expires"
264
+ :row="row.cloudCredential"
265
+ :verbose="true"
266
+ :class="{'mb-10': row.stateDescription}"
267
+ />
268
+ <div
269
+ v-if="row.stateDescription"
270
+ :class="{ 'text-error' : row.stateObj.error }"
271
+ >
272
+ {{ row.stateDescription }}
273
+ </div>
223
274
  </td>
224
275
  </tr>
225
276
  </template>
package/mixins/chart.js CHANGED
@@ -291,6 +291,8 @@ export default {
291
291
  id: `${ this.query.appNamespace }/${ this.query.appName }`,
292
292
  });
293
293
 
294
+ await this.existing?.fetchValues(true);
295
+
294
296
  this.mode = _EDIT;
295
297
  } catch (e) {
296
298
  this.mode = _CREATE;
@@ -450,10 +452,12 @@ export default {
450
452
  }
451
453
  }
452
454
  if (existingCRDApp) {
455
+ await existingCRDApp.fetchValues(true);
456
+
453
457
  // spec.values are any non-default values the user configured
454
458
  // the installation form should show these, as well as any default values from the chart
455
- const existingValues = clone(existingCRDApp.spec?.values || {});
456
- const defaultValues = clone(existingCRDApp.spec?.chart?.values || {});
459
+ const existingValues = clone(existingCRDApp.values || {});
460
+ const defaultValues = clone(existingCRDApp.chartValues || {});
457
461
 
458
462
  crdVersionInfo.existingValues = existingValues;
459
463
  crdVersionInfo.allValues = merge(defaultValues, existingValues);