@rancher/shell 0.5.2 → 1.2.0

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 (338) hide show
  1. package/.DS_Store +0 -0
  2. package/assets/images/providers/aks-black.svg +28 -0
  3. package/assets/images/providers/aks.svg +31 -0
  4. package/assets/styles/global/_labeled-input.scss +1 -0
  5. package/assets/styles/global/_layout.scss +0 -99
  6. package/assets/translations/en-us.yaml +77 -71
  7. package/assets/translations/zh-hans.yaml +25 -23
  8. package/babel.config.js +1 -7
  9. package/chart/gatekeeper.vue +11 -2
  10. package/chart/istio.vue +10 -1
  11. package/chart/logging/index.vue +11 -2
  12. package/chart/monitoring/alerting/index.vue +21 -7
  13. package/chart/monitoring/grafana/index.vue +2 -57
  14. package/chart/monitoring/index.vue +26 -52
  15. package/chart/monitoring/prometheus/index.vue +43 -37
  16. package/chart/rancher-backup/index.vue +10 -3
  17. package/cloud-credential/azure.vue +17 -4
  18. package/components/AsyncButton.vue +0 -9
  19. package/components/Carousel.vue +0 -1
  20. package/components/ChartPsp.vue +76 -0
  21. package/components/CodeMirror.vue +21 -19
  22. package/components/CopyCode.vue +2 -6
  23. package/components/CopyToClipboard.vue +1 -2
  24. package/components/CopyToClipboardText.vue +9 -14
  25. package/components/CruResource.vue +0 -1
  26. package/components/EtcdInfoBanner.vue +5 -5
  27. package/components/ExplorerProjectsNamespaces.vue +1 -25
  28. package/components/IconOrSvg.vue +1 -1
  29. package/components/Markdown.vue +12 -16
  30. package/components/Questions/index.vue +1 -1
  31. package/components/ResourceDetail/Masthead.vue +9 -25
  32. package/components/ResourceList/Masthead.vue +18 -1
  33. package/components/ResourceTable.vue +2 -14
  34. package/components/ResourceYaml.vue +0 -5
  35. package/components/SideNav.vue +1 -1
  36. package/components/SortableTable/THead.vue +9 -7
  37. package/components/SortableTable/index.vue +3 -2
  38. package/components/StatusTable.vue +1 -5
  39. package/components/TabTitle.vue +84 -0
  40. package/components/Tabbed/index.vue +0 -12
  41. package/components/__tests__/ChartPsp.test.ts +75 -0
  42. package/components/__tests__/CopyCode.test.ts +4 -5
  43. package/components/fleet/FleetBundles.vue +11 -5
  44. package/components/fleet/FleetRepos.vue +27 -62
  45. package/components/fleet/FleetResources.vue +1 -6
  46. package/components/fleet/FleetStatus.vue +3 -3
  47. package/components/fleet/FleetSummary.vue +30 -35
  48. package/components/form/ArrayList.vue +8 -1
  49. package/components/form/ArrayListSelect.vue +9 -9
  50. package/components/form/KeyValue.vue +0 -1
  51. package/components/form/LabeledSelect.vue +0 -4
  52. package/components/form/Password.vue +1 -3
  53. package/components/form/Select.vue +1 -1
  54. package/components/form/SelectOrCreateAuthSecret.vue +4 -4
  55. package/components/form/__tests__/KeyValue.test.ts +1 -1
  56. package/components/formatter/Checked.vue +3 -11
  57. package/components/formatter/ClusterProvider.vue +18 -1
  58. package/components/formatter/FleetSummaryGraph.vue +11 -23
  59. package/components/formatter/LiveDate.vue +16 -0
  60. package/components/formatter/LiveDuration.vue +1 -1
  61. package/components/formatter/PercentageBar.vue +1 -1
  62. package/components/formatter/__tests__/ClusterProvider.test.ts +28 -0
  63. package/components/nav/Group.vue +2 -2
  64. package/components/nav/Header.vue +2 -1
  65. package/components/nav/TopLevelMenu.vue +3 -29
  66. package/components/nav/Type.vue +3 -1
  67. package/components/nav/WindowManager/ContainerLogs.vue +19 -120
  68. package/components/nav/WindowManager/ContainerShell.vue +1 -6
  69. package/components/nav/WindowManager/index.vue +10 -11
  70. package/components/nav/__tests__/TopLevelMenu.test.ts +0 -33
  71. package/components/nav/__tests__/Type.test.ts +1 -1
  72. package/components/nuxt/nuxt-child.js +78 -14
  73. package/components/nuxt/nuxt.js +1 -1
  74. package/components/user.retention/user-retention-header.vue +34 -0
  75. package/composables/useI18n.ts +26 -0
  76. package/composables/useStore.ts +16 -0
  77. package/config/harvester-manager-types.js +0 -2
  78. package/config/home-links.js +32 -2
  79. package/config/private-label.js +0 -22
  80. package/config/product/explorer.js +4 -4
  81. package/config/product/fleet.js +1 -6
  82. package/config/product/legacy.js +1 -84
  83. package/config/product/manager.js +15 -8
  84. package/config/query-params.js +0 -1
  85. package/config/router.js +368 -385
  86. package/config/settings.ts +9 -2
  87. package/config/store.js +1 -1
  88. package/config/system-namespaces.js +0 -3
  89. package/config/table-headers.js +27 -47
  90. package/config/types.js +5 -0
  91. package/config/uiplugins.js +1 -1
  92. package/core/plugin-helpers.js +5 -3
  93. package/core/plugin-routes.ts +114 -56
  94. package/core/plugin.ts +10 -16
  95. package/core/plugins-loader.js +9 -7
  96. package/core/plugins.js +3 -0
  97. package/core/types-provisioning.ts +0 -7
  98. package/creators/app/init +0 -19
  99. package/detail/fleet.cattle.io.cluster.vue +1 -11
  100. package/detail/node.vue +0 -42
  101. package/detail/pod.vue +1 -68
  102. package/detail/provisioning.cattle.io.cluster.vue +4 -6
  103. package/detail/workload/index.vue +1 -15
  104. package/dialog/ScaleMachineDownDialog.vue +17 -34
  105. package/edit/auth/googleoauth.vue +5 -1
  106. package/edit/catalog.cattle.io.clusterrepo.vue +7 -20
  107. package/edit/cloudcredential.vue +0 -2
  108. package/edit/fleet.cattle.io.gitrepo.vue +4 -3
  109. package/edit/management.cattle.io.project.vue +52 -1
  110. package/edit/management.cattle.io.setting.vue +2 -31
  111. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +3 -12
  112. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +1 -2
  113. package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.spec.ts +1 -1
  114. package/edit/provisioning.cattle.io.cluster/{tabs/Basics.vue → Basics.vue} +126 -109
  115. package/edit/provisioning.cattle.io.cluster/{tabs/MachinePool.vue → MachinePool.vue} +7 -1
  116. package/edit/provisioning.cattle.io.cluster/{tabs/registries/RegistryConfigs.vue → RegistryConfigs.vue} +3 -1
  117. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +7 -15
  118. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +237 -0
  119. package/edit/provisioning.cattle.io.cluster/__tests__/{CustomCommand.test.ts → CustomCommand.tests.ts} +0 -6
  120. package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +1 -1
  121. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +1 -7
  122. package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
  123. package/edit/provisioning.cattle.io.cluster/index.vue +37 -99
  124. package/edit/provisioning.cattle.io.cluster/rke2.vue +690 -181
  125. package/edit/service.vue +0 -12
  126. package/edit/workload/Upgrading.vue +2 -3
  127. package/edit/workload/index.vue +1 -2
  128. package/edit/workload/mixins/workload.js +1 -1
  129. package/initialize/App.js +71 -25
  130. package/initialize/client.js +162 -21
  131. package/initialize/index.js +124 -47
  132. package/initialize/layouts.ts +26 -0
  133. package/{components/templates → layouts}/blank.vue +1 -1
  134. package/{components/templates → layouts}/default.vue +98 -8
  135. package/{components/templates → layouts}/error.vue +19 -10
  136. package/{components/templates → layouts}/home.vue +1 -4
  137. package/{components/templates → layouts}/plain.vue +1 -4
  138. package/{components/templates → layouts}/standalone.vue +1 -1
  139. package/{components/templates → layouts}/unauthenticated.vue +1 -1
  140. package/list/management.cattle.io.feature.vue +7 -1
  141. package/list/management.cattle.io.user.vue +25 -1
  142. package/list/node.vue +0 -1
  143. package/machine-config/__tests__/vmwarevsphere.test.ts +161 -56
  144. package/machine-config/amazonec2.vue +1 -0
  145. package/machine-config/azure.vue +37 -21
  146. package/machine-config/vmwarevsphere.vue +47 -42
  147. package/middleware/authenticated.js +19 -14
  148. package/mixins/auth-config.js +7 -2
  149. package/mixins/brand.js +41 -29
  150. package/mixins/fetch.server.js +73 -0
  151. package/mixins/labeled-form-element.ts +1 -6
  152. package/models/__tests__/management.cattle.io.node.ts +0 -85
  153. package/models/__tests__/namespace.test.ts +9 -49
  154. package/models/cluster/node.js +4 -4
  155. package/models/cluster.x-k8s.io.machine.js +1 -1
  156. package/models/cluster.x-k8s.io.machinedeployment.js +0 -14
  157. package/models/fleet.cattle.io.cluster.js +0 -4
  158. package/models/fleet.cattle.io.gitrepo.js +13 -56
  159. package/models/management.cattle.io.cluster.js +3 -11
  160. package/models/management.cattle.io.kontainerdriver.js +0 -1
  161. package/models/management.cattle.io.node.js +14 -18
  162. package/models/management.cattle.io.nodepool.js +0 -17
  163. package/models/management.cattle.io.project.js +36 -0
  164. package/models/management.cattle.io.setting.js +7 -11
  165. package/models/management.cattle.io.user.js +65 -0
  166. package/models/namespace.js +1 -1
  167. package/models/pod.js +0 -20
  168. package/models/provisioning.cattle.io.cluster.js +8 -55
  169. package/models/secret.js +18 -117
  170. package/models/workload.js +0 -16
  171. package/models/workload.service.js +0 -18
  172. package/package.json +10 -12
  173. package/pages/about.vue +1 -0
  174. package/pages/account/create-key.vue +1 -0
  175. package/pages/account/index.vue +1 -0
  176. package/pages/auth/login.vue +1 -0
  177. package/pages/auth/logout.vue +2 -0
  178. package/pages/auth/setup.vue +4 -37
  179. package/pages/auth/verify.vue +8 -14
  180. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +17 -2
  181. package/pages/c/_cluster/apps/charts/index.vue +58 -64
  182. package/pages/c/_cluster/apps/charts/install.helpers.js +13 -2
  183. package/pages/c/_cluster/apps/charts/install.vue +5 -5
  184. package/pages/c/_cluster/apps/index.vue +2 -0
  185. package/pages/c/_cluster/auth/index.vue +2 -0
  186. package/pages/c/_cluster/auth/user.retention/index.vue +384 -0
  187. package/pages/c/_cluster/ecm/index.vue +2 -0
  188. package/pages/c/_cluster/explorer/index.vue +53 -56
  189. package/pages/c/_cluster/explorer/tools/index.vue +3 -171
  190. package/pages/c/_cluster/fleet/index.vue +1 -1
  191. package/pages/c/_cluster/index.vue +2 -0
  192. package/pages/c/_cluster/manager/pages/_page.vue +5 -4
  193. package/pages/c/_cluster/monitoring/index.vue +1 -17
  194. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +1 -0
  195. package/pages/c/_cluster/settings/banners.vue +2 -0
  196. package/pages/c/_cluster/settings/brand.vue +2 -0
  197. package/pages/c/_cluster/settings/index.vue +2 -0
  198. package/pages/c/_cluster/settings/links.vue +3 -2
  199. package/pages/c/_cluster/settings/performance.vue +1 -0
  200. package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +4 -4
  201. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +1 -2
  202. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +46 -10
  203. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +5 -2
  204. package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +96 -0
  205. package/pages/c/_cluster/uiplugins/__tests__/SetupUIPlugins.test.ts +128 -0
  206. package/pages/c/_cluster/uiplugins/index.vue +2 -0
  207. package/pages/c/index.vue +9 -0
  208. package/pages/diagnostic.vue +2 -1
  209. package/pages/fail-whale.vue +1 -0
  210. package/pages/prefs.vue +1 -0
  211. package/pages/rio/mesh.vue +508 -0
  212. package/pages/support/index.vue +8 -2
  213. package/pkg/auto-import.js +1 -1
  214. package/plugins/axios.js +36 -0
  215. package/plugins/back-button.js +5 -3
  216. package/plugins/clean-html-directive.js +19 -1
  217. package/plugins/clean-tooltip-directive.js +1 -1
  218. package/plugins/codemirror-loader.js +1 -1
  219. package/plugins/codemirror.js +0 -41
  220. package/plugins/dashboard-store/__tests__/actions.spec.ts +250 -0
  221. package/plugins/dashboard-store/__tests__/{mutations.test.ts → mutations.spec.ts} +1 -1
  222. package/plugins/dashboard-store/actions.js +21 -22
  223. package/plugins/dashboard-store/classify.js +18 -1
  224. package/plugins/dashboard-store/getters.js +5 -10
  225. package/plugins/dashboard-store/index.js +12 -0
  226. package/plugins/dashboard-store/mutations.js +4 -0
  227. package/plugins/dashboard-store/resource-class.js +18 -59
  228. package/plugins/i18n.js +1 -1
  229. package/plugins/steve/__tests__/getters.spec.ts +56 -24
  230. package/plugins/steve/__tests__/subscribe.spec.ts +106 -0
  231. package/plugins/steve/getters.js +30 -7
  232. package/plugins/steve/mutations.js +5 -2
  233. package/plugins/steve/norman-class.js +0 -19
  234. package/plugins/steve/steve-class.js +0 -22
  235. package/plugins/steve/subscribe.js +34 -13
  236. package/plugins/transitions.js +4 -0
  237. package/plugins/vue-clipboard2.js +4 -0
  238. package/rancher-components/Accordion/Accordion.vue +3 -2
  239. package/rancher-components/BadgeState/BadgeState.vue +3 -3
  240. package/rancher-components/Banner/Banner.test.ts +1 -5
  241. package/rancher-components/Banner/Banner.vue +2 -2
  242. package/rancher-components/Card/Card.vue +4 -4
  243. package/rancher-components/Form/Checkbox/Checkbox.vue +4 -3
  244. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +1 -1
  245. package/rancher-components/Form/LabeledInput/LabeledInput.vue +55 -24
  246. package/rancher-components/Form/Radio/RadioButton.test.ts +1 -3
  247. package/rancher-components/Form/Radio/RadioButton.vue +13 -7
  248. package/rancher-components/Form/Radio/RadioGroup.vue +4 -3
  249. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -5
  250. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
  251. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
  252. package/rancher-components/StringList/StringList.vue +8 -8
  253. package/rancher-components/components/Accordion/Accordion.vue +3 -2
  254. package/rancher-components/components/BadgeState/BadgeState.test.ts +12 -0
  255. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +2 -19
  256. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +14 -11
  257. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +1 -1
  258. package/rancher-components/components/StringList/StringList.test.ts +0 -270
  259. package/rancher-components/components/StringList/StringList.vue +18 -57
  260. package/scripts/extension/bundle +7 -19
  261. package/scripts/extension/helm/scripts/package +3 -11
  262. package/scripts/extension/parse-tag-name +4 -4
  263. package/scripts/extension/publish +9 -20
  264. package/scripts/publish-shell.sh +1 -11
  265. package/scripts/test-plugins-build.sh +9 -85
  266. package/store/catalog.js +1 -1
  267. package/store/features.js +0 -1
  268. package/store/i18n.js +0 -11
  269. package/store/index.js +11 -8
  270. package/store/prefs.js +38 -33
  271. package/store/type-map.js +8 -13
  272. package/tsconfig.default.json +46 -0
  273. package/tsconfig.json +9 -35
  274. package/types/shell/index.d.ts +404 -463
  275. package/utils/__tests__/create-yaml.test.ts +10 -0
  276. package/utils/axios.js +19 -0
  277. package/utils/create-yaml.js +6 -6
  278. package/utils/custom-validators.js +2 -0
  279. package/utils/error.js +1 -16
  280. package/utils/monitoring.js +2 -37
  281. package/utils/nuxt.js +39 -18
  282. package/utils/object.js +0 -14
  283. package/utils/router.scrollBehavior.js +14 -12
  284. package/utils/socket.js +1 -0
  285. package/utils/time.js +1 -1
  286. package/utils/title.ts +3 -0
  287. package/utils/url.ts +1 -1
  288. package/utils/validators/formRules/__tests__/index.test.ts +4 -49
  289. package/utils/validators/formRules/index.ts +9 -12
  290. package/utils/validators/setting.js +10 -6
  291. package/vue.config.js +3 -24
  292. package/chart/monitoring/steps/uninstall-v1.vue +0 -135
  293. package/components/Certificates.vue +0 -164
  294. package/components/fleet/__tests__/FleetSummary.test.ts +0 -316
  295. package/components/formatter/FleetClusterSummaryGraph.vue +0 -27
  296. package/components/formatter/__tests__/Checked.test.ts +0 -19
  297. package/components/nav/WindowManager/__tests__/ContainerLogs.test.ts +0 -186
  298. package/composables/useCompactInput.ts +0 -20
  299. package/composables/useLabeledFormElement.ts +0 -138
  300. package/creators/app/files/.gitlab-ci.yml +0 -14
  301. package/edit/__tests__/service.test.ts +0 -89
  302. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +0 -112
  303. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +0 -473
  304. package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +0 -73
  305. package/edit/provisioning.cattle.io.cluster/__tests__/utils/cluster.ts +0 -386
  306. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +0 -137
  307. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +0 -157
  308. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +0 -135
  309. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +0 -189
  310. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +0 -144
  311. package/edit/provisioning.cattle.io.cluster/tabs/upgrade/index.vue +0 -76
  312. package/mixins/v1-workload-metrics.js +0 -43
  313. package/models/__tests__/management.cattle.io.cluster.test.ts +0 -23
  314. package/models/__tests__/management.cattle.io.nodepool.ts +0 -83
  315. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +0 -90
  316. package/models/__tests__/workload.test.ts +0 -91
  317. package/plugins/clean-html.js +0 -53
  318. package/plugins/dashboard-store/__tests__/actions.test.ts +0 -165
  319. package/plugins/dashboard-store/__tests__/resource-class.test.ts +0 -49
  320. package/plugins/dashboard-store/__tests__/utils/store-mocks.ts +0 -7
  321. package/plugins/index.js +0 -11
  322. package/plugins/steve/__tests__/steve-class.spec.ts +0 -59
  323. package/plugins/steve/__tests__/utils/steve-mocks.ts +0 -31
  324. package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +0 -50
  325. package/server/har-file.js +0 -183
  326. package/tsconfig.paths.json +0 -18
  327. package/utils/azure.js +0 -24
  328. package/utils/clipboard.js +0 -5
  329. /package/components/form/__tests__/{NameNsDescription.test.ts → NameNsDescription.ts} +0 -0
  330. /package/edit/networking.k8s.io.networkpolicy/__tests__/utils/{selectors.test.ts → selectors.ts} +0 -0
  331. /package/edit/provisioning.cattle.io.cluster/{tabs/networking/ACE.vue → ACE.vue} +0 -0
  332. /package/edit/provisioning.cattle.io.cluster/{tabs/AgentConfiguration.vue → AgentConfiguration.vue} +0 -0
  333. /package/edit/provisioning.cattle.io.cluster/{tabs/upgrade/DrainOptions.vue → DrainOptions.vue} +0 -0
  334. /package/edit/provisioning.cattle.io.cluster/{tabs/MemberRoles.vue → MemberRoles.vue} +0 -0
  335. /package/edit/provisioning.cattle.io.cluster/{tabs/registries/RegistryMirrors.vue → RegistryMirrors.vue} +0 -0
  336. /package/edit/provisioning.cattle.io.cluster/{tabs/etcd/S3Config.vue → S3Config.vue} +0 -0
  337. /package/plugins/dashboard-store/__tests__/{getters.test.ts → getters.spec.ts} +0 -0
  338. /package/rancher-components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
package/detail/node.vue CHANGED
@@ -11,7 +11,6 @@ import {
11
11
  VALUE
12
12
  } from '@shell/config/table-headers';
13
13
  import ResourceTabs from '@shell/components/form/ResourceTabs';
14
- import EmberPage from '@shell/components/EmberPage';
15
14
  import { METRIC, POD } from '@shell/config/types';
16
15
  import createEditView from '@shell/mixins/create-edit-view';
17
16
  import { formatSi, exponentNeeded, UNITS } from '@shell/utils/units';
@@ -20,7 +19,6 @@ import { mapGetters } from 'vuex';
20
19
  import { allDashboardsExist } from '@shell/utils/grafana';
21
20
  import Loading from '@shell/components/Loading';
22
21
  import metricPoller from '@shell/mixins/metric-poller';
23
- import { haveV1Monitoring } from '@shell/utils/monitoring';
24
22
 
25
23
  const NODE_METRICS_DETAIL_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-node-detail-1/rancher-node-detail?orgId=1';
26
24
  const NODE_METRICS_SUMMARY_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-node-1/rancher-node?orgId=1';
@@ -36,7 +34,6 @@ export default {
36
34
  ResourceTabs,
37
35
  Tab,
38
36
  ResourceTable,
39
- EmberPage,
40
37
  },
41
38
 
42
39
  mixins: [createEditView, metricPoller],
@@ -51,15 +48,6 @@ export default {
51
48
  async fetch() {
52
49
  this.showMetrics = await allDashboardsExist(this.$store, this.currentCluster.id, [NODE_METRICS_DETAIL_URL, NODE_METRICS_SUMMARY_URL]);
53
50
 
54
- if (haveV1Monitoring(this.$store.getters)) {
55
- const v3Nodes = await this.$store.dispatch('rancher/request', {
56
- url: '/v3/nodes',
57
- method: 'get'
58
- });
59
-
60
- this.v3Nodes = v3Nodes;
61
- }
62
-
63
51
  return this.$store.dispatch('cluster/findAll', { type: POD });
64
52
  },
65
53
 
@@ -67,7 +55,6 @@ export default {
67
55
  const podSchema = this.$store.getters['cluster/schemaFor'](POD);
68
56
 
69
57
  return {
70
- v3Nodes: null,
71
58
  metrics: { cpu: 0, memory: 0 },
72
59
  infoTableHeaders: [
73
60
  {
@@ -99,22 +86,6 @@ export default {
99
86
 
100
87
  computed: {
101
88
  ...mapGetters(['currentCluster']),
102
- v1MonitoringUrl() {
103
- if (this.v3Nodes && this.v3Nodes.data) {
104
- const node = this.v3Nodes.data.find((n) => {
105
- return n.nodeName === this.value.metadata?.name;
106
- });
107
-
108
- if (node) {
109
- // Custom page just with node metrics graphs
110
- const id = this.currentCluster.id;
111
-
112
- return `/k/${ id }/monitoring/${ node.id }/metrics`;
113
- }
114
- }
115
-
116
- return null;
117
- },
118
89
  memoryUnits() {
119
90
  const exponent = exponentNeeded(this.value.ramReserved, 1024);
120
91
 
@@ -320,19 +291,6 @@ export default {
320
291
  :search="false"
321
292
  />
322
293
  </Tab>
323
- <Tab
324
- v-if="v1MonitoringUrl"
325
- name="v1Metrics"
326
- :label="t('node.detail.tab.metrics')"
327
- :weight="0"
328
- >
329
- <div id="ember-anchor">
330
- <EmberPage
331
- inline="ember-anchor"
332
- :src="v1MonitoringUrl"
333
- />
334
- </div>
335
- </Tab>
336
294
  </ResourceTabs>
337
295
  </div>
338
296
  </template>
package/detail/pod.vue CHANGED
@@ -7,10 +7,8 @@ import { STATE, SIMPLE_NAME, IMAGE_NAME } from '@shell/config/table-headers';
7
7
  import { sortableNumericSuffix } from '@shell/utils/sort';
8
8
  import { findBy } from '@shell/utils/array';
9
9
  import DashboardMetrics from '@shell/components/DashboardMetrics';
10
- import V1WorkloadMetrics from '@shell/mixins/v1-workload-metrics';
11
10
  import { mapGetters } from 'vuex';
12
11
  import { allDashboardsExist } from '@shell/utils/grafana';
13
- import LabeledSelect from '@shell/components/form/LabeledSelect';
14
12
  import day from 'dayjs';
15
13
  import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
16
14
  import { escapeHtml } from '@shell/utils/string';
@@ -28,10 +26,9 @@ export default {
28
26
  ResourceTabs,
29
27
  Tab,
30
28
  SortableTable,
31
- LabeledSelect,
32
29
  },
33
30
 
34
- mixins: [CreateEditView, V1WorkloadMetrics],
31
+ mixins: [CreateEditView],
35
32
 
36
33
  async fetch() {
37
34
  this.showMetrics = await allDashboardsExist(this.$store, this.currentCluster.id, [POD_METRICS_DETAIL_URL, POD_METRICS_SUMMARY_URL]);
@@ -50,22 +47,13 @@ export default {
50
47
  },
51
48
 
52
49
  data() {
53
- const t = this.$store.getters['i18n/t'];
54
- const POD_OPTION = {
55
- id: '//POD//',
56
- label: t('workload.metrics.pod'),
57
- };
58
-
59
50
  return {
60
51
  POD_METRICS_DETAIL_URL,
61
52
  POD_METRICS_SUMMARY_URL,
62
53
  POD_PROJECT_METRICS_DETAIL_URL: '',
63
54
  POD_PROJECT_METRICS_SUMMARY_URL: '',
64
- POD_OPTION,
65
55
  showMetrics: false,
66
56
  showProjectMetrics: false,
67
- selection: POD_OPTION,
68
- metricsID: null,
69
57
  };
70
58
  },
71
59
 
@@ -194,27 +182,6 @@ export default {
194
182
  };
195
183
  },
196
184
 
197
- metricsOptions() {
198
- const v = this.containers.map((c) => {
199
- return {
200
- id: c.name,
201
- label: c.name
202
- };
203
- });
204
-
205
- v.unshift(this.POD_OPTION);
206
-
207
- return v;
208
- },
209
-
210
- v1Metrics() {
211
- if (!this.metricsID) {
212
- return this.v1MonitoringUrl;
213
- } else {
214
- return `${ this.v1MonitoringContainerBaseUrl }/${ this.metricsID }`;
215
- }
216
- },
217
-
218
185
  dateTimeFormatString() {
219
186
  const dateFormat = escapeHtml( this.$store.getters['prefs/get'](DATE_FORMAT));
220
187
  const timeFormat = escapeHtml( this.$store.getters['prefs/get'](TIME_FORMAT));
@@ -224,13 +191,6 @@ export default {
224
191
  },
225
192
 
226
193
  methods: {
227
- selectionChanged(c) {
228
- const id = c === this.POD_OPTION ? null : c.id;
229
-
230
- this.metricsID = id;
231
- this.selection = c;
232
- },
233
-
234
194
  dateTimeFormat(value) {
235
195
  return value ? day(value).format(this.dateTimeFormatString) : '';
236
196
  }
@@ -259,26 +219,6 @@ export default {
259
219
  :table-actions="false"
260
220
  />
261
221
  </Tab>
262
- <Tab
263
- v-if="v1MonitoringUrl"
264
- name="v1Metrics"
265
- :label="t('node.detail.tab.metrics')"
266
- :weight="0"
267
- >
268
- <LabeledSelect
269
- class="pod-metrics-chooser"
270
- :value="selection"
271
- label-key="workload.metrics.metricsView"
272
- :options="metricsOptions"
273
- @input="selectionChanged($event)"
274
- />
275
- <div id="ember-anchor">
276
- <EmberPage
277
- inline="ember-anchor"
278
- :src="v1Metrics"
279
- />
280
- </div>
281
- </Tab>
282
222
  <Tab
283
223
  v-if="showMetrics"
284
224
  :label="t('workload.container.titles.metrics')"
@@ -313,10 +253,3 @@ export default {
313
253
  </Tab>
314
254
  </ResourceTabs>
315
255
  </template>
316
- <style scoped>
317
- .pod-metrics-chooser {
318
- width: fit-content;
319
- margin-bottom: 10px;
320
- min-width: 300px;
321
- }
322
- </style>
@@ -775,18 +775,17 @@ export default {
775
775
  v-clean-html="t('resourceTable.groupLabel.notInANodePool')"
776
776
  />
777
777
  <div
778
- v-if="group.ref && group.ref.providerSummary"
778
+ v-if="group.ref && group.ref.template"
779
779
  class="description text-muted text-small"
780
780
  >
781
- {{ group.ref.providerSummary }}
781
+ {{ group.ref.providerDisplay }} &ndash; {{ group.ref.providerLocation }} / {{ group.ref.providerSize }} ({{ group.ref.providerName }})
782
782
  </div>
783
783
  </div>
784
784
  <div
785
- v-if="group.ref"
785
+ v-if="group.ref && poolSummaryInfo[group.ref]"
786
786
  class="right group-header-buttons mr-20"
787
787
  >
788
788
  <MachineSummaryGraph
789
- v-if="poolSummaryInfo[group.ref]"
790
789
  :row="poolSummaryInfo[group.ref]"
791
790
  :horizontal="true"
792
791
  class="mr-20"
@@ -880,7 +879,7 @@ export default {
880
879
  <template v-if="group.ref.hasLink('update')">
881
880
  <button
882
881
  v-clean-tooltip="t('node.list.scaleDown')"
883
- :disabled="!group.ref.canScaleDownPool()"
882
+ :disabled="group.ref.spec.quantity < 2"
884
883
  type="button"
885
884
  class="btn btn-sm role-secondary"
886
885
  @click="toggleScaleDownModal($event, group.ref)"
@@ -1006,7 +1005,6 @@ export default {
1006
1005
  >
1007
1006
  <SortableTable
1008
1007
  class="snapshots"
1009
- :data-testid="'cluster-snapshots-list'"
1010
1008
  :headers="value.isRke1 ? rke1SnapshotHeaders : rke2SnapshotHeaders"
1011
1009
  default-sort-by="age"
1012
1010
  :table-actions="value.isRke1"
@@ -11,7 +11,6 @@ import ResourceTabs from '@shell/components/form/ResourceTabs';
11
11
  import CountGauge from '@shell/components/CountGauge';
12
12
  import { allHash } from '@shell/utils/promise';
13
13
  import DashboardMetrics from '@shell/components/DashboardMetrics';
14
- import V1WorkloadMetrics from '@shell/mixins/v1-workload-metrics';
15
14
  import { mapGetters } from 'vuex';
16
15
  import { allDashboardsExist } from '@shell/utils/grafana';
17
16
  import PlusMinus from '@shell/components/form/PlusMinus';
@@ -51,7 +50,7 @@ export default {
51
50
  PlusMinus
52
51
  },
53
52
 
54
- mixins: [CreateEditView, V1WorkloadMetrics],
53
+ mixins: [CreateEditView],
55
54
 
56
55
  async fetch() {
57
56
  let hasNodes = false;
@@ -452,19 +451,6 @@ export default {
452
451
  />
453
452
  </template>
454
453
  </Tab>
455
- <Tab
456
- v-if="v1MonitoringUrl"
457
- name="v1Metrics"
458
- :label="t('node.detail.tab.metrics')"
459
- :weight="10"
460
- >
461
- <div id="ember-anchor">
462
- <EmberPage
463
- inline="ember-anchor"
464
- :src="v1MonitoringUrl"
465
- />
466
- </div>
467
- </Tab>
468
454
  <Tab
469
455
  v-if="!isJob && !isCronJob"
470
456
  name="services"
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { CAPI as CAPI_LABELS } from '@shell/config/labels-annotations';
3
- import { MANAGEMENT, CAPI } from '@shell/config/types';
3
+ import { CAPI } from '@shell/config/types';
4
4
  import GenericPrompt from './GenericPrompt';
5
5
 
6
6
  export default {
@@ -14,38 +14,30 @@ export default {
14
14
  },
15
15
 
16
16
  async fetch() {
17
- if (this.isRke2) {
18
- await Promise.all([
19
- this.$store.dispatch('management/findAll', { type: CAPI.MACHINE_DEPLOYMENT }),
20
- this.$store.dispatch('management/findAll', { type: CAPI.MACHINE })
21
- ]);
22
- } else {
23
- await Promise.all([
24
- this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE_POOL }),
25
- this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE })
26
- ]);
27
- }
17
+ await Promise.all([
18
+ this.$store.dispatch('management/findAll', { type: CAPI.MACHINE_DEPLOYMENT }),
19
+ this.$store.dispatch('management/findAll', { type: CAPI.MACHINE })
20
+ ]);
28
21
  },
29
22
 
30
23
  data() {
31
- const isRke2 = this.resources[0].cluster?.isRke2;
32
- const cluster = isRke2 ? this.resources[0].cluster : this.resources[0].provisioningCluster;
24
+ const allToDelete = Array.isArray(this.resources) ? this.resources : [this.resources];
25
+ const cluster = allToDelete[0].cluster;
33
26
 
34
27
  // Not all machines can be deleted, there must always be at least one left for roles control plane and etcd
35
28
  // First ensure that at least one control plane exists... and then check from the remaining machines that at least one etcd exists
36
29
  // This isn't optimisied, there may be cases that retaining a single machine with both roles would be better than retaining two with single roles
37
- const [ignoredControlPlane, safeControlePlaneMachinesToDelete] = this.deleteType('isControlPlane', this.resources, cluster, isRke2);
38
- const [ignoredEtcd, safeMachinesToDelete] = this.deleteType('isEtcd', safeControlePlaneMachinesToDelete, cluster, isRke2);
30
+ const [ignoredControlPlane, safeControlePlaneMachinesToDelete] = this.deleteType('isControlPlane', allToDelete, cluster);
31
+ const [ignoredEtcd, safeMachinesToDelete] = this.deleteType('isEtcd', safeControlePlaneMachinesToDelete, cluster);
39
32
  const ignored = [ignoredControlPlane, ignoredEtcd].filter((i) => !!i);
40
33
 
41
34
  return {
42
35
  cluster,
43
- isRke2,
44
- allToDelete: this.resources,
36
+ allToDelete,
45
37
  safeMachinesToDelete,
46
38
  ignored,
47
- type: this.$store.getters['type-map/labelFor'](this.resources[0].schema, this.resources.length),
48
- config: {
39
+ type: this.$store.getters['type-map/labelFor'](allToDelete[0].schema, allToDelete.length),
40
+ config: {
49
41
  title: this.t('promptRemove.title'),
50
42
  applyMode: 'delete',
51
43
  applyAction: this.remove,
@@ -54,7 +46,7 @@ export default {
54
46
  },
55
47
 
56
48
  methods: {
57
- deleteType(type, allToDelete, cluster, isRke2) {
49
+ deleteType(type, allToDelete, cluster) {
58
50
  const allToDeleteByType = allToDelete.reduce((res, m) => {
59
51
  if (m[type]) {
60
52
  res.typed.push(m);
@@ -65,8 +57,7 @@ export default {
65
57
  return res;
66
58
  }, { typed: [], others: [] });
67
59
 
68
- const machines = isRke2 ? cluster.machines : cluster.nodes;
69
- const totalTypes = machines.filter((m) => m[type]).length;
60
+ const totalTypes = cluster.machines.filter((m) => m[type]).length;
70
61
  const typesToDelete = allToDeleteByType.typed.length;
71
62
  // If we're attempting to remove all control plan machines.... ignore one
72
63
  const ignoredType = totalTypes - typesToDelete === 0 ? allToDeleteByType.typed.pop() : undefined;
@@ -76,14 +67,6 @@ export default {
76
67
  },
77
68
 
78
69
  async remove() {
79
- if (!this.isRke2) {
80
- await Promise.all(this.safeMachinesToDelete.map((node) => {
81
- return node.norman?.doAction('scaledown');
82
- }));
83
-
84
- return;
85
- }
86
-
87
70
  // Group machines into pools
88
71
  const poolInfo = this.safeMachinesToDelete.reduce((res, m) => {
89
72
  res.set(m.pool, res.get(m.pool) || []);
@@ -120,7 +103,7 @@ export default {
120
103
  <template slot="body">
121
104
  <div class="pl-10 pr-10 mt-20 mb-20 body">
122
105
  <div v-if="allToDelete.length === 1">
123
- {{ t('promptRemove.attemptingToRemove', { type }) }} <b>{{ safeMachinesToDelete[0].nameDisplay }}</b>
106
+ {{ t('promptRemove.attemptingToRemove', { type }) }} <b>{{ safeMachinesToDelete[0].name }}</b>
124
107
  </div>
125
108
  <div v-else>
126
109
  {{ t('promptScaleMachineDown.attemptingToRemove', { type, count: allToDelete.length }, true) }}
@@ -132,8 +115,8 @@ export default {
132
115
  <span class="mb-20">{{ t('promptScaleMachineDown.retainedMachine1') }}</span>
133
116
  <span
134
117
  v-for="i in ignored"
135
- :key="i.nameDisplay"
136
- v-clean-html="t('promptScaleMachineDown.retainedMachine2', { name: i.nameDisplay }, true)"
118
+ :key="i.name"
119
+ v-clean-html="t('promptScaleMachineDown.retainedMachine2', { name: i.name }, true)"
137
120
  />
138
121
  </div>
139
122
  </div>
@@ -33,7 +33,11 @@ export default {
33
33
 
34
34
  computed: {
35
35
  tArgs() {
36
- const hostname = window.location.hostname;
36
+ let hostname = '';
37
+
38
+ if (process.client) {
39
+ hostname = window.location.hostname;
40
+ }
37
41
 
38
42
  return {
39
43
  hostname,
@@ -1,5 +1,4 @@
1
1
  <script>
2
- import Vue from 'vue';
3
2
  import CreateEditView from '@shell/mixins/create-edit-view';
4
3
  import Footer from '@shell/components/form/Footer';
5
4
  import { LabeledInput } from '@components/Form/LabeledInput';
@@ -7,7 +6,7 @@ import { RadioGroup } from '@components/Form/Radio';
7
6
  import NameNsDescription from '@shell/components/form/NameNsDescription';
8
7
  import Labels from '@shell/components/form/Labels';
9
8
  import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthSecret';
10
- import { NAMESPACE } from '@shell/config/types';
9
+ import { MANAGEMENT, NAMESPACE } from '@shell/config/types';
11
10
 
12
11
  export default {
13
12
  name: 'CruCatalogRepo',
@@ -28,6 +27,9 @@ export default {
28
27
  },
29
28
 
30
29
  computed: {
30
+ inStore() {
31
+ return this.$store.getters['currentProduct']?.inStore || MANAGEMENT;
32
+ },
31
33
  secretNamespace() {
32
34
  const tryNames = ['cattle-system', 'default'];
33
35
 
@@ -37,22 +39,7 @@ export default {
37
39
  }
38
40
  }
39
41
 
40
- return this.$store.getters['cluster/all'](NAMESPACE)[0]?.id;
41
- }
42
- },
43
-
44
- methods: {
45
- onTargetChange(isGit) {
46
- // reset entered value when switching options
47
- if (isGit) {
48
- Vue.set(this.value.spec, 'url', '');
49
- } else {
50
- Vue.set(this.value.spec, 'gitRepo', '');
51
-
52
- if (!!this.value.spec.gitBranch) {
53
- Vue.set(this.value.spec, 'gitBranch', '');
54
- }
55
- }
42
+ return this.$store.getters[`${ this.inStore }/all`](NAMESPACE)[0]?.id;
56
43
  }
57
44
  },
58
45
  };
@@ -76,7 +63,6 @@ export default {
76
63
  :labels="[t('catalog.repo.target.http'), t('catalog.repo.target.git')]"
77
64
  :mode="mode"
78
65
  data-testid="clusterrepo-radio-input"
79
- @input="onTargetChange"
80
66
  />
81
67
  </div>
82
68
  </div>
@@ -114,14 +100,15 @@ export default {
114
100
  :label="t('catalog.repo.url.label')"
115
101
  :placeholder="t('catalog.repo.url.placeholder', null, true)"
116
102
  :mode="mode"
117
- data-testid="clusterrepo-helm-url-input"
118
103
  />
119
104
 
120
105
  <SelectOrCreateAuthSecret
121
106
  v-model="value.spec.clientSecret"
107
+ data-testid="clusterrepo-auth-secret"
122
108
  :register-before-hook="registerBeforeHook"
123
109
  :namespace="secretNamespace"
124
110
  :limit-to-namespace="false"
111
+ :in-store="inStore"
125
112
  generate-name="clusterrepo-auth-"
126
113
  />
127
114
 
@@ -260,8 +260,6 @@ export default {
260
260
  v-model="value"
261
261
  name-key="_name"
262
262
  description-key="description"
263
- name-label="cluster.credential.name.label"
264
- name-placeholder="cluster.credential.name.placeholder"
265
263
  :mode="mode"
266
264
  :namespaced="false"
267
265
  />
@@ -22,7 +22,7 @@ import { base64Decode, base64Encode } from '@shell/utils/crypto';
22
22
  import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthSecret';
23
23
  import { _CREATE } from '@shell/config/query-params';
24
24
  import { isHarvesterCluster } from '@shell/utils/cluster';
25
- import { CAPI, CATALOG } from '@shell/config/labels-annotations';
25
+ import { CAPI, CATALOG, FLEET as FLEET_LABELS } from '@shell/config/labels-annotations';
26
26
  import { SECRET_TYPES } from '@shell/config/secret';
27
27
  import { checkSchemasForFindAllHash } from '@shell/utils/auth';
28
28
  import Checkbox from '@components/Form/Checkbox/Checkbox.vue';
@@ -413,8 +413,9 @@ export default {
413
413
  type: SECRET,
414
414
  metadata: {
415
415
  namespace: this.value.metadata.namespace,
416
- generateName: 'auth-'
417
- },
416
+ generateName: 'auth-',
417
+ labels: { [FLEET_LABELS.MANAGED]: 'true' }
418
+ }
418
419
  });
419
420
 
420
421
  let type, publicField, privateField;
@@ -5,6 +5,7 @@ import CreateEditView from '@shell/mixins/create-edit-view';
5
5
  import FormValidation from '@shell/mixins/form-validation';
6
6
  import CruResource from '@shell/components/CruResource';
7
7
  import Labels from '@shell/components/form/Labels';
8
+ import LabeledSelect from '@shell/components/form/LabeledSelect';
8
9
  import ResourceQuota from '@shell/components/form/ResourceQuota/Project';
9
10
  import { HARVESTER_TYPES, RANCHER_TYPES } from '@shell/components/form/ResourceQuota/shared';
10
11
  import Tab from '@shell/components/Tabbed/Tab';
@@ -20,15 +21,26 @@ import { Banner } from '@components/Banner';
20
21
 
21
22
  export default {
22
23
  components: {
23
- ContainerResourceLimit, CruResource, Labels, NameNsDescription, ProjectMembershipEditor, ResourceQuota, Tabbed, Tab, Banner
24
+ ContainerResourceLimit, CruResource, Labels, LabeledSelect, NameNsDescription, ProjectMembershipEditor, ResourceQuota, Tabbed, Tab, Banner
24
25
  },
25
26
 
26
27
  mixins: [CreateEditView, FormValidation],
28
+ async fetch() {
29
+ if ( this.$store.getters['management/canList'](MANAGEMENT.POD_SECURITY_POLICY_TEMPLATE) ) {
30
+ this.allPSPs = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.POD_SECURITY_POLICY_TEMPLATE });
31
+ }
32
+
33
+ // User can only change the PSP if the user has permissions to see the binding schema for PSP Templates
34
+ const pspBindingSchema = this.$store.getters['management/schemaFor'](MANAGEMENT.PSP_TEMPLATE_BINDING);
35
+
36
+ this.canEditPSPBindings = !!pspBindingSchema;
37
+ },
27
38
  data() {
28
39
  this.$set(this.value, 'spec', this.value.spec || {});
29
40
  this.$set(this.value.spec, 'podSecurityPolicyTemplateId', this.value.status?.podSecurityPolicyTemplateId || '');
30
41
 
31
42
  return {
43
+ allPSPs: [],
32
44
  projectRoleTemplateBindingSchema: this.$store.getters[`management/schemaFor`](MANAGEMENT.PROJECT_ROLE_TEMPLATE_BINDING),
33
45
  createLocation: {
34
46
  name: 'c-cluster-product-resource-create',
@@ -45,6 +57,7 @@ export default {
45
57
  HARVESTER_TYPES,
46
58
  RANCHER_TYPES,
47
59
  fvFormRuleSets: [{ path: 'spec.displayName', rules: ['required'] }],
60
+ canEditPSPBindings: true,
48
61
  };
49
62
  },
50
63
  computed: {
@@ -78,6 +91,31 @@ export default {
78
91
  return (this.currentCluster?.spec?.kubernetesVersion || '').includes('k3s');
79
92
  },
80
93
 
94
+ pspOptions() {
95
+ if ( this.isK3s || !this.currentCluster.spec.defaultPodSecurityPolicyTemplateName ) {
96
+ return null;
97
+ }
98
+
99
+ const out = [{ label: this.t('project.psp.default'), value: '' }];
100
+
101
+ if ( this.allPSPs ) {
102
+ for ( const pspt of this.allPSPs ) {
103
+ out.push({
104
+ label: pspt.nameDisplay,
105
+ value: pspt.id,
106
+ });
107
+ }
108
+ }
109
+
110
+ const cur = this.value.status?.podSecurityPolicyTemplateId;
111
+
112
+ if ( cur && !out.find((x) => x.value === cur) ) {
113
+ out.unshift({ label: this.t('project.psp.current', { value: cur }), value: cur });
114
+ }
115
+
116
+ return out;
117
+ },
118
+
81
119
  isHarvester() {
82
120
  return this.$store.getters['currentProduct'].inStore === HARVESTER;
83
121
  },
@@ -185,6 +223,19 @@ export default {
185
223
  :normalize-name="false"
186
224
  :rules="{ name: fvGetAndReportPathRules('spec.displayName'), namespace: [], description: [] }"
187
225
  />
226
+ <div class="row mb-20">
227
+ <div class="col span-3">
228
+ <LabeledSelect
229
+ v-if="pspOptions"
230
+ v-model="value.spec.podSecurityPolicyTemplateId"
231
+ class="psp"
232
+ :mode="mode"
233
+ :options="pspOptions"
234
+ :disabled="!canEditPSPBindings"
235
+ :label="t('project.psp.label')"
236
+ />
237
+ </div>
238
+ </div>
188
239
  <Tabbed :side-tabs="true">
189
240
  <Tab
190
241
  v-if="canViewMembers"