diff --git a/i18n/de/messages.de.xlf b/i18n/de/messages.de.xlf index b3b6778ccc5f..b7535f3c4bb2 100644 --- a/i18n/de/messages.de.xlf +++ b/i18n/de/messages.de.xlf @@ -603,6 +603,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1394,13 +1398,21 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces Namespaces src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -1409,7 +1421,7 @@ src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -1418,7 +1430,7 @@ src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -1427,7 +1439,7 @@ src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -1436,7 +1448,7 @@ src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -1445,7 +1457,7 @@ src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -1454,7 +1466,7 @@ src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -1463,7 +1475,7 @@ src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -1472,7 +1484,7 @@ src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -1489,7 +1501,7 @@ src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -1498,7 +1510,7 @@ src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -2009,6 +2021,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -2614,6 +2630,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -2673,6 +2709,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3551,6 +3591,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5181,6 +5225,10 @@ Parameter Parameter + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/i18n/es/messages.es.xlf b/i18n/es/messages.es.xlf index 3274e4cb0297..f98e60177322 100644 --- a/i18n/es/messages.es.xlf +++ b/i18n/es/messages.es.xlf @@ -603,6 +603,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1393,12 +1397,20 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces Espacios de Nombre src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -1406,7 +1418,7 @@ Políticas de Red src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -1414,7 +1426,7 @@ Nodos src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -1422,7 +1434,7 @@ Volúmenes Persistentes src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -1430,7 +1442,7 @@ Vinculaciones de roles src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -1438,7 +1450,7 @@ Roles src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -1446,7 +1458,7 @@ Cuentas de Servicio src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -1454,7 +1466,7 @@ Definiciones de recursos personalizadas src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -1462,7 +1474,7 @@ Complementos src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -1478,7 +1490,7 @@ Ajustes src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -1487,7 +1499,7 @@ src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -1998,6 +2010,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -2603,6 +2619,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -2662,6 +2698,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3540,6 +3580,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5170,6 +5214,10 @@ Parameter Parámetro + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/i18n/fr/messages.fr.xlf b/i18n/fr/messages.fr.xlf index 12db837aa386..7f12da9a596a 100644 --- a/i18n/fr/messages.fr.xlf +++ b/i18n/fr/messages.fr.xlf @@ -603,6 +603,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1394,13 +1398,21 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces Namespaces src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -1409,7 +1421,7 @@ src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -1418,7 +1430,7 @@ src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -1427,7 +1439,7 @@ src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -1436,7 +1448,7 @@ src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -1445,7 +1457,7 @@ src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -1454,7 +1466,7 @@ src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -1463,7 +1475,7 @@ src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -1472,7 +1484,7 @@ src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -1489,7 +1501,7 @@ src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -1498,7 +1510,7 @@ src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -2009,6 +2021,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -2614,6 +2630,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -2673,6 +2709,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3551,6 +3591,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5192,6 +5236,10 @@ Parameter Paramètre + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/i18n/ja/messages.ja.xlf b/i18n/ja/messages.ja.xlf index 06f147f5c26f..390bfdbe7369 100644 --- a/i18n/ja/messages.ja.xlf +++ b/i18n/ja/messages.ja.xlf @@ -784,6 +784,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -924,6 +928,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1289,6 +1297,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -1348,6 +1376,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3360,13 +3392,21 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces ネームスペース src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -3375,7 +3415,7 @@ src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -3384,7 +3424,7 @@ src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -3393,7 +3433,7 @@ src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -3402,7 +3442,7 @@ src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -3411,7 +3451,7 @@ src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -3420,7 +3460,7 @@ src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -3429,7 +3469,7 @@ src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -3438,7 +3478,7 @@ src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -3455,7 +3495,7 @@ src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -3464,7 +3504,7 @@ src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -3706,6 +3746,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5268,6 +5312,10 @@ Parameter パラメーター + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/i18n/ko/messages.ko.xlf b/i18n/ko/messages.ko.xlf index 2520d3f980d7..c8c315d0b97c 100644 --- a/i18n/ko/messages.ko.xlf +++ b/i18n/ko/messages.ko.xlf @@ -919,6 +919,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -1059,6 +1063,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1424,6 +1432,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -1483,6 +1511,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3343,13 +3375,21 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces 네임스페이스 src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -3358,7 +3398,7 @@ src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -3367,7 +3407,7 @@ src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -3376,7 +3416,7 @@ src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -3385,7 +3425,7 @@ src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -3394,7 +3434,7 @@ src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -3403,7 +3443,7 @@ src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -3412,7 +3452,7 @@ src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -3421,7 +3461,7 @@ src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -3438,7 +3478,7 @@ src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -3447,7 +3487,7 @@ src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -3693,6 +3733,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5335,6 +5379,10 @@ Parameter 파라미터 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/i18n/messages.xlf b/i18n/messages.xlf index 6e27ebee81c3..5554e8bce4d2 100644 --- a/i18n/messages.xlf +++ b/i18n/messages.xlf @@ -349,6 +349,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -812,6 +816,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1419,62 +1427,6 @@ 27 - - Select namespace... - - src/app/frontend/common/components/namespace/template.html - 24 - - - - NAMESPACES - - src/app/frontend/common/components/namespace/template.html - 34 - - - - All namespaces - - src/app/frontend/common/components/namespace/template.html - 33 - - - - Namespace conflict - - src/app/frontend/common/components/namespace/changedialog/template.html - 19 - - - - Selected namespace is different than namespace of currently selected resource. - - src/app/frontend/common/components/namespace/changedialog/template.html - 22 - - - - Do you want to stay on current page and change namespace from to ? - - src/app/frontend/common/components/namespace/changedialog/template.html - 24,26 - - - - Yes - - src/app/frontend/common/components/namespace/changedialog/template.html - 32 - - - - No - - src/app/frontend/common/components/namespace/changedialog/template.html - 35 - - Metadata @@ -1532,6 +1484,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -1737,6 +1693,41 @@ 88 + + Namespace conflict + + src/app/frontend/common/components/namespace/changedialog/template.html + 19 + + + + Selected namespace is different than namespace of currently selected resource. + + src/app/frontend/common/components/namespace/changedialog/template.html + 22 + + + + Do you want to stay on current page and change namespace from to ? + + src/app/frontend/common/components/namespace/changedialog/template.html + 24,26 + + + + Yes + + src/app/frontend/common/components/namespace/changedialog/template.html + 32 + + + + No + + src/app/frontend/common/components/namespace/changedialog/template.html + 35 + + Pods status @@ -1923,6 +1914,27 @@ 90 + + Select namespace... + + src/app/frontend/common/components/namespace/template.html + 24 + + + + NAMESPACES + + src/app/frontend/common/components/namespace/template.html + 34 + + + + All namespaces + + src/app/frontend/common/components/namespace/template.html + 33 + + Resource Quotas @@ -2168,6 +2180,24 @@ 68 + + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Ingresses @@ -2719,13 +2749,6 @@ 60 - - Workload Status - - src/app/frontend/common/components/workloadstatus/template.html - 20 - - You can deploy a containerized app, select other namespace or take the Dashboard Tour open_in_new to learn more. @@ -2733,6 +2756,13 @@ 26,35 + + Workload Status + + src/app/frontend/common/components/workloadstatus/template.html + 20 + + Workloads @@ -2880,81 +2910,88 @@ 125 + + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces src/app/frontend/chrome/nav/template.html - 129 + 133 Network Policies src/app/frontend/chrome/nav/template.html - 134,135 + 138,139 Nodes src/app/frontend/chrome/nav/template.html - 139 + 143 Persistent Volumes src/app/frontend/chrome/nav/template.html - 143,144 + 147,148 Role Bindings src/app/frontend/chrome/nav/template.html - 149,150 + 153,154 Roles src/app/frontend/chrome/nav/template.html - 155 + 159 Service Accounts src/app/frontend/chrome/nav/template.html - 160,161 + 164,165 Custom Resource Definitions src/app/frontend/chrome/nav/template.html - 168,169 + 172,173 Settings src/app/frontend/chrome/nav/template.html - 187 + 191 About src/app/frontend/chrome/nav/template.html - 192 + 196 Plugins src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -3489,6 +3526,13 @@ 35 + + Shell in in + + src/app/frontend/shell/template.html + 22,33 + + About @@ -3717,13 +3761,6 @@ 28 - - Shell in in - - src/app/frontend/shell/template.html - 22,33 - - Local settings @@ -3851,12 +3888,27 @@ 22 + + There is no data to display. + + src/app/frontend/resource/config/configmap/detail/template.html + 32 + + + src/app/frontend/resource/config/secret/detail/template.html + 40 + + Resource information src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -3929,19 +3981,12 @@ Parameter - src/app/frontend/resource/config/storageclass/detail/template.html + src/app/frontend/resource/cluster/ingressclass/detail/template.html 37 - - - There is no data to display. - - src/app/frontend/resource/config/configmap/detail/template.html - 32 - - src/app/frontend/resource/config/secret/detail/template.html - 40 + src/app/frontend/resource/config/storageclass/detail/template.html + 37 diff --git a/i18n/zh-Hans/messages.zh-Hans.xlf b/i18n/zh-Hans/messages.zh-Hans.xlf index 3ed657f42ed0..ec91f7cd5314 100644 --- a/i18n/zh-Hans/messages.zh-Hans.xlf +++ b/i18n/zh-Hans/messages.zh-Hans.xlf @@ -919,6 +919,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -1059,6 +1063,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1424,6 +1432,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -1483,6 +1511,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3332,12 +3364,20 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces 命名空间 src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -3345,7 +3385,7 @@ 网络策略 src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -3353,7 +3393,7 @@ Nodes src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -3361,7 +3401,7 @@ Persistent Volumes src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -3369,7 +3409,7 @@ Role Bindings src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -3377,7 +3417,7 @@ Roles src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -3385,7 +3425,7 @@ 服务账号 src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -3393,7 +3433,7 @@ 自定义资源 src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -3401,7 +3441,7 @@ 插件 src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -3417,7 +3457,7 @@ 设置 src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -3425,7 +3465,7 @@ 关于 src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -3657,6 +3697,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5196,6 +5240,10 @@ Parameter 参数 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf b/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf index 50cfdc358729..b87285c9f1a0 100644 --- a/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf +++ b/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf @@ -919,6 +919,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -1059,6 +1063,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1424,6 +1432,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -1483,6 +1511,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3335,13 +3367,21 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces Namespaces src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -3350,7 +3390,7 @@ src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -3359,7 +3399,7 @@ src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -3368,7 +3408,7 @@ src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -3377,7 +3417,7 @@ src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -3386,7 +3426,7 @@ src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -3395,7 +3435,7 @@ src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -3404,7 +3444,7 @@ src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -3413,7 +3453,7 @@ src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -3430,7 +3470,7 @@ src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -3439,7 +3479,7 @@ src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -3685,6 +3725,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5330,6 +5374,10 @@ Parameter 參數 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/i18n/zh-Hant/messages.zh-Hant.xlf b/i18n/zh-Hant/messages.zh-Hant.xlf index 695b9cc9d871..ebbf6549348a 100644 --- a/i18n/zh-Hant/messages.zh-Hant.xlf +++ b/i18n/zh-Hant/messages.zh-Hant.xlf @@ -919,6 +919,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 23 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 23 + src/app/frontend/common/components/resourcelist/job/template.html 29 @@ -1059,6 +1063,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 44 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 44 + src/app/frontend/common/components/resourcelist/job/template.html 69 @@ -1424,6 +1432,26 @@ 74 + + Ingress Classes + Ingress Classes + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 21 + + + + Controller + Controller + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 55 + + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 29 + + Events Events @@ -1483,6 +1511,10 @@ src/app/frontend/common/components/resourcelist/ingress/template.html 116 + + src/app/frontend/common/components/resourcelist/ingressclass/template.html + 65 + src/app/frontend/common/components/resourcelist/job/template.html 124 @@ -3343,13 +3375,21 @@ 125 + + Ingress Classes + Ingress Classes + + src/app/frontend/chrome/nav/template.html + 129 + + Namespaces Namespaces src/app/frontend/chrome/nav/template.html - 129 + 133 @@ -3358,7 +3398,7 @@ src/app/frontend/chrome/nav/template.html - 134 + 138 @@ -3367,7 +3407,7 @@ src/app/frontend/chrome/nav/template.html - 139 + 143 @@ -3376,7 +3416,7 @@ src/app/frontend/chrome/nav/template.html - 143 + 147 @@ -3385,7 +3425,7 @@ src/app/frontend/chrome/nav/template.html - 149 + 153 @@ -3394,7 +3434,7 @@ src/app/frontend/chrome/nav/template.html - 155 + 159 @@ -3403,7 +3443,7 @@ src/app/frontend/chrome/nav/template.html - 160 + 164 @@ -3412,7 +3452,7 @@ src/app/frontend/chrome/nav/template.html - 168 + 172 @@ -3421,7 +3461,7 @@ src/app/frontend/chrome/nav/template.html - 179 + 183 @@ -3438,7 +3478,7 @@ src/app/frontend/chrome/nav/template.html - 187 + 191 @@ -3447,7 +3487,7 @@ src/app/frontend/chrome/nav/template.html - 192 + 196 @@ -3693,6 +3733,10 @@ src/app/frontend/resource/cluster/clusterrolebinding/detail/template.html 22 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 22 + src/app/frontend/resource/cluster/namespace/detail/template.html 22 @@ -5338,6 +5382,10 @@ Parameter 參數 + + src/app/frontend/resource/cluster/ingressclass/detail/template.html + 37 + src/app/frontend/resource/config/storageclass/detail/template.html 37 diff --git a/src/app/backend/api/types.go b/src/app/backend/api/types.go index 9e4ebc44a97b..d1131abff1d6 100644 --- a/src/app/backend/api/types.go +++ b/src/app/backend/api/types.go @@ -148,6 +148,7 @@ const ( ResourceKindPlugin = "plugin" ResourceKindEndpoint = "endpoint" ResourceKindNetworkPolicy = "networkpolicy" + ResourceKindIngressClass = "ingressclass" ) // Scalable method return whether ResourceKind is scalable. @@ -224,6 +225,7 @@ var KindToAPIMapping = map[string]APIMapping{ ResourceKindEvent: {"events", ClientTypeDefault, true}, ResourceKindHorizontalPodAutoscaler: {"horizontalpodautoscalers", ClientTypeAutoscalingClient, true}, ResourceKindIngress: {"ingresses", ClientTypeNetworkingClient, true}, + ResourceKindIngressClass: {"ingressclasses", ClientTypeNetworkingClient, false}, ResourceKindJob: {"jobs", ClientTypeBatchClient, true}, ResourceKindCronJob: {"cronjobs", ClientTypeBetaBatchClient, true}, ResourceKindLimitRange: {"limitrange", ClientTypeDefault, true}, diff --git a/src/app/backend/handler/apihandler.go b/src/app/backend/handler/apihandler.go index 29cebc5b0885..f320273e7729 100644 --- a/src/app/backend/handler/apihandler.go +++ b/src/app/backend/handler/apihandler.go @@ -54,6 +54,7 @@ import ( "github.com/kubernetes/dashboard/src/app/backend/resource/event" "github.com/kubernetes/dashboard/src/app/backend/resource/horizontalpodautoscaler" "github.com/kubernetes/dashboard/src/app/backend/resource/ingress" + "github.com/kubernetes/dashboard/src/app/backend/resource/ingressclass" "github.com/kubernetes/dashboard/src/app/backend/resource/job" "github.com/kubernetes/dashboard/src/app/backend/resource/logs" ns "github.com/kubernetes/dashboard/src/app/backend/resource/namespace" @@ -688,6 +689,15 @@ func CreateHTTPAPIHandler(iManager integration.IntegrationManager, cManager clie To(apiHandler.handleGetStorageClassPersistentVolumes). Writes(persistentvolume.PersistentVolumeList{})) + apiV1Ws.Route( + apiV1Ws.GET("/ingressclass"). + To(apiHandler.handleGetIngressClassList). + Writes(ingressclass.IngressClassList{})) + apiV1Ws.Route( + apiV1Ws.GET("/ingressclass/{ingressclass}"). + To(apiHandler.handleGetIngressClass). + Writes(ingressclass.IngressClass{})) + apiV1Ws.Route( apiV1Ws.GET("/log/source/{namespace}/{resourceName}/{resourceType}"). To(apiHandler.handleLogSource). @@ -2554,6 +2564,38 @@ func (apiHandler *APIHandler) handleGetStorageClassPersistentVolumes(request *re response.WriteHeaderAndEntity(http.StatusOK, result) } +func (apiHandler *APIHandler) handleGetIngressClassList(request *restful.Request, response *restful.Response) { + k8sClient, err := apiHandler.cManager.Client(request) + if err != nil { + errors.HandleInternalError(response, err) + return + } + + dataSelect := parser.ParseDataSelectPathParameter(request) + result, err := ingressclass.GetIngressClassList(k8sClient, dataSelect) + if err != nil { + errors.HandleInternalError(response, err) + return + } + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +func (apiHandler *APIHandler) handleGetIngressClass(request *restful.Request, response *restful.Response) { + k8sClient, err := apiHandler.cManager.Client(request) + if err != nil { + errors.HandleInternalError(response, err) + return + } + + name := request.PathParameter("ingressclass") + result, err := ingressclass.GetIngressClass(k8sClient, name) + if err != nil { + errors.HandleInternalError(response, err) + return + } + response.WriteHeaderAndEntity(http.StatusOK, result) +} + func (apiHandler *APIHandler) handleGetPodPersistentVolumeClaims(request *restful.Request, response *restful.Response) { k8sClient, err := apiHandler.cManager.Client(request) diff --git a/src/app/backend/resource/common/resourcechannels.go b/src/app/backend/resource/common/resourcechannels.go index 5ea6b75633d0..32507b30331e 100644 --- a/src/app/backend/resource/common/resourcechannels.go +++ b/src/app/backend/resource/common/resourcechannels.go @@ -112,6 +112,9 @@ type ResourceChannels struct { // List and error channels to StorageClasses StorageClassList StorageClassListChannel + // List and error channels to IngressClasses + IngressClassList IngressClassListChannel + // List and error channels to Roles RoleList RoleListChannel @@ -943,3 +946,28 @@ func GetStorageClassListChannel(client client.Interface, numReads int) StorageCl return channel } + +// IngressClassListChannel is a list and error channels to ingress classes. +type IngressClassListChannel struct { + List chan *networkingv1.IngressClassList + Error chan error +} + +// GetIngressClassListChannel returns a pair of channels to a ingress class list and +// errors that both must be read numReads times. +func GetIngressClassListChannel(client client.Interface, numReads int) IngressClassListChannel { + channel := IngressClassListChannel{ + List: make(chan *networkingv1.IngressClassList, numReads), + Error: make(chan error, numReads), + } + + go func() { + list, err := client.NetworkingV1().IngressClasses().List(context.TODO(), api.ListEverything) + for i := 0; i < numReads; i++ { + channel.List <- list + channel.Error <- err + } + }() + + return channel +} diff --git a/src/app/backend/resource/ingressclass/common.go b/src/app/backend/resource/ingressclass/common.go new file mode 100644 index 000000000000..5cfe080ef5ff --- /dev/null +++ b/src/app/backend/resource/ingressclass/common.go @@ -0,0 +1,54 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ingressclass + +import ( + "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect" + networkingv1 "k8s.io/api/networking/v1" +) + +// The code below allows to perform complex data section on []networkingv1.IngressClass + +type IngressClassCell networkingv1.IngressClass + +func (self IngressClassCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue { + switch name { + case dataselect.NameProperty: + return dataselect.StdComparableString(self.ObjectMeta.Name) + case dataselect.CreationTimestampProperty: + return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time) + case dataselect.NamespaceProperty: + return dataselect.StdComparableString(self.ObjectMeta.Namespace) + default: + // if name is not supported then just return a constant dummy value, sort will have no effect. + return nil + } +} + +func toCells(std []networkingv1.IngressClass) []dataselect.DataCell { + cells := make([]dataselect.DataCell, len(std)) + for i := range std { + cells[i] = IngressClassCell(std[i]) + } + return cells +} + +func fromCells(cells []dataselect.DataCell) []networkingv1.IngressClass { + std := make([]networkingv1.IngressClass, len(cells)) + for i := range std { + std[i] = networkingv1.IngressClass(cells[i].(IngressClassCell)) + } + return std +} diff --git a/src/app/backend/resource/ingressclass/detail.go b/src/app/backend/resource/ingressclass/detail.go new file mode 100644 index 000000000000..278aae0441e8 --- /dev/null +++ b/src/app/backend/resource/ingressclass/detail.go @@ -0,0 +1,68 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ingressclass + +import ( + "context" + "log" + + networkingv1 "k8s.io/api/networking/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +// IngressClassDetail provides the presentation layer view of Ingress Class resource. +type IngressClassDetail struct { + // Extends list item structure. + IngressClass `json:",inline"` + Parameters map[string]string `json:"parameters"` +} + +// GetIngressClass returns Storage Class resource. +func GetIngressClass(client kubernetes.Interface, name string) (*IngressClassDetail, error) { + log.Printf("Getting details of %s ingress class", name) + + ic, err := client.NetworkingV1().IngressClasses().Get(context.TODO(), name, metaV1.GetOptions{}) + if err != nil { + return nil, err + } + + ingressClass := toIngressClassDetail(ic) + return &ingressClass, err +} + +func toIngressClassDetail(ingressClass *networkingv1.IngressClass) IngressClassDetail { + parametersMap := make(map[string]string) + parameters := ingressClass.Spec.Parameters + if parameters != nil { + // Mandatory parameters + parametersMap["Kind"] = parameters.Kind + parametersMap["Name"] = parameters.Name + // Optional parameters + if parameters.APIGroup != nil { + parametersMap["ApiGroup"] = *parameters.APIGroup + } + if parameters.Namespace != nil { + parametersMap["Namespace"] = *parameters.Namespace + } + if parameters.Scope != nil { + parametersMap["Scope"] = *parameters.Scope + } + } + return IngressClassDetail{ + IngressClass: toIngressClass(ingressClass), + Parameters: parametersMap, + } +} diff --git a/src/app/backend/resource/ingressclass/detail_test.go b/src/app/backend/resource/ingressclass/detail_test.go new file mode 100644 index 000000000000..63669487c3c9 --- /dev/null +++ b/src/app/backend/resource/ingressclass/detail_test.go @@ -0,0 +1,69 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ingressclass + +import ( + "reflect" + "testing" + + "github.com/kubernetes/dashboard/src/app/backend/api" + networkingv1 "k8s.io/api/networking/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestToIngressClassDetails(t *testing.T) { + paramRef := networkingv1.IngressClassParametersReference{Kind: "pods", Name: "test"} + apiGroup := "k8s.example.com" + scope := "Namespace" + paramFullRef := networkingv1.IngressClassParametersReference{Kind: "pods", Name: "test", APIGroup: &apiGroup, Scope: &scope} + cases := []struct { + ingressClass *networkingv1.IngressClass + expected IngressClassDetail + }{ + { + ingressClass: &networkingv1.IngressClass{ + ObjectMeta: metaV1.ObjectMeta{Name: "test-ic"}, + Spec: networkingv1.IngressClassSpec{Controller: "k8s.io/ingress-nginx", Parameters: ¶mRef}, + }, + expected: IngressClassDetail{ + IngressClass: IngressClass{ + ObjectMeta: api.ObjectMeta{Name: "test-ic"}, + TypeMeta: api.TypeMeta{Kind: "ingressclass"}, + Controller: "k8s.io/ingress-nginx"}, + Parameters: map[string]string{"Kind": "pods", "Name": "test"}, + }, + }, { + ingressClass: &networkingv1.IngressClass{ + ObjectMeta: metaV1.ObjectMeta{Name: "test-ic"}, + Spec: networkingv1.IngressClassSpec{Controller: "k8s.io/ingress-nginx", Parameters: ¶mFullRef}, + }, + expected: IngressClassDetail{ + IngressClass: IngressClass{ + ObjectMeta: api.ObjectMeta{Name: "test-ic"}, + TypeMeta: api.TypeMeta{Kind: "ingressclass"}, + Controller: "k8s.io/ingress-nginx"}, + Parameters: map[string]string{"ApiGroup": "k8s.example.com", "Kind": "pods", "Name": "test", "Scope": "Namespace"}, + }, + }, + } + + for _, c := range cases { + actual := toIngressClassDetail(c.ingressClass) + + if !reflect.DeepEqual(actual, c.expected) { + t.Errorf("toIngressClassDetails(%#v) == \ngot %#v, \nexpected %#v", c.ingressClass, actual, c.expected) + } + } +} diff --git a/src/app/backend/resource/ingressclass/list.go b/src/app/backend/resource/ingressclass/list.go new file mode 100644 index 000000000000..149509fdc8db --- /dev/null +++ b/src/app/backend/resource/ingressclass/list.go @@ -0,0 +1,95 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ingressclass + +import ( + "log" + + "github.com/kubernetes/dashboard/src/app/backend/api" + "github.com/kubernetes/dashboard/src/app/backend/errors" + "github.com/kubernetes/dashboard/src/app/backend/resource/common" + "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect" + networkingv1 "k8s.io/api/networking/v1" + "k8s.io/client-go/kubernetes" +) + +// IngressClassList holds a list of Ingress Class objects in the cluster. +type IngressClassList struct { + ListMeta api.ListMeta `json:"listMeta"` + Items []IngressClass `json:"items"` + + // List of non-critical errors, that occurred during resource retrieval. + Errors []error `json:"errors"` +} + +// IngressClass is a representation of a Kubernetes Ingress Class object. +type IngressClass struct { + ObjectMeta api.ObjectMeta `json:"objectMeta"` + TypeMeta api.TypeMeta `json:"typeMeta"` + Controller string `json:"controller"` +} + +// GetIngressClassList returns a list of all Ingress class objects in the cluster. +func GetIngressClassList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) ( + *IngressClassList, error) { + log.Print("Getting list of ingress classes in the cluster") + + channels := &common.ResourceChannels{ + IngressClassList: common.GetIngressClassListChannel(client, 1), + } + + return GetIngressClassListFromChannels(channels, dsQuery) +} + +// GetIngressClassListFromChannels returns a list of all ingress class objects in the cluster. +func GetIngressClassListFromChannels(channels *common.ResourceChannels, + dsQuery *dataselect.DataSelectQuery) (*IngressClassList, error) { + ingressClasses := <-channels.IngressClassList.List + err := <-channels.IngressClassList.Error + nonCriticalErrors, criticalError := errors.HandleError(err) + if criticalError != nil { + return nil, criticalError + } + + return toIngressClassList(ingressClasses.Items, nonCriticalErrors, dsQuery), nil +} + +func toIngressClassList(ingressClasses []networkingv1.IngressClass, nonCriticalErrors []error, + dsQuery *dataselect.DataSelectQuery) *IngressClassList { + + ingressClassList := &IngressClassList{ + Items: make([]IngressClass, 0), + ListMeta: api.ListMeta{TotalItems: len(ingressClasses)}, + Errors: nonCriticalErrors, + } + + ingressClassCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(ingressClasses), dsQuery) + ingressClasses = fromCells(ingressClassCells) + ingressClassList.ListMeta = api.ListMeta{TotalItems: filteredTotal} + + for _, ingressClass := range ingressClasses { + ingressClassList.Items = append(ingressClassList.Items, toIngressClass(&ingressClass)) + } + + return ingressClassList +} + +func toIngressClass(ingressClass *networkingv1.IngressClass) IngressClass { + return IngressClass{ + ObjectMeta: api.NewObjectMeta(ingressClass.ObjectMeta), + TypeMeta: api.NewTypeMeta(api.ResourceKindIngressClass), + Controller: ingressClass.Spec.Controller, + } +} diff --git a/src/app/backend/resource/ingressclass/list_test.go b/src/app/backend/resource/ingressclass/list_test.go new file mode 100644 index 000000000000..4f93bdf5c8e3 --- /dev/null +++ b/src/app/backend/resource/ingressclass/list_test.go @@ -0,0 +1,134 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ingressclass + +import ( + "reflect" + "testing" + + "github.com/kubernetes/dashboard/src/app/backend/api" + "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect" + networkingv1 "k8s.io/api/networking/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" +) + +func TestGetIngressClassList(t *testing.T) { + cases := []struct { + ingressClassList *networkingv1.IngressClassList + expectedActions []string + expected *IngressClassList + }{ + { + ingressClassList: &networkingv1.IngressClassList{ + Items: []networkingv1.IngressClass{ + { + ObjectMeta: metaV1.ObjectMeta{ + Name: "ingress-1", + Labels: map[string]string{}, + }, + }, + }}, + expectedActions: []string{"list"}, + expected: &IngressClassList{ + ListMeta: api.ListMeta{TotalItems: 1}, + Items: []IngressClass{ + { + ObjectMeta: api.ObjectMeta{ + Name: "ingress-1", + Labels: map[string]string{}, + }, + TypeMeta: api.TypeMeta{Kind: api.ResourceKindIngressClass}, + }, + }, + Errors: []error{}, + }, + }, + } + + for _, c := range cases { + fakeClient := fake.NewSimpleClientset(c.ingressClassList) + + actual, _ := GetIngressClassList(fakeClient, dataselect.NoDataSelect) + + actions := fakeClient.Actions() + if len(actions) != len(c.expectedActions) { + t.Errorf("Unexpected actions: %v, expected %d actions got %d", actions, + len(c.expectedActions), len(actions)) + continue + } + + for i, verb := range c.expectedActions { + if actions[i].GetVerb() != verb { + t.Errorf("Unexpected action: %+v, expected %s", + actions[i], verb) + } + } + + if !reflect.DeepEqual(actual, c.expected) { + t.Errorf("GetIngressClassList(client) == got\n%#v, expected\n %#v", actual, c.expected) + } + } +} + +func TestToIngressClass(t *testing.T) { + paramRef := networkingv1.IngressClassParametersReference{Kind: "pods", Name: "test"} + cases := []struct { + ingressClass *networkingv1.IngressClass + expected IngressClass + }{ + { + ingressClass: &networkingv1.IngressClass{}, + expected: IngressClass{ + TypeMeta: api.TypeMeta{Kind: api.ResourceKindIngressClass}, + }, + }, { + ingressClass: &networkingv1.IngressClass{ + ObjectMeta: metaV1.ObjectMeta{Name: "test-ic"}}, + expected: IngressClass{ + ObjectMeta: api.ObjectMeta{Name: "test-ic"}, + TypeMeta: api.TypeMeta{Kind: api.ResourceKindIngressClass}, + }, + }, { + ingressClass: &networkingv1.IngressClass{ + ObjectMeta: metaV1.ObjectMeta{Name: "test-ic"}, + Spec: networkingv1.IngressClassSpec{Controller: "k8s.io/ingress-nginx"}, + }, + expected: IngressClass{ + ObjectMeta: api.ObjectMeta{Name: "test-ic"}, + TypeMeta: api.TypeMeta{Kind: api.ResourceKindIngressClass}, + Controller: "k8s.io/ingress-nginx", + }, + }, { + ingressClass: &networkingv1.IngressClass{ + ObjectMeta: metaV1.ObjectMeta{Name: "test-ic"}, + Spec: networkingv1.IngressClassSpec{Controller: "k8s.io/ingress-nginx", Parameters: ¶mRef}, + }, + expected: IngressClass{ + ObjectMeta: api.ObjectMeta{Name: "test-ic"}, + TypeMeta: api.TypeMeta{Kind: api.ResourceKindIngressClass}, + Controller: "k8s.io/ingress-nginx", + }, + }, + } + + for _, c := range cases { + actual := toIngressClass(c.ingressClass) + + if !reflect.DeepEqual(actual, c.expected) { + t.Errorf("toIngressClass(%#v) == \ngot %#v, \nexpected %#v", c.ingressClass, actual, c.expected) + } + } +} diff --git a/src/app/frontend/chrome/nav/template.html b/src/app/frontend/chrome/nav/template.html index c27d4f43884e..5f0047df2d30 100644 --- a/src/app/frontend/chrome/nav/template.html +++ b/src/app/frontend/chrome/nav/template.html @@ -123,6 +123,10 @@ id="nav-events" [namespaced]="true" i18n>Events + Ingress Classes import('resource/cluster/rolebinding/module').then(m => m.RoleBingingModule), }, + { + path: 'ingressclass', + loadChildren: () => import('resource/cluster/ingressclass/module').then(m => m.IngressClassModule), + }, // Overview { diff --git a/src/app/frontend/common/components/module.ts b/src/app/frontend/common/components/module.ts index 8187f2abdd12..9b846e63085d 100644 --- a/src/app/frontend/common/components/module.ts +++ b/src/app/frontend/common/components/module.ts @@ -78,6 +78,7 @@ import {DaemonSetListComponent} from './resourcelist/daemonset/component'; import {DeploymentListComponent} from './resourcelist/deployment/component'; import {EventListComponent} from './resourcelist/event/component'; import {HorizontalPodAutoscalerListComponent} from './resourcelist/horizontalpodautoscaler/component'; +import {IngressClassListComponent} from './resourcelist/ingressclass/component'; import {IngressListComponent} from './resourcelist/ingress/component'; import {JobListComponent} from './resourcelist/job/component'; import {NamespaceListComponent} from './resourcelist/namespace/component'; @@ -146,6 +147,7 @@ const components = [ GraphMetricsComponent, HiddenPropertyComponent, HorizontalPodAutoscalerListComponent, + IngressClassListComponent, IngressListComponent, IngressRuleFlatListComponent, InternalEndpointComponent, diff --git a/src/app/frontend/common/components/resourcelist/groupids.ts b/src/app/frontend/common/components/resourcelist/groupids.ts index b0371298f758..1d16eec685ed 100644 --- a/src/app/frontend/common/components/resourcelist/groupids.ts +++ b/src/app/frontend/common/components/resourcelist/groupids.ts @@ -21,6 +21,7 @@ export enum ListIdentifier { node = 'nodeList', persistentVolume = 'persistentVolumeList', storageClass = 'storageClassList', + ingressClass = 'ingressClassList', cronJob = 'cronJobList', crd = 'crdList', crdObject = 'crdObjectList', diff --git a/src/app/frontend/common/components/resourcelist/ingressclass/component.ts b/src/app/frontend/common/components/resourcelist/ingressclass/component.ts new file mode 100644 index 000000000000..02e971f61ffb --- /dev/null +++ b/src/app/frontend/common/components/resourcelist/ingressclass/component.ts @@ -0,0 +1,59 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {HttpParams} from '@angular/common/http'; +import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input} from '@angular/core'; +import {IngressClass, IngressClassList} from '@api/root.api'; +import {Observable} from 'rxjs'; + +import {ResourceListBase} from '@common/resources/list'; +import {NotificationsService} from '@common/services/global/notifications'; +import {EndpointManager, Resource} from '@common/services/resource/endpoint'; +import {ResourceService} from '@common/services/resource/resource'; +import {MenuComponent} from '../../list/column/menu/component'; +import {ListGroupIdentifier, ListIdentifier} from '../groupids'; + +@Component({ + selector: 'kd-ingress-class-list', + templateUrl: './template.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class IngressClassListComponent extends ResourceListBase { + @Input() endpoint = EndpointManager.resource(Resource.ingressClass).list(); + + constructor( + private readonly ic_: ResourceService, + notifications: NotificationsService, + cdr: ChangeDetectorRef + ) { + super('ingressclass', notifications, cdr); + this.id = ListIdentifier.ingressClass; + this.groupId = ListGroupIdentifier.cluster; + + // Register action columns. + this.registerActionColumn('menu', MenuComponent); + } + + getResourceObservable(params?: HttpParams): Observable { + return this.ic_.get(this.endpoint, undefined, params); + } + + map(ingressClassList: IngressClassList): IngressClass[] { + return ingressClassList.items; + } + + getDisplayColumns(): string[] { + return ['name', 'controller', 'created']; + } +} diff --git a/src/app/frontend/common/components/resourcelist/ingressclass/template.html b/src/app/frontend/common/components/resourcelist/ingressclass/template.html new file mode 100644 index 000000000000..3a269379769d --- /dev/null +++ b/src/app/frontend/common/components/resourcelist/ingressclass/template.html @@ -0,0 +1,98 @@ + + + +
Ingress Classes
+
Items: {{ totalItems }}
+
+ +
+ +
+
+ + + + Name + + {{ sc.objectMeta.name }} + + + + + Controller + {{ sc.controller }} + + + + Created + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ +
+
diff --git a/src/app/frontend/common/services/resource/endpoint.ts b/src/app/frontend/common/services/resource/endpoint.ts index a441551cedb1..c1e1190473a9 100644 --- a/src/app/frontend/common/services/resource/endpoint.ts +++ b/src/app/frontend/common/services/resource/endpoint.ts @@ -33,6 +33,7 @@ export enum Resource { namespace = 'namespace', persistentVolume = 'persistentvolume', storageClass = 'storageclass', + ingressClass = 'ingressclass', clusterRole = 'clusterrole', clusterRoleBinding = 'clusterrolebinding', role = 'role', diff --git a/src/app/frontend/overview/template.html b/src/app/frontend/overview/template.html index b3a773b55f99..dd3e8c27f5ab 100644 --- a/src/app/frontend/overview/template.html +++ b/src/app/frontend/overview/template.html @@ -76,6 +76,8 @@ [hideable]="true"> + (); + + ingressClass: IngressClassDetail; + isInitialized = false; + + constructor( + private readonly ingressClass_: ResourceService, + private readonly actionbar_: ActionbarService, + private readonly activatedRoute_: ActivatedRoute, + private readonly notifications_: NotificationsService + ) {} + + ngOnInit(): void { + const resourceName = this.activatedRoute_.snapshot.params.resourceName; + + this.ingressClass_ + .get(this.endpoint_.detail(), resourceName) + .pipe(takeUntil(this.unsubscribe_)) + .subscribe((d: IngressClassDetail) => { + this.ingressClass = d; + this.notifications_.pushErrors(d.errors); + this.actionbar_.onInit.emit(new ResourceMeta('Ingress Class', d.objectMeta, d.typeMeta)); + this.isInitialized = true; + }); + } + + ngOnDestroy(): void { + this.unsubscribe_.next(); + this.unsubscribe_.complete(); + this.actionbar_.onDetailsLeave.emit(); + } + + getParameterNames(): string[] { + return this.ingressClass.parameters ? Object.keys(this.ingressClass.parameters) : []; + } +} diff --git a/src/app/frontend/resource/cluster/ingressclass/detail/style.scss b/src/app/frontend/resource/cluster/ingressclass/detail/style.scss new file mode 100644 index 000000000000..1b08d10a84df --- /dev/null +++ b/src/app/frontend/resource/cluster/ingressclass/detail/style.scss @@ -0,0 +1,23 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@use '../../../../variables' as *; +@use '../../../../mixins' as *; + +.kd-ingress-class-parameter-icon { + @include kd-icon-size($caption-font-size-base); + + align-self: center; + margin-left: $baseline-grid * 0.5; +} diff --git a/src/app/frontend/resource/cluster/ingressclass/detail/template.html b/src/app/frontend/resource/cluster/ingressclass/detail/template.html new file mode 100644 index 000000000000..e8f46134a8c4 --- /dev/null +++ b/src/app/frontend/resource/cluster/ingressclass/detail/template.html @@ -0,0 +1,43 @@ + + + + + +
Resource information
+
+ +
Controller
+
{{ ingressClass?.controller }}
+
+ +
+ {{ parameter }} + tune +
+
{{ ingressClass?.parameters[parameter] }}
+
+
+
diff --git a/src/app/frontend/resource/cluster/ingressclass/list/component.ts b/src/app/frontend/resource/cluster/ingressclass/list/component.ts new file mode 100644 index 000000000000..b898242f1d38 --- /dev/null +++ b/src/app/frontend/resource/cluster/ingressclass/list/component.ts @@ -0,0 +1,21 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {Component} from '@angular/core'; + +@Component({ + selector: 'kd-ingress-class-list-state', + template: '', +}) +export class IngressClassListComponent {} diff --git a/src/app/frontend/resource/cluster/ingressclass/module.ts b/src/app/frontend/resource/cluster/ingressclass/module.ts new file mode 100644 index 000000000000..d6bca5594065 --- /dev/null +++ b/src/app/frontend/resource/cluster/ingressclass/module.ts @@ -0,0 +1,28 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {NgModule} from '@angular/core'; + +import {ComponentsModule} from '@common/components/module'; +import {SharedModule} from '../../../shared.module'; + +import {IngressClassDetailComponent} from './detail/component'; +import {IngressClassListComponent} from './list/component'; +import {IngressClassRoutingModule} from './routing'; + +@NgModule({ + imports: [SharedModule, ComponentsModule, IngressClassRoutingModule], + declarations: [IngressClassListComponent, IngressClassDetailComponent], +}) +export class IngressClassModule {} diff --git a/src/app/frontend/resource/cluster/ingressclass/routing.ts b/src/app/frontend/resource/cluster/ingressclass/routing.ts new file mode 100644 index 000000000000..d091d76147a0 --- /dev/null +++ b/src/app/frontend/resource/cluster/ingressclass/routing.ts @@ -0,0 +1,46 @@ +// Copyright 2017 The Kubernetes Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {NgModule} from '@angular/core'; +import {Route, RouterModule} from '@angular/router'; +import {DEFAULT_ACTIONBAR} from '@common/components/actionbars/routing'; + +import {CLUSTER_ROUTE} from '../routing'; + +import {IngressClassDetailComponent} from './detail/component'; +import {IngressClassListComponent} from './list/component'; + +const INGRESSCLASS_LIST_ROUTE: Route = { + path: '', + component: IngressClassListComponent, + data: { + breadcrumb: 'Ingress Classes', + parent: CLUSTER_ROUTE, + }, +}; + +const INGRESSCLASS_DETAIL_ROUTE: Route = { + path: ':resourceName', + component: IngressClassDetailComponent, + data: { + breadcrumb: '{{ resourceName }}', + parent: INGRESSCLASS_LIST_ROUTE, + }, +}; + +@NgModule({ + imports: [RouterModule.forChild([INGRESSCLASS_LIST_ROUTE, INGRESSCLASS_DETAIL_ROUTE, DEFAULT_ACTIONBAR])], + exports: [RouterModule], +}) +export class IngressClassRoutingModule {} diff --git a/src/app/frontend/search/template.html b/src/app/frontend/search/template.html index 2f68dd6eb41c..18dc090b74c6 100644 --- a/src/app/frontend/search/template.html +++ b/src/app/frontend/search/template.html @@ -85,6 +85,8 @@ [hideable]="true"> + diff --git a/src/app/frontend/typings/root.api.ts b/src/app/frontend/typings/root.api.ts index d1b9081a6874..4a07b1bb1595 100644 --- a/src/app/frontend/typings/root.api.ts +++ b/src/app/frontend/typings/root.api.ts @@ -211,6 +211,10 @@ export interface StorageClassList extends ResourceList { items: StorageClass[]; } +export interface IngressClassList extends ResourceList { + items: IngressClass[]; +} + // Simple detail types export type ClusterRole = Resource; @@ -405,6 +409,11 @@ export interface StorageClass extends Resource { parameters: StringMap[]; } +export interface IngressClass extends Resource { + controller: string; + parameters: StringMap[]; +} + // Detail types export interface ReplicaSetDetail extends ResourceDetail { @@ -581,6 +590,11 @@ export interface StorageClassDetail extends ResourceDetail { provisioner: string; } +export interface IngressClassDetail extends ResourceDetail { + parameters: StringMap; + controller: string; +} + export interface ConfigMapDetail extends ResourceDetail { data: StringMap; }