@rancher/shell 0.3.17 → 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/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 +7 -5
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/ResourceDetail/index.vue +4 -2
- package/components/__tests__/PromptRestore.test.ts +72 -0
- package/components/auth/AzureWarning.vue +1 -1
- 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/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 -187
- 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/fleet.cattle.io.cluster.js +33 -4
- package/models/fleet.cattle.io.gitrepo.js +112 -38
- 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/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/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/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 +695 -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/validators/formRules/index.ts +3 -3
- package/plugins/steve/urloptions.js +0 -47
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { convert, matching, convertSelectorObj } from '@shell/utils/selector';
|
|
2
2
|
import jsyaml from 'js-yaml';
|
|
3
|
-
import { escapeHtml } from '@shell/utils/string';
|
|
3
|
+
import { escapeHtml, randomStr } from '@shell/utils/string';
|
|
4
4
|
import { FLEET } from '@shell/config/types';
|
|
5
5
|
import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
6
6
|
import { addObject, addObjects, findBy, insertAt } from '@shell/utils/array';
|
|
7
7
|
import { set } from '@shell/utils/object';
|
|
8
8
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
9
|
+
import { STATES_ENUM, colorForState, stateDisplay, stateSort } from '@shell/plugins/dashboard-store/resource-class';
|
|
10
|
+
import { NAME } from '@shell/config/product/explorer';
|
|
9
11
|
|
|
10
12
|
function quacksLikeAHash(str) {
|
|
11
|
-
if (
|
|
13
|
+
if (str.match(/^[a-f0-9]{40,}$/i)) {
|
|
12
14
|
return true;
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -24,7 +26,7 @@ export default class GitRepo extends SteveModel {
|
|
|
24
26
|
|
|
25
27
|
spec.repo = spec.repo || '';
|
|
26
28
|
|
|
27
|
-
if (
|
|
29
|
+
if (!spec.branch && !spec.revision) {
|
|
28
30
|
spec.branch = 'master';
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -86,7 +88,7 @@ export default class GitRepo extends SteveModel {
|
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
get state() {
|
|
89
|
-
if (
|
|
91
|
+
if (this.spec?.paused === true) {
|
|
90
92
|
return 'paused';
|
|
91
93
|
}
|
|
92
94
|
|
|
@@ -98,10 +100,10 @@ export default class GitRepo extends SteveModel {
|
|
|
98
100
|
const clusters = workspace?.clusters || [];
|
|
99
101
|
const groups = workspace?.clusterGroups || [];
|
|
100
102
|
|
|
101
|
-
if (
|
|
103
|
+
if (workspace?.id === 'fleet-local') {
|
|
102
104
|
const local = findBy(groups, 'id', 'fleet-local/default');
|
|
103
105
|
|
|
104
|
-
if (
|
|
106
|
+
if (local) {
|
|
105
107
|
return local.targetClusters;
|
|
106
108
|
}
|
|
107
109
|
|
|
@@ -114,30 +116,30 @@ export default class GitRepo extends SteveModel {
|
|
|
114
116
|
|
|
115
117
|
const out = [];
|
|
116
118
|
|
|
117
|
-
for (
|
|
118
|
-
if (
|
|
119
|
+
for (const tgt of this.spec.targets) {
|
|
120
|
+
if (tgt.clusterName) {
|
|
119
121
|
const cluster = findBy(clusters, 'metadata.name', tgt.clusterName);
|
|
120
122
|
|
|
121
|
-
if (
|
|
123
|
+
if (cluster) {
|
|
122
124
|
addObject(out, cluster);
|
|
123
125
|
}
|
|
124
|
-
} else if (
|
|
126
|
+
} else if (tgt.clusterGroup) {
|
|
125
127
|
const group = findBy(groups, {
|
|
126
128
|
'metadata.namespace': this.metadata.namespace,
|
|
127
129
|
'metadata.name': tgt.clusterGroup,
|
|
128
130
|
});
|
|
129
131
|
|
|
130
|
-
if (
|
|
132
|
+
if (group) {
|
|
131
133
|
addObjects(out, group.targetClusters);
|
|
132
134
|
}
|
|
133
|
-
} else if (
|
|
135
|
+
} else if (tgt.clusterGroupSelector) {
|
|
134
136
|
const expressions = convertSelectorObj(tgt.clusterGroupSelector);
|
|
135
137
|
const matchingGroups = matching(groups, expressions);
|
|
136
138
|
|
|
137
|
-
for (
|
|
139
|
+
for (const group of matchingGroups) {
|
|
138
140
|
addObjects(out, group.targetClusters);
|
|
139
141
|
}
|
|
140
|
-
} else if (
|
|
142
|
+
} else if (tgt.clusterSelector) {
|
|
141
143
|
const expressions = convertSelectorObj(tgt.clusterSelector);
|
|
142
144
|
const matchingClusters = matching(clusters, expressions);
|
|
143
145
|
|
|
@@ -151,7 +153,7 @@ export default class GitRepo extends SteveModel {
|
|
|
151
153
|
get github() {
|
|
152
154
|
const match = this.spec.repo.match(/^https?:\/\/github\.com\/(.*?)(\.git)?\/*$/);
|
|
153
155
|
|
|
154
|
-
if (
|
|
156
|
+
if (match) {
|
|
155
157
|
return match[1];
|
|
156
158
|
}
|
|
157
159
|
|
|
@@ -159,7 +161,7 @@ export default class GitRepo extends SteveModel {
|
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
get repoIcon() {
|
|
162
|
-
if (
|
|
164
|
+
if (this.github) {
|
|
163
165
|
return 'icon icon-github';
|
|
164
166
|
}
|
|
165
167
|
|
|
@@ -173,7 +175,7 @@ export default class GitRepo extends SteveModel {
|
|
|
173
175
|
repo = repo.replace(/^https:\/\//, '');
|
|
174
176
|
repo = repo.replace(/\/+$/, '');
|
|
175
177
|
|
|
176
|
-
if (
|
|
178
|
+
if (this.github) {
|
|
177
179
|
return this.github;
|
|
178
180
|
}
|
|
179
181
|
|
|
@@ -184,15 +186,15 @@ export default class GitRepo extends SteveModel {
|
|
|
184
186
|
const spec = this.spec;
|
|
185
187
|
const hash = this.status?.commit?.substr(0, 7);
|
|
186
188
|
|
|
187
|
-
if (
|
|
189
|
+
if (!spec || !spec.repo) {
|
|
188
190
|
return null;
|
|
189
191
|
}
|
|
190
192
|
|
|
191
|
-
if (
|
|
193
|
+
if (spec.revision && quacksLikeAHash(spec.revision)) {
|
|
192
194
|
return spec.revision.substr(0, 7);
|
|
193
|
-
} else if (
|
|
195
|
+
} else if (spec.revision) {
|
|
194
196
|
return spec.revision;
|
|
195
|
-
} else if (
|
|
197
|
+
} else if (spec.branch) {
|
|
196
198
|
return spec.branch + (hash ? ` @ ${ hash }` : '');
|
|
197
199
|
}
|
|
198
200
|
|
|
@@ -220,7 +222,7 @@ export default class GitRepo extends SteveModel {
|
|
|
220
222
|
|
|
221
223
|
advanced = jsyaml.dump(targets);
|
|
222
224
|
|
|
223
|
-
if (
|
|
225
|
+
if (advanced === '[]\n') {
|
|
224
226
|
advanced = `# - name:
|
|
225
227
|
# clusterSelector:
|
|
226
228
|
# matchLabels:
|
|
@@ -240,39 +242,39 @@ export default class GitRepo extends SteveModel {
|
|
|
240
242
|
`;
|
|
241
243
|
}
|
|
242
244
|
|
|
243
|
-
if (
|
|
245
|
+
if (this.metadata.namespace === 'fleet-local') {
|
|
244
246
|
mode = 'local';
|
|
245
|
-
} else if (
|
|
247
|
+
} else if (!targets.length) {
|
|
246
248
|
mode = 'none';
|
|
247
|
-
} else if (
|
|
249
|
+
} else if (targets.length === 1) {
|
|
248
250
|
const target = targets[0];
|
|
249
251
|
|
|
250
252
|
if (Object.keys(target).length > 1) {
|
|
251
253
|
// There are multiple properties in a single target, so use the 'advanced' mode
|
|
252
254
|
// (otherwise any existing content is nuked for what we provide)
|
|
253
255
|
mode = 'advanced';
|
|
254
|
-
} else if (
|
|
256
|
+
} else if (target.clusterGroup) {
|
|
255
257
|
clusterGroup = target.clusterGroup;
|
|
256
258
|
|
|
257
|
-
if (
|
|
259
|
+
if (!mode) {
|
|
258
260
|
mode = 'clusterGroup';
|
|
259
261
|
}
|
|
260
|
-
} else if (
|
|
262
|
+
} else if (target.clusterName) {
|
|
261
263
|
mode = 'cluster';
|
|
262
264
|
cluster = target.clusterName;
|
|
263
|
-
} else if (
|
|
264
|
-
if (
|
|
265
|
+
} else if (target.clusterSelector) {
|
|
266
|
+
if (Object.keys(target.clusterSelector).length === 0) {
|
|
265
267
|
mode = 'all';
|
|
266
268
|
} else {
|
|
267
269
|
const expressions = convert(target.clusterSelector.matchLabels, target.clusterSelector.matchExpressions);
|
|
268
270
|
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
271
|
+
if (expressions.length === 1 &&
|
|
272
|
+
expressions[0].key === FLEET_ANNOTATIONS.CLUSTER_NAME &&
|
|
273
|
+
expressions[0].operator === 'In' &&
|
|
274
|
+
expressions[0].values.length === 1
|
|
273
275
|
) {
|
|
274
276
|
cluster = expressions[0].values[0];
|
|
275
|
-
if (
|
|
277
|
+
if (!mode) {
|
|
276
278
|
mode = 'cluster';
|
|
277
279
|
}
|
|
278
280
|
}
|
|
@@ -280,7 +282,7 @@ export default class GitRepo extends SteveModel {
|
|
|
280
282
|
}
|
|
281
283
|
}
|
|
282
284
|
|
|
283
|
-
if (
|
|
285
|
+
if (!mode) {
|
|
284
286
|
mode = 'advanced';
|
|
285
287
|
}
|
|
286
288
|
|
|
@@ -296,7 +298,7 @@ export default class GitRepo extends SteveModel {
|
|
|
296
298
|
get groupByLabel() {
|
|
297
299
|
const name = this.metadata.namespace;
|
|
298
300
|
|
|
299
|
-
if (
|
|
301
|
+
if (name) {
|
|
300
302
|
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.workspace', { name: escapeHtml(name) });
|
|
301
303
|
} else {
|
|
302
304
|
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.notInAWorkspace');
|
|
@@ -306,7 +308,7 @@ export default class GitRepo extends SteveModel {
|
|
|
306
308
|
get bundles() {
|
|
307
309
|
const all = this.$getters['all'](FLEET.BUNDLE);
|
|
308
310
|
|
|
309
|
-
return all.filter((bundle) => bundle.
|
|
311
|
+
return all.filter((bundle) => bundle.repoName === this.name &&
|
|
310
312
|
bundle.namespace === this.namespace &&
|
|
311
313
|
bundle.namespacedName.startsWith(`${ this.namespace }:${ this.name }`));
|
|
312
314
|
}
|
|
@@ -325,6 +327,78 @@ export default class GitRepo extends SteveModel {
|
|
|
325
327
|
return bds.filter((bd) => bd.metadata?.labels?.['fleet.cattle.io/repo-name'] === this.name);
|
|
326
328
|
}
|
|
327
329
|
|
|
330
|
+
get resourcesStatuses() {
|
|
331
|
+
const clusters = this.targetClusters || [];
|
|
332
|
+
const resources = this.status?.resources || [];
|
|
333
|
+
const conditions = this.status?.conditions || [];
|
|
334
|
+
|
|
335
|
+
const out = [];
|
|
336
|
+
|
|
337
|
+
for (const c of clusters) {
|
|
338
|
+
const clusterBundleDeploymentResources = this.bundleDeployments
|
|
339
|
+
.find((bd) => bd.metadata?.labels?.[FLEET_ANNOTATIONS.CLUSTER] === c.metadata.name)
|
|
340
|
+
?.status?.resources || [];
|
|
341
|
+
|
|
342
|
+
resources.forEach((r, i) => {
|
|
343
|
+
let namespacedName = r.name;
|
|
344
|
+
|
|
345
|
+
if (r.namespace) {
|
|
346
|
+
namespacedName = `${ r.namespace }:${ r.name }`;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
let state = r.state;
|
|
350
|
+
const perEntry = r.perClusterState?.find((x) => x.clusterId === c.id);
|
|
351
|
+
const tooMany = r.perClusterState?.length >= 10 || false;
|
|
352
|
+
|
|
353
|
+
if (perEntry) {
|
|
354
|
+
state = perEntry.state;
|
|
355
|
+
} else if (tooMany) {
|
|
356
|
+
state = STATES_ENUM.UNKNOWN;
|
|
357
|
+
} else {
|
|
358
|
+
state = STATES_ENUM.READY;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const color = colorForState(state).replace('text-', 'bg-');
|
|
362
|
+
const display = stateDisplay(state);
|
|
363
|
+
|
|
364
|
+
const detailLocation = {
|
|
365
|
+
name: `c-cluster-product-resource${ r.namespace ? '-namespace' : '' }-id`,
|
|
366
|
+
params: {
|
|
367
|
+
product: NAME,
|
|
368
|
+
cluster: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME],
|
|
369
|
+
resource: r.type,
|
|
370
|
+
namespace: r.namespace,
|
|
371
|
+
id: r.name,
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
out.push({
|
|
376
|
+
key: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }`,
|
|
377
|
+
tableKey: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }-${ randomStr(8) }`,
|
|
378
|
+
kind: r.kind,
|
|
379
|
+
apiVersion: r.apiVersion,
|
|
380
|
+
type: r.type,
|
|
381
|
+
id: r.id,
|
|
382
|
+
namespace: r.namespace,
|
|
383
|
+
name: r.name,
|
|
384
|
+
clusterId: c.id,
|
|
385
|
+
clusterName: c.nameDisplay,
|
|
386
|
+
state,
|
|
387
|
+
stateBackground: color,
|
|
388
|
+
stateDisplay: display,
|
|
389
|
+
stateSort: stateSort(color, display),
|
|
390
|
+
namespacedName,
|
|
391
|
+
detailLocation,
|
|
392
|
+
conditions: conditions[i],
|
|
393
|
+
bundleDeploymentStatus: clusterBundleDeploymentResources?.[i],
|
|
394
|
+
creationTimestamp: clusterBundleDeploymentResources?.[i]?.createdAt
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return out;
|
|
400
|
+
}
|
|
401
|
+
|
|
328
402
|
get clustersList() {
|
|
329
403
|
return this.$getters['all'](FLEET.CLUSTER);
|
|
330
404
|
}
|
|
@@ -15,8 +15,10 @@ export const KONTAINER_TO_DRIVER = {
|
|
|
15
15
|
huaweicontainercloudengine: 'huaweicce', // Does this actually exist?
|
|
16
16
|
huaweiengine: 'huaweicce',
|
|
17
17
|
linodekubernetesengine: 'linodelke', // Does this actually exist?
|
|
18
|
+
lke: 'linodelke',
|
|
18
19
|
lkeengine: 'linodelke',
|
|
19
20
|
okeengine: 'oracleoke',
|
|
21
|
+
oke: 'oracleoke',
|
|
20
22
|
oraclecontainerengine: 'oracleoke', // Does this actually exist?
|
|
21
23
|
rke2: 'rke2',
|
|
22
24
|
tencentengine: 'tencenttke',
|
|
@@ -63,6 +65,18 @@ export default class KontainerDriver extends HybridModel {
|
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
get driverName() {
|
|
68
|
+
if (!this.spec.builtIn) {
|
|
69
|
+
// if the driver is not built in, there's a good change its a custom one
|
|
70
|
+
// custom drivers have a random id, so shouldn't be used as the type
|
|
71
|
+
// instead use the status.displayName. this will map to the name extracted from the binary
|
|
72
|
+
const driverName = this.status?.displayName?.toLowerCase();
|
|
73
|
+
|
|
74
|
+
if (driverName) {
|
|
75
|
+
// some drivers are built in but don't have the builtIn flag. ensure we pass these through K_TO_D
|
|
76
|
+
return KONTAINER_TO_DRIVER[driverName] || driverName;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
66
80
|
return KONTAINER_TO_DRIVER[this.id] || this.id;
|
|
67
81
|
}
|
|
68
82
|
}
|
|
@@ -1,116 +1,7 @@
|
|
|
1
|
-
import { PVC } from '@shell/config/types';
|
|
1
|
+
import { PVC, LONGHORN_DRIVER } from '@shell/config/types';
|
|
2
|
+
import { VOLUME_PLUGINS } from '@shell/config/persistentVolume';
|
|
2
3
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
3
4
|
|
|
4
|
-
export const VOLUME_PLUGINS = [
|
|
5
|
-
{
|
|
6
|
-
labelKey: 'persistentVolume.awsElasticBlockStore.label',
|
|
7
|
-
value: 'awsElasticBlockStore',
|
|
8
|
-
supported: true
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
labelKey: 'persistentVolume.azureDisk.label',
|
|
12
|
-
value: 'azureDisk',
|
|
13
|
-
supported: true
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
labelKey: 'persistentVolume.azureFile.label',
|
|
17
|
-
value: 'azureFile',
|
|
18
|
-
supported: true
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
labelKey: 'persistentVolume.cephfs.label',
|
|
22
|
-
value: 'cephfs',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
labelKey: 'persistentVolume.rbd.label',
|
|
26
|
-
value: 'rbd',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
labelKey: 'persistentVolume.csi.label',
|
|
30
|
-
value: 'csi',
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
labelKey: 'persistentVolume.fc.label',
|
|
34
|
-
value: 'fc',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
labelKey: 'persistentVolume.flexVolume.label',
|
|
38
|
-
value: 'flexVolume',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
labelKey: 'persistentVolume.flocker.label',
|
|
42
|
-
value: 'flocker',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
labelKey: 'persistentVolume.glusterfs.label',
|
|
46
|
-
value: 'glusterfs',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
labelKey: 'persistentVolume.gcePersistentDisk.label',
|
|
50
|
-
value: 'gcePersistentDisk',
|
|
51
|
-
supported: true
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
labelKey: 'persistentVolume.hostPath.label',
|
|
55
|
-
value: 'hostPath',
|
|
56
|
-
supported: true
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
labelKey: 'persistentVolume.iscsi.label',
|
|
60
|
-
value: 'iscsi',
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
labelKey: 'persistentVolume.local.label',
|
|
64
|
-
value: 'local',
|
|
65
|
-
supported: true
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
labelKey: 'persistentVolume.longhorn.label',
|
|
69
|
-
value: 'longhorn',
|
|
70
|
-
supported: true
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
labelKey: 'persistentVolume.nfs.label',
|
|
74
|
-
value: 'nfs',
|
|
75
|
-
supported: true
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
labelKey: 'persistentVolume.cinder.label',
|
|
79
|
-
value: 'cinder',
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
labelKey: 'persistentVolume.photonPersistentDisk.label',
|
|
83
|
-
value: 'photonPersistentDisk',
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
labelKey: 'persistentVolume.portworxVolume.label',
|
|
87
|
-
value: 'portworxVolume',
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
{
|
|
91
|
-
labelKey: 'persistentVolume.quobyte.label',
|
|
92
|
-
value: 'quobyte',
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
{
|
|
96
|
-
labelKey: 'persistentVolume.scaleIO.label',
|
|
97
|
-
value: 'scaleIO',
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
labelKey: 'persistentVolume.storageos.label',
|
|
101
|
-
value: 'storageos',
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
labelKey: 'persistentVolume.vsphereVolume.label',
|
|
105
|
-
value: 'vsphereVolume',
|
|
106
|
-
supported: true
|
|
107
|
-
},
|
|
108
|
-
];
|
|
109
|
-
|
|
110
|
-
export const LONGHORN_DRIVER = 'driver.longhorn.io';
|
|
111
|
-
|
|
112
|
-
export const LONGHORN_PLUGIN = VOLUME_PLUGINS.find((plugin) => plugin.value === 'longhorn');
|
|
113
|
-
|
|
114
5
|
export default class PV extends SteveModel {
|
|
115
6
|
// plugin display value table
|
|
116
7
|
get source() {
|
package/models/pod.js
CHANGED
|
@@ -15,6 +15,36 @@ export const WORKLOAD_PRIORITY = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export default class Pod extends WorkloadService {
|
|
18
|
+
_os = undefined;
|
|
19
|
+
|
|
20
|
+
get inStore() {
|
|
21
|
+
return this.$rootGetters['currentProduct'].inStore;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
set os(operatingSystem) {
|
|
25
|
+
this._os = operatingSystem;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get os() {
|
|
29
|
+
if (this._os) {
|
|
30
|
+
return this._os;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return this?.node?.status?.nodeInfo?.operatingSystem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get node() {
|
|
37
|
+
try {
|
|
38
|
+
const schema = this.$store.getters[`cluster/schemaFor`](NODE);
|
|
39
|
+
|
|
40
|
+
if (schema) {
|
|
41
|
+
this.$dispatch(`find`, { type: NODE, id: this.spec.nodeName });
|
|
42
|
+
}
|
|
43
|
+
} catch {}
|
|
44
|
+
|
|
45
|
+
return this.$getters['byId'](NODE, this.spec.nodeName);
|
|
46
|
+
}
|
|
47
|
+
|
|
18
48
|
get _availableActions() {
|
|
19
49
|
const out = super._availableActions;
|
|
20
50
|
|
|
@@ -5,17 +5,20 @@ import { findBy } from '@shell/utils/array';
|
|
|
5
5
|
import { get } from '@shell/utils/object';
|
|
6
6
|
import { base64Decode } from '@shell/utils/crypto';
|
|
7
7
|
import { ucFirst } from '@shell/utils/string';
|
|
8
|
+
import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
8
9
|
|
|
9
10
|
export default class EtcdBackup extends NormanModel {
|
|
10
11
|
/**
|
|
11
12
|
* Restrict actions for snapshots to restore only
|
|
12
13
|
*/
|
|
13
14
|
get _availableActions() {
|
|
15
|
+
const enabled = this.snapshotFile?.status === STATES_ENUM.SUCCESSFUL;
|
|
16
|
+
|
|
14
17
|
return [{
|
|
15
|
-
action:
|
|
16
|
-
enabled
|
|
17
|
-
icon:
|
|
18
|
-
label:
|
|
18
|
+
action: 'promptRestore',
|
|
19
|
+
enabled,
|
|
20
|
+
icon: 'icon icon-fw icon-backup-restore',
|
|
21
|
+
label: 'Restore'
|
|
19
22
|
}];
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -48,7 +51,7 @@ export default class EtcdBackup extends NormanModel {
|
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
get errorMessage() {
|
|
51
|
-
const inError = get(this, 'snapshotFile.status') ===
|
|
54
|
+
const inError = get(this, 'snapshotFile.status') === STATES_ENUM.FAILED;
|
|
52
55
|
|
|
53
56
|
if (inError) {
|
|
54
57
|
return base64Decode(this.snapshotFile?.message);
|
|
@@ -59,10 +62,10 @@ export default class EtcdBackup extends NormanModel {
|
|
|
59
62
|
|
|
60
63
|
get stateDescription() {
|
|
61
64
|
const trans = this.stateObj?.transitioning || false;
|
|
62
|
-
const error = this.stateObj?.error || this.snapshotFile?.status ===
|
|
65
|
+
const error = this.stateObj?.error || this.snapshotFile?.status === STATES_ENUM.FAILED || false;
|
|
63
66
|
const message = this.stateObj?.message;
|
|
64
67
|
|
|
65
|
-
const fileMessage = this.snapshotFile?.status ===
|
|
68
|
+
const fileMessage = this.snapshotFile?.status === STATES_ENUM.FAILED ? base64Decode(this.snapshotFile?.message) : null;
|
|
66
69
|
|
|
67
70
|
return trans || error ? fileMessage || ucFirst(message) : '';
|
|
68
71
|
}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ import { NORMAN } from '@shell/config/types';
|
|
|
6
6
|
import { _VIEW, _EDIT } from '@shell/config/query-params';
|
|
7
7
|
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
8
8
|
import { NAME } from '@shell/config/product/auth';
|
|
9
|
-
import { BLANK_CLUSTER } from '@shell/store';
|
|
9
|
+
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
10
10
|
|
|
11
11
|
export default {
|
|
12
12
|
components: {
|
|
@@ -6,7 +6,7 @@ import ResourceTable from '@shell/components/ResourceTable';
|
|
|
6
6
|
import Loading from '@shell/components/Loading';
|
|
7
7
|
import { SUBTYPE_MAPPING, CREATE_VERBS } from '@shell/models/management.cattle.io.roletemplate';
|
|
8
8
|
import { NAME } from '@shell/config/product/auth';
|
|
9
|
-
import { BLANK_CLUSTER } from '@shell/store';
|
|
9
|
+
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
10
10
|
|
|
11
11
|
const GLOBAL = SUBTYPE_MAPPING.GLOBAL.key;
|
|
12
12
|
const CLUSTER = SUBTYPE_MAPPING.CLUSTER.key;
|
|
@@ -103,7 +103,7 @@ export default {
|
|
|
103
103
|
`Determine etcd metrics`
|
|
104
104
|
);
|
|
105
105
|
|
|
106
|
-
if (this.currentCluster.isLocal) {
|
|
106
|
+
if (this.currentCluster.isLocal && this.$store.getters['management/schemaFor'](MANAGEMENT.NODE)) {
|
|
107
107
|
this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE });
|
|
108
108
|
}
|
|
109
109
|
}
|
|
@@ -4,7 +4,7 @@ import ColorInput from '@shell/components/form/ColorInput';
|
|
|
4
4
|
import TypeDescription from '@shell/components/TypeDescription';
|
|
5
5
|
|
|
6
6
|
import { Checkbox } from '@components/Form/Checkbox';
|
|
7
|
-
import
|
|
7
|
+
import FileImageSelector from '@shell/components/form/FileImageSelector';
|
|
8
8
|
import SimpleBox from '@shell/components/SimpleBox';
|
|
9
9
|
import Loading from '@shell/components/Loading';
|
|
10
10
|
import AsyncButton from '@shell/components/AsyncButton';
|
|
@@ -23,7 +23,7 @@ export default {
|
|
|
23
23
|
layout: 'authenticated',
|
|
24
24
|
|
|
25
25
|
components: {
|
|
26
|
-
LabeledInput, Checkbox,
|
|
26
|
+
LabeledInput, Checkbox, FileImageSelector, Loading, SimpleBox, AsyncButton, Banner, ColorInput, TypeDescription
|
|
27
27
|
},
|
|
28
28
|
|
|
29
29
|
async fetch() {
|
|
@@ -222,14 +222,15 @@ export default {
|
|
|
222
222
|
>
|
|
223
223
|
<div class="col logo-container span-6">
|
|
224
224
|
<div class="mb-10">
|
|
225
|
-
<
|
|
225
|
+
<FileImageSelector
|
|
226
226
|
:byte-limit="20000"
|
|
227
227
|
:read-as-data-url="true"
|
|
228
228
|
class="role-secondary"
|
|
229
229
|
:label="t('branding.logos.uploadLight')"
|
|
230
230
|
:mode="mode"
|
|
231
|
+
accept="image/jpeg,image/png,image/svg+xml"
|
|
231
232
|
@error="setError"
|
|
232
|
-
@
|
|
233
|
+
@input="updateLogo($event, 'uiLogoLight')"
|
|
233
234
|
/>
|
|
234
235
|
</div>
|
|
235
236
|
<SimpleBox
|
|
@@ -245,14 +246,15 @@ export default {
|
|
|
245
246
|
</div>
|
|
246
247
|
<div class="col logo-container span-6">
|
|
247
248
|
<div class="mb-10">
|
|
248
|
-
<
|
|
249
|
+
<FileImageSelector
|
|
249
250
|
:byte-limit="20000"
|
|
250
251
|
:read-as-data-url="true"
|
|
251
252
|
class="role-secondary"
|
|
252
253
|
:label="t('branding.logos.uploadDark')"
|
|
253
254
|
:mode="mode"
|
|
255
|
+
accept="image/jpeg,image/png,image/svg+xml"
|
|
254
256
|
@error="setError"
|
|
255
|
-
@
|
|
257
|
+
@input="updateLogo($event, 'uiLogoDark')"
|
|
256
258
|
/>
|
|
257
259
|
</div>
|
|
258
260
|
<SimpleBox
|
|
@@ -289,14 +291,15 @@ export default {
|
|
|
289
291
|
>
|
|
290
292
|
<div class="col logo-container span-12">
|
|
291
293
|
<div class="mb-10">
|
|
292
|
-
<
|
|
294
|
+
<FileImageSelector
|
|
293
295
|
:byte-limit="20000"
|
|
294
296
|
:read-as-data-url="true"
|
|
295
297
|
class="role-secondary"
|
|
296
298
|
:label="t('branding.favicon.upload')"
|
|
297
299
|
:mode="mode"
|
|
300
|
+
accept="image/jpeg,image/png,image/svg+xml"
|
|
298
301
|
@error="setError"
|
|
299
|
-
@
|
|
302
|
+
@input="updateLogo($event, 'uiFavicon')"
|
|
300
303
|
/>
|
|
301
304
|
</div>
|
|
302
305
|
<SimpleBox v-if="uiFavicon">
|