@rancher/shell 0.3.17 → 0.3.19
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/translations/en-us.yaml +8 -4
- package/assets/translations/zh-hans.yaml +64 -8
- package/components/AsyncButton.vue +1 -1
- package/components/Inactivity.vue +10 -0
- package/components/LazyImage.vue +2 -2
- package/components/PromptRestore.vue +8 -6
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/ResourceDetail/index.vue +4 -2
- package/components/__tests__/PromptRestore.test.ts +142 -0
- package/components/auth/AzureWarning.vue +1 -1
- package/components/auth/RoleDetailEdit.vue +2 -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/__tests__/FileImageSelector.test.ts +42 -0
- package/components/form/__tests__/FileSelector.test.ts +76 -0
- package/components/formatter/ClusterProvider.vue +3 -1
- package/components/formatter/__tests__/ClusterProvider.test.ts +24 -0
- package/components/nav/WindowManager/ContainerShell.vue +60 -36
- package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +561 -0
- package/config/labels-annotations.js +2 -1
- package/config/persistentVolume.ts +108 -0
- package/config/product/manager.js +5 -1
- package/config/types.js +2 -0
- package/core/plugin-helpers.js +19 -3
- package/core/types.ts +4 -0
- package/detail/fleet.cattle.io.gitrepo.vue +10 -2
- package/detail/pod.vue +36 -3
- package/detail/workload/index.vue +40 -9
- package/dialog/DiagnosticTimingsDialog.vue +1 -0
- package/edit/__tests__/ui.cattle.io.navlink.test.ts +110 -0
- package/edit/fleet.cattle.io.clustergroup.vue +14 -3
- 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/RegistryConfigs.vue +15 -11
- package/edit/provisioning.cattle.io.cluster/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +5 -1
- package/edit/storage.k8s.io.storageclass/index.vue +1 -2
- package/edit/ui.cattle.io.navlink.vue +213 -186
- package/layouts/default.vue +1 -1
- package/list/group.principal.vue +1 -1
- package/middleware/authenticated.js +12 -4
- package/mixins/create-edit-view/impl.js +2 -2
- package/models/chart.js +1 -1
- package/models/etcdbackup.js +2 -1
- package/models/fleet.cattle.io.cluster.js +33 -4
- package/models/fleet.cattle.io.gitrepo.js +112 -38
- package/models/management.cattle.io.cluster.js +13 -3
- package/models/management.cattle.io.kontainerdriver.js +14 -0
- package/models/persistentvolume.js +2 -111
- package/models/pod.js +30 -0
- package/models/rke.cattle.io.etcdsnapshot.js +10 -7
- package/package.json +1 -1
- package/pages/c/_cluster/apps/charts/install.vue +74 -25
- 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 +1 -1
- 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/index.vue +9 -4
- package/pages/diagnostic.vue +5 -3
- package/pages/home.vue +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 +4 -0
- 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/components/BadgeState/BadgeState.spec.ts +12 -0
- package/rancher-components/components/BadgeState/BadgeState.vue +111 -0
- package/rancher-components/components/BadgeState/index.ts +1 -0
- package/rancher-components/components/Banner/Banner.test.ts +63 -0
- package/rancher-components/components/Banner/Banner.vue +244 -0
- package/rancher-components/components/Banner/index.ts +1 -0
- package/rancher-components/components/Card/Card.test.ts +37 -0
- package/rancher-components/components/Card/Card.vue +167 -0
- package/rancher-components/components/Card/index.ts +1 -0
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +68 -0
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +420 -0
- package/rancher-components/components/Form/Checkbox/index.ts +1 -0
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +23 -0
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +355 -0
- package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +287 -0
- package/rancher-components/components/Form/Radio/RadioGroup.vue +254 -0
- package/rancher-components/components/Form/Radio/index.ts +2 -0
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +170 -0
- package/rancher-components/components/Form/TextArea/index.ts +1 -0
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +94 -0
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +149 -0
- package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
- package/rancher-components/components/Form/index.ts +5 -0
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +151 -0
- package/rancher-components/components/LabeledTooltip/index.ts +1 -0
- package/rancher-components/components/StringList/StringList.test.ts +484 -0
- package/rancher-components/components/StringList/StringList.vue +611 -0
- package/rancher-components/components/StringList/index.ts +1 -0
- package/scripts/extension/publish +54 -14
- package/scripts/typegen.sh +10 -2
- package/store/index.js +1 -3
- package/store/store-types.js +2 -0
- package/types/api.d.ts +1 -0
- package/types/fleet.d.ts +1 -0
- package/types/shell/index.d.ts +696 -2
- package/types/userPreferences.d.ts +1 -1
- package/utils/__mocks__/socket.js +21 -0
- package/utils/grafana.js +23 -11
- package/utils/selector.js +2 -1
- package/utils/socket.js +1 -0
- package/utils/validators/formRules/index.ts +3 -3
- package/plugins/steve/urloptions.js +0 -47
|
@@ -3512,10 +3512,13 @@ navLink:
|
|
|
3512
3512
|
label: Group name
|
|
3513
3513
|
tooltip: Assign link to a group
|
|
3514
3514
|
sideLabel:
|
|
3515
|
-
label: Link
|
|
3515
|
+
label: Link label
|
|
3516
3516
|
description:
|
|
3517
3517
|
label: Link description
|
|
3518
|
+
groupImage:
|
|
3519
|
+
label: Group Image
|
|
3518
3520
|
iconSrc:
|
|
3521
|
+
tip: 'Image height should be 21 pixels with a max width of 200 pixels. Max file size is 20KB. Accepted formats: JPEG, PNG, SVG.'
|
|
3519
3522
|
label: Add image
|
|
3520
3523
|
networkpolicy:
|
|
3521
3524
|
egress:
|
|
@@ -3703,7 +3706,7 @@ persistentVolume:
|
|
|
3703
3706
|
label: Storage Policy ID
|
|
3704
3707
|
placeholder: e.g. sp1
|
|
3705
3708
|
csi:
|
|
3706
|
-
label: CSI
|
|
3709
|
+
label: CSI
|
|
3707
3710
|
suffix: (CSI)
|
|
3708
3711
|
driver:
|
|
3709
3712
|
label: Driver
|
|
@@ -4147,7 +4150,7 @@ plugins:
|
|
|
4147
4150
|
title: Extensions Safe Mode
|
|
4148
4151
|
message: Extensions were not loaded
|
|
4149
4152
|
addRepos:
|
|
4150
|
-
banner: There are new extensions repositories available. To enable
|
|
4153
|
+
banner: There are new extensions repositories available. To enable these repositories, click the button on the right.
|
|
4151
4154
|
bannerBtn: Add repositories
|
|
4152
4155
|
title: Add Extensions repositories
|
|
4153
4156
|
prompt: You can install multiple Rancher extension repositories to increase your extensions catalog
|
|
@@ -4167,7 +4170,7 @@ plugins:
|
|
|
4167
4170
|
airgap: Air-gapped installations should NOT enable this feature
|
|
4168
4171
|
addRancherRepo: Add Official Rancher Extensions Repository
|
|
4169
4172
|
addPartnersRancherRepo: Add Partners Extensions Repository
|
|
4170
|
-
addCommunityRancherRepo: Add Community
|
|
4173
|
+
addCommunityRancherRepo: Add Community Extensions Repository
|
|
4171
4174
|
remove:
|
|
4172
4175
|
label: Disable Extension Support
|
|
4173
4176
|
title: Disable Extension Support?
|
|
@@ -5766,6 +5769,7 @@ wm:
|
|
|
5766
5769
|
containerShell:
|
|
5767
5770
|
clear: Clear
|
|
5768
5771
|
containerName: "Container: {label}"
|
|
5772
|
+
failed: "Unable to open a shell to the container (none of the shell commmands succeeded)\n\r"
|
|
5769
5773
|
kubectlShell:
|
|
5770
5774
|
title: "Kubectl: {name}"
|
|
5771
5775
|
|
|
@@ -197,6 +197,12 @@ nav:
|
|
|
197
197
|
accountAndKeys: 账号 & API 密钥
|
|
198
198
|
logOut: 登出
|
|
199
199
|
failWhale:
|
|
200
|
+
authMiddleware: 认证中间件
|
|
201
|
+
clusterNotFound: 未找到集群 { clusterId }
|
|
202
|
+
productNotFound: 未找到产品 {productNotFound}
|
|
203
|
+
resourceNotFound: 未找到资源类型 { resource }
|
|
204
|
+
resourceListNotFound: 未找到资源类型 { resource },无法显示列表
|
|
205
|
+
resourceIdNotFound: 未找到 ID 为 { fqid } 的资源 { resources },无法显示资源详细信息
|
|
200
206
|
reload: 重新加载
|
|
201
207
|
separator: 或者
|
|
202
208
|
|
|
@@ -589,6 +595,10 @@ asyncButton:
|
|
|
589
595
|
action: 应用
|
|
590
596
|
success: 已应用
|
|
591
597
|
waiting: 正在应用…
|
|
598
|
+
add:
|
|
599
|
+
action: 添加
|
|
600
|
+
success: 已添加
|
|
601
|
+
waiting: 正在添加…
|
|
592
602
|
continue:
|
|
593
603
|
action: 继续
|
|
594
604
|
success: 已保存
|
|
@@ -2157,8 +2167,10 @@ fleet:
|
|
|
2157
2167
|
protocolBanner: 输入指向 git 仓库的有效 HTTPS 或 SSH URL。
|
|
2158
2168
|
resources:
|
|
2159
2169
|
label: '资源处理'
|
|
2160
|
-
keepResources:
|
|
2161
|
-
|
|
2170
|
+
keepResources: 永远保留资源
|
|
2171
|
+
keepResourcesBanner: 启用时,删除 GitRepo 或 Bundle 后将保留资源,只会删除 Helm Release Secret。
|
|
2172
|
+
correctDrift: 启用自我修复
|
|
2173
|
+
correctDriftBanner: 启用后,Fleet 将确保集群资源与 Git 仓库保持同步。在 ecluster 上进行的所有资源更改都将丢失。
|
|
2162
2174
|
add:
|
|
2163
2175
|
steps:
|
|
2164
2176
|
repoInfo:
|
|
@@ -2399,11 +2411,32 @@ hpa:
|
|
|
2399
2411
|
name:
|
|
2400
2412
|
label: 引用名称
|
|
2401
2413
|
placeholder: 例如:php-apache
|
|
2414
|
+
scaleDownRules:
|
|
2415
|
+
label: 缩减行为
|
|
2416
|
+
enable: 配置缩减行为
|
|
2417
|
+
scaleUpRules:
|
|
2418
|
+
label: 扩展行为
|
|
2419
|
+
enable: 配置扩展行为
|
|
2420
|
+
scalingRule:
|
|
2421
|
+
policyHeader: 策略
|
|
2422
|
+
addPolicy: 添加策略
|
|
2423
|
+
selectPolicy: 选择策略
|
|
2424
|
+
selectPolicyTooltip: 选择具有最大值、最小值或禁用缩放的策略。
|
|
2425
|
+
stabilizationWindowSeconds: 稳定窗口秒数
|
|
2426
|
+
stabilizationWindowSecondsTooltip: 在扩展或缩减时应考虑过去建议的秒数。
|
|
2427
|
+
policy:
|
|
2428
|
+
type: 类型
|
|
2429
|
+
typeTooltip: 根据要扩展的 Pod 数量或要扩展的当前副本百分比设置策略。
|
|
2430
|
+
value: 值
|
|
2431
|
+
valueTooltip: 策略允许的变更数量。
|
|
2432
|
+
periodSeconds: 周期秒数
|
|
2433
|
+
periodSecondsTooltip: 策略生效的时间窗口。
|
|
2402
2434
|
tabs:
|
|
2403
2435
|
labels: 标签
|
|
2404
2436
|
metrics: 指标
|
|
2405
2437
|
target: 目标
|
|
2406
2438
|
workload: 工作负载
|
|
2439
|
+
behavior: 行为
|
|
2407
2440
|
types:
|
|
2408
2441
|
cpu: CPU
|
|
2409
2442
|
memory: 内存
|
|
@@ -3030,6 +3063,9 @@ login:
|
|
|
3030
3063
|
remember:
|
|
3031
3064
|
label: 记住用户名
|
|
3032
3065
|
|
|
3066
|
+
logout:
|
|
3067
|
+
message: 正在登出...
|
|
3068
|
+
|
|
3033
3069
|
managementNode:
|
|
3034
3070
|
customName: 自定义名称
|
|
3035
3071
|
|
|
@@ -3677,7 +3713,7 @@ persistentVolume:
|
|
|
3677
3713
|
label: 存储策略 ID
|
|
3678
3714
|
placeholder: 例如:sp1
|
|
3679
3715
|
csi:
|
|
3680
|
-
label: CSI
|
|
3716
|
+
label: CSI
|
|
3681
3717
|
suffix: (CSI)
|
|
3682
3718
|
driver:
|
|
3683
3719
|
label: 驱动
|
|
@@ -3999,6 +4035,8 @@ inactivity:
|
|
|
3999
4035
|
# Rancher Extensions
|
|
4000
4036
|
plugins:
|
|
4001
4037
|
incompatibleRancherVersion: "此扩展的最新版本 ({ version }) 与当前的 Rancher 版本 ({ rancherVersion }) 不兼容。"
|
|
4038
|
+
incompatibleKubeVersion: "此扩展的最新版本 ({ version }) 与当前的 Kube 版本 ({ kubeVersion }) 不兼容。"
|
|
4039
|
+
currentInstalledVersionBlockedByKubeVersion: "此版本与当前 Kubernetes 版本 ({ kubeVersion } Vs { kubeVersionToCheck }) 不兼容。"
|
|
4002
4040
|
labels:
|
|
4003
4041
|
builtin: 内置角色
|
|
4004
4042
|
experimental: 实验功能
|
|
@@ -4036,6 +4074,7 @@ plugins:
|
|
|
4036
4074
|
versions: 版本
|
|
4037
4075
|
versionError: 无法加载版本信息
|
|
4038
4076
|
requiresRancherVersion: "需要 Rancher {version}"
|
|
4077
|
+
requiresKubeVersion: "需要 Kube {version}"
|
|
4039
4078
|
empty:
|
|
4040
4079
|
all: 扩展未安装或不可用
|
|
4041
4080
|
available: 没有可用的扩展
|
|
@@ -4045,6 +4084,7 @@ plugins:
|
|
|
4045
4084
|
loadError: 加载此扩展的代码时出错
|
|
4046
4085
|
helmError: "通过 Helm 安装扩展时出错"
|
|
4047
4086
|
manageRepos: 管理仓库
|
|
4087
|
+
addRancherRepos: 添加 Rancher 仓库
|
|
4048
4088
|
manageCharts: 管理扩展 Chart
|
|
4049
4089
|
manageCatalog:
|
|
4050
4090
|
label: 管理扩展商店
|
|
@@ -4116,23 +4156,39 @@ plugins:
|
|
|
4116
4156
|
safeMode:
|
|
4117
4157
|
title: 扩展安全模式
|
|
4118
4158
|
message: 未加载扩展
|
|
4159
|
+
addRepos:
|
|
4160
|
+
banner: 有新的扩展仓库可用。要启用这些仓库,请单击右侧的按钮。
|
|
4161
|
+
bannerBtn: 添加仓库
|
|
4162
|
+
title: 添加扩展仓库
|
|
4163
|
+
prompt: 你可以安装多个 Rancher 扩展仓库来增加你的扩展商店
|
|
4119
4164
|
setup:
|
|
4165
|
+
installed: 已安装
|
|
4166
|
+
uninstalled: 已卸载
|
|
4120
4167
|
title: 未启用扩展支持
|
|
4121
4168
|
prompt:
|
|
4122
4169
|
cant: 自动安装不可用 - 找不到所需的 Helm Chart
|
|
4123
4170
|
can: 你需要安装 Extension Operator
|
|
4171
|
+
official: Official Rancher Extensions 仓库提供了由 Rancher 发布的扩展。
|
|
4172
|
+
partners: Partners Extensions 仓库提供了由 Rancher 合作伙伴发布的扩展。
|
|
4173
|
+
community: Community Extensions 仓库提供了由 Rancher 社区发布的扩展。
|
|
4124
4174
|
install:
|
|
4125
4175
|
title: 启用扩展支持?
|
|
4126
|
-
prompt:
|
|
4127
|
-
airgap:
|
|
4128
|
-
addRancherRepo: 添加 Rancher
|
|
4176
|
+
prompt: 这将安装启用扩展支持所需的 Helm Chart
|
|
4177
|
+
airgap: 离线安装环境请不要启用此功能
|
|
4178
|
+
addRancherRepo: 添加 Official Rancher Extensions 仓库
|
|
4179
|
+
addPartnersRancherRepo: 添加 Partners Extensions 仓库
|
|
4180
|
+
addCommunityRancherRepo: 添加 Community Extensions 仓库
|
|
4129
4181
|
remove:
|
|
4130
4182
|
label: 禁用扩展支持
|
|
4131
4183
|
title: 禁用扩展支持?
|
|
4132
4184
|
prompt: 这将卸载启用扩展支持的 Helm Chart
|
|
4133
4185
|
registry:
|
|
4134
|
-
|
|
4135
|
-
|
|
4186
|
+
official:
|
|
4187
|
+
title: 删除 Official Rancher Extensions 仓库
|
|
4188
|
+
partners:
|
|
4189
|
+
title: 删除 Partners Rancher Extensions 仓库
|
|
4190
|
+
community:
|
|
4191
|
+
title: 删除 Community Extensions 仓库
|
|
4136
4192
|
crd:
|
|
4137
4193
|
title: 删除 Rancher Extensions CRD
|
|
4138
4194
|
prompt: 目前已安装了一个或多个扩展 - 如果你后续需要重新启用扩展支持,删除 CRD 后你需要手动重新安装这些扩展。
|
|
@@ -14,7 +14,7 @@ const TOOLTIP = 'tooltip';
|
|
|
14
14
|
|
|
15
15
|
export type AsyncButtonCallback = (success: boolean) => void;
|
|
16
16
|
|
|
17
|
-
export default Vue.extend({
|
|
17
|
+
export default Vue.extend<{ phase: string}, any, any, any>({
|
|
18
18
|
props: {
|
|
19
19
|
/**
|
|
20
20
|
* Mode maps to keys in asyncButton.* translations
|
|
@@ -6,6 +6,8 @@ import throttle from 'lodash/throttle';
|
|
|
6
6
|
import { MANAGEMENT } from '@shell/config/types';
|
|
7
7
|
import { DEFAULT_PERF_SETTING, SETTING } from '@shell/config/settings';
|
|
8
8
|
|
|
9
|
+
let globalId;
|
|
10
|
+
|
|
9
11
|
export default {
|
|
10
12
|
name: 'Inactivity',
|
|
11
13
|
components: {
|
|
@@ -22,6 +24,7 @@ export default {
|
|
|
22
24
|
courtesyTimerId: null,
|
|
23
25
|
courtesyCountdown: null,
|
|
24
26
|
trackInactivity: throttle(this._trackInactivity, 1000),
|
|
27
|
+
id: null,
|
|
25
28
|
};
|
|
26
29
|
},
|
|
27
30
|
async mounted() {
|
|
@@ -72,9 +75,16 @@ export default {
|
|
|
72
75
|
this.clearAllTimeouts();
|
|
73
76
|
const endTime = Date.now() + this.showModalAfter * 1000;
|
|
74
77
|
|
|
78
|
+
this.id = endTime;
|
|
79
|
+
globalId = endTime;
|
|
80
|
+
|
|
75
81
|
const checkInactivityTimer = () => {
|
|
76
82
|
const now = Date.now();
|
|
77
83
|
|
|
84
|
+
if (this.id !== globalId) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
78
88
|
if (now >= endTime) {
|
|
79
89
|
this.isOpen = true;
|
|
80
90
|
this.startCountdown();
|
package/components/LazyImage.vue
CHANGED
|
@@ -3,12 +3,12 @@ export default {
|
|
|
3
3
|
props: {
|
|
4
4
|
initialSrc: {
|
|
5
5
|
type: String,
|
|
6
|
-
default: require('
|
|
6
|
+
default: require('@shell/assets/images/generic-catalog.svg'),
|
|
7
7
|
},
|
|
8
8
|
|
|
9
9
|
errorSrc: {
|
|
10
10
|
type: String,
|
|
11
|
-
default: require('
|
|
11
|
+
default: require('@shell/assets/images/generic-catalog.svg'),
|
|
12
12
|
},
|
|
13
13
|
|
|
14
14
|
src: {
|
|
@@ -14,6 +14,7 @@ import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
|
|
|
14
14
|
import { escapeHtml } from '@shell/utils/string';
|
|
15
15
|
import day from 'dayjs';
|
|
16
16
|
import { sortBy } from '@shell/utils/sort';
|
|
17
|
+
import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
17
18
|
|
|
18
19
|
export default {
|
|
19
20
|
components: {
|
|
@@ -51,7 +52,7 @@ export default {
|
|
|
51
52
|
// Was the dialog opened to restore a specific snapshot, or opened on a cluster to choose
|
|
52
53
|
isCluster() {
|
|
53
54
|
const isSnapshot = this.toRestore[0]?.type.toLowerCase() === NORMAN.ETCD_BACKUP ||
|
|
54
|
-
|
|
55
|
+
this.toRestore[0]?.type.toLowerCase() === SNAPSHOT;
|
|
55
56
|
|
|
56
57
|
return !isSnapshot;
|
|
57
58
|
},
|
|
@@ -113,20 +114,21 @@ export default {
|
|
|
113
114
|
const cluster = this.toRestore?.[0];
|
|
114
115
|
let promise;
|
|
115
116
|
|
|
116
|
-
if (!cluster
|
|
117
|
+
if (!cluster?.isRke2) {
|
|
117
118
|
promise = this.$store.dispatch('rancher/findAll', { type: NORMAN.ETCD_BACKUP }).then((snapshots) => {
|
|
118
|
-
return snapshots.filter((s) => s.clusterId === cluster.metadata.name);
|
|
119
|
+
return snapshots.filter((s) => s.state === STATES_ENUM.ACTIVE && s.clusterId === cluster.metadata.name);
|
|
119
120
|
});
|
|
120
121
|
} else {
|
|
121
122
|
promise = this.$store.dispatch('management/findAll', { type: SNAPSHOT }).then((snapshots) => {
|
|
122
123
|
const toRestoreClusterName = cluster?.clusterName || cluster?.metadata?.name;
|
|
123
124
|
|
|
124
|
-
return snapshots.filter((s) => s.clusterName === toRestoreClusterName
|
|
125
|
+
return snapshots.filter((s) => s?.snapshotFile?.status === STATES_ENUM.SUCCESSFUL && s.clusterName === toRestoreClusterName
|
|
126
|
+
);
|
|
125
127
|
});
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
// Map of snapshots by name
|
|
129
|
-
const
|
|
131
|
+
const allSnapshots = await promise.then((snapshots) => {
|
|
130
132
|
return snapshots.reduce((v, s) => {
|
|
131
133
|
v[s.name] = s;
|
|
132
134
|
|
|
@@ -136,7 +138,7 @@ export default {
|
|
|
136
138
|
this.errors = exceptionToErrorsArray(err);
|
|
137
139
|
});
|
|
138
140
|
|
|
139
|
-
this.allSnapshots =
|
|
141
|
+
this.allSnapshots = allSnapshots;
|
|
140
142
|
this.sortedSnapshots = sortBy(Object.values(this.allSnapshots), ['snapshotFile.createdAt', 'created', 'metadata.creationTimestamp'], true);
|
|
141
143
|
},
|
|
142
144
|
|
|
@@ -216,7 +216,7 @@ export default {
|
|
|
216
216
|
},
|
|
217
217
|
|
|
218
218
|
parent() {
|
|
219
|
-
const displayName = this.value
|
|
219
|
+
const displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
|
|
220
220
|
const product = this.$store.getters['currentProduct'].name;
|
|
221
221
|
|
|
222
222
|
const defaultLocation = {
|
|
@@ -83,16 +83,18 @@ export default {
|
|
|
83
83
|
default: 'resource-details'
|
|
84
84
|
}
|
|
85
85
|
},
|
|
86
|
+
|
|
86
87
|
async fetch() {
|
|
87
88
|
const store = this.$store;
|
|
88
89
|
const route = this.$route;
|
|
89
90
|
const params = route.params;
|
|
90
|
-
|
|
91
|
+
let resource = this.resourceOverride || params.resource;
|
|
92
|
+
|
|
93
|
+
const inStore = this.storeOverride || store.getters['currentStore'](resource);
|
|
91
94
|
const realMode = this.realMode;
|
|
92
95
|
|
|
93
96
|
// eslint-disable-next-line prefer-const
|
|
94
97
|
let { namespace, id } = params;
|
|
95
|
-
let resource = this.resourceOverride || params.resource;
|
|
96
98
|
|
|
97
99
|
// There are 6 "real" modes that can be put into the query string
|
|
98
100
|
// These are mapped down to the 3 regular page "mode"s that create-edit-view components
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
|
2
|
+
import PromptRestore from '@shell/components/PromptRestore.vue';
|
|
3
|
+
import Vuex from 'vuex';
|
|
4
|
+
import { ExtendedVue, Vue } from 'vue/types/vue';
|
|
5
|
+
import { DefaultProps } from 'vue/types/options';
|
|
6
|
+
import { CAPI, NORMAN } from '@shell/config/types';
|
|
7
|
+
import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
8
|
+
|
|
9
|
+
const RKE2_CLUSTER_NAME = 'rke2_cluster_name';
|
|
10
|
+
const RKE2_SUCCESSFUL_SNAPSHOT_1 = {
|
|
11
|
+
clusterName: RKE2_CLUSTER_NAME,
|
|
12
|
+
type: CAPI.RANCHER_CLUSTER,
|
|
13
|
+
created: 'Thu Jul 20 2023 11:11:39',
|
|
14
|
+
snapshotFile: { status: STATES_ENUM.SUCCESSFUL },
|
|
15
|
+
id: 'rke2_id_1',
|
|
16
|
+
name: 'rke2_name_1'
|
|
17
|
+
};
|
|
18
|
+
const RKE2_SUCCESSFUL_SNAPSHOT_2 = {
|
|
19
|
+
clusterName: RKE2_CLUSTER_NAME,
|
|
20
|
+
type: CAPI.RANCHER_CLUSTER,
|
|
21
|
+
created: 'Thu Jul 20 2022 11:11:39',
|
|
22
|
+
snapshotFile: { status: STATES_ENUM.SUCCESSFUL },
|
|
23
|
+
id: 'rke2_id_2',
|
|
24
|
+
name: 'rke2_name_2'
|
|
25
|
+
};
|
|
26
|
+
const RKE2_FAILED_SNAPSHOT = {
|
|
27
|
+
clusterName: RKE2_CLUSTER_NAME,
|
|
28
|
+
type: CAPI.RANCHER_CLUSTER,
|
|
29
|
+
created: 'Thu Jul 20 2021 11:11:39',
|
|
30
|
+
snapshotFile: { status: STATES_ENUM.FAILED },
|
|
31
|
+
id: 'rke2_id_3',
|
|
32
|
+
name: 'rke2_name_3'
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const RKE1_CLUSTER_NAME = 'rke1_cluster_name';
|
|
36
|
+
const RKE1_SUCCESSFUL_SNAPSHOT_1 = {
|
|
37
|
+
clusterId: RKE1_CLUSTER_NAME,
|
|
38
|
+
type: NORMAN.ETCD_BACKUP,
|
|
39
|
+
state: STATES_ENUM.ACTIVE,
|
|
40
|
+
created: 'Thu Jul 30 2023 11:11:39',
|
|
41
|
+
id: 'rke1_id_1',
|
|
42
|
+
name: 'rke1_name_1'
|
|
43
|
+
};
|
|
44
|
+
const RKE1_SUCCESSFUL_SNAPSHOT_2 = {
|
|
45
|
+
clusterId: RKE1_CLUSTER_NAME,
|
|
46
|
+
type: NORMAN.ETCD_BACKUP,
|
|
47
|
+
state: STATES_ENUM.ACTIVE,
|
|
48
|
+
created: 'Thu Jul 30 2022 11:11:39',
|
|
49
|
+
id: 'rke1_id_2',
|
|
50
|
+
name: 'rke1_name_2'
|
|
51
|
+
};
|
|
52
|
+
const RKE1_WITH_ERROR_SNAPSHOT = {
|
|
53
|
+
clusterId: RKE1_CLUSTER_NAME,
|
|
54
|
+
type: NORMAN.ETCD_BACKUP,
|
|
55
|
+
state: STATES_ENUM.ERROR,
|
|
56
|
+
created: 'Thu Jul 30 2021 11:11:39',
|
|
57
|
+
id: 'rke1_id_3',
|
|
58
|
+
name: 'rke1_name_3'
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
describe('component: PromptRestore', () => {
|
|
62
|
+
const localVue = createLocalVue();
|
|
63
|
+
|
|
64
|
+
localVue.use(Vuex);
|
|
65
|
+
|
|
66
|
+
const rke2TestCases = [
|
|
67
|
+
[[], 0],
|
|
68
|
+
[[RKE2_FAILED_SNAPSHOT], 0],
|
|
69
|
+
[[RKE2_SUCCESSFUL_SNAPSHOT_1], 1],
|
|
70
|
+
[[RKE2_SUCCESSFUL_SNAPSHOT_1, RKE2_SUCCESSFUL_SNAPSHOT_2], 2],
|
|
71
|
+
[[RKE2_FAILED_SNAPSHOT, RKE2_SUCCESSFUL_SNAPSHOT_1, RKE2_SUCCESSFUL_SNAPSHOT_2], 2]
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
it.each(rke2TestCases)('should list RKE2 snapshots properly', async(snapShots, expected) => {
|
|
75
|
+
const store = new Vuex.Store({
|
|
76
|
+
modules: {
|
|
77
|
+
'action-menu': {
|
|
78
|
+
namespaced: true,
|
|
79
|
+
state: {
|
|
80
|
+
showPromptRestore: true,
|
|
81
|
+
toRestore: [{
|
|
82
|
+
isRke2: true,
|
|
83
|
+
type: CAPI.RANCHER_CLUSTER,
|
|
84
|
+
metadata: { name: RKE2_CLUSTER_NAME },
|
|
85
|
+
snapShots
|
|
86
|
+
}]
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
getters: { 'i18n/t': () => jest.fn(), 'prefs/get': () => jest.fn() },
|
|
91
|
+
actions: { 'management/findAll': jest.fn().mockResolvedValue(snapShots), 'rancher/findAll': jest.fn().mockResolvedValue([]) }
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const wrapper = shallowMount(PromptRestore as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
|
|
95
|
+
store,
|
|
96
|
+
localVue
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
await wrapper.vm.fetchSnapshots();
|
|
100
|
+
await wrapper.vm.$nextTick();
|
|
101
|
+
|
|
102
|
+
expect(wrapper.vm.clusterSnapshots).toHaveLength(expected);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const rke1TestCases = [
|
|
106
|
+
[[], 0],
|
|
107
|
+
[[RKE1_WITH_ERROR_SNAPSHOT], 0],
|
|
108
|
+
[[RKE1_SUCCESSFUL_SNAPSHOT_1], 1],
|
|
109
|
+
[[RKE1_SUCCESSFUL_SNAPSHOT_1, RKE1_SUCCESSFUL_SNAPSHOT_2], 2],
|
|
110
|
+
[[RKE1_WITH_ERROR_SNAPSHOT, RKE1_SUCCESSFUL_SNAPSHOT_1, RKE1_SUCCESSFUL_SNAPSHOT_2], 2]
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
it.each(rke1TestCases)('should list RKE1 snapshots properly', async(snapShots, expected) => {
|
|
114
|
+
const store = new Vuex.Store({
|
|
115
|
+
modules: {
|
|
116
|
+
'action-menu': {
|
|
117
|
+
namespaced: true,
|
|
118
|
+
state: {
|
|
119
|
+
showPromptRestore: true,
|
|
120
|
+
toRestore: [{
|
|
121
|
+
type: CAPI.RANCHER_CLUSTER,
|
|
122
|
+
metadata: { name: RKE1_CLUSTER_NAME },
|
|
123
|
+
snapShots
|
|
124
|
+
}]
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
getters: { 'i18n/t': () => jest.fn(), 'prefs/get': () => jest.fn() },
|
|
129
|
+
actions: { 'rancher/findAll': jest.fn().mockResolvedValue(snapShots) }
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const wrapper = shallowMount(PromptRestore as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
|
|
133
|
+
store,
|
|
134
|
+
localVue
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
await wrapper.vm.fetchSnapshots();
|
|
138
|
+
await wrapper.vm.$nextTick();
|
|
139
|
+
|
|
140
|
+
expect(wrapper.vm.clusterSnapshots).toHaveLength(expected);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { NORMAN, MANAGEMENT } from '@shell/config/types';
|
|
4
4
|
import { get } from '@shell/utils/object';
|
|
5
5
|
import { AZURE_MIGRATED } from '@shell/config/labels-annotations';
|
|
6
|
-
import { BLANK_CLUSTER } from '@shell/store';
|
|
6
|
+
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
7
7
|
|
|
8
8
|
export default {
|
|
9
9
|
async fetch() {
|
|
@@ -579,6 +579,7 @@ export default {
|
|
|
579
579
|
name="storageSource"
|
|
580
580
|
:label="defaultLabel"
|
|
581
581
|
class="mb-10"
|
|
582
|
+
data-testid="roletemplate-creator-default-options"
|
|
582
583
|
:options="newUserDefaultOptions"
|
|
583
584
|
:mode="mode"
|
|
584
585
|
/>
|
|
@@ -592,6 +593,7 @@ export default {
|
|
|
592
593
|
name="storageSource"
|
|
593
594
|
:label="t('rbac.roletemplate.locked.label')"
|
|
594
595
|
class="mb-10"
|
|
596
|
+
data-testid="roletemplate-locked-options"
|
|
595
597
|
:options="lockedOptions"
|
|
596
598
|
:mode="mode"
|
|
597
599
|
/>
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { colorForState, stateDisplay, stateSort, STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
3
2
|
import SortableTable from '@shell/components/SortableTable';
|
|
4
|
-
import {
|
|
5
|
-
import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
6
|
-
import { randomStr } from '@shell/utils/string';
|
|
3
|
+
import { AGE } from '@shell/config/table-headers';
|
|
7
4
|
|
|
8
5
|
export default {
|
|
9
6
|
name: 'FleetResources',
|
|
@@ -19,66 +16,7 @@ export default {
|
|
|
19
16
|
|
|
20
17
|
computed: {
|
|
21
18
|
computedResources() {
|
|
22
|
-
|
|
23
|
-
const resources = this.value.status?.resources || [];
|
|
24
|
-
const out = [];
|
|
25
|
-
|
|
26
|
-
for ( const r of resources ) {
|
|
27
|
-
let namespacedName = r.name;
|
|
28
|
-
|
|
29
|
-
if ( r.namespace ) {
|
|
30
|
-
namespacedName = `${ r.namespace }:${ r.name }`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
for ( const c of clusters ) {
|
|
34
|
-
let state = r.state;
|
|
35
|
-
const perEntry = r.perClusterState?.find((x) => x.clusterId === c.id );
|
|
36
|
-
const tooMany = r.perClusterState?.length >= 10 || false;
|
|
37
|
-
|
|
38
|
-
if ( perEntry ) {
|
|
39
|
-
state = perEntry.state;
|
|
40
|
-
} else if ( tooMany ) {
|
|
41
|
-
state = STATES_ENUM.UNKNOWN;
|
|
42
|
-
} else {
|
|
43
|
-
state = STATES_ENUM.READY;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const color = colorForState(state).replace('text-', 'bg-');
|
|
47
|
-
const display = stateDisplay(state);
|
|
48
|
-
|
|
49
|
-
const detailLocation = {
|
|
50
|
-
name: `c-cluster-product-resource${ r.namespace ? '-namespace' : '' }-id`,
|
|
51
|
-
params: {
|
|
52
|
-
product: EXPLORER,
|
|
53
|
-
cluster: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME],
|
|
54
|
-
resource: r.type,
|
|
55
|
-
namespace: r.namespace,
|
|
56
|
-
id: r.name,
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
out.push({
|
|
61
|
-
key: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }`,
|
|
62
|
-
tableKey: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }-${ randomStr(8) }`,
|
|
63
|
-
kind: r.kind,
|
|
64
|
-
apiVersion: r.apiVersion,
|
|
65
|
-
type: r.type,
|
|
66
|
-
id: r.id,
|
|
67
|
-
namespace: r.namespace,
|
|
68
|
-
name: r.name,
|
|
69
|
-
clusterId: c.id,
|
|
70
|
-
clusterName: c.nameDisplay,
|
|
71
|
-
state,
|
|
72
|
-
stateBackground: color,
|
|
73
|
-
stateDisplay: display,
|
|
74
|
-
stateSort: stateSort(color, display),
|
|
75
|
-
namespacedName,
|
|
76
|
-
detailLocation,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return out;
|
|
19
|
+
return this.value.resourcesStatuses;
|
|
82
20
|
},
|
|
83
21
|
|
|
84
22
|
resourceHeaders() {
|
|
@@ -122,6 +60,7 @@ export default {
|
|
|
122
60
|
sort: 'namespace',
|
|
123
61
|
label: 'Namespace',
|
|
124
62
|
},
|
|
63
|
+
{ ...AGE }
|
|
125
64
|
];
|
|
126
65
|
},
|
|
127
66
|
}
|
|
@@ -31,6 +31,10 @@ export default {
|
|
|
31
31
|
type: Number,
|
|
32
32
|
default: 200000
|
|
33
33
|
},
|
|
34
|
+
accept: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: 'image/*'
|
|
37
|
+
}
|
|
34
38
|
},
|
|
35
39
|
computed: {
|
|
36
40
|
isView() {
|
|
@@ -44,6 +48,9 @@ export default {
|
|
|
44
48
|
*/
|
|
45
49
|
setIcon(event) {
|
|
46
50
|
this.$emit('input', event);
|
|
51
|
+
},
|
|
52
|
+
setError(error) {
|
|
53
|
+
this.$emit('error', error);
|
|
47
54
|
}
|
|
48
55
|
}
|
|
49
56
|
};
|
|
@@ -58,7 +65,9 @@ export default {
|
|
|
58
65
|
:read-as-data-url="true"
|
|
59
66
|
:byte-limit="byteLimit"
|
|
60
67
|
:label="label"
|
|
68
|
+
:accept="accept"
|
|
61
69
|
@selected="setIcon"
|
|
70
|
+
@error="setError"
|
|
62
71
|
/>
|
|
63
72
|
|
|
64
73
|
<div
|
|
@@ -218,12 +218,10 @@ export default {
|
|
|
218
218
|
|
|
219
219
|
if ( rule.operator === 'Exists' || rule.operator === 'DoesNotExist') {
|
|
220
220
|
val = null;
|
|
221
|
-
} else if (!val) {
|
|
222
|
-
return;
|
|
223
221
|
}
|
|
224
222
|
|
|
225
223
|
if ( val !== null ) {
|
|
226
|
-
expression.values = val.split(/\s*,\s*/)
|
|
224
|
+
expression.values = val.split(/\s*,\s*/);
|
|
227
225
|
}
|
|
228
226
|
|
|
229
227
|
return expression;
|