@rancher/shell 0.5.2 → 0.5.3
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/components/ClusterIconMenu.vue +24 -9
- package/components/CodeMirror.vue +79 -18
- package/components/FixedBanner.vue +1 -0
- package/components/ResourceDetail/index.vue +1 -4
- package/components/ResourceYaml.vue +29 -5
- package/components/SideNav.vue +42 -64
- package/components/SortableTable/index.vue +1 -1
- package/components/YamlEditor.vue +1 -0
- package/components/__tests__/CodeMirror.spec.ts +99 -0
- package/components/form/BannerSettings.vue +3 -0
- package/components/form/FileSelector.vue +1 -0
- package/components/form/KeyValue.vue +1 -0
- package/components/formatter/WorkloadDetailEndpoints.vue +12 -22
- package/components/formatter/__tests__/WorkloadDetailEndpoints.test.ts +81 -0
- package/components/nav/Header.vue +1 -0
- package/components/nav/Jump.vue +19 -9
- package/components/nav/TopLevelMenu.vue +37 -15
- package/components/nav/Type.vue +15 -4
- package/components/nav/__tests__/TopLevelMenu.test.ts +1 -1
- package/components/nav/__tests__/Type.test.ts +30 -0
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +77 -0
- package/detail/fleet.cattle.io.bundle.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +19 -4
- package/edit/management.cattle.io.setting.vue +1 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue +1 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +1 -2
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/slack.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +14 -7
- package/edit/provisioning.cattle.io.cluster/rke2.vue +22 -50
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +9 -11
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +3 -1
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +3 -0
- package/edit/token.vue +1 -0
- package/list/catalog.cattle.io.app.vue +1 -0
- package/list/management.cattle.io.setting.vue +1 -0
- package/machine-config/amazonec2.vue +1 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +151 -0
- package/models/__tests__/secret.test.ts +37 -0
- package/models/__tests__/storage.k8s.io.storageclass.test.ts +22 -0
- package/models/provisioning.cattle.io.cluster.js +36 -1
- package/models/secret.js +9 -0
- package/models/storage.k8s.io.storageclass.js +1 -1
- package/package.json +1 -1
- package/pages/c/_cluster/settings/DefaultLinksEditor.vue +1 -0
- package/pages/c/_cluster/settings/brand.vue +3 -0
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +4 -4
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +5 -2
- package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +96 -0
- package/pages/c/_cluster/uiplugins/__tests__/SetupUIPlugins.test.ts +128 -0
- package/plugins/dashboard-store/__tests__/actions.test.ts +196 -111
- package/plugins/dashboard-store/actions.js +4 -6
- package/plugins/dashboard-store/getters.js +60 -2
- package/plugins/dashboard-store/resource-class.js +6 -2
- package/plugins/steve/__tests__/getters.spec.ts +10 -0
- package/plugins/steve/__tests__/resource-utils.test.ts +159 -0
- package/plugins/steve/actions.js +3 -37
- package/plugins/steve/getters.js +6 -0
- package/plugins/steve/resource-utils.ts +38 -0
- package/store/__tests__/type-map.test.ts +1122 -0
- package/store/index.js +3 -2
- package/store/type-map.js +145 -75
- package/types/shell/index.d.ts +2 -0
- package/utils/__tests__/create-yaml.test.ts +10 -0
- package/utils/create-yaml.js +5 -1
- package/utils/object.js +10 -0
|
@@ -7,6 +7,7 @@ import { classify } from '@shell/plugins/dashboard-store/classify';
|
|
|
7
7
|
import { normalizeType } from './normalize';
|
|
8
8
|
import garbageCollect from '@shell/utils/gc/gc';
|
|
9
9
|
import { addSchemaIndexFields } from '@shell/plugins/steve/schema.utils';
|
|
10
|
+
import { addParam } from '@shell/utils/url';
|
|
10
11
|
|
|
11
12
|
export const _ALL = 'all';
|
|
12
13
|
export const _MERGE = 'merge';
|
|
@@ -208,12 +209,12 @@ export default {
|
|
|
208
209
|
|
|
209
210
|
const pageFetchOpts = {
|
|
210
211
|
...opt,
|
|
211
|
-
url:
|
|
212
|
+
url: addParam(opt.url, 'limit', `${ opt.incremental }`),
|
|
212
213
|
};
|
|
213
214
|
|
|
214
215
|
// this is where we "hijack" the limit for the dispatch('request') some lines below
|
|
215
216
|
// and therefore have 2 initial requests in parallel
|
|
216
|
-
opt.url =
|
|
217
|
+
opt.url = addParam(opt.url, 'limit', '100');
|
|
217
218
|
skipHaveAll = true;
|
|
218
219
|
|
|
219
220
|
// since we are forcing a request, clear the haveAll
|
|
@@ -368,10 +369,7 @@ export default {
|
|
|
368
369
|
const typeOptions = rootGetters['type-map/optionsFor'](type);
|
|
369
370
|
|
|
370
371
|
opt = opt || {};
|
|
371
|
-
|
|
372
|
-
opt.filter = opt.filter || {};
|
|
373
|
-
opt.filter['labelSelector'] = selector;
|
|
374
|
-
|
|
372
|
+
opt.labelSelector = selector;
|
|
375
373
|
opt.url = getters.urlFor(type, null, opt);
|
|
376
374
|
opt.depaginate = typeOptions?.depaginate;
|
|
377
375
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { SCHEMA } from '@shell/config/types';
|
|
2
|
+
import { SCHEMA, COUNT } from '@shell/config/types';
|
|
3
3
|
|
|
4
4
|
import { matches } from '@shell/utils/selector';
|
|
5
5
|
import { typeMunge, typeRef, SIMPLE_TYPES } from '@shell/utils/create-yaml';
|
|
@@ -45,6 +45,29 @@ export const urlFor = (state, getters) => (type, id, opt) => {
|
|
|
45
45
|
return url;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Find the number of resources given
|
|
50
|
+
* - if the type is namespaced
|
|
51
|
+
* - if there are any counts per namespace
|
|
52
|
+
* - if there are no namespaces
|
|
53
|
+
* - if there is no total count
|
|
54
|
+
*/
|
|
55
|
+
function matchingCounts(typeObj, namespaces) {
|
|
56
|
+
// That was easy
|
|
57
|
+
if ( !typeObj.namespaced || !typeObj.byNamespace || namespaces === null || typeObj.count === null) {
|
|
58
|
+
return typeObj.count;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let out = 0;
|
|
62
|
+
|
|
63
|
+
// Otherwise start with 0 and count up
|
|
64
|
+
for ( const namespace of namespaces ) {
|
|
65
|
+
out += typeObj.byNamespace[namespace]?.count || 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
|
|
48
71
|
export default {
|
|
49
72
|
|
|
50
73
|
all: (state, getters, rootState) => (type) => {
|
|
@@ -345,5 +368,40 @@ export default {
|
|
|
345
368
|
|
|
346
369
|
gcIgnoreTypes: () => {
|
|
347
370
|
return {};
|
|
348
|
-
}
|
|
371
|
+
},
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* For the given type, and it's settings, find the number of resources associated with it
|
|
375
|
+
*
|
|
376
|
+
* This takes into account if the type is namespaced.
|
|
377
|
+
*
|
|
378
|
+
* @param typeObj see inners for properties. must have at least `name` (resource type)
|
|
379
|
+
*
|
|
380
|
+
*/
|
|
381
|
+
count: (state, getters, rootState, rootGetters) => (typeObj) => {
|
|
382
|
+
let _typeObj = typeObj;
|
|
383
|
+
const { name: type, count } = _typeObj;
|
|
384
|
+
|
|
385
|
+
if (!type) {
|
|
386
|
+
throw new Error(`Resource type required to calc count: ${ JSON.stringify(typeObj) }`);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (!count) {
|
|
390
|
+
const schema = getters.schemaFor(type);
|
|
391
|
+
const counts = getters.all(COUNT)?.[0]?.counts || {};
|
|
392
|
+
const count = counts[type];
|
|
393
|
+
|
|
394
|
+
_typeObj = {
|
|
395
|
+
count: count ? count.summary.count || 0 : null,
|
|
396
|
+
byNamespace: count ? count.namespaces : {},
|
|
397
|
+
revision: count ? count.revision : null,
|
|
398
|
+
namespaced: schema?.attributes?.namespaced
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const namespaces = Object.keys(rootGetters.activeNamespaceCache || {});
|
|
403
|
+
|
|
404
|
+
return matchingCounts(_typeObj, namespaces.length ? namespaces : null);
|
|
405
|
+
},
|
|
406
|
+
|
|
349
407
|
};
|
|
@@ -1381,7 +1381,7 @@ export default class Resource {
|
|
|
1381
1381
|
|
|
1382
1382
|
async download() {
|
|
1383
1383
|
const value = await this.followLink('view', { headers: { accept: 'application/yaml' } });
|
|
1384
|
-
const data = await this
|
|
1384
|
+
const data = await this.cleanForDownload(value.data);
|
|
1385
1385
|
|
|
1386
1386
|
downloadFile(`${ this.nameDisplay }.yaml`, data, 'application/yaml');
|
|
1387
1387
|
}
|
|
@@ -1404,7 +1404,7 @@ export default class Resource {
|
|
|
1404
1404
|
await eachLimit(items, 10, (item, idx) => {
|
|
1405
1405
|
return item.followLink('view', { headers: { accept: 'application/yaml' } } ).then(async(data) => {
|
|
1406
1406
|
const yaml = data.data || data;
|
|
1407
|
-
const cleanedYaml = await this
|
|
1407
|
+
const cleanedYaml = await this.cleanForDownload(yaml);
|
|
1408
1408
|
|
|
1409
1409
|
files[`resources/${ names[idx] }`] = cleanedYaml;
|
|
1410
1410
|
});
|
|
@@ -1481,6 +1481,10 @@ export default class Resource {
|
|
|
1481
1481
|
this.$dispatch(`cleanForDiff`, this.toJSON());
|
|
1482
1482
|
}
|
|
1483
1483
|
|
|
1484
|
+
async cleanForDownload(yaml) {
|
|
1485
|
+
return this.$dispatch(`cleanForDownload`, yaml);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1484
1488
|
yamlForSave(yaml) {
|
|
1485
1489
|
try {
|
|
1486
1490
|
const obj = jsyaml.load(yaml);
|
|
@@ -37,6 +37,7 @@ describe('steve: getters', () => {
|
|
|
37
37
|
expect(urlForGetter('typeFoo', undefined, { namespaced: ['nsBar', 'nsBaz'] })).toBe('protocol/urlFoo');
|
|
38
38
|
});
|
|
39
39
|
});
|
|
40
|
+
|
|
40
41
|
describe('steve > getters > urlOptions', () => {
|
|
41
42
|
// we're not testing function output based off of state or getter inputs here since they are dependencies
|
|
42
43
|
const state = { config: { baseUrl: 'protocol' } };
|
|
@@ -71,12 +72,21 @@ describe('steve: getters', () => {
|
|
|
71
72
|
it('returns a string with a single filter statement applied and formatted for steve if a single filter statement is applied and the url starts with "/v1"', () => {
|
|
72
73
|
expect(urlOptionsGetter('/v1/foo', { filter: { bar: 'baz' } })).toBe('/v1/foo?filter=bar=baz&exclude=metadata.managedFields');
|
|
73
74
|
});
|
|
75
|
+
it('returns a string with a single filter statement applied and formatted for steve if a single filter statement is applied and the url starts with "/k8s/clusters/c-m-n4x45x4b/v1/"', () => {
|
|
76
|
+
expect(urlOptionsGetter('/k8s/clusters/c-m-n4x45x4b/v1/foo', { filter: { bar: 'baz' } })).toBe('/k8s/clusters/c-m-n4x45x4b/v1/foo?filter=bar=baz&exclude=metadata.managedFields');
|
|
77
|
+
});
|
|
74
78
|
it('returns a string with a multiple filter statements applied if a single filter statement is applied', () => {
|
|
75
79
|
expect(urlOptionsGetter('foo', { filter: { bar: 'baz', far: 'faz' } })).toBe('foo?bar=baz&far=faz');
|
|
76
80
|
});
|
|
77
81
|
it('returns a string with a multiple filter statements applied and formatted for steve if a single filter statement is applied and the url starts with "/v1"', () => {
|
|
78
82
|
expect(urlOptionsGetter('/v1/foo', { filter: { bar: 'baz', far: 'faz' } })).toBe('/v1/foo?filter=bar=baz&far=faz&exclude=metadata.managedFields');
|
|
79
83
|
});
|
|
84
|
+
it('returns a string with a labelSelector and formatted for steve if the url starts with "/v1"', () => {
|
|
85
|
+
expect(urlOptionsGetter('/v1/foo', { labelSelector: 'a=b' })).toBe('/v1/foo?labelSelector=a=b&exclude=metadata.managedFields');
|
|
86
|
+
});
|
|
87
|
+
it('returns a string with a labelSelector and filter, and formatted for steve if the url starts with "/v1"', () => {
|
|
88
|
+
expect(urlOptionsGetter('/v1/foo', { labelSelector: 'a=b', filter: { bar: 'baz', far: 'faz' } })).toBe('/v1/foo?labelSelector=a=b&filter=bar=baz&far=faz&exclude=metadata.managedFields');
|
|
89
|
+
});
|
|
80
90
|
it('returns a string with an exclude statement for "bar" and "metadata.managedFields" if excludeFields is a single element array with the string "bar" and the url starts with "/v1/"', () => {
|
|
81
91
|
expect(urlOptionsGetter('/v1/foo', { excludeFields: ['bar'] })).toBe('/v1/foo?exclude=bar&exclude=metadata.managedFields');
|
|
82
92
|
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { steveCleanForDownload } from '@shell/plugins/steve/resource-utils';
|
|
2
|
+
|
|
3
|
+
describe('steve: ressource-utils', () => {
|
|
4
|
+
it('should do nothing if the yaml is not passed', () => {
|
|
5
|
+
const r = steveCleanForDownload();
|
|
6
|
+
|
|
7
|
+
expect(r).toBeUndefined();
|
|
8
|
+
});
|
|
9
|
+
it('should remove all default rootKeys', () => {
|
|
10
|
+
const expectedYamlStr = `apiVersion: v1
|
|
11
|
+
kind: ConfigMap
|
|
12
|
+
metadata:
|
|
13
|
+
name: my-configmap
|
|
14
|
+
`;
|
|
15
|
+
const yamlStr = `
|
|
16
|
+
id: test_id
|
|
17
|
+
links:
|
|
18
|
+
view: https://example.com2
|
|
19
|
+
type: test_type
|
|
20
|
+
actions:
|
|
21
|
+
remove: https://example.com
|
|
22
|
+
${ expectedYamlStr }
|
|
23
|
+
`;
|
|
24
|
+
const cleanedYamlStr = steveCleanForDownload(yamlStr);
|
|
25
|
+
|
|
26
|
+
expect(cleanedYamlStr).toBe(expectedYamlStr);
|
|
27
|
+
});
|
|
28
|
+
it('should remove all the specified root keys', () => {
|
|
29
|
+
const part = `apiVersion: v1
|
|
30
|
+
kind: Secret
|
|
31
|
+
metadata:
|
|
32
|
+
name: my-secret`;
|
|
33
|
+
|
|
34
|
+
const rootKeyToYamlStringMap = {
|
|
35
|
+
id: 'id: test_id',
|
|
36
|
+
links: `links:
|
|
37
|
+
view: https://example.com`,
|
|
38
|
+
actions: `actions:
|
|
39
|
+
remove: https://example.com`,
|
|
40
|
+
type: 'type: Opaque'
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const entries = Object.entries(rootKeyToYamlStringMap);
|
|
44
|
+
const yamlStr = `${ part }
|
|
45
|
+
${ entries.map(([_, str]) => str).join('\n') }`;
|
|
46
|
+
|
|
47
|
+
entries.forEach(([key, str]) => {
|
|
48
|
+
const expectedYamlStr = `${ part }
|
|
49
|
+
${ entries.filter(([k]) => k !== key).map(([_, str]) => str).join('\n') }\n`;
|
|
50
|
+
const cleanedYamlStr = steveCleanForDownload(yamlStr, { rootKeys: [key] });
|
|
51
|
+
|
|
52
|
+
expect(cleanedYamlStr).toBe(expectedYamlStr);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
it('should remove all default metadata keys', () => {
|
|
56
|
+
const expectedYamlStr = `apiVersion: v1
|
|
57
|
+
kind: ConfigMap
|
|
58
|
+
metadata:
|
|
59
|
+
name: my-configmap
|
|
60
|
+
`;
|
|
61
|
+
const yamlStr = `apiVersion: v1
|
|
62
|
+
kind: ConfigMap
|
|
63
|
+
metadata:
|
|
64
|
+
name: my-configmap
|
|
65
|
+
fields:
|
|
66
|
+
- kube-root-ca.crt
|
|
67
|
+
- 1
|
|
68
|
+
- 7d23h
|
|
69
|
+
relationships:
|
|
70
|
+
- rel: 'owner'
|
|
71
|
+
state: 'active'
|
|
72
|
+
`;
|
|
73
|
+
const cleanedYamlStr = steveCleanForDownload(yamlStr);
|
|
74
|
+
|
|
75
|
+
expect(cleanedYamlStr).toBe(expectedYamlStr);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should remove all the specified metadata keys', () => {
|
|
79
|
+
const part = `apiVersion: v1
|
|
80
|
+
kind: ConfigMap
|
|
81
|
+
metadata:
|
|
82
|
+
name: my-configmap`;
|
|
83
|
+
|
|
84
|
+
const metadataKeyToYamlStringMap = {
|
|
85
|
+
fields:
|
|
86
|
+
` fields:
|
|
87
|
+
- kube-root-ca.crt
|
|
88
|
+
- 1
|
|
89
|
+
- 7d23h`,
|
|
90
|
+
relationships:
|
|
91
|
+
` relationships:
|
|
92
|
+
- rel: owner`,
|
|
93
|
+
state: ` state: active`
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const entries = Object.entries(metadataKeyToYamlStringMap);
|
|
97
|
+
const yamlStr = `${ part }
|
|
98
|
+
${ entries.map(([_, str]) => str).join('\n') }`;
|
|
99
|
+
|
|
100
|
+
entries.forEach(([key, str]) => {
|
|
101
|
+
const expectedYamlStr = `${ part }
|
|
102
|
+
${ entries.filter(([k]) => k !== key).map(([_, str]) => str).join('\n') }\n`;
|
|
103
|
+
const cleanedYamlStr = steveCleanForDownload(yamlStr, { metadataKeys: [key] });
|
|
104
|
+
|
|
105
|
+
expect(cleanedYamlStr).toBe(expectedYamlStr);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
it('should remove all defalut condition keys', () => {
|
|
109
|
+
const expectedYamlStr = `apiVersion: v1
|
|
110
|
+
kind: ConfigMap
|
|
111
|
+
metadata:
|
|
112
|
+
name: my-configmap
|
|
113
|
+
status:
|
|
114
|
+
conditions:
|
|
115
|
+
- {}
|
|
116
|
+
- {}
|
|
117
|
+
- message: message
|
|
118
|
+
`;
|
|
119
|
+
const yamlStr = `apiVersion: v1
|
|
120
|
+
kind: ConfigMap
|
|
121
|
+
metadata:
|
|
122
|
+
name: my-configmap
|
|
123
|
+
status:
|
|
124
|
+
conditions:
|
|
125
|
+
- error: 'error'
|
|
126
|
+
- transitioning: false
|
|
127
|
+
- message: message
|
|
128
|
+
`;
|
|
129
|
+
const cleanedYamlStr = steveCleanForDownload(yamlStr);
|
|
130
|
+
|
|
131
|
+
expect(cleanedYamlStr).toBe(expectedYamlStr);
|
|
132
|
+
});
|
|
133
|
+
it('should remove all the specified condition keys', () => {
|
|
134
|
+
const part = `apiVersion: v1
|
|
135
|
+
kind: ConfigMap
|
|
136
|
+
metadata:
|
|
137
|
+
name: my-configmap
|
|
138
|
+
status:
|
|
139
|
+
conditions:
|
|
140
|
+
- message: message`;
|
|
141
|
+
|
|
142
|
+
const conditionKeyToYamlStringMap = {
|
|
143
|
+
error: ' - error: error',
|
|
144
|
+
transitioning: ' - transitioning: false'
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const entries = Object.entries(conditionKeyToYamlStringMap);
|
|
148
|
+
const yamlStr = `${ part }
|
|
149
|
+
${ entries.map(([_, str]) => str).join('\n') }`;
|
|
150
|
+
|
|
151
|
+
entries.forEach(([key, str]) => {
|
|
152
|
+
const expectedYamlStr = `${ part }
|
|
153
|
+
${ entries.map(([k, str]) => k === key ? ' - {}' : str).join('\n') }\n`;
|
|
154
|
+
const cleanedYamlStr = steveCleanForDownload(yamlStr, { conditionKeys: [key] });
|
|
155
|
+
|
|
156
|
+
expect(cleanedYamlStr).toBe(expectedYamlStr);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
package/plugins/steve/actions.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import https from 'https';
|
|
2
2
|
import { addParam, parse as parseUrl, stringify as unParseUrl } from '@shell/utils/url';
|
|
3
3
|
import { handleSpoofedRequest, loadSchemas } from '@shell/plugins/dashboard-store/actions';
|
|
4
|
-
import { set } from '@shell/utils/object';
|
|
4
|
+
import { dropKeys, set } from '@shell/utils/object';
|
|
5
5
|
import { deferred } from '@shell/utils/promise';
|
|
6
6
|
import { streamJson, streamingSupported } from '@shell/utils/stream';
|
|
7
7
|
import isObject from 'lodash/isObject';
|
|
8
8
|
import { classify } from '@shell/plugins/dashboard-store/classify';
|
|
9
9
|
import { NAMESPACE } from '@shell/config/types';
|
|
10
|
-
import jsyaml from 'js-yaml';
|
|
11
10
|
import { handleKubeApiHeaderWarnings } from '@shell/plugins/steve/header-warnings';
|
|
11
|
+
import { steveCleanForDownload } from '@shell/plugins/steve/resource-utils';
|
|
12
12
|
|
|
13
13
|
export default {
|
|
14
14
|
|
|
@@ -330,31 +330,7 @@ export default {
|
|
|
330
330
|
|
|
331
331
|
// remove fields added by steve before showing/downloading yamls
|
|
332
332
|
cleanForDownload(ctx, yaml) {
|
|
333
|
-
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
const rootKeys = [
|
|
337
|
-
'id',
|
|
338
|
-
'links',
|
|
339
|
-
'type',
|
|
340
|
-
'actions'
|
|
341
|
-
];
|
|
342
|
-
const metadataKeys = [
|
|
343
|
-
'fields',
|
|
344
|
-
'relationships',
|
|
345
|
-
'state',
|
|
346
|
-
];
|
|
347
|
-
const conditionKeys = [
|
|
348
|
-
'error',
|
|
349
|
-
'transitioning',
|
|
350
|
-
];
|
|
351
|
-
const obj = jsyaml.load(yaml);
|
|
352
|
-
|
|
353
|
-
dropKeys(obj, rootKeys);
|
|
354
|
-
dropKeys(obj?.metadata, metadataKeys);
|
|
355
|
-
(obj?.status?.conditions || []).forEach((condition) => dropKeys(condition, conditionKeys));
|
|
356
|
-
|
|
357
|
-
return jsyaml.dump(obj);
|
|
333
|
+
return steveCleanForDownload(yaml);
|
|
358
334
|
}
|
|
359
335
|
};
|
|
360
336
|
|
|
@@ -398,16 +374,6 @@ function dropUnderscores(obj) {
|
|
|
398
374
|
}
|
|
399
375
|
}
|
|
400
376
|
|
|
401
|
-
function dropKeys(obj, keys) {
|
|
402
|
-
if ( !obj ) {
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
for ( const k of keys ) {
|
|
407
|
-
delete obj[k];
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
377
|
function dropCattleKeys(obj) {
|
|
412
378
|
if ( !obj ) {
|
|
413
379
|
return;
|
package/plugins/steve/getters.js
CHANGED
|
@@ -33,6 +33,12 @@ export default {
|
|
|
33
33
|
const parsedUrl = parse(url);
|
|
34
34
|
const isSteve = steveRegEx.test(parsedUrl.path);
|
|
35
35
|
|
|
36
|
+
// labelSelector
|
|
37
|
+
if ( opt.labelSelector ) {
|
|
38
|
+
url += `${ url.includes('?') ? '&' : '?' }labelSelector=${ opt.labelSelector }`;
|
|
39
|
+
}
|
|
40
|
+
// End: labelSelector
|
|
41
|
+
|
|
36
42
|
// Filter
|
|
37
43
|
if ( opt.filter ) {
|
|
38
44
|
url += `${ (url.includes('?') ? '&' : '?') }`;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { dropKeys } from '@shell/utils/object';
|
|
2
|
+
import jsyaml from 'js-yaml';
|
|
3
|
+
|
|
4
|
+
export function steveCleanForDownload(yaml: string, keys?: {
|
|
5
|
+
rootKeys?: string[],
|
|
6
|
+
metadataKeys?: string[],
|
|
7
|
+
conditionKeys?: string[]
|
|
8
|
+
}): string | undefined {
|
|
9
|
+
if (!yaml) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
rootKeys = [
|
|
15
|
+
'id',
|
|
16
|
+
'links',
|
|
17
|
+
'type',
|
|
18
|
+
'actions'
|
|
19
|
+
],
|
|
20
|
+
metadataKeys = [
|
|
21
|
+
'fields',
|
|
22
|
+
'relationships',
|
|
23
|
+
'state',
|
|
24
|
+
],
|
|
25
|
+
conditionKeys = [
|
|
26
|
+
'error',
|
|
27
|
+
'transitioning',
|
|
28
|
+
]
|
|
29
|
+
} = keys || {};
|
|
30
|
+
|
|
31
|
+
const obj: any = jsyaml.load(yaml);
|
|
32
|
+
|
|
33
|
+
dropKeys(obj, rootKeys);
|
|
34
|
+
dropKeys(obj?.metadata, metadataKeys);
|
|
35
|
+
(obj?.status?.conditions || []).forEach((condition: any) => dropKeys(condition, conditionKeys));
|
|
36
|
+
|
|
37
|
+
return jsyaml.dump(obj);
|
|
38
|
+
}
|