@rancher/shell 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/assets/styles/global/_button.scss +5 -1
  2. package/assets/styles/global/_columns.scss +4 -0
  3. package/assets/styles/global/_layout.scss +1 -2
  4. package/assets/styles/global/_select.scss +1 -4
  5. package/assets/styles/themes/_dark.scss +4 -4
  6. package/assets/styles/themes/_light.scss +4 -3
  7. package/assets/styles/themes/_suse.scss +1 -1
  8. package/assets/styles/vendor/vue-select.scss +4 -3
  9. package/assets/translations/en-us.yaml +669 -73
  10. package/assets/translations/zh-hans.yaml +547 -165
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/cloud-credential/azure.vue +23 -0
  13. package/cloud-credential/harvester.vue +25 -62
  14. package/cloud-credential/pnap.vue +80 -0
  15. package/components/.DS_Store +0 -0
  16. package/components/AdvancedSection.vue +9 -2
  17. package/components/Alert.vue +2 -2
  18. package/components/ButtonDropdown.vue +0 -2
  19. package/components/ButtonGroup.vue +1 -0
  20. package/components/CollapsibleCard.vue +0 -1
  21. package/components/CruResource.vue +41 -4
  22. package/components/DetailTop.vue +58 -3
  23. package/components/DisableAuthProviderModal.vue +106 -0
  24. package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
  25. package/components/ExplorerMembers.vue +253 -30
  26. package/components/ExplorerProjectsNamespaces.vue +77 -33
  27. package/components/GrowlManager.vue +3 -3
  28. package/components/IconOrSvg.vue +149 -0
  29. package/components/LogItem.vue +69 -0
  30. package/components/PodSecurityAdmission.vue +302 -0
  31. package/components/PromptModal.vue +1 -0
  32. package/components/ResourceDetail/Masthead.vue +54 -2
  33. package/components/ResourceDetail/index.vue +12 -5
  34. package/components/ResourceList/Masthead.vue +11 -1
  35. package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
  36. package/components/ResourceList/index.vue +53 -12
  37. package/components/ResourceList/resource-list.config.js +7 -0
  38. package/components/ResourceTable.vue +31 -6
  39. package/components/SimpleBox.vue +1 -1
  40. package/components/SortableTable/THead.vue +15 -5
  41. package/components/SortableTable/index.vue +21 -10
  42. package/components/Tabbed/index.vue +20 -15
  43. package/components/__tests__/.DS_Store +0 -0
  44. package/components/__tests__/AsyncButton.test.ts +140 -0
  45. package/components/__tests__/BackLink.test.ts +33 -0
  46. package/components/__tests__/ButtonGroup.test.ts +124 -0
  47. package/components/__tests__/ClusterBadge.test.ts +32 -0
  48. package/components/__tests__/CollapsibleCard.test.ts +64 -0
  49. package/components/__tests__/ConsumptionGauge.test.ts +88 -0
  50. package/components/__tests__/CruResource.test.ts +3 -2
  51. package/components/__tests__/FixedBanner.test.ts +129 -0
  52. package/components/__tests__/GrowlManager.test.ts +147 -0
  53. package/components/__tests__/NamespaceFilter.test.ts +33 -25
  54. package/components/__tests__/PercentageBar.test.ts +32 -0
  55. package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
  56. package/components/auth/AuthBanner.vue +20 -10
  57. package/components/auth/RoleDetailEdit.vue +26 -17
  58. package/components/auth/SelectPrincipal.vue +36 -5
  59. package/components/form/ArrayList.vue +3 -35
  60. package/components/form/ArrayListGrouped.vue +13 -4
  61. package/components/form/ArrayListSelect.vue +5 -5
  62. package/components/form/Error.vue +8 -0
  63. package/components/form/KeyValue.vue +39 -7
  64. package/components/form/LabeledSelect.vue +5 -2
  65. package/components/form/Labels.vue +46 -16
  66. package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
  67. package/components/form/Members/MembershipEditor.vue +12 -12
  68. package/components/form/NameNsDescription.vue +1 -1
  69. package/components/form/NodeScheduling.vue +1 -1
  70. package/components/form/Probe.vue +3 -3
  71. package/components/form/ResourceQuota/Project.vue +6 -6
  72. package/components/form/ResourceTabs/index.vue +1 -6
  73. package/components/form/Security.vue +7 -6
  74. package/components/form/Select.vue +3 -2
  75. package/components/form/SelectOrCreateAuthSecret.vue +22 -29
  76. package/components/form/ServicePorts.vue +8 -0
  77. package/components/form/WorkloadPorts.vue +7 -1
  78. package/components/form/__tests__/ArrayList.test.ts +74 -0
  79. package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
  80. package/components/formatter/Checked.vue +1 -1
  81. package/components/formatter/ClusterLink.vue +5 -0
  82. package/components/formatter/IconIsDefault.vue +2 -2
  83. package/components/formatter/InternalExternalIP.vue +11 -8
  84. package/components/formatter/LiveDuration.vue +78 -0
  85. package/components/formatter/WorkloadHealthScale.vue +5 -3
  86. package/components/nav/Header.vue +6 -3
  87. package/components/nav/NamespaceFilter.vue +146 -63
  88. package/components/nav/TopLevelMenu.vue +22 -19
  89. package/components/nav/WindowManager/ContainerLogs.vue +83 -126
  90. package/components/nav/WindowManager/ContainerShell.vue +9 -7
  91. package/components/nav/WindowManager/Window.vue +2 -0
  92. package/components/nav/WindowManager/index.vue +10 -0
  93. package/config/elemental-types.js +9 -0
  94. package/config/features.js +2 -0
  95. package/config/home-links.js +4 -1
  96. package/config/pod-security-admission.ts +82 -0
  97. package/config/product/apps.js +1 -1
  98. package/config/product/auth.js +6 -5
  99. package/config/product/explorer.js +6 -6
  100. package/config/product/fleet.js +1 -1
  101. package/config/product/manager.js +6 -2
  102. package/config/secret.js +0 -1
  103. package/config/settings.ts +26 -9
  104. package/config/table-headers.js +22 -11
  105. package/config/types.js +4 -1
  106. package/content/docs/zh-hans/getting-started.md +113 -137
  107. package/content/docs/zh-hans/whats-new.md +8 -46
  108. package/creators/pkg/package-lock.json +37 -0
  109. package/creators/pkg/package.json +1 -1
  110. package/detail/catalog.cattle.io.app.vue +1 -1
  111. package/detail/pod.vue +1 -1
  112. package/detail/provisioning.cattle.io.cluster.vue +35 -9
  113. package/detail/service.vue +2 -9
  114. package/detail/workload/index.vue +0 -1
  115. package/dialog/AddClusterMemberDialog.vue +22 -28
  116. package/dialog/AddProjectMemberDialog.vue +53 -9
  117. package/dialog/DiagnosticTimingsDialog.vue +8 -7
  118. package/dialog/DrainNode.vue +44 -48
  119. package/dialog/ForceMachineRemoveDialog.vue +5 -7
  120. package/dialog/GenericPrompt.vue +15 -20
  121. package/dialog/RollbackWorkloadDialog.vue +15 -46
  122. package/dialog/RotateCertificatesDialog.vue +5 -7
  123. package/dialog/RotateEncryptionKeyDialog.vue +5 -9
  124. package/dialog/SaveAsRKETemplateDialog.vue +5 -13
  125. package/dialog/ScaleMachineDownDialog.vue +1 -1
  126. package/dialog/ScalePoolDownDialog.vue +121 -0
  127. package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
  128. package/edit/auth/azuread.vue +16 -16
  129. package/edit/auth/github.vue +8 -0
  130. package/edit/auth/googleoauth.vue +10 -1
  131. package/edit/auth/ldap/index.vue +10 -0
  132. package/edit/auth/oidc.vue +10 -0
  133. package/edit/auth/saml.vue +10 -0
  134. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
  135. package/edit/cloudcredential.vue +3 -7
  136. package/edit/logging-flow/Match.vue +39 -8
  137. package/edit/logging-flow/index.vue +27 -4
  138. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
  139. package/edit/management.cattle.io.project.vue +8 -1
  140. package/edit/management.cattle.io.setting.vue +5 -2
  141. package/edit/management.cattle.io.user.vue +7 -1
  142. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +23 -7
  143. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
  144. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
  145. package/edit/namespace.vue +18 -4
  146. package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
  147. package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
  148. package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
  149. package/edit/networking.k8s.io.ingress/index.vue +8 -6
  150. package/edit/persistentvolume/index.vue +30 -27
  151. package/edit/persistentvolume/plugins/cephfs.vue +29 -29
  152. package/edit/persistentvolume/plugins/csi.vue +102 -62
  153. package/edit/persistentvolume/plugins/fc.vue +19 -19
  154. package/edit/persistentvolume/plugins/iscsi.vue +45 -45
  155. package/edit/persistentvolume/plugins/rbd.vue +39 -39
  156. package/edit/persistentvolumeclaim.vue +78 -75
  157. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
  158. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
  159. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
  160. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
  161. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +93 -0
  162. package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
  164. package/edit/provisioning.cattle.io.cluster/rke2.vue +440 -152
  165. package/edit/secret/index.vue +3 -7
  166. package/edit/service.vue +3 -1
  167. package/edit/storage.k8s.io.storageclass/index.vue +100 -16
  168. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
  169. package/edit/workload/__tests__/index.test.ts +98 -0
  170. package/edit/workload/index.vue +58 -8
  171. package/edit/workload/mixins/workload.js +107 -70
  172. package/edit/workload/storage/ContainerMountPaths.vue +0 -10
  173. package/edit/workload/storage/emptyDir.vue +88 -0
  174. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  175. package/edit/workload/storage/index.vue +8 -0
  176. package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
  177. package/layouts/default.vue +57 -44
  178. package/list/__tests__/workload.test.ts +5 -2
  179. package/list/catalog.cattle.io.app.vue +1 -0
  180. package/list/cis.cattle.io.clusterscan.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +5 -6
  182. package/list/fleet.cattle.io.cluster.vue +6 -3
  183. package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
  184. package/list/fleet.cattle.io.gitrepo.vue +4 -9
  185. package/list/helm.cattle.io.projecthelmchart.vue +1 -5
  186. package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
  187. package/list/logging.banzaicloud.io.flow.vue +6 -5
  188. package/list/management.cattle.io.cluster.vue +1 -0
  189. package/list/management.cattle.io.feature.vue +3 -4
  190. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
  191. package/list/management.cattle.io.setting.vue +2 -2
  192. package/list/management.cattle.io.user.vue +4 -10
  193. package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
  194. package/list/node.vue +8 -5
  195. package/list/persistentvolume.vue +3 -3
  196. package/list/persistentvolumeclaim.vue +3 -4
  197. package/list/provisioning.cattle.io.cluster.vue +18 -19
  198. package/list/service.vue +6 -14
  199. package/list/workload.vue +43 -38
  200. package/machine-config/azure.vue +429 -60
  201. package/machine-config/pnap.vue +288 -0
  202. package/mixins/auth-config.js +1 -3
  203. package/mixins/browser-tab-visibility.js +8 -14
  204. package/mixins/chart.js +1 -1
  205. package/mixins/create-edit-view/impl.js +4 -0
  206. package/mixins/create-edit-view/index.js +4 -2
  207. package/mixins/resource-fetch-namespaced.js +98 -0
  208. package/mixins/resource-fetch.js +79 -45
  209. package/mixins/resource-manager.js +1 -23
  210. package/models/apps.controllerrevision.js +7 -0
  211. package/models/apps.daemonset.js +18 -0
  212. package/models/apps.deployment.js +44 -0
  213. package/models/apps.replicaset.js +7 -0
  214. package/models/apps.statefulset.js +18 -0
  215. package/models/batch.job.js +7 -14
  216. package/models/cluster/node.js +10 -2
  217. package/models/cluster.x-k8s.io.machine.js +26 -4
  218. package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
  219. package/models/event.js +7 -0
  220. package/models/logging.banzaicloud.io.flow.js +4 -0
  221. package/models/management.cattle.io.cluster.js +1 -1
  222. package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
  223. package/models/management.cattle.io.globalrole.js +2 -2
  224. package/models/management.cattle.io.node.js +37 -2
  225. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
  226. package/models/management.cattle.io.project.js +30 -11
  227. package/models/management.cattle.io.setting.js +1 -1
  228. package/models/management.cattle.io.user.js +37 -1
  229. package/models/namespace.js +42 -5
  230. package/models/persistentvolume.js +14 -2
  231. package/models/pod.js +15 -0
  232. package/models/projectroletemplatebinding.js +7 -0
  233. package/models/provisioning.cattle.io.cluster.js +61 -10
  234. package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
  235. package/models/service.js +14 -13
  236. package/models/storage.k8s.io.storageclass.js +33 -18
  237. package/models/workload.js +38 -7
  238. package/nuxt.config.js +27 -17
  239. package/package.json +7 -7
  240. package/pages/about.vue +14 -2
  241. package/pages/c/_cluster/apps/charts/index.vue +4 -3
  242. package/pages/c/_cluster/apps/charts/install.vue +59 -22
  243. package/pages/c/_cluster/auth/config/_id.vue +6 -0
  244. package/pages/c/_cluster/auth/config/index.vue +8 -6
  245. package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
  246. package/pages/c/_cluster/auth/roles/index.vue +1 -1
  247. package/pages/c/_cluster/explorer/index.vue +12 -6
  248. package/pages/c/_cluster/longhorn/index.vue +1 -1
  249. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
  250. package/pages/c/_cluster/monitoring/index.vue +1 -1
  251. package/pages/c/_cluster/neuvector/index.vue +1 -1
  252. package/pages/c/_cluster/settings/performance.vue +48 -2
  253. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +34 -1
  254. package/pages/c/_cluster/uiplugins/index.vue +28 -2
  255. package/pages/diagnostic.vue +5 -4
  256. package/pages/home.vue +105 -30
  257. package/pages/prefs.vue +23 -12
  258. package/pages/rio/mesh.vue +1 -1
  259. package/pkg/dynamic-importer.lib.js +8 -0
  260. package/pkg/vue.config.js +4 -0
  261. package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
  262. package/plugins/dashboard-store/actions.js +32 -25
  263. package/plugins/dashboard-store/getters.js +50 -33
  264. package/plugins/dashboard-store/mutations.js +134 -28
  265. package/plugins/dashboard-store/resource-class.js +21 -41
  266. package/plugins/steve/actions.js +30 -0
  267. package/plugins/steve/caches/resourceCache.js +60 -0
  268. package/plugins/steve/getters.js +44 -1
  269. package/plugins/steve/mutations.js +97 -36
  270. package/plugins/steve/resourceWatcher.js +277 -0
  271. package/plugins/steve/schema.utils.js +25 -0
  272. package/plugins/steve/subscribe.js +288 -115
  273. package/plugins/steve/worker/index.js +17 -0
  274. package/plugins/steve/worker/web-worker.advanced.js +302 -0
  275. package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
  276. package/rancher-components/Card/Card.vue +3 -3
  277. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
  278. package/rancher-components/StringList/StringList.test.ts +45 -420
  279. package/rancher-components/StringList/StringList.vue +1 -10
  280. package/rancher-components/components/Banner/Banner.test.ts +44 -0
  281. package/rancher-components/components/Banner/Banner.vue +129 -61
  282. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
  283. package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
  284. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
  285. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
  286. package/rancher-components/components/StringList/StringList.test.ts +7 -7
  287. package/rancher-components/components/StringList/StringList.vue +21 -15
  288. package/scripts/test-plugins-build.sh +8 -0
  289. package/static/loading-indicator.html +1 -1
  290. package/store/index.js +54 -3
  291. package/store/plugins.js +0 -17
  292. package/store/pnap.js +128 -0
  293. package/store/prefs.js +4 -2
  294. package/store/type-map.js +55 -13
  295. package/types/pod-security-admission.ts +36 -0
  296. package/types/shell/index.d.ts +496 -396
  297. package/utils/__tests__/object.test.ts +17 -1
  298. package/utils/__tests__/pod-security-admission.test.ts +61 -0
  299. package/utils/async.ts +36 -0
  300. package/utils/color.js +45 -0
  301. package/utils/crypto/browserHashUtils.js +18 -0
  302. package/utils/dynamic-importer.js +8 -0
  303. package/utils/install-redirect.js +1 -1
  304. package/utils/object.js +24 -0
  305. package/utils/pod-security-admission.ts +39 -0
  306. package/utils/socket.js +61 -24
  307. package/utils/string.js +2 -0
  308. package/utils/svg-filter.js +301 -0
  309. package/utils/time.js +49 -0
  310. package/utils/validators/cidr.js +4 -0
  311. package/utils/validators/formRules/__tests__/index.test.ts +23 -3
  312. package/utils/validators/formRules/index.ts +14 -0
  313. package/config/product/harvester-manager.js +0 -162
  314. package/edit/harvesterhci.io.management.cluster.vue +0 -153
  315. package/list/harvesterhci.io.management.cluster.vue +0 -241
  316. package/machine-config/harvester.vue +0 -693
  317. package/models/harvesterhci.io.management.cluster.js +0 -228
  318. package/pages/c/_cluster/harvesterManager/index.vue +0 -24
  319. package/rancher-components/Card/Card.test.ts +0 -39
  320. package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
  321. package/rancher-components/Utils/DraggableZone/index.ts +0 -1
  322. package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
@@ -1,15 +1,18 @@
1
- import { addObject, removeObject } from '@shell/utils/array';
1
+ import { addObject } from '@shell/utils/array';
2
2
  import { NAMESPACE, POD, SCHEMA } from '@shell/config/types';
3
3
  import {
4
4
  forgetType,
5
5
  resetStore,
6
6
  loadAll,
7
7
  load,
8
- remove
8
+ remove,
9
+ batchChanges,
10
+ replace
9
11
  } from '@shell/plugins/dashboard-store/mutations';
10
- import { keyForSubscribe } from '@shell/plugins/steve/subscribe';
12
+ import { keyForSubscribe } from '@shell/plugins/steve/resourceWatcher';
11
13
  import { perfLoadAll } from '@shell/plugins/steve/performanceTesting';
12
14
  import Vue from 'vue';
15
+ import { classify } from '@shell/plugins/dashboard-store/classify';
13
16
 
14
17
  function registerNamespace(state, namespace) {
15
18
  let cache = state.podsByNamespace[namespace];
@@ -26,12 +29,99 @@ function registerNamespace(state, namespace) {
26
29
  return cache;
27
30
  }
28
31
 
32
+ /**
33
+ * update the podsByNamespace cache with new or changed pods
34
+ */
35
+ function updatePodsByNamespaceCache(state, ctx, pods, loadAll) {
36
+ if (loadAll) {
37
+ // Clear the entire cache - this is a fresh load
38
+ Object.keys(state.podsByNamespace).forEach((ns) => {
39
+ delete state.podsByNamespace[ns];
40
+ });
41
+ }
42
+
43
+ // Go through all of the pods and populate cache by namespace
44
+ pods.forEach((entry) => {
45
+ const classyResource = state.types[POD].map.get(entry.id) || classify(ctx, entry);
46
+
47
+ const cache = registerNamespace(state, classyResource.namespace); // Raw entry.namespace doesn't exist, so use classy
48
+ const existing = cache.map.get(entry.id);
49
+
50
+ if (existing) {
51
+ // CANNOT BE THE SAME REFERENCE
52
+ replace(existing, entry);
53
+ } else {
54
+ addObject(cache.list, classyResource);
55
+ cache.map.set(entry.id, classyResource);
56
+ }
57
+ });
58
+ }
59
+
60
+ /**
61
+ * clean the podsByNamespace cache of removed pods
62
+ */
63
+ function cleanPodsByNamespaceCache(state, resource) {
64
+ if (resource && resource.type === POD) {
65
+ const cache = state.podsByNamespace[resource.namespace];
66
+
67
+ // Extra defensive check that the cache exists for the namespace being removed
68
+ if (cache) {
69
+ const inList = cache.list.findIndex(p => p.id === resource.id);
70
+
71
+ if ( inList >= 0 ) {
72
+ cache.list.splice(inList, 1);
73
+ }
74
+ cache.map.delete(resource.id);
75
+ }
76
+ } else if (resource && resource.type === NAMESPACE) {
77
+ // Namespace deleted
78
+ delete state.podsByNamespace[resource.id];
79
+ }
80
+ }
81
+
29
82
  export default {
83
+ batchChanges(state, { ctx, batch }) {
84
+ batchChanges(state, { ctx, batch });
85
+
86
+ if (batch[POD]) {
87
+ const newAndChangedPods = Object.entries(batch[POD]).reduce((pods, [id, pod]) => {
88
+ if (pod.id) {
89
+ // resource.create and resource.change
90
+ pods.push(pod);// must NOT be same reference from store
91
+ } else {
92
+ // resource.remove (note - we've already lost the resource in the store, so pass through mocked one)
93
+ cleanPodsByNamespaceCache(state, {
94
+ id,
95
+ type: POD,
96
+ namespace: id.substring(0, id.indexOf('/'))
97
+ });
98
+ }
99
+
100
+ return pods;
101
+ }, []);
102
+
103
+ updatePodsByNamespaceCache(state, ctx, newAndChangedPods, false);
104
+ }
105
+
106
+ if (batch[NAMESPACE]) {
107
+ Object.entries(batch[NAMESPACE]).forEach(([id, namespace]) => {
108
+ if (!namespace.id) {
109
+ // resource.remove (note - we've already lost the resource in the store, so pass through mocked one)
110
+ cleanPodsByNamespaceCache(state, {
111
+ id,
112
+ type: NAMESPACE,
113
+ });
114
+ }
115
+ });
116
+ }
117
+ },
118
+
30
119
  loadAll(state, {
31
120
  type,
32
121
  data,
33
122
  ctx,
34
- skipHaveAll
123
+ skipHaveAll,
124
+ namespace
35
125
  }) {
36
126
  // Performance testing in dev and when env var is set
37
127
  if (process.env.dev && !!process.env.perfTest) {
@@ -39,23 +129,12 @@ export default {
39
129
  }
40
130
 
41
131
  const proxies = loadAll(state, {
42
- type, data, ctx, skipHaveAll
132
+ type, data, ctx, skipHaveAll, namespace
43
133
  });
44
134
 
45
135
  // If we loaded a set of pods, then update the podsByNamespace cache
46
136
  if (type === POD) {
47
- // Clear the entire cache - this is a fresh load
48
- Object.keys(state.podsByNamespace).forEach((ns) => {
49
- delete state.podsByNamespace[ns];
50
- });
51
-
52
- // Go through all of the pods and populate cache by namespace
53
- proxies.forEach((entry) => {
54
- const cache = registerNamespace(state, entry.namespace);
55
-
56
- addObject(cache.list, entry);
57
- cache.map.set(entry.id, entry);
58
- });
137
+ updatePodsByNamespaceCache(state, ctx, proxies, true);
59
138
  }
60
139
 
61
140
  // Notify the web worker of the initial load of schemas
@@ -83,13 +162,6 @@ export default {
83
162
  state.podsByNamespace = {};
84
163
  },
85
164
 
86
- clearFromQueue(state, type) {
87
- // Remove anything in the queue that is a resource update for the given type
88
- state.queue = state.queue.filter((item) => {
89
- return item.body?.type !== type;
90
- });
91
- },
92
-
93
165
  loadMulti(state, { data, ctx }) {
94
166
  for (const entry of data) {
95
167
  const resource = load(state, { data: entry, ctx });
@@ -106,17 +178,6 @@ export default {
106
178
  remove(state, obj) {
107
179
  remove(state, obj, this.getters);
108
180
 
109
- if (obj && obj.type === POD) {
110
- const cache = state.podsByNamespace[obj.namespace];
111
-
112
- // Extra defensive check that the cache exists for the namespace being removed
113
- if (cache) {
114
- removeObject(cache.list, obj);
115
- cache.map.delete(obj.id);
116
- }
117
- } else if (obj && obj.type === NAMESPACE) {
118
- // Namespace deleted
119
- delete state.podsByNamespace[obj.namespace];
120
- }
181
+ cleanPodsByNamespaceCache(state, obj);
121
182
  }
122
183
  };
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Imports in a worker cannot include exports from the file invoking the worker or from files importing the invoking file.
3
+ */
4
+
5
+ import Socket, {
6
+ NO_WATCH,
7
+ NO_SCHEMA,
8
+ EVENT_MESSAGE,
9
+ EVENT_CONNECTED,
10
+ } from '@shell/utils/socket';
11
+ import { addParam } from '@shell/utils/url';
12
+
13
+ export const WATCH_STATUSES = {
14
+ /**
15
+ * watch has been asked for this resource but not request has not successfully been sent
16
+ */
17
+ WATCH_PENDING: 'pending',
18
+ /**
19
+ * requested but not confirmed by the socket yet
20
+ */
21
+ WATCH_REQUESTED: 'requested',
22
+ /**
23
+ * confirmed as active by the socket
24
+ */
25
+ WATCHING: 'watching',
26
+ /**
27
+ * temporarily stopped via message from the socket, a watch should immediately be triggered but the maintenance cycle will pick it up if that doesn't happen.
28
+ */
29
+ STOPPED: 'stopped',
30
+ /**
31
+ * stop has been asked for this resource, but request has not successfully been sent
32
+ */
33
+ REMOVE_PENDING: 'removed_pending',
34
+ /**
35
+ * stop request has been sent to the socket or it's been stopped by the socket itself and is now awaiting a resource.stop message
36
+ */
37
+ REMOVE_REQUESTED: 'removed_requested'
38
+ };
39
+
40
+ export const keyForSubscribe = ({
41
+ resourceType, type, namespace, id, selector
42
+ } = {}) => {
43
+ return [(resourceType || type), namespace, id, selector] // each watch param in an array
44
+ .filter(param => !!param) // filter out all the empty ones // the filter makes these keys neater
45
+ .join('/'); // join into a string so we can use it as an object key
46
+ };
47
+
48
+ export const watchKeyFromMessage = (msg) => {
49
+ const {
50
+ resourceType,
51
+ namespace,
52
+ id,
53
+ selector
54
+ } = msg;
55
+
56
+ const watchObject = {
57
+ resourceType,
58
+ id,
59
+ namespace,
60
+ selector
61
+ };
62
+
63
+ return keyForSubscribe(watchObject);
64
+ };
65
+
66
+ const {
67
+ WATCH_PENDING, WATCH_REQUESTED, WATCHING, STOPPED, REMOVE_PENDING, REQUESTED_REMOVE
68
+ } = WATCH_STATUSES;
69
+
70
+ export default class ResourceWatcher extends Socket {
71
+ watches = {};
72
+ status = '';
73
+ debugWatcher = false;
74
+ csrf;
75
+
76
+ constructor(url, autoReconnect = true, frameTimeout = null, protocol = null, maxTries = null, csrf) {
77
+ super(url, autoReconnect, frameTimeout, protocol, maxTries, true);
78
+ this.baseUrl = self.location.origin + url.replace('subscribe', '');
79
+ this.csrf = csrf;
80
+
81
+ this.addEventListener(EVENT_CONNECTED, (e) => {
82
+ this.trace(EVENT_CONNECTED, ': processing previously requested or watched resources');
83
+
84
+ Object.values(this.watches).forEach((watch) => {
85
+ const { status, error } = watch;
86
+ const watchKey = keyForSubscribe(watch);
87
+
88
+ if ([WATCH_PENDING, WATCH_REQUESTED, WATCHING].includes(status) && !error) {
89
+ this.trace(EVENT_CONNECTED, ': re-watching previously required resource', watchKey, status);
90
+ this.watches[watchKey].status = WATCH_PENDING;
91
+ this.watch(watchKey);
92
+ } else if ([REMOVE_PENDING].includes(status)) {
93
+ this.trace(EVENT_CONNECTED, ': un-watching previously watched resource', watchKey, status);
94
+ this.watches[watchKey].status = REMOVE_PENDING;
95
+ this.unwatch(watchKey);
96
+ }
97
+ });
98
+ });
99
+ }
100
+
101
+ trace(...args) {
102
+ this.debugWatcher && console.info('Resource Watcher:', ...args); // eslint-disable-line no-console
103
+ }
104
+
105
+ setDebug(on) {
106
+ this.debugWatcher = !!on;
107
+ }
108
+
109
+ watchExists(watchKey) {
110
+ return !!this.watches?.[watchKey];
111
+ }
112
+
113
+ async watch(watchKey, providedResourceVersion, providedResourceVersionTime, providedKeyParts = {}, providedSkipResourceVersion) {
114
+ const {
115
+ resourceType: providedResourceType,
116
+ id: providedId,
117
+ namespace: providedNamespace,
118
+ selector: providedSelector
119
+ } = providedKeyParts;
120
+
121
+ this.trace('watch:', 'requested', watchKey);
122
+
123
+ if ([WATCH_REQUESTED, WATCHING].includes(this.watches?.[watchKey]?.status)) {
124
+ this.trace('watch:', 'already requested or watching, aborting', watchKey);
125
+
126
+ return;
127
+ }
128
+
129
+ if (this.watches?.[watchKey]?.error) {
130
+ this.trace('watch:', 'in error, aborting', watchKey);
131
+
132
+ return;
133
+ }
134
+
135
+ const resourceType = providedResourceType || this.watches?.[watchKey]?.resourceType;
136
+ const id = providedId || this.watches?.[watchKey]?.id;
137
+ const namespace = providedNamespace || this.watches?.[watchKey]?.namespace;
138
+ const selector = providedSelector || this.watches?.[watchKey]?.selector;
139
+ let skipResourceVersion = this.watches?.[watchKey]?.skipResourceVersion || providedSkipResourceVersion;
140
+
141
+ const watchObject = {
142
+ resourceType,
143
+ id,
144
+ namespace,
145
+ selector
146
+ };
147
+
148
+ let resourceVersionTime = providedResourceVersionTime || this.watches?.[watchKey]?.resourceVersionTime;
149
+ let resourceVersion = providedResourceVersion || this.watches?.[watchKey]?.resourceVersion;
150
+
151
+ if (!skipResourceVersion && (!resourceVersion || Date.now() - resourceVersionTime > 300000)) { // 300000ms is 5minutes
152
+ this.trace('watch:', 'revision update required', watchKey);
153
+
154
+ const resourceUrl = this.baseUrl + resourceType;
155
+ const limitedResourceUrl = addParam(resourceUrl, 'limit', 1);
156
+ const opt = {
157
+ method: 'get',
158
+ headers: { accept: 'application/json' },
159
+ };
160
+
161
+ if (this.csrf) {
162
+ opt.headers['x-api-csrf'] = this.csrf;
163
+ }
164
+
165
+ await fetch(limitedResourceUrl, opt)
166
+ .then((res) => {
167
+ this.watches[watchKey] = { ...watchObject };
168
+ if (!res.ok) {
169
+ this.watches[watchKey].error = res.json();
170
+ console.warn(`Resource error retrieving resourceVersion`, resourceType, ':', res.json()); // eslint-disable-line no-console
171
+ } else {
172
+ this.watches[watchKey].error = undefined;
173
+ }
174
+
175
+ return res.json();
176
+ })
177
+ .then((res) => {
178
+ if (res.revision) {
179
+ resourceVersionTime = Date.now();
180
+ resourceVersion = res.revision;
181
+ } else if (!this.watches[watchKey].error) {
182
+ // if there wasn't a revision in the response and there wasn't an error we wrote to the watch then the resource doesn't get a revision and we can skip it on subsequent rewatches
183
+ skipResourceVersion = true;
184
+ }
185
+ });
186
+ // When this fails we should re-fetch all resources (aka same as resyncWatch, or we actually call it). #7917
187
+ // This would match the old approach
188
+ }
189
+
190
+ const success = this.send(JSON.stringify({
191
+ ...watchObject,
192
+ resourceVersion: !skipResourceVersion ? resourceVersion : undefined
193
+ }));
194
+
195
+ this.watches[watchKey] = {
196
+ ...watchObject,
197
+ status: success ? WATCH_STATUSES.WATCH_REQUESTED : WATCH_STATUSES.WATCH_PENDING,
198
+ resourceVersion,
199
+ resourceVersionTime,
200
+ skipResourceVersion
201
+ };
202
+ }
203
+
204
+ unwatch(watchKey) {
205
+ const watch = this.watches?.[watchKey] || {};
206
+ const {
207
+ resourceType, id, namespace, selector
208
+ } = watch;
209
+ const watchObject = {
210
+ resourceType,
211
+ id,
212
+ namespace,
213
+ selector
214
+ };
215
+
216
+ if (resourceType && this.watches[watchKey].status !== REQUESTED_REMOVE) {
217
+ const success = this.send(JSON.stringify({
218
+ ...watchObject,
219
+ stop: true
220
+ }));
221
+
222
+ this.watches[watchKey].status = success ? REQUESTED_REMOVE : REMOVE_PENDING;
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Handles message from Backend to UI
228
+ */
229
+ _onmessage(event) {
230
+ const {
231
+ name: eventName, resourceType, data: { type }, id, namespace, selector, data
232
+ } = JSON.parse(event.data);
233
+ const watchKey = keyForSubscribe({
234
+ resourceType,
235
+ type,
236
+ id,
237
+ namespace,
238
+ selector
239
+ });
240
+
241
+ if (eventName === 'resource.start' && this.watches?.[watchKey]?.status === WATCH_REQUESTED) {
242
+ this.watches[watchKey].status = WATCHING;
243
+ } else if (eventName === 'resource.stop' && this.watches?.[watchKey]) {
244
+ if (this.watches?.[watchKey]?.status === REQUESTED_REMOVE) {
245
+ delete this.watches[watchKey];
246
+ } else {
247
+ this.watches[watchKey].status = STOPPED;
248
+ delete this.watches[watchKey].resourceVersion;
249
+ delete this.watches[watchKey].resourceVersionTime;
250
+ this.watch(watchKey);
251
+ this.dispatchEvent(new CustomEvent(EVENT_MESSAGE, { detail: event }));
252
+ }
253
+ } else if (eventName === 'resource.error') {
254
+ const err = data?.error?.toLowerCase();
255
+
256
+ if ( this.watches[watchKey] && err.includes('watch not allowed') ) {
257
+ this.watches[watchKey].error = { type: resourceType, reason: NO_WATCH };
258
+ } else if ( this.watches[watchKey] && err.includes('failed to find schema') ) {
259
+ // This can happen when the cattle-cluster-agent goes down (redeploy deployment, kill pod, etc)
260
+ // The previous method was just to track the error and block any further attempts to watch (canWatch)
261
+ // This method means we can retry on the next findX (should be safe, unless there are other use cases...)
262
+
263
+ this.watches[watchKey].error = { type: resourceType, reason: NO_SCHEMA };
264
+ } else if ( err.includes('too old') ) {
265
+ // We don't actually know the gap between the requested revision and the oldest available revision.
266
+ // For this case we should re-fetch all resources (aka same as resyncWatch, or we actually call it). #7917
267
+ // This would match the old approach
268
+ delete this.watches[watchKey].resourceVersion;
269
+ delete this.watches[watchKey].resourceVersionTime;
270
+ delete this.watches[watchKey].skipResourceVersion;
271
+ this.watch(watchKey);
272
+ }
273
+ }
274
+
275
+ super._onmessage(event);
276
+ }
277
+ }
@@ -0,0 +1,25 @@
1
+ import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
2
+
3
+ /**
4
+ * Inject special fields for indexing schemas
5
+ *
6
+ * Note
7
+ * This mutates input in a function, which is bad...
8
+ * but ensures the reference isn't broken, which is needed to maintain similar functionality as before
9
+ */
10
+ export function addSchemaIndexFields(schema) {
11
+ schema._id = normalizeType(schema.id);
12
+ schema._group = normalizeType(schema.attributes?.group);
13
+ }
14
+
15
+ /**
16
+ * Remove special fields for indexing schemas
17
+ *
18
+ * Note
19
+ * This mutates input in a function, which is bad...
20
+ * but ensures the reference isn't broken, which is needed to maintain similar functionality as before
21
+ */
22
+ export function removeSchemaIndexFields(schema) {
23
+ delete schema._id;
24
+ delete schema._group;
25
+ }