@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.3

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 (272) hide show
  1. package/apis/impl/apis.ts +6 -0
  2. package/apis/index.ts +26 -0
  3. package/apis/intf/resources-api/cluster-api.ts +18 -0
  4. package/apis/intf/resources-api/mgmt-api.ts +15 -0
  5. package/apis/intf/resources-api/resource-base.ts +107 -0
  6. package/apis/intf/resources-api/resource-constants.ts +147 -0
  7. package/apis/intf/resources-api/resources-api.ts +143 -0
  8. package/apis/intf/resources.ts +49 -0
  9. package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
  10. package/apis/intf/shell-api/proxy.ts +216 -0
  11. package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
  12. package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
  13. package/apis/intf/shell.ts +12 -6
  14. package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
  15. package/apis/resources/index.ts +22 -0
  16. package/apis/resources/resources-api-class.ts +187 -0
  17. package/apis/shell/__tests__/proxy.test.ts +369 -0
  18. package/apis/shell/index.ts +8 -1
  19. package/apis/shell/modal.ts +4 -1
  20. package/apis/shell/notifications.ts +9 -6
  21. package/apis/shell/proxy.ts +256 -0
  22. package/apis/shell/slide-in.ts +4 -1
  23. package/apis/vue-shim.d.ts +2 -1
  24. package/assets/data/aws-regions.json +4 -0
  25. package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
  26. package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
  27. package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
  28. package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
  29. package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
  30. package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
  31. package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
  32. package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
  33. package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
  34. package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
  35. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
  36. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
  37. package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
  38. package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
  39. package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
  40. package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
  41. package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
  42. package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
  43. package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
  44. package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
  45. package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
  46. package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
  47. package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
  48. package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
  49. package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
  50. package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
  51. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
  52. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
  53. package/assets/styles/base/_variables.scss +2 -0
  54. package/assets/styles/fonts/_fontstack.scss +132 -8
  55. package/assets/translations/en-us.yaml +22 -5
  56. package/chart/monitoring/index.vue +10 -1
  57. package/components/ActionDropdownShell.vue +2 -1
  58. package/components/CruResourceFooter.vue +9 -5
  59. package/components/ExplorerProjectsNamespaces.vue +1 -1
  60. package/components/InstallHelmCharts.vue +2 -2
  61. package/components/LandingPagePreference.vue +14 -5
  62. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +15 -1
  63. package/components/Resource/Detail/Metadata/index.vue +6 -0
  64. package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
  65. package/components/Resource/Detail/SpacedRow.vue +3 -1
  66. package/components/Resource/Detail/TitleBar/index.vue +10 -11
  67. package/components/ResourceList/Masthead.vue +12 -8
  68. package/components/SelectIconGrid.vue +0 -10
  69. package/components/SingleClusterInfo.vue +1 -0
  70. package/components/SortableTable/__tests__/sorting.test.ts +126 -0
  71. package/components/SortableTable/index.vue +6 -9
  72. package/components/SortableTable/selection.js +23 -5
  73. package/components/SortableTable/sorting.js +6 -3
  74. package/components/Wizard.vue +14 -13
  75. package/components/fleet/FleetBundles.vue +100 -12
  76. package/components/fleet/FleetClusterTargets/index.vue +37 -15
  77. package/components/fleet/__tests__/FleetClusterTargets.test.ts +149 -115
  78. package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
  79. package/components/form/LabeledSelect.vue +20 -3
  80. package/components/form/NameNsDescription.vue +11 -0
  81. package/components/form/Security.vue +6 -2
  82. package/components/form/WorkloadPorts.vue +2 -7
  83. package/components/form/__tests__/Security.test.ts +76 -0
  84. package/components/formatter/Autoscaler.vue +4 -4
  85. package/components/formatter/ClusterKubeVersion.vue +27 -0
  86. package/components/formatter/ClusterLink.vue +1 -7
  87. package/components/formatter/ClusterProvider.vue +6 -10
  88. package/components/formatter/FleetSummaryGraph.vue +0 -3
  89. package/components/formatter/MachineSummaryGraph.vue +1 -1
  90. package/components/formatter/PodsUsage.vue +2 -2
  91. package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
  92. package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
  93. package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
  94. package/components/nav/NamespaceFilter.vue +2 -2
  95. package/components/nav/TopLevelMenu.helper.ts +15 -3
  96. package/components/nav/TopLevelMenu.vue +16 -5
  97. package/components/nav/__tests__/TopLevelMenu.test.ts +145 -21
  98. package/components/templates/home.vue +18 -0
  99. package/components/templates/plain.vue +18 -0
  100. package/components/templates/standalone.vue +17 -0
  101. package/composables/useFormValidation.ts +93 -0
  102. package/composables/useVeeValidateField.test.ts +159 -0
  103. package/composables/useVeeValidateField.ts +67 -0
  104. package/config/pagination-table-headers.js +18 -1
  105. package/config/product/manager.js +82 -21
  106. package/config/router/routes.js +6 -0
  107. package/config/table-headers.js +20 -1
  108. package/config/types.js +2 -1
  109. package/core/__tests__/plugin-products.test.ts +904 -20
  110. package/core/plugin-products-base.ts +107 -7
  111. package/core/plugin-products.ts +4 -0
  112. package/core/plugin-types.ts +111 -1
  113. package/core/plugin.ts +15 -7
  114. package/core/productDebugger.js +9 -4
  115. package/core/types-provisioning.ts +43 -30
  116. package/core/types.ts +57 -20
  117. package/detail/__tests__/pod.test.ts +41 -0
  118. package/detail/harvesterhci.io.management.cluster.vue +6 -2
  119. package/detail/pod.vue +1 -1
  120. package/detail/provisioning.cattle.io.cluster.vue +4 -10
  121. package/edit/auth/__tests__/azuread.test.ts +217 -34
  122. package/edit/auth/azuread.vue +122 -14
  123. package/edit/auth/oidc.vue +2 -2
  124. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
  125. package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
  126. package/edit/networking.k8s.io.ingress/index.vue +75 -20
  127. package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
  128. package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
  129. package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -4
  130. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
  131. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
  132. package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
  133. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
  134. package/edit/secret/__tests__/ssh.test.ts +5 -6
  135. package/edit/secret/basic.vue +31 -0
  136. package/edit/secret/index.vue +68 -17
  137. package/edit/secret/registry.vue +38 -0
  138. package/edit/secret/ssh.vue +29 -0
  139. package/edit/secret/tls.vue +30 -0
  140. package/edit/service.vue +4 -4
  141. package/edit/workload/Upgrading.vue +3 -3
  142. package/edit/workload/__tests__/Upgrading.test.ts +6 -9
  143. package/edit/workload/mixins/workload.js +2 -1
  144. package/list/fleet.cattle.io.bundle.vue +7 -104
  145. package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
  146. package/list/provisioning.cattle.io.cluster.vue +262 -180
  147. package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
  148. package/mixins/__tests__/chart.test.ts +112 -0
  149. package/mixins/brand.js +2 -1
  150. package/mixins/chart.js +12 -8
  151. package/mixins/resource-fetch-api-pagination.js +41 -5
  152. package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
  153. package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
  154. package/models/__tests__/management.cattle.io.node.ts +6 -5
  155. package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
  156. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +32 -11
  157. package/models/base-cluster.x-k8s.io.js +26 -0
  158. package/models/cluster.js +1 -1
  159. package/models/cluster.x-k8s.io.machine.js +4 -22
  160. package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
  161. package/models/cluster.x-k8s.io.machineset.js +2 -20
  162. package/models/compliance.cattle.io.clusterscan.js +130 -2
  163. package/models/ext.cattle.io.kubeconfig.ts +4 -7
  164. package/models/fleet-application.js +3 -1
  165. package/models/management.cattle.io.cluster.js +417 -40
  166. package/models/management.cattle.io.node.js +6 -4
  167. package/models/management.cattle.io.nodepool.js +1 -1
  168. package/models/networking.k8s.io.ingress.js +12 -4
  169. package/models/provisioning.cattle.io.cluster.js +47 -330
  170. package/models/rke.cattle.io.etcdsnapshot.js +1 -2
  171. package/package.json +11 -29
  172. package/pages/__tests__/readme.test.ts +49 -0
  173. package/pages/auth/setup.vue +2 -3
  174. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
  175. package/pages/c/_cluster/apps/charts/chart.vue +60 -8
  176. package/pages/c/_cluster/apps/charts/install.vue +10 -7
  177. package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
  178. package/pages/c/_cluster/explorer/index.vue +5 -49
  179. package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
  180. package/pages/c/_cluster/istio/index.vue +21 -6
  181. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
  182. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +719 -2
  183. package/pages/c/_cluster/uiplugins/index.vue +203 -197
  184. package/pages/diagnostic.vue +13 -17
  185. package/pages/fail-whale.vue +18 -0
  186. package/pages/home.vue +77 -260
  187. package/pages/readme.vue +88 -0
  188. package/plugins/dashboard-store/__tests__/resource-class.test.ts +88 -0
  189. package/plugins/dashboard-store/actions.js +40 -18
  190. package/plugins/dashboard-store/resource-class.js +5 -2
  191. package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
  192. package/plugins/steve/steve-pagination-utils.ts +11 -3
  193. package/plugins/steve/subscribe.js +35 -5
  194. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
  195. package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
  196. package/rancher-components/RcButton/RcButton.test.ts +37 -1
  197. package/rancher-components/RcButton/RcButton.vue +38 -8
  198. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
  199. package/store/__tests__/catalog.test.ts +115 -1
  200. package/store/__tests__/type-map.test.ts +556 -1
  201. package/store/action-menu.js +8 -3
  202. package/store/auth.js +1 -1
  203. package/store/aws.js +27 -16
  204. package/store/catalog.js +27 -3
  205. package/store/digitalocean.js +20 -38
  206. package/store/index.js +2 -0
  207. package/store/linode.js +25 -40
  208. package/store/pnap.js +1 -0
  209. package/store/type-map.js +111 -29
  210. package/tsconfig.paths.json +8 -8
  211. package/types/kube/kube-api.ts +14 -1
  212. package/types/rancher/steve.api.ts +12 -12
  213. package/types/resources/settings.d.ts +2 -1
  214. package/types/shell/index.d.ts +102 -2
  215. package/types/store/dashboard-store.types.ts +108 -11
  216. package/types/store/pagination.types.ts +6 -3
  217. package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
  218. package/utils/__tests__/async.test.ts +87 -0
  219. package/utils/__tests__/aws.test.ts +140 -0
  220. package/utils/__tests__/banners.test.ts +176 -0
  221. package/utils/__tests__/chart.test.ts +64 -1
  222. package/utils/__tests__/color.test.ts +226 -0
  223. package/utils/__tests__/duration.test.ts +140 -0
  224. package/utils/__tests__/fleet.test.ts +340 -0
  225. package/utils/__tests__/ingress.test.ts +553 -0
  226. package/utils/__tests__/kube.test.ts +68 -0
  227. package/utils/__tests__/namespace-filter.test.ts +109 -0
  228. package/utils/__tests__/pagination-utils.test.ts +361 -0
  229. package/utils/__tests__/parse-externalid.test.ts +137 -0
  230. package/utils/__tests__/perf-setting.utils.test.ts +98 -0
  231. package/utils/__tests__/poller-sequential.test.ts +177 -0
  232. package/utils/__tests__/poller.test.ts +170 -0
  233. package/utils/__tests__/promise.test.ts +346 -0
  234. package/utils/__tests__/settings.test.ts +140 -0
  235. package/utils/__tests__/sort-utils.test.ts +301 -0
  236. package/utils/__tests__/string-utils.test.ts +798 -0
  237. package/utils/__tests__/string.test.ts +23 -1
  238. package/utils/__tests__/style.test.ts +154 -0
  239. package/utils/__tests__/svg-filter.test.ts +184 -0
  240. package/utils/__tests__/units.test.ts +417 -0
  241. package/utils/__tests__/versions.test.ts +128 -0
  242. package/utils/__tests__/xccdf.test.ts +391 -0
  243. package/utils/chart.js +36 -0
  244. package/utils/fleet.ts +13 -3
  245. package/utils/gatekeeper/__tests__/util.test.ts +174 -0
  246. package/utils/gc/__tests__/gc-interval.test.ts +119 -0
  247. package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
  248. package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
  249. package/utils/gc/__tests__/gc.test.ts +487 -0
  250. package/utils/ingress.ts +9 -1
  251. package/utils/pagination-utils.ts +2 -1
  252. package/utils/string.js +25 -2
  253. package/utils/uiplugins.ts +5 -5
  254. package/utils/validators/__tests__/cluster-name.test.ts +110 -0
  255. package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
  256. package/utils/validators/__tests__/index.test.ts +481 -0
  257. package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
  258. package/utils/validators/__tests__/misc-validators.test.ts +246 -0
  259. package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
  260. package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
  261. package/utils/validators/__tests__/role-template.test.ts +149 -0
  262. package/utils/validators/__tests__/service.test.ts +283 -0
  263. package/utils/validators/__tests__/setting.test.js +32 -0
  264. package/utils/validators/formRules/__tests__/index.test.ts +50 -0
  265. package/utils/validators/formRules/index.ts +5 -5
  266. package/utils/validators/machine-pool.ts +1 -1
  267. package/utils/validators/setting.js +18 -3
  268. package/utils/xccdf.ts +418 -0
  269. package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
  270. package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
  271. package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
  272. package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
@@ -1,5 +1,8 @@
1
1
  <script>
2
+ import { useStore } from 'vuex';
2
3
  import { LabeledInput } from '@components/Form/LabeledInput';
4
+ import { useFormRules } from '@shell/composables/useFormValidation';
5
+ import { useI18n } from '@shell/composables/useI18n';
3
6
 
4
7
  export default {
5
8
  components: { LabeledInput },
@@ -16,6 +19,28 @@ export default {
16
19
  }
17
20
  },
18
21
 
22
+ setup() {
23
+ const store = useStore();
24
+ const { t } = useI18n(store);
25
+ const { getRules } = useFormRules(
26
+ t,
27
+ [
28
+ {
29
+ path: 'username',
30
+ rules: ['required'],
31
+ translationKey: 'secret.basic.username',
32
+ },
33
+ {
34
+ path: 'password',
35
+ rules: ['required'],
36
+ translationKey: 'secret.basic.password',
37
+ },
38
+ ]
39
+ );
40
+
41
+ return { getRules };
42
+ },
43
+
19
44
  data() {
20
45
  const username = this.value.decodedData.username || '';
21
46
  const password = this.value.decodedData.password || '';
@@ -46,18 +71,24 @@ export default {
46
71
  <div class="col span-6">
47
72
  <LabeledInput
48
73
  v-model:value="username"
74
+ name="username"
49
75
  required
50
76
  :label="t('secret.basic.username')"
51
77
  :mode="mode"
78
+ :rules="getRules('username')"
52
79
  data-testid="secret-basic-username"
53
80
  />
54
81
  </div>
55
82
  <div class="col span-6">
56
83
  <LabeledInput
57
84
  v-model:value="password"
85
+ name="password"
86
+ required
58
87
  :label="t('secret.basic.password')"
59
88
  :mode="mode"
60
89
  type="password"
90
+ :rules="getRules('password')"
91
+ data-testid="secret-basic-password"
61
92
  />
62
93
  </div>
63
94
  </div>
@@ -7,7 +7,9 @@ import {
7
7
  } from '@shell/config/query-params';
8
8
  import { MANAGEMENT, NAMESPACE, DEFAULT_WORKSPACE, VIRTUAL_TYPES } from '@shell/config/types';
9
9
  import { CAPI, UI_PROJECT_SECRET } from '@shell/config/labels-annotations';
10
- import FormValidation from '@shell/mixins/form-validation';
10
+ import { useStore } from 'vuex';
11
+ import { useFormValidation } from '@shell/composables/useFormValidation';
12
+ import { useI18n } from '@shell/composables/useI18n';
11
13
  import CreateEditView from '@shell/mixins/create-edit-view';
12
14
  import NameNsDescription from '@shell/components/form/NameNsDescription';
13
15
  import { LabeledInput } from '@components/Form/LabeledInput';
@@ -48,7 +50,46 @@ export default {
48
50
  SelectIconGrid
49
51
  },
50
52
 
51
- mixins: [CreateEditView, FormValidation],
53
+ mixins: [CreateEditView],
54
+
55
+ setup() {
56
+ const store = useStore();
57
+ const { t } = useI18n(store);
58
+ const {
59
+ getRules, isFormValid, validateForm, veeErrors
60
+ } = useFormValidation(
61
+ t,
62
+ [
63
+ {
64
+ path: 'metadata.name',
65
+ rules: ['required'],
66
+ translationKey: 'nameNsDescription.name.label',
67
+ },
68
+ {
69
+ path: 'metadata.namespace',
70
+ rules: ['required'],
71
+ translationKey: 'nameNsDescription.namespace.label',
72
+ },
73
+ {
74
+ path: 'secretType',
75
+ rules: ['required'],
76
+ translationKey: 'secret.type',
77
+ },
78
+ {
79
+ path: 'secret._type',
80
+ rules: ['required'],
81
+ translationKey: 'secret.customType',
82
+ },
83
+ ]
84
+ );
85
+
86
+ return {
87
+ getRules,
88
+ isFormValid,
89
+ veeValidateForm: validateForm,
90
+ veeErrors,
91
+ };
92
+ },
52
93
 
53
94
  async fetch() {
54
95
  if ( this.isCloud ) {
@@ -119,16 +160,6 @@ export default {
119
160
  secretType: this.value._type,
120
161
  initialSecretType: this.value._type,
121
162
  projectName: null,
122
- fvFormRuleSets: [
123
- {
124
- path: 'metadata.name',
125
- rules: ['required'],
126
- },
127
- {
128
- path: 'metadata.namespace',
129
- rules: ['required'],
130
- },
131
- ],
132
163
  };
133
164
  },
134
165
 
@@ -261,6 +292,12 @@ export default {
261
292
  return this.$store.getters['prefs/get'](HIDE_SENSITIVE);
262
293
  },
263
294
 
295
+ dataTabHasError() {
296
+ const topLevelFields = new Set(['metadata.name', 'metadata.namespace', 'secretType', 'secret._type']);
297
+
298
+ return Object.keys(this.veeErrors).some((key) => !topLevelFields.has(key));
299
+ },
300
+
264
301
  dataLabel() {
265
302
  switch (this.value._type) {
266
303
  case TYPES.TLS:
@@ -288,6 +325,14 @@ export default {
288
325
 
289
326
  methods: {
290
327
  async saveSecret(btnCb) {
328
+ const { valid } = await this.veeValidateForm();
329
+
330
+ if (!valid) {
331
+ btnCb(false);
332
+
333
+ return;
334
+ }
335
+
291
336
  if ( this.errors ) {
292
337
  clear(this.errors);
293
338
  }
@@ -399,7 +444,7 @@ export default {
399
444
  <CruResource
400
445
  v-else
401
446
  :mode="mode"
402
- :validation-passed="fvFormIsValid"
447
+ :validation-passed="isFormValid"
403
448
  :selected-subtype="value._type"
404
449
  :resource="value"
405
450
  :errors="errors"
@@ -416,6 +461,9 @@ export default {
416
461
  :value="value"
417
462
  :mode="mode"
418
463
  :namespaced="!isCloud"
464
+ :name-field-name="'metadata.name'"
465
+ :namespace-field-name="'metadata.namespace'"
466
+ :rules="{ name: getRules('metadata.name'), namespace: getRules('metadata.namespace'), description: [] }"
419
467
  @update:value="$emit('input', $event)"
420
468
  />
421
469
  <NameNsDescription
@@ -423,10 +471,8 @@ export default {
423
471
  :value="value"
424
472
  :namespaced="false"
425
473
  :mode="mode"
426
- :rules="{
427
- name: fvGetAndReportPathRules('metadata.name'),
428
- namespace: fvGetAndReportPathRules('metadata.namespace'),
429
- }"
474
+ :name-field-name="'metadata.name'"
475
+ :rules="{ name: getRules('metadata.name'), namespace: [], description: [] }"
430
476
  >
431
477
  <template #project-selector>
432
478
  <LabeledSelect
@@ -448,11 +494,13 @@ export default {
448
494
  <div class="col span-3">
449
495
  <LabeledSelect
450
496
  v-model:value="secretType"
497
+ name="secretType"
451
498
  :options="secretTypes"
452
499
  :searchable="false"
453
500
  :mode="mode"
454
501
  :multiple="false"
455
502
  :reduce="(e) => e.value"
503
+ :rules="getRules('secretType')"
456
504
  label-key="secret.type"
457
505
  required
458
506
  @update:value="selectCustomType"
@@ -465,8 +513,10 @@ export default {
465
513
  ref="customType"
466
514
  v-model:value="value._type"
467
515
  v-focus
516
+ name="secret._type"
468
517
  label-key="secret.customType"
469
518
  :mode="mode"
519
+ :rules="getRules('secret._type')"
470
520
  required
471
521
  />
472
522
  </div>
@@ -492,6 +542,7 @@ export default {
492
542
  name="data"
493
543
  :label="dataLabel"
494
544
  :weight="99"
545
+ :error="dataTabHasError"
495
546
  >
496
547
  <component
497
548
  :is="dataComponent"
@@ -1,6 +1,9 @@
1
1
  <script>
2
+ import { useStore } from 'vuex';
2
3
  import { LabeledInput } from '@components/Form/LabeledInput';
3
4
  import { RadioGroup } from '@components/Form/Radio';
5
+ import { useFormRules } from '@shell/composables/useFormValidation';
6
+ import { useI18n } from '@shell/composables/useI18n';
4
7
 
5
8
  export default {
6
9
  components: { LabeledInput, RadioGroup },
@@ -17,6 +20,33 @@ export default {
17
20
  }
18
21
  },
19
22
 
23
+ setup() {
24
+ const store = useStore();
25
+ const { t } = useI18n(store);
26
+ const { getRules } = useFormRules(
27
+ t,
28
+ [
29
+ {
30
+ path: 'registryUrl',
31
+ rules: ['required'],
32
+ translationKey: 'secret.registry.domainName',
33
+ },
34
+ {
35
+ path: 'username',
36
+ rules: ['required'],
37
+ translationKey: 'secret.registry.username',
38
+ },
39
+ {
40
+ path: 'password',
41
+ rules: ['required'],
42
+ translationKey: 'secret.registry.password',
43
+ },
44
+ ]
45
+ );
46
+
47
+ return { getRules };
48
+ },
49
+
20
50
  data() {
21
51
  let registryProvider = 'Custom';
22
52
 
@@ -118,26 +148,34 @@ export default {
118
148
  >
119
149
  <LabeledInput
120
150
  v-model:value="registryUrl"
151
+ name="registryUrl"
121
152
  required
122
153
  :label="t('secret.registry.domainName')"
123
154
  placeholder="e.g. index.docker.io"
124
155
  :mode="mode"
156
+ :rules="getRules('registryUrl')"
125
157
  />
126
158
  </div>
127
159
  <div class="row mb-20">
128
160
  <div class="col span-6">
129
161
  <LabeledInput
130
162
  v-model:value="username"
163
+ name="username"
164
+ required
131
165
  :label="t('secret.registry.username')"
132
166
  :mode="mode"
167
+ :rules="getRules('username')"
133
168
  />
134
169
  </div>
135
170
  <div class="col span-6">
136
171
  <LabeledInput
137
172
  v-model:value="password"
173
+ name="password"
174
+ required
138
175
  :label="t('secret.registry.password')"
139
176
  :mode="mode"
140
177
  type="password"
178
+ :rules="getRules('password')"
141
179
  />
142
180
  </div>
143
181
  </div>
@@ -1,6 +1,9 @@
1
1
  <script>
2
+ import { useStore } from 'vuex';
2
3
  import { LabeledInput } from '@components/Form/LabeledInput';
3
4
  import FileSelector, { createOnSelected } from '@shell/components/form/FileSelector';
5
+ import { useFormRules } from '@shell/composables/useFormValidation';
6
+ import { useI18n } from '@shell/composables/useI18n';
4
7
 
5
8
  export default {
6
9
  components: { LabeledInput, FileSelector },
@@ -17,6 +20,28 @@ export default {
17
20
  }
18
21
  },
19
22
 
23
+ setup() {
24
+ const store = useStore();
25
+ const { t } = useI18n(store);
26
+ const { getRules } = useFormRules(
27
+ t,
28
+ [
29
+ {
30
+ path: 'ssh-publickey',
31
+ rules: ['required'],
32
+ translationKey: 'secret.ssh.public',
33
+ },
34
+ {
35
+ path: 'ssh-privatekey',
36
+ rules: ['required'],
37
+ translationKey: 'secret.ssh.private',
38
+ },
39
+ ]
40
+ );
41
+
42
+ return { getRules };
43
+ },
44
+
20
45
  data() {
21
46
  const username = this.value.decodedData['ssh-publickey'] || '';
22
47
  const password = this.value.decodedData['ssh-privatekey'] || '';
@@ -60,10 +85,12 @@ export default {
60
85
  <LabeledInput
61
86
  v-model:value="username"
62
87
  type="multiline"
88
+ name="ssh-publickey"
63
89
  data-testid="ssh-public-key"
64
90
  :label="t('secret.ssh.public')"
65
91
  :mode="mode"
66
92
  required
93
+ :rules="getRules('ssh-publickey')"
67
94
  :placeholder="t('secret.ssh.publicPlaceholder')"
68
95
  />
69
96
  <FileSelector
@@ -76,10 +103,12 @@ export default {
76
103
  <LabeledInput
77
104
  v-model:value="password"
78
105
  type="multiline"
106
+ name="ssh-privatekey"
79
107
  data-testid="ssh-private-key"
80
108
  :label="t('secret.ssh.private')"
81
109
  :mode="mode"
82
110
  required
111
+ :rules="getRules('ssh-privatekey')"
83
112
  :placeholder="t('secret.ssh.privatePlaceholder')"
84
113
  />
85
114
  <FileSelector
@@ -1,7 +1,10 @@
1
1
  <script>
2
2
  import { _EDIT } from '@shell/config/query-params';
3
+ import { useStore } from 'vuex';
3
4
  import { LabeledInput } from '@components/Form/LabeledInput';
4
5
  import FileSelector, { createOnSelected } from '@shell/components/form/FileSelector';
6
+ import { useFormRules } from '@shell/composables/useFormValidation';
7
+ import { useI18n } from '@shell/composables/useI18n';
5
8
 
6
9
  export default {
7
10
  components: { LabeledInput, FileSelector },
@@ -18,6 +21,28 @@ export default {
18
21
  }
19
22
  },
20
23
 
24
+ setup() {
25
+ const store = useStore();
26
+ const { t } = useI18n(store);
27
+ const { getRules } = useFormRules(
28
+ t,
29
+ [
30
+ {
31
+ path: 'tls.key',
32
+ rules: ['required'],
33
+ translationKey: 'secret.certificate.privateKey',
34
+ },
35
+ {
36
+ path: 'tls.crt',
37
+ rules: ['required'],
38
+ translationKey: 'secret.certificate.certificate',
39
+ },
40
+ ]
41
+ );
42
+
43
+ return { getRules };
44
+ },
45
+
21
46
  data() {
22
47
  // do not show existing key when editing
23
48
  const originalKey = this.value.decodedData['tls.key'] || '';
@@ -63,9 +88,12 @@ export default {
63
88
  <div class="col span-6">
64
89
  <LabeledInput
65
90
  v-model:value="key"
91
+ name="tls.key"
92
+ required
66
93
  type="multiline"
67
94
  :label="t('secret.certificate.privateKey')"
68
95
  :mode="mode"
96
+ :rules="getRules('tls.key')"
69
97
  :placeholder="t('secret.certificate.privateKeyPlaceholder')"
70
98
  />
71
99
  <FileSelector
@@ -77,10 +105,12 @@ export default {
77
105
  <div class="col span-6">
78
106
  <LabeledInput
79
107
  v-model:value="crt"
108
+ name="tls.crt"
80
109
  required
81
110
  type="multiline"
82
111
  :label="t('secret.certificate.certificate')"
83
112
  :mode="mode"
113
+ :rules="getRules('tls.crt')"
84
114
  :placeholder="t('secret.certificate.certificatePlaceholder')"
85
115
  />
86
116
  <FileSelector
package/edit/service.vue CHANGED
@@ -203,10 +203,9 @@ export default {
203
203
  },
204
204
 
205
205
  provisioningCluster() {
206
- const out = this.$store.getters['management/all'](CAPI.RANCHER_CLUSTER).find((c) => c?.status?.clusterName === this.currentCluster.metadata.name);
207
-
208
- return out;
206
+ return this.currentCluster.provCluster;
209
207
  },
208
+
210
209
  errorMessages() {
211
210
  if (!this.serviceType) {
212
211
  return [];
@@ -273,8 +272,9 @@ export default {
273
272
  const hash = {};
274
273
 
275
274
  if (this.$store.getters[`management/canList`](CAPI.RANCHER_CLUSTER)) {
276
- hash.provClusters = this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
275
+ hash.provClusters = this.$store.dispatch('management/find', { type: CAPI.RANCHER_CLUSTER, id: this.currentCluster.provClusterId });
277
276
  }
277
+
278
278
  if (this.$store.getters[`management/canList`](HCI.HARVESTER_CONFIG)) {
279
279
  hash.harvesterConfigs = this.$store.dispatch(`management/findAll`, { type: HCI.HARVESTER_CONFIG });
280
280
  }
@@ -133,10 +133,10 @@ export default {
133
133
  } = this;
134
134
  let { maxSurge, maxUnavailable } = this;
135
135
 
136
- if (this.surgeUnits === '%' && !maxSurge.includes('%')) {
136
+ if (this.surgeUnits === '%' && !`${ maxSurge }`.includes('%')) {
137
137
  maxSurge = `${ maxSurge }%`;
138
138
  }
139
- if (this.unavailableUnits === '%' && !maxUnavailable.includes('%')) {
139
+ if (this.unavailableUnits === '%' && !`${ maxUnavailable }`.includes('%')) {
140
140
  maxUnavailable = `${ maxUnavailable }%`;
141
141
  }
142
142
 
@@ -204,7 +204,7 @@ export default {
204
204
  if (units === 'Pods') {
205
205
  this[target] = parseInt(value);
206
206
  } else {
207
- this[target] = `${ value }%`;
207
+ this[target] = value;
208
208
  }
209
209
  if (target === 'maxSurge') {
210
210
  this.surgeUnits = units;
@@ -25,20 +25,17 @@ describe('component: Upgrading', () => {
25
25
  expect(wrapper.props('value')?.[key]).toBe(newValue);
26
26
  });
27
27
 
28
- // TODO: #6179: Integrate test with component fix, as the scope is not to check the value of the input
29
- // eslint-disable-next-line jest/no-disabled-tests
30
- it.skip.each([
31
- ['surge', 'maxSurge', '%'],
32
- ['unavailable', 'maxUnavailable', '%'],
33
- ])('should set typed value in %p into %p and unit', (field, key, unit) => {
28
+ it.each([
29
+ ['maxSurge', '%'],
30
+ ['maxUnavailable', '%'],
31
+ ])('should set typed value in %p with %p unit', (key, unit) => {
34
32
  const wrapper = mount(Upgrading);
35
- const input = wrapper.find(`[data-testid="input-policy-${ field }"]`).find('input');
36
33
  const newValue = 123;
37
34
  const expectation = `${ newValue }${ unit }`;
38
35
 
39
- input.setValue(newValue);
40
- input.trigger('blur');
36
+ wrapper.vm.updateWithUnits({ selected: unit, text: newValue }, key);
41
37
 
38
+ expect(wrapper.vm[key]).toBe(newValue);
42
39
  expect(wrapper.props('value')?.strategy.rollingUpdate[key]).toBe(expectation);
43
40
  });
44
41
 
@@ -151,7 +151,8 @@ export default {
151
151
  const fetches = {};
152
152
 
153
153
  if (this.$store.getters[`management/canList`](CAPI.RANCHER_CLUSTER)) {
154
- fetches.rancherClusters = this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
154
+ // I could only find one place where a prov cluster might be used by this and parent components - shell/components/form/WorkloadPorts.vue provisioningCluster
155
+ fetches.rancherCluster = this.$store.dispatch('management/find', { type: CAPI.RANCHER_CLUSTER, id: this.currentCluster.provClusterId });
155
156
  }
156
157
 
157
158
  if (this.$store.getters[`management/canList`](HCI.HARVESTER_CONFIG)) {
@@ -1,19 +1,9 @@
1
1
  <script>
2
- import { FLEET } from '@shell/config/types';
3
- import { Banner } from '@components/Banner';
4
- import ResourceTable from '@shell/components/ResourceTable';
5
- import ResourceFetch from '@shell/mixins/resource-fetch';
6
- import {
7
- AGE,
8
- STATE,
9
- NAME,
10
- } from '@shell/config/table-headers';
11
- import { isHarvesterCluster } from '@shell/utils/cluster';
2
+ import FleetBundles from '@shell/components/fleet/FleetBundles';
12
3
 
13
4
  export default {
14
5
  name: 'ListBundle',
15
- components: { Banner, ResourceTable },
16
- mixins: [ResourceFetch],
6
+ components: { FleetBundles },
17
7
  props: {
18
8
  resource: {
19
9
  type: String,
@@ -28,100 +18,13 @@ export default {
28
18
  default: false
29
19
  }
30
20
  },
31
-
32
- async fetch() {
33
- await this.$fetchType(this.resource);
34
- if (this.$store.getters['management/schemaFor']( FLEET.CLUSTER )) {
35
- this.allFleet = await this.$store.getters['management/all'](FLEET.CLUSTER);
36
- }
37
- },
38
-
39
- data() {
40
- return { allFleet: [] };
41
- },
42
-
43
- computed: {
44
- harvesterClusters() {
45
- const harvester = {};
46
-
47
- this.allFleet.forEach((c) => {
48
- if (isHarvesterCluster(c)) {
49
- harvester[c.metadata.name] = c;
50
- }
51
- });
52
-
53
- return harvester;
54
- },
55
-
56
- bundles() {
57
- const harvester = this.harvesterClusters;
58
-
59
- return this.rows.filter((bundle) => {
60
- const targets = bundle.spec?.targets || [];
61
-
62
- // Filter out any bundle that has one target whose cluster is a harvester cluster
63
- if (targets.length === 1) {
64
- return !harvester[targets[0].clusterName];
65
- }
66
-
67
- return true;
68
- });
69
- },
70
-
71
- hidden() {
72
- return this.rows.length - this.bundles.length;
73
- },
74
-
75
- headers() {
76
- const out = [
77
- STATE,
78
- NAME,
79
- {
80
- name: 'deploymentsReady',
81
- labelKey: 'tableHeaders.bundleDeploymentsReady',
82
- value: 'status.display.readyClusters',
83
- sort: 'status.display.readyClusters',
84
- search: ['status.summary.ready', 'status.summary.desiredReady'],
85
- },
86
- AGE
87
- ];
88
-
89
- return out;
90
- },
91
- },
92
-
93
- // override with relevant info for the loading indicator since this doesn't use it's own masthead
94
- $loadingResources() {
95
- // results are filtered so we wouldn't get the correct count on indicator...
96
- return { loadIndeterminate: true };
97
- },
98
21
  };
99
22
  </script>
100
23
 
101
24
  <template>
102
- <div>
103
- <Banner
104
- v-if="hidden"
105
- color="info"
106
- :label="t('fleet.bundles.harvester', {count: hidden} )"
107
- />
108
- <ResourceTable
109
- :schema="schema"
110
- :headers="headers"
111
- :rows="bundles"
112
- :loading="loading"
113
- :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
114
- :force-update-live-and-delayed="forceUpdateLiveAndDelayed"
115
- >
116
- <template #cell:deploymentsReady="{row}">
117
- <span
118
- v-if="row.status && row.status.summary && (row.status.summary.desiredReady !== row.status.summary.ready)"
119
- class="text-warning"
120
- >
121
- {{ row.status.summary.ready || 0 }}/{{ row.status.summary.desiredReady }}</span>
122
- <span v-else-if="row.status && row.status.summary">{{ row.status.summary.desiredReady }}</span>
123
- <span v-else>-</span>
124
- </template>
125
- </ResourceTable>
126
- </div>
25
+ <FleetBundles
26
+ :resource="resource"
27
+ :schema="schema"
28
+ :use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
29
+ />
127
30
  </template>