@rancher/shell 0.3.0 → 0.3.1

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 (322) hide show
  1. package/assets/styles/global/_button.scss +5 -1
  2. package/assets/styles/global/_columns.scss +4 -0
  3. package/assets/styles/global/_layout.scss +1 -2
  4. package/assets/styles/global/_select.scss +1 -4
  5. package/assets/styles/themes/_dark.scss +4 -4
  6. package/assets/styles/themes/_light.scss +4 -3
  7. package/assets/styles/themes/_suse.scss +1 -1
  8. package/assets/styles/vendor/vue-select.scss +4 -3
  9. package/assets/translations/en-us.yaml +669 -73
  10. package/assets/translations/zh-hans.yaml +547 -165
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/cloud-credential/azure.vue +23 -0
  13. package/cloud-credential/harvester.vue +25 -62
  14. package/cloud-credential/pnap.vue +80 -0
  15. package/components/.DS_Store +0 -0
  16. package/components/AdvancedSection.vue +9 -2
  17. package/components/Alert.vue +2 -2
  18. package/components/ButtonDropdown.vue +0 -2
  19. package/components/ButtonGroup.vue +1 -0
  20. package/components/CollapsibleCard.vue +0 -1
  21. package/components/CruResource.vue +41 -4
  22. package/components/DetailTop.vue +58 -3
  23. package/components/DisableAuthProviderModal.vue +106 -0
  24. package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
  25. package/components/ExplorerMembers.vue +253 -30
  26. package/components/ExplorerProjectsNamespaces.vue +77 -33
  27. package/components/GrowlManager.vue +3 -3
  28. package/components/IconOrSvg.vue +149 -0
  29. package/components/LogItem.vue +69 -0
  30. package/components/PodSecurityAdmission.vue +302 -0
  31. package/components/PromptModal.vue +1 -0
  32. package/components/ResourceDetail/Masthead.vue +54 -2
  33. package/components/ResourceDetail/index.vue +12 -5
  34. package/components/ResourceList/Masthead.vue +11 -1
  35. package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
  36. package/components/ResourceList/index.vue +53 -12
  37. package/components/ResourceList/resource-list.config.js +7 -0
  38. package/components/ResourceTable.vue +31 -6
  39. package/components/SimpleBox.vue +1 -1
  40. package/components/SortableTable/THead.vue +15 -5
  41. package/components/SortableTable/index.vue +21 -10
  42. package/components/Tabbed/index.vue +20 -15
  43. package/components/__tests__/.DS_Store +0 -0
  44. package/components/__tests__/AsyncButton.test.ts +140 -0
  45. package/components/__tests__/BackLink.test.ts +33 -0
  46. package/components/__tests__/ButtonGroup.test.ts +124 -0
  47. package/components/__tests__/ClusterBadge.test.ts +32 -0
  48. package/components/__tests__/CollapsibleCard.test.ts +64 -0
  49. package/components/__tests__/ConsumptionGauge.test.ts +88 -0
  50. package/components/__tests__/CruResource.test.ts +3 -2
  51. package/components/__tests__/FixedBanner.test.ts +129 -0
  52. package/components/__tests__/GrowlManager.test.ts +147 -0
  53. package/components/__tests__/NamespaceFilter.test.ts +33 -25
  54. package/components/__tests__/PercentageBar.test.ts +32 -0
  55. package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
  56. package/components/auth/AuthBanner.vue +20 -10
  57. package/components/auth/RoleDetailEdit.vue +26 -17
  58. package/components/auth/SelectPrincipal.vue +36 -5
  59. package/components/form/ArrayList.vue +3 -35
  60. package/components/form/ArrayListGrouped.vue +13 -4
  61. package/components/form/ArrayListSelect.vue +5 -5
  62. package/components/form/Error.vue +8 -0
  63. package/components/form/KeyValue.vue +39 -7
  64. package/components/form/LabeledSelect.vue +5 -2
  65. package/components/form/Labels.vue +46 -16
  66. package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
  67. package/components/form/Members/MembershipEditor.vue +12 -12
  68. package/components/form/NameNsDescription.vue +1 -1
  69. package/components/form/NodeScheduling.vue +1 -1
  70. package/components/form/Probe.vue +3 -3
  71. package/components/form/ResourceQuota/Project.vue +6 -6
  72. package/components/form/ResourceTabs/index.vue +1 -6
  73. package/components/form/Security.vue +7 -6
  74. package/components/form/Select.vue +3 -2
  75. package/components/form/SelectOrCreateAuthSecret.vue +22 -29
  76. package/components/form/ServicePorts.vue +8 -0
  77. package/components/form/WorkloadPorts.vue +7 -1
  78. package/components/form/__tests__/ArrayList.test.ts +74 -0
  79. package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
  80. package/components/formatter/Checked.vue +1 -1
  81. package/components/formatter/ClusterLink.vue +5 -0
  82. package/components/formatter/IconIsDefault.vue +2 -2
  83. package/components/formatter/InternalExternalIP.vue +11 -8
  84. package/components/formatter/LiveDuration.vue +78 -0
  85. package/components/formatter/WorkloadHealthScale.vue +5 -3
  86. package/components/nav/Header.vue +6 -3
  87. package/components/nav/NamespaceFilter.vue +146 -63
  88. package/components/nav/TopLevelMenu.vue +22 -19
  89. package/components/nav/WindowManager/ContainerLogs.vue +83 -126
  90. package/components/nav/WindowManager/ContainerShell.vue +9 -7
  91. package/components/nav/WindowManager/Window.vue +2 -0
  92. package/components/nav/WindowManager/index.vue +10 -0
  93. package/config/elemental-types.js +9 -0
  94. package/config/features.js +2 -0
  95. package/config/home-links.js +4 -1
  96. package/config/pod-security-admission.ts +82 -0
  97. package/config/product/apps.js +1 -1
  98. package/config/product/auth.js +6 -5
  99. package/config/product/explorer.js +6 -6
  100. package/config/product/fleet.js +1 -1
  101. package/config/product/manager.js +6 -2
  102. package/config/secret.js +0 -1
  103. package/config/settings.ts +26 -9
  104. package/config/table-headers.js +22 -11
  105. package/config/types.js +4 -1
  106. package/content/docs/zh-hans/getting-started.md +113 -137
  107. package/content/docs/zh-hans/whats-new.md +8 -46
  108. package/creators/pkg/package-lock.json +37 -0
  109. package/creators/pkg/package.json +1 -1
  110. package/detail/catalog.cattle.io.app.vue +1 -1
  111. package/detail/pod.vue +1 -1
  112. package/detail/provisioning.cattle.io.cluster.vue +35 -9
  113. package/detail/service.vue +2 -9
  114. package/detail/workload/index.vue +0 -1
  115. package/dialog/AddClusterMemberDialog.vue +22 -28
  116. package/dialog/AddProjectMemberDialog.vue +53 -9
  117. package/dialog/DiagnosticTimingsDialog.vue +8 -7
  118. package/dialog/DrainNode.vue +44 -48
  119. package/dialog/ForceMachineRemoveDialog.vue +5 -7
  120. package/dialog/GenericPrompt.vue +15 -20
  121. package/dialog/RollbackWorkloadDialog.vue +15 -46
  122. package/dialog/RotateCertificatesDialog.vue +5 -7
  123. package/dialog/RotateEncryptionKeyDialog.vue +5 -9
  124. package/dialog/SaveAsRKETemplateDialog.vue +5 -13
  125. package/dialog/ScaleMachineDownDialog.vue +1 -1
  126. package/dialog/ScalePoolDownDialog.vue +121 -0
  127. package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
  128. package/edit/auth/azuread.vue +16 -16
  129. package/edit/auth/github.vue +8 -0
  130. package/edit/auth/googleoauth.vue +10 -1
  131. package/edit/auth/ldap/index.vue +10 -0
  132. package/edit/auth/oidc.vue +10 -0
  133. package/edit/auth/saml.vue +10 -0
  134. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
  135. package/edit/cloudcredential.vue +3 -7
  136. package/edit/logging-flow/Match.vue +39 -8
  137. package/edit/logging-flow/index.vue +27 -4
  138. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
  139. package/edit/management.cattle.io.project.vue +8 -1
  140. package/edit/management.cattle.io.setting.vue +5 -2
  141. package/edit/management.cattle.io.user.vue +7 -1
  142. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +23 -7
  143. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
  144. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
  145. package/edit/namespace.vue +18 -4
  146. package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
  147. package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
  148. package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
  149. package/edit/networking.k8s.io.ingress/index.vue +8 -6
  150. package/edit/persistentvolume/index.vue +30 -27
  151. package/edit/persistentvolume/plugins/cephfs.vue +29 -29
  152. package/edit/persistentvolume/plugins/csi.vue +102 -62
  153. package/edit/persistentvolume/plugins/fc.vue +19 -19
  154. package/edit/persistentvolume/plugins/iscsi.vue +45 -45
  155. package/edit/persistentvolume/plugins/rbd.vue +39 -39
  156. package/edit/persistentvolumeclaim.vue +78 -75
  157. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
  158. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
  159. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
  160. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
  161. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +93 -0
  162. package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
  164. package/edit/provisioning.cattle.io.cluster/rke2.vue +440 -152
  165. package/edit/secret/index.vue +3 -7
  166. package/edit/service.vue +3 -1
  167. package/edit/storage.k8s.io.storageclass/index.vue +100 -16
  168. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
  169. package/edit/workload/__tests__/index.test.ts +98 -0
  170. package/edit/workload/index.vue +58 -8
  171. package/edit/workload/mixins/workload.js +107 -70
  172. package/edit/workload/storage/ContainerMountPaths.vue +0 -10
  173. package/edit/workload/storage/emptyDir.vue +88 -0
  174. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  175. package/edit/workload/storage/index.vue +8 -0
  176. package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
  177. package/layouts/default.vue +57 -44
  178. package/list/__tests__/workload.test.ts +5 -2
  179. package/list/catalog.cattle.io.app.vue +1 -0
  180. package/list/cis.cattle.io.clusterscan.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +5 -6
  182. package/list/fleet.cattle.io.cluster.vue +6 -3
  183. package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
  184. package/list/fleet.cattle.io.gitrepo.vue +4 -9
  185. package/list/helm.cattle.io.projecthelmchart.vue +1 -5
  186. package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
  187. package/list/logging.banzaicloud.io.flow.vue +6 -5
  188. package/list/management.cattle.io.cluster.vue +1 -0
  189. package/list/management.cattle.io.feature.vue +3 -4
  190. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
  191. package/list/management.cattle.io.setting.vue +2 -2
  192. package/list/management.cattle.io.user.vue +4 -10
  193. package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
  194. package/list/node.vue +8 -5
  195. package/list/persistentvolume.vue +3 -3
  196. package/list/persistentvolumeclaim.vue +3 -4
  197. package/list/provisioning.cattle.io.cluster.vue +18 -19
  198. package/list/service.vue +6 -14
  199. package/list/workload.vue +43 -38
  200. package/machine-config/azure.vue +429 -60
  201. package/machine-config/pnap.vue +288 -0
  202. package/mixins/auth-config.js +1 -3
  203. package/mixins/browser-tab-visibility.js +8 -14
  204. package/mixins/chart.js +1 -1
  205. package/mixins/create-edit-view/impl.js +4 -0
  206. package/mixins/create-edit-view/index.js +4 -2
  207. package/mixins/resource-fetch-namespaced.js +98 -0
  208. package/mixins/resource-fetch.js +79 -45
  209. package/mixins/resource-manager.js +1 -23
  210. package/models/apps.controllerrevision.js +7 -0
  211. package/models/apps.daemonset.js +18 -0
  212. package/models/apps.deployment.js +44 -0
  213. package/models/apps.replicaset.js +7 -0
  214. package/models/apps.statefulset.js +18 -0
  215. package/models/batch.job.js +7 -14
  216. package/models/cluster/node.js +10 -2
  217. package/models/cluster.x-k8s.io.machine.js +26 -4
  218. package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
  219. package/models/event.js +7 -0
  220. package/models/logging.banzaicloud.io.flow.js +4 -0
  221. package/models/management.cattle.io.cluster.js +1 -1
  222. package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
  223. package/models/management.cattle.io.globalrole.js +2 -2
  224. package/models/management.cattle.io.node.js +37 -2
  225. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
  226. package/models/management.cattle.io.project.js +30 -11
  227. package/models/management.cattle.io.setting.js +1 -1
  228. package/models/management.cattle.io.user.js +37 -1
  229. package/models/namespace.js +42 -5
  230. package/models/persistentvolume.js +14 -2
  231. package/models/pod.js +15 -0
  232. package/models/projectroletemplatebinding.js +7 -0
  233. package/models/provisioning.cattle.io.cluster.js +61 -10
  234. package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
  235. package/models/service.js +14 -13
  236. package/models/storage.k8s.io.storageclass.js +33 -18
  237. package/models/workload.js +38 -7
  238. package/nuxt.config.js +27 -17
  239. package/package.json +7 -7
  240. package/pages/about.vue +14 -2
  241. package/pages/c/_cluster/apps/charts/index.vue +4 -3
  242. package/pages/c/_cluster/apps/charts/install.vue +59 -22
  243. package/pages/c/_cluster/auth/config/_id.vue +6 -0
  244. package/pages/c/_cluster/auth/config/index.vue +8 -6
  245. package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
  246. package/pages/c/_cluster/auth/roles/index.vue +1 -1
  247. package/pages/c/_cluster/explorer/index.vue +12 -6
  248. package/pages/c/_cluster/longhorn/index.vue +1 -1
  249. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
  250. package/pages/c/_cluster/monitoring/index.vue +1 -1
  251. package/pages/c/_cluster/neuvector/index.vue +1 -1
  252. package/pages/c/_cluster/settings/performance.vue +48 -2
  253. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +34 -1
  254. package/pages/c/_cluster/uiplugins/index.vue +28 -2
  255. package/pages/diagnostic.vue +5 -4
  256. package/pages/home.vue +105 -30
  257. package/pages/prefs.vue +23 -12
  258. package/pages/rio/mesh.vue +1 -1
  259. package/pkg/dynamic-importer.lib.js +8 -0
  260. package/pkg/vue.config.js +4 -0
  261. package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
  262. package/plugins/dashboard-store/actions.js +32 -25
  263. package/plugins/dashboard-store/getters.js +50 -33
  264. package/plugins/dashboard-store/mutations.js +134 -28
  265. package/plugins/dashboard-store/resource-class.js +21 -41
  266. package/plugins/steve/actions.js +30 -0
  267. package/plugins/steve/caches/resourceCache.js +60 -0
  268. package/plugins/steve/getters.js +44 -1
  269. package/plugins/steve/mutations.js +97 -36
  270. package/plugins/steve/resourceWatcher.js +277 -0
  271. package/plugins/steve/schema.utils.js +25 -0
  272. package/plugins/steve/subscribe.js +288 -115
  273. package/plugins/steve/worker/index.js +17 -0
  274. package/plugins/steve/worker/web-worker.advanced.js +302 -0
  275. package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
  276. package/rancher-components/Card/Card.vue +3 -3
  277. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
  278. package/rancher-components/StringList/StringList.test.ts +45 -420
  279. package/rancher-components/StringList/StringList.vue +1 -10
  280. package/rancher-components/components/Banner/Banner.test.ts +44 -0
  281. package/rancher-components/components/Banner/Banner.vue +129 -61
  282. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
  283. package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
  284. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
  285. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
  286. package/rancher-components/components/StringList/StringList.test.ts +7 -7
  287. package/rancher-components/components/StringList/StringList.vue +21 -15
  288. package/scripts/test-plugins-build.sh +8 -0
  289. package/static/loading-indicator.html +1 -1
  290. package/store/index.js +54 -3
  291. package/store/plugins.js +0 -17
  292. package/store/pnap.js +128 -0
  293. package/store/prefs.js +4 -2
  294. package/store/type-map.js +55 -13
  295. package/types/pod-security-admission.ts +36 -0
  296. package/types/shell/index.d.ts +496 -396
  297. package/utils/__tests__/object.test.ts +17 -1
  298. package/utils/__tests__/pod-security-admission.test.ts +61 -0
  299. package/utils/async.ts +36 -0
  300. package/utils/color.js +45 -0
  301. package/utils/crypto/browserHashUtils.js +18 -0
  302. package/utils/dynamic-importer.js +8 -0
  303. package/utils/install-redirect.js +1 -1
  304. package/utils/object.js +24 -0
  305. package/utils/pod-security-admission.ts +39 -0
  306. package/utils/socket.js +61 -24
  307. package/utils/string.js +2 -0
  308. package/utils/svg-filter.js +301 -0
  309. package/utils/time.js +49 -0
  310. package/utils/validators/cidr.js +4 -0
  311. package/utils/validators/formRules/__tests__/index.test.ts +23 -3
  312. package/utils/validators/formRules/index.ts +14 -0
  313. package/config/product/harvester-manager.js +0 -162
  314. package/edit/harvesterhci.io.management.cluster.vue +0 -153
  315. package/list/harvesterhci.io.management.cluster.vue +0 -241
  316. package/machine-config/harvester.vue +0 -693
  317. package/models/harvesterhci.io.management.cluster.js +0 -228
  318. package/pages/c/_cluster/harvesterManager/index.vue +0 -24
  319. package/rancher-components/Card/Card.test.ts +0 -39
  320. package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
  321. package/rancher-components/Utils/DraggableZone/index.ts +0 -1
  322. package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
@@ -16,7 +16,6 @@ import Labels from '@shell/components/form/Labels';
16
16
  import { HIDE_SENSITIVE } from '@shell/store/prefs';
17
17
  import { CAPI } from '@shell/config/labels-annotations';
18
18
  import { clear, uniq } from '@shell/utils/array';
19
- import { importCloudCredential } from '@shell/utils/dynamic-importer';
20
19
  import { NAME as MANAGER } from '@shell/config/product/manager';
21
20
  import SelectIconGrid from '@shell/components/SelectIconGrid';
22
21
  import { sortBy } from '@shell/utils/sort';
@@ -128,14 +127,11 @@ export default {
128
127
  },
129
128
 
130
129
  cloudComponent() {
131
- const driver = this.driverName;
132
- const haveProviders = this.$store.getters['plugins/credentialDrivers'];
133
-
134
- if ( haveProviders.includes(driver) ) {
135
- return importCloudCredential(driver);
130
+ if (this.$store.getters['type-map/hasCustomCloudCredentialComponent'](this.driverName)) {
131
+ return this.$store.getters['type-map/importCloudCredential'](this.driverName);
136
132
  }
137
133
 
138
- return importCloudCredential('generic');
134
+ return this.$store.getters['type-map/importCloudCredential']('generic');
139
135
  },
140
136
 
141
137
  // array of id, label, description, initials for type selection step
package/edit/service.vue CHANGED
@@ -22,7 +22,7 @@ import HarvesterServiceAddOnConfig from '@shell/components/HarvesterServiceAddOn
22
22
  import { clone } from '@shell/utils/object';
23
23
  import { POD, CAPI } from '@shell/config/types';
24
24
  import { matching } from '@shell/utils/selector';
25
- import { HARVESTER_NAME as HARVESTER } from '@shell/config/product/harvester-manager';
25
+ import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
26
26
  import { allHash } from '@shell/utils/promise';
27
27
  import { isHarvesterSatisfiesVersion } from '@shell/utils/cluster';
28
28
  import { Port } from '@shell/utils/validators/formRules';
@@ -328,6 +328,7 @@ export default {
328
328
  :validation-passed="fvFormIsValid"
329
329
  :errors="fvUnreportedValidationErrors"
330
330
  :apply-hooks="applyHooks"
331
+ :description="t('servicesPage.serviceListDescription')"
331
332
  @error="(e) => (errors = e)"
332
333
  @finish="save"
333
334
  @cancel="done"
@@ -385,6 +386,7 @@ export default {
385
386
  name="selectors"
386
387
  :label="t('servicesPage.selectors.label')"
387
388
  >
389
+ <p>{{ t('servicesPage.selectors.matchingPods.description') }}</p>
388
390
  <div class="row">
389
391
  <div class="col span-12">
390
392
  <Banner :color="(matchingPods.none ? 'warning' : 'success')">
@@ -5,11 +5,14 @@ import NameNsDescription from '@shell/components/form/NameNsDescription';
5
5
  import ArrayList from '@shell/components/form/ArrayList';
6
6
  import Tab from '@shell/components/Tabbed/Tab';
7
7
  import Tabbed from '@shell/components/Tabbed';
8
+ import Banner from '@components/Banner/Banner.vue';
8
9
  import { RadioGroup } from '@components/Form/Radio';
9
10
  import LabeledSelect from '@shell/components/form/LabeledSelect';
10
11
  import { _CREATE, _VIEW } from '@shell/config/query-params';
11
12
  import { PROVISIONER_OPTIONS } from '@shell/models/storage.k8s.io.storageclass';
12
13
  import { mapFeature, UNSUPPORTED_STORAGE_DRIVERS } from '@shell/store/features';
14
+ import { CSI_DRIVER } from '@shell/config/types';
15
+ import { LONGHORN_DRIVER } from '@shell/models/persistentvolume';
13
16
 
14
17
  export default {
15
18
  name: 'StorageClass',
@@ -22,10 +25,17 @@ export default {
22
25
  RadioGroup,
23
26
  Tab,
24
27
  Tabbed,
28
+ Banner
25
29
  },
26
30
 
27
31
  mixins: [CreateEditView],
28
32
 
33
+ async fetch() {
34
+ if (this.$store.getters['cluster/schemaFor'](CSI_DRIVER)) {
35
+ this.csiDrivers = await this.$store.dispatch('cluster/findAll', { type: CSI_DRIVER });
36
+ }
37
+ },
38
+
29
39
  data() {
30
40
  const reclaimPolicyOptions = [
31
41
  {
@@ -70,7 +80,7 @@ export default {
70
80
  allowVolumeExpansionOptions,
71
81
  volumeBindingModeOptions,
72
82
  mountOptions: [],
73
- provisioner: PROVISIONER_OPTIONS[0].value,
83
+ csiDrivers: [],
74
84
  };
75
85
  },
76
86
 
@@ -85,9 +95,59 @@ export default {
85
95
  return this.value.provisioner;
86
96
  },
87
97
 
98
+ // PROVISIONER_OPTIONS are provs with custom components: all the in-tree types + longhorn and harvester
99
+ // CSI drivers are third party provisioner options - this.csiDrivers is a list of the ones that are currently installed on this cluster
88
100
  provisioners() {
89
- return PROVISIONER_OPTIONS.filter(provisioner => this.showUnsupportedStorage || provisioner.supported);
90
- }
101
+ const dropdownOptions = [];
102
+ const provisionerOptionsDrivers = [];
103
+
104
+ PROVISIONER_OPTIONS.forEach((opt) => {
105
+ provisionerOptionsDrivers.push(opt.value);
106
+ if (this.showUnsupportedStorage || opt.supported) {
107
+ let label = this.t(opt.labelKey);
108
+
109
+ if (opt.value.includes('kubernetes')) {
110
+ label += ` ${ this.t('persistentVolume.plugin.inTree') }`;
111
+ }
112
+ if (!opt.supported) {
113
+ label += ` ${ this.t('persistentVolume.plugin.unsupported') }`;
114
+ }
115
+ dropdownOptions.push({
116
+ value: opt.value,
117
+ label,
118
+ deprecated: opt.deprecated
119
+ });
120
+ }
121
+ });
122
+
123
+ this.csiDrivers.forEach((driver) => {
124
+ // if a csiDriver is in PROVISIONER_OPTIONS, it's already in the dropdown list; dont add again
125
+ if (driver.metadata.name === LONGHORN_DRIVER || provisionerOptionsDrivers.includes(driver.metadata.name)) {
126
+ return;
127
+ }
128
+ const fallback = `${ driver.metadata.name } ${ this.t('persistentVolume.csi.drivers.suffix') }`;
129
+
130
+ dropdownOptions.push({
131
+ value: driver.metadata.name,
132
+ label: this.$store.getters['i18n/withFallback'](`persistentVolume.csi.drivers.${ driver.metadata.name.replaceAll('.', '-') }`, null, fallback)
133
+ });
134
+ });
135
+ const out = dropdownOptions.sort((a, b) => a.label.toLowerCase() > b.label.toLowerCase() ? 1 : -1);
136
+
137
+ return out;
138
+ },
139
+
140
+ provisionerIsDeprecated() {
141
+ const provisionerOpt = PROVISIONER_OPTIONS.find(opt => opt.value === this.value.provisioner);
142
+
143
+ return provisionerOpt && provisionerOpt.deprecated !== undefined;
144
+ },
145
+
146
+ provisionerIsHideCustomize() {
147
+ const provisionerOpt = PROVISIONER_OPTIONS.find(opt => opt.value === this.value.provisioner);
148
+
149
+ return provisionerOpt && provisionerOpt.hideCustomize !== undefined;
150
+ },
91
151
  },
92
152
 
93
153
  watch: {
@@ -120,6 +180,18 @@ export default {
120
180
  delete this.value.parameters[key];
121
181
  }
122
182
  });
183
+ },
184
+ provisionerLabel(provisioner) {
185
+ const provisionerOpt = PROVISIONER_OPTIONS.find(opt => opt.value === provisioner);
186
+
187
+ return provisionerOpt?.labelKey ? this.t(provisionerOpt.labelKey) : provisioner;
188
+ },
189
+ getOptionLabel(opt) {
190
+ if (opt.deprecated) {
191
+ return `${ opt.label } ${ this.t('storageClass.deprecated.title') }`;
192
+ }
193
+
194
+ return opt.label;
123
195
  }
124
196
  }
125
197
  };
@@ -143,34 +215,46 @@ export default {
143
215
  :mode="modeOverride"
144
216
  :register-before-hook="registerBeforeHook"
145
217
  />
218
+
146
219
  <LabeledSelect
147
220
  :value="value.provisioner"
148
221
  label="Provisioner"
149
222
  :options="provisioners"
150
223
  :localized-label="true"
151
- option-label="labelKey"
224
+ :get-option-label="getOptionLabel"
152
225
  :mode="modeOverride"
153
226
  :searchable="true"
154
227
  :taggable="true"
155
228
  class="mb-20"
156
229
  @input="updateProvisioner($event)"
157
230
  />
231
+ <Banner
232
+ v-if="provisionerIsDeprecated"
233
+ color="warning"
234
+ >
235
+ <t
236
+ k="storageClass.deprecated.warning"
237
+ raw
238
+ :provisioner="provisionerLabel(value.provisioner)"
239
+ />
240
+ </Banner>
158
241
  <Tabbed :side-tabs="true">
159
- <Tab
160
- name="parameters"
161
- :label="t('storageClass.parameters.label')"
162
- :weight="2"
242
+ <Tab
243
+ name="parameters"
244
+ :label="t('storageClass.parameters.label')"
245
+ :weight="2"
163
246
  >
164
- <component
165
- :is="getComponent(value.provisioner)"
166
- :key="value.provisioner"
167
- :value="value"
168
- :mode="modeOverride"
247
+ <component
248
+ :is="getComponent(value.provisioner)"
249
+ :key="value.provisioner"
250
+ :value="value"
251
+ :mode="modeOverride"
169
252
  />
170
253
  </Tab>
171
- <Tab
172
- name="customize"
173
- :label="t('storageClass.customize.label')"
254
+ <Tab
255
+ v-if="!provisionerIsHideCustomize"
256
+ name="customize"
257
+ :label="t('storageClass.customize.label')"
174
258
  >
175
259
  <div class="row mt-20">
176
260
  <div class="col span-6">
@@ -0,0 +1,114 @@
1
+ <script>
2
+ import { mapGetters } from 'vuex';
3
+ import semver from 'semver';
4
+
5
+ import { LabeledInput } from '@components/Form/LabeledInput';
6
+ import Banner from '@components/Banner/Banner.vue';
7
+ import KeyValue from '@shell/components/form/KeyValue';
8
+
9
+ import { clone } from '@shell/utils/object';
10
+ import { allHash } from '@shell/utils/promise';
11
+
12
+ const DEFAULT_PARAMETERS = [
13
+ 'hostStorageClass',
14
+ ];
15
+
16
+ export default {
17
+ components: {
18
+ LabeledInput,
19
+ Banner,
20
+ KeyValue,
21
+ },
22
+
23
+ props: {
24
+ value: {
25
+ type: Object,
26
+ required: true
27
+ },
28
+ mode: {
29
+ type: String,
30
+ required: true
31
+ }
32
+ },
33
+
34
+ async fetch() {
35
+ const res = await allHash({ rke2Versions: this.$store.dispatch('management/request', { url: '/v1-rke2-release/releases' }) });
36
+
37
+ this.rke2Versions = res.rke2Versions;
38
+ },
39
+
40
+ data() {
41
+ return { rke2Versions: {} };
42
+ },
43
+
44
+ computed: {
45
+ ...mapGetters(['currentCluster']),
46
+
47
+ isSatisfiesVersion() {
48
+ const kubernetesVersion = this.currentCluster.kubernetesVersion;
49
+ const kubernetesVersionExtension = this.currentCluster.kubernetesVersionExtension;
50
+
51
+ if (kubernetesVersionExtension.startsWith('rke2')) {
52
+ const charts = ((this.rke2Versions?.data || []).find(v => v.id === kubernetesVersion) || {}).charts;
53
+ let csiVersion = charts?.['harvester-csi-driver']?.version || '';
54
+
55
+ if (csiVersion.endsWith('00')) {
56
+ csiVersion = csiVersion.slice(0, -2);
57
+ }
58
+
59
+ return semver.satisfies(csiVersion, '>=0.1.15');
60
+ } else {
61
+ return true;
62
+ }
63
+ },
64
+
65
+ parameters: {
66
+ get() {
67
+ const parameters = clone(this.value?.parameters) || {};
68
+
69
+ DEFAULT_PARAMETERS.map((key) => {
70
+ delete parameters[key];
71
+ });
72
+
73
+ return parameters;
74
+ },
75
+
76
+ set(value) {
77
+ Object.assign(this.value.parameters, value);
78
+ }
79
+ },
80
+ },
81
+ };
82
+ </script>
83
+
84
+ <template>
85
+ <div>
86
+ <Banner
87
+ v-if="!isSatisfiesVersion"
88
+ color="warning"
89
+ >
90
+ {{ t('storageClass.harvesterhci.warning.unSatisfiesVersion', null, true) }}
91
+ </Banner>
92
+ <div v-else>
93
+ <div
94
+ class="row mb-10"
95
+ >
96
+ <div class="col span-6">
97
+ <LabeledInput
98
+ v-model="value.parameters.hostStorageClass"
99
+ :label="t('storageClass.harvesterhci.hostStorageClass.label')"
100
+ :placeholder="t('storageClass.harvesterhci.hostStorageClass.placeholder')"
101
+ :mode="mode"
102
+ :tooltip="t('storageClass.harvesterhci.hostStorageClass.tooltip')"
103
+ />
104
+ </div>
105
+ </div>
106
+ <KeyValue
107
+ v-model="parameters"
108
+ :add-label="t('storageClass.longhorn.addLabel')"
109
+ :read-allowed="false"
110
+ :mode="mode"
111
+ />
112
+ </div>
113
+ </div>
114
+ </template>
@@ -0,0 +1,98 @@
1
+ import { createLocalVue, shallowMount } from '@vue/test-utils';
2
+ import Workload from '@shell/edit/workload/index.vue';
3
+
4
+ jest.mock('@shell/models/secret', () => ({ onmessage: jest.fn() }));
5
+
6
+ describe('component: Workload', () => {
7
+ it.each([
8
+ [
9
+ `pods \"test\" is forbidden: violates PodSecurity \"restricted:latest\": allowPrivilegeEscalation != false (container \"container-0\" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container \"container-0\" must set securityContext.capabilities.drop=[\"ALL\"]), runAsNonRoot != true (container \"container-0\" must not set securityContext.runAsNonRoot=false), seccompProfile (pod or container \"container-0\" must set securityContext.seccompProfile.type to \"RuntimeDefault\" or \"Localhost\")`,
10
+ `Pod "test" Security Policy Violation "restricted:latest"`
11
+ ]
12
+ ])('should map error message into object', (oldMessage, newMessage) => {
13
+ const mockedValidationMixin = {
14
+ methods: {
15
+ fvFormIsValid: jest.fn(),
16
+ type: jest.fn(),
17
+ fvUnreportedValidationErrors: jest.fn(),
18
+ fvGetAndReportPathRules: jest.fn(),
19
+ }
20
+ };
21
+ const mockedCREMixin = {};
22
+ const mockedWorkloadMixin = {
23
+ methods: {
24
+ doneRoute: jest.fn(),
25
+ workloadSubTypes: jest.fn(),
26
+ applyHooks: jest.fn(),
27
+ save: jest.fn(),
28
+ selectType: jest.fn(),
29
+ isCronJob: jest.fn(),
30
+ spec: jest.fn(),
31
+ isReplicable: jest.fn(),
32
+ isStatefulSet: jest.fn(),
33
+ headlessServices: jest.fn(),
34
+ defaultTab: jest.fn(),
35
+ allContainers: jest.fn(),
36
+ isPod: jest.fn(),
37
+ tabWeightMap: jest.fn(),
38
+ podLabels: jest.fn(),
39
+ podTemplateSpec: jest.fn(),
40
+ isLoadingSecondaryResources: jest.fn(),
41
+ allNodes: jest.fn(),
42
+ allNodeObjects: jest.fn(),
43
+ clearPvcFormState: jest.fn(),
44
+ savePvcHookName: jest.fn(),
45
+ namespacedConfigMaps: jest.fn(),
46
+ podAnnotations: jest.fn(),
47
+ isJob: jest.fn(),
48
+ podFsGroup: jest.fn(),
49
+ namespacedSecrets: jest.fn(),
50
+ registerBeforeHook: jest.fn(),
51
+ pvcs: jest.fn(),
52
+ // tabWeightMap: jest.fn(),
53
+ }
54
+ };
55
+ const localVue = createLocalVue();
56
+ const MockedWorkload = { ...Workload, mixins: [mockedValidationMixin, mockedCREMixin, mockedWorkloadMixin] };
57
+ const wrapper = shallowMount(MockedWorkload, {
58
+ localVue,
59
+ propsData: {
60
+ value: { metadata: {}, spec: { template: {} } },
61
+ params: {},
62
+ fvFormIsValid: {}
63
+ },
64
+ mocks: {
65
+ $route: { params: {}, query: {} },
66
+ $router: { applyQuery: jest.fn() },
67
+ $fetchState: { pending: false },
68
+ $store: {
69
+ getters: {
70
+ 'cluster/schemaFor': jest.fn(),
71
+ 'type-map/labelFor': jest.fn(),
72
+ 'i18n/t': jest.fn(),
73
+ },
74
+ },
75
+ },
76
+ stubs: {
77
+ Tab: true,
78
+ LabeledInput: true,
79
+ VolumeClaimTemplate: true,
80
+ Networking: true,
81
+ Job: true,
82
+ NodeScheduling: true,
83
+ PodAffinity: true,
84
+ Tolerations: true,
85
+ Storage: true,
86
+ Tabbed: true,
87
+ LabeledSelect: true,
88
+ NameNsDescription: true,
89
+ CruResource: true,
90
+ KeyValue: true
91
+ }
92
+ });
93
+
94
+ const result = (wrapper.vm as any).mapError(oldMessage).message;
95
+
96
+ expect(result).toStrictEqual(newMessage);
97
+ });
98
+ });
@@ -22,12 +22,48 @@ export default {
22
22
  },
23
23
  methods: {
24
24
  changed(tab) {
25
+ const key = this.idKey;
26
+
25
27
  this.selectedName = tab.selectedName;
26
- const container = this.containerOptions.find( c => c.name === tab.selectedName);
28
+ const container = this.containerOptions.find( c => c[key] === tab.selectedName);
27
29
 
28
30
  if ( container ) {
29
31
  this.selectContainer(container);
30
32
  }
33
+ },
34
+
35
+ /**
36
+ * Find error exceptions to be mapped for each case
37
+ */
38
+ mapError(error) {
39
+ switch (true) {
40
+ case error.includes('violates PodSecurity'): {
41
+ const match = error.match(/\"(.*?)\"/gi);
42
+ const name = match[0];
43
+ const policy = match[1];
44
+
45
+ return {
46
+ message: `Pod ${ name } Security Policy Violation ${ policy }`,
47
+ icon: 'icon-pod_security'
48
+ };
49
+ }
50
+
51
+ default:
52
+ break;
53
+ }
54
+ },
55
+
56
+ /**
57
+ * Map all the error texts to a message and icon object
58
+ */
59
+ getErrorsMap(errors) {
60
+ return !errors || !Array.isArray(errors) ? {} : errors.reduce((acc, error) => ({
61
+ ...acc,
62
+ [error]: this.mapError(error) || {
63
+ message: error,
64
+ icon: null
65
+ }
66
+ }), {});
31
67
  }
32
68
  }
33
69
  };
@@ -49,6 +85,7 @@ export default {
49
85
  :subtypes="workloadSubTypes"
50
86
  :apply-hooks="applyHooks"
51
87
  :value="value"
88
+ :errors-map="getErrorsMap(fvUnreportedValidationErrors)"
52
89
  @finish="save"
53
90
  @select-type="selectType"
54
91
  @error="e=>errors = e"
@@ -108,6 +145,7 @@ export default {
108
145
  </div>
109
146
  </div>
110
147
  <Tabbed
148
+ ref="containersTabbed"
111
149
  class="deployment-tabs"
112
150
  :show-tabs-add-remove="true"
113
151
  :default-tab="defaultTab"
@@ -116,9 +154,9 @@ export default {
116
154
  >
117
155
  <Tab
118
156
  v-for="(tab, i) in allContainers"
119
- :key="i"
157
+ :key="tab[idKey]"
120
158
  :label="tab.name"
121
- :name="tab.name"
159
+ :name="tab[idKey]"
122
160
  :weight="tab.weight"
123
161
  :error="!!tab.error"
124
162
  >
@@ -160,11 +198,11 @@ export default {
160
198
  <div class="col span-6">
161
199
  <RadioGroup
162
200
  :mode="mode"
163
- :value="isInitContainer"
201
+ :value="allContainers[i]._init"
164
202
  name="initContainer"
165
203
  :options="[true, false]"
166
204
  :labels="[t('workload.container.init'), t('workload.container.standard')]"
167
- @input="updateInitContainer"
205
+ @input="updateInitContainer($event, allContainers[i])"
168
206
  />
169
207
  </div>
170
208
  </div>
@@ -206,7 +244,16 @@ export default {
206
244
  </div>
207
245
  <div class="spacer" />
208
246
  <div>
209
- <h3>{{ t('workload.container.titles.ports') }}</h3>
247
+ <h3>
248
+ {{ t('workload.container.ports.expose') }}
249
+ <i
250
+ v-tooltip="t('workload.container.ports.toolTip')"
251
+ class="icon icon-info"
252
+ />
253
+ </h3>
254
+ <p class="padded">
255
+ {{ t('workload.container.ports.description') }}
256
+ </p>
210
257
  <div class="row">
211
258
  <WorkloadPorts
212
259
  v-model="allContainers[i].ports"
@@ -260,7 +307,7 @@ export default {
260
307
  </Tab>
261
308
 
262
309
  <Tab
263
- v-if="!isInitContainer"
310
+ v-if="!allContainers[i]._init"
264
311
  :label="t('workload.container.titles.healthCheck')"
265
312
  name="healthCheck"
266
313
  :weight="tabWeightMap['healthCheck']"
@@ -528,7 +575,7 @@ export default {
528
575
  class="btn-sm role-link"
529
576
  @click="addContainerBtn"
530
577
  >
531
- <i class="icon icon-plus icon-lg" /> {{ t('workload.container.addContainer') }}
578
+ <i class="icon icon-plus pr-5" /> {{ t('workload.container.addContainer') }}
532
579
  </button>
533
580
  </li>
534
581
  </template>
@@ -597,4 +644,7 @@ export default {
597
644
  margin-bottom: 10px;
598
645
  }
599
646
  }
647
+ .padded {
648
+ padding-bottom: 10px;
649
+ }
600
650
  </style>