@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.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/apis/impl/apis.ts +6 -0
- package/apis/index.ts +26 -0
- package/apis/intf/resources-api/cluster-api.ts +18 -0
- package/apis/intf/resources-api/mgmt-api.ts +15 -0
- package/apis/intf/resources-api/resource-base.ts +107 -0
- package/apis/intf/resources-api/resource-constants.ts +147 -0
- package/apis/intf/resources-api/resources-api.ts +143 -0
- package/apis/intf/resources.ts +49 -0
- package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
- package/apis/intf/shell-api/proxy.ts +216 -0
- package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
- package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
- package/apis/intf/shell.ts +12 -6
- package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
- package/apis/resources/index.ts +22 -0
- package/apis/resources/resources-api-class.ts +187 -0
- package/apis/shell/__tests__/proxy.test.ts +369 -0
- package/apis/shell/index.ts +8 -1
- package/apis/shell/modal.ts +4 -1
- package/apis/shell/notifications.ts +9 -6
- package/apis/shell/proxy.ts +256 -0
- package/apis/shell/slide-in.ts +4 -1
- package/apis/vue-shim.d.ts +2 -1
- package/assets/data/aws-regions.json +4 -0
- package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/fonts/_fontstack.scss +132 -8
- package/assets/translations/en-us.yaml +22 -5
- package/chart/monitoring/index.vue +10 -1
- package/components/ActionDropdownShell.vue +2 -1
- package/components/CruResourceFooter.vue +9 -5
- package/components/ExplorerProjectsNamespaces.vue +1 -1
- package/components/InstallHelmCharts.vue +2 -2
- package/components/LandingPagePreference.vue +14 -5
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +15 -1
- package/components/Resource/Detail/Metadata/index.vue +6 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
- package/components/Resource/Detail/SpacedRow.vue +3 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -11
- package/components/ResourceList/Masthead.vue +12 -8
- package/components/SelectIconGrid.vue +0 -10
- package/components/SingleClusterInfo.vue +1 -0
- package/components/SortableTable/__tests__/sorting.test.ts +126 -0
- package/components/SortableTable/index.vue +6 -9
- package/components/SortableTable/selection.js +23 -5
- package/components/SortableTable/sorting.js +6 -3
- package/components/Wizard.vue +14 -13
- package/components/fleet/FleetBundles.vue +100 -12
- package/components/fleet/FleetClusterTargets/index.vue +37 -15
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +149 -115
- package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
- package/components/form/LabeledSelect.vue +20 -3
- package/components/form/NameNsDescription.vue +11 -0
- package/components/form/Security.vue +6 -2
- package/components/form/WorkloadPorts.vue +2 -7
- package/components/form/__tests__/Security.test.ts +76 -0
- package/components/formatter/Autoscaler.vue +4 -4
- package/components/formatter/ClusterKubeVersion.vue +27 -0
- package/components/formatter/ClusterLink.vue +1 -7
- package/components/formatter/ClusterProvider.vue +6 -10
- package/components/formatter/FleetSummaryGraph.vue +0 -3
- package/components/formatter/MachineSummaryGraph.vue +1 -1
- package/components/formatter/PodsUsage.vue +2 -2
- package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
- package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
- package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
- package/components/nav/NamespaceFilter.vue +2 -2
- package/components/nav/TopLevelMenu.helper.ts +15 -3
- package/components/nav/TopLevelMenu.vue +16 -5
- package/components/nav/__tests__/TopLevelMenu.test.ts +145 -21
- package/components/templates/home.vue +18 -0
- package/components/templates/plain.vue +18 -0
- package/components/templates/standalone.vue +17 -0
- package/composables/useFormValidation.ts +93 -0
- package/composables/useVeeValidateField.test.ts +159 -0
- package/composables/useVeeValidateField.ts +67 -0
- package/config/pagination-table-headers.js +18 -1
- package/config/product/manager.js +82 -21
- package/config/router/routes.js +6 -0
- package/config/table-headers.js +20 -1
- package/config/types.js +2 -1
- package/core/__tests__/plugin-products.test.ts +904 -20
- package/core/plugin-products-base.ts +107 -7
- package/core/plugin-products.ts +4 -0
- package/core/plugin-types.ts +111 -1
- package/core/plugin.ts +15 -7
- package/core/productDebugger.js +9 -4
- package/core/types-provisioning.ts +43 -30
- package/core/types.ts +57 -20
- package/detail/__tests__/pod.test.ts +41 -0
- package/detail/harvesterhci.io.management.cluster.vue +6 -2
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +4 -10
- package/edit/auth/__tests__/azuread.test.ts +217 -34
- package/edit/auth/azuread.vue +122 -14
- package/edit/auth/oidc.vue +2 -2
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
- package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
- package/edit/networking.k8s.io.ingress/index.vue +75 -20
- package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
- package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -4
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
- package/edit/secret/__tests__/ssh.test.ts +5 -6
- package/edit/secret/basic.vue +31 -0
- package/edit/secret/index.vue +68 -17
- package/edit/secret/registry.vue +38 -0
- package/edit/secret/ssh.vue +29 -0
- package/edit/secret/tls.vue +30 -0
- package/edit/service.vue +4 -4
- package/edit/workload/Upgrading.vue +3 -3
- package/edit/workload/__tests__/Upgrading.test.ts +6 -9
- package/edit/workload/mixins/workload.js +2 -1
- package/list/fleet.cattle.io.bundle.vue +7 -104
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
- package/list/provisioning.cattle.io.cluster.vue +262 -180
- package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
- package/mixins/__tests__/chart.test.ts +112 -0
- package/mixins/brand.js +2 -1
- package/mixins/chart.js +12 -8
- package/mixins/resource-fetch-api-pagination.js +41 -5
- package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
- package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
- package/models/__tests__/management.cattle.io.node.ts +6 -5
- package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +32 -11
- package/models/base-cluster.x-k8s.io.js +26 -0
- package/models/cluster.js +1 -1
- package/models/cluster.x-k8s.io.machine.js +4 -22
- package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
- package/models/cluster.x-k8s.io.machineset.js +2 -20
- package/models/compliance.cattle.io.clusterscan.js +130 -2
- package/models/ext.cattle.io.kubeconfig.ts +4 -7
- package/models/fleet-application.js +3 -1
- package/models/management.cattle.io.cluster.js +417 -40
- package/models/management.cattle.io.node.js +6 -4
- package/models/management.cattle.io.nodepool.js +1 -1
- package/models/networking.k8s.io.ingress.js +12 -4
- package/models/provisioning.cattle.io.cluster.js +47 -330
- package/models/rke.cattle.io.etcdsnapshot.js +1 -2
- package/package.json +11 -29
- package/pages/__tests__/readme.test.ts +49 -0
- package/pages/auth/setup.vue +2 -3
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
- package/pages/c/_cluster/apps/charts/chart.vue +60 -8
- package/pages/c/_cluster/apps/charts/install.vue +10 -7
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
- package/pages/c/_cluster/explorer/index.vue +5 -49
- package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
- package/pages/c/_cluster/istio/index.vue +21 -6
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +719 -2
- package/pages/c/_cluster/uiplugins/index.vue +203 -197
- package/pages/diagnostic.vue +13 -17
- package/pages/fail-whale.vue +18 -0
- package/pages/home.vue +77 -260
- package/pages/readme.vue +88 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +88 -0
- package/plugins/dashboard-store/actions.js +40 -18
- package/plugins/dashboard-store/resource-class.js +5 -2
- package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
- package/plugins/steve/steve-pagination-utils.ts +11 -3
- package/plugins/steve/subscribe.js +35 -5
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
- package/rancher-components/RcButton/RcButton.test.ts +37 -1
- package/rancher-components/RcButton/RcButton.vue +38 -8
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
- package/store/__tests__/catalog.test.ts +115 -1
- package/store/__tests__/type-map.test.ts +556 -1
- package/store/action-menu.js +8 -3
- package/store/auth.js +1 -1
- package/store/aws.js +27 -16
- package/store/catalog.js +27 -3
- package/store/digitalocean.js +20 -38
- package/store/index.js +2 -0
- package/store/linode.js +25 -40
- package/store/pnap.js +1 -0
- package/store/type-map.js +111 -29
- package/tsconfig.paths.json +8 -8
- package/types/kube/kube-api.ts +14 -1
- package/types/rancher/steve.api.ts +12 -12
- package/types/resources/settings.d.ts +2 -1
- package/types/shell/index.d.ts +102 -2
- package/types/store/dashboard-store.types.ts +108 -11
- package/types/store/pagination.types.ts +6 -3
- package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
- package/utils/__tests__/async.test.ts +87 -0
- package/utils/__tests__/aws.test.ts +140 -0
- package/utils/__tests__/banners.test.ts +176 -0
- package/utils/__tests__/chart.test.ts +64 -1
- package/utils/__tests__/color.test.ts +226 -0
- package/utils/__tests__/duration.test.ts +140 -0
- package/utils/__tests__/fleet.test.ts +340 -0
- package/utils/__tests__/ingress.test.ts +553 -0
- package/utils/__tests__/kube.test.ts +68 -0
- package/utils/__tests__/namespace-filter.test.ts +109 -0
- package/utils/__tests__/pagination-utils.test.ts +361 -0
- package/utils/__tests__/parse-externalid.test.ts +137 -0
- package/utils/__tests__/perf-setting.utils.test.ts +98 -0
- package/utils/__tests__/poller-sequential.test.ts +177 -0
- package/utils/__tests__/poller.test.ts +170 -0
- package/utils/__tests__/promise.test.ts +346 -0
- package/utils/__tests__/settings.test.ts +140 -0
- package/utils/__tests__/sort-utils.test.ts +301 -0
- package/utils/__tests__/string-utils.test.ts +798 -0
- package/utils/__tests__/string.test.ts +23 -1
- package/utils/__tests__/style.test.ts +154 -0
- package/utils/__tests__/svg-filter.test.ts +184 -0
- package/utils/__tests__/units.test.ts +417 -0
- package/utils/__tests__/versions.test.ts +128 -0
- package/utils/__tests__/xccdf.test.ts +391 -0
- package/utils/chart.js +36 -0
- package/utils/fleet.ts +13 -3
- package/utils/gatekeeper/__tests__/util.test.ts +174 -0
- package/utils/gc/__tests__/gc-interval.test.ts +119 -0
- package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
- package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
- package/utils/gc/__tests__/gc.test.ts +487 -0
- package/utils/ingress.ts +9 -1
- package/utils/pagination-utils.ts +2 -1
- package/utils/string.js +25 -2
- package/utils/uiplugins.ts +5 -5
- package/utils/validators/__tests__/cluster-name.test.ts +110 -0
- package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
- package/utils/validators/__tests__/index.test.ts +481 -0
- package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
- package/utils/validators/__tests__/misc-validators.test.ts +246 -0
- package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
- package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
- package/utils/validators/__tests__/role-template.test.ts +149 -0
- package/utils/validators/__tests__/service.test.ts +283 -0
- package/utils/validators/__tests__/setting.test.js +32 -0
- package/utils/validators/formRules/__tests__/index.test.ts +50 -0
- package/utils/validators/formRules/index.ts +5 -5
- package/utils/validators/machine-pool.ts +1 -1
- package/utils/validators/setting.js +18 -3
- package/utils/xccdf.ts +418 -0
- package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
|
@@ -167,11 +167,12 @@ describe('class MgmtNode', () => {
|
|
|
167
167
|
id: nodeId
|
|
168
168
|
}, {
|
|
169
169
|
...baseCtx,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
rootGetters: {
|
|
171
|
+
...baseCtx.rootGetters,
|
|
172
|
+
'management/byId': () => ({
|
|
173
|
+
id: mgmtClusterId,
|
|
174
|
+
provCluster: { nodes }
|
|
175
|
+
})
|
|
175
176
|
}
|
|
176
177
|
});
|
|
177
178
|
|
|
@@ -66,14 +66,15 @@ describe('class MgmtNodePool', () => {
|
|
|
66
66
|
const { spec, nodes } = data;
|
|
67
67
|
const mgmtNode = new MgmtNodePool({
|
|
68
68
|
spec,
|
|
69
|
-
|
|
69
|
+
metadata: {},
|
|
70
|
+
id: nodeId
|
|
70
71
|
}, {
|
|
71
72
|
...baseCtx,
|
|
72
73
|
getters: {
|
|
73
|
-
|
|
74
|
-
mgmtClusterId,
|
|
74
|
+
byId: () => ({
|
|
75
|
+
id: mgmtClusterId,
|
|
75
76
|
nodes
|
|
76
|
-
}
|
|
77
|
+
})
|
|
77
78
|
}
|
|
78
79
|
});
|
|
79
80
|
|
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
import ProvCluster from '@shell/models/provisioning.cattle.io.cluster';
|
|
2
|
+
import MgmtCluster from '@shell/models/management.cattle.io.cluster';
|
|
3
|
+
|
|
2
4
|
jest.mock('@shell/utils/provider', () => ({
|
|
3
5
|
isHostedProvider: jest.fn().mockImplementation((context, provider) => {
|
|
4
6
|
return ['GKE', 'EKS', 'AKS'].includes(provider);
|
|
5
7
|
})
|
|
6
8
|
}));
|
|
9
|
+
|
|
10
|
+
jest.mock('@shell/utils/clipboard', () => {
|
|
11
|
+
return { copyTextToClipboard: jest.fn(() => Promise.resolve({})) };
|
|
12
|
+
});
|
|
13
|
+
|
|
7
14
|
describe('class ProvCluster', () => {
|
|
8
15
|
const gkeClusterWithPrivateEndpoint = {
|
|
9
16
|
clusterName: 'test',
|
|
10
17
|
provisioner: 'GKE',
|
|
11
18
|
spec: { },
|
|
12
|
-
mgmt: { spec: { gkeConfig: { privateClusterConfig: { enablePrivateEndpoint: true } } } }
|
|
19
|
+
mgmt: new MgmtCluster({ spec: { gkeConfig: { privateClusterConfig: { enablePrivateEndpoint: true } } } }),
|
|
13
20
|
};
|
|
14
21
|
|
|
15
22
|
const eksClusterWithPrivateEndpoint = {
|
|
16
23
|
clusterName: 'test',
|
|
17
24
|
provisioner: 'EKS',
|
|
18
25
|
spec: { },
|
|
19
|
-
mgmt: { spec: { eksConfig: { privateAccess: true } } }
|
|
26
|
+
mgmt: new MgmtCluster({ spec: { eksConfig: { privateAccess: true } } }),
|
|
20
27
|
};
|
|
21
28
|
|
|
22
29
|
const aksClusterWithPrivateEndpoint = {
|
|
23
30
|
clusterName: 'test',
|
|
24
31
|
provisioner: 'AKS',
|
|
25
32
|
spec: { },
|
|
26
|
-
mgmt: { spec: { aksConfig: { privateCluster: true } } }
|
|
33
|
+
mgmt: new MgmtCluster({ spec: { aksConfig: { privateCluster: true } } }),
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
// Related to https://github.com/rancher/dashboard/issues/9402
|
|
@@ -41,10 +48,14 @@ describe('class ProvCluster', () => {
|
|
|
41
48
|
it.each(testCases)('should return the isHostedKubernetesProvider and isPrivateHostedProvider values properly based on the props data', (clusterData: Object, expected: Boolean) => {
|
|
42
49
|
const cluster = new ProvCluster({ spec: clusterData.spec });
|
|
43
50
|
|
|
51
|
+
jest.spyOn(clusterData.mgmt, 'provCluster', 'get').mockReturnValue(
|
|
52
|
+
clusterData
|
|
53
|
+
);
|
|
54
|
+
|
|
44
55
|
jest.spyOn(cluster, 'mgmt', 'get').mockReturnValue(
|
|
45
56
|
clusterData.mgmt
|
|
46
57
|
);
|
|
47
|
-
jest.spyOn(
|
|
58
|
+
jest.spyOn(clusterData.mgmt, 'provisioner', 'get').mockReturnValue(
|
|
48
59
|
clusterData.provisioner
|
|
49
60
|
);
|
|
50
61
|
|
|
@@ -54,6 +65,7 @@ describe('class ProvCluster', () => {
|
|
|
54
65
|
resetMocks();
|
|
55
66
|
});
|
|
56
67
|
});
|
|
68
|
+
|
|
57
69
|
describe('isImported', () => {
|
|
58
70
|
const testCases = [
|
|
59
71
|
{
|
|
@@ -114,7 +126,8 @@ describe('class ProvCluster', () => {
|
|
|
114
126
|
clusterData: {
|
|
115
127
|
isLocal: false,
|
|
116
128
|
isHostedKubernetesProvider: true,
|
|
117
|
-
providerConfig: { imported: true }
|
|
129
|
+
providerConfig: { imported: true },
|
|
130
|
+
mgmt: { status: { provider: '', driver: 'EKS' } }
|
|
118
131
|
},
|
|
119
132
|
expected: true
|
|
120
133
|
},
|
|
@@ -123,7 +136,8 @@ describe('class ProvCluster', () => {
|
|
|
123
136
|
clusterData: {
|
|
124
137
|
isLocal: false,
|
|
125
138
|
isHostedKubernetesProvider: true,
|
|
126
|
-
providerConfig: { imported: false }
|
|
139
|
+
providerConfig: { imported: false },
|
|
140
|
+
mgmt: { status: { provider: '', driver: 'EKS' } }
|
|
127
141
|
},
|
|
128
142
|
expected: false
|
|
129
143
|
},
|
|
@@ -150,23 +164,27 @@ describe('class ProvCluster', () => {
|
|
|
150
164
|
};
|
|
151
165
|
|
|
152
166
|
it.each(testCases)('$description', ({ clusterData, expected }) => {
|
|
167
|
+
const mgmtCluster = new MgmtCluster(clusterData.mgmt || {});
|
|
153
168
|
const cluster = new ProvCluster({});
|
|
154
169
|
|
|
155
170
|
// Mock getters
|
|
156
171
|
jest.spyOn(cluster, 'mgmt', 'get').mockReturnValue(
|
|
157
|
-
|
|
172
|
+
mgmtCluster
|
|
173
|
+
);
|
|
174
|
+
jest.spyOn(mgmtCluster, 'provCluster', 'get').mockReturnValue(
|
|
175
|
+
cluster
|
|
158
176
|
);
|
|
159
177
|
if (clusterData.isLocal !== undefined) {
|
|
160
|
-
jest.spyOn(
|
|
178
|
+
jest.spyOn(mgmtCluster, 'isLocal', 'get').mockReturnValue(clusterData.isLocal);
|
|
161
179
|
}
|
|
162
180
|
if (clusterData.isHostedKubernetesProvider !== undefined) {
|
|
163
|
-
jest.spyOn(
|
|
181
|
+
jest.spyOn(mgmtCluster, 'isHostedKubernetesProvider', 'get').mockReturnValue(clusterData.isHostedKubernetesProvider);
|
|
164
182
|
}
|
|
165
183
|
if (clusterData.providerConfig !== undefined) {
|
|
166
184
|
jest.spyOn(cluster, 'providerConfig', 'get').mockReturnValue(clusterData.providerConfig);
|
|
167
185
|
}
|
|
168
186
|
if (clusterData.provisioner !== undefined) {
|
|
169
|
-
jest.spyOn(
|
|
187
|
+
jest.spyOn(mgmtCluster, 'provisioner', 'get').mockReturnValue(clusterData.provisioner);
|
|
170
188
|
}
|
|
171
189
|
|
|
172
190
|
expect(cluster.isImported).toBe(expected);
|
|
@@ -268,7 +286,10 @@ describe('class ProvCluster', () => {
|
|
|
268
286
|
|
|
269
287
|
it.each(testCases)('should return the hasError value properly based on the "status.conditions" props data for testcase %p', (testName: string, conditions: Array, expected: Boolean) => {
|
|
270
288
|
const ctx = { rootGetters: { 'management/byId': jest.fn() } };
|
|
271
|
-
const
|
|
289
|
+
const mgmtCluster = new MgmtCluster({ status: { conditions } }, ctx);
|
|
290
|
+
const cluster = new ProvCluster({}, ctx);
|
|
291
|
+
|
|
292
|
+
jest.spyOn(cluster, 'mgmt', 'get').mockReturnValue(mgmtCluster);
|
|
272
293
|
|
|
273
294
|
expect(cluster.hasError).toBe(expected);
|
|
274
295
|
resetMocks();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { escapeHtml } from '@shell/utils/string';
|
|
2
|
+
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
3
|
+
import { CAPI } from '@shell/config/types';
|
|
4
|
+
|
|
5
|
+
export default class CapiMachineRoot extends SteveModel {
|
|
6
|
+
get cluster() {
|
|
7
|
+
if ( !this.spec.clusterName ) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// This is used to get the cluster's human name
|
|
12
|
+
// Ideally we get this via the management cluster. To find it though we have to go via the provisioning cluster. So might as well just use that
|
|
13
|
+
|
|
14
|
+
const clusterId = `${ this.metadata.namespace }/${ this.spec.clusterName }`;
|
|
15
|
+
|
|
16
|
+
return this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get clusterName() {
|
|
20
|
+
return this.cluster?.nameDisplay || this.spec.clusterName;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get groupByLabel() {
|
|
24
|
+
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(this.clusterName) });
|
|
25
|
+
}
|
|
26
|
+
}
|
package/models/cluster.js
CHANGED
|
@@ -69,6 +69,6 @@ export default class NormanCluster extends NormanModel {
|
|
|
69
69
|
const id = this.provisioningClusterId;
|
|
70
70
|
|
|
71
71
|
return id && !!this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, id);
|
|
72
|
-
}, this.$rootGetters['i18n/t']('cluster.managementTimeout'), timeout, interval);
|
|
72
|
+
}, this.$rootGetters['i18n/t']('cluster.managementTimeout', { type: CAPI.RANCHER_CLUSTER, name: this.provisioningClusterId }), timeout, interval);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -2,11 +2,10 @@ import { ADDRESSES, CAPI, NODE } from '@shell/config/types';
|
|
|
2
2
|
import { CAPI as CAPI_LABELS, MACHINE_ROLES } from '@shell/config/labels-annotations';
|
|
3
3
|
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
4
4
|
import { listNodeRoles } from '@shell/models/cluster/node';
|
|
5
|
-
import { escapeHtml } from '@shell/utils/string';
|
|
6
5
|
import { insertAt, findBy } from '@shell/utils/array';
|
|
7
6
|
import { get } from '@shell/utils/object';
|
|
8
7
|
import { downloadUrl } from '@shell/utils/download';
|
|
9
|
-
import
|
|
8
|
+
import CapiMachineRoot from '@shell/models/base-cluster.x-k8s.io';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Prevent scaling down control plane or etcd machines to zero
|
|
@@ -53,7 +52,8 @@ export function notOnlyOfRole(current, all) {
|
|
|
53
52
|
|
|
54
53
|
return false;
|
|
55
54
|
}
|
|
56
|
-
|
|
55
|
+
|
|
56
|
+
export default class CapiMachine extends CapiMachineRoot {
|
|
57
57
|
get _availableActions() {
|
|
58
58
|
const out = super._availableActions;
|
|
59
59
|
|
|
@@ -144,18 +144,6 @@ export default class CapiMachine extends SteveModel {
|
|
|
144
144
|
return await this.$dispatch('find', { type: kind, id });
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
get cluster() {
|
|
148
|
-
if ( !this.spec.clusterName ) {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const clusterId = `${ this.metadata.namespace }/${ this.spec.clusterName }`;
|
|
153
|
-
|
|
154
|
-
const cluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
|
|
155
|
-
|
|
156
|
-
return cluster;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
147
|
get poolName() {
|
|
160
148
|
return this.metadata?.labels?.[ CAPI_LABELS.DEPLOYMENT_NAME ] || '';
|
|
161
149
|
}
|
|
@@ -182,7 +170,7 @@ export default class CapiMachine extends SteveModel {
|
|
|
182
170
|
return {
|
|
183
171
|
name: 'c-cluster-product-resource-id',
|
|
184
172
|
params: {
|
|
185
|
-
cluster
|
|
173
|
+
cluster,
|
|
186
174
|
product: EXPLORER,
|
|
187
175
|
resource: NODE,
|
|
188
176
|
id: kubeId
|
|
@@ -193,12 +181,6 @@ export default class CapiMachine extends SteveModel {
|
|
|
193
181
|
return kubeId;
|
|
194
182
|
}
|
|
195
183
|
|
|
196
|
-
get groupByLabel() {
|
|
197
|
-
const name = this.cluster?.nameDisplay || this.spec.clusterName;
|
|
198
|
-
|
|
199
|
-
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(name) });
|
|
200
|
-
}
|
|
201
|
-
|
|
202
184
|
get labels() {
|
|
203
185
|
return this.metadata?.labels || {};
|
|
204
186
|
}
|
|
@@ -1,33 +1,15 @@
|
|
|
1
1
|
import { CAPI } from '@shell/config/types';
|
|
2
2
|
import { escapeHtml } from '@shell/utils/string';
|
|
3
3
|
import { sortBy } from '@shell/utils/sort';
|
|
4
|
-
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
5
4
|
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
6
5
|
import { handleConflict } from '@shell/plugins/dashboard-store/normalize';
|
|
7
6
|
import { CAPI as CAPI_ANNOTATIONS, MACHINE_ROLES } from '@shell/config/labels-annotations';
|
|
8
7
|
import { notOnlyOfRole } from '@shell/models/cluster.x-k8s.io.machine';
|
|
9
8
|
import { KIND } from '../config/elemental-types';
|
|
10
9
|
import { KIND as HARVESTER_KIND } from '../config/harvester-manager-types';
|
|
10
|
+
import CapiMachineRoot from '@shell/models/base-cluster.x-k8s.io';
|
|
11
11
|
|
|
12
|
-
export default class CapiMachineDeployment extends
|
|
13
|
-
get cluster() {
|
|
14
|
-
if ( !this.spec.clusterName ) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const clusterId = `${ this.metadata.namespace }/${ this.spec.clusterName }`;
|
|
19
|
-
|
|
20
|
-
const cluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
|
|
21
|
-
|
|
22
|
-
return cluster;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get groupByLabel() {
|
|
26
|
-
const name = this.cluster?.nameDisplay || this.spec.clusterName;
|
|
27
|
-
|
|
28
|
-
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(name) });
|
|
29
|
-
}
|
|
30
|
-
|
|
12
|
+
export default class CapiMachineDeployment extends CapiMachineRoot {
|
|
31
13
|
get groupByPoolLabel() {
|
|
32
14
|
return `${ this.$rootGetters['i18n/t']('resourceTable.groupLabel.machinePool', { name: escapeHtml(this.nameDisplay) }) }`;
|
|
33
15
|
}
|
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
import { CAPI } from '@shell/config/types';
|
|
2
|
-
import { escapeHtml } from '@shell/utils/string';
|
|
3
|
-
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
4
1
|
|
|
5
|
-
|
|
6
|
-
get cluster() {
|
|
7
|
-
if ( !this.spec.clusterName ) {
|
|
8
|
-
return null;
|
|
9
|
-
}
|
|
2
|
+
import CapiMachineRoot from '@shell/models/base-cluster.x-k8s.io';
|
|
10
3
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const cluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
|
|
14
|
-
|
|
15
|
-
return cluster;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get groupByLabel() {
|
|
19
|
-
const name = this.cluster?.nameDisplay || this.spec.clusterName;
|
|
20
|
-
|
|
21
|
-
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(name) });
|
|
22
|
-
}
|
|
4
|
+
export default class CapiMachineSet extends CapiMachineRoot {
|
|
23
5
|
}
|
|
@@ -65,8 +65,29 @@ export default class ClusterScan extends SteveModel {
|
|
|
65
65
|
total: 1,
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
+
const downloadReportXCCDF = {
|
|
69
|
+
action: 'downloadLatestReportXCCDF',
|
|
70
|
+
enabled: this.hasReport,
|
|
71
|
+
icon: 'icon icon-download',
|
|
72
|
+
label: t('compliance.downloadReportXCCDF'),
|
|
73
|
+
total: 1,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const downloadAllReportsXCCDF = {
|
|
77
|
+
action: 'downloadAllReportsXCCDF',
|
|
78
|
+
enabled: this.hasReport,
|
|
79
|
+
icon: 'icon icon-download',
|
|
80
|
+
label: t('compliance.downloadAllReportsXCCDF'),
|
|
81
|
+
total: 1,
|
|
82
|
+
};
|
|
83
|
+
|
|
68
84
|
if (this.hasReports) {
|
|
69
85
|
out.unshift({ divider: true });
|
|
86
|
+
if (this.spec?.scheduledScanConfig?.cronSchedule) {
|
|
87
|
+
out.unshift(downloadAllReportsXCCDF);
|
|
88
|
+
downloadReportXCCDF.label = t('compliance.downloadLatestReportXCCDF');
|
|
89
|
+
}
|
|
90
|
+
out.unshift(downloadReportXCCDF);
|
|
70
91
|
if (this.spec?.scheduledScanConfig?.cronSchedule) {
|
|
71
92
|
out.unshift(downloadAllReports);
|
|
72
93
|
downloadReport.label = t('compliance.downloadLatestReport');
|
|
@@ -121,7 +142,7 @@ export default class ClusterScan extends SteveModel {
|
|
|
121
142
|
|
|
122
143
|
downloadFile(`${ labelFor(report) }.csv`, csv, 'application/csv');
|
|
123
144
|
} catch (err) {
|
|
124
|
-
this.$dispatch('growl/fromError', { title: '
|
|
145
|
+
this.$dispatch('growl/fromError', { title: this.t('compliance.scan.errorDownload'), err }, { root: true });
|
|
125
146
|
}
|
|
126
147
|
}
|
|
127
148
|
|
|
@@ -143,7 +164,7 @@ export default class ClusterScan extends SteveModel {
|
|
|
143
164
|
|
|
144
165
|
toZip[`${ labelFor(report) }.csv`] = csv;
|
|
145
166
|
} catch (err) {
|
|
146
|
-
this.$dispatch('growl/fromError', { title: '
|
|
167
|
+
this.$dispatch('growl/fromError', { title: this.t('compliance.scan.errorDownload'), err }, { root: true });
|
|
147
168
|
}
|
|
148
169
|
});
|
|
149
170
|
if (!isEmpty(toZip)) {
|
|
@@ -153,6 +174,113 @@ export default class ClusterScan extends SteveModel {
|
|
|
153
174
|
}
|
|
154
175
|
}
|
|
155
176
|
|
|
177
|
+
async _resolveBenchmark() {
|
|
178
|
+
const profileName = this.status?.lastRunScanProfileName;
|
|
179
|
+
|
|
180
|
+
if (!profileName) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const profile = await this.$dispatch('find', { type: COMPLIANCE.CLUSTER_SCAN_PROFILE, id: profileName });
|
|
184
|
+
const benchmarkId = profile?.spec?.benchmarkVersion;
|
|
185
|
+
|
|
186
|
+
if (!benchmarkId) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return this.$dispatch('find', { type: COMPLIANCE.BENCHMARK, id: benchmarkId });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async downloadLatestReportXCCDF() {
|
|
194
|
+
const reports = await this.getReports() || [];
|
|
195
|
+
const report = sortBy(reports, 'metadata.creationTimestamp', true)[0];
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
const benchmark = await this._resolveBenchmark();
|
|
199
|
+
const { generateXCCDFPerNode } = await import(/* webpackChunkName: "xccdf" */'@shell/utils/xccdf');
|
|
200
|
+
|
|
201
|
+
const parsed = report.parsedReport || {};
|
|
202
|
+
const common = {
|
|
203
|
+
report: parsed,
|
|
204
|
+
benchmarkVersion: parsed.version || benchmark?.spec?.benchmarkVersion || '',
|
|
205
|
+
metadata: benchmark?.spec?.benchmarkMetadata || {},
|
|
206
|
+
stigChecks: benchmark?.spec?.stigChecks || {},
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const toZip = {};
|
|
210
|
+
|
|
211
|
+
if (!Object.entries(parsed.nodes || {}).length) {
|
|
212
|
+
this.$dispatch('growl/fromError', { title: this.t('compliance.scan.errorNoParsedNodes') }, { root: true });
|
|
213
|
+
} else {
|
|
214
|
+
Object.entries(parsed.nodes || {}).forEach(([role, hosts]) => {
|
|
215
|
+
(hosts || []).forEach((hostname) => {
|
|
216
|
+
const xml = generateXCCDFPerNode({
|
|
217
|
+
...common, hostname, role,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
toZip[`${ labelFor(report) }--${ hostname }.xml`] = xml;
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
if (!isEmpty(toZip)) {
|
|
225
|
+
const zip = await generateZip(toZip);
|
|
226
|
+
|
|
227
|
+
downloadFile(`${ labelFor(report) }-per-node.zip`, zip, 'application/zip');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
} catch (err) {
|
|
231
|
+
this.$dispatch('growl/fromError', { title: this.t('compliance.scan.errorDownload'), err }, { root: true });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async downloadAllReportsXCCDF() {
|
|
236
|
+
const toZip = {};
|
|
237
|
+
const reports = await this.getReports() || [];
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const benchmark = await this._resolveBenchmark();
|
|
241
|
+
const { generateXCCDFPerNode } = await import(/* webpackChunkName: "xccdf" */'@shell/utils/xccdf');
|
|
242
|
+
|
|
243
|
+
const hasParsedNodes = reports.some((report) => Object.entries(report.parsedReport?.nodes || {}).length);
|
|
244
|
+
|
|
245
|
+
if (!hasParsedNodes) {
|
|
246
|
+
this.$dispatch('growl/fromError', { title: this.t('compliance.scan.errorNoParsedNodes') }, { root: true });
|
|
247
|
+
} else {
|
|
248
|
+
reports.forEach((report) => {
|
|
249
|
+
try {
|
|
250
|
+
const parsed = report.parsedReport || {};
|
|
251
|
+
const common = {
|
|
252
|
+
report: parsed,
|
|
253
|
+
benchmarkVersion: parsed.version || benchmark?.spec?.benchmarkVersion || '',
|
|
254
|
+
metadata: benchmark?.spec?.benchmarkMetadata || {},
|
|
255
|
+
stigChecks: benchmark?.spec?.stigChecks || {},
|
|
256
|
+
};
|
|
257
|
+
const folder = labelFor(report);
|
|
258
|
+
|
|
259
|
+
Object.entries(parsed.nodes || {}).forEach(([role, hosts]) => {
|
|
260
|
+
(hosts || []).forEach((hostname) => {
|
|
261
|
+
const xml = generateXCCDFPerNode({
|
|
262
|
+
...common, hostname, role,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
toZip[`${ folder }/${ hostname }.xml`] = xml;
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
} catch (err) {
|
|
269
|
+
this.$dispatch('growl/fromError', { title: this.t('compliance.scan.errorDownload'), err }, { root: true });
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
if (!isEmpty(toZip)) {
|
|
274
|
+
generateZip(toZip).then((zip) => {
|
|
275
|
+
downloadFile(`${ this.id }-reports-xccdf-per-node.zip`, zip, 'application/zip');
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
} catch (err) {
|
|
280
|
+
this.$dispatch('growl/fromError', { title: this.t('compliance.scan.errorDownload'), err }, { root: true });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
156
284
|
get scanProfileLink() {
|
|
157
285
|
if (this.status?.lastRunScanProfileName) {
|
|
158
286
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MANAGEMENT } from '@shell/config/types';
|
|
2
2
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
3
3
|
import { Location } from 'vue-router';
|
|
4
4
|
|
|
@@ -49,16 +49,13 @@ export default class Kubeconfig extends SteveModel {
|
|
|
49
49
|
*/
|
|
50
50
|
get referencedClusters(): ReferencedCluster[] {
|
|
51
51
|
const clusterIds = this.spec?.clusters || [];
|
|
52
|
-
const provClusters = this.$rootGetters['management/all'](CAPI.RANCHER_CLUSTER) || [];
|
|
53
|
-
const mgmtClusters = this.$rootGetters['management/all'](MANAGEMENT.CLUSTER) || [];
|
|
54
52
|
|
|
55
53
|
return clusterIds.map((id: string) => {
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const cluster = provCluster || mgmtCluster;
|
|
54
|
+
const mgmtCluster = this.$rootGetters['management/byId'](MANAGEMENT.CLUSTER, id);
|
|
55
|
+
const provCluster = mgmtCluster?.provCluster;
|
|
59
56
|
|
|
60
57
|
return {
|
|
61
|
-
label:
|
|
58
|
+
label: mgmtCluster?.nameDisplay || this.t('"ext.cattle.io.kubeconfig".deleted', { name: id }),
|
|
62
59
|
location: provCluster?.detailLocation || mgmtCluster?.detailLocation || null
|
|
63
60
|
};
|
|
64
61
|
});
|
|
@@ -7,6 +7,7 @@ import { addObject, addObjects, findBy } from '@shell/utils/array';
|
|
|
7
7
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
8
8
|
import { mapStateToEnum, primaryDisplayStatusFromCount, STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
9
9
|
import FleetUtils from '@shell/utils/fleet';
|
|
10
|
+
import { HARVESTER_CONTAINER } from '@shell/store/features';
|
|
10
11
|
|
|
11
12
|
function normalizeStateCounts(data) {
|
|
12
13
|
if (isEmpty(data)) {
|
|
@@ -138,7 +139,8 @@ export default class FleetApplication extends SteveModel {
|
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
get targetInfo() {
|
|
141
|
-
const
|
|
142
|
+
const areHarvesterHostsVisible = this.$rootGetters['features/get'](HARVESTER_CONTAINER);
|
|
143
|
+
const mode = FleetUtils.Application.getTargetMode(this.spec.targets || [], this.metadata.namespace, areHarvesterHostsVisible);
|
|
142
144
|
|
|
143
145
|
return {
|
|
144
146
|
mode,
|