@rancher/shell 0.3.16 → 0.3.18
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/images/wechat-qr-code.jpg +0 -0
- package/assets/translations/en-us.yaml +75 -16
- package/assets/translations/zh-hans.yaml +151 -15
- package/chart/__tests__/S3.test.ts +50 -0
- package/chart/rancher-backup/S3.vue +21 -0
- package/chart/rancher-backup/index.vue +4 -0
- package/components/AsyncButton.vue +1 -1
- package/components/CommunityLinks.vue +1 -0
- package/components/FileDiff.vue +92 -85
- package/components/Inactivity.vue +10 -0
- package/components/LazyImage.vue +2 -2
- package/components/PromptRestore.vue +7 -5
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/ResourceDetail/index.vue +8 -14
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +50 -2
- package/components/YamlEditor.vue +1 -0
- package/components/__tests__/PromptRestore.test.ts +72 -0
- package/components/auth/AzureWarning.vue +1 -1
- package/components/auth/RoleDetailEdit.vue +1 -0
- package/components/fleet/FleetResources.vue +3 -64
- package/components/form/FileImageSelector.vue +9 -0
- package/components/form/FileSelector.vue +2 -1
- package/components/form/MatchExpressions.vue +1 -3
- package/components/form/NameNsDescription.vue +28 -12
- package/components/form/NodeAffinity.vue +2 -2
- package/components/form/PodAffinity.vue +2 -2
- package/components/form/ResourceTabs/index.vue +8 -2
- package/components/form/Select.vue +16 -0
- package/components/form/__tests__/FileImageSelector.test.ts +42 -0
- package/components/form/__tests__/FileSelector.test.ts +76 -0
- package/components/form/__tests__/NodeAffinity.test.ts +38 -0
- package/components/form/__tests__/PodAffinity.test.ts +46 -0
- package/components/formatter/ClusterLink.vue +8 -4
- package/components/formatter/ClusterProvider.vue +3 -1
- package/components/formatter/ImageName.vue +23 -0
- package/components/formatter/PodImages.vue +7 -1
- package/components/formatter/__tests__/ClusterLink.test.ts +101 -0
- package/components/formatter/__tests__/ClusterProvider.test.ts +24 -0
- package/components/nav/Header.vue +2 -2
- package/components/nav/WindowManager/ContainerShell.vue +60 -36
- package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +561 -0
- package/config/__test__/home-links.test.ts +62 -0
- package/config/home-links.js +15 -3
- package/config/labels-annotations.js +7 -2
- package/config/persistentVolume.ts +108 -0
- package/config/product/manager.js +5 -1
- package/config/router.js +0 -4
- package/config/settings.ts +4 -0
- package/config/table-headers.js +6 -5
- package/config/types.js +2 -0
- package/config/uiplugins.js +50 -5
- package/core/plugin-helpers.js +39 -15
- package/core/plugin.ts +9 -0
- package/core/plugins.js +1 -1
- package/core/types-provisioning.ts +253 -0
- package/core/types.ts +21 -3
- package/detail/autoscaling.horizontalpodautoscaler/index.vue +50 -1
- package/detail/fleet.cattle.io.gitrepo.vue +10 -2
- package/detail/node.vue +6 -6
- package/detail/pod.vue +38 -9
- package/detail/provisioning.cattle.io.cluster.vue +46 -7
- package/detail/workload/index.vue +49 -18
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +62 -0
- package/edit/__tests__/ui.cattle.io.navlink.test.ts +110 -0
- package/edit/auth/github.vue +1 -0
- package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +130 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +79 -0
- package/edit/fleet.cattle.io.clustergroup.vue +14 -3
- package/edit/fleet.cattle.io.gitrepo.vue +18 -1
- package/edit/namespace.vue +9 -1
- package/edit/networking.k8s.io.ingress/RulePath.vue +0 -2
- package/edit/persistentvolume/__tests__/persistentvolume.test.ts +82 -0
- package/edit/persistentvolume/index.vue +2 -1
- package/edit/persistentvolume/plugins/csi.vue +3 -1
- package/edit/persistentvolume/plugins/longhorn.vue +12 -12
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +1 -30
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +15 -11
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +79 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +53 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +335 -151
- package/edit/storage.k8s.io.storageclass/index.vue +1 -2
- package/edit/ui.cattle.io.navlink.vue +213 -186
- package/initialize/App.js +3 -13
- package/initialize/layouts.ts +26 -0
- package/layouts/default.vue +1 -1
- package/list/group.principal.vue +1 -1
- package/list/provisioning.cattle.io.cluster.vue +8 -1
- package/middleware/authenticated.js +101 -5
- package/mixins/brand.js +39 -3
- package/mixins/child-hook.js +2 -2
- package/mixins/create-edit-view/impl.js +4 -4
- package/models/chart.js +1 -1
- package/models/fleet.cattle.io.cluster.js +33 -4
- package/models/fleet.cattle.io.gitrepo.js +113 -38
- package/models/management.cattle.io.kontainerdriver.js +14 -0
- package/models/persistentvolume.js +2 -111
- package/models/pod.js +30 -0
- package/models/provisioning.cattle.io.cluster.js +9 -1
- package/models/rke.cattle.io.etcdsnapshot.js +10 -7
- package/package.json +2 -2
- package/pages/about.vue +8 -2
- package/pages/auth/login.vue +1 -1
- package/pages/auth/logout.vue +11 -3
- package/pages/c/_cluster/apps/charts/index.vue +5 -2
- package/pages/c/_cluster/apps/charts/install.vue +5 -0
- 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 +2 -11
- package/pages/c/_cluster/manager/cloudCredential/_id.vue +0 -1
- package/pages/c/_cluster/manager/cloudCredential/create.vue +0 -1
- package/pages/c/_cluster/settings/brand.vue +11 -8
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +177 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +19 -3
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +90 -21
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +107 -37
- package/pages/c/_cluster/uiplugins/index.vue +160 -44
- package/pages/docs/_doc.vue +9 -3
- package/pages/home.vue +6 -6
- package/pages/support/index.vue +10 -4
- package/pkg/auto-import.js +1 -1
- package/plugins/clean-tooltip-directive.js +1 -1
- package/plugins/dashboard-store/__tests__/actions.spec.ts +165 -0
- package/plugins/dashboard-store/__tests__/getters.spec.ts +100 -0
- package/plugins/dashboard-store/__tests__/{mutations.spec.js → mutations.spec.ts} +2 -2
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/resource-class.js +39 -2
- package/plugins/plugin.js +9 -1
- package/plugins/steve/__tests__/getters.spec.ts +93 -0
- package/plugins/steve/getters.js +21 -1
- package/plugins/steve/subscribe.js +1 -3
- package/rancher-components/BadgeState/BadgeState.vue +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -1
- package/rancher-components/Banner/Banner.vue +134 -53
- package/rancher-components/Card/Card.test.ts +37 -0
- package/rancher-components/Card/Card.vue +24 -7
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
- package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
- package/rancher-components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/Form/Radio/RadioButton.vue +30 -13
- package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
- package/rancher-components/StringList/StringList.test.ts +453 -49
- package/rancher-components/StringList/StringList.vue +44 -26
- package/scripts/extension/publish +2 -2
- package/scripts/typegen.sh +11 -2
- package/server/server-middleware.js +4 -12
- package/store/index.js +14 -3
- package/store/prefs.js +0 -3
- package/store/store-types.js +2 -0
- package/store/type-map.js +17 -29
- package/types/api.d.ts +1 -0
- package/types/fleet.d.ts +1 -0
- package/types/shell/index.d.ts +931 -85
- package/types/userPreferences.d.ts +1 -1
- package/utils/__mocks__/socket.js +21 -0
- package/utils/grafana.js +23 -11
- package/utils/kube.js +9 -0
- package/utils/object.js +27 -0
- package/utils/selector.js +2 -1
- package/utils/settings.ts +2 -2
- package/utils/validators/formRules/index.ts +3 -3
- package/vue.config.js +3 -2
- package/components/.DS_Store +0 -0
- package/components/__tests__/.DS_Store +0 -0
- package/creators/pkg/package-lock.json +0 -37
- package/pages/safeMode.vue +0 -17
- package/plugins/steve/urloptions.js +0 -47
- package/yarn-error.log +0 -196
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export const VOLUME_PLUGINS = [
|
|
2
|
+
{
|
|
3
|
+
labelKey: 'persistentVolume.awsElasticBlockStore.label',
|
|
4
|
+
value: 'awsElasticBlockStore',
|
|
5
|
+
supported: true
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
labelKey: 'persistentVolume.azureDisk.label',
|
|
9
|
+
value: 'azureDisk',
|
|
10
|
+
supported: true
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
labelKey: 'persistentVolume.azureFile.label',
|
|
14
|
+
value: 'azureFile',
|
|
15
|
+
supported: true
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
labelKey: 'persistentVolume.cephfs.label',
|
|
19
|
+
value: 'cephfs',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
labelKey: 'persistentVolume.rbd.label',
|
|
23
|
+
value: 'rbd',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
labelKey: 'persistentVolume.csi.label',
|
|
27
|
+
value: 'csi',
|
|
28
|
+
supported: true
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
labelKey: 'persistentVolume.fc.label',
|
|
32
|
+
value: 'fc',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
labelKey: 'persistentVolume.flexVolume.label',
|
|
36
|
+
value: 'flexVolume',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
labelKey: 'persistentVolume.flocker.label',
|
|
40
|
+
value: 'flocker',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
labelKey: 'persistentVolume.glusterfs.label',
|
|
44
|
+
value: 'glusterfs',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
labelKey: 'persistentVolume.gcePersistentDisk.label',
|
|
48
|
+
value: 'gcePersistentDisk',
|
|
49
|
+
supported: true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
labelKey: 'persistentVolume.hostPath.label',
|
|
53
|
+
value: 'hostPath',
|
|
54
|
+
supported: true
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
labelKey: 'persistentVolume.iscsi.label',
|
|
58
|
+
value: 'iscsi',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
labelKey: 'persistentVolume.local.label',
|
|
62
|
+
value: 'local',
|
|
63
|
+
supported: true
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
labelKey: 'persistentVolume.longhorn.label',
|
|
67
|
+
value: 'longhorn',
|
|
68
|
+
supported: true
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
labelKey: 'persistentVolume.nfs.label',
|
|
72
|
+
value: 'nfs',
|
|
73
|
+
supported: true
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
labelKey: 'persistentVolume.cinder.label',
|
|
77
|
+
value: 'cinder',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
labelKey: 'persistentVolume.photonPersistentDisk.label',
|
|
81
|
+
value: 'photonPersistentDisk',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
labelKey: 'persistentVolume.portworxVolume.label',
|
|
85
|
+
value: 'portworxVolume',
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
{
|
|
89
|
+
labelKey: 'persistentVolume.quobyte.label',
|
|
90
|
+
value: 'quobyte',
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
labelKey: 'persistentVolume.scaleIO.label',
|
|
95
|
+
value: 'scaleIO',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
labelKey: 'persistentVolume.storageos.label',
|
|
99
|
+
value: 'storageos',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
labelKey: 'persistentVolume.vsphereVolume.label',
|
|
103
|
+
value: 'vsphereVolume',
|
|
104
|
+
supported: true
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
export const LONGHORN_PLUGIN = VOLUME_PLUGINS.find((plugin) => plugin.value === 'longhorn');
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '@shell/config/types';
|
|
9
9
|
import { MULTI_CLUSTER } from '@shell/store/features';
|
|
10
10
|
import { DSL } from '@shell/store/type-map';
|
|
11
|
-
import { BLANK_CLUSTER } from '@shell/store';
|
|
11
|
+
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
12
12
|
|
|
13
13
|
export const NAME = 'manager';
|
|
14
14
|
|
|
@@ -38,6 +38,10 @@ export function init(store) {
|
|
|
38
38
|
resource: CAPI.RANCHER_CLUSTER
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
|
+
typeStoreMap: {
|
|
42
|
+
[NORMAN.CLOUD_CREDENTIAL]: 'rancher',
|
|
43
|
+
cloudCredential: 'rancher',
|
|
44
|
+
}
|
|
41
45
|
});
|
|
42
46
|
|
|
43
47
|
virtualType({
|
package/config/router.js
CHANGED
|
@@ -48,10 +48,6 @@ export const routerOptions = {
|
|
|
48
48
|
path: '/prefs',
|
|
49
49
|
component: () => interopDefault(import('../pages/prefs.vue' /* webpackChunkName: "pages/prefs" */)),
|
|
50
50
|
name: 'prefs'
|
|
51
|
-
}, {
|
|
52
|
-
path: '/safeMode',
|
|
53
|
-
component: () => interopDefault(import('../pages/safeMode.vue' /* webpackChunkName: "pages/safeMode" */)),
|
|
54
|
-
name: 'safeMode'
|
|
55
51
|
}, {
|
|
56
52
|
path: '/support',
|
|
57
53
|
component: () => interopDefault(import('../pages/support/index.vue' /* webpackChunkName: "pages/support/index" */)),
|
package/config/settings.ts
CHANGED
|
@@ -89,6 +89,10 @@ export const SETTING = {
|
|
|
89
89
|
*/
|
|
90
90
|
CLUSTER_AGENT_DEFAULT_AFFINITY: 'cluster-agent-default-affinity',
|
|
91
91
|
FLEET_AGENT_DEFAULT_AFFINITY: 'fleet-agent-default-affinity',
|
|
92
|
+
/**
|
|
93
|
+
* manage rancher repositories in extensions (official, partners repos)
|
|
94
|
+
*/
|
|
95
|
+
ADD_EXTENSION_REPOS_BANNER_DISPLAY: 'display-add-extension-repos-banner'
|
|
92
96
|
};
|
|
93
97
|
|
|
94
98
|
// These are the settings that are allowed to be edited via the UI
|
package/config/table-headers.js
CHANGED
|
@@ -264,11 +264,12 @@ export const DURATION = {
|
|
|
264
264
|
formatter: 'LiveDuration',
|
|
265
265
|
};
|
|
266
266
|
|
|
267
|
-
export const
|
|
268
|
-
name:
|
|
269
|
-
labelKey:
|
|
270
|
-
value:
|
|
271
|
-
sort:
|
|
267
|
+
export const IMAGE_NAME = {
|
|
268
|
+
name: 'image',
|
|
269
|
+
labelKey: 'tableHeaders.image',
|
|
270
|
+
value: 'image',
|
|
271
|
+
sort: ['image', 'nameSort'],
|
|
272
|
+
formatter: 'ImageName',
|
|
272
273
|
};
|
|
273
274
|
|
|
274
275
|
export const POD_IMAGES = {
|
package/config/types.js
CHANGED
package/config/uiplugins.js
CHANGED
|
@@ -29,8 +29,21 @@ export const UI_PLUGINS_REPO_NAME = 'rancher-ui-plugins';
|
|
|
29
29
|
export const UI_PLUGINS_REPO_URL = 'https://github.com/rancher/ui-plugin-charts';
|
|
30
30
|
export const UI_PLUGINS_REPO_BRANCH = 'main';
|
|
31
31
|
|
|
32
|
+
// Info for the Helm Chart Repo for Partner Extensions
|
|
33
|
+
export const UI_PLUGINS_PARTNERS_REPO_NAME = 'partner-extensions';
|
|
34
|
+
|
|
35
|
+
export const UI_PLUGINS_PARTNERS_REPO_URL = 'https://github.com/rancher/partner-extensions';
|
|
36
|
+
export const UI_PLUGINS_PARTNERS_REPO_BRANCH = 'main';
|
|
37
|
+
|
|
38
|
+
// Info for the Helm Chart Repo for Community Extensions
|
|
39
|
+
export const UI_PLUGINS_COMMUNITY_REPO_NAME = 'community-extensions';
|
|
40
|
+
|
|
41
|
+
export const UI_PLUGINS_COMMUNITY_REPO_URL = 'https://github.com/rancher/community-extensions';
|
|
42
|
+
export const UI_PLUGINS_COMMUNITY_REPO_BRANCH = 'main';
|
|
43
|
+
|
|
32
44
|
// Chart annotations
|
|
33
45
|
export const UI_PLUGIN_CHART_ANNOTATIONS = {
|
|
46
|
+
KUBE_VERSION: 'catalog.cattle.io/kube-version',
|
|
34
47
|
RANCHER_VERSION: 'catalog.cattle.io/rancher-version',
|
|
35
48
|
EXTENSIONS_VERSION: 'catalog.cattle.io/ui-extensions-version',
|
|
36
49
|
UI_VERSION: 'catalog.cattle.io/ui-version',
|
|
@@ -121,16 +134,18 @@ export function shouldNotLoadPlugin(plugin, rancherVersion, loadedPlugins) {
|
|
|
121
134
|
}
|
|
122
135
|
|
|
123
136
|
// Can a chart version be used for this Rancher (based on the annotations on the chart)?
|
|
124
|
-
export function isSupportedChartVersion(
|
|
137
|
+
export function isSupportedChartVersion(versionsData) {
|
|
138
|
+
const { version, rancherVersion, kubeVersion } = versionsData;
|
|
139
|
+
|
|
125
140
|
// Plugin specified a required extension API version
|
|
126
|
-
const requiredAPI =
|
|
141
|
+
const requiredAPI = version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.EXTENSIONS_VERSION];
|
|
127
142
|
|
|
128
143
|
if (requiredAPI && !semver.satisfies(UI_PLUGIN_API_VERSION, requiredAPI)) {
|
|
129
144
|
return false;
|
|
130
145
|
}
|
|
131
146
|
|
|
132
147
|
// Host application
|
|
133
|
-
const requiredHost =
|
|
148
|
+
const requiredHost = version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.EXTENSIONS_HOST];
|
|
134
149
|
|
|
135
150
|
if (requiredHost && requiredHost !== UI_PLUGIN_HOST_APP) {
|
|
136
151
|
return false;
|
|
@@ -138,24 +153,37 @@ export function isSupportedChartVersion(chartVersion, rancherVersion) {
|
|
|
138
153
|
|
|
139
154
|
// Rancher version
|
|
140
155
|
if (rancherVersion) {
|
|
141
|
-
const requiredRancherVersion =
|
|
156
|
+
const requiredRancherVersion = version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.RANCHER_VERSION];
|
|
142
157
|
|
|
143
158
|
if (requiredRancherVersion && !semver.satisfies(rancherVersion, requiredRancherVersion)) {
|
|
144
159
|
return false;
|
|
145
160
|
}
|
|
146
161
|
}
|
|
147
162
|
|
|
163
|
+
// Kube version
|
|
164
|
+
if (kubeVersion) {
|
|
165
|
+
const requiredKubeVersion = version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.KUBE_VERSION];
|
|
166
|
+
|
|
167
|
+
if (requiredKubeVersion && !semver.satisfies(kubeVersion, requiredKubeVersion)) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
148
172
|
return true;
|
|
149
173
|
}
|
|
150
174
|
|
|
151
|
-
export function isChartVersionAvailableForInstall(
|
|
175
|
+
export function isChartVersionAvailableForInstall(versionsData, returnObj = false) {
|
|
176
|
+
const { version, rancherVersion, kubeVersion } = versionsData;
|
|
177
|
+
|
|
152
178
|
const parsedRancherVersion = rancherVersion.split('-')?.[0];
|
|
153
179
|
const regexHashString = new RegExp('^[A-Za-z0-9]{9}$');
|
|
154
180
|
const isRancherVersionHashString = regexHashString.test(rancherVersion);
|
|
155
181
|
const requiredUiVersion = version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.UI_VERSION];
|
|
182
|
+
const requiredKubeVersion = version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.KUBE_VERSION];
|
|
156
183
|
const versionObj = { ...version };
|
|
157
184
|
|
|
158
185
|
versionObj.isCompatibleWithUi = true;
|
|
186
|
+
versionObj.isCompatibleWithKubeVersion = true;
|
|
159
187
|
|
|
160
188
|
// if it's a head version of Rancher, then we skip the validation and enable them all
|
|
161
189
|
if (!isRancherVersionHashString && requiredUiVersion && !semver.satisfies(parsedRancherVersion, requiredUiVersion)) {
|
|
@@ -164,6 +192,23 @@ export function isChartVersionAvailableForInstall(version, rancherVersion, retur
|
|
|
164
192
|
}
|
|
165
193
|
versionObj.isCompatibleWithUi = false;
|
|
166
194
|
versionObj.requiredUiVersion = requiredUiVersion;
|
|
195
|
+
|
|
196
|
+
if (returnObj) {
|
|
197
|
+
return versionObj;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// check kube version
|
|
202
|
+
if (kubeVersion && requiredKubeVersion && !semver.satisfies(kubeVersion, requiredKubeVersion)) {
|
|
203
|
+
if (!returnObj) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
versionObj.isCompatibleWithKubeVersion = false;
|
|
207
|
+
versionObj.requiredKubeVersion = requiredKubeVersion;
|
|
208
|
+
|
|
209
|
+
if (returnObj) {
|
|
210
|
+
return versionObj;
|
|
211
|
+
}
|
|
167
212
|
}
|
|
168
213
|
|
|
169
214
|
if (returnObj) {
|
package/core/plugin-helpers.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { ActionLocation, CardLocation, ExtensionPoint } from '@shell/core/types';
|
|
2
2
|
import { isMac } from '@shell/utils/platform';
|
|
3
3
|
import { ucFirst, randomStr } from '@shell/utils/string';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
_EDIT, _CONFIG, _DETAIL, _LIST, _CREATE
|
|
6
|
+
} from '@shell/config/query-params';
|
|
5
7
|
import { getProductFromRoute } from '@shell/middleware/authenticated';
|
|
8
|
+
import { isEqual } from '@shell/utils/object';
|
|
6
9
|
|
|
7
10
|
function checkRouteProduct({ name, params, query }, locationConfigParam) {
|
|
8
11
|
const product = getProductFromRoute({
|
|
@@ -20,21 +23,24 @@ function checkRouteProduct({ name, params, query }, locationConfigParam) {
|
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
function checkRouteMode({ name, query }, locationConfigParam) {
|
|
23
|
-
if (locationConfigParam === _EDIT && query.mode && query.mode === _EDIT) {
|
|
26
|
+
if (locationConfigParam === _EDIT && query.mode && query.mode === _EDIT && !query.as) {
|
|
24
27
|
return true;
|
|
25
28
|
} else if (locationConfigParam === _CONFIG && query.as && query.as === _CONFIG) {
|
|
26
29
|
return true;
|
|
27
|
-
} else if (locationConfigParam === _DETAIL && name.includes('-id')) {
|
|
30
|
+
} else if (locationConfigParam === _DETAIL && !query.as && name.includes('-id') && (!query.mode || query?.mode !== _EDIT)) {
|
|
28
31
|
return true;
|
|
29
32
|
// alias to target all list views
|
|
30
33
|
} else if (locationConfigParam === _LIST && !name.includes('-id') && name.includes('-resource')) {
|
|
31
34
|
return true;
|
|
35
|
+
// alias to target create views
|
|
36
|
+
} else if (locationConfigParam === _CREATE && name.endsWith('-create')) {
|
|
37
|
+
return true;
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
return false;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
function checkExtensionRouteBinding($route, locationConfig) {
|
|
43
|
+
function checkExtensionRouteBinding($route, locationConfig, context) {
|
|
38
44
|
// if no configuration is passed, consider it as global
|
|
39
45
|
if (!Object.keys(locationConfig).length) {
|
|
40
46
|
return true;
|
|
@@ -43,23 +49,31 @@ function checkExtensionRouteBinding($route, locationConfig) {
|
|
|
43
49
|
const { params } = $route;
|
|
44
50
|
|
|
45
51
|
// "params" to be checked based on the locationConfig
|
|
52
|
+
// This has become overloaded with mode and context
|
|
46
53
|
const paramsToCheck = [
|
|
47
54
|
'product',
|
|
48
55
|
'resource',
|
|
49
56
|
'namespace',
|
|
50
57
|
'cluster',
|
|
51
58
|
'id',
|
|
52
|
-
'mode'
|
|
59
|
+
'mode',
|
|
60
|
+
'path',
|
|
61
|
+
// url query params
|
|
62
|
+
'queryParam',
|
|
63
|
+
// Custom context specific params provided by the extension, not to be confused with location params
|
|
64
|
+
'context',
|
|
53
65
|
];
|
|
54
66
|
|
|
55
|
-
let res =
|
|
67
|
+
let res = true;
|
|
56
68
|
|
|
57
69
|
for (let i = 0; i < paramsToCheck.length; i++) {
|
|
58
70
|
const param = paramsToCheck[i];
|
|
59
71
|
|
|
60
72
|
if (locationConfig[param]) {
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
const asArray = Array.isArray(locationConfig[param]) ? locationConfig[param] : [locationConfig[param]];
|
|
74
|
+
|
|
75
|
+
for (let x = 0; x < asArray.length; x++) {
|
|
76
|
+
const locationConfigParam = asArray[x];
|
|
63
77
|
|
|
64
78
|
if (locationConfigParam) {
|
|
65
79
|
// handle "product" in a separate way...
|
|
@@ -68,6 +82,21 @@ function checkExtensionRouteBinding($route, locationConfig) {
|
|
|
68
82
|
// also handle "mode" in a separate way because it mainly depends on query params
|
|
69
83
|
} else if (param === 'mode') {
|
|
70
84
|
res = checkRouteMode($route, locationConfigParam);
|
|
85
|
+
} else if (param === 'context') {
|
|
86
|
+
// Need all keys and values to match
|
|
87
|
+
res = isEqual(locationConfigParam, context);
|
|
88
|
+
// evaluate queryParam in route
|
|
89
|
+
} else if (param === 'queryParam') {
|
|
90
|
+
res = isEqual(locationConfigParam, $route.query);
|
|
91
|
+
// evaluate path in route
|
|
92
|
+
} else if (param === 'path' && locationConfigParam.urlPath) {
|
|
93
|
+
if (locationConfigParam.endsWith) {
|
|
94
|
+
res = $route.path.endsWith(locationConfigParam.urlPath);
|
|
95
|
+
} else if (!Object.keys(locationConfigParam).includes('exact') || locationConfigParam.exact) {
|
|
96
|
+
res = locationConfigParam.urlPath === $route.path;
|
|
97
|
+
} else {
|
|
98
|
+
res = $route.path.includes(locationConfigParam.urlPath);
|
|
99
|
+
}
|
|
71
100
|
} else if (locationConfigParam === params[param]) {
|
|
72
101
|
res = true;
|
|
73
102
|
} else {
|
|
@@ -91,7 +120,7 @@ function checkExtensionRouteBinding($route, locationConfig) {
|
|
|
91
120
|
return res;
|
|
92
121
|
}
|
|
93
122
|
|
|
94
|
-
export function getApplicableExtensionEnhancements(pluginCtx, actionType, uiArea, currRoute, translationCtx = pluginCtx) {
|
|
123
|
+
export function getApplicableExtensionEnhancements(pluginCtx, actionType, uiArea, currRoute, translationCtx = pluginCtx, context) {
|
|
95
124
|
const extensionEnhancements = [];
|
|
96
125
|
|
|
97
126
|
// gate it so that we prevent errors on older versions of dashboard
|
|
@@ -99,7 +128,7 @@ export function getApplicableExtensionEnhancements(pluginCtx, actionType, uiArea
|
|
|
99
128
|
const actions = pluginCtx.$plugin.getUIConfig(actionType, uiArea);
|
|
100
129
|
|
|
101
130
|
actions.forEach((action, i) => {
|
|
102
|
-
if (checkExtensionRouteBinding(currRoute, action.locationConfig)) {
|
|
131
|
+
if (checkExtensionRouteBinding(currRoute, action.locationConfig, context || {})) {
|
|
103
132
|
// ADD CARD PLUGIN UI ENHANCEMENT
|
|
104
133
|
if (actionType === ExtensionPoint.CARD) {
|
|
105
134
|
// intercept to apply translation
|
|
@@ -116,11 +145,6 @@ export function getApplicableExtensionEnhancements(pluginCtx, actionType, uiArea
|
|
|
116
145
|
actions[i].label = translationCtx.t(action.labelKey);
|
|
117
146
|
}
|
|
118
147
|
|
|
119
|
-
// sets the enabled flag to true if omitted on the config
|
|
120
|
-
if (!Object.keys(action).includes('enabled')) {
|
|
121
|
-
actions[i].enabled = true;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
148
|
// bulkable flag
|
|
125
149
|
actions[i].bulkable = actions[i].multiple || actions[i].bulkable;
|
|
126
150
|
|
package/core/plugin.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
PluginRouteConfig, RegisterStore, UnregisterStore, CoreStoreSpecifics, CoreStoreConfig, OnNavToPackage, OnNavAwayFromPackage, OnLogOut
|
|
16
16
|
} from './types';
|
|
17
17
|
import coreStore, { coreStoreModule, coreStoreState } from '@shell/plugins/dashboard-store';
|
|
18
|
+
import { registerLayout } from '@shell/initialize/layouts';
|
|
18
19
|
|
|
19
20
|
export type ProductFunction = (plugin: IPlugin, store: any) => void;
|
|
20
21
|
|
|
@@ -267,6 +268,14 @@ export class Plugin implements IPlugin {
|
|
|
267
268
|
}
|
|
268
269
|
|
|
269
270
|
this.l10n[name].push(fn);
|
|
271
|
+
} else if (type === 'layouts') {
|
|
272
|
+
fn().then((component: any) => {
|
|
273
|
+
if (component.default) {
|
|
274
|
+
registerLayout(name, component.default);
|
|
275
|
+
} else {
|
|
276
|
+
console.error(`Failed to load layout ${ name } because the file didn't export a default component.`); // eslint-disable-line no-console
|
|
277
|
+
}
|
|
278
|
+
});
|
|
270
279
|
} else {
|
|
271
280
|
if (!this.types[type]) {
|
|
272
281
|
this.types[type] = {};
|