@rancher/shell 3.0.5-rc.6 → 3.0.5-rc.8
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/brand/classic/metadata.json +3 -0
- package/assets/styles/app.scss +1 -0
- package/assets/styles/base/_color.scss +16 -0
- package/assets/styles/base/_helpers.scss +10 -0
- package/assets/styles/base/_variables.scss +18 -12
- package/assets/styles/fonts/_icons.scss +1 -32
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/themes/_dark.scss +262 -258
- package/assets/styles/themes/_light.scss +538 -509
- package/assets/styles/themes/_modern.scss +914 -0
- package/assets/translations/en-us.yaml +110 -29
- package/chart/__tests__/S3.test.ts +2 -1
- package/cloud-credential/generic.vue +18 -10
- package/cloud-credential/harvester.vue +1 -9
- package/components/AdvancedSection.vue +8 -0
- package/components/ChartReadme.vue +17 -7
- package/components/CodeMirror.vue +1 -1
- package/components/Drawer/Chrome.vue +0 -1
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +27 -28
- package/components/Drawer/ResourceDetailDrawer/composables.ts +4 -24
- package/components/Drawer/ResourceDetailDrawer/index.vue +18 -4
- package/components/InstallHelmCharts.vue +656 -0
- package/components/LazyImage.vue +60 -4
- package/components/Loading.vue +1 -1
- package/components/LocaleSelector.vue +7 -2
- package/components/Markdown.vue +4 -0
- package/components/PaginatedResourceTable.vue +46 -1
- package/components/PromptRestore.vue +22 -44
- package/components/Resource/Detail/Masthead/composable.ts +16 -0
- package/components/Resource/Detail/Masthead/index.vue +37 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +10 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +26 -7
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +8 -1
- package/components/Resource/Detail/Metadata/KeyValue.vue +12 -10
- package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
- package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +10 -17
- package/components/Resource/Detail/Metadata/composables.ts +9 -7
- package/components/Resource/Detail/Metadata/index.vue +17 -2
- package/components/Resource/Detail/Page.vue +35 -21
- package/components/Resource/Detail/SpacedRow.vue +1 -1
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +8 -9
- package/components/Resource/Detail/TitleBar/composables.ts +5 -5
- package/components/Resource/Detail/TitleBar/index.vue +12 -3
- package/components/ResourceDetail/Masthead/legacy.vue +1 -1
- package/components/ResourceDetail/index.vue +569 -72
- package/components/ResourceList/index.vue +1 -0
- package/components/ResourceTable.vue +6 -1
- package/components/ResourceYaml.vue +1 -1
- package/components/RichTranslation.vue +106 -0
- package/components/SlideInPanelManager.vue +13 -10
- package/components/SortableTable/index.vue +5 -5
- package/components/SortableTable/selection.js +0 -1
- package/components/Tabbed/index.vue +35 -4
- package/components/__tests__/LazyImage.spec.ts +121 -0
- package/components/__tests__/PromptRestore.test.ts +1 -65
- package/components/__tests__/RichTranslation.test.ts +115 -0
- package/components/fleet/FleetStatus.vue +4 -0
- package/components/fleet/dashboard/ResourcePanel.vue +2 -1
- package/components/form/ClusterAppearance.vue +5 -0
- package/components/form/FileImageSelector.vue +1 -1
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/NameNsDescription.vue +1 -0
- package/components/form/Networking.vue +24 -19
- package/components/form/ProjectMemberEditor.vue +1 -1
- package/components/form/ResourceLabeledSelect.vue +22 -8
- package/components/form/ResourceTabs/index.vue +20 -0
- package/components/form/SecretSelector.vue +9 -0
- package/components/form/SelectOrCreateAuthSecret.vue +6 -3
- package/components/form/__tests__/Networking.test.ts +116 -0
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
- package/components/formatter/FleetApplicationSource.vue +25 -17
- package/components/formatter/PodImages.vue +1 -1
- package/components/formatter/__tests__/LiveDate.test.ts +10 -2
- package/components/google/AccountAccess.vue +44 -46
- package/components/nav/Favorite.vue +4 -0
- package/components/nav/Group.vue +4 -1
- package/components/nav/NotificationCenter/Notification.vue +1 -27
- package/components/nav/WindowManager/index.vue +3 -3
- package/composables/resources.ts +2 -2
- package/config/labels-annotations.js +3 -2
- package/config/pagination-table-headers.js +8 -1
- package/config/product/explorer.js +27 -2
- package/config/product/manager.js +0 -1
- package/config/query-params.js +10 -0
- package/config/router/routes.js +21 -1
- package/config/system-namespaces.js +1 -1
- package/config/table-headers.js +30 -1
- package/config/types.js +1 -1
- package/config/version.js +1 -1
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +11 -0
- package/detail/__tests__/workload.test.ts +164 -0
- package/detail/configmap.vue +33 -75
- package/detail/projectsecret.vue +11 -0
- package/detail/provisioning.cattle.io.cluster.vue +351 -369
- package/detail/secret.vue +49 -308
- package/detail/workload/index.vue +38 -21
- package/dialog/InstallExtensionDialog.vue +8 -5
- package/dialog/RotateEncryptionKeyDialog.vue +10 -30
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/edit/auth/ldap/__tests__/config.test.ts +14 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/compliance.cattle.io.clusterscan.vue +1 -1
- package/edit/configmap.vue +4 -1
- package/edit/fleet.cattle.io.gitrepo.vue +5 -6
- package/edit/fleet.cattle.io.helmop.vue +78 -56
- package/edit/logging.banzaicloud.io.output/index.vue +1 -1
- package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
- package/edit/networking.k8s.io.ingress/Certificate.vue +20 -22
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +8 -3
- package/edit/networking.k8s.io.ingress/Rule.vue +2 -5
- package/edit/networking.k8s.io.ingress/RulePath.vue +17 -11
- package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +11 -10
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -3
- package/edit/networking.k8s.io.networkpolicy/index.vue +17 -17
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +123 -61
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +9 -7
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +22 -13
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +10 -12
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +39 -38
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +41 -19
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +16 -3
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +32 -33
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue +9 -10
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +16 -9
- package/edit/secret/basic.vue +1 -0
- package/edit/secret/index.vue +126 -15
- package/edit/workload/index.vue +5 -14
- package/list/projectsecret.vue +345 -0
- package/list/provisioning.cattle.io.cluster.vue +1 -69
- package/list/secret.vue +109 -0
- package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
- package/machine-config/google.vue +9 -1
- package/machine-config/vmwarevsphere.vue +7 -17
- package/mixins/__tests__/brand.spec.ts +2 -2
- package/mixins/chart.js +0 -2
- package/mixins/create-edit-view/impl.js +10 -1
- package/mixins/resource-fetch-api-pagination.js +11 -12
- package/mixins/resource-fetch.js +3 -1
- package/models/__tests__/chart.test.ts +111 -80
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/models/__tests__/node.test.ts +7 -63
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/catalog.cattle.io.operation.js +1 -1
- package/models/chart.js +36 -20
- package/models/cloudcredential.js +2 -163
- package/models/cluster/node.js +7 -7
- package/models/cluster.x-k8s.io.machine.js +3 -3
- package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
- package/models/compliance.cattle.io.clusterscan.js +2 -2
- package/models/configmap.js +4 -0
- package/models/constraints.gatekeeper.sh.constraint.js +1 -1
- package/models/fleet-application.js +0 -17
- package/models/fleet.cattle.io.cluster.js +2 -2
- package/models/fleet.cattle.io.gitrepo.js +15 -1
- package/models/fleet.cattle.io.helmop.js +26 -22
- package/models/management.cattle.io.setting.js +4 -0
- package/models/persistentvolumeclaim.js +1 -1
- package/models/pod.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +39 -67
- package/models/rke.cattle.io.etcdsnapshot.js +1 -1
- package/models/secret.js +161 -2
- package/models/storage.k8s.io.storageclass.js +2 -2
- package/models/workload.js +3 -3
- package/package.json +11 -10
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +1 -0
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +4 -1
- package/pages/c/_cluster/apps/charts/__tests__/AppChartCardFooter.spec.js +41 -0
- package/pages/c/_cluster/apps/charts/chart.vue +422 -174
- package/pages/c/_cluster/apps/charts/index.vue +46 -35
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/projectsecret.vue +24 -0
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +608 -314
- package/pages/c/_cluster/fleet/index.vue +103 -45
- package/pages/c/_cluster/manager/cloudCredential/index.vue +2 -59
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +10 -3
- package/pages/c/_cluster/uiplugins/index.vue +36 -25
- package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
- package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
- package/plugins/dashboard-store/actions.js +42 -22
- package/plugins/dashboard-store/normalize.js +29 -17
- package/plugins/dashboard-store/resource-class.js +83 -17
- package/plugins/steve/__tests__/getters.test.ts +1 -1
- package/plugins/steve/__tests__/subscribe.spec.ts +259 -1
- package/plugins/steve/getters.js +8 -2
- package/plugins/steve/resourceWatcher.js +10 -3
- package/plugins/steve/steve-pagination-utils.ts +14 -3
- package/plugins/steve/subscribe.js +192 -19
- package/plugins/steve/worker/web-worker.advanced.js +2 -0
- package/rancher-components/Card/Card.vue +0 -18
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.test.ts +15 -0
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +65 -0
- package/rancher-components/Pill/RcStatusBadge/index.ts +2 -0
- package/rancher-components/Pill/RcStatusBadge/types.ts +5 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.test.ts +33 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +75 -0
- package/rancher-components/Pill/RcStatusIndicator/index.ts +2 -0
- package/rancher-components/Pill/RcStatusIndicator/types.ts +7 -0
- package/rancher-components/Pill/types.ts +2 -0
- package/rancher-components/RcButton/RcButton.vue +1 -1
- package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +5 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +7 -1
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +2 -1
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +2 -1
- package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
- package/rancher-components/RcDropdown/useDropdownItem.ts +30 -1
- package/rancher-components/RcItemCard/RcItemCard.test.ts +20 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +40 -6
- package/store/__tests__/catalog.test.ts +93 -1
- package/store/aws.js +19 -8
- package/store/catalog.js +8 -3
- package/types/kube/kube-api.ts +12 -0
- package/types/resources/settings.d.ts +1 -1
- package/types/shell/index.d.ts +643 -585
- package/types/store/pagination.types.ts +16 -6
- package/types/uiplugins.ts +73 -0
- package/utils/__tests__/back-off.test.ts +354 -0
- package/utils/__tests__/create-yaml.test.ts +235 -0
- package/utils/__tests__/kontainer.test.ts +19 -0
- package/utils/__tests__/uiplugins.test.ts +84 -0
- package/utils/back-off.ts +176 -0
- package/utils/create-yaml.js +103 -9
- package/utils/dynamic-importer.js +8 -0
- package/utils/kontainer.ts +3 -5
- package/utils/pagination-utils.ts +18 -0
- package/utils/style.ts +3 -0
- package/utils/uiplugins.ts +29 -2
- package/utils/validators/__tests__/setting.test.js +92 -0
- package/utils/validators/formRules/__tests__/index.test.ts +88 -7
- package/utils/validators/formRules/index.ts +83 -8
- package/utils/validators/setting.js +17 -0
- package/cloud-credential/__tests__/harvester.test.ts +0 -18
- package/components/ResourceDetail/__tests__/index.test.ts +0 -135
- package/components/ResourceDetail/legacy.vue +0 -562
- package/components/formatter/CloudCredExpired.vue +0 -69
- package/models/etcdbackup.js +0 -45
- package/pages/explorer/resource/detail/configmap.vue +0 -42
- package/pages/explorer/resource/detail/secret.vue +0 -50
- package/utils/aws.js +0 -0
|
@@ -488,3 +488,238 @@ __clone: true
|
|
|
488
488
|
expect(actual).toStrictEqual(expected);
|
|
489
489
|
});
|
|
490
490
|
});
|
|
491
|
+
|
|
492
|
+
describe('fx: createYaml', () => {
|
|
493
|
+
interface CommentFieldsOption {
|
|
494
|
+
path: string;
|
|
495
|
+
key: string;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const schemas = [
|
|
499
|
+
{
|
|
500
|
+
id: 'provisioning.cattle.io.cluster',
|
|
501
|
+
resourceFields: {
|
|
502
|
+
apiVersion: {
|
|
503
|
+
type: 'string',
|
|
504
|
+
create: false,
|
|
505
|
+
update: false
|
|
506
|
+
},
|
|
507
|
+
kind: {
|
|
508
|
+
type: 'string',
|
|
509
|
+
create: false,
|
|
510
|
+
update: false
|
|
511
|
+
},
|
|
512
|
+
metadata: {
|
|
513
|
+
type: 'io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta',
|
|
514
|
+
create: true,
|
|
515
|
+
update: true
|
|
516
|
+
},
|
|
517
|
+
spec: {
|
|
518
|
+
type: 'provisioning.cattle.io.v1.cluster.spec',
|
|
519
|
+
nullable: true,
|
|
520
|
+
create: true,
|
|
521
|
+
update: true
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
id: 'io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta',
|
|
527
|
+
resourceFields: {
|
|
528
|
+
annotations: {
|
|
529
|
+
type: 'map[string]',
|
|
530
|
+
create: true,
|
|
531
|
+
update: true
|
|
532
|
+
},
|
|
533
|
+
labels: {
|
|
534
|
+
type: 'map[string]',
|
|
535
|
+
create: true,
|
|
536
|
+
update: true
|
|
537
|
+
},
|
|
538
|
+
namespace: {
|
|
539
|
+
type: 'string',
|
|
540
|
+
create: true,
|
|
541
|
+
update: true
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
id: 'provisioning.cattle.io.v1.cluster.spec',
|
|
547
|
+
resourceFields: {
|
|
548
|
+
localClusterAuthEndpoint: {
|
|
549
|
+
type: 'provisioning.cattle.io.v1.cluster.spec.localClusterAuthEndpoint',
|
|
550
|
+
nullable: true,
|
|
551
|
+
create: true,
|
|
552
|
+
update: true
|
|
553
|
+
},
|
|
554
|
+
rkeConfig: {
|
|
555
|
+
type: 'provisioning.cattle.io.v1.cluster.spec.rkeConfig',
|
|
556
|
+
nullable: true,
|
|
557
|
+
create: true,
|
|
558
|
+
update: true
|
|
559
|
+
},
|
|
560
|
+
foo: {
|
|
561
|
+
type: 'array[string]',
|
|
562
|
+
nullable: true,
|
|
563
|
+
create: true,
|
|
564
|
+
update: true
|
|
565
|
+
},
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
id: 'provisioning.cattle.io.v1.cluster.spec.localClusterAuthEndpoint',
|
|
570
|
+
resourceFields: {
|
|
571
|
+
caCerts: {
|
|
572
|
+
type: 'string',
|
|
573
|
+
nullable: true,
|
|
574
|
+
create: true,
|
|
575
|
+
update: true
|
|
576
|
+
},
|
|
577
|
+
enabled: {
|
|
578
|
+
type: 'boolean',
|
|
579
|
+
nullable: true,
|
|
580
|
+
create: true,
|
|
581
|
+
update: true
|
|
582
|
+
},
|
|
583
|
+
fqdn: {
|
|
584
|
+
type: 'string',
|
|
585
|
+
nullable: true,
|
|
586
|
+
create: true,
|
|
587
|
+
update: true
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
id: 'provisioning.cattle.io.v1.cluster.spec.rkeConfig',
|
|
593
|
+
resourceFields: {
|
|
594
|
+
additionalManifest: {
|
|
595
|
+
type: 'string',
|
|
596
|
+
nullable: true,
|
|
597
|
+
create: true,
|
|
598
|
+
update: true
|
|
599
|
+
},
|
|
600
|
+
chartValues: {
|
|
601
|
+
type: 'provisioning.cattle.io.v1.cluster.spec.rkeConfig.chartValues',
|
|
602
|
+
nullable: true,
|
|
603
|
+
create: true,
|
|
604
|
+
update: true
|
|
605
|
+
},
|
|
606
|
+
machineGlobalConfig: {
|
|
607
|
+
type: 'provisioning.cattle.io.v1.cluster.spec.rkeConfig.machineGlobalConfig',
|
|
608
|
+
nullable: true,
|
|
609
|
+
create: true,
|
|
610
|
+
update: true
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
id: 'provisioning.cattle.io.v1.cluster.spec.rkeConfig.chartValues',
|
|
616
|
+
resourceFields: {}
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
id: 'provisioning.cattle.io.v1.cluster.spec.rkeConfig.machineGlobalConfig',
|
|
620
|
+
resourceFields: {}
|
|
621
|
+
}
|
|
622
|
+
];
|
|
623
|
+
|
|
624
|
+
it('should comment out fields when specific properties are defined on the model with commentFieldsOptions', () => {
|
|
625
|
+
const obj = {
|
|
626
|
+
type: 'provisioning.cattle.io.cluster',
|
|
627
|
+
metadata: {
|
|
628
|
+
namespace: 'fleet-default',
|
|
629
|
+
annotations: { someannotation: 'test' },
|
|
630
|
+
labels: {}
|
|
631
|
+
},
|
|
632
|
+
__clone: true,
|
|
633
|
+
spec: {
|
|
634
|
+
localClusterAuthEndpoint: {
|
|
635
|
+
caCerts: '',
|
|
636
|
+
enabled: false,
|
|
637
|
+
fqdn: ''
|
|
638
|
+
},
|
|
639
|
+
rkeConfig: {
|
|
640
|
+
machineGlobalConfig: {
|
|
641
|
+
cni: 'calico',
|
|
642
|
+
'disable-kube-proxy': false,
|
|
643
|
+
'etcd-expose-metrics': false,
|
|
644
|
+
profile: null
|
|
645
|
+
},
|
|
646
|
+
chartValues: {}
|
|
647
|
+
},
|
|
648
|
+
foo: [
|
|
649
|
+
'bar',
|
|
650
|
+
'bar2'
|
|
651
|
+
],
|
|
652
|
+
},
|
|
653
|
+
apiVersion: 'provisioning.cattle.io/v1',
|
|
654
|
+
kind: 'Cluster'
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
const objResult = {
|
|
658
|
+
metadata: {
|
|
659
|
+
namespace: 'fleet-default',
|
|
660
|
+
annotations: { someannotation: 'test' },
|
|
661
|
+
labels: {}
|
|
662
|
+
},
|
|
663
|
+
__clone: true,
|
|
664
|
+
spec: {
|
|
665
|
+
rkeConfig: {
|
|
666
|
+
machineGlobalConfig: {
|
|
667
|
+
cni: 'calico',
|
|
668
|
+
'disable-kube-proxy': false,
|
|
669
|
+
'etcd-expose-metrics': false,
|
|
670
|
+
},
|
|
671
|
+
chartValues: {}
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
apiVersion: 'provisioning.cattle.io/v1',
|
|
675
|
+
kind: 'Cluster'
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
const type = 'provisioning.cattle.io.cluster';
|
|
679
|
+
const commentFieldsOptions: CommentFieldsOption[] = [
|
|
680
|
+
{ path: 'spec.rkeConfig.machineGlobalConfig', key: 'profile' },
|
|
681
|
+
{ path: 'spec', key: 'localClusterAuthEndpoint' },
|
|
682
|
+
{ path: 'spec', key: 'foo' },
|
|
683
|
+
];
|
|
684
|
+
|
|
685
|
+
// Define the expected YAML output as a string, adjusted for correct spacing
|
|
686
|
+
const expectedYaml = `
|
|
687
|
+
apiVersion: provisioning.cattle.io/v1
|
|
688
|
+
kind: Cluster
|
|
689
|
+
metadata:
|
|
690
|
+
annotations:
|
|
691
|
+
someannotation: test
|
|
692
|
+
# key: string
|
|
693
|
+
labels:
|
|
694
|
+
{}
|
|
695
|
+
# key: string
|
|
696
|
+
namespace: fleet-default
|
|
697
|
+
spec:
|
|
698
|
+
# localClusterAuthEndpoint:
|
|
699
|
+
# caCerts: ''
|
|
700
|
+
# enabled: false
|
|
701
|
+
# fqdn: ''
|
|
702
|
+
rkeConfig:
|
|
703
|
+
chartValues:
|
|
704
|
+
{}
|
|
705
|
+
machineGlobalConfig:
|
|
706
|
+
cni: calico
|
|
707
|
+
disable-kube-proxy: false
|
|
708
|
+
etcd-expose-metrics: false
|
|
709
|
+
# profile: null
|
|
710
|
+
# additionalManifest: string
|
|
711
|
+
# foo:
|
|
712
|
+
# - bar
|
|
713
|
+
# - bar2
|
|
714
|
+
# - string
|
|
715
|
+
__clone: true`.trim();
|
|
716
|
+
|
|
717
|
+
const result = createYaml(schemas, type, obj, true, 0, '', null, {}, commentFieldsOptions as any);
|
|
718
|
+
|
|
719
|
+
// Check if result is a valid YAML
|
|
720
|
+
expect(jsyaml.load(result.trim())).toStrictEqual(objResult);
|
|
721
|
+
|
|
722
|
+
// Check if properties are commented out
|
|
723
|
+
expect(result.trim()).toStrictEqual(expectedYaml);
|
|
724
|
+
});
|
|
725
|
+
});
|
|
@@ -17,6 +17,25 @@ describe('fx: diffUpstreamSpec', () => {
|
|
|
17
17
|
expect(diffUpstreamSpec(upstream, local)).toStrictEqual(diff);
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
+
it.each([
|
|
21
|
+
[{
|
|
22
|
+
a: { one: 'a' },
|
|
23
|
+
b: ['1', 'b'],
|
|
24
|
+
c: 'c'
|
|
25
|
+
}, {
|
|
26
|
+
a: {},
|
|
27
|
+
b: [],
|
|
28
|
+
c: ''
|
|
29
|
+
}, {
|
|
30
|
+
a: {},
|
|
31
|
+
b: [],
|
|
32
|
+
c: ''
|
|
33
|
+
}],
|
|
34
|
+
[{ a: 'a' }, { b: null }, { }],
|
|
35
|
+
])('should include fields that are empty objects, arrays or strings on the local object regardless of upstream definition', (upstream, local, diff) => {
|
|
36
|
+
expect(diffUpstreamSpec(upstream, local)).toStrictEqual(diff);
|
|
37
|
+
});
|
|
38
|
+
|
|
20
39
|
it.each([
|
|
21
40
|
[{ a: null }, { a: {} }, {}],
|
|
22
41
|
[{ a: null }, { a: [] }, {}],
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Plugin, Version } from '@shell/types/uiplugins';
|
|
2
|
+
import { getPluginChartVersion, getPluginChartVersionLabel } from '../uiplugins';
|
|
3
|
+
|
|
4
|
+
function makePlugin(partial: Partial<Plugin>): Plugin {
|
|
5
|
+
return {
|
|
6
|
+
name: 'test',
|
|
7
|
+
label: 'Test',
|
|
8
|
+
description: '',
|
|
9
|
+
id: 'test',
|
|
10
|
+
versions: [],
|
|
11
|
+
installed: false,
|
|
12
|
+
builtin: false,
|
|
13
|
+
experimental: false,
|
|
14
|
+
certified: false,
|
|
15
|
+
chart: {} as any,
|
|
16
|
+
incompatibilityMessage: '',
|
|
17
|
+
installableVersions: [],
|
|
18
|
+
displayVersion: '',
|
|
19
|
+
pluginVersionLabel: '',
|
|
20
|
+
helmError: false,
|
|
21
|
+
...partial
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('fx: getPluginChartVersion', () => {
|
|
26
|
+
it('returns the Helm Chart version when displayVersion matches appVersion', () => {
|
|
27
|
+
const plugin = makePlugin({
|
|
28
|
+
displayVersion: '1.2.3',
|
|
29
|
+
versions: [
|
|
30
|
+
{ appVersion: '1.2.3', version: '4.5.6' } as Version,
|
|
31
|
+
{ appVersion: '2.0.0', version: '5.0.0' } as Version
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
expect(getPluginChartVersion(plugin)).toBe('4.5.6');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('falls back to version if appVersion is not present', () => {
|
|
39
|
+
const plugin = makePlugin({
|
|
40
|
+
displayVersion: '7.8.9',
|
|
41
|
+
versions: [
|
|
42
|
+
{ version: '7.8.9' } as Version,
|
|
43
|
+
{ version: '8.0.0' } as Version
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(getPluginChartVersion(plugin)).toBe('7.8.9');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('returns displayVersion if no matching chart is found', () => {
|
|
51
|
+
const plugin = makePlugin({
|
|
52
|
+
displayVersion: '9.9.9',
|
|
53
|
+
versions: [
|
|
54
|
+
{ appVersion: '1.0.0', version: '1.0.0' } as Version,
|
|
55
|
+
{ appVersion: '2.0.0', version: '2.0.0' } as Version
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(getPluginChartVersion(plugin)).toBe('9.9.9');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('returns undefined if plugin is undefined', () => {
|
|
63
|
+
expect(getPluginChartVersion(undefined)).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('returns displayVersion if plugin.versions is undefined', () => {
|
|
67
|
+
const plugin = makePlugin({ displayVersion: '1.0.0', versions: undefined as any });
|
|
68
|
+
|
|
69
|
+
expect(getPluginChartVersion(plugin)).toBe('1.0.0');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('fx: getPluginChartVersionLabel', () => {
|
|
74
|
+
it('returns simple version string if Helm Chart Version appVersion matches version', () => {
|
|
75
|
+
const version = { version: '1.2.3', appVersion: '1.2.3' } as Version;
|
|
76
|
+
|
|
77
|
+
expect(getPluginChartVersionLabel(version)).toBe('1.2.3');
|
|
78
|
+
});
|
|
79
|
+
it(`if version and appVersion don't match, it returns 'appVersion (version)' string`, () => {
|
|
80
|
+
const version = { version: '1.2.3', appVersion: '4.5.6' } as Version;
|
|
81
|
+
|
|
82
|
+
expect(getPluginChartVersionLabel(version)).toBe('4.5.6 (1.2.3)');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
type BackOffEntry = {
|
|
2
|
+
timeoutId?: NodeJS.Timeout,
|
|
3
|
+
try: number,
|
|
4
|
+
retries: number,
|
|
5
|
+
description: string,
|
|
6
|
+
metadata: any,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Helper class which handles backing off making the supplied request
|
|
11
|
+
*
|
|
12
|
+
* see `execute` for more info
|
|
13
|
+
*/
|
|
14
|
+
class BackOff {
|
|
15
|
+
private map: {
|
|
16
|
+
[id: string]: BackOffEntry
|
|
17
|
+
} = {};
|
|
18
|
+
|
|
19
|
+
private log(level: 'error' | 'info' | 'debug', id: string, classDescription: string, description: string, ...args: any[]) {
|
|
20
|
+
console[level](`BackOff... Id: "${ id }". Description: "${ description }"\nStatus: ${ classDescription }\n`, ...args); // eslint-disable-line no-console
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get a specific back off process
|
|
25
|
+
*/
|
|
26
|
+
getBackOff(id: string): BackOffEntry {
|
|
27
|
+
return this.map[id];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Stop ALL back off processes started since the ui was loaded
|
|
32
|
+
*/
|
|
33
|
+
resetAll() {
|
|
34
|
+
Object.keys(this.map).forEach((id) => {
|
|
35
|
+
this.reset(id);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Stop all back off process with a specific prefix
|
|
41
|
+
*/
|
|
42
|
+
resetPrefix(prefix:string) {
|
|
43
|
+
Object.keys(this.map).forEach((id) => {
|
|
44
|
+
if (id.startsWith(prefix)) {
|
|
45
|
+
this.reset(id);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Stop a back off process with a specific id
|
|
52
|
+
*/
|
|
53
|
+
reset(id: string) {
|
|
54
|
+
const backOff: BackOffEntry = this.map[id];
|
|
55
|
+
|
|
56
|
+
if (backOff) {
|
|
57
|
+
if (backOff?.timeoutId) {
|
|
58
|
+
this.log('info', id, 'Stopping (cancelling active back-off)', backOff.description);
|
|
59
|
+
|
|
60
|
+
clearTimeout(backOff.timeoutId);
|
|
61
|
+
}
|
|
62
|
+
this.log('debug', id, 'Reset', backOff.description);
|
|
63
|
+
|
|
64
|
+
delete this.map[id];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Call a function, but if it's recently been called delay execution aka back off
|
|
70
|
+
*
|
|
71
|
+
* This can be used in a totally disjoined asynchronous way
|
|
72
|
+
*
|
|
73
|
+
* 1. Request function A to be run
|
|
74
|
+
* 2. Entirely separate process requests function A to be run again
|
|
75
|
+
* 3. Back off process waits Xms and then runs function A again
|
|
76
|
+
* 4. Repeat steps 2 and 3, with an exponential increasing delay
|
|
77
|
+
*
|
|
78
|
+
* This can be called repeatedly, if the previous delay is still running new requests will be ignored
|
|
79
|
+
*/
|
|
80
|
+
async execute<T = any>({
|
|
81
|
+
id, description, retries = 10, delayedFn, canFn = async() => true, metadata
|
|
82
|
+
}: {
|
|
83
|
+
/**
|
|
84
|
+
* Unique id for the execution of this function.
|
|
85
|
+
*
|
|
86
|
+
* This will be used to delay further executions, and also to cancel it
|
|
87
|
+
*/
|
|
88
|
+
id: string,
|
|
89
|
+
/**
|
|
90
|
+
* Basic text description to use in logging
|
|
91
|
+
*/
|
|
92
|
+
description: string,
|
|
93
|
+
/**
|
|
94
|
+
* Number of executions allowed before flatly refusing to call more. Defaults to 10
|
|
95
|
+
*/
|
|
96
|
+
retries?: number,
|
|
97
|
+
/**
|
|
98
|
+
* Before calling delayedFn check if it can still run
|
|
99
|
+
*
|
|
100
|
+
* Useful for checking state after a looong delay
|
|
101
|
+
*/
|
|
102
|
+
canFn?: () => Promise<boolean>,
|
|
103
|
+
/**
|
|
104
|
+
* Call this function
|
|
105
|
+
* - if it's not already waiting to run
|
|
106
|
+
* - if it's passed canFn
|
|
107
|
+
* - if it hasn't been tried over `retries` amount
|
|
108
|
+
*
|
|
109
|
+
* The function will be increasingly (exponentially) delayed if it has previously been called
|
|
110
|
+
*/
|
|
111
|
+
delayedFn: () => Promise<any>,
|
|
112
|
+
/**
|
|
113
|
+
* Anything that might be important outside of this file (used with `getBackOff`)
|
|
114
|
+
*/
|
|
115
|
+
metadata?: T,
|
|
116
|
+
}): Promise<NodeJS.Timeout | undefined> {
|
|
117
|
+
const backOff: BackOffEntry = this.map[id];
|
|
118
|
+
|
|
119
|
+
const cont = await canFn();
|
|
120
|
+
|
|
121
|
+
if (!cont) {
|
|
122
|
+
this.log('info', id, 'Skipping (can execute fn test failed)', description);
|
|
123
|
+
|
|
124
|
+
return undefined;
|
|
125
|
+
} else if (backOff?.timeoutId) {
|
|
126
|
+
this.log('info', id, 'Skipping (previous back off process still running)', description);
|
|
127
|
+
|
|
128
|
+
return backOff.timeoutId;
|
|
129
|
+
} else {
|
|
130
|
+
const backOffTry = backOff?.try || 0;
|
|
131
|
+
|
|
132
|
+
if (backOffTry + 1 > retries) {
|
|
133
|
+
this.log('error', id, 'Aborting (too many retries)', description);
|
|
134
|
+
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// First step is immediate (0.001s)
|
|
139
|
+
// Second and others are exponential
|
|
140
|
+
// 1, 2, 3, 4, 5, 6, 7, 8, 9
|
|
141
|
+
// 1, 4, 9, 16, 25, 36, 49, 64, 81
|
|
142
|
+
// 0.25s, 1s, 2.25s, 4s, 6.25s, 9s, 12.25s, 16s, 20.25s
|
|
143
|
+
const delay = backOffTry === 0 ? 1 : Math.pow(backOffTry, 2) * 250;
|
|
144
|
+
|
|
145
|
+
this.log('info', id, `Delaying call (attempt ${ backOffTry + 1 }, delayed by ${ delay }ms)`, description);
|
|
146
|
+
|
|
147
|
+
const timeout = setTimeout(async() => {
|
|
148
|
+
try {
|
|
149
|
+
this.log('info', id, `Executing call`, description);
|
|
150
|
+
|
|
151
|
+
await delayedFn();
|
|
152
|
+
} catch (e) {
|
|
153
|
+
// Error occurred. Don't clear the map. Next time this is called we'll back off before trying ...
|
|
154
|
+
this.log('error', id, 'Failed call', description, e);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Unblock future calls
|
|
158
|
+
delete this.map[id]?.timeoutId;
|
|
159
|
+
}, delay);
|
|
160
|
+
|
|
161
|
+
this.map[id] = {
|
|
162
|
+
timeoutId: timeout,
|
|
163
|
+
try: backOff?.try ? backOff.try + 1 : 1,
|
|
164
|
+
retries,
|
|
165
|
+
description,
|
|
166
|
+
metadata
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return timeout;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const backOff = new BackOff();
|
|
175
|
+
|
|
176
|
+
export default backOff;
|
package/utils/create-yaml.js
CHANGED
|
@@ -70,13 +70,14 @@ export const ACTIVELY_REMOVE = [
|
|
|
70
70
|
|
|
71
71
|
const INDENT = 2;
|
|
72
72
|
|
|
73
|
-
export function createYamlWithOptions(schemas, type, data, options) {
|
|
73
|
+
export function createYamlWithOptions(schemas, type, data, options, commentFieldsOptions) {
|
|
74
74
|
return createYaml(
|
|
75
75
|
schemas,
|
|
76
76
|
type,
|
|
77
77
|
data,
|
|
78
78
|
true, 0, '', null,
|
|
79
|
-
options
|
|
79
|
+
options,
|
|
80
|
+
commentFieldsOptions
|
|
80
81
|
);
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -89,6 +90,7 @@ export function createYaml(
|
|
|
89
90
|
path = '',
|
|
90
91
|
rootType = null,
|
|
91
92
|
dataOptions = {},
|
|
93
|
+
commentFieldsOptions = null
|
|
92
94
|
) {
|
|
93
95
|
data = data || {};
|
|
94
96
|
|
|
@@ -133,6 +135,10 @@ export function createYaml(
|
|
|
133
135
|
|
|
134
136
|
const regularFields = [];
|
|
135
137
|
|
|
138
|
+
if ( !commentFieldsOptions ) {
|
|
139
|
+
commentFieldsOptions = data?.commentFieldsOptions;
|
|
140
|
+
}
|
|
141
|
+
|
|
136
142
|
if (processAlwaysAdd) {
|
|
137
143
|
// Add all the parents of each key so that spec.template.foo.blah
|
|
138
144
|
// causes 'spec', 'template' and 'foo' keys to be created
|
|
@@ -230,6 +236,18 @@ export function createYaml(
|
|
|
230
236
|
out = 'type:';
|
|
231
237
|
}
|
|
232
238
|
|
|
239
|
+
commentFieldsOptions = addCommentSubFieldsOptions(commentFieldsOptions, data, path, key);
|
|
240
|
+
|
|
241
|
+
// If commentFieldOptions is defined on the model and the currentPath matches the path and key
|
|
242
|
+
// defined in one of the options, then comment out that line.
|
|
243
|
+
if ( Array.isArray(commentFieldsOptions) && commentFieldsOptions.length ) {
|
|
244
|
+
const currentPath = path ? `${ path }.${ key }` : key;
|
|
245
|
+
|
|
246
|
+
if ( commentFieldsOptions.some((option) => `${ option.path }.${ option.key }` === currentPath) ) {
|
|
247
|
+
out = `#${ out }`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
233
251
|
// if a key on data is not listed in the schema's resourceFields, just convert it to yaml, add indents where needed, and return
|
|
234
252
|
if ( !field ) {
|
|
235
253
|
if (data[key]) {
|
|
@@ -275,7 +293,7 @@ export function createYaml(
|
|
|
275
293
|
out += `# key: ${ mapOf }`;
|
|
276
294
|
} else {
|
|
277
295
|
// If not a simple type ie some sort of object/array, recursively build out commented fields (note data = null here) per the type's (mapOf's) schema
|
|
278
|
-
const chunk = createYaml(schemas, mapOf, null, processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions);
|
|
296
|
+
const chunk = createYaml(schemas, mapOf, null, processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions, commentFieldsOptions);
|
|
279
297
|
let indented = indent(chunk);
|
|
280
298
|
|
|
281
299
|
// convert "# foo" to "#foo"
|
|
@@ -296,7 +314,34 @@ export function createYaml(
|
|
|
296
314
|
if ( cleaned?.[key] ) {
|
|
297
315
|
const parsedData = jsyaml.dump(cleaned[key]);
|
|
298
316
|
|
|
299
|
-
|
|
317
|
+
let chunk;
|
|
318
|
+
|
|
319
|
+
// If commentFieldOptions is defined on the model and the array has the property (`key`)
|
|
320
|
+
// defined in one of the options, then comment out that line.
|
|
321
|
+
if ( Array.isArray(commentFieldsOptions) && commentFieldsOptions.length ) {
|
|
322
|
+
let lines = parsedData.split('\n');
|
|
323
|
+
|
|
324
|
+
commentFieldsOptions.forEach((option) => {
|
|
325
|
+
// Assuming the path for the current array matches the option's path
|
|
326
|
+
// and the specific key to comment out exists in the array
|
|
327
|
+
if ( `${ path }.${ key }` === option.path && data[key][option.key] !== undefined ) {
|
|
328
|
+
// Comment out the line containing the target line
|
|
329
|
+
lines = lines.map((line, i) => {
|
|
330
|
+
if ( i === Number(option.key) ) {
|
|
331
|
+
return `#${ line }`;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return line;
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
chunk = lines.join('\n').trim();
|
|
340
|
+
} else {
|
|
341
|
+
chunk = parsedData.trim();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
out += `\n${ indent(chunk) }`;
|
|
300
345
|
}
|
|
301
346
|
} catch (e) {
|
|
302
347
|
console.error(`Error: Unable to parse array data for yaml of type: ${ type }`, e); // eslint-disable-line no-console
|
|
@@ -306,7 +351,7 @@ export function createYaml(
|
|
|
306
351
|
if ( SIMPLE_TYPES.includes(arrayOf) ) {
|
|
307
352
|
out += `\n# - ${ arrayOf }`;
|
|
308
353
|
} else {
|
|
309
|
-
const chunk = createYaml(schemas, arrayOf, null, false, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions);
|
|
354
|
+
const chunk = createYaml(schemas, arrayOf, null, false, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions, commentFieldsOptions);
|
|
310
355
|
let indented = indent(chunk, 2);
|
|
311
356
|
|
|
312
357
|
// turn "# foo" into "# - foo"
|
|
@@ -357,19 +402,45 @@ export function createYaml(
|
|
|
357
402
|
|
|
358
403
|
const subDef = schemaDefinitions?.[type] || findBy(schemas, 'id', type);
|
|
359
404
|
|
|
360
|
-
if ( subDef) {
|
|
405
|
+
if ( subDef ) {
|
|
361
406
|
let chunk;
|
|
362
407
|
|
|
363
408
|
if (subDef?.resourceFields && !isEmpty(subDef?.resourceFields)) {
|
|
364
|
-
chunk = createYaml(schemas, type, data[key], processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions);
|
|
409
|
+
chunk = createYaml(schemas, type, data[key], processAlwaysAdd, depth + 1, (path ? `${ path }.${ key }` : key), rootType, dataOptions, commentFieldsOptions);
|
|
365
410
|
} else if (data[key]) {
|
|
366
411
|
// if there are no fields defined on the schema but there are in the data, just format data as yaml and add to output yaml
|
|
367
412
|
try {
|
|
368
413
|
const parsed = jsyaml.dump(data[key]);
|
|
369
414
|
|
|
370
|
-
|
|
415
|
+
// If commentFieldOptions is defined on the model and `data[key]` has the property (`key`)
|
|
416
|
+
// defined in one of the options, then comment out that line.
|
|
417
|
+
if ( Array.isArray(commentFieldsOptions) && commentFieldsOptions.length ) {
|
|
418
|
+
let lines = parsed.split('\n');
|
|
419
|
+
|
|
420
|
+
commentFieldsOptions.forEach((option) => {
|
|
421
|
+
// Assuming the path for the current data[key] matches the option's path
|
|
422
|
+
// and the specific key to comment out exists in the data[key]
|
|
423
|
+
if ( `${ path }.${ key }` === option.path && data[key][option.key] !== undefined ) {
|
|
424
|
+
const targetKeyString = `${ option.key }:`;
|
|
425
|
+
|
|
426
|
+
// Comment out the line containing the target key
|
|
427
|
+
lines = lines.map((line) => {
|
|
428
|
+
if ( line.trim().startsWith(targetKeyString) ) {
|
|
429
|
+
return `# ${ line }`;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return line;
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
chunk = lines.join('\n').trim();
|
|
438
|
+
} else {
|
|
439
|
+
// If commentFieldsOptions do not exist, use the original `parsed` string
|
|
440
|
+
chunk = parsed.trim();
|
|
441
|
+
}
|
|
371
442
|
} catch (e) {
|
|
372
|
-
console.error(`Error:
|
|
443
|
+
console.error(`Error: Unable to parse data for yaml of type: ${ type }`, e); // eslint-disable-line no-console
|
|
373
444
|
}
|
|
374
445
|
}
|
|
375
446
|
|
|
@@ -380,6 +451,29 @@ export function createYaml(
|
|
|
380
451
|
|
|
381
452
|
return out;
|
|
382
453
|
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Extends original commentFieldsOptions to cover nested objects
|
|
457
|
+
*/
|
|
458
|
+
function addCommentSubFieldsOptions(options, data, path, key) {
|
|
459
|
+
if (!!options) {
|
|
460
|
+
if ( Array.isArray(options) && options.length ) {
|
|
461
|
+
const currentPath = path ? `${ path }.${ key }` : key;
|
|
462
|
+
|
|
463
|
+
if ( options.some((option) => `${ option.path }.${ option.key }` === currentPath) ) {
|
|
464
|
+
options = [
|
|
465
|
+
...options,
|
|
466
|
+
...Object.keys(data[key]).map((k) => ({
|
|
467
|
+
path: `${ path }.${ key }`,
|
|
468
|
+
key: k
|
|
469
|
+
}))
|
|
470
|
+
];
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return options;
|
|
476
|
+
}
|
|
383
477
|
}
|
|
384
478
|
|
|
385
479
|
function comment(lines) {
|