@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.
- package/assets/styles/global/_button.scss +5 -1
- package/assets/styles/global/_columns.scss +4 -0
- package/assets/styles/global/_layout.scss +1 -2
- package/assets/styles/global/_select.scss +1 -4
- package/assets/styles/themes/_dark.scss +4 -4
- package/assets/styles/themes/_light.scss +4 -3
- package/assets/styles/themes/_suse.scss +1 -1
- package/assets/styles/vendor/vue-select.scss +4 -3
- package/assets/translations/en-us.yaml +669 -73
- package/assets/translations/zh-hans.yaml +547 -165
- package/chart/monitoring/steps/uninstall-v1.vue +2 -2
- package/cloud-credential/azure.vue +23 -0
- package/cloud-credential/harvester.vue +25 -62
- package/cloud-credential/pnap.vue +80 -0
- package/components/.DS_Store +0 -0
- package/components/AdvancedSection.vue +9 -2
- package/components/Alert.vue +2 -2
- package/components/ButtonDropdown.vue +0 -2
- package/components/ButtonGroup.vue +1 -0
- package/components/CollapsibleCard.vue +0 -1
- package/components/CruResource.vue +41 -4
- package/components/DetailTop.vue +58 -3
- package/components/DisableAuthProviderModal.vue +106 -0
- package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
- package/components/ExplorerMembers.vue +253 -30
- package/components/ExplorerProjectsNamespaces.vue +77 -33
- package/components/GrowlManager.vue +3 -3
- package/components/IconOrSvg.vue +149 -0
- package/components/LogItem.vue +69 -0
- package/components/PodSecurityAdmission.vue +302 -0
- package/components/PromptModal.vue +1 -0
- package/components/ResourceDetail/Masthead.vue +54 -2
- package/components/ResourceDetail/index.vue +12 -5
- package/components/ResourceList/Masthead.vue +11 -1
- package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
- package/components/ResourceList/index.vue +53 -12
- package/components/ResourceList/resource-list.config.js +7 -0
- package/components/ResourceTable.vue +31 -6
- package/components/SimpleBox.vue +1 -1
- package/components/SortableTable/THead.vue +15 -5
- package/components/SortableTable/index.vue +21 -10
- package/components/Tabbed/index.vue +20 -15
- package/components/__tests__/.DS_Store +0 -0
- package/components/__tests__/AsyncButton.test.ts +140 -0
- package/components/__tests__/BackLink.test.ts +33 -0
- package/components/__tests__/ButtonGroup.test.ts +124 -0
- package/components/__tests__/ClusterBadge.test.ts +32 -0
- package/components/__tests__/CollapsibleCard.test.ts +64 -0
- package/components/__tests__/ConsumptionGauge.test.ts +88 -0
- package/components/__tests__/CruResource.test.ts +3 -2
- package/components/__tests__/FixedBanner.test.ts +129 -0
- package/components/__tests__/GrowlManager.test.ts +147 -0
- package/components/__tests__/NamespaceFilter.test.ts +33 -25
- package/components/__tests__/PercentageBar.test.ts +32 -0
- package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
- package/components/auth/AuthBanner.vue +20 -10
- package/components/auth/RoleDetailEdit.vue +26 -17
- package/components/auth/SelectPrincipal.vue +36 -5
- package/components/form/ArrayList.vue +3 -35
- package/components/form/ArrayListGrouped.vue +13 -4
- package/components/form/ArrayListSelect.vue +5 -5
- package/components/form/Error.vue +8 -0
- package/components/form/KeyValue.vue +39 -7
- package/components/form/LabeledSelect.vue +5 -2
- package/components/form/Labels.vue +46 -16
- package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
- package/components/form/Members/MembershipEditor.vue +12 -12
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/NodeScheduling.vue +1 -1
- package/components/form/Probe.vue +3 -3
- package/components/form/ResourceQuota/Project.vue +6 -6
- package/components/form/ResourceTabs/index.vue +1 -6
- package/components/form/Security.vue +7 -6
- package/components/form/Select.vue +3 -2
- package/components/form/SelectOrCreateAuthSecret.vue +22 -29
- package/components/form/ServicePorts.vue +8 -0
- package/components/form/WorkloadPorts.vue +7 -1
- package/components/form/__tests__/ArrayList.test.ts +74 -0
- package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
- package/components/formatter/Checked.vue +1 -1
- package/components/formatter/ClusterLink.vue +5 -0
- package/components/formatter/IconIsDefault.vue +2 -2
- package/components/formatter/InternalExternalIP.vue +11 -8
- package/components/formatter/LiveDuration.vue +78 -0
- package/components/formatter/WorkloadHealthScale.vue +5 -3
- package/components/nav/Header.vue +6 -3
- package/components/nav/NamespaceFilter.vue +146 -63
- package/components/nav/TopLevelMenu.vue +22 -19
- package/components/nav/WindowManager/ContainerLogs.vue +83 -126
- package/components/nav/WindowManager/ContainerShell.vue +9 -7
- package/components/nav/WindowManager/Window.vue +2 -0
- package/components/nav/WindowManager/index.vue +10 -0
- package/config/elemental-types.js +9 -0
- package/config/features.js +2 -0
- package/config/home-links.js +4 -1
- package/config/pod-security-admission.ts +82 -0
- package/config/product/apps.js +1 -1
- package/config/product/auth.js +6 -5
- package/config/product/explorer.js +6 -6
- package/config/product/fleet.js +1 -1
- package/config/product/manager.js +6 -2
- package/config/secret.js +0 -1
- package/config/settings.ts +26 -9
- package/config/table-headers.js +22 -11
- package/config/types.js +4 -1
- package/content/docs/zh-hans/getting-started.md +113 -137
- package/content/docs/zh-hans/whats-new.md +8 -46
- package/creators/pkg/package-lock.json +37 -0
- package/creators/pkg/package.json +1 -1
- package/detail/catalog.cattle.io.app.vue +1 -1
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +35 -9
- package/detail/service.vue +2 -9
- package/detail/workload/index.vue +0 -1
- package/dialog/AddClusterMemberDialog.vue +22 -28
- package/dialog/AddProjectMemberDialog.vue +53 -9
- package/dialog/DiagnosticTimingsDialog.vue +8 -7
- package/dialog/DrainNode.vue +44 -48
- package/dialog/ForceMachineRemoveDialog.vue +5 -7
- package/dialog/GenericPrompt.vue +15 -20
- package/dialog/RollbackWorkloadDialog.vue +15 -46
- package/dialog/RotateCertificatesDialog.vue +5 -7
- package/dialog/RotateEncryptionKeyDialog.vue +5 -9
- package/dialog/SaveAsRKETemplateDialog.vue +5 -13
- package/dialog/ScaleMachineDownDialog.vue +1 -1
- package/dialog/ScalePoolDownDialog.vue +121 -0
- package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
- package/edit/auth/azuread.vue +16 -16
- package/edit/auth/github.vue +8 -0
- package/edit/auth/googleoauth.vue +10 -1
- package/edit/auth/ldap/index.vue +10 -0
- package/edit/auth/oidc.vue +10 -0
- package/edit/auth/saml.vue +10 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
- package/edit/cloudcredential.vue +3 -7
- package/edit/logging-flow/Match.vue +39 -8
- package/edit/logging-flow/index.vue +27 -4
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
- package/edit/management.cattle.io.project.vue +8 -1
- package/edit/management.cattle.io.setting.vue +5 -2
- package/edit/management.cattle.io.user.vue +7 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +23 -7
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
- package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
- package/edit/namespace.vue +18 -4
- package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
- package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
- package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
- package/edit/networking.k8s.io.ingress/index.vue +8 -6
- package/edit/persistentvolume/index.vue +30 -27
- package/edit/persistentvolume/plugins/cephfs.vue +29 -29
- package/edit/persistentvolume/plugins/csi.vue +102 -62
- package/edit/persistentvolume/plugins/fc.vue +19 -19
- package/edit/persistentvolume/plugins/iscsi.vue +45 -45
- package/edit/persistentvolume/plugins/rbd.vue +39 -39
- package/edit/persistentvolumeclaim.vue +78 -75
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
- package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +93 -0
- package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
- package/edit/provisioning.cattle.io.cluster/rke2.vue +440 -152
- package/edit/secret/index.vue +3 -7
- package/edit/service.vue +3 -1
- package/edit/storage.k8s.io.storageclass/index.vue +100 -16
- package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
- package/edit/workload/__tests__/index.test.ts +98 -0
- package/edit/workload/index.vue +58 -8
- package/edit/workload/mixins/workload.js +107 -70
- package/edit/workload/storage/ContainerMountPaths.vue +0 -10
- package/edit/workload/storage/emptyDir.vue +88 -0
- package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
- package/edit/workload/storage/index.vue +8 -0
- package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
- package/layouts/default.vue +57 -44
- package/list/__tests__/workload.test.ts +5 -2
- package/list/catalog.cattle.io.app.vue +1 -0
- package/list/cis.cattle.io.clusterscan.vue +1 -0
- package/list/fleet.cattle.io.bundle.vue +5 -6
- package/list/fleet.cattle.io.cluster.vue +6 -3
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
- package/list/fleet.cattle.io.gitrepo.vue +4 -9
- package/list/helm.cattle.io.projecthelmchart.vue +1 -5
- package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
- package/list/logging.banzaicloud.io.flow.vue +6 -5
- package/list/management.cattle.io.cluster.vue +1 -0
- package/list/management.cattle.io.feature.vue +3 -4
- package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
- package/list/management.cattle.io.setting.vue +2 -2
- package/list/management.cattle.io.user.vue +4 -10
- package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
- package/list/node.vue +8 -5
- package/list/persistentvolume.vue +3 -3
- package/list/persistentvolumeclaim.vue +3 -4
- package/list/provisioning.cattle.io.cluster.vue +18 -19
- package/list/service.vue +6 -14
- package/list/workload.vue +43 -38
- package/machine-config/azure.vue +429 -60
- package/machine-config/pnap.vue +288 -0
- package/mixins/auth-config.js +1 -3
- package/mixins/browser-tab-visibility.js +8 -14
- package/mixins/chart.js +1 -1
- package/mixins/create-edit-view/impl.js +4 -0
- package/mixins/create-edit-view/index.js +4 -2
- package/mixins/resource-fetch-namespaced.js +98 -0
- package/mixins/resource-fetch.js +79 -45
- package/mixins/resource-manager.js +1 -23
- package/models/apps.controllerrevision.js +7 -0
- package/models/apps.daemonset.js +18 -0
- package/models/apps.deployment.js +44 -0
- package/models/apps.replicaset.js +7 -0
- package/models/apps.statefulset.js +18 -0
- package/models/batch.job.js +7 -14
- package/models/cluster/node.js +10 -2
- package/models/cluster.x-k8s.io.machine.js +26 -4
- package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
- package/models/event.js +7 -0
- package/models/logging.banzaicloud.io.flow.js +4 -0
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
- package/models/management.cattle.io.globalrole.js +2 -2
- package/models/management.cattle.io.node.js +37 -2
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
- package/models/management.cattle.io.project.js +30 -11
- package/models/management.cattle.io.setting.js +1 -1
- package/models/management.cattle.io.user.js +37 -1
- package/models/namespace.js +42 -5
- package/models/persistentvolume.js +14 -2
- package/models/pod.js +15 -0
- package/models/projectroletemplatebinding.js +7 -0
- package/models/provisioning.cattle.io.cluster.js +61 -10
- package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
- package/models/service.js +14 -13
- package/models/storage.k8s.io.storageclass.js +33 -18
- package/models/workload.js +38 -7
- package/nuxt.config.js +27 -17
- package/package.json +7 -7
- package/pages/about.vue +14 -2
- package/pages/c/_cluster/apps/charts/index.vue +4 -3
- package/pages/c/_cluster/apps/charts/install.vue +59 -22
- package/pages/c/_cluster/auth/config/_id.vue +6 -0
- package/pages/c/_cluster/auth/config/index.vue +8 -6
- package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
- package/pages/c/_cluster/auth/roles/index.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +12 -6
- package/pages/c/_cluster/longhorn/index.vue +1 -1
- package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
- package/pages/c/_cluster/monitoring/index.vue +1 -1
- package/pages/c/_cluster/neuvector/index.vue +1 -1
- package/pages/c/_cluster/settings/performance.vue +48 -2
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +34 -1
- package/pages/c/_cluster/uiplugins/index.vue +28 -2
- package/pages/diagnostic.vue +5 -4
- package/pages/home.vue +105 -30
- package/pages/prefs.vue +23 -12
- package/pages/rio/mesh.vue +1 -1
- package/pkg/dynamic-importer.lib.js +8 -0
- package/pkg/vue.config.js +4 -0
- package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
- package/plugins/dashboard-store/actions.js +32 -25
- package/plugins/dashboard-store/getters.js +50 -33
- package/plugins/dashboard-store/mutations.js +134 -28
- package/plugins/dashboard-store/resource-class.js +21 -41
- package/plugins/steve/actions.js +30 -0
- package/plugins/steve/caches/resourceCache.js +60 -0
- package/plugins/steve/getters.js +44 -1
- package/plugins/steve/mutations.js +97 -36
- package/plugins/steve/resourceWatcher.js +277 -0
- package/plugins/steve/schema.utils.js +25 -0
- package/plugins/steve/subscribe.js +288 -115
- package/plugins/steve/worker/index.js +17 -0
- package/plugins/steve/worker/web-worker.advanced.js +302 -0
- package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
- package/rancher-components/Card/Card.vue +3 -3
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
- package/rancher-components/StringList/StringList.test.ts +45 -420
- package/rancher-components/StringList/StringList.vue +1 -10
- package/rancher-components/components/Banner/Banner.test.ts +44 -0
- package/rancher-components/components/Banner/Banner.vue +129 -61
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +7 -7
- package/rancher-components/components/StringList/StringList.vue +21 -15
- package/scripts/test-plugins-build.sh +8 -0
- package/static/loading-indicator.html +1 -1
- package/store/index.js +54 -3
- package/store/plugins.js +0 -17
- package/store/pnap.js +128 -0
- package/store/prefs.js +4 -2
- package/store/type-map.js +55 -13
- package/types/pod-security-admission.ts +36 -0
- package/types/shell/index.d.ts +496 -396
- package/utils/__tests__/object.test.ts +17 -1
- package/utils/__tests__/pod-security-admission.test.ts +61 -0
- package/utils/async.ts +36 -0
- package/utils/color.js +45 -0
- package/utils/crypto/browserHashUtils.js +18 -0
- package/utils/dynamic-importer.js +8 -0
- package/utils/install-redirect.js +1 -1
- package/utils/object.js +24 -0
- package/utils/pod-security-admission.ts +39 -0
- package/utils/socket.js +61 -24
- package/utils/string.js +2 -0
- package/utils/svg-filter.js +301 -0
- package/utils/time.js +49 -0
- package/utils/validators/cidr.js +4 -0
- package/utils/validators/formRules/__tests__/index.test.ts +23 -3
- package/utils/validators/formRules/index.ts +14 -0
- package/config/product/harvester-manager.js +0 -162
- package/edit/harvesterhci.io.management.cluster.vue +0 -153
- package/list/harvesterhci.io.management.cluster.vue +0 -241
- package/machine-config/harvester.vue +0 -693
- package/models/harvesterhci.io.management.cluster.js +0 -228
- package/pages/c/_cluster/harvesterManager/index.vue +0 -24
- package/rancher-components/Card/Card.test.ts +0 -39
- package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
- package/rancher-components/Utils/DraggableZone/index.ts +0 -1
- package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { addObject
|
|
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/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|