@rancher/shell 3.0.5-rc.6 → 3.0.5-rc.8

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 (243) hide show
  1. package/assets/brand/classic/metadata.json +3 -0
  2. package/assets/styles/app.scss +1 -0
  3. package/assets/styles/base/_color.scss +16 -0
  4. package/assets/styles/base/_helpers.scss +10 -0
  5. package/assets/styles/base/_variables.scss +18 -12
  6. package/assets/styles/fonts/_icons.scss +1 -32
  7. package/assets/styles/global/_layout.scss +1 -1
  8. package/assets/styles/themes/_dark.scss +262 -258
  9. package/assets/styles/themes/_light.scss +538 -509
  10. package/assets/styles/themes/_modern.scss +914 -0
  11. package/assets/translations/en-us.yaml +110 -29
  12. package/chart/__tests__/S3.test.ts +2 -1
  13. package/cloud-credential/generic.vue +18 -10
  14. package/cloud-credential/harvester.vue +1 -9
  15. package/components/AdvancedSection.vue +8 -0
  16. package/components/ChartReadme.vue +17 -7
  17. package/components/CodeMirror.vue +1 -1
  18. package/components/Drawer/Chrome.vue +0 -1
  19. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +27 -28
  20. package/components/Drawer/ResourceDetailDrawer/composables.ts +4 -24
  21. package/components/Drawer/ResourceDetailDrawer/index.vue +18 -4
  22. package/components/InstallHelmCharts.vue +656 -0
  23. package/components/LazyImage.vue +60 -4
  24. package/components/Loading.vue +1 -1
  25. package/components/LocaleSelector.vue +7 -2
  26. package/components/Markdown.vue +4 -0
  27. package/components/PaginatedResourceTable.vue +46 -1
  28. package/components/PromptRestore.vue +22 -44
  29. package/components/Resource/Detail/Masthead/composable.ts +16 -0
  30. package/components/Resource/Detail/Masthead/index.vue +37 -0
  31. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +10 -2
  32. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +26 -7
  33. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +8 -1
  34. package/components/Resource/Detail/Metadata/KeyValue.vue +12 -10
  35. package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
  36. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +10 -17
  37. package/components/Resource/Detail/Metadata/composables.ts +9 -7
  38. package/components/Resource/Detail/Metadata/index.vue +17 -2
  39. package/components/Resource/Detail/Page.vue +35 -21
  40. package/components/Resource/Detail/SpacedRow.vue +1 -1
  41. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +8 -9
  42. package/components/Resource/Detail/TitleBar/composables.ts +5 -5
  43. package/components/Resource/Detail/TitleBar/index.vue +12 -3
  44. package/components/ResourceDetail/Masthead/legacy.vue +1 -1
  45. package/components/ResourceDetail/index.vue +569 -72
  46. package/components/ResourceList/index.vue +1 -0
  47. package/components/ResourceTable.vue +6 -1
  48. package/components/ResourceYaml.vue +1 -1
  49. package/components/RichTranslation.vue +106 -0
  50. package/components/SlideInPanelManager.vue +13 -10
  51. package/components/SortableTable/index.vue +5 -5
  52. package/components/SortableTable/selection.js +0 -1
  53. package/components/Tabbed/index.vue +35 -4
  54. package/components/__tests__/LazyImage.spec.ts +121 -0
  55. package/components/__tests__/PromptRestore.test.ts +1 -65
  56. package/components/__tests__/RichTranslation.test.ts +115 -0
  57. package/components/fleet/FleetStatus.vue +4 -0
  58. package/components/fleet/dashboard/ResourcePanel.vue +2 -1
  59. package/components/form/ClusterAppearance.vue +5 -0
  60. package/components/form/FileImageSelector.vue +1 -1
  61. package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
  62. package/components/form/NameNsDescription.vue +1 -0
  63. package/components/form/Networking.vue +24 -19
  64. package/components/form/ProjectMemberEditor.vue +1 -1
  65. package/components/form/ResourceLabeledSelect.vue +22 -8
  66. package/components/form/ResourceTabs/index.vue +20 -0
  67. package/components/form/SecretSelector.vue +9 -0
  68. package/components/form/SelectOrCreateAuthSecret.vue +6 -3
  69. package/components/form/__tests__/Networking.test.ts +116 -0
  70. package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
  71. package/components/formatter/FleetApplicationSource.vue +25 -17
  72. package/components/formatter/PodImages.vue +1 -1
  73. package/components/formatter/__tests__/LiveDate.test.ts +10 -2
  74. package/components/google/AccountAccess.vue +44 -46
  75. package/components/nav/Favorite.vue +4 -0
  76. package/components/nav/Group.vue +4 -1
  77. package/components/nav/NotificationCenter/Notification.vue +1 -27
  78. package/components/nav/WindowManager/index.vue +3 -3
  79. package/composables/resources.ts +2 -2
  80. package/config/labels-annotations.js +3 -2
  81. package/config/pagination-table-headers.js +8 -1
  82. package/config/product/explorer.js +27 -2
  83. package/config/product/manager.js +0 -1
  84. package/config/query-params.js +10 -0
  85. package/config/router/routes.js +21 -1
  86. package/config/system-namespaces.js +1 -1
  87. package/config/table-headers.js +30 -1
  88. package/config/types.js +1 -1
  89. package/config/version.js +1 -1
  90. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +11 -0
  91. package/detail/__tests__/workload.test.ts +164 -0
  92. package/detail/configmap.vue +33 -75
  93. package/detail/projectsecret.vue +11 -0
  94. package/detail/provisioning.cattle.io.cluster.vue +351 -369
  95. package/detail/secret.vue +49 -308
  96. package/detail/workload/index.vue +38 -21
  97. package/dialog/InstallExtensionDialog.vue +8 -5
  98. package/dialog/RotateEncryptionKeyDialog.vue +10 -30
  99. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
  100. package/edit/auth/ldap/__tests__/config.test.ts +14 -0
  101. package/edit/auth/ldap/config.vue +24 -0
  102. package/edit/compliance.cattle.io.clusterscan.vue +1 -1
  103. package/edit/configmap.vue +4 -1
  104. package/edit/fleet.cattle.io.gitrepo.vue +5 -6
  105. package/edit/fleet.cattle.io.helmop.vue +78 -56
  106. package/edit/logging.banzaicloud.io.output/index.vue +1 -1
  107. package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
  108. package/edit/networking.k8s.io.ingress/Certificate.vue +20 -22
  109. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +8 -3
  110. package/edit/networking.k8s.io.ingress/Rule.vue +2 -5
  111. package/edit/networking.k8s.io.ingress/RulePath.vue +17 -11
  112. package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
  113. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +11 -10
  114. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -3
  115. package/edit/networking.k8s.io.networkpolicy/index.vue +17 -17
  116. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
  117. package/edit/provisioning.cattle.io.cluster/rke2.vue +123 -61
  118. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +9 -7
  119. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +22 -13
  120. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +10 -12
  121. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +39 -38
  122. package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +41 -19
  123. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +16 -3
  124. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +32 -33
  125. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue +9 -10
  126. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -3
  127. package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +16 -9
  128. package/edit/secret/basic.vue +1 -0
  129. package/edit/secret/index.vue +126 -15
  130. package/edit/workload/index.vue +5 -14
  131. package/list/projectsecret.vue +345 -0
  132. package/list/provisioning.cattle.io.cluster.vue +1 -69
  133. package/list/secret.vue +109 -0
  134. package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
  135. package/machine-config/google.vue +9 -1
  136. package/machine-config/vmwarevsphere.vue +7 -17
  137. package/mixins/__tests__/brand.spec.ts +2 -2
  138. package/mixins/chart.js +0 -2
  139. package/mixins/create-edit-view/impl.js +10 -1
  140. package/mixins/resource-fetch-api-pagination.js +11 -12
  141. package/mixins/resource-fetch.js +3 -1
  142. package/models/__tests__/chart.test.ts +111 -80
  143. package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
  144. package/models/__tests__/node.test.ts +7 -63
  145. package/models/catalog.cattle.io.app.js +1 -1
  146. package/models/catalog.cattle.io.operation.js +1 -1
  147. package/models/chart.js +36 -20
  148. package/models/cloudcredential.js +2 -163
  149. package/models/cluster/node.js +7 -7
  150. package/models/cluster.x-k8s.io.machine.js +3 -3
  151. package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
  152. package/models/compliance.cattle.io.clusterscan.js +2 -2
  153. package/models/configmap.js +4 -0
  154. package/models/constraints.gatekeeper.sh.constraint.js +1 -1
  155. package/models/fleet-application.js +0 -17
  156. package/models/fleet.cattle.io.cluster.js +2 -2
  157. package/models/fleet.cattle.io.gitrepo.js +15 -1
  158. package/models/fleet.cattle.io.helmop.js +26 -22
  159. package/models/management.cattle.io.setting.js +4 -0
  160. package/models/persistentvolumeclaim.js +1 -1
  161. package/models/pod.js +2 -2
  162. package/models/provisioning.cattle.io.cluster.js +39 -67
  163. package/models/rke.cattle.io.etcdsnapshot.js +1 -1
  164. package/models/secret.js +161 -2
  165. package/models/storage.k8s.io.storageclass.js +2 -2
  166. package/models/workload.js +3 -3
  167. package/package.json +11 -10
  168. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +1 -0
  169. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +4 -1
  170. package/pages/c/_cluster/apps/charts/__tests__/AppChartCardFooter.spec.js +41 -0
  171. package/pages/c/_cluster/apps/charts/chart.vue +422 -174
  172. package/pages/c/_cluster/apps/charts/index.vue +46 -35
  173. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  174. package/pages/c/_cluster/explorer/projectsecret.vue +24 -0
  175. package/pages/c/_cluster/fleet/__tests__/index.test.ts +608 -314
  176. package/pages/c/_cluster/fleet/index.vue +103 -45
  177. package/pages/c/_cluster/manager/cloudCredential/index.vue +2 -59
  178. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +10 -3
  179. package/pages/c/_cluster/uiplugins/index.vue +36 -25
  180. package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
  181. package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
  182. package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
  183. package/plugins/dashboard-store/actions.js +42 -22
  184. package/plugins/dashboard-store/normalize.js +29 -17
  185. package/plugins/dashboard-store/resource-class.js +83 -17
  186. package/plugins/steve/__tests__/getters.test.ts +1 -1
  187. package/plugins/steve/__tests__/subscribe.spec.ts +259 -1
  188. package/plugins/steve/getters.js +8 -2
  189. package/plugins/steve/resourceWatcher.js +10 -3
  190. package/plugins/steve/steve-pagination-utils.ts +14 -3
  191. package/plugins/steve/subscribe.js +192 -19
  192. package/plugins/steve/worker/web-worker.advanced.js +2 -0
  193. package/rancher-components/Card/Card.vue +0 -18
  194. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.test.ts +15 -0
  195. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +65 -0
  196. package/rancher-components/Pill/RcStatusBadge/index.ts +2 -0
  197. package/rancher-components/Pill/RcStatusBadge/types.ts +5 -0
  198. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.test.ts +33 -0
  199. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +75 -0
  200. package/rancher-components/Pill/RcStatusIndicator/index.ts +2 -0
  201. package/rancher-components/Pill/RcStatusIndicator/types.ts +7 -0
  202. package/rancher-components/Pill/types.ts +2 -0
  203. package/rancher-components/RcButton/RcButton.vue +1 -1
  204. package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
  205. package/rancher-components/RcDropdown/RcDropdown.vue +5 -0
  206. package/rancher-components/RcDropdown/RcDropdownItem.vue +7 -1
  207. package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +2 -1
  208. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +2 -1
  209. package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
  210. package/rancher-components/RcDropdown/useDropdownItem.ts +30 -1
  211. package/rancher-components/RcItemCard/RcItemCard.test.ts +20 -0
  212. package/rancher-components/RcItemCard/RcItemCard.vue +40 -6
  213. package/store/__tests__/catalog.test.ts +93 -1
  214. package/store/aws.js +19 -8
  215. package/store/catalog.js +8 -3
  216. package/types/kube/kube-api.ts +12 -0
  217. package/types/resources/settings.d.ts +1 -1
  218. package/types/shell/index.d.ts +643 -585
  219. package/types/store/pagination.types.ts +16 -6
  220. package/types/uiplugins.ts +73 -0
  221. package/utils/__tests__/back-off.test.ts +354 -0
  222. package/utils/__tests__/create-yaml.test.ts +235 -0
  223. package/utils/__tests__/kontainer.test.ts +19 -0
  224. package/utils/__tests__/uiplugins.test.ts +84 -0
  225. package/utils/back-off.ts +176 -0
  226. package/utils/create-yaml.js +103 -9
  227. package/utils/dynamic-importer.js +8 -0
  228. package/utils/kontainer.ts +3 -5
  229. package/utils/pagination-utils.ts +18 -0
  230. package/utils/style.ts +3 -0
  231. package/utils/uiplugins.ts +29 -2
  232. package/utils/validators/__tests__/setting.test.js +92 -0
  233. package/utils/validators/formRules/__tests__/index.test.ts +88 -7
  234. package/utils/validators/formRules/index.ts +83 -8
  235. package/utils/validators/setting.js +17 -0
  236. package/cloud-credential/__tests__/harvester.test.ts +0 -18
  237. package/components/ResourceDetail/__tests__/index.test.ts +0 -135
  238. package/components/ResourceDetail/legacy.vue +0 -562
  239. package/components/formatter/CloudCredExpired.vue +0 -69
  240. package/models/etcdbackup.js +0 -45
  241. package/pages/explorer/resource/detail/configmap.vue +0 -42
  242. package/pages/explorer/resource/detail/secret.vue +0 -50
  243. package/utils/aws.js +0 -0
@@ -3,15 +3,17 @@ import { Checkbox } from '@components/Form/Checkbox';
3
3
  import { LabeledInput } from '@components/Form/LabeledInput';
4
4
  import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthSecret';
5
5
  import { NORMAN } from '@shell/config/types';
6
+ import FormValidation from '@shell/mixins/form-validation';
6
7
 
7
8
  export default {
8
- emits: ['update:value'],
9
+ emits: ['update:value', 'validationChanged'],
9
10
 
10
11
  components: {
11
12
  LabeledInput,
12
13
  Checkbox,
13
14
  SelectOrCreateAuthSecret,
14
15
  },
16
+ mixins: [FormValidation],
15
17
 
16
18
  props: {
17
19
  mode: {
@@ -36,22 +38,30 @@ export default {
36
38
  },
37
39
 
38
40
  data() {
39
- const config = {
40
- bucket: '',
41
- cloudCredentialName: null,
42
- endpoint: '',
43
- endpointCA: '',
44
- folder: '',
45
- region: '',
46
- skipSSLVerify: false,
47
-
48
- ...(this.value || {}),
41
+ return {
42
+ config: {
43
+ bucket: '',
44
+ cloudCredentialName: null,
45
+ endpoint: '',
46
+ endpointCA: '',
47
+ folder: '',
48
+ region: '',
49
+ skipSSLVerify: false,
50
+ ...(this.value || {}),
51
+ },
52
+ fvFormRuleSets: [
53
+ {
54
+ path: 'endpoint', rootObject: this.config, rules: ['awsStyleEndpoint']
55
+ },
56
+ {
57
+ path: 'bucket', rootObject: this.config, rules: ['required']
58
+ },
59
+ ]
49
60
  };
50
-
51
- return { config };
52
61
  },
53
62
 
54
63
  computed: {
64
+
55
65
  ccData() {
56
66
  if ( this.config.cloudCredentialName ) {
57
67
  const cred = this.$store.getters['rancher/byId'](NORMAN.CLOUD_CREDENTIAL, this.config.cloudCredentialName);
@@ -64,6 +74,11 @@ export default {
64
74
  return {};
65
75
  },
66
76
  },
77
+ watch: {
78
+ fvFormIsValid(newValue) {
79
+ this.$emit('validationChanged', !!newValue);
80
+ }
81
+ },
67
82
 
68
83
  methods: {
69
84
  update() {
@@ -79,6 +94,7 @@ export default {
79
94
  <div>
80
95
  <SelectOrCreateAuthSecret
81
96
  v-model:value="config.cloudCredentialName"
97
+ :mode="mode"
82
98
  :register-before-hook="registerBeforeHook"
83
99
  in-store="management"
84
100
  :allow-ssh="false"
@@ -94,16 +110,19 @@ export default {
94
110
  <div class="col span-6">
95
111
  <LabeledInput
96
112
  v-model:value="config.bucket"
97
- label="Bucket"
113
+ :label="t('cluster.rke2.etcd.s3config.bucket.label')"
114
+ :mode="mode"
98
115
  :placeholder="ccData.defaultBucket"
99
116
  :required="!ccData.defaultBucket"
117
+ :rules="!ccData.defaultBucket ? fvGetAndReportPathRules('bucket') : []"
100
118
  @update:value="update"
101
119
  />
102
120
  </div>
103
121
  <div class="col span-6">
104
122
  <LabeledInput
105
123
  v-model:value="config.folder"
106
- label="Folder"
124
+ :label="t('cluster.rke2.etcd.s3config.folder.label')"
125
+ :mode="mode"
107
126
  :placeholder="ccData.defaultFolder"
108
127
  @update:value="update"
109
128
  />
@@ -114,7 +133,8 @@ export default {
114
133
  <div class="col span-6">
115
134
  <LabeledInput
116
135
  v-model:value="config.region"
117
- label="Region"
136
+ :label="t('cluster.rke2.etcd.s3config.region.label')"
137
+ :mode="mode"
118
138
  :placeholder="ccData.defaultRegion"
119
139
  @update:value="update"
120
140
  />
@@ -122,8 +142,10 @@ export default {
122
142
  <div class="col span-6">
123
143
  <LabeledInput
124
144
  v-model:value="config.endpoint"
125
- label="Endpoint"
145
+ :label="t('cluster.rke2.etcd.s3config.endpoint.label')"
146
+ :mode="mode"
126
147
  :placeholder="ccData.defaultEndpoint"
148
+ :rules="fvGetAndReportPathRules('endpoint')"
127
149
  @update:value="update"
128
150
  />
129
151
  </div>
@@ -136,7 +158,7 @@ export default {
136
158
  <Checkbox
137
159
  v-model:value="config.skipSSLVerify"
138
160
  :mode="mode"
139
- label="Accept any certificate (insecure)"
161
+ :label="t('cluster.rke2.etcd.s3config.skipSSLVerify.label')"
140
162
  @update:value="update"
141
163
  />
142
164
 
@@ -144,7 +166,7 @@ export default {
144
166
  v-if="!config.skipSSLVerify"
145
167
  v-model:value="config.endpointCA"
146
168
  type="multiline"
147
- label="Endpoint CA Cert"
169
+ :label="t('cluster.rke2.etcd.s3config.endpointCA.label')"
148
170
  :placeholder="ccData.defaultEndpointCA"
149
171
  @update:value="update"
150
172
  />
@@ -7,7 +7,7 @@ import S3Config from '@shell/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Con
7
7
  import UnitInput from '@shell/components/form/UnitInput';
8
8
 
9
9
  export default {
10
- emits: ['s3-backup-changed', 'config-etcd-expose-metrics-changed'],
10
+ emits: ['s3-backup-changed', 'config-etcd-expose-metrics-changed', 'etcd-validation-changed'],
11
11
 
12
12
  components: {
13
13
  LabeledInput,
@@ -53,8 +53,19 @@ export default {
53
53
  configEtcdExposeMetrics() {
54
54
  return !!this.value.spec.rkeConfig.machineGlobalConfig['etcd-expose-metrics'];
55
55
  },
56
-
57
56
  },
57
+ methods: {
58
+ s3BackupChanged(val) {
59
+ this.$emit('s3-backup-changed', val);
60
+ this.$emit('etcd-validation-changed', !val);
61
+ },
62
+ disableSnapshotsChanged(val) {
63
+ if (val) {
64
+ this.$emit('etcd-validation-changed', true);
65
+ this.$emit('s3-backup-changed', false);
66
+ }
67
+ }
68
+ }
58
69
  };
59
70
  </script>
60
71
 
@@ -69,6 +80,7 @@ export default {
69
80
  :label="t('cluster.rke2.etcd.disableSnapshots.label')"
70
81
  :labels="[t('generic.disable'), t('generic.enable')]"
71
82
  :mode="mode"
83
+ @update:value="disableSnapshotsChanged"
72
84
  />
73
85
  </div>
74
86
  </div>
@@ -106,7 +118,7 @@ export default {
106
118
  :label="t('cluster.rke2.etcd.s3backups.label')"
107
119
  :labels="[t('generic.disable'),t('generic.enable')]"
108
120
  :mode="mode"
109
- @update:value="$emit('s3-backup-changed', $event)"
121
+ @update:value="s3BackupChanged"
110
122
  />
111
123
 
112
124
  <S3Config
@@ -115,6 +127,7 @@ export default {
115
127
  :namespace="value.metadata.namespace"
116
128
  :register-before-hook="registerBeforeHook"
117
129
  :mode="mode"
130
+ @validationChanged="$emit('etcd-validation-changed', $event)"
118
131
  />
119
132
  </template>
120
133
 
@@ -44,35 +44,16 @@ export default {
44
44
  },
45
45
 
46
46
  data() {
47
- const configMap = clone(this.value.spec.rkeConfig?.registries?.configs) || {};
48
- const entries = [];
49
-
50
- const defaultAddValue = {
51
- hostname: '',
52
- authConfigSecretName: null,
53
- caBundle: '',
54
- insecureSkipVerify: false,
55
- tlsSecretName: null,
56
- };
57
-
58
- for ( const hostname in configMap ) {
59
- if (configMap[hostname]) {
60
- configMap[hostname].insecureSkipVerify = configMap[hostname].insecureSkipVerify ?? defaultAddValue.insecureSkipVerify;
61
- configMap[hostname].authConfigSecretName = configMap[hostname].authConfigSecretName ?? defaultAddValue.authConfigSecretName;
62
-
63
- const caBundle = configMap[hostname].caBundle ?? defaultAddValue.caBundle;
64
-
65
- configMap[hostname].caBundle = isBase64(caBundle) ? base64Decode(caBundle) : caBundle;
66
-
67
- configMap[hostname].tlsSecretName = configMap[hostname].tlsSecretName ?? defaultAddValue.tlsSecretName;
47
+ return {
48
+ entries: [],
49
+ defaultAddValue: {
50
+ hostname: '',
51
+ authConfigSecretName: null,
52
+ caBundle: '',
53
+ insecureSkipVerify: false,
54
+ tlsSecretName: null,
68
55
  }
69
- entries.push({
70
- hostname,
71
- ...configMap[hostname],
72
- });
73
- }
74
-
75
- return { entries, defaultAddValue };
56
+ };
76
57
  },
77
58
 
78
59
  computed: {
@@ -87,9 +68,27 @@ export default {
87
68
  window.z = this;
88
69
  },
89
70
 
90
- // created() {
91
- // set(this.value, 'spec.rkeConfig.registries.configs', {});
92
- // },
71
+ created() {
72
+ const configMap = clone(this.value.spec.rkeConfig?.registries?.configs) || {};
73
+
74
+ for ( const hostname in configMap ) {
75
+ if (configMap[hostname]) {
76
+ configMap[hostname].insecureSkipVerify = configMap[hostname].insecureSkipVerify ?? this.defaultAddValue.insecureSkipVerify;
77
+ configMap[hostname].authConfigSecretName = configMap[hostname].authConfigSecretName ?? this.defaultAddValue.authConfigSecretName;
78
+
79
+ const caBundle = configMap[hostname].caBundle ?? this.defaultAddValue.caBundle;
80
+
81
+ configMap[hostname].caBundle = isBase64(caBundle) ? base64Decode(caBundle) : caBundle;
82
+
83
+ configMap[hostname].tlsSecretName = configMap[hostname].tlsSecretName ?? this.defaultAddValue.tlsSecretName;
84
+ }
85
+
86
+ this.entries.push({
87
+ hostname,
88
+ ...configMap[hostname],
89
+ });
90
+ }
91
+ },
93
92
 
94
93
  methods: {
95
94
  update() {
@@ -104,7 +103,7 @@ export default {
104
103
 
105
104
  configs[h] = {
106
105
  ...entry,
107
- caBundle: base64Encode(entry.caBundle)
106
+ caBundle: entry.caBundle ? base64Encode(entry.caBundle) : null
108
107
  };
109
108
 
110
109
  delete configs[h].hostname;
@@ -172,7 +171,7 @@ export default {
172
171
  :mode="mode"
173
172
  generate-name="registryconfig-auth-"
174
173
  :data-testid="`registry-auth-select-or-create-${i}`"
175
- :cache-secrets="true"
174
+ :cache-secrets="false"
176
175
  @update:value="update"
177
176
  />
178
177
  </div>
@@ -22,24 +22,23 @@ export default {
22
22
  },
23
23
 
24
24
  data() {
25
+ return { entries: [] };
26
+ },
27
+
28
+ created() {
29
+ if (!this.value.spec.rkeConfig?.registries?.mirrors) {
30
+ set(this.value, 'spec.rkeConfig.registries.mirrors', {});
31
+ }
32
+
25
33
  const mirrorMap = this.value.spec.rkeConfig?.registries?.mirrors || {};
26
- const entries = [];
27
34
 
28
35
  for ( const hostname in mirrorMap ) {
29
- entries.push({
36
+ this.entries.push({
30
37
  hostname,
31
38
  endpoints: (mirrorMap[hostname].endpoint || []).join(', '),
32
39
  rewrite: mirrorMap[hostname].rewrite || {},
33
40
  });
34
41
  }
35
-
36
- return { entries };
37
- },
38
-
39
- created() {
40
- if (!this.value.spec.rkeConfig?.registries?.mirrors) {
41
- set(this.value, 'spec.rkeConfig.registries.mirrors', {});
42
- }
43
42
  },
44
43
 
45
44
  computed: {
@@ -78,7 +78,6 @@ export default {
78
78
  <div class="row">
79
79
  <Checkbox
80
80
  :value="showCustomRegistryInput"
81
- class="mb-20"
82
81
  :label="t('cluster.privateRegistry.label')"
83
82
  data-testid="registries-enable-checkbox"
84
83
  @update:value="$emit('custom-registry-changed', $event)"
@@ -86,7 +85,7 @@ export default {
86
85
  </div>
87
86
  <div
88
87
  v-if="showCustomRegistryInput"
89
- class="row"
88
+ class="row mt-20"
90
89
  >
91
90
  <div class="col span-6">
92
91
  <LabeledInput
@@ -114,7 +113,6 @@ export default {
114
113
  </div>
115
114
  </div>
116
115
  <div
117
- v-if="showCustomRegistryInput"
118
116
  class="row"
119
117
  >
120
118
  <AdvancedSection
@@ -34,23 +34,30 @@ export default {
34
34
  },
35
35
 
36
36
  data() {
37
- const out = {};
37
+ return {
38
+ deleteEmptyDirData: DEFAULTS.deleteEmptyDirData,
39
+ disableEviction: DEFAULTS.disableEviction,
40
+ enabled: DEFAULTS.enabled,
41
+ force: DEFAULTS.force,
42
+ gracePeriod: DEFAULTS.gracePeriod,
43
+ ignoreDaemonSets: DEFAULTS.ignoreDaemonSets,
44
+ skipWaitForDeleteTimeoutSeconds: DEFAULTS.skipWaitForDeleteTimeoutSeconds,
45
+ timeout: DEFAULTS.timeout,
46
+ };
47
+ },
38
48
 
49
+ created() {
39
50
  for ( const k in DEFAULTS ) {
40
51
  if ( typeof this.value[k] === 'undefined' ) {
41
- out[k] = DEFAULTS[k];
52
+ this.$data[k] = DEFAULTS[k];
42
53
  } else {
43
- out[k] = this.value[k];
54
+ this.$data[k] = this.value[k];
44
55
  }
45
56
  }
46
57
 
47
- out.customGracePeriod = out.gracePeriod >= 0;
48
- out.customTimeout = out.timeout >= 0;
58
+ this.customGracePeriod = this.gracePeriod >= 0;
59
+ this.customTimeout = this.timeout >= 0;
49
60
 
50
- return out;
51
- },
52
-
53
- created() {
54
61
  this.update();
55
62
  },
56
63
 
@@ -49,6 +49,7 @@ export default {
49
49
  required
50
50
  :label="t('secret.basic.username')"
51
51
  :mode="mode"
52
+ data-testid="secret-basic-username"
52
53
  />
53
54
  </div>
54
55
  <div class="col span-6">
@@ -1,22 +1,23 @@
1
1
  <script>
2
2
  import { SECRET_TYPES as TYPES } from '@shell/config/secret';
3
- import { MANAGEMENT, NAMESPACE, DEFAULT_WORKSPACE } from '@shell/config/types';
3
+ import {
4
+ SECRET_SCOPE, SECRET_QUERY_PARAMS,
5
+ CLOUD_CREDENTIAL, _CLONE, _CREATE, _EDIT, _FLAGGED
6
+ } from '@shell/config/query-params';
7
+ import { MANAGEMENT, NAMESPACE, DEFAULT_WORKSPACE, VIRTUAL_TYPES } from '@shell/config/types';
8
+ import { CAPI, UI_PROJECT_SECRET } from '@shell/config/labels-annotations';
9
+ import FormValidation from '@shell/mixins/form-validation';
4
10
  import CreateEditView from '@shell/mixins/create-edit-view';
5
11
  import NameNsDescription from '@shell/components/form/NameNsDescription';
6
12
  import { LabeledInput } from '@components/Form/LabeledInput';
7
13
  import LabeledSelect from '@shell/components/form/LabeledSelect';
8
14
  import CruResource from '@shell/components/CruResource';
9
- import {
10
- CLOUD_CREDENTIAL, _CLONE, _CREATE, _EDIT, _FLAGGED
11
- } from '@shell/config/query-params';
12
15
  import Loading from '@shell/components/Loading';
13
16
  import Tabbed from '@shell/components/Tabbed';
14
17
  import Tab from '@shell/components/Tabbed/Tab';
15
18
  import Labels from '@shell/components/form/Labels';
16
19
  import { HIDE_SENSITIVE } from '@shell/store/prefs';
17
- import { CAPI } from '@shell/config/labels-annotations';
18
20
  import { clear, uniq } from '@shell/utils/array';
19
- import { NAME as MANAGER } from '@shell/config/product/manager';
20
21
  import SelectIconGrid from '@shell/components/SelectIconGrid';
21
22
  import { sortBy } from '@shell/utils/sort';
22
23
  import { ucFirst } from '@shell/utils/string';
@@ -46,12 +47,34 @@ export default {
46
47
  SelectIconGrid
47
48
  },
48
49
 
49
- mixins: [CreateEditView],
50
+ mixins: [CreateEditView, FormValidation],
50
51
 
51
52
  async fetch() {
52
53
  if ( this.isCloud ) {
53
54
  this.nodeDrivers = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE_DRIVER });
54
55
  }
56
+
57
+ const projectScopedLabel = this.value.metadata?.labels?.[UI_PROJECT_SECRET];
58
+ const isProjectScoped = !!projectScopedLabel || (this.isCreate && this.$route.query[SECRET_SCOPE] === SECRET_QUERY_PARAMS.PROJECT_SCOPED);
59
+
60
+ this.isProjectScoped = isProjectScoped;
61
+
62
+ if (isProjectScoped) {
63
+ // If ssp is enabled the store not have all projects. ensure we have them all
64
+ await this.$store.dispatch('management/findAll', { type: MANAGEMENT.PROJECT });
65
+ if (this.isCreate) {
66
+ // Pick first project as default
67
+ this.projectName = this.filteredProjects[0].metadata.name;
68
+
69
+ this.value.metadata.labels = this.value.metadata.labels || {};
70
+
71
+ // Set namespace and project-scoped label
72
+ this.value.metadata.namespace = this.filteredProjects[0].status.backingNamespace;
73
+ this.value.metadata.labels[UI_PROJECT_SECRET] = this.filteredProjects[0].metadata.name;
74
+ } else {
75
+ this.projectName = this.filteredProjects.find((p) => p.metadata.name === projectScopedLabel).metadata.name;
76
+ }
77
+ }
55
78
  },
56
79
 
57
80
  data() {
@@ -89,14 +112,50 @@ export default {
89
112
 
90
113
  return {
91
114
  isCloud,
115
+ isProjectScoped: false,
92
116
  nodeDrivers: null,
93
117
  secretTypes,
94
118
  secretType: this.value._type,
95
- initialSecretType: this.value._type
119
+ initialSecretType: this.value._type,
120
+ projectName: null,
121
+ fvFormRuleSets: [
122
+ {
123
+ path: 'metadata.name',
124
+ rules: ['required'],
125
+ },
126
+ {
127
+ path: 'metadata.namespace',
128
+ rules: ['required'],
129
+ },
130
+ ],
96
131
  };
97
132
  },
98
133
 
99
134
  computed: {
135
+ clusterId() {
136
+ return this.$store.getters['currentCluster'].id;
137
+ },
138
+
139
+ filteredProjects() {
140
+ const allProjects = this.$store.getters['management/all'](MANAGEMENT.PROJECT);
141
+
142
+ return allProjects.filter((p) => p.spec?.clusterName === this.clusterId);
143
+ },
144
+
145
+ projectOpts() {
146
+ let projects = this.$store.getters['management/all'](MANAGEMENT.PROJECT);
147
+
148
+ // Filter out projects not for the current cluster
149
+ projects = projects.filter((c) => c.spec?.clusterName === this.clusterId);
150
+ const out = projects.map((project) => {
151
+ return {
152
+ label: project.nameDisplay,
153
+ value: project.metadata.name,
154
+ };
155
+ });
156
+
157
+ return out;
158
+ },
100
159
  isCustomSecretCreate() {
101
160
  return this.mode === _CREATE && this.$route.query.type === 'custom';
102
161
  },
@@ -214,12 +273,15 @@ export default {
214
273
  }
215
274
  },
216
275
 
217
- doneRoute() {
218
- if ( this.$store.getters['currentProduct'].name === MANAGER ) {
219
- return 'c-cluster-manager-secret';
220
- } else {
221
- return 'c-cluster-product-resource';
276
+ doneLocationOverride() {
277
+ if (this.isProjectScoped) {
278
+ return {
279
+ ...this.value.listLocation,
280
+ params: { resource: VIRTUAL_TYPES.PROJECT_SECRETS }
281
+ };
222
282
  }
283
+
284
+ return this.value.listLocation;
223
285
  },
224
286
  },
225
287
 
@@ -251,6 +313,13 @@ export default {
251
313
  }
252
314
  }
253
315
 
316
+ if (this.isProjectScoped) {
317
+ // Always create project-scoped secrets in the upstream local cluster
318
+ const url = this.$store.getters['management/urlFor'](this.value.type, this.value.id);
319
+
320
+ return this.save(btnCb, url);
321
+ }
322
+
254
323
  return this.save(btnCb);
255
324
  },
256
325
 
@@ -301,8 +370,25 @@ export default {
301
370
  if (type !== 'custom') {
302
371
  this.value['_type'] = type;
303
372
  }
373
+ },
374
+
375
+ redirectAfterCancel() {
376
+ this.$router.replace(this.doneLocationOverride);
304
377
  }
305
378
  },
379
+
380
+ watch: {
381
+ projectName(neu) {
382
+ if (this.isCreate && neu) {
383
+ this.value.metadata.labels = this.value.metadata.labels || {};
384
+ this.value.metadata.labels[UI_PROJECT_SECRET] = neu;
385
+
386
+ const projectScopedNamespace = this.filteredProjects.find((p) => p.metadata.name === neu).status.backingNamespace;
387
+
388
+ this.value.metadata.namespace = projectScopedNamespace;
389
+ }
390
+ }
391
+ }
306
392
  };
307
393
  </script>
308
394
 
@@ -312,22 +398,47 @@ export default {
312
398
  <CruResource
313
399
  v-else
314
400
  :mode="mode"
315
- :validation-passed="true"
401
+ :validation-passed="fvFormIsValid"
316
402
  :selected-subtype="value._type"
317
403
  :resource="value"
318
404
  :errors="errors"
319
- :done-route="doneRoute"
320
405
  :subtypes="secretSubTypes"
406
+ :cancel-event="true"
407
+ :done-route="doneLocationOverride"
321
408
  @finish="saveSecret"
322
409
  @select-type="selectType"
323
410
  @error="e=>errors = e"
411
+ @cancel="redirectAfterCancel"
324
412
  >
325
413
  <NameNsDescription
414
+ v-if="!isProjectScoped"
326
415
  :value="value"
327
416
  :mode="mode"
328
417
  :namespaced="!isCloud"
329
418
  @update:value="$emit('input', $event)"
330
419
  />
420
+ <NameNsDescription
421
+ v-else
422
+ :value="value"
423
+ :namespaced="false"
424
+ :mode="mode"
425
+ :rules="{
426
+ name: fvGetAndReportPathRules('metadata.name'),
427
+ namespace: fvGetAndReportPathRules('metadata.namespace'),
428
+ }"
429
+ >
430
+ <template #project-selector>
431
+ <LabeledSelect
432
+ v-model:value="projectName"
433
+ class="mr-20"
434
+ :disabled="!isCreate"
435
+ :label="t('namespace.project.label')"
436
+ :options="projectOpts"
437
+ required
438
+ data-testid="secret-project-select"
439
+ />
440
+ </template>
441
+ </NameNsDescription>
331
442
 
332
443
  <div
333
444
  v-if="isCustomSecretCreate"
@@ -20,19 +20,10 @@ export default {
20
20
  },
21
21
  },
22
22
  data() {
23
- return { selectedName: null, closedErrorMessages: [] };
23
+ return { selectedName: null, errors: [] };
24
24
  },
25
- computed: {
26
- ...mapGetters({ t: 'i18n/t' }),
27
- errorMessages() {
28
- if (!this.type) {
29
- return [];
30
- }
31
-
32
- return this.fvUnreportedValidationErrors.filter((e) => !this.closedErrorMessages.includes(e));
33
- }
34
- },
35
- methods: {
25
+ computed: { ...mapGetters({ t: 'i18n/t' }) },
26
+ methods: {
36
27
  changed(tab) {
37
28
  const key = this.idKey;
38
29
 
@@ -94,7 +85,7 @@ export default {
94
85
  :selected-subtype="type"
95
86
  :resource="value"
96
87
  :mode="mode"
97
- :errors="errorMessages"
88
+ :errors="errors"
98
89
  :done-route="doneRoute"
99
90
  :subtypes="workloadSubTypes"
100
91
  :apply-hooks="applyHooks"
@@ -102,7 +93,7 @@ export default {
102
93
  :errors-map="getErrorsMap(fvUnreportedValidationErrors)"
103
94
  @finish="save"
104
95
  @select-type="selectType"
105
- @error="(_, closedError) => closedErrorMessages.push(closedError)"
96
+ @error="e=>errors = e"
106
97
  >
107
98
  <NameNsDescription
108
99
  :value="value"