diff --git a/i18n/de/messages.de.xlf b/i18n/de/messages.de.xlf index d142564577b..2d0f2634714 100644 --- a/i18n/de/messages.de.xlf +++ b/i18n/de/messages.de.xlf @@ -702,13 +702,17 @@ 51 - ../src/app/frontend/create/from/form/environmentvariables/template.html - 29 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 + + ../src/app/frontend/create/from/form/environmentvariables/template.html + 29 + Namespace @@ -786,13 +790,17 @@ 63 - ../src/app/frontend/create/from/form/template.html - 184 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 + + ../src/app/frontend/create/from/form/template.html + 184 + Age @@ -882,13 +890,17 @@ 69 - ../src/app/frontend/create/from/form/template.html - 164 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 + + ../src/app/frontend/create/from/form/template.html + 164 + Annotations @@ -1290,6 +1302,14 @@ 91 + + Service Accounts + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + Items:  Elemente:  @@ -1409,6 +1429,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Host @@ -1770,6 +1794,14 @@ 58 + + + + + ../src/app/frontend/common/components/resourcelist/secret/template.html + 21 + + Schedule Planung @@ -1909,6 +1941,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Replications Controllers @@ -1942,14 +1978,6 @@ 54 - - Secrets - Secrets - - ../src/app/frontend/common/components/resourcelist/secret/template.html - 21 - - Message Nachricht @@ -2890,6 +2918,16 @@ 145 + + Service Accounts + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins @@ -2897,7 +2935,7 @@ ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2907,7 +2945,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2916,7 +2954,7 @@ Einstellungen ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2925,7 +2963,7 @@ Über ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/i18n/fr/messages.fr.xlf b/i18n/fr/messages.fr.xlf index 26cc752de56..7b5a44879ca 100644 --- a/i18n/fr/messages.fr.xlf +++ b/i18n/fr/messages.fr.xlf @@ -706,13 +706,17 @@ 51 - ../src/app/frontend/create/from/form/environmentvariables/template.html - 29 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 + + ../src/app/frontend/create/from/form/environmentvariables/template.html + 29 + Namespace @@ -790,13 +794,17 @@ 63 - ../src/app/frontend/create/from/form/template.html - 184 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 + + ../src/app/frontend/create/from/form/template.html + 184 + Age @@ -886,13 +894,17 @@ 69 - ../src/app/frontend/create/from/form/template.html - 164 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 + + ../src/app/frontend/create/from/form/template.html + 164 + Annotations @@ -1294,6 +1306,14 @@ 91 + + Service Accounts + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + Items:  Éléments :  @@ -1413,6 +1433,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Host @@ -1774,6 +1798,14 @@ 58 + + + + + ../src/app/frontend/common/components/resourcelist/secret/template.html + 21 + + Schedule Planning @@ -1913,6 +1945,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Replications Controllers @@ -1946,14 +1982,6 @@ 54 - - Secrets - Secrets - - ../src/app/frontend/common/components/resourcelist/secret/template.html - 21 - - Message Message @@ -2894,6 +2922,16 @@ 145 + + Service Accounts + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins @@ -2901,7 +2939,7 @@ ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2911,7 +2949,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2920,7 +2958,7 @@ Paramètres ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2929,7 +2967,7 @@ À propos ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/i18n/ja/messages.ja.xlf b/i18n/ja/messages.ja.xlf index 8b4996aa6c9..f670d3d42f3 100644 --- a/i18n/ja/messages.ja.xlf +++ b/i18n/ja/messages.ja.xlf @@ -665,6 +665,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Name @@ -774,13 +778,17 @@ 51 - ../src/app/frontend/create/from/form/environmentvariables/template.html - 29 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 + + ../src/app/frontend/create/from/form/environmentvariables/template.html + 29 + Namespace @@ -858,13 +866,17 @@ 63 - ../src/app/frontend/create/from/form/template.html - 184 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 + + ../src/app/frontend/create/from/form/template.html + 184 + Labels @@ -938,13 +950,17 @@ 69 - ../src/app/frontend/create/from/form/template.html - 164 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 + + ../src/app/frontend/create/from/form/template.html + 164 + Schedule @@ -1085,6 +1101,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Age @@ -2273,6 +2293,14 @@ 58 + + + + + ../src/app/frontend/common/components/resourcelist/secret/template.html + 21 + + Stateful Sets ステートフルセット @@ -2345,14 +2373,6 @@ 22 - - Secrets - シークレット - - ../src/app/frontend/common/components/resourcelist/secret/template.html - 21 - - Services サービス @@ -2389,6 +2409,14 @@ 91 + + Service Accounts + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + You can deploy a containerized app, select other namespace or @@ -2612,6 +2640,16 @@ 145 + + Service Accounts + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins @@ -2619,7 +2657,7 @@ ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2629,7 +2667,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2638,7 +2676,7 @@ 設定 ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2647,7 +2685,7 @@ Kubernetes Dashboard について ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/i18n/ko/messages.ko.xlf b/i18n/ko/messages.ko.xlf index 33c3d004238..d5b7b7c1d99 100644 --- a/i18n/ko/messages.ko.xlf +++ b/i18n/ko/messages.ko.xlf @@ -861,6 +861,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Name @@ -970,13 +974,17 @@ 51 - ../src/app/frontend/create/from/form/environmentvariables/template.html - 29 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 + + ../src/app/frontend/create/from/form/environmentvariables/template.html + 29 + Namespace @@ -1054,13 +1062,17 @@ 63 - ../src/app/frontend/create/from/form/template.html - 184 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 + + ../src/app/frontend/create/from/form/template.html + 184 + Labels @@ -1134,13 +1146,17 @@ 69 - ../src/app/frontend/create/from/form/template.html - 164 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 + + ../src/app/frontend/create/from/form/template.html + 164 + Schedule @@ -1281,6 +1297,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Age @@ -2376,9 +2396,9 @@ 58 - - Secrets - 시크릿 + + + ../src/app/frontend/common/components/resourcelist/secret/template.html 21 @@ -2420,6 +2440,14 @@ 91 + + Service Accounts + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + You can deploy a containerized app, select other namespace or @@ -2666,6 +2694,16 @@ 145 + + Service Accounts + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins @@ -2673,7 +2711,7 @@ ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2683,7 +2721,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2693,7 +2731,7 @@ ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2703,7 +2741,7 @@ ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/i18n/messages.xlf b/i18n/messages.xlf index 8f0f68faf64..86176e7b89a 100644 --- a/i18n/messages.xlf +++ b/i18n/messages.xlf @@ -902,6 +902,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Name @@ -1009,6 +1013,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 51 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 + ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 @@ -1092,6 +1100,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 63 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 + ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 @@ -1171,6 +1183,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 69 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 + ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 @@ -1314,6 +1330,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Cluster Roles @@ -2245,8 +2265,8 @@ 58 - - Secrets + + ../src/app/frontend/common/components/resourcelist/secret/template.html 21 @@ -2284,6 +2304,13 @@ 91 + + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + You can deploy a containerized app, select other namespace or @@ -2479,12 +2506,20 @@ 145 + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2492,7 +2527,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2500,7 +2535,7 @@ ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2508,7 +2543,7 @@ ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/i18n/zh-Hans/messages.zh-Hans.xlf b/i18n/zh-Hans/messages.zh-Hans.xlf index 353b26967d2..cce752c4772 100644 --- a/i18n/zh-Hans/messages.zh-Hans.xlf +++ b/i18n/zh-Hans/messages.zh-Hans.xlf @@ -861,6 +861,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Name @@ -970,13 +974,17 @@ 51 - ../src/app/frontend/create/from/form/environmentvariables/template.html - 29 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 + + ../src/app/frontend/create/from/form/environmentvariables/template.html + 29 + Namespace @@ -1054,13 +1062,17 @@ 63 - ../src/app/frontend/create/from/form/template.html - 184 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 + + ../src/app/frontend/create/from/form/template.html + 184 + Labels @@ -1134,13 +1146,17 @@ 69 - ../src/app/frontend/create/from/form/template.html - 164 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 + + ../src/app/frontend/create/from/form/template.html + 164 + Schedule @@ -1281,6 +1297,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Age @@ -2376,9 +2396,9 @@ 58 - - Secrets - Secrets + + + ../src/app/frontend/common/components/resourcelist/secret/template.html 21 @@ -2420,6 +2440,14 @@ 91 + + Service Accounts + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + You can deploy a containerized app, select other namespace or @@ -2666,6 +2694,16 @@ 145 + + Service Accounts + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins @@ -2673,7 +2711,7 @@ ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2683,7 +2721,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2693,7 +2731,7 @@ ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2703,7 +2741,7 @@ ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf b/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf index c37c414fc81..45493c8fb75 100644 --- a/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf +++ b/i18n/zh-Hant-HK/messages.zh-Hant-HK.xlf @@ -861,6 +861,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Name @@ -970,13 +974,17 @@ 51 - ../src/app/frontend/create/from/form/environmentvariables/template.html - 29 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 + + ../src/app/frontend/create/from/form/environmentvariables/template.html + 29 + Namespace @@ -1054,13 +1062,17 @@ 63 - ../src/app/frontend/create/from/form/template.html - 184 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 + + ../src/app/frontend/create/from/form/template.html + 184 + Labels @@ -1134,13 +1146,17 @@ 69 - ../src/app/frontend/create/from/form/template.html - 164 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 + + ../src/app/frontend/create/from/form/template.html + 164 + Schedule @@ -1281,6 +1297,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Age @@ -2380,9 +2400,9 @@ 58 - - Secrets - Secrets + + + ../src/app/frontend/common/components/resourcelist/secret/template.html 21 @@ -2424,6 +2444,14 @@ 91 + + Service Accounts + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + You can deploy a containerized app, select other namespace or @@ -2670,6 +2698,16 @@ 145 + + Service Accounts + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins @@ -2677,7 +2715,7 @@ ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2687,7 +2725,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2697,7 +2735,7 @@ ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2707,7 +2745,7 @@ ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/i18n/zh-Hant/messages.zh-Hant.xlf b/i18n/zh-Hant/messages.zh-Hant.xlf index 343eea31617..0ce901fba80 100644 --- a/i18n/zh-Hant/messages.zh-Hant.xlf +++ b/i18n/zh-Hant/messages.zh-Hant.xlf @@ -861,6 +861,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 23 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 23 + Name @@ -970,13 +974,17 @@ 51 - ../src/app/frontend/create/from/form/environmentvariables/template.html - 29 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 42 ../src/app/frontend/resource/workloads/deployment/detail/template.html 223 + + ../src/app/frontend/create/from/form/environmentvariables/template.html + 29 + Namespace @@ -1054,13 +1062,17 @@ 63 - ../src/app/frontend/create/from/form/template.html - 184 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 54 ../src/app/frontend/resource/workloads/deployment/detail/template.html 231 + + ../src/app/frontend/create/from/form/template.html + 184 + Labels @@ -1134,13 +1146,17 @@ 69 - ../src/app/frontend/create/from/form/template.html - 164 + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 60 ../src/app/frontend/resource/workloads/deployment/detail/template.html 254 + + ../src/app/frontend/create/from/form/template.html + 164 + Schedule @@ -1281,6 +1297,10 @@ ../src/app/frontend/common/components/resourcelist/service/template.html 101 + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 70 + Age @@ -2380,9 +2400,9 @@ 58 - - Secrets - Secrets + + + ../src/app/frontend/common/components/resourcelist/secret/template.html 21 @@ -2424,6 +2444,14 @@ 91 + + Service Accounts + Service Accounts + + ../src/app/frontend/common/components/resourcelist/serviceaccount/template.html + 21 + + You can deploy a containerized app, select other namespace or @@ -2670,6 +2698,16 @@ 145 + + Service Accounts + + Service Accounts + + + ../src/app/frontend/chrome/nav/template.html + 150 + + Plugins @@ -2677,7 +2715,7 @@ ../src/app/frontend/chrome/nav/template.html - 151 + 156 @@ -2687,7 +2725,7 @@ ../src/app/frontend/chrome/nav/template.html - 163 + 168 @@ -2697,7 +2735,7 @@ ../src/app/frontend/chrome/nav/template.html - 175 + 180 @@ -2707,7 +2745,7 @@ ../src/app/frontend/chrome/nav/template.html - 181 + 186 diff --git a/src/app/backend/api/types.go b/src/app/backend/api/types.go index 566142439f8..a9e0b4e16a9 100644 --- a/src/app/backend/api/types.go +++ b/src/app/backend/api/types.go @@ -120,6 +120,7 @@ const ( ResourceKindEvent = "event" ResourceKindHorizontalPodAutoscaler = "horizontalpodautoscaler" ResourceKindIngress = "ingress" + ResourceKindServiceAccount = "serviceaccount" ResourceKindJob = "job" ResourceKindCronJob = "cronjob" ResourceKindLimitRange = "limitrange" @@ -216,6 +217,7 @@ var KindToAPIMapping = map[string]APIMapping{ ResourceKindResourceQuota: {"resourcequotas", ClientTypeDefault, true}, ResourceKindSecret: {"secrets", ClientTypeDefault, true}, ResourceKindService: {"services", ClientTypeDefault, true}, + ResourceKindServiceAccount: {"serviceaccounts", ClientTypeDefault, true}, ResourceKindStatefulSet: {"statefulsets", ClientTypeAppsClient, true}, ResourceKindStorageClass: {"storageclasses", ClientTypeStorageClient, false}, ResourceKindEndpoint: {"endpoints", ClientTypeDefault, true}, diff --git a/src/app/backend/handler/apihandler.go b/src/app/backend/handler/apihandler.go index 0c5a0b8cbb7..343d4dc9c8e 100644 --- a/src/app/backend/handler/apihandler.go +++ b/src/app/backend/handler/apihandler.go @@ -63,6 +63,7 @@ import ( "github.com/kubernetes/dashboard/src/app/backend/resource/rolebinding" "github.com/kubernetes/dashboard/src/app/backend/resource/secret" resourceService "github.com/kubernetes/dashboard/src/app/backend/resource/service" + "github.com/kubernetes/dashboard/src/app/backend/resource/serviceaccount" "github.com/kubernetes/dashboard/src/app/backend/resource/statefulset" "github.com/kubernetes/dashboard/src/app/backend/resource/storageclass" "github.com/kubernetes/dashboard/src/app/backend/scaling" @@ -445,6 +446,27 @@ func CreateHTTPAPIHandler(iManager integration.IntegrationManager, cManager clie To(apiHandler.handleGetServicePods). Writes(pod.PodList{})) + apiV1Ws.Route( + apiV1Ws.GET("/serviceaccount"). + To(apiHandler.handleGetServiceAccountList). + Writes(serviceaccount.ServiceAccountList{})) + apiV1Ws.Route( + apiV1Ws.GET("/serviceaccount/{namespace}"). + To(apiHandler.handleGetServiceAccountList). + Writes(serviceaccount.ServiceAccountList{})) + apiV1Ws.Route( + apiV1Ws.GET("/serviceaccount/{namespace}/{serviceaccount}"). + To(apiHandler.handleGetServiceAccountDetail). + Writes(serviceaccount.ServiceAccountDetail{})) + apiV1Ws.Route( + apiV1Ws.GET("/serviceaccount/{namespace}/{serviceaccount}/secret"). + To(apiHandler.handleGetServiceAccountSecrets). + Writes(secret.SecretList{})) + apiV1Ws.Route( + apiV1Ws.GET("/serviceaccount/{namespace}/{serviceaccount}/imagepullsecret"). + To(apiHandler.handleGetServiceAccountImagePullSecrets). + Writes(secret.SecretList{})) + apiV1Ws.Route( apiV1Ws.GET("/ingress"). To(apiHandler.handleGetIngressList). @@ -903,6 +925,76 @@ func (apiHandler *APIHandler) handleGetServiceEvent(request *restful.Request, re response.WriteHeaderAndEntity(http.StatusOK, result) } +func (apiHandler *APIHandler) handleGetServiceAccountList(request *restful.Request, response *restful.Response) { + k8sClient, err := apiHandler.cManager.Client(request) + if err != nil { + errors.HandleInternalError(response, err) + return + } + + namespace := parseNamespacePathParameter(request) + dataSelect := parser.ParseDataSelectPathParameter(request) + result, err := serviceaccount.GetServiceAccountList(k8sClient, namespace, dataSelect) + if err != nil { + errors.HandleInternalError(response, err) + return + } + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +func (apiHandler *APIHandler) handleGetServiceAccountDetail(request *restful.Request, response *restful.Response) { + k8sClient, err := apiHandler.cManager.Client(request) + if err != nil { + errors.HandleInternalError(response, err) + return + } + + namespace := request.PathParameter("namespace") + name := request.PathParameter("serviceaccount") + result, err := serviceaccount.GetServiceAccountDetail(k8sClient, namespace, name) + if err != nil { + errors.HandleInternalError(response, err) + return + } + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +func (apiHandler *APIHandler) handleGetServiceAccountImagePullSecrets(request *restful.Request, response *restful.Response) { + k8sClient, err := apiHandler.cManager.Client(request) + if err != nil { + errors.HandleInternalError(response, err) + return + } + + namespace := request.PathParameter("namespace") + name := request.PathParameter("serviceaccount") + dataSelect := parser.ParseDataSelectPathParameter(request) + result, err := serviceaccount.GetServiceAccountImagePullSecrets(k8sClient, namespace, name, dataSelect) + if err != nil { + errors.HandleInternalError(response, err) + return + } + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +func (apiHandler *APIHandler) handleGetServiceAccountSecrets(request *restful.Request, response *restful.Response) { + k8sClient, err := apiHandler.cManager.Client(request) + if err != nil { + errors.HandleInternalError(response, err) + return + } + + namespace := request.PathParameter("namespace") + name := request.PathParameter("serviceaccount") + dataSelect := parser.ParseDataSelectPathParameter(request) + result, err := serviceaccount.GetServiceAccountSecrets(k8sClient, namespace, name, dataSelect) + if err != nil { + errors.HandleInternalError(response, err) + return + } + response.WriteHeaderAndEntity(http.StatusOK, result) +} + func (apiHandler *APIHandler) handleGetIngressDetail(request *restful.Request, response *restful.Response) { k8sClient, err := apiHandler.cManager.Client(request) if err != nil { diff --git a/src/app/backend/resource/secret/list.go b/src/app/backend/resource/secret/list.go index 70e0c2cd21b..f31ba22935b 100644 --- a/src/app/backend/resource/secret/list.go +++ b/src/app/backend/resource/secret/list.go @@ -93,7 +93,7 @@ func GetSecretList(client kubernetes.Interface, namespace *common.NamespaceQuery return nil, criticalError } - return toSecretList(secretList.Items, nonCriticalErrors, dsQuery), nil + return ToSecretList(secretList.Items, nonCriticalErrors, dsQuery), nil } // CreateSecret creates a single secret using the cluster API client @@ -120,7 +120,7 @@ func toSecret(secret *v1.Secret) Secret { } } -func toSecretList(secrets []v1.Secret, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *SecretList { +func ToSecretList(secrets []v1.Secret, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *SecretList { newSecretList := &SecretList{ ListMeta: api.ListMeta{TotalItems: len(secrets)}, Secrets: make([]Secret, 0), diff --git a/src/app/backend/resource/secret/list_test.go b/src/app/backend/resource/secret/list_test.go index 8a8cb9335af..4b6155bda30 100644 --- a/src/app/backend/resource/secret/list_test.go +++ b/src/app/backend/resource/secret/list_test.go @@ -76,7 +76,7 @@ func TestToSecretList(t *testing.T) { } for _, c := range cases { - actual := toSecretList(c.secrets, nil, dataselect.NoDataSelect) + actual := ToSecretList(c.secrets, nil, dataselect.NoDataSelect) if !reflect.DeepEqual(actual, c.expected) { t.Errorf("toSecretList() ==\n%#v\nExpected: %#v", actual, c.expected) } diff --git a/src/app/backend/resource/serviceaccount/common.go b/src/app/backend/resource/serviceaccount/common.go new file mode 100644 index 00000000000..21d77de3586 --- /dev/null +++ b/src/app/backend/resource/serviceaccount/common.go @@ -0,0 +1,52 @@ +// 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 serviceaccount + +import ( + "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect" + v1 "k8s.io/api/core/v1" +) + +type ServiceAccountCell v1.ServiceAccount + +func (self ServiceAccountCell) 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 []v1.ServiceAccount) []dataselect.DataCell { + cells := make([]dataselect.DataCell, len(std)) + for i := range std { + cells[i] = ServiceAccountCell(std[i]) + } + return cells +} + +func fromCells(cells []dataselect.DataCell) []v1.ServiceAccount { + std := make([]v1.ServiceAccount, len(cells)) + for i := range std { + std[i] = v1.ServiceAccount(cells[i].(ServiceAccountCell)) + } + return std +} diff --git a/src/app/backend/resource/serviceaccount/detail.go b/src/app/backend/resource/serviceaccount/detail.go new file mode 100644 index 00000000000..db53b94ca73 --- /dev/null +++ b/src/app/backend/resource/serviceaccount/detail.go @@ -0,0 +1,48 @@ +// 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 serviceaccount + +import ( + "context" + "log" + + v1 "k8s.io/api/core/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" + client "k8s.io/client-go/kubernetes" +) + +// ServiceAccountDetail contains detailed information about a service account. +type ServiceAccountDetail struct { + ServiceAccount `json:",inline"` + Errors []error `json:"errors"` +} + +// GetServiceAccountDetail returns detailed information about a service account. +func GetServiceAccountDetail(client client.Interface, namespace, name string) (*ServiceAccountDetail, error) { + log.Printf("Getting details of %s service account in %s namespace", name, namespace) + + raw, err := client.CoreV1().ServiceAccounts(namespace).Get(context.TODO(), name, metaV1.GetOptions{}) + if err != nil { + return nil, err + } + + return getServiceAccountDetail(raw), nil +} + +func getServiceAccountDetail(sa *v1.ServiceAccount) *ServiceAccountDetail { + return &ServiceAccountDetail{ + ServiceAccount: toServiceAccount(sa), + } +} diff --git a/src/app/backend/resource/serviceaccount/list.go b/src/app/backend/resource/serviceaccount/list.go new file mode 100644 index 00000000000..ed370594e38 --- /dev/null +++ b/src/app/backend/resource/serviceaccount/list.go @@ -0,0 +1,80 @@ +// 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 serviceaccount + +import ( + "context" + + v1 "k8s.io/api/core/v1" + + "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" + client "k8s.io/client-go/kubernetes" +) + +// ServiceAccount contains an information about single service account in the list. +type ServiceAccount struct { + api.ObjectMeta `json:"objectMeta"` + api.TypeMeta `json:"typeMeta"` +} + +// ServiceAccountList contains a list of service accounts. +type ServiceAccountList struct { + api.ListMeta `json:"listMeta"` + Items []ServiceAccount `json:"items"` + Errors []error `json:"errors"` +} + +// GetServiceAccountList lists service accounts from given namespace using given data select query. +func GetServiceAccountList(client client.Interface, namespace *common.NamespaceQuery, + dsQuery *dataselect.DataSelectQuery) (*ServiceAccountList, error) { + saList, err := client.CoreV1().ServiceAccounts(namespace.ToRequestParam()).List(context.TODO(), + api.ListEverything) + + nonCriticalErrors, criticalError := errors.HandleError(err) + if criticalError != nil { + return nil, criticalError + } + + return toServiceAccountList(saList.Items, nonCriticalErrors, dsQuery), nil +} + +func toServiceAccount(sa *v1.ServiceAccount) ServiceAccount { + return ServiceAccount{ + ObjectMeta: api.NewObjectMeta(sa.ObjectMeta), + TypeMeta: api.NewTypeMeta(api.ResourceKindServiceAccount), + } +} + +func toServiceAccountList(serviceAccounts []v1.ServiceAccount, nonCriticalErrors []error, + dsQuery *dataselect.DataSelectQuery) *ServiceAccountList { + newServiceAccountList := &ServiceAccountList{ + ListMeta: api.ListMeta{TotalItems: len(serviceAccounts)}, + Items: make([]ServiceAccount, 0), + Errors: nonCriticalErrors, + } + + saCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(serviceAccounts), dsQuery) + serviceAccounts = fromCells(saCells) + + newServiceAccountList.ListMeta = api.ListMeta{TotalItems: filteredTotal} + for _, sa := range serviceAccounts { + newServiceAccountList.Items = append(newServiceAccountList.Items, toServiceAccount(&sa)) + } + + return newServiceAccountList +} diff --git a/src/app/backend/resource/serviceaccount/secrets.go b/src/app/backend/resource/serviceaccount/secrets.go new file mode 100644 index 00000000000..17357619efd --- /dev/null +++ b/src/app/backend/resource/serviceaccount/secrets.go @@ -0,0 +1,110 @@ +// 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 serviceaccount + +import ( + "context" + + "github.com/kubernetes/dashboard/src/app/backend/resource/common" + "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect" + "github.com/kubernetes/dashboard/src/app/backend/resource/secret" + v1 "k8s.io/api/core/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sClient "k8s.io/client-go/kubernetes" +) + +// GetServiceAccountImagePullSecrets list image pull secrets of given service account. +func GetServiceAccountImagePullSecrets(client k8sClient.Interface, namespace, + name string, dsQuery *dataselect.DataSelectQuery) (*secret.SecretList, error) { + imagePullSecretList := secret.SecretList{ + Secrets: []secret.Secret{}, + } + + serviceAccount, err := client.CoreV1().ServiceAccounts(namespace).Get(context.TODO(), name, metaV1.GetOptions{}) + if err != nil { + return &imagePullSecretList, err + } + + if serviceAccount.ImagePullSecrets == nil { + return &imagePullSecretList, nil + } + + channels := &common.ResourceChannels{ + SecretList: common.GetSecretListChannel(client, common.NewSameNamespaceQuery(namespace), 1), + } + + apiSecretList := <-channels.SecretList.List + if err := <-channels.SecretList.Error; err != nil { + return &imagePullSecretList, err + } + + imagePullSecretsMap := map[string]struct{}{} + for _, ips := range serviceAccount.ImagePullSecrets { + imagePullSecretsMap[ips.Name] = struct{}{} + } + + var rawImagePullSecretList []v1.Secret + for _, apiSecret := range apiSecretList.Items { + if _, ok := imagePullSecretsMap[apiSecret.Name]; ok { + rawImagePullSecretList = append(rawImagePullSecretList, apiSecret) + } + } + + return secret.ToSecretList(rawImagePullSecretList, []error{}, dsQuery), nil +} + +// GetServiceAccountSecrets list secrets of given service account. +// Note: Secrets are referenced by ObjectReference compared to image pull secrets LocalObjectReference but still only +// the name field is used and most of the time other fields are empty. Because of that we are using only the name field +// to find referenced objects assuming that the namespace is the same. ObjectReference is being slowly replaced with +// more specific types. +func GetServiceAccountSecrets(client k8sClient.Interface, namespace, + name string, dsQuery *dataselect.DataSelectQuery) (*secret.SecretList, error) { + secretList := secret.SecretList{ + Secrets: []secret.Secret{}, + } + + serviceAccount, err := client.CoreV1().ServiceAccounts(namespace).Get(context.TODO(), name, metaV1.GetOptions{}) + if err != nil { + return &secretList, err + } + + if serviceAccount.Secrets == nil { + return &secretList, nil + } + + channels := &common.ResourceChannels{ + SecretList: common.GetSecretListChannel(client, common.NewSameNamespaceQuery(namespace), 1), + } + + apiSecretList := <-channels.SecretList.List + if err := <-channels.SecretList.Error; err != nil { + return &secretList, err + } + + secretsMap := map[string]v1.ObjectReference{} + for _, s := range serviceAccount.Secrets { + secretsMap[s.Name] = s + } + + var rawSecretList []v1.Secret + for _, apiSecret := range apiSecretList.Items { + if _, ok := secretsMap[apiSecret.Name]; ok { + rawSecretList = append(rawSecretList, apiSecret) + } + } + + return secret.ToSecretList(rawSecretList, []error{}, dsQuery), nil +} diff --git a/src/app/frontend/chrome/nav/template.html b/src/app/frontend/chrome/nav/template.html index 854ac7125db..62fb111bcb1 100644 --- a/src/app/frontend/chrome/nav/template.html +++ b/src/app/frontend/chrome/nav/template.html @@ -144,6 +144,11 @@ id="nav-secret" i18n>Secrets + Service Accounts + import('resource/config/secret/module').then(m => m.SecretModule), }, + { + path: 'serviceaccount', + loadChildren: () => import('resource/config/serviceaccount/module').then(m => m.ServiceAccountModule), + }, // Custom resource definitions { diff --git a/src/app/frontend/common/components/module.ts b/src/app/frontend/common/components/module.ts index 761d014e1cc..5ff2cfa6496 100644 --- a/src/app/frontend/common/components/module.ts +++ b/src/app/frontend/common/components/module.ts @@ -94,6 +94,7 @@ import {TextInputComponent} from './textinput/component'; import {UploadFileComponent} from './uploadfile/component'; import {WorkloadStatusComponent} from './workloadstatus/component'; import {ZeroStateComponent} from './zerostate/component'; +import {ServiceAccountListComponent} from './resourcelist/serviceaccount/component'; const components = [ ActionbarDetailActionsComponent, @@ -105,9 +106,7 @@ const components = [ ActionbarDetailPinComponent, ActionbarComponent, ActionbarDetailTriggerComponent, - BreadcrumbsComponent, - CardComponent, CardListFilterComponent, ChipsComponent, @@ -123,43 +122,32 @@ const components = [ CRDListComponent, CRDObjectListComponent, CRDVersionListComponent, - DaemonSetListComponent, DateComponent, DeploymentListComponent, DefaultActionbar, - EndpointListComponent, ExternalEndpointComponent, EventListComponent, - GraphComponent, GraphCardComponent, GraphMetricsComponent, - HiddenPropertyComponent, HorizontalPodAutoscalerListComponent, - IngressListComponent, InternalEndpointComponent, - JobListComponent, - LoadingSpinner, ListZeroStateComponent, LogsScaleDefaultActionbar, LogsExecDefaultActionbar, LogsDefaultActionbar, - MenuComponent, - NamespaceListComponent, NodeListComponent, NamespaceSelectorComponent, NamespaceChangeDialog, - ObjectMetaComponent, - PodStatusCardComponent, PropertyComponent, ProxyComponent, @@ -168,26 +156,22 @@ const components = [ PersistentVolumeClaimListComponent, PolicyRuleListComponent, PinDefaultActionbar, - ResourceQuotaListComponent, ResourceLimitListComponent, ReplicaSetListComponent, ReplicationControllerListComponent, RowDetailComponent, - StorageClassListComponent, StatefulSetListComponent, SecretListComponent, ServiceListComponent, + ServiceAccountListComponent, CpuSparklineComponent, MemorySparklineComponent, ScaleDefaultActionbar, - TextInputComponent, TriggerDefaultActionbar, - UploadFileComponent, - ZeroStateComponent, WorkloadStatusComponent, ]; diff --git a/src/app/frontend/common/components/resourcelist/groupids.ts b/src/app/frontend/common/components/resourcelist/groupids.ts index fb92959125d..6af9b1e47d4 100644 --- a/src/app/frontend/common/components/resourcelist/groupids.ts +++ b/src/app/frontend/common/components/resourcelist/groupids.ts @@ -29,6 +29,7 @@ export enum ListIdentifier { replicaSet = 'replicaSetList', ingress = 'ingressList', service = 'serviceList', + serviceAccount = 'serviceAccountList', configMap = 'configMapList', persistentVolumeClaim = 'persistentVolumeClaimList', secret = 'secretList', diff --git a/src/app/frontend/common/components/resourcelist/secret/component.ts b/src/app/frontend/common/components/resourcelist/secret/component.ts index 56a9ecc39a2..1daca09d653 100644 --- a/src/app/frontend/common/components/resourcelist/secret/component.ts +++ b/src/app/frontend/common/components/resourcelist/secret/component.ts @@ -29,6 +29,7 @@ import {ListGroupIdentifier, ListIdentifier} from '../groupids'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class SecretListComponent extends ResourceListBase { + @Input() title = 'Secrets'; @Input() endpoint = EndpointManager.resource(Resource.secret, true).list(); constructor( diff --git a/src/app/frontend/common/components/resourcelist/secret/template.html b/src/app/frontend/common/components/resourcelist/secret/template.html index b761bc152e2..34fc3909bd7 100644 --- a/src/app/frontend/common/components/resourcelist/secret/template.html +++ b/src/app/frontend/common/components/resourcelist/secret/template.html @@ -18,7 +18,7 @@ [hidden]="isHidden()">
Secrets
+ i18n>{{title}}
Items: {{totalItems}}
diff --git a/src/app/frontend/common/components/resourcelist/serviceaccount/component.ts b/src/app/frontend/common/components/resourcelist/serviceaccount/component.ts new file mode 100644 index 00000000000..20d00a13a48 --- /dev/null +++ b/src/app/frontend/common/components/resourcelist/serviceaccount/component.ts @@ -0,0 +1,66 @@ +// 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 {Observable} from 'rxjs/Observable'; +import {ServiceAccount, ServiceAccountList} from 'typings/backendapi'; + +import {ResourceListBase} from '../../../resources/list'; +import {NotificationsService} from '../../../services/global/notifications'; +import {EndpointManager, Resource} from '../../../services/resource/endpoint'; +import {NamespacedResourceService} from '../../../services/resource/resource'; +import {MenuComponent} from '../../list/column/menu/component'; +import {ListGroupIdentifier, ListIdentifier} from '../groupids'; + +@Component({ + selector: 'kd-service-account-list', + templateUrl: './template.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ServiceAccountListComponent extends ResourceListBase { + @Input() endpoint = EndpointManager.resource(Resource.serviceAccount, true).list(); + + constructor( + private readonly serviceAccount_: NamespacedResourceService, + notifications: NotificationsService, + cdr: ChangeDetectorRef, + ) { + super('serviceaccount', notifications, cdr); + this.id = ListIdentifier.serviceAccount; + this.groupId = ListGroupIdentifier.config; + + // Register action columns. + this.registerActionColumn('menu', MenuComponent); + + // Register dynamic columns. + this.registerDynamicColumn('namespace', 'name', this.shouldShowNamespaceColumn_.bind(this)); + } + + getResourceObservable(params?: HttpParams): Observable { + return this.serviceAccount_.get(this.endpoint, undefined, undefined, params); + } + + map(serviceAccountList: ServiceAccountList): ServiceAccount[] { + return serviceAccountList.items; + } + + getDisplayColumns(): string[] { + return ['name', 'labels', 'created']; + } + + private shouldShowNamespaceColumn_(): boolean { + return this.namespaceService_.areMultipleNamespacesSelected(); + } +} diff --git a/src/app/frontend/common/components/resourcelist/serviceaccount/template.html b/src/app/frontend/common/components/resourcelist/serviceaccount/template.html new file mode 100644 index 00000000000..f5640ca8e82 --- /dev/null +++ b/src/app/frontend/common/components/resourcelist/serviceaccount/template.html @@ -0,0 +1,100 @@ + + + +
Service Accounts
+
Items: {{totalItems}}
+
+ +
+ +
+
+ + + + Name + + + {{serviceAccount.objectMeta.name}} + + + + + + Namespace + {{serviceAccount.objectMeta.namespace}} + + + + Labels + + + + + + + Created + + + + + + + + + + + + + + + + + +
+ +
+ +
+
diff --git a/src/app/frontend/common/services/resource/endpoint.ts b/src/app/frontend/common/services/resource/endpoint.ts index 8750fb287e0..29ac37ab8be 100644 --- a/src/app/frontend/common/services/resource/endpoint.ts +++ b/src/app/frontend/common/services/resource/endpoint.ts @@ -37,8 +37,10 @@ export enum Resource { configMap = 'configmap', persistentVolumeClaim = 'persistentvolumeclaim', secret = 'secret', + imagePullSecret = 'imagepullsecret', ingress = 'ingress', service = 'service', + serviceAccount = 'serviceaccount', event = 'event', container = 'container', plugin = 'plugin', diff --git a/src/app/frontend/overview/template.html b/src/app/frontend/overview/template.html index 94b0af4f37d..cb3e3698aa3 100644 --- a/src/app/frontend/overview/template.html +++ b/src/app/frontend/overview/template.html @@ -62,6 +62,8 @@ [hideable]="true"> +
diff --git a/src/app/frontend/resource/config/serviceaccount/detail/component.ts b/src/app/frontend/resource/config/serviceaccount/detail/component.ts new file mode 100644 index 00000000000..5903a8178cd --- /dev/null +++ b/src/app/frontend/resource/config/serviceaccount/detail/component.ts @@ -0,0 +1,67 @@ +// 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 'rxjs/add/operator/startWith'; + +import {Component, OnDestroy, OnInit} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {ServiceAccountDetail} from '@api/backendapi'; +import {Subscription} from 'rxjs/Subscription'; + +import {ActionbarService, ResourceMeta} from '../../../../common/services/global/actionbar'; +import {NotificationsService} from '../../../../common/services/global/notifications'; +import {EndpointManager, Resource} from '../../../../common/services/resource/endpoint'; +import {NamespacedResourceService} from '../../../../common/services/resource/resource'; + +@Component({ + selector: 'kd-service-account-detail', + templateUrl: './template.html', +}) +export class ServiceAccountDetailComponent implements OnInit, OnDestroy { + private serviceAccountSubscription_: Subscription; + private readonly endpoint_ = EndpointManager.resource(Resource.serviceAccount, true); + secretListEndpoint: string; + imagePullSecretListEndpoint: string; + serviceAccount: ServiceAccountDetail; + isInitialized = false; + + constructor( + private readonly serviceAccount_: NamespacedResourceService, + private readonly actionbar_: ActionbarService, + private readonly activatedRoute_: ActivatedRoute, + private readonly notifications_: NotificationsService, + ) {} + + ngOnInit(): void { + const resourceName = this.activatedRoute_.snapshot.params.resourceName; + const resourceNamespace = this.activatedRoute_.snapshot.params.resourceNamespace; + + this.secretListEndpoint = this.endpoint_.child(resourceName, Resource.secret, resourceNamespace); + this.imagePullSecretListEndpoint = this.endpoint_.child(resourceName, Resource.imagePullSecret, resourceNamespace); + + this.serviceAccountSubscription_ = this.serviceAccount_ + .get(this.endpoint_.detail(), resourceName, resourceNamespace) + .subscribe((d: ServiceAccountDetail) => { + this.serviceAccount = d; + this.notifications_.pushErrors(d.errors); + this.actionbar_.onInit.emit(new ResourceMeta('Service Account', d.objectMeta, d.typeMeta)); + this.isInitialized = true; + }); + } + + ngOnDestroy(): void { + this.serviceAccountSubscription_.unsubscribe(); + this.actionbar_.onDetailsLeave.emit(); + } +} diff --git a/src/app/frontend/resource/config/serviceaccount/detail/template.html b/src/app/frontend/resource/config/serviceaccount/detail/template.html new file mode 100644 index 00000000000..b447633a896 --- /dev/null +++ b/src/app/frontend/resource/config/serviceaccount/detail/template.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/src/app/frontend/resource/config/serviceaccount/list/component.ts b/src/app/frontend/resource/config/serviceaccount/list/component.ts new file mode 100644 index 00000000000..e30c7c200f0 --- /dev/null +++ b/src/app/frontend/resource/config/serviceaccount/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-service-account-list-state', + template: '', +}) +export class ServiceAccountListComponent {} diff --git a/src/app/frontend/resource/config/serviceaccount/module.ts b/src/app/frontend/resource/config/serviceaccount/module.ts new file mode 100644 index 00000000000..2d4f212ef24 --- /dev/null +++ b/src/app/frontend/resource/config/serviceaccount/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 {ServiceAccountDetailComponent} from './detail/component'; +import {ServiceAccountListComponent} from './list/component'; +import {ServiceAccountRoutingModule} from './routing'; + +@NgModule({ + imports: [SharedModule, ComponentsModule, ServiceAccountRoutingModule], + declarations: [ServiceAccountListComponent, ServiceAccountDetailComponent], +}) +export class ServiceAccountModule {} diff --git a/src/app/frontend/resource/config/serviceaccount/routing.ts b/src/app/frontend/resource/config/serviceaccount/routing.ts new file mode 100644 index 00000000000..9da7c6a9402 --- /dev/null +++ b/src/app/frontend/resource/config/serviceaccount/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 {CONFIG_ROUTE} from '../routing'; + +import {ServiceAccountDetailComponent} from './detail/component'; +import {ServiceAccountListComponent} from './list/component'; + +const SERVICEACCOUNT_LIST_ROUTE: Route = { + path: '', + component: ServiceAccountListComponent, + data: { + breadcrumb: 'Service Accounts', + parent: CONFIG_ROUTE, + }, +}; + +const SERVICEACCOUNT_DETAIL_ROUTE: Route = { + path: ':resourceNamespace/:resourceName', + component: ServiceAccountDetailComponent, + data: { + breadcrumb: '{{ resourceName }}', + parent: SERVICEACCOUNT_LIST_ROUTE, + }, +}; + +@NgModule({ + imports: [RouterModule.forChild([SERVICEACCOUNT_LIST_ROUTE, SERVICEACCOUNT_DETAIL_ROUTE, DEFAULT_ACTIONBAR])], + exports: [RouterModule], +}) +export class ServiceAccountRoutingModule {} diff --git a/src/app/frontend/resource/config/template.html b/src/app/frontend/resource/config/template.html index 30e7ff05ce3..30cf431a4c7 100644 --- a/src/app/frontend/resource/config/template.html +++ b/src/app/frontend/resource/config/template.html @@ -21,6 +21,8 @@ [hideable]="true"> + diff --git a/src/app/frontend/typings/backendapi.ts b/src/app/frontend/typings/backendapi.ts index 6f847799c1e..2505d685841 100644 --- a/src/app/frontend/typings/backendapi.ts +++ b/src/app/frontend/typings/backendapi.ts @@ -123,6 +123,10 @@ export interface IngressList extends ResourceList { items: Ingress[]; } +export interface ServiceAccountList extends ResourceList { + items: ServiceAccount[]; +} + export interface JobList extends ResourceList { cumulativeMetrics: Metric[] | null; jobs: Job[]; @@ -195,6 +199,8 @@ export type ClusterRole = Resource; export type ConfigMap = Resource; +export type ServiceAccount = Resource; + export interface Controller extends Resource { pods: PodInfo; containerImages: string[]; @@ -446,6 +452,8 @@ export interface SecretDetail extends ResourceDetail { data: StringMap; } +export type ServiceAccountDetail = ResourceDetail; + export type IngressDetail = ResourceDetail; export interface PersistentVolumeClaimDetail extends ResourceDetail {