@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.
Files changed (118) hide show
  1. package/assets/translations/en-us.yaml +8 -4
  2. package/assets/translations/zh-hans.yaml +64 -8
  3. package/components/AsyncButton.vue +1 -1
  4. package/components/Inactivity.vue +10 -0
  5. package/components/LazyImage.vue +2 -2
  6. package/components/PromptRestore.vue +8 -6
  7. package/components/ResourceDetail/Masthead.vue +1 -1
  8. package/components/ResourceDetail/index.vue +4 -2
  9. package/components/__tests__/PromptRestore.test.ts +142 -0
  10. package/components/auth/AzureWarning.vue +1 -1
  11. package/components/auth/RoleDetailEdit.vue +2 -0
  12. package/components/fleet/FleetResources.vue +3 -64
  13. package/components/form/FileImageSelector.vue +9 -0
  14. package/components/form/FileSelector.vue +2 -1
  15. package/components/form/MatchExpressions.vue +1 -3
  16. package/components/form/__tests__/FileImageSelector.test.ts +42 -0
  17. package/components/form/__tests__/FileSelector.test.ts +76 -0
  18. package/components/formatter/ClusterProvider.vue +3 -1
  19. package/components/formatter/__tests__/ClusterProvider.test.ts +24 -0
  20. package/components/nav/WindowManager/ContainerShell.vue +60 -36
  21. package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +561 -0
  22. package/config/labels-annotations.js +2 -1
  23. package/config/persistentVolume.ts +108 -0
  24. package/config/product/manager.js +5 -1
  25. package/config/types.js +2 -0
  26. package/core/plugin-helpers.js +19 -3
  27. package/core/types.ts +4 -0
  28. package/detail/fleet.cattle.io.gitrepo.vue +10 -2
  29. package/detail/pod.vue +36 -3
  30. package/detail/workload/index.vue +40 -9
  31. package/dialog/DiagnosticTimingsDialog.vue +1 -0
  32. package/edit/__tests__/ui.cattle.io.navlink.test.ts +110 -0
  33. package/edit/fleet.cattle.io.clustergroup.vue +14 -3
  34. package/edit/persistentvolume/__tests__/persistentvolume.test.ts +82 -0
  35. package/edit/persistentvolume/index.vue +2 -1
  36. package/edit/persistentvolume/plugins/csi.vue +3 -1
  37. package/edit/persistentvolume/plugins/longhorn.vue +12 -12
  38. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +15 -11
  39. package/edit/provisioning.cattle.io.cluster/index.vue +1 -1
  40. package/edit/provisioning.cattle.io.cluster/rke2.vue +5 -1
  41. package/edit/storage.k8s.io.storageclass/index.vue +1 -2
  42. package/edit/ui.cattle.io.navlink.vue +213 -186
  43. package/layouts/default.vue +1 -1
  44. package/list/group.principal.vue +1 -1
  45. package/middleware/authenticated.js +12 -4
  46. package/mixins/create-edit-view/impl.js +2 -2
  47. package/models/chart.js +1 -1
  48. package/models/etcdbackup.js +2 -1
  49. package/models/fleet.cattle.io.cluster.js +33 -4
  50. package/models/fleet.cattle.io.gitrepo.js +112 -38
  51. package/models/management.cattle.io.cluster.js +13 -3
  52. package/models/management.cattle.io.kontainerdriver.js +14 -0
  53. package/models/persistentvolume.js +2 -111
  54. package/models/pod.js +30 -0
  55. package/models/rke.cattle.io.etcdsnapshot.js +10 -7
  56. package/package.json +1 -1
  57. package/pages/c/_cluster/apps/charts/install.vue +74 -25
  58. package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
  59. package/pages/c/_cluster/auth/roles/index.vue +1 -1
  60. package/pages/c/_cluster/explorer/index.vue +1 -1
  61. package/pages/c/_cluster/manager/cloudCredential/_id.vue +0 -1
  62. package/pages/c/_cluster/manager/cloudCredential/create.vue +0 -1
  63. package/pages/c/_cluster/settings/brand.vue +11 -8
  64. package/pages/c/_cluster/uiplugins/index.vue +9 -4
  65. package/pages/diagnostic.vue +5 -3
  66. package/pages/home.vue +1 -1
  67. package/plugins/dashboard-store/__tests__/actions.spec.ts +165 -0
  68. package/plugins/dashboard-store/__tests__/getters.spec.ts +100 -0
  69. package/plugins/dashboard-store/__tests__/{mutations.spec.js → mutations.spec.ts} +2 -2
  70. package/plugins/dashboard-store/actions.js +1 -1
  71. package/plugins/dashboard-store/resource-class.js +4 -0
  72. package/plugins/steve/__tests__/getters.spec.ts +93 -0
  73. package/plugins/steve/getters.js +21 -1
  74. package/plugins/steve/subscribe.js +1 -3
  75. package/rancher-components/components/BadgeState/BadgeState.spec.ts +12 -0
  76. package/rancher-components/components/BadgeState/BadgeState.vue +111 -0
  77. package/rancher-components/components/BadgeState/index.ts +1 -0
  78. package/rancher-components/components/Banner/Banner.test.ts +63 -0
  79. package/rancher-components/components/Banner/Banner.vue +244 -0
  80. package/rancher-components/components/Banner/index.ts +1 -0
  81. package/rancher-components/components/Card/Card.test.ts +37 -0
  82. package/rancher-components/components/Card/Card.vue +167 -0
  83. package/rancher-components/components/Card/index.ts +1 -0
  84. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +68 -0
  85. package/rancher-components/components/Form/Checkbox/Checkbox.vue +420 -0
  86. package/rancher-components/components/Form/Checkbox/index.ts +1 -0
  87. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +23 -0
  88. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +355 -0
  89. package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
  90. package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
  91. package/rancher-components/components/Form/Radio/RadioButton.vue +287 -0
  92. package/rancher-components/components/Form/Radio/RadioGroup.vue +254 -0
  93. package/rancher-components/components/Form/Radio/index.ts +2 -0
  94. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +170 -0
  95. package/rancher-components/components/Form/TextArea/index.ts +1 -0
  96. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +94 -0
  97. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +149 -0
  98. package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
  99. package/rancher-components/components/Form/index.ts +5 -0
  100. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +151 -0
  101. package/rancher-components/components/LabeledTooltip/index.ts +1 -0
  102. package/rancher-components/components/StringList/StringList.test.ts +484 -0
  103. package/rancher-components/components/StringList/StringList.vue +611 -0
  104. package/rancher-components/components/StringList/index.ts +1 -0
  105. package/scripts/extension/publish +54 -14
  106. package/scripts/typegen.sh +10 -2
  107. package/store/index.js +1 -3
  108. package/store/store-types.js +2 -0
  109. package/types/api.d.ts +1 -0
  110. package/types/fleet.d.ts +1 -0
  111. package/types/shell/index.d.ts +696 -2
  112. package/types/userPreferences.d.ts +1 -1
  113. package/utils/__mocks__/socket.js +21 -0
  114. package/utils/grafana.js +23 -11
  115. package/utils/selector.js +2 -1
  116. package/utils/socket.js +1 -0
  117. package/utils/validators/formRules/index.ts +3 -3
  118. 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 Label
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 (Unsupported)
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 them, click the menu button at the top right of this page and select “Add Rancher Repositories”.
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 Extension sRepository
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
- resourceBanner: 启用时,删除 GitRepo 或 Bundle 后将保留资源,只会删除 Helm Release Secret。
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: 这将安装 Helm Chart 以启用扩展支持
4127
- airgap: Rancher Extensions 仓库提供了由 Rancher 发布的扩展。如果你的 Rancher 是离线的,请取消选中。
4128
- addRancherRepo: 添加 Rancher Extension 仓库
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
- title: 删除 Rancher Rancher Extensions 仓库
4135
- prompt: Rancher Extensions 仓库提供了由 Rancher 发布的扩展。
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();
@@ -3,12 +3,12 @@ export default {
3
3
  props: {
4
4
  initialSrc: {
5
5
  type: String,
6
- default: require('~shell/assets/images/generic-catalog.svg'),
6
+ default: require('@shell/assets/images/generic-catalog.svg'),
7
7
  },
8
8
 
9
9
  errorSrc: {
10
10
  type: String,
11
- default: require('~shell/assets/images/generic-catalog.svg'),
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
- this.toRestore[0]?.type.toLowerCase() === SNAPSHOT;
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.isRke2) {
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 allSnapshosts = await promise.then((snapshots) => {
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 = allSnapshosts;
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.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
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
- const inStore = this.storeOverride || store.getters['currentStore'](params.resource);
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 { NAME as EXPLORER } from '@shell/config/product/explorer';
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
- const clusters = this.value.targetClusters || [];
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
@@ -63,7 +63,8 @@ export default {
63
63
  accept: {
64
64
  type: String,
65
65
  default: '*'
66
- }
66
+ },
67
+
67
68
  },
68
69
 
69
70
  computed: {
@@ -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*/).filter((x) => !!x);
224
+ expression.values = val.split(/\s*,\s*/);
227
225
  }
228
226
 
229
227
  return expression;