@rancher/shell 3.0.9-rc.5 → 3.0.9-rc.6
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/images/providers/oci-open-containers.svg +22 -0
- package/assets/images/providers/traefik.png +0 -0
- package/assets/styles/themes/_dark.scss +2 -0
- package/assets/styles/themes/_light.scss +2 -0
- package/assets/styles/themes/_modern.scss +6 -0
- package/assets/translations/en-us.yaml +129 -25
- package/components/CruResource.vue +3 -1
- package/components/ExplorerProjectsNamespaces.vue +12 -12
- package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +109 -0
- package/components/Resource/Detail/Card/StatusCard/index.vue +21 -4
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +19 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +19 -11
- package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +12 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +2 -0
- package/components/Resource/Detail/ResourceRow.vue +2 -2
- package/components/ResourceList/index.vue +7 -4
- package/components/Window/ContainerLogs.vue +48 -37
- package/components/fleet/FleetClusterTargets/TargetsList.vue +2 -2
- package/components/fleet/FleetClusterTargets/index.vue +6 -1
- package/components/fleet/GitRepoAdvancedTab.vue +333 -0
- package/components/fleet/GitRepoMetadataTab.vue +43 -0
- package/components/fleet/GitRepoRepositoryTab.vue +101 -0
- package/components/fleet/GitRepoTargetTab.vue +77 -0
- package/components/fleet/HelmOpAdvancedTab.vue +247 -0
- package/components/fleet/HelmOpChartTab.vue +158 -0
- package/components/fleet/HelmOpMetadataTab.vue +46 -0
- package/components/fleet/HelmOpTargetTab.vue +84 -0
- package/components/fleet/HelmOpValuesTab.vue +147 -0
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +119 -70
- package/components/form/NodeScheduling.vue +81 -7
- package/components/form/PodAffinity.vue +1 -36
- package/components/form/ResourceLabeledSelect.vue +8 -4
- package/components/form/ResourceQuota/Namespace.vue +30 -9
- package/components/form/ResourceQuota/NamespaceRow.vue +25 -7
- package/components/form/ResourceQuota/Project.vue +140 -82
- package/components/form/ResourceQuota/ResourceQuotaEntry.vue +145 -0
- package/components/form/ResourceQuota/__tests__/Namespace.test.ts +307 -0
- package/components/form/ResourceQuota/__tests__/NamespaceRow.test.ts +281 -0
- package/components/form/ResourceQuota/__tests__/Project.test.ts +274 -27
- package/components/form/ResourceQuota/__tests__/ResourceQuotaEntry.test.ts +215 -0
- package/components/form/SchedulingCustomization.vue +14 -6
- package/components/form/SelectOrCreateAuthSecret.vue +107 -18
- package/components/form/__tests__/NodeScheduling.test.ts +12 -9
- package/components/form/__tests__/PodAffinity.test.ts +21 -2
- package/components/form/__tests__/SchedulingCustomization.test.ts +240 -0
- package/components/formatter/ClusterLink.vue +8 -0
- package/components/formatter/SecretOrigin.vue +79 -0
- package/config/labels-annotations.js +7 -6
- package/config/pagination-table-headers.js +6 -4
- package/config/product/explorer.js +1 -11
- package/config/query-params.js +3 -0
- package/config/settings.ts +15 -2
- package/config/table-headers.js +21 -17
- package/config/types.js +23 -8
- package/detail/workload/index.vue +11 -16
- package/dialog/DeactivateDriverDialog.vue +1 -1
- package/dialog/Ipv6NetworkingDialog.vue +156 -0
- package/dialog/ScalePoolDownDialog.vue +2 -2
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +1 -0
- package/edit/__tests__/management.cattle.io.project.test.js +56 -128
- package/edit/auth/oidc.vue +1 -1
- package/edit/catalog.cattle.io.clusterrepo.vue +155 -25
- package/edit/fleet.cattle.io.gitrepo.vue +153 -283
- package/edit/fleet.cattle.io.helmop.vue +190 -332
- package/edit/management.cattle.io.project.vue +5 -42
- package/edit/management.cattle.io.setting.vue +6 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +55 -24
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +1 -103
- package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +13 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2-fleet-cluster-agent.test.ts +283 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -49
- package/edit/provisioning.cattle.io.cluster/ingress/IngressCards.vue +112 -0
- package/edit/provisioning.cattle.io.cluster/ingress/IngressConfiguration.vue +158 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +171 -72
- package/edit/provisioning.cattle.io.cluster/shared.ts +36 -1
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +2 -1
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +55 -7
- package/edit/provisioning.cattle.io.cluster/tabs/Ingress.vue +319 -0
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +2 -1
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/__tests__/S3Config.test.ts +13 -1
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +10 -44
- package/edit/secret/index.vue +1 -1
- package/edit/token.vue +68 -29
- package/edit/workload/__tests__/index.test.ts +2 -37
- package/edit/workload/index.vue +6 -2
- package/edit/workload/mixins/workload.js +0 -32
- package/list/__tests__/management.cattle.io.setting.test.ts +198 -0
- package/list/management.cattle.io.setting.vue +13 -0
- package/list/provisioning.cattle.io.cluster.vue +50 -1
- package/list/secret.vue +4 -9
- package/list/service.vue +6 -8
- package/machine-config/amazonec2.vue +11 -4
- package/machine-config/components/EC2Networking.vue +46 -30
- package/machine-config/components/__tests__/EC2Networking.test.ts +7 -7
- package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +0 -9
- package/machine-config/digitalocean.vue +3 -3
- package/models/__tests__/namespace.test.ts +11 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +96 -0
- package/models/__tests__/workload.test.ts +42 -1
- package/models/catalog.cattle.io.clusterrepo.js +30 -4
- package/models/ext.cattle.io.token.js +48 -0
- package/models/kontainerdriver.js +2 -2
- package/models/namespace.js +7 -1
- package/models/nodedriver.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +28 -7
- package/models/secret.js +0 -17
- package/models/service.js +44 -1
- package/models/token.js +4 -0
- package/models/workload.js +12 -6
- package/package.json +1 -1
- package/pages/account/index.vue +96 -67
- package/pages/auth/setup.vue +5 -14
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +4 -1
- package/pages/c/_cluster/apps/charts/index.vue +93 -4
- package/pages/c/_cluster/apps/charts/install.vue +317 -42
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -4
- package/pages/c/_cluster/settings/index.vue +3 -1
- package/plugins/dashboard-store/__tests__/getters.test.ts +108 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +27 -0
- package/plugins/dashboard-store/actions.js +3 -8
- package/plugins/dashboard-store/getters.js +7 -5
- package/plugins/dashboard-store/mutations.js +4 -1
- package/plugins/dashboard-store/resource-class.js +3 -3
- package/plugins/steve/__tests__/steve-class.test.ts +102 -141
- package/plugins/steve/steve-class.js +12 -3
- package/plugins/steve/steve-pagination-utils.ts +6 -2
- package/rancher-components/RcIcon/types.ts +2 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +64 -19
- package/store/prefs.js +3 -0
- package/types/aws-sdk.d.ts +121 -0
- package/types/resources/node.ts +15 -0
- package/types/shell/index.d.ts +536 -506
- package/types/store/pagination.types.ts +5 -5
- package/utils/__tests__/array.test.ts +1 -29
- package/utils/__tests__/cluster-agent-configuration.test.ts +203 -0
- package/utils/array.ts +0 -11
- package/utils/aws.ts +21 -0
- package/utils/cluster.js +22 -2
- package/utils/selector-typed.ts +1 -1
- package/components/__tests__/ProjectRow.test.ts +0 -206
- package/components/form/ResourceQuota/ProjectRow.vue +0 -277
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import { mount, shallowMount } from '@vue/test-utils';
|
|
2
2
|
import { SECRET } from '@shell/config/types';
|
|
3
|
-
import { _CREATE } from '@shell/config/query-params';
|
|
3
|
+
import { _CREATE, _EDIT } from '@shell/config/query-params';
|
|
4
4
|
import rke2 from '@shell/edit/provisioning.cattle.io.cluster/rke2.vue';
|
|
5
5
|
import { get } from '@shell/utils/object';
|
|
6
6
|
import { rke2TestTable } from './utils/rke2-test-data';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
RKE2_INGRESS_NGINX, INGRESS_CONTROLLER, INGRESS_NGINX, TRAEFIK, INGRESS_NONE, RKE2_TRAEFIK
|
|
9
|
+
} from '@shell/edit/provisioning.cattle.io.cluster/shared';
|
|
10
|
+
|
|
11
|
+
jest.mock('@shell/edit/provisioning.cattle.io.cluster/shared', () => ({
|
|
12
|
+
RETENTION_DEFAULT: 5,
|
|
13
|
+
RKE2_INGRESS_NGINX: 'rke2-ingress-nginx',
|
|
14
|
+
RKE2_TRAEFIK: 'rke2-traefik',
|
|
15
|
+
INGRESS_NGINX: 'ingress-nginx',
|
|
16
|
+
INGRESS_CONTROLLER: 'ingress-controller',
|
|
17
|
+
TRAEFIK: 'traefik',
|
|
18
|
+
HARVESTER: 'harvester',
|
|
19
|
+
INGRESS_DUAL: 'dual',
|
|
20
|
+
INGRESS_NONE: 'none',
|
|
21
|
+
INGRESS_OPTIONS: [],
|
|
22
|
+
INGRESS_MIGRATION_KB_LINK: 'mock-link'
|
|
23
|
+
}));
|
|
8
24
|
|
|
9
25
|
/**
|
|
10
26
|
* DISCLAIMER ***************************************************************************************
|
|
@@ -453,7 +469,11 @@ describe('component: rke2', () => {
|
|
|
453
469
|
rke2Versions: [{
|
|
454
470
|
id: k8s,
|
|
455
471
|
version: k8s,
|
|
456
|
-
serverArgs: true
|
|
472
|
+
serverArgs: true,
|
|
473
|
+
charts: {
|
|
474
|
+
[RKE2_INGRESS_NGINX]: {},
|
|
475
|
+
[RKE2_TRAEFIK]: {}
|
|
476
|
+
}
|
|
457
477
|
}]
|
|
458
478
|
});
|
|
459
479
|
|
|
@@ -593,6 +613,7 @@ describe('component: rke2', () => {
|
|
|
593
613
|
repo: 'rancher-rke2-charts',
|
|
594
614
|
version: '3.12.200'
|
|
595
615
|
},
|
|
616
|
+
'rke2-traefik': {}
|
|
596
617
|
}
|
|
597
618
|
}
|
|
598
619
|
]
|
|
@@ -616,10 +637,10 @@ describe('component: rke2', () => {
|
|
|
616
637
|
|
|
617
638
|
describe('should correctly update NGINX configuration', () => {
|
|
618
639
|
const k8sVersion = 'v1.25.0+rke2r1';
|
|
619
|
-
const createWrapper = () => {
|
|
640
|
+
const createWrapper = (mode = _EDIT) => {
|
|
620
641
|
return shallowMount(rke2, {
|
|
621
642
|
props: {
|
|
622
|
-
mode
|
|
643
|
+
mode,
|
|
623
644
|
value: {
|
|
624
645
|
spec: {
|
|
625
646
|
...defaultSpec,
|
|
@@ -646,33 +667,47 @@ describe('component: rke2', () => {
|
|
|
646
667
|
},
|
|
647
668
|
});
|
|
648
669
|
};
|
|
670
|
+
const mockCharts = {
|
|
671
|
+
[RKE2_INGRESS_NGINX]: {},
|
|
672
|
+
[RKE2_TRAEFIK]: {}
|
|
673
|
+
};
|
|
649
674
|
|
|
650
|
-
it('should set ingress-controller to
|
|
651
|
-
const wrapper = createWrapper();
|
|
675
|
+
it('should set ingress-controller to traefik by default for new clusters', async() => {
|
|
676
|
+
const wrapper = createWrapper(_CREATE);
|
|
652
677
|
|
|
653
678
|
await wrapper.setData({
|
|
654
679
|
rke2Versions: [{
|
|
655
680
|
id: k8sVersion,
|
|
656
681
|
version: k8sVersion,
|
|
657
|
-
serverArgs: { disable: { options: [
|
|
682
|
+
serverArgs: { disable: { options: [RKE2_INGRESS_NGINX] } },
|
|
683
|
+
charts: mockCharts
|
|
658
684
|
}]
|
|
659
685
|
});
|
|
660
686
|
|
|
661
|
-
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBe(
|
|
687
|
+
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBe(TRAEFIK);
|
|
662
688
|
});
|
|
663
689
|
|
|
664
|
-
it('should set ingress-controller to
|
|
690
|
+
it('should set ingress-controller to None on version change when nginx is not supported', async() => {
|
|
665
691
|
const wrapper = createWrapper();
|
|
692
|
+
const newVersion = 'v1.26.0+rke2r1';
|
|
666
693
|
|
|
667
694
|
await wrapper.setData({
|
|
668
695
|
rke2Versions: [{
|
|
669
696
|
id: k8sVersion,
|
|
670
697
|
version: k8sVersion,
|
|
671
|
-
serverArgs: { disable: { options: [] } }
|
|
698
|
+
serverArgs: { disable: { options: [] } },
|
|
699
|
+
charts: mockCharts
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
id: newVersion,
|
|
703
|
+
version: newVersion,
|
|
704
|
+
serverArgs: { disable: { options: [] } },
|
|
705
|
+
charts: mockCharts
|
|
672
706
|
}]
|
|
673
707
|
});
|
|
674
|
-
|
|
675
|
-
|
|
708
|
+
wrapper.vm.value.spec.kubernetesVersion = newVersion;
|
|
709
|
+
(wrapper.vm as any).handleKubernetesChange(newVersion);
|
|
710
|
+
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBe(INGRESS_NONE);
|
|
676
711
|
});
|
|
677
712
|
|
|
678
713
|
it('should set ingress-controller to ingress-nginx on change when nginx is supported and not disabled', () => {
|
|
@@ -682,7 +717,8 @@ describe('component: rke2', () => {
|
|
|
682
717
|
rke2Versions: [{
|
|
683
718
|
id: k8sVersion,
|
|
684
719
|
version: k8sVersion,
|
|
685
|
-
serverArgs: { disable: { options: [
|
|
720
|
+
serverArgs: { disable: { options: [RKE2_INGRESS_NGINX] } },
|
|
721
|
+
charts: mockCharts
|
|
686
722
|
}]
|
|
687
723
|
});
|
|
688
724
|
|
|
@@ -691,36 +727,38 @@ describe('component: rke2', () => {
|
|
|
691
727
|
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBe(INGRESS_NGINX);
|
|
692
728
|
});
|
|
693
729
|
|
|
694
|
-
it('should set ingress-controller to
|
|
730
|
+
it('should set ingress-controller to None when nginx is supported but disabled', () => {
|
|
695
731
|
const wrapper = createWrapper();
|
|
696
732
|
|
|
697
733
|
wrapper.setData({
|
|
698
734
|
rke2Versions: [{
|
|
699
735
|
id: k8sVersion,
|
|
700
736
|
version: k8sVersion,
|
|
701
|
-
serverArgs: { disable: { options: [
|
|
737
|
+
serverArgs: { disable: { options: [RKE2_INGRESS_NGINX] } },
|
|
738
|
+
charts: mockCharts
|
|
702
739
|
}]
|
|
703
740
|
});
|
|
704
741
|
|
|
705
|
-
(wrapper.vm as any).handleEnabledSystemServicesChanged([
|
|
742
|
+
(wrapper.vm as any).handleEnabledSystemServicesChanged([RKE2_INGRESS_NGINX]);
|
|
706
743
|
|
|
707
|
-
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).
|
|
744
|
+
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBe(INGRESS_NONE);
|
|
708
745
|
});
|
|
709
746
|
|
|
710
|
-
it('should set ingress-controller to
|
|
747
|
+
it('should set ingress-controller for existing cluster to None when nginx is not supported', () => {
|
|
711
748
|
const wrapper = createWrapper();
|
|
712
749
|
|
|
713
750
|
wrapper.setData({
|
|
714
751
|
rke2Versions: [{
|
|
715
752
|
id: k8sVersion,
|
|
716
753
|
version: k8sVersion,
|
|
717
|
-
serverArgs: { disable: { options: [] } }
|
|
754
|
+
serverArgs: { disable: { options: [] } },
|
|
755
|
+
charts: mockCharts
|
|
718
756
|
}]
|
|
719
757
|
});
|
|
720
758
|
|
|
721
759
|
(wrapper.vm as any).handleEnabledSystemServicesChanged([]);
|
|
722
760
|
|
|
723
|
-
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).
|
|
761
|
+
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBe(INGRESS_NONE);
|
|
724
762
|
});
|
|
725
763
|
|
|
726
764
|
it('should correctly update disable list in serverConfig', () => {
|
|
@@ -730,7 +768,8 @@ describe('component: rke2', () => {
|
|
|
730
768
|
rke2Versions: [{
|
|
731
769
|
id: k8sVersion,
|
|
732
770
|
version: k8sVersion,
|
|
733
|
-
serverArgs: { disable: { options: [
|
|
771
|
+
serverArgs: { disable: { options: [RKE2_INGRESS_NGINX] } },
|
|
772
|
+
charts: mockCharts
|
|
734
773
|
}]
|
|
735
774
|
});
|
|
736
775
|
const disabledServices = ['other-service'];
|
|
@@ -749,12 +788,14 @@ describe('component: rke2', () => {
|
|
|
749
788
|
{
|
|
750
789
|
id: k8sVersion,
|
|
751
790
|
version: k8sVersion,
|
|
752
|
-
serverArgs: { disable: { options: [
|
|
791
|
+
serverArgs: { disable: { options: [RKE2_INGRESS_NGINX] } },
|
|
792
|
+
charts: mockCharts
|
|
753
793
|
},
|
|
754
794
|
{
|
|
755
795
|
id: newVersion,
|
|
756
796
|
version: newVersion,
|
|
757
|
-
serverArgs: { disable: { options: [
|
|
797
|
+
serverArgs: { disable: { options: [RKE2_INGRESS_NGINX] } },
|
|
798
|
+
charts: mockCharts
|
|
758
799
|
}
|
|
759
800
|
]
|
|
760
801
|
});
|
|
@@ -764,30 +805,5 @@ describe('component: rke2', () => {
|
|
|
764
805
|
|
|
765
806
|
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBe(INGRESS_NGINX);
|
|
766
807
|
});
|
|
767
|
-
|
|
768
|
-
it('should not set ingress-controller to ingress-nginx on version change when nginx is not supported', async() => {
|
|
769
|
-
const wrapper = createWrapper();
|
|
770
|
-
const newVersion = 'v1.26.0+rke2r1';
|
|
771
|
-
|
|
772
|
-
await wrapper.setData({
|
|
773
|
-
k3sVersions: [
|
|
774
|
-
{
|
|
775
|
-
id: k8sVersion,
|
|
776
|
-
version: k8sVersion,
|
|
777
|
-
serverArgs: { disable: { options: [] } }
|
|
778
|
-
},
|
|
779
|
-
{
|
|
780
|
-
id: newVersion,
|
|
781
|
-
version: newVersion,
|
|
782
|
-
serverArgs: { disable: { options: [] } }
|
|
783
|
-
}
|
|
784
|
-
]
|
|
785
|
-
});
|
|
786
|
-
|
|
787
|
-
wrapper.vm.value.spec.kubernetesVersion = newVersion;
|
|
788
|
-
(wrapper.vm as any).handleKubernetesChange(newVersion);
|
|
789
|
-
|
|
790
|
-
expect(wrapper.vm.value.spec.rkeConfig.machineGlobalConfig[INGRESS_CONTROLLER]).toBeUndefined();
|
|
791
|
-
});
|
|
792
808
|
});
|
|
793
809
|
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { _CREATE, _VIEW } from '@shell/config/query-params';
|
|
3
|
+
import { PropType } from 'vue';
|
|
4
|
+
import { useStore } from 'vuex';
|
|
5
|
+
import { useI18n } from '@shell/composables/useI18n';
|
|
6
|
+
import { RcItemCard, RcItemCardAction } from '@components/RcItemCard';
|
|
7
|
+
|
|
8
|
+
interface IngressCard {
|
|
9
|
+
id: string;
|
|
10
|
+
image?: any;
|
|
11
|
+
header: { title: { key: string } };
|
|
12
|
+
subHeader: { label: { key: string } };
|
|
13
|
+
content: { key: string };
|
|
14
|
+
doc?: {url: string};
|
|
15
|
+
selected?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
defineProps({
|
|
19
|
+
options: {
|
|
20
|
+
type: Array as PropType<IngressCard[]>,
|
|
21
|
+
required: true
|
|
22
|
+
},
|
|
23
|
+
mode: { type: String, default: _CREATE },
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const emit = defineEmits(['select']);
|
|
27
|
+
|
|
28
|
+
const store = useStore();
|
|
29
|
+
const { t } = useI18n(store);
|
|
30
|
+
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<div class="ingress-cards">
|
|
35
|
+
<rc-item-card
|
|
36
|
+
v-for="card in options"
|
|
37
|
+
:id="card.id"
|
|
38
|
+
:key="card.id"
|
|
39
|
+
:header="card.header"
|
|
40
|
+
:image="card.image"
|
|
41
|
+
:content="card.content"
|
|
42
|
+
:selected="card.selected"
|
|
43
|
+
variant="small"
|
|
44
|
+
role="link"
|
|
45
|
+
:disabled="mode === _VIEW"
|
|
46
|
+
:class="{ 'single-card': options.length === 1 }"
|
|
47
|
+
:clickable="mode !== _VIEW"
|
|
48
|
+
@card-click="emit('select', card.id)"
|
|
49
|
+
>
|
|
50
|
+
<template
|
|
51
|
+
v-once
|
|
52
|
+
#item-card-sub-header
|
|
53
|
+
>
|
|
54
|
+
<p class="ingress-card-sub-header">
|
|
55
|
+
{{ t(card.subHeader.label.key) }}
|
|
56
|
+
</p>
|
|
57
|
+
</template>
|
|
58
|
+
<template
|
|
59
|
+
v-if="!!card.doc"
|
|
60
|
+
v-once
|
|
61
|
+
#item-card-footer
|
|
62
|
+
>
|
|
63
|
+
<rc-item-card-action>
|
|
64
|
+
<a
|
|
65
|
+
:href="card.doc.url"
|
|
66
|
+
rel="nofollow noopener noreferrer"
|
|
67
|
+
target="_blank"
|
|
68
|
+
class="ingress-card-footer-button secondary-text-link"
|
|
69
|
+
>
|
|
70
|
+
{{ t('cluster.ingress.learnMore.label') }}
|
|
71
|
+
<i class="icon icon-external-link" />
|
|
72
|
+
<span class="sr-only">{{ t('generic.opensInNewTab') }}</span>
|
|
73
|
+
</a>
|
|
74
|
+
</rc-item-card-action>
|
|
75
|
+
</template>
|
|
76
|
+
</rc-item-card>
|
|
77
|
+
</div>
|
|
78
|
+
</template>
|
|
79
|
+
|
|
80
|
+
<style scoped lang="scss">
|
|
81
|
+
.ingress-cards{
|
|
82
|
+
display: grid;
|
|
83
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
84
|
+
grid-gap: var(--gap-md);
|
|
85
|
+
width: 100%;
|
|
86
|
+
height: max-content;
|
|
87
|
+
overflow: hidden;
|
|
88
|
+
|
|
89
|
+
.single-card {
|
|
90
|
+
max-width: 500px;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
.ingress-card-sub-header {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-wrap: wrap;
|
|
96
|
+
gap: var(--gap) var(--gap-md);
|
|
97
|
+
color: var(--link-text-secondary);
|
|
98
|
+
margin-bottom: 8px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
button.variant-ghost.ingress-card-footer-button {
|
|
102
|
+
padding: 0;
|
|
103
|
+
gap: 0;
|
|
104
|
+
min-height: 20px;
|
|
105
|
+
|
|
106
|
+
&:focus-visible {
|
|
107
|
+
border-color: var(--primary);
|
|
108
|
+
@include focus-outline;
|
|
109
|
+
outline-offset: -2px;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
</style>
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, watch } from 'vue';
|
|
3
|
+
import { _CREATE } from '@shell/config/query-params';
|
|
4
|
+
import { useStore } from 'vuex';
|
|
5
|
+
import { useI18n } from '@shell/composables/useI18n';
|
|
6
|
+
import LabeledInput from '@components/Form/LabeledInput/LabeledInput.vue';
|
|
7
|
+
import { INGRESS_DUAL, TRAEFIK, INGRESS_NGINX } from '@shell/edit/provisioning.cattle.io.cluster/shared';
|
|
8
|
+
import Checkbox from '@components/Form/Checkbox/Checkbox.vue';
|
|
9
|
+
import formRulesGenerator from '@shell/utils/validators/formRules';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
mode?: string;
|
|
13
|
+
ingressSelection: string;
|
|
14
|
+
}
|
|
15
|
+
const {
|
|
16
|
+
mode = _CREATE,
|
|
17
|
+
ingressSelection,
|
|
18
|
+
} = defineProps<Props>();
|
|
19
|
+
const store = useStore();
|
|
20
|
+
const { t } = useI18n(store);
|
|
21
|
+
|
|
22
|
+
const emit = defineEmits(['validation-changed']);
|
|
23
|
+
|
|
24
|
+
const compatibilityMode = defineModel<boolean>('compatibilityMode');
|
|
25
|
+
const nginxHttp = defineModel<number>('nginxHttp');
|
|
26
|
+
const nginxHttps = defineModel<number>('nginxHttps');
|
|
27
|
+
const traefikHttp = defineModel<number>('traefikHttp');
|
|
28
|
+
const traefikHttps = defineModel<number>('traefikHttps');
|
|
29
|
+
|
|
30
|
+
const nginxHttpRules = computed(() => {
|
|
31
|
+
const { portNumber, isInteger } = formRulesGenerator(t, { key: t('cluster.ingress.configurationOptions.nginx.http') });
|
|
32
|
+
const portRules = [(val: any) => !val ? undefined : isInteger(val), portNumber];
|
|
33
|
+
|
|
34
|
+
return [...portRules,
|
|
35
|
+
(val: any) => {
|
|
36
|
+
if (ingressSelection === INGRESS_DUAL && String(val) === String(traefikHttp.value)) {
|
|
37
|
+
return t('cluster.ingress.validation.portsMatch');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const nginxHttpsRules = computed(() => {
|
|
46
|
+
const { portNumber, isInteger } = formRulesGenerator(t, { key: t('cluster.ingress.configurationOptions.nginx.https') });
|
|
47
|
+
const portRules = [(val: any) => !val ? undefined : isInteger(val), portNumber];
|
|
48
|
+
|
|
49
|
+
return [...portRules,
|
|
50
|
+
(val: any) => {
|
|
51
|
+
if (ingressSelection === INGRESS_DUAL && String(val) === String(traefikHttps.value)) {
|
|
52
|
+
return t('cluster.ingress.validation.portsMatch');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const traefikHttpRules = computed(() => {
|
|
61
|
+
const { portNumber, isInteger } = formRulesGenerator(t, { key: t('cluster.ingress.configurationOptions.traefik.http') });
|
|
62
|
+
const portRules = [(val: any) => !val ? undefined : isInteger(val), portNumber];
|
|
63
|
+
|
|
64
|
+
return [...portRules, (val: any) => {
|
|
65
|
+
if (ingressSelection === INGRESS_DUAL && String(val) === String(nginxHttp.value)) {
|
|
66
|
+
return t('cluster.ingress.validation.portsMatch');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const traefikHttpsRules = computed(() => {
|
|
75
|
+
const { portNumber, isInteger } = formRulesGenerator(t, { key: t('cluster.ingress.configurationOptions.traefik.https') });
|
|
76
|
+
const portRules = [(val: any) => !val ? undefined : isInteger(val), portNumber];
|
|
77
|
+
|
|
78
|
+
return [...portRules, (val: any) => {
|
|
79
|
+
if (ingressSelection === INGRESS_DUAL && String(val) === String(nginxHttps.value)) {
|
|
80
|
+
return t('cluster.ingress.validation.portsMatch');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const isValid = computed(() => {
|
|
89
|
+
const check = (val: any, rules: any[]) => rules.every((rule) => rule(val) === undefined);
|
|
90
|
+
|
|
91
|
+
if (ingressSelection === INGRESS_DUAL) {
|
|
92
|
+
return check(nginxHttp.value, nginxHttpRules.value) && check(nginxHttps.value, nginxHttpsRules.value) &&
|
|
93
|
+
check(traefikHttp.value, traefikHttpRules.value) && check(traefikHttps.value, traefikHttpsRules.value);
|
|
94
|
+
}
|
|
95
|
+
if (ingressSelection === TRAEFIK) {
|
|
96
|
+
return check(traefikHttp.value, traefikHttpRules.value) && check(traefikHttps.value, traefikHttpsRules.value);
|
|
97
|
+
}
|
|
98
|
+
if (ingressSelection === INGRESS_NGINX) {
|
|
99
|
+
return check(nginxHttp.value, nginxHttpRules.value) && check(nginxHttps.value, nginxHttpsRules.value);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return true;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
watch(isValid, (val) => emit('validation-changed', val), { immediate: true });
|
|
106
|
+
</script>
|
|
107
|
+
<template>
|
|
108
|
+
<h4>{{ t('cluster.ingress.configurationOptions.title') }}</h4>
|
|
109
|
+
<Checkbox
|
|
110
|
+
v-if="ingressSelection === INGRESS_DUAL"
|
|
111
|
+
v-model:value="compatibilityMode"
|
|
112
|
+
label-key="cluster.ingress.configurationOptions.compatibilityMode"
|
|
113
|
+
class="mb-10"
|
|
114
|
+
/>
|
|
115
|
+
<div
|
|
116
|
+
v-if="ingressSelection === TRAEFIK || ingressSelection === INGRESS_DUAL"
|
|
117
|
+
class="row"
|
|
118
|
+
:class="ingressSelection === INGRESS_DUAL ? 'mb-10' : ''"
|
|
119
|
+
>
|
|
120
|
+
<div class="span-2 mr-20">
|
|
121
|
+
<LabeledInput
|
|
122
|
+
v-model:value="traefikHttp"
|
|
123
|
+
label-key="cluster.ingress.configurationOptions.traefik.http"
|
|
124
|
+
:mode="mode"
|
|
125
|
+
:rules="traefikHttpRules"
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="span-2">
|
|
129
|
+
<LabeledInput
|
|
130
|
+
v-model:value="traefikHttps"
|
|
131
|
+
label-key="cluster.ingress.configurationOptions.traefik.https"
|
|
132
|
+
:mode="mode"
|
|
133
|
+
:rules="traefikHttpsRules"
|
|
134
|
+
/>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
<div
|
|
138
|
+
v-if="ingressSelection === INGRESS_NGINX || ingressSelection === INGRESS_DUAL"
|
|
139
|
+
class="row"
|
|
140
|
+
>
|
|
141
|
+
<div class="span-2 mr-20">
|
|
142
|
+
<LabeledInput
|
|
143
|
+
v-model:value="nginxHttp"
|
|
144
|
+
label-key="cluster.ingress.configurationOptions.nginx.http"
|
|
145
|
+
:mode="mode"
|
|
146
|
+
:rules="nginxHttpRules"
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="span-2">
|
|
150
|
+
<LabeledInput
|
|
151
|
+
v-model:value="nginxHttps"
|
|
152
|
+
label-key="cluster.ingress.configurationOptions.nginx.https"
|
|
153
|
+
:mode="mode"
|
|
154
|
+
:rules="nginxHttpsRules"
|
|
155
|
+
/>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</template>
|