@rancher/shell 0.5.1 → 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/core/types-provisioning.ts +7 -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 +23 -10
- 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/management.cattle.io.kontainerdriver.js +2 -1
- 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/scripts/extension/parse-tag-name +3 -3
- package/store/__tests__/type-map.test.ts +1122 -0
- package/store/index.js +3 -2
- package/store/plugins.js +7 -6
- 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
package/store/index.js
CHANGED
|
@@ -604,7 +604,7 @@ export const mutations = {
|
|
|
604
604
|
state.isRancherInHarvester = neu;
|
|
605
605
|
},
|
|
606
606
|
|
|
607
|
-
updateNamespaces(state, { filters, all }) {
|
|
607
|
+
updateNamespaces(state, { filters, all, getters }) {
|
|
608
608
|
state.namespaceFilters = filters.filter((x) => !!x);
|
|
609
609
|
|
|
610
610
|
if ( all ) {
|
|
@@ -957,6 +957,7 @@ export const actions = {
|
|
|
957
957
|
commit('updateNamespaces', {
|
|
958
958
|
filters: filters || [ALL_USER],
|
|
959
959
|
all: allNamespaces,
|
|
960
|
+
getters
|
|
960
961
|
});
|
|
961
962
|
|
|
962
963
|
if (getters['currentCluster'] && getters['currentCluster'].isHarvester) {
|
|
@@ -979,7 +980,7 @@ export const actions = {
|
|
|
979
980
|
}
|
|
980
981
|
});
|
|
981
982
|
|
|
982
|
-
commit('updateNamespaces', { filters: ids });
|
|
983
|
+
commit('updateNamespaces', { filters: ids, getters });
|
|
983
984
|
},
|
|
984
985
|
|
|
985
986
|
async cleanNamespaces({ getters, dispatch }) {
|
package/store/plugins.js
CHANGED
|
@@ -100,12 +100,13 @@ export const suffixFields = [
|
|
|
100
100
|
|
|
101
101
|
// Machine driver to cloud provider mapping
|
|
102
102
|
const driverToCloudProviderMap = {
|
|
103
|
-
amazonec2:
|
|
104
|
-
azure:
|
|
105
|
-
digitalocean:
|
|
106
|
-
harvester:
|
|
107
|
-
linode:
|
|
108
|
-
vmwarevsphere:
|
|
103
|
+
amazonec2: 'aws',
|
|
104
|
+
azure: 'azure',
|
|
105
|
+
digitalocean: '', // Show restricted options
|
|
106
|
+
harvester: 'harvester',
|
|
107
|
+
linode: '', // Show restricted options
|
|
108
|
+
vmwarevsphere: 'rancher-vsphere',
|
|
109
|
+
ovhcloudpubliccloud: '',
|
|
109
110
|
|
|
110
111
|
custom: undefined // Show all options
|
|
111
112
|
};
|
package/store/type-map.js
CHANGED
|
@@ -155,10 +155,48 @@ export const NAMESPACED = 'namespaced';
|
|
|
155
155
|
export const CLUSTER_LEVEL = 'cluster';
|
|
156
156
|
export const BOTH = 'both';
|
|
157
157
|
|
|
158
|
-
export const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
export const TYPE_MODES = {
|
|
159
|
+
/**
|
|
160
|
+
* allTypes usage: All resource types
|
|
161
|
+
*
|
|
162
|
+
* getTree usage: Remove ignored schemas, resources not applicable to ns, etc
|
|
163
|
+
*/
|
|
164
|
+
ALL: 'all',
|
|
165
|
+
/**
|
|
166
|
+
* Represents resource types that should be shown at the top of the side nav.
|
|
167
|
+
*
|
|
168
|
+
* For example all fixed resource types above `More Resources` in the cluster explorer
|
|
169
|
+
*
|
|
170
|
+
* These will always be shown in the side nav
|
|
171
|
+
*
|
|
172
|
+
* allTypes usage: Resources that are in a group
|
|
173
|
+
*
|
|
174
|
+
* getTree usage: Remove ignored schemas, resources not applicable to ns, etc
|
|
175
|
+
*/
|
|
176
|
+
BASIC: 'basic',
|
|
177
|
+
/**
|
|
178
|
+
* Represents any type of resource type that has been favourited
|
|
179
|
+
*
|
|
180
|
+
* These will always be shown in the side nav.
|
|
181
|
+
*
|
|
182
|
+
* allTypes usage: Resource types that have been favorited
|
|
183
|
+
*
|
|
184
|
+
* getTree usage: Remove ignored schemas, resources not applicable to ns, etc
|
|
185
|
+
*/
|
|
186
|
+
FAVORITE: 'favorite',
|
|
187
|
+
/**
|
|
188
|
+
* Represents no virtual or spoofed types that have a count.
|
|
189
|
+
*
|
|
190
|
+
* For example the `More Resource` in the cluster explorer
|
|
191
|
+
*
|
|
192
|
+
* These will be shown in the side nav if there are resources in the ns filter OR the resource is not namespaces
|
|
193
|
+
*
|
|
194
|
+
* allTypes usage: All resource types that are not virtual or spoofed
|
|
195
|
+
*
|
|
196
|
+
* getTree usage: Remove types with no counts. Remove ignored schemas, resources not applicable to ns, etc
|
|
197
|
+
*/
|
|
198
|
+
USED: 'used',
|
|
199
|
+
};
|
|
162
200
|
|
|
163
201
|
export const ROOT = 'root';
|
|
164
202
|
|
|
@@ -535,17 +573,16 @@ export const getters = {
|
|
|
535
573
|
},
|
|
536
574
|
|
|
537
575
|
getTree(state, getters, rootState, rootGetters) {
|
|
538
|
-
|
|
576
|
+
// Name the function so it's easily identifiable when performance tracing
|
|
577
|
+
return function getTree(productId, mode, allTypes, clusterId, namespaceMode, currentType, search) {
|
|
539
578
|
// getTree has four modes:
|
|
540
|
-
// - `basic` matches data types that should always be shown even if there
|
|
541
|
-
//
|
|
542
|
-
// - `used` matches the data types where there are more than 0 of them
|
|
543
|
-
// in the current set of namespaces.
|
|
579
|
+
// - `basic` matches data types that should always be shown (even if there are 0 of them).
|
|
580
|
+
// - `used` matches the data types where there are more than 0 of them in the current set of namespaces.
|
|
544
581
|
// - `all` matches all types.
|
|
545
582
|
// - `favorite` matches starred types.
|
|
546
583
|
// namespaceMode: 'namespaced', 'cluster', or 'both'
|
|
547
584
|
// namespaces: null means all, otherwise it will be an array of specific namespaces to include
|
|
548
|
-
const isBasic = mode === BASIC;
|
|
585
|
+
const isBasic = mode === TYPE_MODES.BASIC;
|
|
549
586
|
|
|
550
587
|
let searchRegex;
|
|
551
588
|
|
|
@@ -578,7 +615,8 @@ export const getters = {
|
|
|
578
615
|
continue;
|
|
579
616
|
}
|
|
580
617
|
|
|
581
|
-
const
|
|
618
|
+
const inStore = rootGetters.currentStore(typeObj.name);
|
|
619
|
+
const count = rootGetters[`${ inStore }/count`](typeObj);
|
|
582
620
|
const groupForBasicType = getters.groupForBasicType(productId, typeObj.name);
|
|
583
621
|
|
|
584
622
|
if ( typeObj.id === currentType ) {
|
|
@@ -586,7 +624,7 @@ export const getters = {
|
|
|
586
624
|
} else if ( isBasic && !groupForBasicType ) {
|
|
587
625
|
// If we want the basic tree only return basic types;
|
|
588
626
|
continue;
|
|
589
|
-
} else if ( mode === USED && count <= 0 ) {
|
|
627
|
+
} else if ( mode === TYPE_MODES.USED && count <= 0 ) {
|
|
590
628
|
// If there's none of this type, ignore this entry when viewing only in-use types
|
|
591
629
|
// Note: count is sometimes null, which is <= 0.
|
|
592
630
|
continue;
|
|
@@ -594,7 +632,7 @@ export const getters = {
|
|
|
594
632
|
|
|
595
633
|
const label = typeObj.labelKey ? rootGetters['i18n/t'](typeObj.labelKey) || typeObj.label : typeObj.label;
|
|
596
634
|
|
|
597
|
-
const labelDisplay = highlightLabel(label,
|
|
635
|
+
const labelDisplay = highlightLabel(label, count, typeObj.schema);
|
|
598
636
|
|
|
599
637
|
if ( !labelDisplay ) {
|
|
600
638
|
// Search happens in highlight and returns null if not found
|
|
@@ -605,10 +643,10 @@ export const getters = {
|
|
|
605
643
|
|
|
606
644
|
if ( isBasic ) {
|
|
607
645
|
group = _ensureGroup(root, groupForBasicType, true);
|
|
608
|
-
} else if ( mode === FAVORITE ) {
|
|
646
|
+
} else if ( mode === TYPE_MODES.FAVORITE ) {
|
|
609
647
|
group = _ensureGroup(root, 'starred');
|
|
610
648
|
group.weight = 1000;
|
|
611
|
-
} else if ( mode === USED ) {
|
|
649
|
+
} else if ( mode === TYPE_MODES.USED ) {
|
|
612
650
|
group = _ensureGroup(root, `inUse::${ getters.groupLabelFor(typeObj.schema) }`);
|
|
613
651
|
} else {
|
|
614
652
|
group = _ensureGroup(root, typeObj.schema || typeObj.group || ROOT);
|
|
@@ -641,7 +679,6 @@ export const getters = {
|
|
|
641
679
|
label,
|
|
642
680
|
labelDisplay,
|
|
643
681
|
mode: typeObj.mode,
|
|
644
|
-
count,
|
|
645
682
|
exact: typeObj.exact || false,
|
|
646
683
|
namespaced,
|
|
647
684
|
route,
|
|
@@ -811,69 +848,109 @@ export const getters = {
|
|
|
811
848
|
});
|
|
812
849
|
},
|
|
813
850
|
|
|
851
|
+
/**
|
|
852
|
+
* Given many things, create a list of menu items per schema given the mode
|
|
853
|
+
*/
|
|
814
854
|
allTypes(state, getters, rootState, rootGetters) {
|
|
815
|
-
|
|
816
|
-
|
|
855
|
+
// Name the function so it's easily identifiable when performance tracing
|
|
856
|
+
return function allTypes(product, modes = [TYPE_MODES.ALL]) {
|
|
857
|
+
const module = state.products.find((p) => p.name === product)?.inStore;
|
|
817
858
|
const schemas = rootGetters[`${ module }/all`](SCHEMA);
|
|
859
|
+
const isLocal = !rootGetters.currentCluster?.isLocal;
|
|
860
|
+
const isRancher = rootGetters.isRancher;
|
|
818
861
|
const counts = rootGetters[`${ module }/all`](COUNT)?.[0]?.counts || {};
|
|
819
|
-
const isDev = rootGetters['prefs/get'](VIEW_IN_API);
|
|
820
|
-
const isBasic = mode === BASIC;
|
|
821
862
|
|
|
822
863
|
const out = {};
|
|
823
864
|
|
|
865
|
+
// For performance reasons this must be super quick to iterate over.
|
|
866
|
+
// For each schema...
|
|
867
|
+
// 1) Determine if it's applicable given the mode
|
|
868
|
+
// 2) For each applicable mode create a `Type` entry
|
|
824
869
|
for ( const schema of schemas ) {
|
|
870
|
+
let schemaModes = { };
|
|
871
|
+
|
|
872
|
+
modes.forEach((m) => {
|
|
873
|
+
schemaModes[m] = true;
|
|
874
|
+
});
|
|
875
|
+
|
|
825
876
|
const attrs = schema.attributes || {};
|
|
826
|
-
const count = counts[schema.id];
|
|
827
|
-
const label = getters.labelFor(schema, count);
|
|
828
|
-
const weight = getters.typeWeightFor(schema?.id || label, isBasic);
|
|
829
877
|
const typeOptions = getters['optionsFor'](schema);
|
|
830
878
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
continue;
|
|
835
|
-
}
|
|
836
|
-
} else if ( mode === FAVORITE && !getters.isFavorite(schema.id) ) {
|
|
837
|
-
continue;
|
|
838
|
-
} else if ( !attrs.kind ) {
|
|
839
|
-
// Skip the schemas that aren't top-level types
|
|
840
|
-
continue;
|
|
841
|
-
} else if ( typeof typeOptions.ifRancherCluster !== 'undefined' && typeOptions.ifRancherCluster !== rootGetters.isRancher ) {
|
|
879
|
+
schemaModes[TYPE_MODES.BASIC] = schemaModes[TYPE_MODES.BASIC] && getters.groupForBasicType(product, schema.id);
|
|
880
|
+
|
|
881
|
+
if (Object.values(schemaModes).every((s) => !s)) {
|
|
842
882
|
continue;
|
|
843
|
-
}
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
schemaModes[TYPE_MODES.FAVORITE] = schemaModes[TYPE_MODES.FAVORITE] && getters.isFavorite(schema.id);
|
|
886
|
+
|
|
887
|
+
if (Object.values(schemaModes).every((s) => !s)) {
|
|
844
888
|
continue;
|
|
845
889
|
}
|
|
846
890
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
891
|
+
const onlyBasic = schemaModes[TYPE_MODES.BASIC] && modes.length === 1;
|
|
892
|
+
|
|
893
|
+
// This clause is only valid for non-basic modes. So if we have only basic... skip it
|
|
894
|
+
if (!onlyBasic) {
|
|
895
|
+
const invalidType = !attrs.kind ||
|
|
896
|
+
(typeof typeOptions.ifRancherCluster !== 'undefined' && typeOptions.ifRancherCluster !== isRancher) ||
|
|
897
|
+
(typeOptions.localOnly && isLocal);
|
|
898
|
+
|
|
899
|
+
if (invalidType) {
|
|
900
|
+
// Remove anything not basic
|
|
901
|
+
schemaModes = { [TYPE_MODES.BASIC]: schemaModes[TYPE_MODES.BASIC] };
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// This is an expensive request to make, so only do it if we really need to
|
|
906
|
+
let label;
|
|
907
|
+
|
|
908
|
+
Object.entries(schemaModes).forEach(([mode, enabled]) => {
|
|
909
|
+
if (!enabled) {
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
if (!out[mode]) {
|
|
914
|
+
out[mode] = {};
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
if (!label) {
|
|
918
|
+
label = getters.labelFor(schema, counts[schema.id]);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
out[mode][schema.id] = {
|
|
922
|
+
label,
|
|
923
|
+
mode,
|
|
924
|
+
weight: getters.typeWeightFor(schema?.id || label, mode === TYPE_MODES.BASIC),
|
|
925
|
+
schema,
|
|
926
|
+
name: schema.id,
|
|
927
|
+
namespaced: typeOptions.namespaced === null ? attrs.namespaced : typeOptions.namespaced,
|
|
928
|
+
route: typeOptions.customRoute
|
|
929
|
+
};
|
|
930
|
+
});
|
|
859
931
|
}
|
|
860
932
|
|
|
933
|
+
const nonUsedModes = modes.filter((m) => m !== TYPE_MODES.USED);
|
|
934
|
+
const isDev = rootGetters['prefs/get'](VIEW_IN_API);
|
|
935
|
+
|
|
861
936
|
// Add virtual and spoofed types
|
|
862
|
-
if (
|
|
937
|
+
if ( nonUsedModes.length ) {
|
|
863
938
|
const virtualTypes = state.virtualTypes[product] || [];
|
|
864
939
|
const spoofedTypes = state.spoofedTypes[product] || [];
|
|
865
940
|
const allTypes = [...virtualTypes, ...spoofedTypes];
|
|
941
|
+
const virtSpoofedModes = [...nonUsedModes];
|
|
866
942
|
|
|
867
943
|
for ( const type of allTypes ) {
|
|
868
944
|
const item = clone(type);
|
|
869
945
|
const id = item.name;
|
|
870
|
-
const weight = type.weight || getters.typeWeightFor(item.label, isBasic);
|
|
871
946
|
|
|
872
947
|
// Is there a virtual/spoofed type override for schema type?
|
|
873
948
|
// Currently used by harvester, this should be investigated and removed if possible
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
949
|
+
virtSpoofedModes.forEach((mode) => {
|
|
950
|
+
if (out[mode]?.[id]) {
|
|
951
|
+
delete out[mode][id];
|
|
952
|
+
}
|
|
953
|
+
});
|
|
877
954
|
|
|
878
955
|
if ( item['public'] === false && !isDev ) {
|
|
879
956
|
continue;
|
|
@@ -916,14 +993,13 @@ export const getters = {
|
|
|
916
993
|
continue;
|
|
917
994
|
}
|
|
918
995
|
|
|
919
|
-
if (
|
|
920
|
-
|
|
921
|
-
} else if ( mode === FAVORITE && !getters.isFavorite(id) ) {
|
|
922
|
-
continue;
|
|
996
|
+
if (virtSpoofedModes.includes(TYPE_MODES.BASIC) && !getters.groupForBasicType(product, id) ) {
|
|
997
|
+
virtSpoofedModes.splice(virtSpoofedModes.indexOf(TYPE_MODES.BASIC), 1);
|
|
923
998
|
}
|
|
924
999
|
|
|
925
|
-
|
|
926
|
-
|
|
1000
|
+
if (virtSpoofedModes.includes(TYPE_MODES.FAVORITE) && !getters.isFavorite(id) ) { // mode === TYPE_MODES.FAVORITE &&
|
|
1001
|
+
virtSpoofedModes.splice(virtSpoofedModes.indexOf(TYPE_MODES.FAVORITE), 1);
|
|
1002
|
+
}
|
|
927
1003
|
|
|
928
1004
|
// Ensure labelKey is taken into account... with a mock count
|
|
929
1005
|
// This is harmless if the translation doesn't require count
|
|
@@ -934,7 +1010,17 @@ export const getters = {
|
|
|
934
1010
|
item.label = item.label || item.name;
|
|
935
1011
|
}
|
|
936
1012
|
|
|
937
|
-
|
|
1013
|
+
virtSpoofedModes.forEach((mode) => {
|
|
1014
|
+
const isBasic = mode === TYPE_MODES.BASIC;
|
|
1015
|
+
const weight = type.weight || getters.typeWeightFor(item.label, isBasic);
|
|
1016
|
+
|
|
1017
|
+
item.mode = mode;
|
|
1018
|
+
item.weight = weight;
|
|
1019
|
+
if (!out[mode]) {
|
|
1020
|
+
out[mode] = {};
|
|
1021
|
+
}
|
|
1022
|
+
out[mode][id] = item;
|
|
1023
|
+
});
|
|
938
1024
|
}
|
|
939
1025
|
}
|
|
940
1026
|
|
|
@@ -1684,22 +1770,6 @@ function _sortGroup(tree, mode) {
|
|
|
1684
1770
|
}
|
|
1685
1771
|
}
|
|
1686
1772
|
|
|
1687
|
-
function _matchingCounts(typeObj, namespaces) {
|
|
1688
|
-
// That was easy
|
|
1689
|
-
if ( !typeObj.namespaced || !typeObj.byNamespace || namespaces === null || typeObj.count === null) {
|
|
1690
|
-
return typeObj.count;
|
|
1691
|
-
}
|
|
1692
|
-
|
|
1693
|
-
let out = 0;
|
|
1694
|
-
|
|
1695
|
-
// Otherwise start with 0 and count up
|
|
1696
|
-
for ( const namespace of namespaces ) {
|
|
1697
|
-
out += typeObj.byNamespace[namespace]?.count || 0;
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
return out;
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
1773
|
function _applyMapping(objOrValue, mappings, keyField, cache, defaultFn) {
|
|
1704
1774
|
let key = objOrValue;
|
|
1705
1775
|
let found = false;
|
package/types/shell/index.d.ts
CHANGED
|
@@ -2815,6 +2815,7 @@ export default class Resource {
|
|
|
2815
2815
|
cleanYaml(yaml: any, mode?: string): any;
|
|
2816
2816
|
cleanForNew(): void;
|
|
2817
2817
|
cleanForDiff(): void;
|
|
2818
|
+
cleanForDownload(yaml: any): Promise<any>;
|
|
2818
2819
|
yamlForSave(yaml: any): any;
|
|
2819
2820
|
saveYaml(yaml: any): Promise<void>;
|
|
2820
2821
|
_saveYaml(yaml: any): Promise<void>;
|
|
@@ -3686,6 +3687,7 @@ export function applyChangeset(obj: any, changeset: any): any;
|
|
|
3686
3687
|
* Creates an object composed of the `object` properties `predicate` returns
|
|
3687
3688
|
*/
|
|
3688
3689
|
export function pickBy(obj?: {}, predicate?: (value: any, key: any) => boolean): {};
|
|
3690
|
+
export function dropKeys(obj: any, keys: any): void;
|
|
3689
3691
|
export { isEqualBasic as isEqual };
|
|
3690
3692
|
export function toDictionary(array: any, callback: any): any;
|
|
3691
3693
|
/**
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
getBlockDescriptor,
|
|
3
3
|
dumpBlock,
|
|
4
4
|
} from '@shell/utils/create-yaml';
|
|
5
|
+
import jsyaml from 'js-yaml';
|
|
5
6
|
|
|
6
7
|
const key = 'example';
|
|
7
8
|
const randomData = '\n foo\n bar\n';
|
|
@@ -61,6 +62,15 @@ describe('fx: dumpBlock', () => {
|
|
|
61
62
|
});
|
|
62
63
|
});
|
|
63
64
|
|
|
65
|
+
it('should not create a data block when the value of a key is not a string', () => {
|
|
66
|
+
const data = { key: { test: 'test' } };
|
|
67
|
+
|
|
68
|
+
const expectedResult = jsyaml.dump(data);
|
|
69
|
+
const result = dumpBlock(data);
|
|
70
|
+
|
|
71
|
+
expect(result).toStrictEqual(expectedResult);
|
|
72
|
+
});
|
|
73
|
+
|
|
64
74
|
it('should retain line breaks when a line longer than 80 characters exists', () => {
|
|
65
75
|
const data = {
|
|
66
76
|
'managerApiConfiguration.properties': `# Sample XPlanManagerAPI Configuration (if this comment is longer than 80 characters, the output should remain the same)
|
package/utils/create-yaml.js
CHANGED
|
@@ -465,7 +465,11 @@ export function dumpBlock(data, options = {}) {
|
|
|
465
465
|
|
|
466
466
|
let out = parsed;
|
|
467
467
|
|
|
468
|
-
const blockFields = Object.keys(data).filter((k) =>
|
|
468
|
+
const blockFields = Object.keys(data).filter((k) => {
|
|
469
|
+
if (typeof data[k] === 'string') {
|
|
470
|
+
return data[k].includes('\n');
|
|
471
|
+
}
|
|
472
|
+
});
|
|
469
473
|
|
|
470
474
|
if (blockFields.length) {
|
|
471
475
|
for (const key of blockFields) {
|
package/utils/object.js
CHANGED
|
@@ -425,3 +425,13 @@ export function pickBy(obj = {}, predicate = (value, key) => false) {
|
|
|
425
425
|
export const toDictionary = (array, callback) => Object.assign(
|
|
426
426
|
{}, ...array.map((item) => ({ [item]: callback(item) }))
|
|
427
427
|
);
|
|
428
|
+
|
|
429
|
+
export function dropKeys(obj, keys) {
|
|
430
|
+
if ( !obj ) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
for ( const k of keys ) {
|
|
435
|
+
delete obj[k];
|
|
436
|
+
}
|
|
437
|
+
}
|