mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Full support for ReplicaSets (#1704)
Signed-off-by: vshakirova <vshakirova@mirantis.com>
This commit is contained in:
parent
d961d8b159
commit
d143b234b7
@ -273,6 +273,12 @@ describe("Lens integration tests", () => {
|
|||||||
expectedSelector: "h5.title",
|
expectedSelector: "h5.title",
|
||||||
expectedText: "Stateful Sets"
|
expectedText: "Stateful Sets"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ReplicaSets",
|
||||||
|
href: "replicasets",
|
||||||
|
expectedSelector: "h5.title",
|
||||||
|
expectedText: "Replica Sets"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Jobs",
|
name: "Jobs",
|
||||||
href: "jobs",
|
href: "jobs",
|
||||||
|
|||||||
@ -223,6 +223,7 @@ msgstr "Affinities"
|
|||||||
#: src/renderer/components/+workloads-pods/pods.tsx:78
|
#: src/renderer/components/+workloads-pods/pods.tsx:78
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:51
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:51
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:41
|
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:41
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:56
|
||||||
msgid "Age"
|
msgid "Age"
|
||||||
msgstr "Age"
|
msgstr "Age"
|
||||||
|
|
||||||
@ -766,6 +767,10 @@ msgstr "Cron Jobs"
|
|||||||
msgid "CronJobs"
|
msgid "CronJobs"
|
||||||
msgstr "CronJobs"
|
msgstr "CronJobs"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:54
|
||||||
|
msgid "Current"
|
||||||
|
msgstr "Current"
|
||||||
|
|
||||||
#: src/renderer/components/+config-autoscalers/hpa-details.tsx:50
|
#: src/renderer/components/+config-autoscalers/hpa-details.tsx:50
|
||||||
msgid "Current / Target"
|
msgid "Current / Target"
|
||||||
msgstr "Current / Target"
|
msgstr "Current / Target"
|
||||||
@ -777,6 +782,7 @@ msgstr "Current Healthy"
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:101
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:101
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:103
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:103
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:104
|
||||||
msgid "Current replica scale: {currentReplicas}"
|
msgid "Current replica scale: {currentReplicas}"
|
||||||
msgstr "Current replica scale: {currentReplicas}"
|
msgstr "Current replica scale: {currentReplicas}"
|
||||||
|
|
||||||
@ -861,6 +867,10 @@ msgstr "Deployments"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Description"
|
msgstr "Description"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:53
|
||||||
|
msgid "Desired"
|
||||||
|
msgstr "Desired"
|
||||||
|
|
||||||
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx:42
|
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx:42
|
||||||
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx:41
|
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx:41
|
||||||
msgid "Desired Healthy"
|
msgid "Desired Healthy"
|
||||||
@ -868,6 +878,7 @@ msgstr "Desired Healthy"
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:105
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:105
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:107
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:107
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:108
|
||||||
msgid "Desired number of replicas"
|
msgid "Desired number of replicas"
|
||||||
msgstr "Desired number of replicas"
|
msgstr "Desired number of replicas"
|
||||||
|
|
||||||
@ -1132,6 +1143,7 @@ msgstr "Hide"
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:127
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:127
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:116
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:116
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:131
|
||||||
msgid "High number of replicas may cause cluster performance issues"
|
msgid "High number of replicas may cause cluster performance issues"
|
||||||
msgstr "High number of replicas may cause cluster performance issues"
|
msgstr "High number of replicas may cause cluster performance issues"
|
||||||
|
|
||||||
@ -1583,6 +1595,7 @@ msgstr "Mounts"
|
|||||||
#: src/renderer/components/+workspaces/workspaces.tsx:135
|
#: src/renderer/components/+workspaces/workspaces.tsx:135
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:89
|
#: src/renderer/components/dock/edit-resource.tsx:89
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Name"
|
msgstr "Name"
|
||||||
|
|
||||||
@ -1632,6 +1645,7 @@ msgstr "Names"
|
|||||||
#: src/renderer/components/item-object-list/page-filters-select.tsx:57
|
#: src/renderer/components/item-object-list/page-filters-select.tsx:57
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:23
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:23
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:144
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:144
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
||||||
msgid "Namespace"
|
msgid "Namespace"
|
||||||
msgstr "Namespace"
|
msgstr "Namespace"
|
||||||
|
|
||||||
@ -2041,6 +2055,7 @@ msgstr "Read-only Root Filesystem"
|
|||||||
msgid "Readiness"
|
msgid "Readiness"
|
||||||
msgstr "Readiness"
|
msgstr "Readiness"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:55
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:145
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:145
|
||||||
msgid "Ready"
|
msgid "Ready"
|
||||||
msgstr "Ready"
|
msgstr "Ready"
|
||||||
@ -2156,6 +2171,10 @@ msgstr "Removing helm branch <0>{0}</0> has failed: {1}"
|
|||||||
msgid "Replicas"
|
msgid "Replicas"
|
||||||
msgstr "Replicas"
|
msgstr "Replicas"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads/workloads.tsx:70
|
||||||
|
msgid "ReplicaSets"
|
||||||
|
msgstr "ReplicaSets"
|
||||||
|
|
||||||
#: src/renderer/components/dock/install-chart.tsx:119
|
#: src/renderer/components/dock/install-chart.tsx:119
|
||||||
msgid "Repo/Name"
|
msgid "Repo/Name"
|
||||||
msgstr "Repo/Name"
|
msgstr "Repo/Name"
|
||||||
@ -2347,6 +2366,7 @@ msgstr "Save"
|
|||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:128
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:128
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:83
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:83
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:84
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:84
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:160
|
||||||
msgid "Scale"
|
msgid "Scale"
|
||||||
msgstr "Scale"
|
msgstr "Scale"
|
||||||
|
|
||||||
@ -2354,6 +2374,10 @@ msgstr "Scale"
|
|||||||
msgid "Scale Deployment <0>{deploymentName}</0>"
|
msgid "Scale Deployment <0>{deploymentName}</0>"
|
||||||
msgstr "Scale Deployment <0>{deploymentName}</0>"
|
msgstr "Scale Deployment <0>{deploymentName}</0>"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:143
|
||||||
|
msgid "Scale Replica Set <0>{replicaSetName}</0>"
|
||||||
|
msgstr "Scale Replica Set <0>{replicaSetName}</0>"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:139
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:139
|
||||||
msgid "Scale Stateful Set <0>{statefulSetName}</0>"
|
msgid "Scale Stateful Set <0>{statefulSetName}</0>"
|
||||||
msgstr "Scale Stateful Set <0>{statefulSetName}</0>"
|
msgstr "Scale Stateful Set <0>{statefulSetName}</0>"
|
||||||
|
|||||||
@ -222,6 +222,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/+workloads-pods/pods.tsx:78
|
#: src/renderer/components/+workloads-pods/pods.tsx:78
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:51
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:51
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:41
|
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:41
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:56
|
||||||
msgid "Age"
|
msgid "Age"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -761,6 +762,10 @@ msgstr ""
|
|||||||
msgid "CronJobs"
|
msgid "CronJobs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:54
|
||||||
|
msgid "Current"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+config-autoscalers/hpa-details.tsx:50
|
#: src/renderer/components/+config-autoscalers/hpa-details.tsx:50
|
||||||
msgid "Current / Target"
|
msgid "Current / Target"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -772,6 +777,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:101
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:101
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:103
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:103
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:104
|
||||||
msgid "Current replica scale: {currentReplicas}"
|
msgid "Current replica scale: {currentReplicas}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -856,6 +862,10 @@ msgstr ""
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:53
|
||||||
|
msgid "Desired"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx:42
|
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx:42
|
||||||
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx:41
|
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx:41
|
||||||
msgid "Desired Healthy"
|
msgid "Desired Healthy"
|
||||||
@ -863,6 +873,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:105
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:105
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:107
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:107
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:108
|
||||||
msgid "Desired number of replicas"
|
msgid "Desired number of replicas"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1122,6 +1133,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:127
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:127
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:116
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:116
|
||||||
|
#: src/renderer/components/+workloads-replicaset/replicaset-scale-dialog.tsx:131
|
||||||
msgid "High number of replicas may cause cluster performance issues"
|
msgid "High number of replicas may cause cluster performance issues"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1573,6 +1585,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/+workspaces/workspaces.tsx:135
|
#: src/renderer/components/+workspaces/workspaces.tsx:135
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:89
|
#: src/renderer/components/dock/edit-resource.tsx:89
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1622,6 +1635,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/item-object-list/page-filters-select.tsx:57
|
#: src/renderer/components/item-object-list/page-filters-select.tsx:57
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:23
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:23
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:144
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:144
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
||||||
msgid "Namespace"
|
msgid "Namespace"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2023,6 +2037,7 @@ msgstr ""
|
|||||||
msgid "Readiness"
|
msgid "Readiness"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:55
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:145
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:145
|
||||||
msgid "Ready"
|
msgid "Ready"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2138,6 +2153,10 @@ msgstr ""
|
|||||||
msgid "Replicas"
|
msgid "Replicas"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads/workloads.tsx:70
|
||||||
|
msgid "ReplicaSets"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/dock/install-chart.tsx:119
|
#: src/renderer/components/dock/install-chart.tsx:119
|
||||||
msgid "Repo/Name"
|
msgid "Repo/Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2329,6 +2348,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:128
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:128
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:83
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:83
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:84
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:84
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:160
|
||||||
msgid "Scale"
|
msgid "Scale"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2336,6 +2356,10 @@ msgstr ""
|
|||||||
msgid "Scale Deployment <0>{deploymentName}</0>"
|
msgid "Scale Deployment <0>{deploymentName}</0>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:143
|
||||||
|
msgid "Scale Replica Set <0>{replicaSetName}</0>"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:139
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:139
|
||||||
msgid "Scale Stateful Set <0>{statefulSetName}</0>"
|
msgid "Scale Stateful Set <0>{statefulSetName}</0>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@ -223,6 +223,7 @@ msgstr "Аффинитеты"
|
|||||||
#: src/renderer/components/+workloads-pods/pods.tsx:78
|
#: src/renderer/components/+workloads-pods/pods.tsx:78
|
||||||
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:51
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:51
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:41
|
#: src/renderer/components/+workloads-statefulsets/statefulsets.tsx:41
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:56
|
||||||
msgid "Age"
|
msgid "Age"
|
||||||
msgstr "Возраст"
|
msgstr "Возраст"
|
||||||
|
|
||||||
@ -766,6 +767,10 @@ msgstr ""
|
|||||||
msgid "CronJobs"
|
msgid "CronJobs"
|
||||||
msgstr "CronJobs"
|
msgstr "CronJobs"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:54
|
||||||
|
msgid "Current"
|
||||||
|
msgstr "Текущее"
|
||||||
|
|
||||||
#: src/renderer/components/+config-autoscalers/hpa-details.tsx:50
|
#: src/renderer/components/+config-autoscalers/hpa-details.tsx:50
|
||||||
msgid "Current / Target"
|
msgid "Current / Target"
|
||||||
msgstr "Текущее / Цель"
|
msgstr "Текущее / Цель"
|
||||||
@ -777,6 +782,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:101
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:101
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:103
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:103
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:104
|
||||||
msgid "Current replica scale: {currentReplicas}"
|
msgid "Current replica scale: {currentReplicas}"
|
||||||
msgstr "Текущий размер реплики: {currentReplicas}"
|
msgstr "Текущий размер реплики: {currentReplicas}"
|
||||||
|
|
||||||
@ -861,6 +867,10 @@ msgstr "Deployments"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Описание"
|
msgstr "Описание"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:53
|
||||||
|
msgid "Desired"
|
||||||
|
msgstr "Желаемое"
|
||||||
|
|
||||||
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx:42
|
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets-details.tsx:42
|
||||||
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx:41
|
#: src/renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.tsx:41
|
||||||
msgid "Desired Healthy"
|
msgid "Desired Healthy"
|
||||||
@ -868,6 +878,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:105
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:105
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:107
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:107
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:108
|
||||||
msgid "Desired number of replicas"
|
msgid "Desired number of replicas"
|
||||||
msgstr "Нужный уровень реплик"
|
msgstr "Нужный уровень реплик"
|
||||||
|
|
||||||
@ -1132,6 +1143,7 @@ msgstr "Скрыть"
|
|||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:127
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:127
|
||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:116
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:116
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:131
|
||||||
msgid "High number of replicas may cause cluster performance issues"
|
msgid "High number of replicas may cause cluster performance issues"
|
||||||
msgstr "Большое количество реплик может вызвать проблемы с производительностью кластера"
|
msgstr "Большое количество реплик может вызвать проблемы с производительностью кластера"
|
||||||
|
|
||||||
@ -1583,6 +1595,7 @@ msgstr "Установки"
|
|||||||
#: src/renderer/components/+workspaces/workspaces.tsx:135
|
#: src/renderer/components/+workspaces/workspaces.tsx:135
|
||||||
#: src/renderer/components/dock/edit-resource.tsx:89
|
#: src/renderer/components/dock/edit-resource.tsx:89
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:20
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:50
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Имя"
|
msgstr "Имя"
|
||||||
|
|
||||||
@ -1632,6 +1645,7 @@ msgstr ""
|
|||||||
#: src/renderer/components/item-object-list/page-filters-select.tsx:57
|
#: src/renderer/components/item-object-list/page-filters-select.tsx:57
|
||||||
#: src/renderer/components/kube-object/kube-object-meta.tsx:23
|
#: src/renderer/components/kube-object/kube-object-meta.tsx:23
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:144
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:144
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:52
|
||||||
msgid "Namespace"
|
msgid "Namespace"
|
||||||
msgstr "Namespace"
|
msgstr "Namespace"
|
||||||
|
|
||||||
@ -2041,6 +2055,7 @@ msgstr ""
|
|||||||
msgid "Readiness"
|
msgid "Readiness"
|
||||||
msgstr "Готовность"
|
msgstr "Готовность"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicasets.tsx:55
|
||||||
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:145
|
#: src/renderer/components/+workloads-pods/pod-details-list.tsx:145
|
||||||
msgid "Ready"
|
msgid "Ready"
|
||||||
msgstr "Готовы"
|
msgstr "Готовы"
|
||||||
@ -2156,6 +2171,10 @@ msgstr ""
|
|||||||
msgid "Replicas"
|
msgid "Replicas"
|
||||||
msgstr "Реплики"
|
msgstr "Реплики"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads/workloads.tsx:70
|
||||||
|
msgid "ReplicaSets"
|
||||||
|
msgstr "ReplicaSets"
|
||||||
|
|
||||||
#: src/renderer/components/dock/install-chart.tsx:119
|
#: src/renderer/components/dock/install-chart.tsx:119
|
||||||
msgid "Repo/Name"
|
msgid "Repo/Name"
|
||||||
msgstr "Репозиторий/Имя"
|
msgstr "Репозиторий/Имя"
|
||||||
@ -2347,6 +2366,7 @@ msgstr "Сохранить"
|
|||||||
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:128
|
#: src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx:128
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:83
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:83
|
||||||
#: src/renderer/components/+workloads-deployments/deployments.tsx:84
|
#: src/renderer/components/+workloads-deployments/deployments.tsx:84
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:160
|
||||||
msgid "Scale"
|
msgid "Scale"
|
||||||
msgstr "Масштабировать"
|
msgstr "Масштабировать"
|
||||||
|
|
||||||
@ -2354,6 +2374,10 @@ msgstr "Масштабировать"
|
|||||||
msgid "Scale Deployment <0>{deploymentName}</0>"
|
msgid "Scale Deployment <0>{deploymentName}</0>"
|
||||||
msgstr "Масштабировать Deployment <0>{deploymentName}</0>"
|
msgstr "Масштабировать Deployment <0>{deploymentName}</0>"
|
||||||
|
|
||||||
|
#: src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.tsx:143
|
||||||
|
msgid "Scale Replica Set <0>{replicaSetName}</0>"
|
||||||
|
msgstr "Масштабировать Replica Set <0>{replicaSetName}</0>"
|
||||||
|
|
||||||
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:139
|
#: src/renderer/components/+workloads-statefulsets/statefulset-scale-dialog.tsx:139
|
||||||
msgid "Scale Stateful Set <0>{statefulSetName}</0>"
|
msgid "Scale Stateful Set <0>{statefulSetName}</0>"
|
||||||
msgstr "Масштабировать Stateful Set <0>{statefulSetName}</0>"
|
msgstr "Масштабировать Stateful Set <0>{statefulSetName}</0>"
|
||||||
|
|||||||
@ -31,6 +31,7 @@ export const apiResources: KubeApiResource[] = [
|
|||||||
{ resource: "poddisruptionbudgets" },
|
{ resource: "poddisruptionbudgets" },
|
||||||
{ resource: "podsecuritypolicies" },
|
{ resource: "podsecuritypolicies" },
|
||||||
{ resource: "resourcequotas" },
|
{ resource: "resourcequotas" },
|
||||||
|
{ resource: "replicasets", group: "apps" },
|
||||||
{ resource: "secrets" },
|
{ resource: "secrets" },
|
||||||
{ resource: "services" },
|
{ resource: "services" },
|
||||||
{ resource: "statefulsets", group: "apps" },
|
{ resource: "statefulsets", group: "apps" },
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export interface IPodContainer {
|
|||||||
image: string;
|
image: string;
|
||||||
command?: string[];
|
command?: string[];
|
||||||
args?: string[];
|
args?: string[];
|
||||||
ports: {
|
ports?: {
|
||||||
name?: string;
|
name?: string;
|
||||||
containerPort: number;
|
containerPort: number;
|
||||||
protocol: string;
|
protocol: string;
|
||||||
@ -137,7 +137,7 @@ interface IContainerProbe {
|
|||||||
|
|
||||||
export interface IPodContainerStatus {
|
export interface IPodContainerStatus {
|
||||||
name: string;
|
name: string;
|
||||||
state: {
|
state?: {
|
||||||
[index: string]: object;
|
[index: string]: object;
|
||||||
running?: {
|
running?: {
|
||||||
startedAt: string;
|
startedAt: string;
|
||||||
@ -153,21 +153,28 @@ export interface IPodContainerStatus {
|
|||||||
reason: string;
|
reason: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
lastState: {
|
lastState?: {
|
||||||
[index: string]: object;
|
[index: string]: object;
|
||||||
|
running?: {
|
||||||
|
startedAt: string;
|
||||||
|
};
|
||||||
|
waiting?: {
|
||||||
|
reason: string;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
terminated?: {
|
terminated?: {
|
||||||
startedAt: string;
|
startedAt: string;
|
||||||
finishedAt: string;
|
finishedAt: string;
|
||||||
exitCode: number;
|
exitCode: number;
|
||||||
reason: string;
|
reason: string;
|
||||||
containerID: string;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
restartCount: number;
|
restartCount: number;
|
||||||
image: string;
|
image: string;
|
||||||
imageID: string;
|
imageID: string;
|
||||||
containerID: string;
|
containerID?: string;
|
||||||
|
started?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
@ -196,28 +203,44 @@ export class Pod extends WorkloadKubeObject {
|
|||||||
}[];
|
}[];
|
||||||
initContainers: IPodContainer[];
|
initContainers: IPodContainer[];
|
||||||
containers: IPodContainer[];
|
containers: IPodContainer[];
|
||||||
restartPolicy: string;
|
restartPolicy?: string;
|
||||||
terminationGracePeriodSeconds: number;
|
terminationGracePeriodSeconds?: number;
|
||||||
dnsPolicy: string;
|
activeDeadlineSeconds?: number;
|
||||||
|
dnsPolicy?: string;
|
||||||
serviceAccountName: string;
|
serviceAccountName: string;
|
||||||
serviceAccount: string;
|
serviceAccount: string;
|
||||||
priority: number;
|
automountServiceAccountToken?: boolean;
|
||||||
priorityClassName: string;
|
priority?: number;
|
||||||
nodeName: string;
|
priorityClassName?: string;
|
||||||
|
nodeName?: string;
|
||||||
nodeSelector?: {
|
nodeSelector?: {
|
||||||
[selector: string]: string;
|
[selector: string]: string;
|
||||||
};
|
};
|
||||||
securityContext: {};
|
securityContext?: {};
|
||||||
schedulerName: string;
|
imagePullSecrets?: {
|
||||||
tolerations: {
|
name: string;
|
||||||
key: string;
|
|
||||||
operator: string;
|
|
||||||
effect: string;
|
|
||||||
tolerationSeconds: number;
|
|
||||||
}[];
|
}[];
|
||||||
affinity: IAffinity;
|
hostNetwork?: boolean;
|
||||||
|
hostPID?: boolean;
|
||||||
|
hostIPC?: boolean;
|
||||||
|
shareProcessNamespace?: boolean;
|
||||||
|
hostname?: string;
|
||||||
|
subdomain?: string;
|
||||||
|
schedulerName?: string;
|
||||||
|
tolerations?: {
|
||||||
|
key?: string;
|
||||||
|
operator?: string;
|
||||||
|
effect?: string;
|
||||||
|
tolerationSeconds?: number;
|
||||||
|
value?: string;
|
||||||
|
}[];
|
||||||
|
hostAliases?: {
|
||||||
|
ip: string;
|
||||||
|
hostnames: string[];
|
||||||
|
};
|
||||||
|
affinity?: IAffinity;
|
||||||
};
|
};
|
||||||
status: {
|
status?: {
|
||||||
phase: string;
|
phase: string;
|
||||||
conditions: {
|
conditions: {
|
||||||
type: string;
|
type: string;
|
||||||
@ -230,7 +253,7 @@ export class Pod extends WorkloadKubeObject {
|
|||||||
startTime: string;
|
startTime: string;
|
||||||
initContainerStatuses?: IPodContainerStatus[];
|
initContainerStatuses?: IPodContainerStatus[];
|
||||||
containerStatuses?: IPodContainerStatus[];
|
containerStatuses?: IPodContainerStatus[];
|
||||||
qosClass: string;
|
qosClass?: string;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,51 +1,78 @@
|
|||||||
import get from "lodash/get";
|
import get from "lodash/get";
|
||||||
import { autobind } from "../../utils";
|
import { autobind } from "../../utils";
|
||||||
import { IAffinity, WorkloadKubeObject } from "../workload-kube-object";
|
import { WorkloadKubeObject } from "../workload-kube-object";
|
||||||
import { IPodContainer } from "./pods.api";
|
import { IPodContainer, Pod } from "./pods.api";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
|
||||||
|
export class ReplicaSetApi extends KubeApi<ReplicaSet> {
|
||||||
|
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||||
|
return `${this.getUrl(params)}/scale`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getReplicas(params: { namespace: string; name: string }): Promise<number> {
|
||||||
|
return this.request
|
||||||
|
.get(this.getScaleApiUrl(params))
|
||||||
|
.then(({ status }: any) => status?.replicas);
|
||||||
|
}
|
||||||
|
|
||||||
|
scale(params: { namespace: string; name: string }, replicas: number) {
|
||||||
|
return this.request.put(this.getScaleApiUrl(params), {
|
||||||
|
data: {
|
||||||
|
metadata: params,
|
||||||
|
spec: {
|
||||||
|
replicas
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
export class ReplicaSet extends WorkloadKubeObject {
|
export class ReplicaSet extends WorkloadKubeObject {
|
||||||
static kind = "ReplicaSet";
|
static kind = "ReplicaSet";
|
||||||
static namespaced = true;
|
static namespaced = true;
|
||||||
static apiBase = "/apis/apps/v1/replicasets";
|
static apiBase = "/apis/apps/v1/replicasets";
|
||||||
|
|
||||||
spec: {
|
spec: {
|
||||||
replicas?: number;
|
replicas?: number;
|
||||||
selector?: {
|
selector: { matchLabels: { [app: string]: string } };
|
||||||
matchLabels: {
|
|
||||||
[key: string]: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
containers?: IPodContainer[];
|
|
||||||
template?: {
|
template?: {
|
||||||
spec?: {
|
metadata: {
|
||||||
affinity?: IAffinity;
|
labels: {
|
||||||
nodeSelector?: {
|
app: string;
|
||||||
[selector: string]: string;
|
|
||||||
};
|
};
|
||||||
tolerations: {
|
|
||||||
key: string;
|
|
||||||
operator: string;
|
|
||||||
effect: string;
|
|
||||||
tolerationSeconds: number;
|
|
||||||
}[];
|
|
||||||
containers: IPodContainer[];
|
|
||||||
};
|
};
|
||||||
|
spec?: Pod["spec"];
|
||||||
};
|
};
|
||||||
restartPolicy?: string;
|
minReadySeconds?: number;
|
||||||
terminationGracePeriodSeconds?: number;
|
|
||||||
dnsPolicy?: string;
|
|
||||||
schedulerName?: string;
|
|
||||||
};
|
};
|
||||||
status: {
|
status: {
|
||||||
replicas: number;
|
replicas: number;
|
||||||
fullyLabeledReplicas: number;
|
fullyLabeledReplicas?: number;
|
||||||
readyReplicas: number;
|
readyReplicas?: number;
|
||||||
availableReplicas: number;
|
availableReplicas?: number;
|
||||||
observedGeneration: number;
|
observedGeneration?: number;
|
||||||
|
conditions?: {
|
||||||
|
type: string;
|
||||||
|
status: string;
|
||||||
|
lastUpdateTime: string;
|
||||||
|
lastTransitionTime: string;
|
||||||
|
reason: string;
|
||||||
|
message: string;
|
||||||
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getDesired() {
|
||||||
|
return this.spec.replicas || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrent() {
|
||||||
|
return this.status.availableReplicas || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
getReady() {
|
||||||
|
return this.status.readyReplicas || 0;
|
||||||
|
}
|
||||||
|
|
||||||
getImages() {
|
getImages() {
|
||||||
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []);
|
const containers: IPodContainer[] = get(this, "spec.template.spec.containers", []);
|
||||||
|
|
||||||
@ -53,6 +80,6 @@ export class ReplicaSet extends WorkloadKubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const replicaSetApi = new KubeApi({
|
export const replicaSetApi = new ReplicaSetApi({
|
||||||
objectConstructor: ReplicaSet,
|
objectConstructor: ReplicaSet,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import { cssNames } from "../../utils";
|
|||||||
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
|
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
|
||||||
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
|
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
|
||||||
import { KubeEventDetails } from "../+events/kube-event-details";
|
import { KubeEventDetails } from "../+events/kube-event-details";
|
||||||
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
|
|
||||||
import { podsStore } from "../+workloads-pods/pods.store";
|
import { podsStore } from "../+workloads-pods/pods.store";
|
||||||
import { KubeObjectDetailsProps } from "../kube-object";
|
import { KubeObjectDetailsProps } from "../kube-object";
|
||||||
import { _i18n } from "../../i18n";
|
import { _i18n } from "../../i18n";
|
||||||
@ -20,7 +19,6 @@ import { deploymentStore } from "./deployments.store";
|
|||||||
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
|
||||||
import { reaction } from "mobx";
|
import { reaction } from "mobx";
|
||||||
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
|
||||||
import { ReplicaSets } from "../+workloads-replicasets";
|
|
||||||
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
|
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
|
||||||
|
|
||||||
@ -38,10 +36,6 @@ export class DeploymentDetails extends React.Component<Props> {
|
|||||||
if (!podsStore.isLoaded) {
|
if (!podsStore.isLoaded) {
|
||||||
podsStore.loadAll();
|
podsStore.loadAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!replicaSetStore.isLoaded) {
|
|
||||||
replicaSetStore.loadAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@ -56,7 +50,6 @@ export class DeploymentDetails extends React.Component<Props> {
|
|||||||
const nodeSelector = deployment.getNodeSelectors();
|
const nodeSelector = deployment.getNodeSelectors();
|
||||||
const selectors = deployment.getSelectors();
|
const selectors = deployment.getSelectors();
|
||||||
const childPods = deploymentStore.getChildPods(deployment);
|
const childPods = deploymentStore.getChildPods(deployment);
|
||||||
const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment);
|
|
||||||
const metrics = deploymentStore.metrics;
|
const metrics = deploymentStore.metrics;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -118,7 +111,6 @@ export class DeploymentDetails extends React.Component<Props> {
|
|||||||
<PodDetailsTolerations workload={deployment}/>
|
<PodDetailsTolerations workload={deployment}/>
|
||||||
<PodDetailsAffinities workload={deployment}/>
|
<PodDetailsAffinities workload={deployment}/>
|
||||||
<ResourceMetricsText metrics={metrics}/>
|
<ResourceMetricsText metrics={metrics}/>
|
||||||
<ReplicaSets replicaSets={replicaSets}/>
|
|
||||||
<PodDetailsList pods={childPods} owner={deployment}/>
|
<PodDetailsList pods={childPods} owner={deployment}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
.workloads {
|
.workloads {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, 155px);
|
grid-template-columns: repeat(auto-fit, 180px);
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
grid-gap: $margin;
|
grid-gap: $margin;
|
||||||
padding: $padding * 2;
|
padding: $padding * 2;
|
||||||
|
|||||||
@ -18,6 +18,7 @@ const resources: KubeResource[] = [
|
|||||||
"deployments",
|
"deployments",
|
||||||
"statefulsets",
|
"statefulsets",
|
||||||
"daemonsets",
|
"daemonsets",
|
||||||
|
"replicasets",
|
||||||
"jobs",
|
"jobs",
|
||||||
"cronjobs",
|
"cronjobs",
|
||||||
];
|
];
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
.ReplicaSetScaleDialog {
|
||||||
|
.Wizard {
|
||||||
|
.header {
|
||||||
|
span {
|
||||||
|
color: #a0a0a0;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.WizardStep {
|
||||||
|
.step-content {
|
||||||
|
min-height: 90px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-scale {
|
||||||
|
font-weight: bold
|
||||||
|
}
|
||||||
|
|
||||||
|
.desired-scale {
|
||||||
|
flex: 1.1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-container {
|
||||||
|
flex: 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plus-minus-container {
|
||||||
|
margin-left: $margin * 2;
|
||||||
|
.Icon {
|
||||||
|
--color-active: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
color: $colorSoftError;
|
||||||
|
font-size: small;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.Icon {
|
||||||
|
margin: 0;
|
||||||
|
margin-right: $margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
167
src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.test.tsx
Executable file
167
src/renderer/components/+workloads-replicasets/replicaset-scale-dialog.test.tsx
Executable file
@ -0,0 +1,167 @@
|
|||||||
|
import "@testing-library/jest-dom/extend-expect";
|
||||||
|
|
||||||
|
jest.mock("../../api/endpoints");
|
||||||
|
import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog";
|
||||||
|
import { render, waitFor, fireEvent } from "@testing-library/react";
|
||||||
|
import React from "react";
|
||||||
|
import { replicaSetApi } from "../../api/endpoints/replica-set.api";
|
||||||
|
|
||||||
|
const dummyReplicaSet = {
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "dummy",
|
||||||
|
metadata: {
|
||||||
|
uid: "dummy",
|
||||||
|
name: "dummy",
|
||||||
|
creationTimestamp: "dummy",
|
||||||
|
resourceVersion: "dummy",
|
||||||
|
selfLink: "link",
|
||||||
|
},
|
||||||
|
selfLink: "link",
|
||||||
|
spec: {
|
||||||
|
replicas: 1,
|
||||||
|
selector: {
|
||||||
|
matchLabels: { "label": "label" }
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
metadata: {
|
||||||
|
labels: {
|
||||||
|
app: "label",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
containers: [{
|
||||||
|
name: "dummy",
|
||||||
|
image: "dummy",
|
||||||
|
imagePullPolicy: "dummy",
|
||||||
|
}],
|
||||||
|
initContainers: [{
|
||||||
|
name: "dummy",
|
||||||
|
image: "dummy",
|
||||||
|
imagePullPolicy: "dummy",
|
||||||
|
}],
|
||||||
|
priority: 1,
|
||||||
|
serviceAccountName: "dummy",
|
||||||
|
serviceAccount: "dummy",
|
||||||
|
securityContext: {},
|
||||||
|
schedulerName: "dummy",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
minReadySeconds: 1,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
replicas: 1,
|
||||||
|
fullyLabeledReplicas: 1,
|
||||||
|
readyReplicas: 1,
|
||||||
|
availableReplicas: 1,
|
||||||
|
observedGeneration: 1,
|
||||||
|
conditions: [{
|
||||||
|
type: "dummy",
|
||||||
|
status: "dummy",
|
||||||
|
lastUpdateTime: "dummy",
|
||||||
|
lastTransitionTime: "dummy",
|
||||||
|
reason: "dummy",
|
||||||
|
message: "dummy",
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
getDesired: jest.fn(),
|
||||||
|
getCurrent: jest.fn(),
|
||||||
|
getReady: jest.fn(),
|
||||||
|
getImages: jest.fn(),
|
||||||
|
getReplicas: jest.fn(),
|
||||||
|
getSelectors: jest.fn(),
|
||||||
|
getTemplateLabels: jest.fn(),
|
||||||
|
getAffinity: jest.fn(),
|
||||||
|
getTolerations: jest.fn(),
|
||||||
|
getNodeSelectors: jest.fn(),
|
||||||
|
getAffinityNumber: jest.fn(),
|
||||||
|
getId: jest.fn(),
|
||||||
|
getResourceVersion: jest.fn(),
|
||||||
|
getName: jest.fn(),
|
||||||
|
getNs: jest.fn(),
|
||||||
|
getAge: jest.fn(),
|
||||||
|
getFinalizers: jest.fn(),
|
||||||
|
getLabels: jest.fn(),
|
||||||
|
getAnnotations: jest.fn(),
|
||||||
|
getOwnerRefs: jest.fn(),
|
||||||
|
getSearchFields: jest.fn(),
|
||||||
|
toPlainObject: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
delete: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("<ReplicaSetScaleDialog />", () => {
|
||||||
|
it("renders w/o errors", () => {
|
||||||
|
const { container } = render(<ReplicaSetScaleDialog/>);
|
||||||
|
|
||||||
|
expect(container).toBeInstanceOf(HTMLElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("init with a dummy replica set and mocked current/desired scale", async () => {
|
||||||
|
// mock replicaSetApi.getReplicas() which will be called
|
||||||
|
// when <ReplicaSetScaleDialog /> rendered.
|
||||||
|
const initReplicas = 1;
|
||||||
|
|
||||||
|
replicaSetApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas);
|
||||||
|
const { getByTestId } = render(<ReplicaSetScaleDialog/>);
|
||||||
|
|
||||||
|
ReplicaSetScaleDialog.open(dummyReplicaSet);
|
||||||
|
// we need to wait for the replicaSetScaleDialog to show up
|
||||||
|
// because there is an <Animate /> in <Dialog /> which renders null at start.
|
||||||
|
await waitFor(async () => {
|
||||||
|
const [currentScale, desiredScale] = await Promise.all([
|
||||||
|
getByTestId("current-scale"),
|
||||||
|
getByTestId("desired-scale"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(currentScale).toHaveTextContent(`${initReplicas}`);
|
||||||
|
expect(desiredScale).toHaveTextContent(`${initReplicas}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("changes the desired scale when clicking the icon buttons +/-", async () => {
|
||||||
|
const initReplicas = 1;
|
||||||
|
|
||||||
|
replicaSetApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas);
|
||||||
|
const component = render(<ReplicaSetScaleDialog/>);
|
||||||
|
|
||||||
|
ReplicaSetScaleDialog.open(dummyReplicaSet);
|
||||||
|
await waitFor(async () => {
|
||||||
|
expect(await component.findByTestId("desired-scale")).toHaveTextContent(`${initReplicas}`);
|
||||||
|
expect(await component.findByTestId("current-scale")).toHaveTextContent(`${initReplicas}`);
|
||||||
|
expect((await component.baseElement.querySelector("input").value)).toBe(`${initReplicas}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const up = await component.findByTestId("desired-replicas-up");
|
||||||
|
const down = await component.findByTestId("desired-replicas-down");
|
||||||
|
|
||||||
|
fireEvent.click(up);
|
||||||
|
expect(await component.findByTestId("desired-scale")).toHaveTextContent(`${initReplicas + 1}`);
|
||||||
|
expect(await component.findByTestId("current-scale")).toHaveTextContent(`${initReplicas}`);
|
||||||
|
expect((await component.baseElement.querySelector("input").value)).toBe(`${initReplicas + 1}`);
|
||||||
|
|
||||||
|
fireEvent.click(down);
|
||||||
|
expect(await component.findByTestId("desired-scale")).toHaveTextContent(`${initReplicas}`);
|
||||||
|
expect(await component.findByTestId("current-scale")).toHaveTextContent(`${initReplicas}`);
|
||||||
|
expect((await component.baseElement.querySelector("input").value)).toBe(`${initReplicas}`);
|
||||||
|
|
||||||
|
// edge case, desiredScale must >= 0
|
||||||
|
let times = 10;
|
||||||
|
|
||||||
|
for (let i = 0; i < times; i++) {
|
||||||
|
fireEvent.click(down);
|
||||||
|
}
|
||||||
|
expect(await component.findByTestId("desired-scale")).toHaveTextContent("0");
|
||||||
|
expect((await component.baseElement.querySelector("input").value)).toBe("0");
|
||||||
|
|
||||||
|
// edge case, desiredScale must <= scaleMax (100)
|
||||||
|
times = 120;
|
||||||
|
|
||||||
|
for (let i = 0; i < times; i++) {
|
||||||
|
fireEvent.click(up);
|
||||||
|
}
|
||||||
|
expect(await component.findByTestId("desired-scale")).toHaveTextContent("100");
|
||||||
|
expect((component.baseElement.querySelector("input").value)).toBe("100");
|
||||||
|
expect(await component.findByTestId("warning"))
|
||||||
|
.toHaveTextContent("High number of replicas may cause cluster performance issues");
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,169 @@
|
|||||||
|
import "./replicaset-scale-dialog.scss";
|
||||||
|
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { computed, observable } from "mobx";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Trans } from "@lingui/macro";
|
||||||
|
import { Dialog, DialogProps } from "../dialog";
|
||||||
|
import { Wizard, WizardStep } from "../wizard";
|
||||||
|
import { Icon } from "../icon";
|
||||||
|
import { Slider } from "../slider";
|
||||||
|
import { Notifications } from "../notifications";
|
||||||
|
import { cssNames } from "../../utils";
|
||||||
|
import { ReplicaSet, replicaSetApi } from "../../api/endpoints/replica-set.api";
|
||||||
|
|
||||||
|
interface Props extends Partial<DialogProps> {
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class ReplicaSetScaleDialog extends Component<Props> {
|
||||||
|
@observable static isOpen = false;
|
||||||
|
@observable static data: ReplicaSet = null;
|
||||||
|
|
||||||
|
@observable ready = false;
|
||||||
|
@observable currentReplicas = 0;
|
||||||
|
@observable desiredReplicas = 0;
|
||||||
|
|
||||||
|
static open(replicaSet: ReplicaSet) {
|
||||||
|
ReplicaSetScaleDialog.isOpen = true;
|
||||||
|
ReplicaSetScaleDialog.data = replicaSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static close() {
|
||||||
|
ReplicaSetScaleDialog.isOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get replicaSet() {
|
||||||
|
return ReplicaSetScaleDialog.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
close = () => {
|
||||||
|
ReplicaSetScaleDialog.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
onOpen = async () => {
|
||||||
|
const { replicaSet } = this;
|
||||||
|
|
||||||
|
this.currentReplicas = await replicaSetApi.getReplicas({
|
||||||
|
namespace: replicaSet.getNs(),
|
||||||
|
name: replicaSet.getName(),
|
||||||
|
});
|
||||||
|
this.desiredReplicas = this.currentReplicas;
|
||||||
|
this.ready = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
onClose = () => {
|
||||||
|
this.ready = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
onChange = (evt: React.ChangeEvent, value: number) => {
|
||||||
|
this.desiredReplicas = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
@computed get scaleMax() {
|
||||||
|
const { currentReplicas } = this;
|
||||||
|
const defaultMax = 50;
|
||||||
|
|
||||||
|
return currentReplicas <= defaultMax
|
||||||
|
? defaultMax * 2
|
||||||
|
: currentReplicas * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale = async () => {
|
||||||
|
const { replicaSet } = this;
|
||||||
|
const { currentReplicas, desiredReplicas, close } = this;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (currentReplicas !== desiredReplicas) {
|
||||||
|
await replicaSetApi.scale({
|
||||||
|
name: replicaSet.getName(),
|
||||||
|
namespace: replicaSet.getNs(),
|
||||||
|
}, desiredReplicas);
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
} catch (err) {
|
||||||
|
Notifications.error(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
desiredReplicasUp = () => {
|
||||||
|
this.desiredReplicas < this.scaleMax && this.desiredReplicas++;
|
||||||
|
};
|
||||||
|
|
||||||
|
desiredReplicasDown = () => {
|
||||||
|
this.desiredReplicas > 0 && this.desiredReplicas--;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderContents() {
|
||||||
|
const { currentReplicas, desiredReplicas, onChange, scaleMax } = this;
|
||||||
|
const warning = currentReplicas < 10 && desiredReplicas > 90;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="current-scale" data-testid="current-scale">
|
||||||
|
<Trans>Current replica scale: {currentReplicas}</Trans>
|
||||||
|
</div>
|
||||||
|
<div className="flex gaps align-center">
|
||||||
|
<div className="desired-scale" data-testid="desired-scale">
|
||||||
|
<Trans>Desired number of replicas</Trans>: {desiredReplicas}
|
||||||
|
</div>
|
||||||
|
<div className="slider-container flex align-center" data-testid="slider">
|
||||||
|
<Slider value={desiredReplicas} max={scaleMax}
|
||||||
|
onChange={onChange as any /** see: https://github.com/mui-org/material-ui/issues/20191 */}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="plus-minus-container flex gaps">
|
||||||
|
<Icon
|
||||||
|
material="add_circle_outline"
|
||||||
|
onClick={this.desiredReplicasUp}
|
||||||
|
data-testid="desired-replicas-up"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
material="remove_circle_outline"
|
||||||
|
onClick={this.desiredReplicasDown}
|
||||||
|
data-testid="desired-replicas-down"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{warning &&
|
||||||
|
<div className="warning" data-testid="warning">
|
||||||
|
<Icon material="warning"/>
|
||||||
|
<Trans>High number of replicas may cause cluster performance issues</Trans>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { className, ...dialogProps } = this.props;
|
||||||
|
const replicaSetName = this.replicaSet ? this.replicaSet.getName() : "";
|
||||||
|
const header = (
|
||||||
|
<h5>
|
||||||
|
<Trans>Scale Replica Set <span>{replicaSetName}</span></Trans>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
{...dialogProps}
|
||||||
|
isOpen={ReplicaSetScaleDialog.isOpen}
|
||||||
|
className={cssNames("ReplicaSetScaleDialog", className)}
|
||||||
|
onOpen={this.onOpen}
|
||||||
|
onClose={this.onClose}
|
||||||
|
close={this.close}
|
||||||
|
>
|
||||||
|
<Wizard header={header} done={this.close}>
|
||||||
|
<WizardStep
|
||||||
|
contentClass="flex gaps column"
|
||||||
|
next={this.scale}
|
||||||
|
nextLabel={<Trans>Scale</Trans>}
|
||||||
|
disabledNext={!this.ready}
|
||||||
|
>
|
||||||
|
{this.renderContents()}
|
||||||
|
</WizardStep>
|
||||||
|
</Wizard>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,20 +1,5 @@
|
|||||||
.ReplicaSets {
|
.ReplicaSets {
|
||||||
position: relative;
|
|
||||||
min-height: 80px;
|
|
||||||
|
|
||||||
.Table {
|
|
||||||
margin: 0 (-$margin * 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.TableCell {
|
.TableCell {
|
||||||
&:first-child {
|
|
||||||
margin-left: $margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: $margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.name {
|
&.name {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
}
|
}
|
||||||
@ -22,13 +7,5 @@
|
|||||||
&.warning {
|
&.warning {
|
||||||
@include table-cell-warning;
|
@include table-cell-warning;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.namespace {
|
|
||||||
flex-grow: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.actions {
|
|
||||||
@include table-cell-action;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { KubeObjectStore } from "../../kube-object.store";
|
|||||||
import { Deployment, IPodMetrics, podsApi, ReplicaSet, replicaSetApi } from "../../api/endpoints";
|
import { Deployment, IPodMetrics, podsApi, ReplicaSet, replicaSetApi } from "../../api/endpoints";
|
||||||
import { podsStore } from "../+workloads-pods/pods.store";
|
import { podsStore } from "../+workloads-pods/pods.store";
|
||||||
import { apiManager } from "../../api/api-manager";
|
import { apiManager } from "../../api/api-manager";
|
||||||
|
import { PodStatus } from "../../api/endpoints/pods.api";
|
||||||
|
|
||||||
@autobind()
|
@autobind()
|
||||||
export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
|
export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
|
||||||
@ -20,6 +21,26 @@ export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
|
|||||||
return podsStore.getPodsByOwner(replicaSet);
|
return podsStore.getPodsByOwner(replicaSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStatuses(replicaSets: ReplicaSet[]) {
|
||||||
|
const status = { failed: 0, pending: 0, running: 0 };
|
||||||
|
|
||||||
|
replicaSets.forEach(replicaSet => {
|
||||||
|
const pods = this.getChildPods(replicaSet);
|
||||||
|
|
||||||
|
if (pods.some(pod => pod.getStatus() === PodStatus.FAILED)) {
|
||||||
|
status.failed++;
|
||||||
|
}
|
||||||
|
else if (pods.some(pod => pod.getStatus() === PodStatus.PENDING)) {
|
||||||
|
status.pending++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status.running++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
getReplicaSetsByOwner(deployment: Deployment) {
|
getReplicaSetsByOwner(deployment: Deployment) {
|
||||||
return this.items.filter(replicaSet =>
|
return this.items.filter(replicaSet =>
|
||||||
!!replicaSet.getOwnerRefs().find(owner => owner.uid === deployment.getId())
|
!!replicaSet.getOwnerRefs().find(owner => owner.uid === deployment.getId())
|
||||||
|
|||||||
@ -2,97 +2,93 @@ import "./replicasets.scss";
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Trans } from "@lingui/macro";
|
import { t, Trans } from "@lingui/macro";
|
||||||
import { ReplicaSet } from "../../api/endpoints";
|
import { ReplicaSet } from "../../api/endpoints";
|
||||||
import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu";
|
import { KubeObjectMenuProps } from "../kube-object/kube-object-menu";
|
||||||
import { replicaSetStore } from "./replicasets.store";
|
import { replicaSetStore } from "./replicasets.store";
|
||||||
import { Spinner } from "../spinner";
|
|
||||||
import { prevDefault, stopPropagation } from "../../utils";
|
|
||||||
import { DrawerTitle } from "../drawer";
|
|
||||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
|
||||||
import { showDetails } from "../../navigation";
|
|
||||||
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
import { RouteComponentProps } from "react-router";
|
||||||
|
import { IReplicaSetsRouteParams } from "../+workloads/workloads.route";
|
||||||
|
import { KubeObjectListLayout } from "../kube-object/kube-object-list-layout";
|
||||||
|
import { MenuItem } from "../menu/menu";
|
||||||
|
import { Icon } from "../icon/icon";
|
||||||
|
import { _i18n } from "../../i18n";
|
||||||
|
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
||||||
|
import { ReplicaSetScaleDialog } from "./replicaset-scale-dialog";
|
||||||
|
|
||||||
enum sortBy {
|
enum sortBy {
|
||||||
name = "name",
|
name = "name",
|
||||||
namespace = "namespace",
|
namespace = "namespace",
|
||||||
pods = "pods",
|
desired = "desired",
|
||||||
|
current = "current",
|
||||||
|
ready = "ready",
|
||||||
age = "age",
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props extends RouteComponentProps<IReplicaSetsRouteParams> {
|
||||||
replicaSets: ReplicaSet[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ReplicaSets extends React.Component<Props> {
|
export class ReplicaSets extends React.Component<Props> {
|
||||||
private sortingCallbacks = {
|
|
||||||
[sortBy.name]: (replicaSet: ReplicaSet) => replicaSet.getName(),
|
|
||||||
[sortBy.namespace]: (replicaSet: ReplicaSet) => replicaSet.getNs(),
|
|
||||||
[sortBy.age]: (replicaSet: ReplicaSet) => replicaSet.metadata.creationTimestamp,
|
|
||||||
[sortBy.pods]: (replicaSet: ReplicaSet) => this.getPodsLength(replicaSet),
|
|
||||||
};
|
|
||||||
|
|
||||||
getPodsLength(replicaSet: ReplicaSet) {
|
|
||||||
return replicaSetStore.getChildPods(replicaSet).length;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { replicaSets } = this.props;
|
|
||||||
|
|
||||||
if (!replicaSets.length && !replicaSetStore.isLoaded) return (
|
|
||||||
<div className="ReplicaSets"><Spinner center/></div>
|
|
||||||
);
|
|
||||||
if (!replicaSets.length) return null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ReplicaSets flex column">
|
<KubeObjectListLayout
|
||||||
<DrawerTitle title={<Trans>Deploy Revisions</Trans>}/>
|
className="ReplicaSets" store={replicaSetStore}
|
||||||
<Table
|
sortingCallbacks={{
|
||||||
selectable
|
[sortBy.name]: (replicaSet: ReplicaSet) => replicaSet.getName(),
|
||||||
scrollable={false}
|
[sortBy.namespace]: (replicaSet: ReplicaSet) => replicaSet.getNs(),
|
||||||
sortable={this.sortingCallbacks}
|
[sortBy.desired]: (replicaSet: ReplicaSet) => replicaSet.getDesired(),
|
||||||
sortByDefault={{ sortBy: sortBy.pods, orderBy: "desc" }}
|
[sortBy.current]: (replicaSet: ReplicaSet) => replicaSet.getCurrent(),
|
||||||
sortSyncWithUrl={false}
|
[sortBy.ready]: (replicaSet: ReplicaSet) => replicaSet.getReady(),
|
||||||
className="box grow"
|
[sortBy.age]: (replicaSet: ReplicaSet) => replicaSet.metadata.creationTimestamp,
|
||||||
>
|
}}
|
||||||
<TableHead>
|
searchFilters={[
|
||||||
<TableCell className="name" sortBy={sortBy.name}><Trans>Name</Trans></TableCell>
|
(replicaSet: ReplicaSet) => replicaSet.getSearchFields(),
|
||||||
<TableCell className="warning"/>
|
]}
|
||||||
<TableCell className="namespace" sortBy={sortBy.namespace}>Namespace</TableCell>
|
renderHeaderTitle={<Trans>Replica Sets</Trans>}
|
||||||
<TableCell className="pods" sortBy={sortBy.pods}><Trans>Pods</Trans></TableCell>
|
renderTableHeader={[
|
||||||
<TableCell className="age" sortBy={sortBy.age}><Trans>Age</Trans></TableCell>
|
{ title: <Trans>Name</Trans>, className: "name", sortBy: sortBy.name },
|
||||||
<TableCell className="actions"/>
|
{ className: "warning" },
|
||||||
</TableHead>
|
{ title: <Trans>Namespace</Trans>, className: "namespace", sortBy: sortBy.namespace },
|
||||||
{
|
{ title: <Trans>Desired</Trans>, className: "desired", sortBy: sortBy.desired },
|
||||||
replicaSets.map(replica => {
|
{ title: <Trans>Current</Trans>, className: "current", sortBy: sortBy.current },
|
||||||
return (
|
{ title: <Trans>Ready</Trans>, className: "ready", sortBy: sortBy.ready },
|
||||||
<TableRow
|
{ title: <Trans>Age</Trans>, className: "age", sortBy: sortBy.age },
|
||||||
key={replica.getId()}
|
]}
|
||||||
sortItem={replica}
|
renderTableContents={(replicaSet: ReplicaSet) => [
|
||||||
nowrap
|
replicaSet.getName(),
|
||||||
onClick={prevDefault(() => showDetails(replica.selfLink, false))}
|
<KubeObjectStatusIcon key="icon" object={replicaSet}/>,
|
||||||
>
|
replicaSet.getNs(),
|
||||||
<TableCell className="name">{replica.getName()}</TableCell>
|
replicaSet.getDesired(),
|
||||||
<TableCell className="warning"><KubeObjectStatusIcon key="icon" object={replica}/></TableCell>
|
replicaSet.getCurrent(),
|
||||||
<TableCell className="namespace">{replica.getNs()}</TableCell>
|
replicaSet.getReady(),
|
||||||
<TableCell className="pods">{this.getPodsLength(replica)}</TableCell>
|
replicaSet.getAge(),
|
||||||
<TableCell className="age">{replica.getAge()}</TableCell>
|
]}
|
||||||
<TableCell className="actions" onClick={stopPropagation}>
|
renderItemMenu={(item: ReplicaSet) => {
|
||||||
<ReplicaSetMenu object={replica}/>
|
return <ReplicaSetMenu object={item}/>;
|
||||||
</TableCell>
|
}}
|
||||||
</TableRow>
|
/>
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Table>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ReplicaSetMenu(props: KubeObjectMenuProps<ReplicaSet>) {
|
export function ReplicaSetMenu(props: KubeObjectMenuProps<ReplicaSet>) {
|
||||||
|
const { object, toolbar } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KubeObjectMenu {...props}/>
|
<>
|
||||||
|
<MenuItem onClick={() => ReplicaSetScaleDialog.open(object)}>
|
||||||
|
<Icon material="open_with" title={_i18n._(t`Scale`)} interactive={toolbar}/>
|
||||||
|
<span className="title"><Trans>Scale</Trans></span>
|
||||||
|
</MenuItem>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kubeObjectMenuRegistry.add({
|
||||||
|
kind: "ReplicaSet",
|
||||||
|
apiVersions: ["apps/v1"],
|
||||||
|
components: {
|
||||||
|
MenuItem: ReplicaSetMenu
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@ -25,6 +25,9 @@ export const daemonSetsRoute: RouteProps = {
|
|||||||
export const statefulSetsRoute: RouteProps = {
|
export const statefulSetsRoute: RouteProps = {
|
||||||
path: "/statefulsets"
|
path: "/statefulsets"
|
||||||
};
|
};
|
||||||
|
export const replicaSetsRoute: RouteProps = {
|
||||||
|
path: "/replicasets"
|
||||||
|
};
|
||||||
export const jobsRoute: RouteProps = {
|
export const jobsRoute: RouteProps = {
|
||||||
path: "/jobs"
|
path: "/jobs"
|
||||||
};
|
};
|
||||||
@ -48,6 +51,9 @@ export interface IDaemonSetsRouteParams {
|
|||||||
export interface IStatefulSetsRouteParams {
|
export interface IStatefulSetsRouteParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IReplicaSetsRouteParams {
|
||||||
|
}
|
||||||
|
|
||||||
export interface IJobsRouteParams {
|
export interface IJobsRouteParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +67,7 @@ export const podsURL = buildURL<IPodsRouteParams>(podsRoute.path);
|
|||||||
export const deploymentsURL = buildURL<IDeploymentsRouteParams>(deploymentsRoute.path);
|
export const deploymentsURL = buildURL<IDeploymentsRouteParams>(deploymentsRoute.path);
|
||||||
export const daemonSetsURL = buildURL<IDaemonSetsRouteParams>(daemonSetsRoute.path);
|
export const daemonSetsURL = buildURL<IDaemonSetsRouteParams>(daemonSetsRoute.path);
|
||||||
export const statefulSetsURL = buildURL<IStatefulSetsRouteParams>(statefulSetsRoute.path);
|
export const statefulSetsURL = buildURL<IStatefulSetsRouteParams>(statefulSetsRoute.path);
|
||||||
|
export const replicaSetsURL = buildURL<IReplicaSetsRouteParams>(replicaSetsRoute.path);
|
||||||
export const jobsURL = buildURL<IJobsRouteParams>(jobsRoute.path);
|
export const jobsURL = buildURL<IJobsRouteParams>(jobsRoute.path);
|
||||||
export const cronJobsURL = buildURL<ICronJobsRouteParams>(cronJobsRoute.path);
|
export const cronJobsURL = buildURL<ICronJobsRouteParams>(cronJobsRoute.path);
|
||||||
|
|
||||||
@ -69,6 +76,7 @@ export const workloadURL: Partial<Record<KubeResource, ReturnType<typeof buildUR
|
|||||||
"deployments": deploymentsURL,
|
"deployments": deploymentsURL,
|
||||||
"daemonsets": daemonSetsURL,
|
"daemonsets": daemonSetsURL,
|
||||||
"statefulsets": statefulSetsURL,
|
"statefulsets": statefulSetsURL,
|
||||||
|
"replicasets": replicaSetsURL,
|
||||||
"jobs": jobsURL,
|
"jobs": jobsURL,
|
||||||
"cronjobs": cronJobsURL,
|
"cronjobs": cronJobsURL,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,12 +6,14 @@ import { statefulSetStore } from "../+workloads-statefulsets/statefulset.store";
|
|||||||
import { jobStore } from "../+workloads-jobs/job.store";
|
import { jobStore } from "../+workloads-jobs/job.store";
|
||||||
import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
|
import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
|
||||||
import { KubeResource } from "../../../common/rbac";
|
import { KubeResource } from "../../../common/rbac";
|
||||||
|
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
|
||||||
|
|
||||||
export const workloadStores: Partial<Record<KubeResource, KubeObjectStore>> = {
|
export const workloadStores: Partial<Record<KubeResource, KubeObjectStore>> = {
|
||||||
"pods": podsStore,
|
"pods": podsStore,
|
||||||
"deployments": deploymentStore,
|
"deployments": deploymentStore,
|
||||||
"daemonsets": daemonSetStore,
|
"daemonsets": daemonSetStore,
|
||||||
"statefulsets": statefulSetStore,
|
"statefulsets": statefulSetStore,
|
||||||
|
"replicasets": replicaSetStore,
|
||||||
"jobs": jobStore,
|
"jobs": jobStore,
|
||||||
"cronjobs": cronJobStore,
|
"cronjobs": cronJobStore,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
|||||||
import { Trans } from "@lingui/macro";
|
import { Trans } from "@lingui/macro";
|
||||||
import { TabLayout, TabLayoutRoute } from "../layout/tab-layout";
|
import { TabLayout, TabLayoutRoute } from "../layout/tab-layout";
|
||||||
import { WorkloadsOverview } from "../+workloads-overview/overview";
|
import { WorkloadsOverview } from "../+workloads-overview/overview";
|
||||||
import { cronJobsRoute, cronJobsURL, daemonSetsRoute, daemonSetsURL, deploymentsRoute, deploymentsURL, jobsRoute, jobsURL, overviewRoute, overviewURL, podsRoute, podsURL, statefulSetsRoute, statefulSetsURL } from "./workloads.route";
|
import { cronJobsRoute, cronJobsURL, daemonSetsRoute, daemonSetsURL, deploymentsRoute, deploymentsURL, jobsRoute, jobsURL, overviewRoute, overviewURL, podsRoute, podsURL, replicaSetsRoute, replicaSetsURL, statefulSetsRoute, statefulSetsURL } from "./workloads.route";
|
||||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||||
import { Pods } from "../+workloads-pods";
|
import { Pods } from "../+workloads-pods";
|
||||||
import { Deployments } from "../+workloads-deployments";
|
import { Deployments } from "../+workloads-deployments";
|
||||||
@ -14,6 +14,7 @@ import { StatefulSets } from "../+workloads-statefulsets";
|
|||||||
import { Jobs } from "../+workloads-jobs";
|
import { Jobs } from "../+workloads-jobs";
|
||||||
import { CronJobs } from "../+workloads-cronjobs";
|
import { CronJobs } from "../+workloads-cronjobs";
|
||||||
import { isAllowedResource } from "../../../common/rbac";
|
import { isAllowedResource } from "../../../common/rbac";
|
||||||
|
import { ReplicaSets } from "../+workloads-replicasets";
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class Workloads extends React.Component {
|
export class Workloads extends React.Component {
|
||||||
@ -64,6 +65,15 @@ export class Workloads extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAllowedResource("replicasets")) {
|
||||||
|
routes.push({
|
||||||
|
title: <Trans>ReplicaSets</Trans>,
|
||||||
|
component: ReplicaSets,
|
||||||
|
url: replicaSetsURL({ query }),
|
||||||
|
routePath: replicaSetsRoute.path.toString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (isAllowedResource("jobs")) {
|
if (isAllowedResource("jobs")) {
|
||||||
routes.push({
|
routes.push({
|
||||||
title: <Trans>Jobs</Trans>,
|
title: <Trans>Jobs</Trans>,
|
||||||
|
|||||||
@ -48,6 +48,7 @@ import { reaction, computed } from "mobx";
|
|||||||
import { nodesStore } from "./+nodes/nodes.store";
|
import { nodesStore } from "./+nodes/nodes.store";
|
||||||
import { podsStore } from "./+workloads-pods/pods.store";
|
import { podsStore } from "./+workloads-pods/pods.store";
|
||||||
import { sum } from "lodash";
|
import { sum } from "lodash";
|
||||||
|
import { ReplicaSetScaleDialog } from "./+workloads-replicasets/replicaset-scale-dialog";
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class App extends React.Component {
|
export class App extends React.Component {
|
||||||
@ -204,6 +205,7 @@ export class App extends React.Component {
|
|||||||
<AddRoleBindingDialog/>
|
<AddRoleBindingDialog/>
|
||||||
<DeploymentScaleDialog/>
|
<DeploymentScaleDialog/>
|
||||||
<StatefulSetScaleDialog/>
|
<StatefulSetScaleDialog/>
|
||||||
|
<ReplicaSetScaleDialog/>
|
||||||
<CronJobTriggerDialog/>
|
<CronJobTriggerDialog/>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user