@rancher/shell 0.1.1 → 0.1.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 (294) hide show
  1. package/assets/translations/en-us.yaml +33 -769
  2. package/assets/translations/zh-hans.yaml +153 -781
  3. package/components/ActionMenu.vue +3 -3
  4. package/components/CodeMirror.vue +6 -8
  5. package/components/CommunityLinks.vue +1 -1
  6. package/components/ContainerResourceLimit.vue +14 -0
  7. package/components/ExplorerMembers.vue +123 -0
  8. package/components/ExplorerProjectsNamespaces.vue +405 -0
  9. package/components/GrafanaDashboard.vue +17 -2
  10. package/components/LocaleSelector.vue +81 -0
  11. package/components/PromptModal.vue +2 -3
  12. package/components/ResourceList/index.vue +1 -1
  13. package/components/ResourceTable.vue +3 -6
  14. package/components/SingleClusterInfo.vue +1 -1
  15. package/components/SortableTable/index.vue +23 -20
  16. package/components/SortableTable/selection.js +1 -0
  17. package/components/auth/AzureWarning.vue +5 -1
  18. package/components/auth/Principal.vue +1 -1
  19. package/components/auth/RoleDetailEdit.vue +32 -12
  20. package/components/fleet/FleetRepos.vue +0 -2
  21. package/components/form/NameNsDescription.vue +4 -6
  22. package/components/form/NodeScheduling.vue +1 -1
  23. package/components/form/ResourceTabs/index.vue +27 -18
  24. package/components/form/WorkloadPorts.vue +1 -1
  25. package/components/formatter/ClusterLink.vue +13 -0
  26. package/components/formatter/PodImages.vue +11 -1
  27. package/components/formatter/RKETemplateName.vue +37 -0
  28. package/components/formatter/WorkloadHealthScale.vue +1 -1
  29. package/components/nav/Header.vue +9 -9
  30. package/components/nav/NamespaceFilter.vue +7 -4
  31. package/components/nav/TopLevelMenu.vue +6 -43
  32. package/components/nav/WindowManager/ContainerLogs.vue +1 -1
  33. package/config/product/harvester-manager.js +64 -2
  34. package/config/product/manager.js +9 -0
  35. package/config/settings.js +17 -71
  36. package/config/table-headers.js +0 -1
  37. package/config/types.js +8 -26
  38. package/core/plugin-routes.ts +34 -22
  39. package/core/plugin.ts +15 -3
  40. package/core/plugins-loader.js +2 -0
  41. package/core/plugins.js +79 -36
  42. package/core/types.ts +7 -1
  43. package/creators/app/tsconfig.json +6 -1
  44. package/creators/pkg/init +3 -0
  45. package/creators/pkg/tsconfig.json +7 -2
  46. package/detail/provisioning.cattle.io.cluster.vue +23 -0
  47. package/detail/workload/index.vue +11 -5
  48. package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
  49. package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
  50. package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
  51. package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
  52. package/{components/dialog → dialog}/DrainNode.vue +0 -0
  53. package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
  54. package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
  55. package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
  56. package/{components/dialog → dialog}/RotateCertificatesDialog.vue +0 -0
  57. package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
  58. package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
  59. package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
  60. package/edit/auth/azuread.vue +20 -1
  61. package/edit/cloudcredential.vue +7 -1
  62. package/edit/management.cattle.io.project.vue +2 -2
  63. package/edit/namespace.vue +17 -10
  64. package/edit/networking.k8s.io.ingress/index.vue +2 -1
  65. package/edit/persistentvolumeclaim.vue +33 -2
  66. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
  67. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +34 -6
  68. package/edit/provisioning.cattle.io.cluster/index.vue +1 -1
  69. package/edit/provisioning.cattle.io.cluster/rke2.vue +21 -6
  70. package/edit/service.vue +1 -1
  71. package/edit/workload/index.vue +363 -15
  72. package/edit/workload/mixins/workload.js +62 -7
  73. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
  74. package/layouts/default.vue +52 -27
  75. package/layouts/error.vue +5 -1
  76. package/layouts/home.vue +6 -2
  77. package/list/harvesterhci.io.management.cluster.vue +74 -33
  78. package/list/namespace.vue +3 -5
  79. package/list/provisioning.cattle.io.cluster.vue +6 -0
  80. package/machine-config/amazonec2.vue +2 -0
  81. package/machine-config/harvester.vue +96 -49
  82. package/middleware/authenticated.js +56 -52
  83. package/mixins/brand.js +3 -4
  84. package/mixins/create-edit-view/impl.js +0 -8
  85. package/mixins/form-validation.js +1 -1
  86. package/mixins/resource-fetch.js +3 -1
  87. package/models/chart.js +1 -1
  88. package/models/cluster/node.js +12 -1
  89. package/models/fleet.cattle.io.bundle.js +26 -19
  90. package/models/harvesterhci.io.management.cluster.js +194 -5
  91. package/models/management.cattle.io.cluster.js +1 -1
  92. package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
  93. package/models/management.cattle.io.globalrole.js +0 -19
  94. package/models/management.cattle.io.project.js +23 -2
  95. package/models/management.cattle.io.roletemplate.js +2 -21
  96. package/models/namespace.js +19 -3
  97. package/models/pod.js +19 -2
  98. package/models/provisioning.cattle.io.cluster.js +71 -0
  99. package/models/service.js +5 -1
  100. package/models/workload.js +4 -243
  101. package/models/workload.service.js +314 -0
  102. package/nuxt.config.js +14 -12
  103. package/package.json +3 -3
  104. package/pages/auth/login.vue +11 -2
  105. package/pages/auth/setup.vue +1 -1
  106. package/pages/c/_cluster/_product/members/index.vue +3 -93
  107. package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
  108. package/pages/c/_cluster/apps/charts/install.vue +0 -6
  109. package/pages/c/_cluster/settings/performance.vue +19 -16
  110. package/pages/fail-whale.vue +1 -10
  111. package/pages/index.vue +18 -4
  112. package/pages/plugins.vue +2 -2
  113. package/pages/prefs.vue +8 -6
  114. package/pkg/auto-import.js +44 -7
  115. package/pkg/dynamic-plugin-loader.js +28 -0
  116. package/pkg/import.js +2 -2
  117. package/pkg/model-loader-require.lib.js +3 -0
  118. package/pkg/vue.config.js +9 -6
  119. package/plugins/console.js +10 -5
  120. package/plugins/dashboard-store/actions.js +8 -3
  121. package/plugins/dashboard-store/getters.js +7 -2
  122. package/plugins/dashboard-store/model-loader-require.js +12 -0
  123. package/plugins/dashboard-store/model-loader.js +4 -1
  124. package/plugins/dashboard-store/resource-class.js +10 -3
  125. package/plugins/steve/actions.js +1 -1
  126. package/plugins/steve/index.js +6 -4
  127. package/plugins/steve/steve-description-class.js +32 -0
  128. package/plugins/steve/subscribe.js +34 -23
  129. package/rancher-components/Banner/Banner.vue +2 -2
  130. package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
  131. package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
  132. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +0 -2
  133. package/rancher-components/Form/LabeledInput/LabeledInput.vue +2 -0
  134. package/rancher-components/Form/Radio/RadioButton.vue +14 -1
  135. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
  136. package/{components/form → rancher-components/Form/ToggleSwitch}/ToggleSwitch.vue +18 -8
  137. package/rancher-components/Form/ToggleSwitch/index.ts +1 -0
  138. package/rancher-components/Form/index.ts +1 -0
  139. package/scripts/build-pkg.sh +48 -2
  140. package/scripts/drone-build-pkg.sh +31 -0
  141. package/scripts/publish-shell.sh +10 -11
  142. package/scripts/serve-pkgs +17 -10
  143. package/scripts/test-plugins-build.sh +18 -1
  144. package/store/catalog.js +3 -1
  145. package/store/i18n.js +16 -11
  146. package/store/index.js +4 -181
  147. package/store/prefs.js +30 -2
  148. package/store/type-map.js +16 -29
  149. package/types/{index.d.ts → rancher/index.d.ts} +0 -0
  150. package/utils/cluster.js +1 -1
  151. package/utils/custom-validators.js +1 -12
  152. package/utils/dynamic-importer.js +1 -1
  153. package/utils/validators/setting.js +0 -35
  154. package/components/FilterLabel.vue +0 -254
  155. package/components/HarvesterUpgradeProgressBarList.vue +0 -109
  156. package/components/VMConsoleBar.vue +0 -87
  157. package/components/dialog/harvester/AddHotplugModal.vue +0 -159
  158. package/components/dialog/harvester/BackupModal.vue +0 -117
  159. package/components/dialog/harvester/CloneTemplate.vue +0 -125
  160. package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
  161. package/components/dialog/harvester/ExportImageDialog.vue +0 -152
  162. package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
  163. package/components/dialog/harvester/MigrationDialog.vue +0 -154
  164. package/components/dialog/harvester/RestoreDialog.vue +0 -153
  165. package/components/dialog/harvester/SupportBundle.vue +0 -217
  166. package/components/dialog/harvester/UnplugVolume.vue +0 -108
  167. package/components/form/SerialConsole/index.vue +0 -267
  168. package/components/formatter/AttachVMWithName.vue +0 -46
  169. package/components/formatter/CloudInitType.vue +0 -27
  170. package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
  171. package/components/formatter/HarvesterCPUUsed.vue +0 -122
  172. package/components/formatter/HarvesterDiskState.vue +0 -66
  173. package/components/formatter/HarvesterHostName.vue +0 -66
  174. package/components/formatter/HarvesterIpAddress.vue +0 -90
  175. package/components/formatter/HarvesterMemoryUsed.vue +0 -140
  176. package/components/formatter/HarvesterMigrationState.vue +0 -85
  177. package/components/formatter/HarvesterNodeName.vue +0 -49
  178. package/components/formatter/HarvesterStorageUsed.vue +0 -194
  179. package/components/formatter/HarvesterVmState.vue +0 -123
  180. package/components/nav/HarvesterUpgrade.vue +0 -232
  181. package/components/novnc/NovncConsole.vue +0 -93
  182. package/components/novnc/NovncConsoleItem.vue +0 -89
  183. package/components/novnc/NovncConsoleWrapper.vue +0 -243
  184. package/config/harvester-map.js +0 -44
  185. package/config/harvester-table-headers.js +0 -27
  186. package/config/product/harvester.js +0 -305
  187. package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
  188. package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
  189. package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
  190. package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
  191. package/detail/harvesterhci.io.host/index.vue +0 -243
  192. package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
  193. package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
  194. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
  195. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
  196. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
  197. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
  198. package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
  199. package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
  200. package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
  201. package/edit/harvesterhci.io.host/index.vue +0 -533
  202. package/edit/harvesterhci.io.keypair.vue +0 -112
  203. package/edit/harvesterhci.io.managedchart/index.vue +0 -25
  204. package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
  205. package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
  206. package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
  207. package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
  208. package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
  209. package/edit/harvesterhci.io.setting/index.vue +0 -201
  210. package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
  211. package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
  212. package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
  213. package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
  214. package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
  215. package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
  216. package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
  217. package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
  218. package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
  219. package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
  220. package/edit/harvesterhci.io.volume.vue +0 -195
  221. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
  222. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
  223. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
  224. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
  225. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
  226. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
  227. package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
  228. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
  229. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
  230. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
  231. package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
  232. package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
  233. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
  234. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
  235. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
  236. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
  237. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
  238. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
  239. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
  240. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
  241. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
  242. package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
  243. package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
  244. package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
  245. package/edit/workload/types/Deployment.vue +0 -377
  246. package/edit/workload/types/Generic.vue +0 -295
  247. package/list/harvesterhci.io.cloudtemplate.vue +0 -78
  248. package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
  249. package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
  250. package/list/harvesterhci.io.dashboard/index.vue +0 -752
  251. package/list/harvesterhci.io.host/index.vue +0 -186
  252. package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
  253. package/list/harvesterhci.io.setting.vue +0 -241
  254. package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
  255. package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
  256. package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
  257. package/list/harvesterhci.io.volume.vue +0 -122
  258. package/list/kubevirt.io.virtualmachine.vue +0 -193
  259. package/mixins/harvester-vm/impl.js +0 -267
  260. package/mixins/harvester-vm/index.js +0 -1357
  261. package/models/harvester/configmap.js +0 -32
  262. package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
  263. package/models/harvester/harvesterhci.io.keypair.js +0 -12
  264. package/models/harvester/harvesterhci.io.setting.js +0 -127
  265. package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
  266. package/models/harvester/harvesterhci.io.upgrade.js +0 -226
  267. package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
  268. package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
  269. package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
  270. package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
  271. package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
  272. package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
  273. package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
  274. package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
  275. package/models/harvester/management.cattle.io.managedchart.js +0 -191
  276. package/models/harvester/management.cattle.io.setting.js +0 -40
  277. package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
  278. package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
  279. package/models/harvester/node.js +0 -255
  280. package/models/harvester/persistentvolumeclaim.js +0 -166
  281. package/models/harvester/pod.js +0 -185
  282. package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
  283. package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
  284. package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
  285. package/pages/c/_cluster/harvester/index.vue +0 -24
  286. package/pages/c/_cluster/harvester/support/index.vue +0 -154
  287. package/pkg/model-loader.lib.js +0 -3
  288. package/plugins/lookup.js +0 -50
  289. package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
  290. package/store/harvester-common.js +0 -126
  291. package/utils/validators/vm-datavolumes.js +0 -38
  292. package/utils/validators/vm-image.js +0 -32
  293. package/utils/validators/vm.js +0 -221
  294. package/yarn-error.log +0 -196
@@ -1,16 +1,12 @@
1
1
  <script>
2
- import WorkloadGeneric from './types/Generic';
3
- import WorkloadDeployment from './types/Deployment';
4
-
2
+ import CreateEditView from '@shell/mixins/create-edit-view';
3
+ import FormValidation from '@shell/mixins/form-validation';
5
4
  import WorkLoadMixin from '@shell/edit/workload/mixins/workload';
6
5
 
7
6
  export default {
8
- name: 'CruWorkload',
9
- components: {
10
- WorkloadGeneric,
11
- WorkloadDeployment
12
- },
13
- props: {
7
+ name: 'WorkloadDeployments',
8
+ mixins: [CreateEditView, FormValidation, WorkLoadMixin], // The order here is important since WorkLoadMixin contains some FormValidation configuration
9
+ props: {
14
10
  value: {
15
11
  type: Object,
16
12
  required: true,
@@ -21,14 +17,366 @@ export default {
21
17
  default: 'create',
22
18
  },
23
19
  },
24
- mixins: [WorkLoadMixin],
20
+ data() {
21
+ return { selectedName: null };
22
+ },
23
+ methods: {
24
+ changed(tab) {
25
+ this.selectedName = tab.selectedName;
26
+ const container = this.containerOptions.find( c => c.name === tab.selectedName);
27
+
28
+ if ( container ) {
29
+ this.selectContainer(container);
30
+ }
31
+ }
32
+ }
25
33
  };
26
34
  </script>
27
35
 
28
36
  <template>
29
- <div>
30
- <Loading v-if="$fetchState.pending" />
31
- <WorkloadDeployment v-else-if="isDeployment" :mode="mode" :value="value" />
32
- <WorkloadGeneric v-else :mode="mode" :value="value" />
33
- </div>
37
+ <Loading v-if="$fetchState.pending" />
38
+ <form v-else class="filled-height">
39
+ <CruResource
40
+ :validation-passed="fvFormIsValid"
41
+ :selected-subtype="type"
42
+ :resource="value"
43
+ :mode="mode"
44
+ :errors="fvUnreportedValidationErrors"
45
+ :done-route="doneRoute"
46
+ :subtypes="workloadSubTypes"
47
+ :apply-hooks="applyHooks"
48
+ :value="value"
49
+ @finish="save"
50
+ @select-type="selectType"
51
+ @error="e=>errors = e"
52
+ >
53
+ <!-- <pre>{{ JSON.stringify(allContainers, null, 2) }}</pre> -->
54
+ <NameNsDescription
55
+ :value="value"
56
+ :mode="mode"
57
+ :rules="{name: fvGetAndReportPathRules('metadata.name'), namespace: fvGetAndReportPathRules('metadata.namespace'), description: []}"
58
+ @change="name=value.metadata.name"
59
+ />
60
+ <div v-if="isCronJob || isReplicable || isStatefulSet || containerOptions.length > 1" class="row mb-20">
61
+ <div v-if="isCronJob" class="col span-3">
62
+ <LabeledInput
63
+ v-model="spec.schedule"
64
+ type="cron"
65
+ required
66
+ :mode="mode"
67
+ :label="t('workload.cronSchedule')"
68
+ :rules="fvGetAndReportPathRules('spec.schedule')"
69
+ placeholder="0 * * * *"
70
+ />
71
+ </div>
72
+ <div v-if="isReplicable" class="col span-3">
73
+ <LabeledInput
74
+ v-model.number="spec.replicas"
75
+ type="number"
76
+ min="0"
77
+ required
78
+ :mode="mode"
79
+ :label="t('workload.replicas')"
80
+ />
81
+ </div>
82
+ <div v-if="isStatefulSet" class="col span-3">
83
+ <LabeledSelect
84
+ v-model="spec.serviceName"
85
+ option-label="metadata.name"
86
+ :reduce="service=>service.metadata.name"
87
+ :mode="mode"
88
+ :label="t('workload.serviceName')"
89
+ :options="headlessServices"
90
+ required
91
+ />
92
+ </div>
93
+ </div>
94
+ <Tabbed class="deployment-tabs" :show-tabs-add-remove="true" :default-tab="defaultTab" @changed="changed">
95
+ <Tab
96
+ v-for="(tab, i) in allContainers"
97
+ :key="i+tab.name"
98
+ :label="tab.name"
99
+ :name="tab.name"
100
+ :weight="tab.weight"
101
+ :error="!!tab.error"
102
+ >
103
+ <Tabbed :side-tabs="true" :weight="99">
104
+ <Tab :label="t('workload.container.titles.general')" name="general" :weight="tabWeightMap['general']" :error="tabErrors.general">
105
+ <template #tab-header-right class="tab-content-controls">
106
+ <button v-if="allContainers.length > 1 && !isView" type="button" class="btn-sm role-link" @click="removeContainer(tab)">
107
+ {{ t('workload.container.removeContainer') }}
108
+ </button>
109
+ </template>
110
+ <div>
111
+ <div :style="{'align-items':'center'}" class="row mb-20">
112
+ <div class="col span-6">
113
+ <LabeledInput v-model="container.name" :mode="mode" :label="t('workload.container.containerName')" />
114
+ </div>
115
+ <div class="col span-6">
116
+ <RadioGroup
117
+ :mode="mode"
118
+ :value="isInitContainer"
119
+ name="initContainer"
120
+ :options="[true, false]"
121
+ :labels="[t('workload.container.init'), t('workload.container.standard')]"
122
+ @input="updateInitContainer"
123
+ />
124
+ </div>
125
+ </div>
126
+ <h3>{{ t('workload.container.titles.image') }}</h3>
127
+ <div class="row mb-20">
128
+ <div class="col span-6">
129
+ <LabeledInput
130
+ v-model.trim="container.image"
131
+ :mode="mode"
132
+ :label="t('workload.container.image')"
133
+ :placeholder="t('generic.placeholder', {text: 'nginx:latest'}, true)"
134
+ :rules="fvGetAndReportPathRules('image')"
135
+ />
136
+ </div>
137
+ <div class="col span-6">
138
+ <LabeledSelect
139
+ v-model="container.imagePullPolicy"
140
+ :label="t('workload.container.imagePullPolicy')"
141
+ :options="pullPolicyOptions"
142
+ :mode="mode"
143
+ />
144
+ </div>
145
+ </div>
146
+ <div class="row">
147
+ <div class="col span-6">
148
+ <LabeledSelect
149
+ v-model="imagePullSecrets"
150
+ :label="t('workload.container.imagePullSecrets')"
151
+ :multiple="true"
152
+ :taggable="true"
153
+ :options="imagePullNamespacedSecrets"
154
+ :mode="mode"
155
+ option-label="metadata.name"
156
+ :reduce="service=>service.metadata.name"
157
+ :create-option="createOption"
158
+ />
159
+ </div>
160
+ </div>
161
+ </div>
162
+ <div class="spacer" />
163
+ <div>
164
+ <h3>{{ t('workload.container.titles.ports') }}</h3>
165
+ <div class="row">
166
+ <WorkloadPorts v-model="allContainers[i].ports" :name="value.metadata.name" :services="servicesOwned" :mode="mode" />
167
+ </div>
168
+ </div>
169
+ <div class="spacer" />
170
+ <div>
171
+ <h3>{{ t('workload.container.titles.command') }}</h3>
172
+ <Command v-model="allContainers[i]" :secrets="namespacedSecrets" :config-maps="namespacedConfigMaps" :mode="mode" />
173
+ </div>
174
+ <ServiceNameSelect
175
+ :value="podTemplateSpec.serviceAccountName"
176
+ :mode="mode"
177
+ :select-label="t('workload.serviceAccountName.label')"
178
+ :select-placeholder="t('workload.serviceAccountName.label')"
179
+ :options="namespacedServiceNames"
180
+ option-label="metadata.name"
181
+ @input="updateServiceAccount"
182
+ />
183
+ <div class="spacer" />
184
+ <div>
185
+ <h3>{{ t('workload.container.titles.lifecycle') }}</h3>
186
+ <LifecycleHooks v-model="allContainers[i].lifecycle" :mode="mode" />
187
+ </div>
188
+ </Tab>
189
+ <Tab :label="t('workload.container.titles.resources')" name="resources" :weight="tabWeightMap['resources']">
190
+ <!-- Resources and Limitations -->
191
+ <ContainerResourceLimit v-model="flatResources" :mode="mode" :show-tip="false" />
192
+ </Tab>
193
+
194
+ <Tab v-if="!isInitContainer" :label="t('workload.container.titles.healthCheck')" name="healthCheck" :weight="tabWeightMap['healthCheck']">
195
+ <HealthCheck :value="allContainers[i]" :mode="mode" @input="Object.assign(allContainers[i], $event)" />
196
+ </Tab>
197
+ <Tab :label="t('workload.container.titles.securityContext')" name="securityContext" :weight="tabWeightMap['securityContext']">
198
+ <Security v-model="allContainers[i].securityContext" :mode="mode" />
199
+ </Tab>
200
+ </Tabbed>
201
+ </Tab>
202
+ <Tab v-if="!isPod" :label="nameDisplayFor(type)" :name="nameDisplayFor(type)" :weight="99">
203
+ <Tabbed :side-tabs="true">
204
+ <Tab name="labels" label-key="generic.labelsAndAnnotations" :weight="tabWeightMap['labels']">
205
+ <Labels v-model="value" :mode="mode" />
206
+ </Tab>
207
+ <Tab :label="t('workload.container.titles.upgrading')" name="upgrading" :weight="tabWeightMap['upgrading']">
208
+ <Job v-if="isJob || isCronJob" v-model="spec" :mode="mode" :type="type" />
209
+ <Upgrading v-else v-model="spec" :mode="mode" :type="type" :no-pod-spec="true" />
210
+ </Tab>
211
+ </Tabbed>
212
+ </Tab>
213
+ <Tab :label="t('workload.tabs.labels.pod')" :name="'pod'" :weight="98">
214
+ <Tabbed :side-tabs="true">
215
+ <Tab :label="t('workload.storage.title')" name="storage" :weight="tabWeightMap['storage']">
216
+ <Storage
217
+ v-model="podTemplateSpec"
218
+ :namespace="value.metadata.namespace"
219
+ :register-before-hook="registerBeforeHook"
220
+ :mode="mode"
221
+ :secrets="namespacedSecrets"
222
+ :config-maps="namespacedConfigMaps"
223
+ :container="container"
224
+ :save-pvc-hook-name="savePvcHookName"
225
+ @removePvcForm="clearPvcFormState"
226
+ />
227
+ </Tab>
228
+ <Tab :label="t('workload.container.titles.resources')" name="resources" :weight="tabWeightMap['resources']">
229
+ <template>
230
+ <div>
231
+ <h3 class="mb-10">
232
+ <t k="workload.scheduling.titles.tolerations" />
233
+ </h3>
234
+ <div class="row">
235
+ <Tolerations v-model="podTemplateSpec.tolerations" :mode="mode" />
236
+ </div>
237
+ </div>
238
+
239
+ <div>
240
+ <div class="spacer" />
241
+ <h3 class="mb-10">
242
+ <t k="workload.scheduling.titles.priority" />
243
+ </h3>
244
+ <div class="row">
245
+ <div class="col span-6">
246
+ <LabeledInput v-model.number="podTemplateSpec.priority" :mode="mode" :label="t('workload.scheduling.priority.priority')" />
247
+ </div>
248
+ <div class="col span-6">
249
+ <LabeledInput v-model="podTemplateSpec.priorityClassName" :mode="mode" :label="t('workload.scheduling.priority.className')" />
250
+ </div>
251
+ </div>
252
+ </div>
253
+ </template>
254
+ </Tab>
255
+ <Tab :label="t('workload.container.titles.podScheduling')" name="podScheduling" :weight="tabWeightMap['podScheduling']">
256
+ <PodAffinity :mode="mode" :value="podTemplateSpec" :nodes="allNodeObjects" />
257
+ </Tab>
258
+ <Tab :label="t('workload.container.titles.nodeScheduling')" name="nodeScheduling" :weight="tabWeightMap['nodeScheduling']">
259
+ <NodeScheduling :mode="mode" :value="podTemplateSpec" :nodes="allNodes" />
260
+ </Tab>
261
+ <Tab :label="t('workload.container.titles.upgrading')" name="upgrading" :weight="tabWeightMap['upgrading']">
262
+ <Job v-if="isJob || isCronJob" v-model="spec" :mode="mode" :type="type" />
263
+ <Upgrading v-else v-model="spec" :mode="mode" :type="type" :no-deployment-spec="true" />
264
+ </Tab>
265
+ <Tab :label="t('workload.container.titles.securityContext')" name="securityContext" :weight="tabWeightMap['securityContext']">
266
+ <div>
267
+ <h3>{{ t('workload.container.security.podFsGroup') }}</h3>
268
+ <div class="row">
269
+ <div class="col span-6">
270
+ <LabeledInput v-model.number="podFsGroup" type="number" :mode="mode" :label="t('workload.container.security.fsGroup')" />
271
+ </div>
272
+ </div>
273
+ </div>
274
+ </Tab>
275
+ <Tab :label="t('workload.container.titles.networking')" name="networking" :weight="tabWeightMap['networking']">
276
+ <Networking v-model="podTemplateSpec" :mode="mode" />
277
+ </Tab>
278
+ <Tab v-if="isStatefulSet" :label="t('workload.container.titles.volumeClaimTemplates')" name="volumeClaimTemplates" :weight="tabWeightMap['volumeClaimTemplates']">
279
+ <VolumeClaimTemplate v-model="spec" :mode="mode" />
280
+ </Tab>
281
+ <Tab name="labels" label-key="generic.labelsAndAnnotations" :weight="tabWeightMap['labels']">
282
+ <div>
283
+ <h3>{{ t('workload.container.titles.podLabels') }}</h3>
284
+ <div class="row mb-20">
285
+ <KeyValue
286
+ key="labels"
287
+ v-model="podLabels"
288
+ :add-label="t('labels.addLabel')"
289
+ :mode="mode"
290
+ :read-allowed="false"
291
+ :protip="false"
292
+ />
293
+ </div>
294
+ <div class="spacer" />
295
+ <h3>{{ t('workload.container.titles.podAnnotations') }}</h3>
296
+ <div class="row">
297
+ <KeyValue
298
+ key="annotations"
299
+ v-model="podAnnotations"
300
+ :add-label="t('labels.addAnnotation')"
301
+ :mode="mode"
302
+ :read-allowed="false"
303
+ :protip="false"
304
+ />
305
+ </div>
306
+ </div>
307
+ </Tab>
308
+ </Tabbed>
309
+ </Tab>
310
+ <template #tab-row-extras>
311
+ <li class="tablist-controls">
312
+ <button v-if="!isView" type="button" class="btn-sm role-link" @click="addContainerBtn">
313
+ <i class="icon icon-plus icon-lg" /> {{ t('workload.container.addContainer') }}
314
+ </button>
315
+ </li>
316
+ </template>
317
+ </Tabbed>
318
+ </CruResource>
319
+ </form>
34
320
  </template>
321
+
322
+ <style lang='scss'>
323
+ .container-row {
324
+ display: flex;
325
+ align-items: center;
326
+ margin-bottom: 20px;
327
+ }
328
+
329
+ .type-placeholder {
330
+ color: white;
331
+ font-size: 2.5em;
332
+ height: 100%;
333
+ width: 100%;
334
+ background-color: var(--primary);
335
+ display: flex;
336
+ justify-content: center;
337
+ align-items: center;
338
+ }
339
+
340
+ .type-description {
341
+ color: var(--input-label);
342
+ }
343
+
344
+ .next-dropdown {
345
+ display: inline-block;
346
+ }
347
+
348
+ .tab-external-controls {
349
+ display: flex;
350
+ justify-content: right;
351
+ }
352
+
353
+ .tab-content-controls {
354
+ display: flex;
355
+ justify-content: right;
356
+ }
357
+
358
+ .tablist-controls {
359
+ .role-link {
360
+ padding: 10px 15px;
361
+ min-height: unset;
362
+ line-height: unset;
363
+
364
+ &:focus {
365
+ background: none;
366
+ box-shadow: none;
367
+ }
368
+
369
+ &:hover {
370
+ border: none;
371
+ }
372
+ }
373
+
374
+ }
375
+
376
+ .deployment-tabs {
377
+ > .tabs.horizontal {
378
+ border-bottom: 1px solid var(--border);
379
+ margin-bottom: 10px;
380
+ }
381
+ }
382
+ </style>
@@ -43,6 +43,7 @@ import { removeObject } from '@shell/utils/array';
43
43
  import { BEFORE_SAVE_HOOKS } from '@shell/mixins/child-hook';
44
44
  import NameNsDescription from '@shell/components/form/NameNsDescription';
45
45
  import formRulesGenerator from '@shell/utils/validators/formRules';
46
+ import { TYPES as SECRET_TYPES } from '@shell/models/secret';
46
47
 
47
48
  const TAB_WEIGHT_MAP = {
48
49
  general: 99,
@@ -102,6 +103,15 @@ export default {
102
103
  type: String,
103
104
  default: 'create',
104
105
  },
106
+
107
+ createOption: {
108
+ default: (text) => {
109
+ if (text) {
110
+ return { metadata: { name: text } };
111
+ }
112
+ },
113
+ type: Function
114
+ },
105
115
  },
106
116
 
107
117
  async fetch() {
@@ -138,6 +148,7 @@ export default {
138
148
  },
139
149
 
140
150
  data() {
151
+ let defaultTab;
141
152
  let type = this.$route.params.resource;
142
153
  const createSidecar = !!this.$route.query.sidecar;
143
154
  const isInitContainer = !!this.$route.query.init;
@@ -148,21 +159,48 @@ export default {
148
159
 
149
160
  if (!this.value.spec) {
150
161
  this.value.spec = {};
162
+ if (this.value.type === WORKLOAD_TYPES.POD) {
163
+ const podContainers = [{
164
+ imagePullPolicy: 'Always',
165
+ name: `container-0`,
166
+ }];
167
+
168
+ defaultTab = 'container-0';
169
+
170
+ const podSpec = { template: { spec: { containers: podContainers, initContainers: [] } } };
171
+
172
+ this.$set(this.value, 'spec', podSpec);
173
+ }
174
+ }
175
+
176
+ if (this.mode === _CREATE) {
177
+ defaultTab = 'container-0';
178
+ }
179
+
180
+ if ((this.mode === _EDIT || this.mode === _VIEW ) && this.value.type === 'pod' ) {
181
+ const podSpec = { ...this.value.spec };
182
+
183
+ this.$set(this.value.spec, 'template', { spec: podSpec });
151
184
  }
152
185
 
153
186
  const spec = this.value.spec;
187
+ let podTemplateSpec = type === WORKLOAD_TYPES.CRON_JOB ? spec.jobTemplate.spec.template.spec : spec?.template?.spec;
188
+
189
+ let containers = podTemplateSpec.containers || [];
154
190
  let container;
155
- const podTemplateSpec =
156
- type === WORKLOAD_TYPES.CRON_JOB ? spec.jobTemplate.spec.template.spec : spec?.template?.spec;
157
- let containers = podTemplateSpec.containers;
191
+
192
+ if (this.mode === _VIEW && this.value.type === 'pod' ) {
193
+ podTemplateSpec = spec;
194
+ }
158
195
 
159
196
  if (
160
197
  this.mode === _CREATE ||
161
198
  this.mode === _VIEW ||
162
- (!createSidecar && !this.value.hasSidecars)
199
+ (!createSidecar && !this.value.hasSidecars) // hasSideCars = containers.length > 1 || initContainers.length;
163
200
  ) {
164
201
  container = containers[0];
165
202
  } else {
203
+ // This means that there are no containers.
166
204
  if (!podTemplateSpec.initContainers) {
167
205
  podTemplateSpec.initContainers = [];
168
206
  }
@@ -176,13 +214,18 @@ export default {
176
214
  imagePullPolicy: 'Always',
177
215
  name: `container-${ allContainers.length }`,
178
216
  });
217
+ defaultTab = 'container-0';
218
+
179
219
  containers = podTemplateSpec.initContainers;
180
220
  }
181
- if (createSidecar) {
221
+ if (createSidecar || this.value.type === 'pod') {
182
222
  container = {
183
223
  imagePullPolicy: 'Always',
184
224
  name: `container-${ allContainers.length }`,
185
225
  };
226
+
227
+ defaultTab = 'container-0';
228
+
186
229
  containers.push(container);
187
230
  } else {
188
231
  container = containers[0];
@@ -217,7 +260,9 @@ export default {
217
260
  fvFormRuleSets: [{
218
261
  path: 'image', rootObject: this.container, rules: ['required'], translationKey: 'workload.container.image'
219
262
  }],
220
- fvReportedValidationPaths: ['spec']
263
+ fvReportedValidationPaths: ['spec'],
264
+ defaultTab
265
+
221
266
  };
222
267
  },
223
268
 
@@ -251,6 +296,10 @@ export default {
251
296
  return this.type === WORKLOAD_TYPES.DEPLOYMENT;
252
297
  },
253
298
 
299
+ isPod() {
300
+ return this.value.type === WORKLOAD_TYPES.POD;
301
+ },
302
+
254
303
  isStatefulSet() {
255
304
  return this.type === WORKLOAD_TYPES.STATEFUL_SET;
256
305
  },
@@ -430,6 +479,12 @@ export default {
430
479
  }
431
480
  },
432
481
 
482
+ imagePullNamespacedSecrets() {
483
+ const namespace = this.value?.metadata?.namespace;
484
+
485
+ return this.allSecrets.filter(secret => secret.metadata.namespace === namespace && (secret._type === SECRET_TYPES.DOCKER || secret._type === SECRET_TYPES.DOCKER_JSON));
486
+ },
487
+
433
488
  namespacedConfigMaps() {
434
489
  const namespace = this.value?.metadata?.namespace;
435
490
 
@@ -882,7 +937,7 @@ export default {
882
937
  }
883
938
  },
884
939
  nvidiaIsValid(nvidiaGpuLimit) {
885
- if (!Number.isInteger(nvidiaGpuLimit)) {
940
+ if ( !Number.isInteger(parseInt(nvidiaGpuLimit)) ) {
886
941
  return false;
887
942
  }
888
943
  if (nvidiaGpuLimit === undefined) {
@@ -209,6 +209,7 @@ export default {
209
209
  :label="t('persistentVolumeClaim.capacity')"
210
210
  :increment="1024"
211
211
  :input-exponent="3"
212
+ :required="true"
212
213
  :output-modifier="true"
213
214
  />
214
215
  </div>