@rancher/shell 3.0.0-rc.8 → 3.0.0-rc.9

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.
@@ -40,6 +40,11 @@ export default {
40
40
  componentTestid: {
41
41
  type: String,
42
42
  default: 'color-input'
43
+ },
44
+
45
+ disabled: {
46
+ type: Boolean,
47
+ default: false,
43
48
  }
44
49
  },
45
50
 
@@ -56,6 +61,12 @@ export default {
56
61
  */
57
62
  inputValue() {
58
63
  return this.value ? this.value : this.defaultValue;
64
+ },
65
+
66
+ isDisabled() {
67
+ const disabled = this.disabled;
68
+
69
+ return this.mode !== this.editMode || disabled;
59
70
  }
60
71
  },
61
72
 
@@ -69,7 +80,7 @@ export default {
69
80
  <template>
70
81
  <div
71
82
  class="color-input"
72
- :class="{[mode]:mode, disabled: mode !== editMode}"
83
+ :class="{[mode]:mode, disabled: isDisabled}"
73
84
  :data-testid="componentTestid + '-color-input'"
74
85
  >
75
86
  <label class="text-label"><t
@@ -89,7 +100,7 @@ export default {
89
100
  <input
90
101
  ref="input"
91
102
  type="color"
92
- :disabled="mode !== editMode"
103
+ :disabled="isDisabled"
93
104
  :value="inputValue"
94
105
  @input="$emit('update:value', $event.target.value)"
95
106
  >
@@ -0,0 +1,27 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import ColorInput from '@shell/components/form/ColorInput.vue';
3
+
4
+ describe('colorInput.vue', () => {
5
+ it('disables the input when disabled prop is true', () => {
6
+ const wrapper = shallowMount(
7
+ ColorInput,
8
+ { props: { disabled: true } }
9
+ );
10
+
11
+ const colorWrapper = wrapper.find('.color-input');
12
+ const colorInput = wrapper.find('input');
13
+
14
+ expect(colorWrapper.classes()).toContain('disabled');
15
+ expect(Object.keys(colorInput.attributes())).toContain('disabled');
16
+ });
17
+
18
+ it('defaults to enabled when no disabled prop is passed', () => {
19
+ const wrapper = shallowMount(ColorInput);
20
+
21
+ const colorWrapper = wrapper.find('.color-input');
22
+ const colorInput = wrapper.find('input');
23
+
24
+ expect(colorWrapper.classes()).not.toContain('disabled');
25
+ expect(Object.keys(colorInput.attributes())).not.toContain('disabled');
26
+ });
27
+ });
@@ -18,6 +18,8 @@ export default {
18
18
 
19
19
  mixins: [createEditView],
20
20
 
21
+ inheritAttrs: false,
22
+
21
23
  props: {
22
24
  value: {
23
25
  type: Object,
@@ -48,6 +48,8 @@ export default {
48
48
 
49
49
  mixins: [CreateEditView],
50
50
 
51
+ inheritAttrs: false,
52
+
51
53
  props: {
52
54
  value: {
53
55
  type: Object,
@@ -20,6 +20,8 @@ export default {
20
20
  NameNsDescription,
21
21
  },
22
22
 
23
+ inheritAttrs: false,
24
+
23
25
  mixins: [CreateEditView],
24
26
 
25
27
  props: {
@@ -53,6 +55,7 @@ export default {
53
55
  methods: {
54
56
  async save(buttonDone) {
55
57
  try {
58
+ this.errors = [];
56
59
  await this.value.save();
57
60
 
58
61
  await this.normanCluster.save();
@@ -60,6 +63,7 @@ export default {
60
63
  this.done();
61
64
  buttonDone(true);
62
65
  } catch (e) {
66
+ this.errors.push(e);
63
67
  buttonDone(false);
64
68
  }
65
69
  },
@@ -21,6 +21,8 @@ export default {
21
21
 
22
22
  mixins: [createEditView],
23
23
 
24
+ inheritAttrs: false,
25
+
24
26
  props: {
25
27
  value: {
26
28
  type: Object,
@@ -22,6 +22,8 @@ export default {
22
22
 
23
23
  mixins: [CreateEditView],
24
24
 
25
+ inheritAttrs: false,
26
+
25
27
  props: {
26
28
  value: {
27
29
  type: Object,
@@ -15,6 +15,8 @@ export default {
15
15
 
16
16
  mixins: [CreateEditView, FormValidation],
17
17
 
18
+ inheritAttrs: false,
19
+
18
20
  data() {
19
21
  return {
20
22
  fvFormRuleSets: [
@@ -50,6 +50,8 @@ export default {
50
50
 
51
51
  mixins: [CreateEditView],
52
52
 
53
+ inheritAttrs: false,
54
+
53
55
  async fetch() {
54
56
  const hasAccessToClusterOutputs = this.$store.getters[`cluster/schemaFor`](LOGGING.CLUSTER_OUTPUT);
55
57
  const hasAccessToOutputs = this.$store.getters[`cluster/schemaFor`](LOGGING.OUTPUT);
@@ -11,7 +11,8 @@ export default {
11
11
  ProjectMemberEditor,
12
12
  },
13
13
 
14
- mixins: [CreateEditView],
14
+ mixins: [CreateEditView],
15
+ inheritAttrs: false,
15
16
  async fetch() {
16
17
  await this.$store.dispatch('management/findAll', { type: MANAGEMENT.USER });
17
18
  this.projects = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.PROJECT });
@@ -14,10 +14,13 @@ export default {
14
14
  components: {
15
15
  ChangePassword, GlobalRoleBindings, CruResource, LabeledInput, Loading
16
16
  },
17
+
17
18
  mixins: [
18
19
  CreateEditView
19
20
  ],
20
21
 
22
+ inheritAttrs: false,
23
+
21
24
  data() {
22
25
  const showGlobalRoles = !!this.$store.getters[`management/schemaFor`](MANAGEMENT.GLOBAL_ROLE);
23
26
 
@@ -30,6 +30,8 @@ export default {
30
30
 
31
31
  mixins: [CreateEditView],
32
32
 
33
+ inheritAttrs: false,
34
+
33
35
  async fetch() {
34
36
  const inStore = this.$store.getters['currentProduct'].inStore;
35
37
  const alertmanagerConfigId = this.value.id;
@@ -105,6 +105,8 @@ export default {
105
105
 
106
106
  mixins: [CreateEditView, FormValidation],
107
107
 
108
+ inheritAttrs: false,
109
+
108
110
  async fetch() {
109
111
  /**
110
112
  * example receiver value:
@@ -29,6 +29,8 @@ export default {
29
29
 
30
30
  mixins: [CreateEditView, FormValidation],
31
31
 
32
+ inheritAttrs: false,
33
+
32
34
  props: {
33
35
  value: {
34
36
  type: Object,
@@ -37,6 +37,8 @@ export default {
37
37
 
38
38
  mixins: [CreateEditView],
39
39
 
40
+ inheritAttrs: false,
41
+
40
42
  async fetch() {
41
43
  await this.$store.dispatch('cluster/findAll', { type: MONITORING.SPOOFED.ROUTE });
42
44
  },
@@ -35,6 +35,8 @@ export default {
35
35
 
36
36
  mixins: [CreateEditView],
37
37
 
38
+ inheritAttrs: false,
39
+
38
40
  async fetch() {
39
41
  const receivers = this.$store.dispatch('cluster/findAll', { type: MONITORING.SPOOFED.RECEIVER });
40
42
  const routes = this.$store.dispatch('cluster/findAll', { type: MONITORING.SPOOFED.ROUTE });
@@ -24,6 +24,8 @@ export default {
24
24
 
25
25
  mixins: [CreateEditView],
26
26
 
27
+ inheritAttrs: false,
28
+
27
29
  created() {
28
30
  if (!get(this.value, 'spec.trafficPolicy.loadBalancer')) {
29
31
  set(this.value, 'spec.trafficPolicy.loadBalancer', { simple: 'ROUND_ROBIN' });
@@ -15,6 +15,8 @@ export default {
15
15
 
16
16
  mixins: [CreateEditView, FormValidation],
17
17
 
18
+ inheritAttrs: false,
19
+
18
20
  data() {
19
21
  return {
20
22
  fvFormRuleSets: [
@@ -2,6 +2,7 @@ import { mount, shallowMount } from '@vue/test-utils';
2
2
  import { SECRET } from '@shell/config/types';
3
3
  import { _CREATE } from '@shell/config/query-params';
4
4
  import rke2 from '@shell/edit/provisioning.cattle.io.cluster/rke2.vue';
5
+ import { get } from '@shell/utils/object';
5
6
 
6
7
  /**
7
8
  * DISCLAIMER ***************************************************************************************
@@ -242,7 +243,9 @@ describe('component: rke2', () => {
242
243
 
243
244
  await wrapper.vm._doSaveOverride(jest.fn());
244
245
 
245
- expect(wrapper.vm.chartValues[`${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`]).toStrictEqual('my-k8s-distro-path/etc/config-files/cloud-provider-config');
246
+ const cloudConfigPath = get(wrapper.vm.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`);
247
+
248
+ expect(cloudConfigPath).toStrictEqual('my-k8s-distro-path/etc/config-files/cloud-provider-config');
246
249
  });
247
250
 
248
251
  // TODO: Complete test after implementing fetch https://github.com/rancher/dashboard/issues/9322
@@ -36,6 +36,8 @@ export default {
36
36
 
37
37
  mixins: [CreateEditView],
38
38
 
39
+ inheritAttrs: false,
40
+
39
41
  props: {
40
42
  mode: {
41
43
  type: String,
@@ -1480,12 +1480,12 @@ export default {
1480
1480
  this.agentConfig['cloud-provider-config'] = `secret://fleet-default:${ harvesterKubeconfigSecret?.metadata?.name }`;
1481
1481
 
1482
1482
  if (this.isCreate) {
1483
- this.chartValues[`${ HARVESTER_CLOUD_PROVIDER }.global.cattle.clusterName`] = this.value.metadata.name;
1483
+ set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.global.cattle.clusterName`, this.value.metadata.name);
1484
1484
  }
1485
1485
 
1486
1486
  const distroRoot = this.value?.spec?.rkeConfig?.dataDirectories?.k8sDistro?.length ? this.value?.spec?.rkeConfig?.dataDirectories?.k8sDistro : '/var/lib/rancher/rke2';
1487
1487
 
1488
- this.chartValues[`${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`] = `${ distroRoot }/etc/config-files/cloud-provider-config`;
1488
+ set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`, `${ distroRoot }/etc/config-files/cloud-provider-config`);
1489
1489
  }
1490
1490
  } catch (err) {
1491
1491
  this.errors.push(err);
@@ -20,9 +20,10 @@ const LINK_TARGET_BLANK = '_blank';
20
20
  const LINK_TARGET_SELF = '_self';
21
21
 
22
22
  export default {
23
- emits: ['update:value.spec.iconSrc ', 'input'],
24
- mixins: [CreateEditView, FormValidation],
25
- components: {
23
+ emits: ['update:value.spec.iconSrc ', 'input'],
24
+ mixins: [CreateEditView, FormValidation],
25
+ inheritAttrs: false,
26
+ components: {
26
27
  CruResource,
27
28
  LabeledInput,
28
29
  RadioGroup,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "3.0.0-rc.8",
3
+ "version": "3.0.0-rc.9",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -41,6 +41,7 @@
41
41
  "@rancher/icons": "2.0.29",
42
42
  "@types/is-url": "1.2.30",
43
43
  "@types/node": "16.4.3",
44
+ "@types/semver": "^7.5.8",
44
45
  "@typescript-eslint/eslint-plugin": "~5.4.0",
45
46
  "@typescript-eslint/parser": "~5.4.0",
46
47
  "@vue/cli-plugin-babel": "~5.0.0",
@@ -53,7 +54,9 @@
53
54
  "babel-eslint": "10.1.0",
54
55
  "babel-plugin-module-resolver": "4.0.0",
55
56
  "babel-preset-vue": "2.0.2",
57
+ "cache-loader": "4.1.0",
56
58
  "clipboard-polyfill": "4.0.1",
59
+ "color": "4.2.3",
57
60
  "codemirror": ">=5.64.0 <6",
58
61
  "codemirror-editor-vue3": "2.7.1",
59
62
  "cookie": "0.5.0",
@@ -89,6 +92,7 @@
89
92
  "frontmatter-markdown-loader": "3.7.0",
90
93
  "identicon.js": "2.3.3",
91
94
  "intl-messageformat": "7.8.4",
95
+ "ip": "2.0.1",
92
96
  "is-url": "1.2.4",
93
97
  "jest": "27.5.1",
94
98
  "jest-serializer-vue": "2.0.2",
@@ -105,6 +109,7 @@
105
109
  "marked": "4.0.17",
106
110
  "nodemon": "2.0.22",
107
111
  "nyc": "15.1.0",
112
+ "node-polyfill-webpack-plugin": "3.0.0",
108
113
  "papaparse": "5.3.0",
109
114
  "portal-vue": "~3.0.0",
110
115
  "sass": "1.51.0",
@@ -153,7 +158,9 @@
153
158
  "qs": "6.11.1",
154
159
  "roarr": "7.0.4",
155
160
  "semver": "7.5.4",
156
- "@vue/cli-service/html-webpack-plugin": "^5.0.0"
161
+ "@types/lodash": "4.17.5",
162
+ "@types/node": "~20.10.0",
163
+ "@vue/cli-service/html-webpack-plugin": "^5.0.0"
157
164
  },
158
165
  "nyc": {
159
166
  "extension": [
@@ -25,9 +25,12 @@ describe('page: cluster dashboard', () => {
25
25
  'cluster/inError': () => false,
26
26
  'cluster/schemaFor': jest.fn(),
27
27
  'cluster/canList': jest.fn(),
28
- 'cluster/all': jest.fn(),
29
- 'i18n/exists': jest.fn(),
30
- 'i18n/t': (label: string) => label === 'generic.provisioning' ? '—' : jest.fn()(),
28
+ 'cluster/byId': () => {
29
+ return {};
30
+ },
31
+ 'cluster/all': jest.fn(),
32
+ 'i18n/exists': jest.fn(),
33
+ 'i18n/t': (label: string) => label === 'generic.provisioning' ? '—' : jest.fn()(),
31
34
  }
32
35
  }
33
36
  },
@@ -115,12 +115,6 @@ export default {
115
115
  if (this.currentCluster.isLocal && this.$store.getters['management/schemaFor'](MANAGEMENT.NODE)) {
116
116
  this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE });
117
117
  }
118
-
119
- this.canViewAgents = this.$store.getters['cluster/canList'](WORKLOAD_TYPES.DEPLOYMENT) && this.$store.getters['cluster/canList'](WORKLOAD_TYPES.STATEFUL_SET);
120
-
121
- if (this.canViewAgents) {
122
- this.loadAgents();
123
- }
124
118
  }
125
119
  },
126
120
 
@@ -138,7 +132,6 @@ export default {
138
132
  cattleDeployment: 'loading',
139
133
  fleetDeployment: 'loading',
140
134
  fleetStatefulSet: 'loading',
141
- canViewAgents: false,
142
135
  disconnected: false,
143
136
  events: [],
144
137
  nodeMetrics: [],
@@ -172,6 +165,17 @@ export default {
172
165
  clearInterval(this.interval);
173
166
  },
174
167
 
168
+ watch: {
169
+ canViewAgents: {
170
+ handler(neu, old) {
171
+ if (neu && !old) {
172
+ this.loadAgents();
173
+ }
174
+ },
175
+ immediate: true
176
+ }
177
+ },
178
+
175
179
  computed: {
176
180
  ...mapGetters(['currentCluster']),
177
181
  ...monitoringStatus(),
@@ -184,6 +188,22 @@ export default {
184
188
  return this.$store.getters['management/all'](MANAGEMENT.CLUSTER);
185
189
  },
186
190
 
191
+ fleetAgentNamespace() {
192
+ return this.$store.getters['cluster/byId'](NAMESPACE, 'cattle-fleet-system');
193
+ },
194
+
195
+ cattleAgentNamespace() {
196
+ if (this.currentCluster.isLocal) {
197
+ return;
198
+ }
199
+
200
+ return this.$store.getters['cluster/byId'](NAMESPACE, 'cattle-system');
201
+ },
202
+
203
+ canViewAgents() {
204
+ return !!this.fleetAgentNamespace || (!this.currentCluster.isLocal && this.cattleAgentNamespace);
205
+ },
206
+
187
207
  showClusterTools() {
188
208
  return this.$store.getters['cluster/canList'](CATALOG.CLUSTER_REPO) &&
189
209
  this.$store.getters['cluster/canList'](CATALOG.APP);
@@ -268,15 +288,15 @@ export default {
268
288
  });
269
289
  });
270
290
 
271
- if (this.canViewAgents) {
272
- if (!this.currentCluster.isLocal) {
273
- services.push({
274
- name: 'cattle',
275
- status: this.cattleStatus,
276
- labelKey: 'clusterIndexPage.sections.componentStatus.cattle',
277
- });
278
- }
291
+ if (this.cattleAgentNamespace) {
292
+ services.push({
293
+ name: 'cattle',
294
+ status: this.cattleStatus,
295
+ labelKey: 'clusterIndexPage.sections.componentStatus.cattle',
296
+ });
297
+ }
279
298
 
299
+ if (this.fleetAgentNamespace) {
280
300
  services.push({
281
301
  name: 'fleet',
282
302
  status: this.fleetStatus,
@@ -485,14 +505,16 @@ export default {
485
505
 
486
506
  methods: {
487
507
  loadAgents() {
488
- if (this.currentCluster.isLocal) {
489
- this.setAgentResource('fleetDeployment', WORKLOAD_TYPES.DEPLOYMENT, 'cattle-fleet-system/fleet-controller');
490
- this.setAgentResource('fleetStatefulSet', WORKLOAD_TYPES.STATEFUL_SET, 'cattle-fleet-local-system/fleet-agent');
491
- } else {
492
- this.setAgentResource('fleetStatefulSet', WORKLOAD_TYPES.STATEFUL_SET, 'cattle-fleet-system/fleet-agent');
508
+ if (this.fleetAgentNamespace) {
509
+ if (this.currentCluster.isLocal) {
510
+ this.setAgentResource('fleetDeployment', WORKLOAD_TYPES.DEPLOYMENT, 'cattle-fleet-system/fleet-controller');
511
+ this.setAgentResource('fleetStatefulSet', WORKLOAD_TYPES.STATEFUL_SET, 'cattle-fleet-local-system/fleet-agent');
512
+ } else {
513
+ this.setAgentResource('fleetStatefulSet', WORKLOAD_TYPES.STATEFUL_SET, 'cattle-fleet-system/fleet-agent');
514
+ }
515
+ }
516
+ if (this.cattleAgentNamespace) {
493
517
  this.setAgentResource('cattleDeployment', WORKLOAD_TYPES.DEPLOYMENT, 'cattle-system/cattle-cluster-agent');
494
-
495
- // Scaling Up/Down cattle deployment causes web sockets disconnection;
496
518
  this.interval = setInterval(() => {
497
519
  this.disconnected = !!this.$store.getters['cluster/inError']({ type: NODE });
498
520
  }, 1000);