@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,7 +1,8 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
2
|
import { addObject, addObjects, clear, removeObject } from '@shell/utils/array';
|
|
3
|
-
import { SCHEMA } from '@shell/config/types';
|
|
4
|
-
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
3
|
+
import { SCHEMA, COUNT } from '@shell/config/types';
|
|
4
|
+
import { normalizeType, keyFieldFor } from '@shell/plugins/dashboard-store/normalize';
|
|
5
|
+
import { addSchemaIndexFields } from '@shell/plugins/steve/schema.utils';
|
|
5
6
|
import { classify } from '@shell/plugins/dashboard-store/classify';
|
|
6
7
|
import garbageCollect from '@shell/utils/gc/gc';
|
|
7
8
|
|
|
@@ -10,12 +11,13 @@ function registerType(state, type) {
|
|
|
10
11
|
|
|
11
12
|
if ( !cache ) {
|
|
12
13
|
cache = {
|
|
13
|
-
list:
|
|
14
|
-
haveAll:
|
|
15
|
-
haveSelector:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
list: [],
|
|
15
|
+
haveAll: false,
|
|
16
|
+
haveSelector: {},
|
|
17
|
+
haveNamespace: undefined, // If the cached list only contains resources for a namespace, this will contain the ns name
|
|
18
|
+
revision: 0, // The highest known resourceVersion from the server for this type
|
|
19
|
+
generation: 0, // Updated every time something is loaded for this type
|
|
20
|
+
loadCounter: 0, // Used to cancel incremental loads if the page changes during load
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
// Not enumerable so they don't get sent back to the client for SSR
|
|
@@ -31,6 +33,24 @@ function registerType(state, type) {
|
|
|
31
33
|
return cache;
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
export function replace(existing, data) {
|
|
37
|
+
for ( const k of Object.keys(existing) ) {
|
|
38
|
+
delete existing[k];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for ( const k of Object.keys(data) ) {
|
|
42
|
+
Vue.set(existing, k, data[k]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return existing;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function replaceResource(existing, data, getters) {
|
|
49
|
+
data = getters.cleanResource(existing, data);
|
|
50
|
+
|
|
51
|
+
return replace(existing, data);
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
export function load(state, { data, ctx, existing }) {
|
|
35
55
|
const { getters } = ctx;
|
|
36
56
|
let type = normalizeType(data.type);
|
|
@@ -40,8 +60,7 @@ export function load(state, { data, ctx, existing }) {
|
|
|
40
60
|
|
|
41
61
|
// Inject special fields for indexing schemas
|
|
42
62
|
if ( type === SCHEMA ) {
|
|
43
|
-
|
|
44
|
-
data._group = normalizeType(data.attributes?.group);
|
|
63
|
+
addSchemaIndexFields(data);
|
|
45
64
|
}
|
|
46
65
|
|
|
47
66
|
const id = data[keyField];
|
|
@@ -52,24 +71,10 @@ export function load(state, { data, ctx, existing }) {
|
|
|
52
71
|
|
|
53
72
|
let entry;
|
|
54
73
|
|
|
55
|
-
function replace(existing, data) {
|
|
56
|
-
data = getters.cleanResource(existing, data);
|
|
57
|
-
|
|
58
|
-
for ( const k of Object.keys(existing) ) {
|
|
59
|
-
delete existing[k];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
for ( const k of Object.keys(data) ) {
|
|
63
|
-
Vue.set(existing, k, data[k]);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return existing;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
74
|
if ( existing && !existing.id ) {
|
|
70
75
|
// A specific proxy instance to used was passed in (for create -> save),
|
|
71
76
|
// use it instead of making a new proxy
|
|
72
|
-
entry =
|
|
77
|
+
entry = replaceResource(existing, data, getters);
|
|
73
78
|
addObject(cache.list, entry);
|
|
74
79
|
cache.map.set(id, entry);
|
|
75
80
|
// console.log('### Mutation added from existing proxy', type, id);
|
|
@@ -78,7 +83,7 @@ export function load(state, { data, ctx, existing }) {
|
|
|
78
83
|
|
|
79
84
|
if ( entry ) {
|
|
80
85
|
// There's already an entry in the store, update it
|
|
81
|
-
|
|
86
|
+
replaceResource(entry, data, getters);
|
|
82
87
|
// console.log('### Mutation Updated', type, id);
|
|
83
88
|
} else {
|
|
84
89
|
// There's no entry, make a new proxy
|
|
@@ -115,6 +120,7 @@ export function forgetType(state, type) {
|
|
|
115
120
|
if ( cache ) {
|
|
116
121
|
cache.haveAll = false;
|
|
117
122
|
cache.haveSelector = {};
|
|
123
|
+
cache.haveNamespace = undefined;
|
|
118
124
|
cache.revision = 0;
|
|
119
125
|
cache.generation = 0;
|
|
120
126
|
clear(cache.list);
|
|
@@ -163,11 +169,99 @@ export function remove(state, obj, getters) {
|
|
|
163
169
|
}
|
|
164
170
|
}
|
|
165
171
|
|
|
172
|
+
export function batchChanges(state, { ctx, batch }) {
|
|
173
|
+
const batchTypes = Object.keys(batch);
|
|
174
|
+
const combinedBatch = {};
|
|
175
|
+
|
|
176
|
+
batchTypes.forEach((batchType) => {
|
|
177
|
+
combinedBatch[batchType] = batch[batchType];
|
|
178
|
+
const typeOption = ctx.rootGetters['type-map/optionsFor'](batchType);
|
|
179
|
+
|
|
180
|
+
if (typeOption?.alias?.length > 0) {
|
|
181
|
+
const alias = typeOption?.alias || [];
|
|
182
|
+
|
|
183
|
+
alias.forEach((aliasType) => {
|
|
184
|
+
combinedBatch[aliasType] = {};
|
|
185
|
+
for (const [key, value] of Object.entries(batch[batchType])) {
|
|
186
|
+
combinedBatch[aliasType][key] = {
|
|
187
|
+
...value,
|
|
188
|
+
type: aliasType
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const combinedBatchTypes = Object.keys(combinedBatch);
|
|
196
|
+
|
|
197
|
+
combinedBatchTypes.forEach((type) => {
|
|
198
|
+
const normalizedType = normalizeType(type === 'counts' ? COUNT : type);
|
|
199
|
+
const keyField = keyFieldFor(normalizedType);
|
|
200
|
+
const typeCache = registerType(state, normalizedType);
|
|
201
|
+
|
|
202
|
+
// making a map for every resource's location in the list is gonna ensure we only have to loop through the big list once.
|
|
203
|
+
const typeCacheIndexMap = {};
|
|
204
|
+
|
|
205
|
+
typeCache.list.forEach((resource, index) => {
|
|
206
|
+
typeCacheIndexMap[resource[keyField]] = index;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const removeAtIndexes = [];
|
|
210
|
+
|
|
211
|
+
// looping through the batch, executing changes, deferring creates and removes since they change the array length
|
|
212
|
+
Object.keys(batch[normalizedType]).forEach((id) => {
|
|
213
|
+
const index = typeCacheIndexMap[id];
|
|
214
|
+
const resource = batch[normalizedType][id];
|
|
215
|
+
|
|
216
|
+
// an empty resource passed into batch changes is how we'll signal which ones to delete
|
|
217
|
+
if (Object.keys(resource).length === 0 && index !== undefined) {
|
|
218
|
+
typeCache.map.delete(id);
|
|
219
|
+
removeAtIndexes.push(index);
|
|
220
|
+
} else if (Object.keys(resource).length === 0) {
|
|
221
|
+
// No op. We're removing it... but we don't have it in the cache
|
|
222
|
+
} else {
|
|
223
|
+
if (normalizedType === SCHEMA) {
|
|
224
|
+
addSchemaIndexFields(resource);
|
|
225
|
+
}
|
|
226
|
+
const classyResource = classify(ctx, resource);
|
|
227
|
+
|
|
228
|
+
if (index === undefined) {
|
|
229
|
+
typeCache.list.push(classyResource);
|
|
230
|
+
typeCache.map.set(id, classyResource);
|
|
231
|
+
|
|
232
|
+
typeCacheIndexMap[classyResource[keyField]] = typeCache.list.length - 1;
|
|
233
|
+
} else {
|
|
234
|
+
replaceResource(typeCache.list[index], resource, ctx.getters);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// looping through the removeAtIndexes, making sure to offset by iteration so the array changing doesn't mess us up
|
|
240
|
+
removeAtIndexes.sort().forEach((cacheIndex, loopIndex) => {
|
|
241
|
+
typeCache.list.splice(cacheIndex - loopIndex, 1);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const opts = ctx.rootGetters[`type-map/optionsFor`](type);
|
|
245
|
+
const limit = opts?.limit;
|
|
246
|
+
|
|
247
|
+
// If there is a limit to the number of resources we can store for this type then
|
|
248
|
+
// remove the first one to keep the list size to that limit
|
|
249
|
+
if (limit && typeCache.list.length > limit) {
|
|
250
|
+
const rm = typeCache.list.shift();
|
|
251
|
+
|
|
252
|
+
typeCache.map.delete(rm.id);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
typeCache.generation++;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
166
259
|
export function loadAll(state, {
|
|
167
260
|
type,
|
|
168
261
|
data,
|
|
169
262
|
ctx,
|
|
170
|
-
skipHaveAll
|
|
263
|
+
skipHaveAll,
|
|
264
|
+
namespace
|
|
171
265
|
}) {
|
|
172
266
|
const { getters } = ctx;
|
|
173
267
|
|
|
@@ -199,7 +293,8 @@ export function loadAll(state, {
|
|
|
199
293
|
|
|
200
294
|
// Allow requester to skip setting that everything has loaded
|
|
201
295
|
if (!skipHaveAll) {
|
|
202
|
-
cache.
|
|
296
|
+
cache.haveNamespace = namespace;
|
|
297
|
+
cache.haveAll = !namespace;
|
|
203
298
|
}
|
|
204
299
|
|
|
205
300
|
return proxies;
|
|
@@ -238,6 +333,11 @@ export default {
|
|
|
238
333
|
|
|
239
334
|
loadAll,
|
|
240
335
|
|
|
336
|
+
/**
|
|
337
|
+
* Handles changes (add, update, remove) to multiple resources for multiple types
|
|
338
|
+
*/
|
|
339
|
+
batchChanges,
|
|
340
|
+
|
|
241
341
|
loadMerge(state, { type, data: allLatest, ctx }) {
|
|
242
342
|
const { commit, getters } = ctx;
|
|
243
343
|
// const allLatest = await dispatch('findAll', { type, opt: { force: true, load, _NONE } });
|
|
@@ -288,6 +388,12 @@ export default {
|
|
|
288
388
|
cache.haveAll = true;
|
|
289
389
|
},
|
|
290
390
|
|
|
391
|
+
setHaveNamespace(state, { type, namespace }) {
|
|
392
|
+
const cache = registerType(state, type);
|
|
393
|
+
|
|
394
|
+
cache.haveNamespace = namespace;
|
|
395
|
+
},
|
|
396
|
+
|
|
291
397
|
loadedAll(state, { type }) {
|
|
292
398
|
const cache = registerType(state, type);
|
|
293
399
|
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
validateLength,
|
|
26
26
|
} from '@shell/utils/validators';
|
|
27
27
|
import formRulesGenerator from '@shell/utils/validators/formRules/index';
|
|
28
|
+
import { waitFor } from '@shell/utils/async';
|
|
28
29
|
import jsyaml from 'js-yaml';
|
|
29
30
|
import compact from 'lodash/compact';
|
|
30
31
|
import forIn from 'lodash/forIn';
|
|
@@ -752,41 +753,7 @@ export default class Resource {
|
|
|
752
753
|
// ------------------------------------------------------------------
|
|
753
754
|
|
|
754
755
|
waitForTestFn(fn, msg, timeoutMs, intervalMs) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
if ( !timeoutMs ) {
|
|
758
|
-
timeoutMs = DEFAULT_WAIT_TMIMEOUT;
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
if ( !intervalMs ) {
|
|
762
|
-
intervalMs = DEFAULT_WAIT_INTERVAL;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
return new Promise((resolve, reject) => {
|
|
766
|
-
// Do a first check immediately
|
|
767
|
-
if ( fn.apply(this) ) {
|
|
768
|
-
console.log('Wait for', msg, 'done immediately'); // eslint-disable-line no-console
|
|
769
|
-
resolve(this);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
const timeout = setTimeout(() => {
|
|
773
|
-
console.log('Wait for', msg, 'timed out'); // eslint-disable-line no-console
|
|
774
|
-
clearInterval(interval);
|
|
775
|
-
clearTimeout(timeout);
|
|
776
|
-
reject(new Error(`Failed waiting for: ${ msg }`));
|
|
777
|
-
}, timeoutMs);
|
|
778
|
-
|
|
779
|
-
const interval = setInterval(() => {
|
|
780
|
-
if ( fn.apply(this) ) {
|
|
781
|
-
console.log('Wait for', msg, 'done'); // eslint-disable-line no-console
|
|
782
|
-
clearInterval(interval);
|
|
783
|
-
clearTimeout(timeout);
|
|
784
|
-
resolve(this);
|
|
785
|
-
} else {
|
|
786
|
-
console.log('Wait for', msg, 'not done yet'); // eslint-disable-line no-console
|
|
787
|
-
}
|
|
788
|
-
}, intervalMs);
|
|
789
|
-
});
|
|
756
|
+
return waitFor(() => fn.apply(this), msg, timeoutMs || DEFAULT_WAIT_TMIMEOUT, intervalMs || DEFAULT_WAIT_INTERVAL, true);
|
|
790
757
|
}
|
|
791
758
|
|
|
792
759
|
waitForState(state, timeout, interval) {
|
|
@@ -798,19 +765,19 @@ export default class Resource {
|
|
|
798
765
|
waitForTransition() {
|
|
799
766
|
return this.waitForTestFn(() => {
|
|
800
767
|
return !this.transitioning;
|
|
801
|
-
}, 'transition completion');
|
|
768
|
+
}, 'transition completion', undefined, undefined);
|
|
802
769
|
}
|
|
803
770
|
|
|
804
771
|
waitForAction(name) {
|
|
805
772
|
return this.waitForTestFn(() => {
|
|
806
773
|
return this.hasAction(name);
|
|
807
|
-
}, `action=${ name }
|
|
774
|
+
}, `action=${ name }`, undefined, undefined);
|
|
808
775
|
}
|
|
809
776
|
|
|
810
777
|
waitForLink(name) {
|
|
811
778
|
return this.waitForTestFn(() => {
|
|
812
779
|
return this.hasLink(name);
|
|
813
|
-
}, `link=${ name }
|
|
780
|
+
}, `link=${ name }`, undefined, undefined);
|
|
814
781
|
}
|
|
815
782
|
|
|
816
783
|
hasCondition(condition) {
|
|
@@ -1075,6 +1042,12 @@ export default class Resource {
|
|
|
1075
1042
|
return this._save(...arguments);
|
|
1076
1043
|
}
|
|
1077
1044
|
|
|
1045
|
+
/**
|
|
1046
|
+
* Allow to handle the response of the save request
|
|
1047
|
+
* @param {*} res Full request response
|
|
1048
|
+
*/
|
|
1049
|
+
processSaveResponse(res) { }
|
|
1050
|
+
|
|
1078
1051
|
async _save(opt = {}) {
|
|
1079
1052
|
delete this.__rehydrate;
|
|
1080
1053
|
delete this.__clone;
|
|
@@ -1151,6 +1124,9 @@ export default class Resource {
|
|
|
1151
1124
|
try {
|
|
1152
1125
|
const res = await this.$dispatch('request', { opt, type: this.type } );
|
|
1153
1126
|
|
|
1127
|
+
// Allow to process response independently from the related models
|
|
1128
|
+
this.processSaveResponse(res);
|
|
1129
|
+
|
|
1154
1130
|
// Steve sometimes returns Table responses instead of the resource you just saved.. ignore
|
|
1155
1131
|
if ( res && res.kind !== 'Table') {
|
|
1156
1132
|
await this.$dispatch('load', { data: res, existing: (forNew ? this : undefined ) });
|
|
@@ -1323,8 +1299,9 @@ export default class Resource {
|
|
|
1323
1299
|
|
|
1324
1300
|
async download() {
|
|
1325
1301
|
const value = await this.followLink('view', { headers: { accept: 'application/yaml' } });
|
|
1302
|
+
const data = await this.$dispatch('cleanForDownload', value.data);
|
|
1326
1303
|
|
|
1327
|
-
downloadFile(`${ this.nameDisplay }.yaml`,
|
|
1304
|
+
downloadFile(`${ this.nameDisplay }.yaml`, data, 'application/yaml');
|
|
1328
1305
|
}
|
|
1329
1306
|
|
|
1330
1307
|
async downloadBulk(items) {
|
|
@@ -1343,8 +1320,11 @@ export default class Resource {
|
|
|
1343
1320
|
}
|
|
1344
1321
|
|
|
1345
1322
|
await eachLimit(items, 10, (item, idx) => {
|
|
1346
|
-
return item.followLink('view', { headers: { accept: 'application/yaml' } } ).then((data) => {
|
|
1347
|
-
|
|
1323
|
+
return item.followLink('view', { headers: { accept: 'application/yaml' } } ).then(async(data) => {
|
|
1324
|
+
const yaml = data.data || data;
|
|
1325
|
+
const cleanedYaml = await this.$dispatch('cleanForDownload', yaml);
|
|
1326
|
+
|
|
1327
|
+
files[`resources/${ names[idx] }`] = cleanedYaml;
|
|
1348
1328
|
});
|
|
1349
1329
|
});
|
|
1350
1330
|
|
package/plugins/steve/actions.js
CHANGED
|
@@ -7,6 +7,7 @@ import { streamJson, streamingSupported } from '@shell/utils/stream';
|
|
|
7
7
|
import isObject from 'lodash/isObject';
|
|
8
8
|
import { classify } from '@shell/plugins/dashboard-store/classify';
|
|
9
9
|
import { NAMESPACE } from '@shell/config/types';
|
|
10
|
+
import jsyaml from 'js-yaml';
|
|
10
11
|
|
|
11
12
|
export default {
|
|
12
13
|
|
|
@@ -323,6 +324,35 @@ export default {
|
|
|
323
324
|
|
|
324
325
|
return resource;
|
|
325
326
|
},
|
|
327
|
+
|
|
328
|
+
// remove fields added by steve before showing/downloading yamls
|
|
329
|
+
cleanForDownload(ctx, yaml) {
|
|
330
|
+
if (!yaml) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const rootKeys = [
|
|
334
|
+
'id',
|
|
335
|
+
'links',
|
|
336
|
+
'type',
|
|
337
|
+
'actions'
|
|
338
|
+
];
|
|
339
|
+
const metadataKeys = [
|
|
340
|
+
'fields',
|
|
341
|
+
'relationships',
|
|
342
|
+
'state',
|
|
343
|
+
];
|
|
344
|
+
const conditionKeys = [
|
|
345
|
+
'error',
|
|
346
|
+
'transitioning',
|
|
347
|
+
];
|
|
348
|
+
const obj = jsyaml.load(yaml);
|
|
349
|
+
|
|
350
|
+
dropKeys(obj, rootKeys);
|
|
351
|
+
dropKeys(obj?.metadata, metadataKeys);
|
|
352
|
+
(obj?.status?.conditions || []).forEach(condition => dropKeys(condition, conditionKeys));
|
|
353
|
+
|
|
354
|
+
return jsyaml.dump(obj);
|
|
355
|
+
}
|
|
326
356
|
};
|
|
327
357
|
|
|
328
358
|
const diffRootKeys = [
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SCHEMA, COUNT } from '@shell/config/types';
|
|
2
|
+
import { keyFieldFor, normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
3
|
+
import { addSchemaIndexFields } from '@shell/plugins/steve/schema.utils';
|
|
4
|
+
import { hashObj } from '@shell/utils/crypto/browserHashUtils';
|
|
5
|
+
|
|
6
|
+
export default class ResourceCache {
|
|
7
|
+
resources = {};
|
|
8
|
+
type;
|
|
9
|
+
keyField;
|
|
10
|
+
constructor(type) {
|
|
11
|
+
this.type = normalizeType(type === 'counts' ? COUNT : type);
|
|
12
|
+
this.keyField = keyFieldFor(this.type);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
load(collection = []) {
|
|
16
|
+
// console.time('startSchemaLoads!!!');
|
|
17
|
+
for (let i = 0; i < collection.length; i++) {
|
|
18
|
+
const resource = collection[i];
|
|
19
|
+
|
|
20
|
+
if ( this.type === SCHEMA ) {
|
|
21
|
+
addSchemaIndexFields(resource);
|
|
22
|
+
}
|
|
23
|
+
const id = resource[this.keyField];
|
|
24
|
+
|
|
25
|
+
// Store the hash instead of the whole object. This means longer load time be reduces memory footprint
|
|
26
|
+
// Perf Note: 3.328125 ms to load ~2500 schemas as objects into cache
|
|
27
|
+
// Perf Note: 67.450927734375 ms to load ~2500 schemas as hashes into cache
|
|
28
|
+
this.resources[id] = hashObj(resource);
|
|
29
|
+
}
|
|
30
|
+
// console.timeEnd('startSchemaLoads!!!');
|
|
31
|
+
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
change(resource, callback) {
|
|
36
|
+
if ( this.type === SCHEMA ) {
|
|
37
|
+
addSchemaIndexFields(resource);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const existingResourceHash = this.resources[resource[this.keyField]] || {};
|
|
41
|
+
const newResourceHash = hashObj(resource);
|
|
42
|
+
|
|
43
|
+
if (existingResourceHash !== newResourceHash) {
|
|
44
|
+
this.resources[resource[this.keyField]] = resource;
|
|
45
|
+
callback();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
create(resource, callback) {
|
|
50
|
+
// ToDo: the logic for create is identical to change in these caches but the worker doesn't know that
|
|
51
|
+
this.change(resource, callback);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
remove(id, callback) {
|
|
55
|
+
if (this.resources[id]) {
|
|
56
|
+
delete this.resources[id];
|
|
57
|
+
callback();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
package/plugins/steve/getters.js
CHANGED
|
@@ -6,6 +6,8 @@ import { NAMESPACE, SCHEMA, COUNT, UI } from '@shell/config/types';
|
|
|
6
6
|
import SteveModel from './steve-class';
|
|
7
7
|
import HybridModel, { cleanHybridResources } from './hybrid-class';
|
|
8
8
|
import NormanModel from './norman-class';
|
|
9
|
+
import { urlFor } from '@shell/plugins/dashboard-store/getters';
|
|
10
|
+
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
9
11
|
|
|
10
12
|
export const STEVE_MODEL_TYPES = {
|
|
11
13
|
NORMAN: 'norman',
|
|
@@ -67,6 +69,20 @@ export default {
|
|
|
67
69
|
return url;
|
|
68
70
|
},
|
|
69
71
|
|
|
72
|
+
urlFor: (state, getters) => (type, id, opt) => {
|
|
73
|
+
let url = urlFor(state, getters)(type, id, opt);
|
|
74
|
+
|
|
75
|
+
if (opt.namespaced) {
|
|
76
|
+
const parts = url.split('/');
|
|
77
|
+
|
|
78
|
+
url = `${ parts.join('/') }/${ opt.namespaced }`;
|
|
79
|
+
|
|
80
|
+
return url;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return url;
|
|
84
|
+
},
|
|
85
|
+
|
|
70
86
|
defaultModel: state => (obj) => {
|
|
71
87
|
const which = state.config.modelBaseClass || STEVE_MODEL_TYPES.BY_TYPE.STEVE;
|
|
72
88
|
|
|
@@ -106,6 +122,21 @@ export default {
|
|
|
106
122
|
},
|
|
107
123
|
|
|
108
124
|
cleanResource: () => (existing, data) => {
|
|
125
|
+
/**
|
|
126
|
+
* Resource counts are contained within a single 'count' resource with a 'counts' field that is a map of resource types
|
|
127
|
+
* When counts are updated through the websocket, only the resources that changed are sent so we can't load the new 'count' resource into the store as we would another resource
|
|
128
|
+
*/
|
|
129
|
+
if (data?.type === COUNT && existing) {
|
|
130
|
+
data.counts = { ...existing.counts, ...data.counts };
|
|
131
|
+
|
|
132
|
+
return data;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// If the existing model has a cleanResource method, use it
|
|
136
|
+
if (existing?.cleanResource && typeof existing.cleanResource === 'function') {
|
|
137
|
+
return existing.cleanResource(data);
|
|
138
|
+
}
|
|
139
|
+
|
|
109
140
|
const typeSuperClass = Object.getPrototypeOf(Object.getPrototypeOf(existing))?.constructor;
|
|
110
141
|
|
|
111
142
|
return typeSuperClass === HybridModel ? cleanHybridResources(data) : data;
|
|
@@ -120,6 +151,18 @@ export default {
|
|
|
120
151
|
|
|
121
152
|
gcIgnoreTypes: () => {
|
|
122
153
|
return GC_IGNORE_TYPES;
|
|
123
|
-
}
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
currentGeneration: state => (type) => {
|
|
157
|
+
type = normalizeType(type);
|
|
158
|
+
|
|
159
|
+
const cache = state.types[type];
|
|
160
|
+
|
|
161
|
+
if ( !cache ) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return cache.generation;
|
|
166
|
+
},
|
|
124
167
|
|
|
125
168
|
};
|