@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
@@ -0,0 +1,224 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { _CREATE, _EDIT, _VIEW } from '@shell/config/query-params';
3
+ import HelmOp from '@shell/models/fleet.cattle.io.helmop';
4
+ import HelmOpComponent from '@shell/edit/fleet.cattle.io.helmop.vue';
5
+
6
+ const mockStore = {
7
+ dispatch: jest.fn(),
8
+ commit: jest.fn(),
9
+ getters: {
10
+ 'i18n/t': (text: string) => text,
11
+ 'i18n/exists': jest.fn(),
12
+ t: (text: string) => text,
13
+ currentStore: () => 'current_store',
14
+ 'current_store/schemaFor': jest.fn(),
15
+ 'current_store/all': jest.fn(),
16
+ workspace: 'test',
17
+ },
18
+ rootGetters: { 'i18n/t': jest.fn() },
19
+ };
20
+
21
+ const mocks = {
22
+ $store: mockStore,
23
+ $fetchState: { pending: false },
24
+ $route: {
25
+ query: { AS: '' },
26
+ name: {
27
+ endsWith: () => {
28
+ return false;
29
+ }
30
+ }
31
+ },
32
+ };
33
+
34
+ const mockComputed = {
35
+ ...HelmOpComponent.computed,
36
+ steps: () => [{
37
+ name: 'advanced',
38
+ title: 'title',
39
+ label: 'label',
40
+ subtext: 'subtext',
41
+ descriptionKey: 'description',
42
+ ready: true,
43
+ weight: 1,
44
+ }],
45
+ };
46
+
47
+ const mockHelmOp = {
48
+ type: 'fleet.cattle.io.helmop',
49
+ apiVersion: 'fleet.cattle.io/v1alpha1',
50
+ kind: 'HelmOp',
51
+ metadata: {
52
+ name: 'test',
53
+ namespace: 'test1',
54
+ },
55
+ spec: {
56
+ targetNamespace: 'custom-namespace-name',
57
+ helm: {},
58
+ targets: [
59
+ { clusterName: `fleet-local` }
60
+ ],
61
+ },
62
+ status: {},
63
+ currentRoute: () => {},
64
+ };
65
+
66
+ const initHelmOp = (props: any, value?: any) => {
67
+ const initValue = new HelmOp({
68
+ ...mockHelmOp,
69
+ ...(value || {})
70
+ }, {
71
+ getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
72
+ dispatch: jest.fn(),
73
+ rootGetters: { 'i18n/t': jest.fn() },
74
+ });
75
+
76
+ return {
77
+ props: {
78
+ value: initValue,
79
+ ...props
80
+ },
81
+ computed: mockComputed,
82
+ global: { mocks },
83
+ };
84
+ };
85
+
86
+ describe('view: fleet.cattle.io.helmop, mode: view', () => {
87
+ it('should hide advanced options banner', () => {
88
+ const wrapper = mount(HelmOpComponent, initHelmOp({ mode: _VIEW }));
89
+
90
+ const advancedInfoBanner = wrapper.find('[data-testid="helmOp-advanced-info"]');
91
+
92
+ expect(advancedInfoBanner.exists()).toBe(false);
93
+ });
94
+ });
95
+
96
+ describe.each([
97
+ _CREATE,
98
+ _EDIT,
99
+ ])('view: fleet.cattle.io.helmop, mode: %p', (mode) => {
100
+ const wrapper = mount(HelmOpComponent, initHelmOp({ mode }));
101
+
102
+ it('should show advanced options banner', () => {
103
+ const advancedInfoBanner = wrapper.find('[data-testid="helmOp-advanced-info"]');
104
+
105
+ expect(advancedInfoBanner.exists()).toBeTruthy();
106
+ });
107
+
108
+ it.each([
109
+ ['not display', ' OCI registry', 'chart', 'oci://foo', false],
110
+ ['not display', 'Tarball', 'https://foo', '', false],
111
+ ['display', 'Repository', 'bar', 'https://foo', true],
112
+ ])('should %p Polling section if source is %p', (
113
+ descr1,
114
+ descr2,
115
+ chart,
116
+ repo,
117
+ visible
118
+ ) => {
119
+ const wrapper = mount(HelmOpComponent, initHelmOp({ realMode: mode }, {
120
+ spec: {
121
+ pollingInterval: 20,
122
+ helm: {
123
+ chart,
124
+ repo,
125
+ version: '1.2.x'
126
+ }
127
+ },
128
+ }));
129
+
130
+ const pollingCheckbox = wrapper.findComponent('[data-testid="helmOp-enablePolling-checkbox"]');
131
+
132
+ expect(pollingCheckbox.exists()).toBe(visible);
133
+ });
134
+
135
+ it.each([
136
+ ['disabled', 'not display', '1.2.3', undefined, false, false],
137
+ ['disabled', 'not display', '1.2.3', null, false, false],
138
+ ['disabled', 'not display', '1.2.3', 0, false, false],
139
+ ['disabled', 'not display', '1.2.3', 10, false, false],
140
+ ['disabled', 'not display', '1.2.3', 30, false, false],
141
+ ['disabled', 'not display', '', 0, false, false],
142
+ ['disabled', 'not display', null, 0, false, false],
143
+ ['enabled', 'display', '1.2.x', 10, true, true],
144
+ ['enabled', 'not display', '1.2.x', 30, true, false],
145
+ ])('should show Polling %p and %p min-value warning, with spec.version: %p and spec.disablePolling: %p', (
146
+ descr1,
147
+ descr2,
148
+ version,
149
+ pollingInterval,
150
+ enabled,
151
+ minValueWarnVisible
152
+ ) => {
153
+ const wrapper = mount(HelmOpComponent, initHelmOp({ realMode: mode }, {
154
+ spec: {
155
+ pollingInterval,
156
+ helm: {
157
+ chart: 'foo',
158
+ repo: 'https://foo',
159
+ version
160
+ }
161
+ },
162
+ }));
163
+
164
+ const pollingCheckbox = wrapper.findComponent('[data-testid="helmOp-enablePolling-checkbox"]') as any;
165
+ const pollingIntervalInput = wrapper.find('[data-testid="helmOp-pollingInterval-input"]');
166
+ const pollingIntervalMinimumValueWarning = wrapper.find('[data-testid="helmOp-pollingInterval-minimumValueWarning"]');
167
+
168
+ expect(pollingCheckbox.exists()).toBe(true);
169
+ expect(pollingCheckbox.vm.value).toBe(enabled);
170
+ expect(pollingCheckbox.element.classList.value.includes('v-popper--has-tooltip')).toBe(!enabled);
171
+ expect(pollingIntervalInput.exists()).toBe(enabled);
172
+ expect(pollingIntervalMinimumValueWarning.exists()).toBe(minValueWarnVisible);
173
+ });
174
+
175
+ it('should disable Polling Interval', async() => {
176
+ const wrapper = mount(HelmOpComponent, initHelmOp({ realMode: mode }, {
177
+ spec: {
178
+ pollingInterval: 10,
179
+ helm: {
180
+ chart: 'foo',
181
+ repo: 'https://foo',
182
+ version: '1.2.x'
183
+ }
184
+ },
185
+ }));
186
+
187
+ wrapper.vm.togglePolling(false);
188
+
189
+ await wrapper.vm.$nextTick();
190
+
191
+ const pollingIntervalInput = wrapper.find('[data-testid="helmOp-pollingInterval-input"]');
192
+
193
+ expect(pollingIntervalInput.exists()).toBe(false);
194
+ });
195
+
196
+ it.each([
197
+ ['15', null],
198
+ ['15', 0],
199
+ ['30', 30],
200
+ ])('should set minimum Polling Interval to %p when input value is %p', async(
201
+ displayValue,
202
+ inputValue
203
+ ) => {
204
+ const wrapper = mount(HelmOpComponent, initHelmOp({ realMode: mode }, {
205
+ spec: {
206
+ pollingInterval: 10,
207
+ helm: {
208
+ chart: 'foo',
209
+ repo: 'https://foo',
210
+ version: '1.2.x'
211
+ }
212
+ },
213
+ }));
214
+
215
+ wrapper.vm.pollingInterval = inputValue;
216
+ wrapper.vm.updatePollingInterval(inputValue);
217
+
218
+ await wrapper.vm.$nextTick();
219
+
220
+ const pollingIntervalInput = wrapper.find('[data-testid="helmOp-pollingInterval-input"]').element as HTMLInputElement;
221
+
222
+ expect(pollingIntervalInput.value).toBe(displayValue);
223
+ });
224
+ });
@@ -41,4 +41,18 @@ describe('lDAP config', () => {
41
41
  expect(userLoginFilter.element.value).toBe(expectedValue);
42
42
  expect(wrapper.vm.model.userLoginFilter).toBeUndefined();
43
43
  });
44
+
45
+ it.each([
46
+ 'openldap', 'freeipa'
47
+ ])('should display searchUsingServiceAccount checkbox if type %p', (type) => {
48
+ const wrapper = mount(LDAPConfig, {
49
+ propsData: {
50
+ value: {},
51
+ type,
52
+ }
53
+ });
54
+ const checkbox = wrapper.find('[data-testid="searchUsingServiceAccount"]');
55
+
56
+ expect(checkbox).toBeDefined();
57
+ });
44
58
  });
@@ -11,6 +11,8 @@ const DEFAULT_TLS_PORT = 636;
11
11
 
12
12
  export const SHIBBOLETH = 'shibboleth';
13
13
  export const OKTA = 'okta';
14
+ export const OPEN_LDAP = 'openldap';
15
+ export const FREE_IPA = 'freeipa';
14
16
 
15
17
  export default {
16
18
  emits: ['update:value'],
@@ -64,6 +66,11 @@ export default {
64
66
  // Does the auth provider support LDAP for search in addition to SAML?
65
67
  isSamlProvider() {
66
68
  return this.type === SHIBBOLETH || this.type === OKTA;
69
+ },
70
+
71
+ // Allow to enable user search just for these providers
72
+ isSearchAllowed() {
73
+ return this.type === OPEN_LDAP || this.type === FREE_IPA;
67
74
  }
68
75
  },
69
76
 
@@ -226,6 +233,23 @@ export default {
226
233
  />
227
234
  </div>
228
235
  </div>
236
+
237
+ <div
238
+ v-if="isSearchAllowed"
239
+ class="row mb-20"
240
+ >
241
+ <div class="col">
242
+ <Checkbox
243
+ v-model:value="model.searchUsingServiceAccount"
244
+ :mode="mode"
245
+ data-testid="searchUsingServiceAccount"
246
+ class="full-height"
247
+ :label="t('authConfig.ldap.searchUsingServiceAccount.label')"
248
+ :tooltip="t('authConfig.ldap.searchUsingServiceAccount.tip')"
249
+ />
250
+ </div>
251
+ </div>
252
+
229
253
  <div class="row mb-20">
230
254
  <div class="col span-6">
231
255
  <LabeledInput
@@ -79,7 +79,7 @@ export default {
79
79
  });
80
80
 
81
81
  try {
82
- this.defaultConfigMap = await this.$store.dispatch('cluster/find', { type: CONFIG_MAP, id: 'rancher-compliance-system/default-clusterscanprofiles' });
82
+ this.defaultConfigMap = await this.$store.dispatch('cluster/find', { type: CONFIG_MAP, id: 'compliance-operator-system/default-clusterscanprofiles' });
83
83
  } catch {}
84
84
 
85
85
  this.allProfiles = hash.profiles;
@@ -1,4 +1,5 @@
1
1
  <script>
2
+ import jsyaml from 'js-yaml';
2
3
  import CreateEditView from '@shell/mixins/create-edit-view';
3
4
  import CruResource from '@shell/components/CruResource';
4
5
  import NameNsDescription from '@shell/components/form/NameNsDescription';
@@ -66,7 +67,9 @@ export default {
66
67
  const yaml = await this.$refs.cru.createResourceYaml(this.yamlModifiers);
67
68
 
68
69
  try {
69
- await this.value.saveYaml(yaml);
70
+ const initialYaml = jsyaml.dump(this.initialValue);
71
+
72
+ await this.value.saveYaml(yaml, initialYaml);
70
73
  this.done();
71
74
  } catch (err) {
72
75
  this.errors.push(err);
@@ -23,7 +23,9 @@ import FleetClusterTargets from '@shell/components/fleet/FleetClusterTargets/ind
23
23
  import { toSeconds } from '@shell/utils/duration';
24
24
  import FleetGitRepoPaths from '@shell/components/fleet/FleetGitRepoPaths.vue';
25
25
  import FleetOCIStorageSecret from '@shell/components/fleet/FleetOCIStorageSecret.vue';
26
- import { DEFAULT_POLLING_INTERVAL, MINIMUM_POLLING_INTERVAL } from '@shell/models/fleet-application';
26
+
27
+ const MINIMUM_POLLING_INTERVAL = 15;
28
+ const DEFAULT_POLLING_INTERVAL = 60;
27
29
 
28
30
  const _VERIFY = 'verify';
29
31
  const _SKIP = 'skip';
@@ -105,10 +107,7 @@ export default {
105
107
  targetsCreated: '',
106
108
  fvFormRuleSets: [{
107
109
  path: 'spec.repo',
108
- rules: [
109
- 'required',
110
- 'urlRepository'
111
- ],
110
+ rules: ['urlRepository'],
112
111
  }],
113
112
  touched: null,
114
113
  };
@@ -636,7 +635,7 @@ export default {
636
635
  <Banner
637
636
  v-if="showPollingIntervalWarning"
638
637
  color="warning"
639
- label-key="fleet.gitRepo.polling.pollingInterval.minimumValuewarning"
638
+ label-key="fleet.gitRepo.polling.pollingInterval.minimumValueWarning"
640
639
  data-testid="gitRepo-pollingInterval-minimumValueWarning"
641
640
  />
642
641
  <Banner
@@ -1,10 +1,11 @@
1
1
  <script>
2
2
  import { clone, set } from '@shell/utils/object';
3
+ import semver from 'semver';
3
4
  import jsyaml from 'js-yaml';
4
5
  import { saferDump } from '@shell/utils/create-yaml';
5
6
  import { mapGetters } from 'vuex';
6
7
  import { base64Encode } from '@shell/utils/crypto';
7
- import { _CREATE, _EDIT, _VIEW } from '@shell/config/query-params';
8
+ import { _CREATE, _EDIT } from '@shell/config/query-params';
8
9
  import { checkSchemasForFindAllHash } from '@shell/utils/auth';
9
10
  import { AUTH_TYPE, CONFIG_MAP, NORMAN, SECRET } from '@shell/config/types';
10
11
  import { CATALOG, FLEET as FLEET_LABELS } from '@shell/config/labels-annotations';
@@ -27,9 +28,10 @@ import { SECRET_TYPES } from '@shell/config/secret';
27
28
  import UnitInput from '@shell/components/form/UnitInput';
28
29
  import FleetClusterTargets from '@shell/components/fleet/FleetClusterTargets/index.vue';
29
30
  import { toSeconds } from '@shell/utils/duration';
30
- import { DEFAULT_POLLING_INTERVAL, MINIMUM_POLLING_INTERVAL } from '@shell/models/fleet-application';
31
31
  import FleetValuesFrom from '@shell/components/fleet/FleetValuesFrom.vue';
32
32
 
33
+ const MINIMUM_POLLING_INTERVAL = 15;
34
+
33
35
  const VALUES_STATE = {
34
36
  YAML: 'YAML',
35
37
  DIFF: 'DIFF'
@@ -77,17 +79,6 @@ export default {
77
79
  },
78
80
 
79
81
  data() {
80
- let pollingInterval = toSeconds(this.value.spec.pollingInterval) || this.value.spec.pollingInterval;
81
-
82
- if (!pollingInterval) {
83
- if (this.realMode === _CREATE) {
84
- pollingInterval = DEFAULT_POLLING_INTERVAL;
85
- this.value.spec.pollingInterval = this.durationSeconds(pollingInterval);
86
- } else if (this.realMode === _EDIT || this.realMode === _VIEW) {
87
- pollingInterval = MINIMUM_POLLING_INTERVAL;
88
- }
89
- }
90
-
91
82
  const correctDriftEnabled = this.value.spec?.correctDrift?.enabled || false;
92
83
 
93
84
  const chartValues = saferDump(clone(this.value.spec.helm.values));
@@ -96,7 +87,7 @@ export default {
96
87
  VALUES_STATE,
97
88
  SOURCE_TYPE,
98
89
  allWorkspaces: [],
99
- pollingInterval,
90
+ pollingInterval: toSeconds(this.value.spec.pollingInterval) || this.value.spec.pollingInterval,
100
91
  sourceTypeInit: this.value.sourceType,
101
92
  sourceType: this.value.sourceType || SOURCE_TYPE.REPO,
102
93
  helmSpecInit: clone(this.value.spec.helm),
@@ -221,9 +212,25 @@ export default {
221
212
  return EDITOR_MODES.EDIT_CODE;
222
213
  },
223
214
 
224
- showPollingIntervalWarning() {
225
- return !this.isView && this.value.isPollingEnabled && this.pollingInterval < MINIMUM_POLLING_INTERVAL;
215
+ isNullOrStaticVersion() {
216
+ return !this.value.spec.helm.version || semver.valid(this.value.spec.helm.version) !== null;
217
+ },
218
+
219
+ isPollingEnabled() {
220
+ return !this.isNullOrStaticVersion && !!this.value.spec.pollingInterval;
221
+ },
222
+
223
+ showPollingIntervalMinValueWarning() {
224
+ return !this.isView && this.isPollingEnabled && this.pollingInterval < MINIMUM_POLLING_INTERVAL;
226
225
  },
226
+
227
+ enablePollingTooltip() {
228
+ if (this.isNullOrStaticVersion) {
229
+ return this.t('fleet.helmOp.polling.pollingInterval.versionTooltip', { version: this.value.spec.helm.version || '' }, true);
230
+ }
231
+
232
+ return null;
233
+ }
227
234
  },
228
235
 
229
236
  watch: {
@@ -255,22 +262,21 @@ export default {
255
262
  this.value.spec.targets = value;
256
263
  },
257
264
 
258
- enablePolling(value) {
265
+ togglePolling(value) {
259
266
  if (value) {
260
- delete this.value.spec.disablePolling;
267
+ this.pollingInterval = this.pollingInterval ?? MINIMUM_POLLING_INTERVAL;
268
+ this.value.spec.pollingInterval = this.value.spec.pollingInterval ?? this.durationSeconds(MINIMUM_POLLING_INTERVAL);
261
269
  } else {
262
- this.value.spec.disablePolling = true;
270
+ delete this.value.spec.pollingInterval;
263
271
  }
264
272
  },
265
273
 
266
274
  updatePollingInterval(value) {
267
- if (!value) {
268
- this.pollingInterval = DEFAULT_POLLING_INTERVAL;
269
- this.value.spec.pollingInterval = this.durationSeconds(DEFAULT_POLLING_INTERVAL);
270
- } else if (value === MINIMUM_POLLING_INTERVAL) {
271
- delete this.value.spec.pollingInterval;
272
- } else {
275
+ if (value) {
273
276
  this.value.spec.pollingInterval = this.durationSeconds(value);
277
+ } else {
278
+ this.pollingInterval = MINIMUM_POLLING_INTERVAL;
279
+ this.value.spec.pollingInterval = this.durationSeconds(MINIMUM_POLLING_INTERVAL);
274
280
  }
275
281
  },
276
282
 
@@ -398,22 +404,28 @@ export default {
398
404
  case SOURCE_TYPE.REPO:
399
405
  this.fvFormRuleSets = [{
400
406
  path: 'spec.helm.repo',
401
- rules: ['required', 'urlRepository'],
407
+ rules: ['urlRepository'],
402
408
  }, {
403
409
  path: 'spec.helm.chart',
404
410
  rules: ['required'],
411
+ }, {
412
+ path: 'spec.helm.version',
413
+ rules: ['semanticVersion'],
405
414
  }];
406
415
  break;
407
416
  case SOURCE_TYPE.OCI:
408
417
  this.fvFormRuleSets = [{
409
418
  path: 'spec.helm.repo',
410
- rules: ['required', 'ociRegistry'],
419
+ rules: ['ociRegistry'],
420
+ }, {
421
+ path: 'spec.helm.version',
422
+ rules: ['semanticVersion'],
411
423
  }];
412
424
  break;
413
425
  case SOURCE_TYPE.TARBALL:
414
426
  this.fvFormRuleSets = [{
415
427
  path: 'spec.helm.chart',
416
- rules: ['required', 'urlRepository'],
428
+ rules: ['urlRepository'],
417
429
  }];
418
430
  break;
419
431
  }
@@ -535,6 +547,7 @@ export default {
535
547
  :mode="mode"
536
548
  label-key="fleet.helmOp.source.version.label"
537
549
  :placeholder="t('fleet.helmOp.source.version.placeholder', null, true)"
550
+ :rules="fvGetAndReportPathRules('spec.helm.version')"
538
551
  />
539
552
  </div>
540
553
  </div>
@@ -558,6 +571,7 @@ export default {
558
571
  :mode="mode"
559
572
  label-key="fleet.helmOp.source.version.label"
560
573
  :placeholder="t('fleet.helmOp.source.version.placeholder', null, true)"
574
+ :rules="fvGetAndReportPathRules('spec.helm.version')"
561
575
  />
562
576
  </div>
563
577
  </div>
@@ -663,6 +677,7 @@ export default {
663
677
  v-if="!isView"
664
678
  color="info"
665
679
  label-key="fleet.helmOp.add.steps.advanced.info"
680
+ data-testid="helmOp-advanced-info"
666
681
  />
667
682
 
668
683
  <h2 v-t="'fleet.helmOp.auth.title'" />
@@ -713,38 +728,45 @@ export default {
713
728
  />
714
729
  </div>
715
730
 
716
- <h2 v-t="'fleet.helmOp.polling.label'" />
717
- <div class="row polling">
718
- <div class="col span-6">
719
- <Checkbox
720
- :value="value.isPollingEnabled"
721
- type="checkbox"
722
- label-key="fleet.helmOp.polling.enable"
723
- :mode="mode"
724
- @update:value="enablePolling"
725
- />
726
- </div>
727
- <template v-if="value.isPollingEnabled">
728
- <div class="col">
729
- <Banner
730
- v-if="showPollingIntervalWarning"
731
- color="warning"
732
- label-key="fleet.helmOp.polling.pollingInterval.minimumValuewarning"
733
- />
734
- </div>
731
+ <template v-if="sourceType === SOURCE_TYPE.REPO">
732
+ <h2 v-t="'fleet.helmOp.polling.label'" />
733
+ <div class="row polling">
735
734
  <div class="col span-6">
736
- <UnitInput
737
- v-model:value="pollingInterval"
738
- min="1"
739
- :suffix="t('suffix.seconds', { count: pollingInterval })"
740
- :label="t('fleet.helmOp.polling.pollingInterval.label')"
735
+ <Checkbox
736
+ :value="isPollingEnabled"
737
+ type="checkbox"
738
+ label-key="fleet.helmOp.polling.enable"
739
+ data-testid="helmOp-enablePolling-checkbox"
740
+ :tooltip="enablePollingTooltip"
741
741
  :mode="mode"
742
- tooltip-key="fleet.helmOp.polling.pollingInterval.tooltip"
743
- @blur.capture="updatePollingInterval(pollingInterval)"
742
+ :disabled="isNullOrStaticVersion"
743
+ @update:value="togglePolling"
744
744
  />
745
745
  </div>
746
- </template>
747
- </div>
746
+ <template v-if="isPollingEnabled">
747
+ <div class="col">
748
+ <Banner
749
+ v-if="showPollingIntervalMinValueWarning"
750
+ color="warning"
751
+ label-key="fleet.helmOp.polling.pollingInterval.minimumValueWarning"
752
+ data-testid="helmOp-pollingInterval-minimumValueWarning"
753
+ />
754
+ </div>
755
+ <div class="col span-6">
756
+ <UnitInput
757
+ v-model:value="pollingInterval"
758
+ min="1"
759
+ data-testid="helmOp-pollingInterval-input"
760
+ :suffix="t('suffix.seconds', { count: pollingInterval })"
761
+ :label="t('fleet.helmOp.polling.pollingInterval.label')"
762
+ :mode="mode"
763
+ tooltip-key="fleet.helmOp.polling.pollingInterval.tooltip"
764
+ @blur.capture="updatePollingInterval(pollingInterval)"
765
+ />
766
+ </div>
767
+ </template>
768
+ </div>
769
+ </template>
748
770
  </template>
749
771
  </CruResource>
750
772
  </template>
@@ -21,7 +21,7 @@ import YamlEditor, { EDITOR_MODES } from '@shell/components/YamlEditor';
21
21
  export default {
22
22
  components: {
23
23
  Banner, CruResource, Labels, LabeledSelect, NameNsDescription, Tab, Tabbed, YamlEditor, Loading
24
- }, //
24
+ },
25
25
 
26
26
  mixins: [CreateEditView],
27
27
 
@@ -36,11 +36,11 @@ export default {
36
36
  </div>
37
37
  <div class="row">
38
38
  <div class="col span-6">
39
- <LabeledInput
40
- v-model:value="value.endpoint.url"
41
- :mode="mode"
42
- :disabled="disabled"
43
- :label="t('logging.awsElasticsearch.url')"
39
+ <LabeledInput
40
+ v-model:value="value.endpoint.url"
41
+ :mode="mode"
42
+ :disabled="disabled"
43
+ :label="t('logging.awsElasticsearch.url')"
44
44
  />
45
45
  </div>
46
46
  </div>
@@ -51,7 +51,6 @@ export default {
51
51
  </div>
52
52
  </div>
53
53
  <div class="row mb-10">
54
- {{ value.namespace }}
55
54
  <div class="col span-6">
56
55
  <SecretSelector
57
56
  v-model:value="value.endpoint.access_key_id"