Repository: kubernetes/dashboard
Pull request #4030 (2019-07-08 11:26:42)

CRD Support - Frontend
- [x] Add CRD ActionBar buttons
- [x] Add Status icon to CRD list
- [x] Paginate CRD Objects list
- [x] Extend Verber to support CRD Objects.
- [x] Add Edit & Delete ActionBar buttons.
- [x] Add Raw object data display.

Ref - #2493 

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes/dashboard/pull/4030#" title="Author self-approved">eloyekunle</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **olekzabl**
You can assign the PR to them by writing `/assign @olekzabl` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes%2Fdashboard).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes/dashboard/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["olekzabl"]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/kubernetes/dashboard/pull/4030?src=pr&el=h1) Report
> Merging [#4030](https://codecov.io/gh/kubernetes/dashboard/pull/4030?src=pr&el=desc) into [master](https://codecov.io/gh/kubernetes/dashboard/commit/83bcb8d8f88cceae1a451194b5ca30e99dd3a3f2?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/kubernetes/dashboard/pull/4030/graphs/tree.svg?width=650&token=Wj7jysJ9A5&height=150&src=pr)](https://codecov.io/gh/kubernetes/dashboard/pull/4030?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           master   #4030   +/-   ##
======================================
  Coverage    46.4%   46.4%           
======================================
  Files         188     188           
  Lines        8708    8708           
  Branches       71      71           
======================================
  Hits         4041    4041           
  Misses       4417    4417           
  Partials      250     250
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/kubernetes/dashboard/pull/4030?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/kubernetes/dashboard/pull/4030?src=pr&el=footer). Last update [83bcb8d...224e10e](https://codecov.io/gh/kubernetes/dashboard/pull/4030?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

maciaszczykm: @eloyekunle Any progress here?
eloyekunle: @maciaszczykm Yes, I'll push updates today or tomorrow.
eloyekunle: Current Screenshots:

**1. CRD List Page**
![localhost_8080_ (1)](https://user-images.githubusercontent.com/11166933/61595778-65830a00-abf3-11e9-9dd4-7aab4d66f59d.png)

**2. CRD Details Page**
![localhost_8080_](https://user-images.githubusercontent.com/11166933/61595780-703d9f00-abf3-11e9-9a7d-205273f134bb.png)

maciaszczykm: What is missing? Can we review?
eloyekunle: @maciaszczykm 

I want to update the CRD Objects list to a paginated display, then it will be ready for review.

The CRD Object Detail Page will then come in via another PR.
eloyekunle: @maciaszczykm this is ready for a review.
/assign maciaszczykm jeefy
eloyekunle: Current Views

**1. CRD Detail View**
![image](https://user-images.githubusercontent.com/11166933/61879451-f48d6c00-aeea-11e9-8c2f-e25b81db691d.png)

**2. CRD Object Detail**
Currently minimal. Separate issue at #4123 
![image](https://user-images.githubusercontent.com/11166933/61879468-fd7e3d80-aeea-11e9-8cdc-2d0f2af5ad89.png)

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes/dashboard/pull/4030#" title="Author self-approved">eloyekunle</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **jeefy**
You can assign the PR to them by writing `/assign @jeefy` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes%2Fdashboard).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes/dashboard/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["jeefy"]} -->
k8s-ci-robot: @eloyekunle: PR needs rebase.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

Patch:
diff --git a/angular.json b/angular.json
index 08fd4e144..c82b97ba3 100644
--- a/angular.json
+++ b/angular.json
@@ -24,6 +24,7 @@
               }
             ],
             "styles": [
+              "node_modules/highlight.js/styles/github.css",
               "node_modules/material-design-icons/iconfont/material-icons.css",
               "node_modules/roboto-fontface/css/roboto/roboto-fontface.css",
               "node_modules/xterm/dist/xterm.css",
diff --git a/go.mod b/go.mod
index dfa14dfc9..bc510a8ad 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,8 @@ module github.com/kubernetes/dashboard
 go 1.12
 
 require (
+	github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
+	github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 // indirect
 	github.com/docker/distribution v2.7.0+incompatible
 	github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
 	github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect
@@ -22,8 +24,9 @@ require (
 	github.com/onsi/gomega v1.5.0 // indirect
 	github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
 	github.com/prometheus/client_golang v0.9.2
-	github.com/prometheus/common v0.0.0-20181218105931-67670fe90761 // indirect
+	github.com/prometheus/common v0.0.0-20181218105931-67670fe90761
 	github.com/prometheus/procfs v0.0.0-20190102135031-14fa7590c24d // indirect
+	github.com/sirupsen/logrus v1.4.2 // indirect
 	github.com/spf13/pflag v1.0.3
 	golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 // indirect
 	golang.org/x/net v0.0.0-20190613194153-d28f0bde5980
@@ -32,6 +35,7 @@ require (
 	golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect
 	golang.org/x/text v0.3.2
 	golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect
+	gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
 	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
 	gopkg.in/igm/sockjs-go.v2 v2.0.0
 	gopkg.in/inf.v0 v0.9.1 // indirect
diff --git a/go.sum b/go.sum
index cffc9ffd1..7868a0523 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,9 @@
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -58,6 +62,7 @@ github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
 github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -92,11 +97,14 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R
 github.com/prometheus/procfs v0.0.0-20190102135031-14fa7590c24d h1:iSxvUGRUGQTUgEo5+8TqMVQoH5AdaphEIjh8AnM7TPo=
 github.com/prometheus/procfs v0.0.0-20190102135031-14fa7590c24d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
+github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
@@ -127,6 +135,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
@@ -143,6 +152,8 @@ google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO50
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
diff --git a/i18n/messages.fr.xlf b/i18n/messages.fr.xlf
index 28f8f9791..bd419f760 100644
--- a/i18n/messages.fr.xlf
+++ b/i18n/messages.fr.xlf
@@ -605,6 +605,18 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">48</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">51</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">41</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">36</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">57</context>
@@ -693,6 +705,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">54</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">70</context>
@@ -777,6 +793,14 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">70</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">80</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">58</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">94</context>
@@ -1314,43 +1338,51 @@
         <source>Items: </source>
         <target>Éléments : </target>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/node/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/cronjob/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/pod/template.html</context>
-          <context context-type="linenumber">24</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/clusterrole/template.html</context>
+          <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/replicaset/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
+          <context context-type="linenumber">23</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/condition/template.html</context>
           <context context-type="linenumber">26</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/namespace/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/persistentvolume/template.html</context>
-          <context context-type="linenumber">23</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">24</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/clusterrole/template.html</context>
-          <context context-type="linenumber">23</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">26</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/storageclass/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/cronjob/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/deployment/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/endpoint/cardlist/template.html</context>
+          <context context-type="linenumber">26</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/event/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/deployment/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/ingress/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
@@ -1358,25 +1390,29 @@
           <context context-type="linenumber">26</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/replicationcontroller/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/namespace/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/statefulset/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/node/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
-          <context context-type="linenumber">23</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/pod/template.html</context>
+          <context context-type="linenumber">24</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/secret/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/persistentvolume/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/persistentvolumeclaim/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/policyrule/template.html</context>
+          <context context-type="linenumber">26</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/quotas/template.html</context>
           <context context-type="linenumber">26</context>
@@ -1386,28 +1422,28 @@
           <context context-type="linenumber">26</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/ingress/template.html</context>
-          <context context-type="linenumber">23</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/replicaset/template.html</context>
+          <context context-type="linenumber">26</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/service/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/replicationcontroller/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/endpoint/cardlist/template.html</context>
-          <context context-type="linenumber">26</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/storageclass/template.html</context>
+          <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/event/template.html</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/statefulset/template.html</context>
           <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/condition/template.html</context>
-          <context context-type="linenumber">26</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/secret/template.html</context>
+          <context context-type="linenumber">23</context>
         </context-group>
         <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/common/components/policyrule/template.html</context>
-          <context context-type="linenumber">26</context>
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/service/template.html</context>
+          <context context-type="linenumber">23</context>
         </context-group>
       </trans-unit>
       <trans-unit id="fe22ca53e651df951dac25b67c17894b0980f767" datatype="html">
@@ -1833,6 +1869,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">58</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">62</context>
+        </context-group>
       </trans-unit>
       <trans-unit id="90ae2a4959c979abc049f4652f59b85e993e16cd" datatype="html">
         <source>CPU requests (cores)</source>
@@ -1922,6 +1962,74 @@
           <context context-type="linenumber">38</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="6af40687e73f3e54515b94380a6463e6f8744ff2" datatype="html">
+        <source>Custom Resource Definitions</source>
+        <target state="new">Custom Resource Definitions</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+        <source>Group</source>
+        <target state="new">Group</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">60</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">38</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="484b0e541230d60ddb5fbd771a34a5c8d90e7a57" datatype="html">
+        <source>Full Name</source>
+        <target state="new">Full Name</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">66</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c3e2c59f79e1c277706a4106e7ada43e5387a9d0" datatype="html">
+        <source>Namespaced</source>
+        <target state="new">Namespaced</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+        <source>Objects</source>
+        <target state="new">Objects</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="cfcee33b4f74fb641e9d6b00f72244d2b78c1480" datatype="html">
+        <source>Versions</source>
+        <target state="new">Versions</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">20</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="151dac5a4f23f33c7c8a2befe8b343edd202fd16" datatype="html">
+        <source>Served</source>
+        <target state="new">Served</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">42</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1fd6dbd0942f77002d852d7744dcb991cdd464d8" datatype="html">
+        <source>Storage</source>
+        <target state="new">Storage</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">48</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="c3a7e364a88ea4673199dfa98bc73e6dbe09dfac" datatype="html">
         <source>Namespaces</source>
         <target>Espacs de noms</target>
@@ -2330,6 +2438,78 @@
           <context context-type="linenumber">35</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="5927a3493fbb556db65f530e01b3aa6ab9f186e6" datatype="html">
+        <source>Resource Information</source>
+        <target state="new">Resource Information</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+        <source>Version</source>
+        <target state="new">Version</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">28</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+        <source>Scope</source>
+        <target state="new">Scope</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">33</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1ec17de9560711cd81108ccf93eb5b1df4eb6d4c" datatype="html">
+        <source>Accepted Names</source>
+        <target state="new">Accepted Names</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">46</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="fa1312fe00bfe38662df238fa059bcd75866ecd7" datatype="html">
+        <source>Plural</source>
+        <target state="new">Plural</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="712232bebfc8836a394c358ce9679452fabb945f" datatype="html">
+        <source>Singular</source>
+        <target state="new">Singular</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">57</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5a2fcb3c1d8240f8f966564ee3500235d7427245" datatype="html">
+        <source>List Kind</source>
+        <target state="new">List Kind</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">67</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d27e60f49dba9b7994331db545a4c14e1e2683ad" datatype="html">
+        <source>Short Names</source>
+        <target state="new">Short Names</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="04201f9d27abd7d6f58a4328ab98063ce1072006" datatype="html">
+        <source>Categories</source>
+        <target state="new">Categories</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">77</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html">
         <source>About</source>
         <target>À propos</target>
@@ -2582,13 +2762,23 @@
           <context context-type="linenumber">121</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="f2f9d18ebacb9e3bcb996d8176609e306864265e" datatype="html">
+        <source>Custom Resource Definitions
+      </source>
+        <target state="new">Custom Resource Definitions
+      </target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
+          <context context-type="linenumber">130</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="03511cfe5e28ed3380ab198c13cf62ebde1e89e6" datatype="html">
         <source>Settings
       </source>
         <target>Paramètres</target>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">130</context>
+          <context context-type="linenumber">139</context>
         </context-group>
       </trans-unit>
       <trans-unit id="c2fa735eb6b1b2c10171c5acb818f6e0975a9406" datatype="html">
@@ -2597,7 +2787,7 @@
         <target>À propos</target>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">135</context>
+          <context context-type="linenumber">144</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7e892ba15f2c6c17e83510e273b3e10fc32ea016" datatype="html">
@@ -4245,6 +4435,10 @@
       <trans-unit id="5ad4eecbd0fe09c34678fefce317a052af39dc96" datatype="html">
         <source>Data</source>
         <target>Données</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/crdobject/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/resource/config/configmap/detail/template.html</context>
           <context context-type="linenumber">23</context>
diff --git a/i18n/messages.ja.xlf b/i18n/messages.ja.xlf
index b6f4ba2b7..9e1d704f8 100644
--- a/i18n/messages.ja.xlf
+++ b/i18n/messages.ja.xlf
@@ -541,6 +541,18 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/condition/template.html</context>
           <context context-type="linenumber">26</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">23</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">24</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">26</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">23</context>
@@ -641,6 +653,18 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">48</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">51</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">41</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">36</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">57</context>
@@ -729,6 +753,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">54</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">70</context>
@@ -925,6 +953,14 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">70</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">80</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">58</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">94</context>
@@ -1245,6 +1281,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">58</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">62</context>
+        </context-group>
       </trans-unit>
       <trans-unit id="7357d53d819cc1f5dd329a4fff4c582461ee1317" datatype="html">
         <source>Pods</source>
@@ -1359,6 +1399,74 @@
           <context context-type="linenumber">38</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="6af40687e73f3e54515b94380a6463e6f8744ff2" datatype="html">
+        <source>Custom Resource Definitions</source>
+        <target state="new">Custom Resource Definitions</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+        <source>Group</source>
+        <target state="new">Group</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">60</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">38</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="484b0e541230d60ddb5fbd771a34a5c8d90e7a57" datatype="html">
+        <source>Full Name</source>
+        <target state="new">Full Name</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">66</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c3e2c59f79e1c277706a4106e7ada43e5387a9d0" datatype="html">
+        <source>Namespaced</source>
+        <target state="new">Namespaced</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+        <source>Objects</source>
+        <target state="new">Objects</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="cfcee33b4f74fb641e9d6b00f72244d2b78c1480" datatype="html">
+        <source>Versions</source>
+        <target state="new">Versions</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">20</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="151dac5a4f23f33c7c8a2befe8b343edd202fd16" datatype="html">
+        <source>Served</source>
+        <target state="new">Served</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">42</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1fd6dbd0942f77002d852d7744dcb991cdd464d8" datatype="html">
+        <source>Storage</source>
+        <target state="new">Storage</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">48</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="d41640b21b662e4d9ee00c35239d30d15f1de9c7" datatype="html">
         <source>Daemon Sets</source>
         <target>デーモンセット</target>
@@ -2392,13 +2500,23 @@
           <context context-type="linenumber">121</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="f2f9d18ebacb9e3bcb996d8176609e306864265e" datatype="html">
+        <source>Custom Resource Definitions
+      </source>
+        <target state="new">Custom Resource Definitions
+      </target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
+          <context context-type="linenumber">130</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="03511cfe5e28ed3380ab198c13cf62ebde1e89e6" datatype="html">
         <source>Settings
       </source>
         <target>設定</target>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">130</context>
+          <context context-type="linenumber">139</context>
         </context-group>
       </trans-unit>
       <trans-unit id="c2fa735eb6b1b2c10171c5acb818f6e0975a9406" datatype="html">
@@ -2407,7 +2525,7 @@
         <target>Kubernetes Dashboard について</target>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">135</context>
+          <context context-type="linenumber">144</context>
         </context-group>
       </trans-unit>
       <trans-unit id="01269ce8051398188d50367ead1831407e77d504" datatype="html">
@@ -2708,6 +2826,78 @@
           <context context-type="linenumber">35</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="5927a3493fbb556db65f530e01b3aa6ab9f186e6" datatype="html">
+        <source>Resource Information</source>
+        <target state="new">Resource Information</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+        <source>Version</source>
+        <target state="new">Version</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">28</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+        <source>Scope</source>
+        <target state="new">Scope</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">33</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1ec17de9560711cd81108ccf93eb5b1df4eb6d4c" datatype="html">
+        <source>Accepted Names</source>
+        <target state="new">Accepted Names</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">46</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="fa1312fe00bfe38662df238fa059bcd75866ecd7" datatype="html">
+        <source>Plural</source>
+        <target state="new">Plural</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="712232bebfc8836a394c358ce9679452fabb945f" datatype="html">
+        <source>Singular</source>
+        <target state="new">Singular</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">57</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5a2fcb3c1d8240f8f966564ee3500235d7427245" datatype="html">
+        <source>List Kind</source>
+        <target state="new">List Kind</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">67</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d27e60f49dba9b7994331db545a4c14e1e2683ad" datatype="html">
+        <source>Short Names</source>
+        <target state="new">Short Names</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="04201f9d27abd7d6f58a4328ab98063ce1072006" datatype="html">
+        <source>Categories</source>
+        <target state="new">Categories</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">77</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="7db62a1ccd31f1bb55e3532b0f58984a492296a8" datatype="html">
         <source>Create from input</source>
         <target>入力して作成</target>
@@ -4219,6 +4409,10 @@
       <trans-unit id="5ad4eecbd0fe09c34678fefce317a052af39dc96" datatype="html">
         <source>Data</source>
         <target>データ</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/crdobject/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/resource/config/configmap/detail/template.html</context>
           <context context-type="linenumber">23</context>
diff --git a/i18n/messages.xlf b/i18n/messages.xlf
index 8651984a9..7817f6f8c 100644
--- a/i18n/messages.xlf
+++ b/i18n/messages.xlf
@@ -653,6 +653,18 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/condition/template.html</context>
           <context context-type="linenumber">26</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">23</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">24</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">26</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">23</context>
@@ -752,6 +764,18 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">48</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">51</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">41</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">36</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">57</context>
@@ -839,6 +863,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">54</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">70</context>
@@ -1029,6 +1057,14 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">70</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">80</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">58</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">94</context>
@@ -1329,6 +1365,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">58</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">62</context>
+        </context-group>
       </trans-unit>
       <trans-unit id="81054386839df6c7c45d298e0044956413589ef4" datatype="html">
         <source>Age
@@ -1397,6 +1437,66 @@
           <context context-type="linenumber">38</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="6af40687e73f3e54515b94380a6463e6f8744ff2" datatype="html">
+        <source>Custom Resource Definitions</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+        <source>Group</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">60</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">38</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="484b0e541230d60ddb5fbd771a34a5c8d90e7a57" datatype="html">
+        <source>Full Name</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">66</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c3e2c59f79e1c277706a4106e7ada43e5387a9d0" datatype="html">
+        <source>Namespaced</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+        <source>Objects</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="cfcee33b4f74fb641e9d6b00f72244d2b78c1480" datatype="html">
+        <source>Versions</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">20</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="151dac5a4f23f33c7c8a2befe8b343edd202fd16" datatype="html">
+        <source>Served</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">42</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1fd6dbd0942f77002d852d7744dcb991cdd464d8" datatype="html">
+        <source>Storage</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">48</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="35bc68bd793eed6ee0232bfa6c4d72bc8c07fe69" datatype="html">
         <source>Endpoints</source>
         <context-group purpose="location">
@@ -2205,12 +2305,20 @@
           <context context-type="linenumber">121</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="f2f9d18ebacb9e3bcb996d8176609e306864265e" datatype="html">
+        <source>Custom Resource Definitions
+      </source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
+          <context context-type="linenumber">130</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="03511cfe5e28ed3380ab198c13cf62ebde1e89e6" datatype="html">
         <source>Settings
       </source>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">130</context>
+          <context context-type="linenumber">139</context>
         </context-group>
       </trans-unit>
       <trans-unit id="c2fa735eb6b1b2c10171c5acb818f6e0975a9406" datatype="html">
@@ -2218,7 +2326,7 @@
       </source>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">135</context>
+          <context context-type="linenumber">144</context>
         </context-group>
       </trans-unit>
       <trans-unit id="01269ce8051398188d50367ead1831407e77d504" datatype="html">
@@ -2475,6 +2583,84 @@
           <context context-type="linenumber">35</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="5927a3493fbb556db65f530e01b3aa6ab9f186e6" datatype="html">
+        <source>Resource Information</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+        <source>Version</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">28</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+        <source>Scope</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">33</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1ec17de9560711cd81108ccf93eb5b1df4eb6d4c" datatype="html">
+        <source>Accepted Names</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">46</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="fa1312fe00bfe38662df238fa059bcd75866ecd7" datatype="html">
+        <source>Plural</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="712232bebfc8836a394c358ce9679452fabb945f" datatype="html">
+        <source>Singular</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">57</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5a2fcb3c1d8240f8f966564ee3500235d7427245" datatype="html">
+        <source>List Kind</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">67</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d27e60f49dba9b7994331db545a4c14e1e2683ad" datatype="html">
+        <source>Short Names</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="04201f9d27abd7d6f58a4328ab98063ce1072006" datatype="html">
+        <source>Categories</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">77</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5ad4eecbd0fe09c34678fefce317a052af39dc96" datatype="html">
+        <source>Data</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/crdobject/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/resource/config/configmap/detail/template.html</context>
+          <context context-type="linenumber">23</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/resource/config/secret/detail/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="7db62a1ccd31f1bb55e3532b0f58984a492296a8" datatype="html">
         <source>Create from input</source>
         <context-group purpose="location">
@@ -3789,17 +3975,6 @@
           <context context-type="linenumber">320</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="5ad4eecbd0fe09c34678fefce317a052af39dc96" datatype="html">
-        <source>Data</source>
-        <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/resource/config/configmap/detail/template.html</context>
-          <context context-type="linenumber">23</context>
-        </context-group>
-        <context-group purpose="location">
-          <context context-type="sourcefile">../src/app/frontend/resource/config/secret/detail/template.html</context>
-          <context context-type="linenumber">22</context>
-        </context-group>
-      </trans-unit>
       <trans-unit id="cb784dbcccfc59a841e1b9477816aa9cada005fb" datatype="html">
         <source>There is no data to display.</source>
         <context-group purpose="location">
diff --git a/i18n/messages.zh.xlf b/i18n/messages.zh.xlf
index 480135569..a3fbe59aa 100644
--- a/i18n/messages.zh.xlf
+++ b/i18n/messages.zh.xlf
@@ -733,6 +733,18 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/condition/template.html</context>
           <context context-type="linenumber">26</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">23</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">24</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">26</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">23</context>
@@ -833,6 +845,18 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">48</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">51</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">41</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">36</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">57</context>
@@ -921,6 +945,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">54</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">70</context>
@@ -1117,6 +1145,14 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/configmap/template.html</context>
           <context context-type="linenumber">70</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">80</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">58</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/daemonset/template.html</context>
           <context context-type="linenumber">94</context>
@@ -1437,6 +1473,10 @@
           <context context-type="sourcefile">../src/app/frontend/common/components/creator/template.html</context>
           <context context-type="linenumber">58</context>
         </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">62</context>
+        </context-group>
       </trans-unit>
       <trans-unit id="81054386839df6c7c45d298e0044956413589ef4" datatype="html">
         <source>Age
@@ -1508,6 +1548,74 @@
           <context context-type="linenumber">38</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="6af40687e73f3e54515b94380a6463e6f8744ff2" datatype="html">
+        <source>Custom Resource Definitions</source>
+        <target state="new">Custom Resource Definitions</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="4c90059afafb7e160384d9f512797c95bb95c6dc" datatype="html">
+        <source>Group</source>
+        <target state="new">Group</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">60</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">38</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="484b0e541230d60ddb5fbd771a34a5c8d90e7a57" datatype="html">
+        <source>Full Name</source>
+        <target state="new">Full Name</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">66</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="c3e2c59f79e1c277706a4106e7ada43e5387a9d0" datatype="html">
+        <source>Namespaced</source>
+        <target state="new">Namespaced</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crd/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="afdb601c16162f2c798b16a2920955f1cc6a20aa" datatype="html">
+        <source>Objects</source>
+        <target state="new">Objects</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdobject/template.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="cfcee33b4f74fb641e9d6b00f72244d2b78c1480" datatype="html">
+        <source>Versions</source>
+        <target state="new">Versions</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">20</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="151dac5a4f23f33c7c8a2befe8b343edd202fd16" datatype="html">
+        <source>Served</source>
+        <target state="new">Served</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">42</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1fd6dbd0942f77002d852d7744dcb991cdd464d8" datatype="html">
+        <source>Storage</source>
+        <target state="new">Storage</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/crdversion/template.html</context>
+          <context context-type="linenumber">48</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="35bc68bd793eed6ee0232bfa6c4d72bc8c07fe69" datatype="html">
         <source>Endpoints</source>
         <target state="new">Endpoints</target>
@@ -2446,6 +2554,16 @@
           <context context-type="linenumber">121</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="f2f9d18ebacb9e3bcb996d8176609e306864265e" datatype="html">
+        <source>Custom Resource Definitions
+      </source>
+        <target state="new">Custom Resource Definitions
+      </target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
+          <context context-type="linenumber">130</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="03511cfe5e28ed3380ab198c13cf62ebde1e89e6" datatype="html">
         <source>Settings
       </source>
@@ -2453,7 +2571,7 @@
       </target>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">130</context>
+          <context context-type="linenumber">139</context>
         </context-group>
       </trans-unit>
       <trans-unit id="c2fa735eb6b1b2c10171c5acb818f6e0975a9406" datatype="html">
@@ -2463,7 +2581,7 @@
       </target>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
-          <context context-type="linenumber">135</context>
+          <context context-type="linenumber">144</context>
         </context-group>
       </trans-unit>
       <trans-unit id="01269ce8051398188d50367ead1831407e77d504" datatype="html">
@@ -2770,6 +2888,78 @@
           <context context-type="linenumber">35</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="5927a3493fbb556db65f530e01b3aa6ab9f186e6" datatype="html">
+        <source>Resource Information</source>
+        <target state="new">Resource Information</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
+        <source>Version</source>
+        <target state="new">Version</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">28</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1481b8488e10dbc437accce89d2ae35a0106e8ba" datatype="html">
+        <source>Scope</source>
+        <target state="new">Scope</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">33</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="1ec17de9560711cd81108ccf93eb5b1df4eb6d4c" datatype="html">
+        <source>Accepted Names</source>
+        <target state="new">Accepted Names</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">46</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="fa1312fe00bfe38662df238fa059bcd75866ecd7" datatype="html">
+        <source>Plural</source>
+        <target state="new">Plural</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">52</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="712232bebfc8836a394c358ce9679452fabb945f" datatype="html">
+        <source>Singular</source>
+        <target state="new">Singular</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">57</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="5a2fcb3c1d8240f8f966564ee3500235d7427245" datatype="html">
+        <source>List Kind</source>
+        <target state="new">List Kind</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">67</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="d27e60f49dba9b7994331db545a4c14e1e2683ad" datatype="html">
+        <source>Short Names</source>
+        <target state="new">Short Names</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">72</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="04201f9d27abd7d6f58a4328ab98063ce1072006" datatype="html">
+        <source>Categories</source>
+        <target state="new">Categories</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/detail/template.html</context>
+          <context context-type="linenumber">77</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="7db62a1ccd31f1bb55e3532b0f58984a492296a8" datatype="html">
         <source>Create from input</source>
         <target state="new">输入并创建</target>
@@ -4353,6 +4543,10 @@
       <trans-unit id="5ad4eecbd0fe09c34678fefce317a052af39dc96" datatype="html">
         <source>Data</source>
         <target state="new">数据</target>
+        <context-group purpose="location">
+          <context context-type="sourcefile">../src/app/frontend/crd/crdobject/template.html</context>
+          <context context-type="linenumber">22</context>
+        </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">../src/app/frontend/resource/config/configmap/detail/template.html</context>
           <context context-type="linenumber">23</context>
diff --git a/package-lock.json b/package-lock.json
index 725381f10..4e1b235bd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -947,28 +947,40 @@
       }
     },
     "@angular-devkit/schematics": {
-      "version": "8.1.3",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.1.3.tgz",
-      "integrity": "sha512-nz3b0uXu3w3PPLq4D+ersjeX/AyW3Amq7UwXa8lZFoJ0oc8cPjXW+h4D56rNw2GbOGZX7aaNe/Cxd9SBt0wF2A==",
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.2.0.tgz",
+      "integrity": "sha512-/XUWJijLXzhtWdjoQ5ioLo5r5V5+sJ0SSnSP0N8MQyLOgTd1FDGtBMsAMJ3n2/uwUl2/O9WTlV1xNLlg7neYVQ==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "8.1.3",
+        "@angular-devkit/core": "8.2.0",
         "rxjs": "6.4.0"
       },
       "dependencies": {
         "@angular-devkit/core": {
-          "version": "8.1.3",
-          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.1.3.tgz",
-          "integrity": "sha512-Vj5fowuz27J+S74U1+MrSrJ7vI+OZC5HBOp4m7rrh/GcYlujcX3BUu0Bxi7LI1v90yDsr0s/iEAKsff05ByXiw==",
+          "version": "8.2.0",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.2.0.tgz",
+          "integrity": "sha512-jZQn5hQ84++00+yuD/Ak303/Q06keFVyd+QbSfVrpHTFyOwPeNNSPLbN6A0S7X3bKOuoZhUHg+eQBa5BljVC2g==",
           "dev": true,
           "requires": {
-            "ajv": "6.10.0",
+            "ajv": "6.10.2",
             "fast-json-stable-stringify": "2.0.0",
             "magic-string": "0.25.3",
             "rxjs": "6.4.0",
             "source-map": "0.7.3"
           }
         },
+        "ajv": {
+          "version": "6.10.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+          "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^2.0.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
         "rxjs": {
           "version": "6.4.0",
           "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@@ -998,58 +1010,76 @@
       }
     },
     "@angular/cli": {
-      "version": "8.1.3",
-      "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.1.3.tgz",
-      "integrity": "sha512-8BuN+UW1etRGS2U8rnxLagcA/zCxAmrtH6cB943CecPkr3p9+VUlVXtrRU8lkQE/wdrGmJjS5qkG9TybTIPRwg==",
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.2.0.tgz",
+      "integrity": "sha512-KtjC5Mge93YjPQXxEKnXzQ7pmryizfVunrcKHSwhnzfNdwqSjcfL2evl4oBT07b6RfT0nF8HWn0ATWpiLWwrXQ==",
       "dev": true,
       "requires": {
-        "@angular-devkit/architect": "0.801.3",
-        "@angular-devkit/core": "8.1.3",
-        "@angular-devkit/schematics": "8.1.3",
-        "@schematics/angular": "8.1.3",
-        "@schematics/update": "0.801.3",
+        "@angular-devkit/architect": "0.802.0",
+        "@angular-devkit/core": "8.2.0",
+        "@angular-devkit/schematics": "8.2.0",
+        "@schematics/angular": "8.2.0",
+        "@schematics/update": "0.802.0",
         "@yarnpkg/lockfile": "1.1.0",
-        "ansi-colors": "4.1.0",
+        "ansi-colors": "4.1.1",
         "debug": "^4.1.1",
         "ini": "1.3.5",
-        "inquirer": "6.4.1",
+        "inquirer": "6.5.0",
         "npm-package-arg": "6.1.0",
         "open": "6.4.0",
-        "pacote": "9.5.1",
+        "pacote": "9.5.4",
         "read-package-tree": "5.3.1",
-        "semver": "6.2.0",
+        "semver": "6.3.0",
         "symbol-observable": "1.2.0",
         "universal-analytics": "^0.4.20",
         "uuid": "^3.3.2"
       },
       "dependencies": {
         "@angular-devkit/architect": {
-          "version": "0.801.3",
-          "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.801.3.tgz",
-          "integrity": "sha512-gg6ZyJMiRYuzzmbpuDszrsE/hpwzoUnlOVoLNNzbACGBSDiqelC1mvGHb9JQM56Sy8gSjZn6RT0K2/Og79GoSg==",
+          "version": "0.802.0",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.802.0.tgz",
+          "integrity": "sha512-Zd/ao7uE8ctV4n6drKl35cK5xrRsmgva7lsiBRc4J09vDWaRrCsxTKr6nw1gkFBDuSGZc9OmvtEFFPg2I/YHwQ==",
           "dev": true,
           "requires": {
-            "@angular-devkit/core": "8.1.3",
+            "@angular-devkit/core": "8.2.0",
             "rxjs": "6.4.0"
           }
         },
         "@angular-devkit/core": {
-          "version": "8.1.3",
-          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.1.3.tgz",
-          "integrity": "sha512-Vj5fowuz27J+S74U1+MrSrJ7vI+OZC5HBOp4m7rrh/GcYlujcX3BUu0Bxi7LI1v90yDsr0s/iEAKsff05ByXiw==",
+          "version": "8.2.0",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.2.0.tgz",
+          "integrity": "sha512-jZQn5hQ84++00+yuD/Ak303/Q06keFVyd+QbSfVrpHTFyOwPeNNSPLbN6A0S7X3bKOuoZhUHg+eQBa5BljVC2g==",
           "dev": true,
           "requires": {
-            "ajv": "6.10.0",
+            "ajv": "6.10.2",
             "fast-json-stable-stringify": "2.0.0",
             "magic-string": "0.25.3",
             "rxjs": "6.4.0",
             "source-map": "0.7.3"
           }
         },
+        "ajv": {
+          "version": "6.10.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+          "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^2.0.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
         "ansi-colors": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+          "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+          "dev": true
+        },
+        "ansi-regex": {
           "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.0.tgz",
-          "integrity": "sha512-3NkLpm6I6kEgC8J0I9EZ0fouXc/mm5J9zqJFCgA2jGqmsL0O64I7Uvi3AmUMnnRqc6u7uLgVVnY4pyBQ03nCiw==",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
           "dev": true
         },
         "debug": {
@@ -1061,6 +1091,27 @@
             "ms": "^2.1.1"
           }
         },
+        "inquirer": {
+          "version": "6.5.0",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz",
+          "integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==",
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^3.2.0",
+            "chalk": "^2.4.2",
+            "cli-cursor": "^2.1.0",
+            "cli-width": "^2.0.0",
+            "external-editor": "^3.0.3",
+            "figures": "^2.0.0",
+            "lodash": "^4.17.12",
+            "mute-stream": "0.0.7",
+            "run-async": "^2.2.0",
+            "rxjs": "^6.4.0",
+            "string-width": "^2.1.0",
+            "strip-ansi": "^5.1.0",
+            "through": "^2.3.6"
+          }
+        },
         "rxjs": {
           "version": "6.4.0",
           "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@@ -1070,11 +1121,14 @@
             "tslib": "^1.9.0"
           }
         },
-        "semver": {
-          "version": "6.2.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
-          "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==",
-          "dev": true
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
         }
       }
     },
@@ -1941,9 +1995,9 @@
       }
     },
     "@babel/code-frame": {
-      "version": "7.5.5",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
-      "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
       "dev": true,
       "requires": {
         "@babel/highlight": "^7.0.0"
@@ -2058,6 +2112,15 @@
         "lodash": "^4.17.13"
       },
       "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.5.5",
+          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
+          "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.0.0"
+          }
+        },
         "debug": {
           "version": "4.1.1",
           "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -2164,28 +2227,40 @@
       }
     },
     "@schematics/angular": {
-      "version": "8.1.3",
-      "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.1.3.tgz",
-      "integrity": "sha512-DsR/LDC7Vifw78pDew4HhUYvhKM5gyY8muvJqqfAU9DLq4yZ5ixus7jpqWXNeL3ZalFcH1/yQW20nzLQiLETkA==",
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.2.0.tgz",
+      "integrity": "sha512-DOo2wtk9fk0kHCDA/I+/mRrGKirgeqVhDbgOV4d2gbYSAiTl0s1Gb4eFAkJeovQTlARfaL2PIqDDkNeYjc7xpw==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "8.1.3",
-        "@angular-devkit/schematics": "8.1.3"
+        "@angular-devkit/core": "8.2.0",
+        "@angular-devkit/schematics": "8.2.0"
       },
       "dependencies": {
         "@angular-devkit/core": {
-          "version": "8.1.3",
-          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.1.3.tgz",
-          "integrity": "sha512-Vj5fowuz27J+S74U1+MrSrJ7vI+OZC5HBOp4m7rrh/GcYlujcX3BUu0Bxi7LI1v90yDsr0s/iEAKsff05ByXiw==",
+          "version": "8.2.0",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.2.0.tgz",
+          "integrity": "sha512-jZQn5hQ84++00+yuD/Ak303/Q06keFVyd+QbSfVrpHTFyOwPeNNSPLbN6A0S7X3bKOuoZhUHg+eQBa5BljVC2g==",
           "dev": true,
           "requires": {
-            "ajv": "6.10.0",
+            "ajv": "6.10.2",
             "fast-json-stable-stringify": "2.0.0",
             "magic-string": "0.25.3",
             "rxjs": "6.4.0",
             "source-map": "0.7.3"
           }
         },
+        "ajv": {
+          "version": "6.10.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+          "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^2.0.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
         "rxjs": {
           "version": "6.4.0",
           "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@@ -2198,34 +2273,46 @@
       }
     },
     "@schematics/update": {
-      "version": "0.801.3",
-      "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.801.3.tgz",
-      "integrity": "sha512-Y4HlG1eMUMlu62Kw2ic1+hF9+kKJlP35o+DO4t2LHKe/Kw+P+HJUeEpr/jocUxV56LDxF43BT3hkc9yJGIQ/Yw==",
+      "version": "0.802.0",
+      "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.802.0.tgz",
+      "integrity": "sha512-vMcFLTuw9jSlWQq6nNgMQi2fT/wGyaucvjkxFAs7pC+lyRwYws3IkOukbET7WeJ3ix0ZBEhMbPJ8EibUNDITjw==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "8.1.3",
-        "@angular-devkit/schematics": "8.1.3",
+        "@angular-devkit/core": "8.2.0",
+        "@angular-devkit/schematics": "8.2.0",
         "@yarnpkg/lockfile": "1.1.0",
         "ini": "1.3.5",
-        "pacote": "9.5.1",
+        "pacote": "9.5.4",
         "rxjs": "6.4.0",
-        "semver": "6.2.0",
+        "semver": "6.3.0",
         "semver-intersect": "1.4.0"
       },
       "dependencies": {
         "@angular-devkit/core": {
-          "version": "8.1.3",
-          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.1.3.tgz",
-          "integrity": "sha512-Vj5fowuz27J+S74U1+MrSrJ7vI+OZC5HBOp4m7rrh/GcYlujcX3BUu0Bxi7LI1v90yDsr0s/iEAKsff05ByXiw==",
+          "version": "8.2.0",
+          "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.2.0.tgz",
+          "integrity": "sha512-jZQn5hQ84++00+yuD/Ak303/Q06keFVyd+QbSfVrpHTFyOwPeNNSPLbN6A0S7X3bKOuoZhUHg+eQBa5BljVC2g==",
           "dev": true,
           "requires": {
-            "ajv": "6.10.0",
+            "ajv": "6.10.2",
             "fast-json-stable-stringify": "2.0.0",
             "magic-string": "0.25.3",
             "rxjs": "6.4.0",
             "source-map": "0.7.3"
           }
         },
+        "ajv": {
+          "version": "6.10.2",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+          "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+          "dev": true,
+          "requires": {
+            "fast-deep-equal": "^2.0.1",
+            "fast-json-stable-stringify": "^2.0.0",
+            "json-schema-traverse": "^0.4.1",
+            "uri-js": "^4.2.2"
+          }
+        },
         "rxjs": {
           "version": "6.4.0",
           "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@@ -2234,12 +2321,6 @@
           "requires": {
             "tslib": "^1.9.0"
           }
-        },
-        "semver": {
-          "version": "6.2.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
-          "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==",
-          "dev": true
         }
       }
     },
@@ -2581,6 +2662,11 @@
         "@types/node": "*"
       }
     },
+    "@types/highlight.js": {
+      "version": "9.12.3",
+      "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz",
+      "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ=="
+    },
     "@types/jasmine": {
       "version": "3.3.16",
       "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.16.tgz",
@@ -2895,9 +2981,9 @@
       "integrity": "sha512-wotVzxv5YClvwOjiuXNyGm4j/CnKoFIoTnnXNmi1nTHjr7hXMMjQeytcnbFua4thaJ5vvpVEDv0utmjqsrp3Jw=="
     },
     "acorn": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz",
-      "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==",
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz",
+      "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==",
       "dev": true
     },
     "acorn-dynamic-import": {
@@ -3131,9 +3217,9 @@
       }
     },
     "arg": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz",
-      "integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
+      "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==",
       "dev": true
     },
     "argparse": {
@@ -3363,20 +3449,12 @@
       "dev": true
     },
     "async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
+      "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
       "dev": true,
       "requires": {
-        "lodash": "^4.17.14"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
+        "lodash": "^4.17.11"
       }
     },
     "async-done": {
@@ -4536,12 +4614,6 @@
           "requires": {
             "ansi-regex": "^4.1.0"
           }
-        },
-        "type-fest": {
-          "version": "0.3.1",
-          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
-          "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
-          "dev": true
         }
       }
     },
@@ -7802,9 +7874,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.3.200",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.200.tgz",
-      "integrity": "sha512-PUurrpyDA74MuAjJRD+79ss5BqJlU3mdArRbuu4wO/dt6jc3Ic/6BDmFJxkdwbfq39cHf/XKm2vW98XSvut9Dg==",
+      "version": "1.3.188",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.188.tgz",
+      "integrity": "sha512-tEQcughYIMj8WDMc59EGEtNxdGgwal/oLLTDw+NEqJRJwGflQvH3aiyiexrWeZOETP4/ko78PVr6gwNhdozvuQ==",
       "dev": true
     },
     "elegant-spinner": {
@@ -10801,6 +10873,11 @@
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
+    "highlight.js": {
+      "version": "9.15.8",
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz",
+      "integrity": "sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA=="
+    },
     "hmac-drbg": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -10998,12 +11075,6 @@
         "slash": "^3.0.0"
       },
       "dependencies": {
-        "ci-info": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
-          "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
-          "dev": true
-        },
         "find-up": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -11014,15 +11085,6 @@
             "path-exists": "^4.0.0"
           }
         },
-        "is-ci": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
-          "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
-          "dev": true,
-          "requires": {
-            "ci-info": "^2.0.0"
-          }
-        },
         "locate-path": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -11085,6 +11147,12 @@
           "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
           "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
           "dev": true
+        },
+        "type-fest": {
+          "version": "0.6.0",
+          "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+          "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+          "dev": true
         }
       }
     },
@@ -11210,6 +11278,12 @@
       "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
       "dev": true
     },
+    "infer-owner": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+      "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+      "dev": true
+    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -12166,6 +12240,10 @@
         "useragent": "2.3.0"
       },
       "dependencies": {
+        "fsevents": {
+          "version": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz",
+          "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ=="
+        },
         "mime": {
           "version": "2.4.4",
           "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
@@ -13181,13 +13259,13 @@
       "dev": true
     },
     "make-fetch-happen": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-4.0.2.tgz",
-      "integrity": "sha512-YMJrAjHSb/BordlsDEcVcPyTbiJKkzqMf48N8dAJZT9Zjctrkb6Yg4TY9Sq2AwSIQJFn5qBBKVTYt3vP5FMIHA==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.0.tgz",
+      "integrity": "sha512-nFr/vpL1Jc60etMVKeaLOqfGjMMb3tAHFVJWxHOFCFS04Zmd7kGlMxo0l1tzfhoQje0/UPnd0X8OeGUiXXnfPA==",
       "dev": true,
       "requires": {
         "agentkeepalive": "^3.4.1",
-        "cacache": "^11.3.3",
+        "cacache": "^12.0.0",
         "http-cache-semantics": "^3.8.1",
         "http-proxy-agent": "^2.1.0",
         "https-proxy-agent": "^2.2.1",
@@ -13197,6 +13275,31 @@
         "promise-retry": "^1.1.1",
         "socks-proxy-agent": "^4.0.0",
         "ssri": "^6.0.0"
+      },
+      "dependencies": {
+        "cacache": {
+          "version": "12.0.2",
+          "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz",
+          "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==",
+          "dev": true,
+          "requires": {
+            "bluebird": "^3.5.5",
+            "chownr": "^1.1.1",
+            "figgy-pudding": "^3.5.1",
+            "glob": "^7.1.4",
+            "graceful-fs": "^4.1.15",
+            "infer-owner": "^1.0.3",
+            "lru-cache": "^5.1.1",
+            "mississippi": "^3.0.0",
+            "mkdirp": "^0.5.1",
+            "move-concurrently": "^1.0.1",
+            "promise-inflight": "^1.0.1",
+            "rimraf": "^2.6.3",
+            "ssri": "^6.0.1",
+            "unique-filename": "^1.1.1",
+            "y18n": "^4.0.0"
+          }
+        }
       }
     },
     "make-iterator": {
@@ -13984,9 +14087,9 @@
       }
     },
     "node-releases": {
-      "version": "1.1.26",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.26.tgz",
-      "integrity": "sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==",
+      "version": "1.1.25",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.25.tgz",
+      "integrity": "sha512-fI5BXuk83lKEoZDdH3gRhtsNgh05/wZacuXkgbiYkceE7+QIMXOg98n9ZV7mz27B+kFHnqHcUpscZZlGRSmTpQ==",
       "dev": true,
       "requires": {
         "semver": "^5.3.0"
@@ -14416,16 +14519,16 @@
       }
     },
     "npm-registry-fetch": {
-      "version": "3.9.1",
-      "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-3.9.1.tgz",
-      "integrity": "sha512-VQCEZlydXw4AwLROAXWUR7QDfe2Y8Id/vpAgp6TI1/H78a4SiQ1kQrKZALm5/zxM5n4HIi+aYb+idUAV/RuY0Q==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz",
+      "integrity": "sha512-Jllq35Jag8dtv0M17ue74XtdQTyqKzuAYGiX9mAjOhkmNjib3bBUgK6mUY61+AHnXeSRobQkpY3/xIOS/omptw==",
       "dev": true,
       "requires": {
         "JSONStream": "^1.3.4",
         "bluebird": "^3.5.1",
         "figgy-pudding": "^3.4.1",
         "lru-cache": "^5.1.1",
-        "make-fetch-happen": "^4.0.2",
+        "make-fetch-happen": "^5.0.0",
         "npm-package-arg": "^6.1.0"
       }
     },
@@ -14850,18 +14953,18 @@
       }
     },
     "pacote": {
-      "version": "9.5.1",
-      "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.1.tgz",
-      "integrity": "sha512-Zqvczvf/zZ7QNosdE9uTC7SRuvSs9tFqRkF6cJl+2HH7COBnx4BRAGpeXJlrbN+mM0CMHpbi620xdEHhCflghA==",
+      "version": "9.5.4",
+      "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.4.tgz",
+      "integrity": "sha512-nWr0ari6E+apbdoN0hToTKZElO5h4y8DGFa2pyNA5GQIdcP0imC96bA0bbPw1gpeguVIiUgHHaAlq/6xfPp8Qw==",
       "dev": true,
       "requires": {
         "bluebird": "^3.5.3",
-        "cacache": "^11.3.2",
+        "cacache": "^12.0.0",
         "figgy-pudding": "^3.5.1",
         "get-stream": "^4.1.0",
         "glob": "^7.1.3",
         "lru-cache": "^5.1.1",
-        "make-fetch-happen": "^4.0.1",
+        "make-fetch-happen": "^5.0.0",
         "minimatch": "^3.0.4",
         "minipass": "^2.3.5",
         "mississippi": "^3.0.0",
@@ -14870,7 +14973,7 @@
         "npm-package-arg": "^6.1.0",
         "npm-packlist": "^1.1.12",
         "npm-pick-manifest": "^2.2.3",
-        "npm-registry-fetch": "^3.8.0",
+        "npm-registry-fetch": "^4.0.0",
         "osenv": "^0.1.5",
         "promise-inflight": "^1.0.1",
         "promise-retry": "^1.1.1",
@@ -14884,6 +14987,29 @@
         "which": "^1.3.1"
       },
       "dependencies": {
+        "cacache": {
+          "version": "12.0.2",
+          "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz",
+          "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==",
+          "dev": true,
+          "requires": {
+            "bluebird": "^3.5.5",
+            "chownr": "^1.1.1",
+            "figgy-pudding": "^3.5.1",
+            "glob": "^7.1.4",
+            "graceful-fs": "^4.1.15",
+            "infer-owner": "^1.0.3",
+            "lru-cache": "^5.1.1",
+            "mississippi": "^3.0.0",
+            "mkdirp": "^0.5.1",
+            "move-concurrently": "^1.0.1",
+            "promise-inflight": "^1.0.1",
+            "rimraf": "^2.6.3",
+            "ssri": "^6.0.1",
+            "unique-filename": "^1.1.1",
+            "y18n": "^4.0.0"
+          }
+        },
         "semver": {
           "version": "5.7.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
@@ -15175,9 +15301,9 @@
       "dev": true
     },
     "portfinder": {
-      "version": "1.0.21",
-      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.21.tgz",
-      "integrity": "sha512-ESabpDCzmBS3ekHbmpAIiESq3udRsCBGiBZLsC+HgBKv2ezb0R4oG+7RnYEVZ/ZCfhel5Tx3UzdNWA0Lox2QCA==",
+      "version": "1.0.20",
+      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz",
+      "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==",
       "dev": true,
       "requires": {
         "async": "^1.5.2",
@@ -15431,9 +15557,9 @@
       },
       "dependencies": {
         "@types/node": {
-          "version": "6.14.7",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.7.tgz",
-          "integrity": "sha512-YbPXbaynBTe0pVExPhL76TsWnxSPeFAvImIsmylpBWn/yfw+lHy+Q68aawvZHsgskT44ZAoeE67GM5f+Brekew==",
+          "version": "6.14.6",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.6.tgz",
+          "integrity": "sha512-rFs9zCFtSHuseiNXxYxFlun8ibu+jtZPgRM+2ILCmeLiGeGLiIGxuOzD+cNyHegI1GD+da3R/cIbs9+xCLp13w==",
           "dev": true
         },
         "ansi-styles": {
@@ -18252,21 +18378,22 @@
           }
         },
         "yargs": {
-          "version": "13.3.0",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
-          "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
+          "version": "13.2.4",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz",
+          "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==",
           "dev": true,
           "requires": {
             "cliui": "^5.0.0",
             "find-up": "^3.0.0",
             "get-caller-file": "^2.0.1",
+            "os-locale": "^3.1.0",
             "require-directory": "^2.1.1",
             "require-main-filename": "^2.0.0",
             "set-blocking": "^2.0.0",
             "string-width": "^3.0.0",
             "which-module": "^2.0.0",
             "y18n": "^4.0.0",
-            "yargs-parser": "^13.1.1"
+            "yargs-parser": "^13.1.0"
           }
         },
         "yargs-parser": {
@@ -18373,9 +18500,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
-      "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz",
+      "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==",
       "dev": true
     },
     "spdy": {
@@ -19423,9 +19550,9 @@
       }
     },
     "type-fest": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
-      "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
+      "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
       "dev": true
     },
     "type-is": {
diff --git a/package.json b/package.json
index 1c6465424..b22ecb270 100644
--- a/package.json
+++ b/package.json
@@ -105,12 +105,14 @@
     "@types/d3": "5.7.2",
     "@types/d3-scale": "2.1.1",
     "@types/file-saver": "2.0.1",
+    "@types/highlight.js": "^9.12.3",
     "ace-builds": "1.4.5",
     "c3": "0.7.3",
     "core-js": "3.1.4",
     "d3": "5.9.7",
     "file-saver": "2.0.2",
     "hammerjs": "2.0.8",
+    "highlight.js": "^9.15.8",
     "js-yaml": "3.13.1",
     "material-design-icons": "3.0.1",
     "ng2-ace-editor": "0.3.9",
@@ -127,7 +129,7 @@
   },
   "devDependencies": {
     "@angular-devkit/build-angular": "0.801.1",
-    "@angular/cli": "8.1.3",
+    "@angular/cli": "8.2.0",
     "@angular/compiler-cli": "8.0.3",
     "@angular/language-service": "8.0.3",
     "@types/jasmine": "3.3.16",
diff --git a/src/app/backend/api/types.go b/src/app/backend/api/types.go
index 95ee8c8bd..cc214bbad 100644
--- a/src/app/backend/api/types.go
+++ b/src/app/backend/api/types.go
@@ -154,17 +154,19 @@ const (
 	ClientTypeAPIExtensionsClient = "apiextensionsclient"
 )
 
-// Mapping from resource kind to K8s apiserver API path. This is mostly pluralization, because
-// K8s apiserver uses plural paths and this project singular.
-// Must be kept in sync with the list of supported kinds.
-var KindToAPIMapping = map[string]struct {
+type APIMapping struct {
 	// Kubernetes resource name.
 	Resource string
 	// Client type used by given resource, i.e. deployments are using extension client.
 	ClientType ClientType
 	// Is this object global scoped (not below a namespace).
 	Namespaced bool
-}{
+}
+
+// Mapping from resource kind to K8s apiserver API path. This is mostly pluralization, because
+// K8s apiserver uses plural paths and this project singular.
+// Must be kept in sync with the list of supported kinds.
+var KindToAPIMapping = map[string]APIMapping{
 	ResourceKindConfigMap:                {"configmaps", ClientTypeDefault, true},
 	ResourceKindDaemonSet:                {"daemonsets", ClientTypeExtensionClient, true},
 	ResourceKindDeployment:               {"deployments", ClientTypeExtensionClient, true},
diff --git a/src/app/backend/client/api/types.go b/src/app/backend/client/api/types.go
index d7b6f5072..c718681a3 100644
--- a/src/app/backend/client/api/types.go
+++ b/src/app/backend/client/api/types.go
@@ -15,7 +15,7 @@
 package api
 
 import (
-	"github.com/emicklei/go-restful"
+	restful "github.com/emicklei/go-restful"
 	authApi "github.com/kubernetes/dashboard/src/app/backend/auth/api"
 	pluginclientset "github.com/kubernetes/dashboard/src/app/backend/plugin/client/clientset/versioned"
 	v1 "k8s.io/api/authorization/v1"
@@ -48,7 +48,7 @@ type ClientManager interface {
 	ClientCmdConfig(req *restful.Request) (clientcmd.ClientConfig, error)
 	CSRFKey() string
 	HasAccess(authInfo api.AuthInfo) error
-	VerberClient(req *restful.Request) (ResourceVerber, error)
+	VerberClient(req *restful.Request, config *rest.Config) (ResourceVerber, error)
 	SetTokenManager(manager authApi.TokenManager)
 }
 
diff --git a/src/app/backend/client/manager.go b/src/app/backend/client/manager.go
index 3be2266ed..4b932f24a 100644
--- a/src/app/backend/client/manager.go
+++ b/src/app/backend/client/manager.go
@@ -18,7 +18,7 @@ import (
 	"log"
 	"strings"
 
-	"github.com/emicklei/go-restful"
+	restful "github.com/emicklei/go-restful"
 	pluginclientset "github.com/kubernetes/dashboard/src/app/backend/plugin/client/clientset/versioned"
 	v1 "k8s.io/api/authorization/v1"
 	apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
@@ -241,7 +241,7 @@ func (self *clientManager) HasAccess(authInfo api.AuthInfo) error {
 }
 
 // VerberClient returns new verber client based on authentication information extracted from request
-func (self *clientManager) VerberClient(req *restful.Request) (clientapi.ResourceVerber, error) {
+func (self *clientManager) VerberClient(req *restful.Request, config *rest.Config) (clientapi.ResourceVerber, error) {
 	k8sClient, err := self.Client(req)
 	if err != nil {
 		return nil, err
@@ -255,7 +255,7 @@ func (self *clientManager) VerberClient(req *restful.Request) (clientapi.Resourc
 	return NewResourceVerber(k8sClient.CoreV1().RESTClient(),
 		k8sClient.ExtensionsV1beta1().RESTClient(), k8sClient.AppsV1().RESTClient(),
 		k8sClient.BatchV1().RESTClient(), k8sClient.BatchV1beta1().RESTClient(), k8sClient.AutoscalingV1().RESTClient(),
-		k8sClient.StorageV1().RESTClient(), k8sClient.RbacV1().RESTClient(), apiextensionsclient.ApiextensionsV1beta1().RESTClient()), nil
+		k8sClient.StorageV1().RESTClient(), k8sClient.RbacV1().RESTClient(), apiextensionsclient.ApiextensionsV1beta1().RESTClient(), config), nil
 }
 
 // SetTokenManager sets the token manager that will be used for token decryption.
diff --git a/src/app/backend/client/verber.go b/src/app/backend/client/verber.go
index 1ded3c523..a62e761ba 100644
--- a/src/app/backend/client/verber.go
+++ b/src/app/backend/client/verber.go
@@ -20,7 +20,8 @@ import (
 	"github.com/kubernetes/dashboard/src/app/backend/api"
 	clientapi "github.com/kubernetes/dashboard/src/app/backend/client/api"
 	"github.com/kubernetes/dashboard/src/app/backend/errors"
-
+	"github.com/kubernetes/dashboard/src/app/backend/resource/customresourcedefinition"
+	apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	restclient "k8s.io/client-go/rest"
@@ -38,6 +39,7 @@ type resourceVerber struct {
 	storageClient       RESTClient
 	rbacClient          RESTClient
 	apiExtensionsClient RESTClient
+	config              *restclient.Config
 }
 
 func (verber *resourceVerber) getRESTClientByType(clientType api.ClientType) RESTClient {
@@ -63,6 +65,46 @@ func (verber *resourceVerber) getRESTClientByType(clientType api.ClientType) RES
 	}
 }
 
+func (verber *resourceVerber) getResourceSpecFromKind(kind string, namespaceSet bool) (client RESTClient, resourceSpec api.APIMapping, err error) {
+	resourceSpec, ok := api.KindToAPIMapping[kind]
+	if !ok {
+		// check if kind is CRD
+		var crd apiextensions.CustomResourceDefinition
+		err = verber.apiExtensionsClient.Get().Resource("customresourcedefinitions").Name(kind).Do().Into(&crd)
+		if err != nil {
+			if errors.IsNotFoundError(err) {
+				err = errors.NewInvalid(fmt.Sprintf("Unknown resource kind: %s", kind))
+			}
+			return
+		}
+
+		client, err = customresourcedefinition.NewRESTClient(verber.config, &crd)
+		if err != nil {
+			return
+		}
+
+		resourceSpec = api.APIMapping{
+			Resource:   crd.Status.AcceptedNames.Plural,
+			Namespaced: crd.Spec.Scope == apiextensions.NamespaceScoped,
+		}
+	}
+
+	if namespaceSet != resourceSpec.Namespaced {
+		if namespaceSet {
+			err = errors.NewInvalid(fmt.Sprintf("Set namespace for not-namespaced resource kind: %s", kind))
+			return
+		} else {
+			err = errors.NewInvalid(fmt.Sprintf("Set no namespace for namespaced resource kind: %s", kind))
+			return
+		}
+	}
+
+	if client == nil {
+		client = verber.getRESTClientByType(resourceSpec.ClientType)
+	}
+	return
+}
+
 // RESTClient is an interface for REST operations used in this file.
 type RESTClient interface {
 	Delete() *restclient.Request
@@ -73,28 +115,18 @@ type RESTClient interface {
 // NewResourceVerber creates a new resource verber that uses the given client for performing operations.
 func NewResourceVerber(client, extensionsClient, appsClient,
 	batchClient, betaBatchClient, autoscalingClient, storageClient,
-	rbacClient, apiExtensionsClient RESTClient) clientapi.ResourceVerber {
+	rbacClient, apiExtensionsClient RESTClient, config *restclient.Config) clientapi.ResourceVerber {
 	return &resourceVerber{client, extensionsClient, appsClient,
-		batchClient, betaBatchClient, autoscalingClient, storageClient, rbacClient, apiExtensionsClient}
+		batchClient, betaBatchClient, autoscalingClient, storageClient, rbacClient, apiExtensionsClient, config}
 }
 
 // Delete deletes the resource of the given kind in the given namespace with the given name.
 func (verber *resourceVerber) Delete(kind string, namespaceSet bool, namespace string, name string) error {
-	resourceSpec, ok := api.KindToAPIMapping[kind]
-	if !ok {
-		return errors.NewInvalid(fmt.Sprintf("Unknown resource kind: %s", kind))
+	client, resourceSpec, err := verber.getResourceSpecFromKind(kind, namespaceSet)
+	if err != nil {
+		return err
 	}
 
-	if namespaceSet != resourceSpec.Namespaced {
-		if namespaceSet {
-			return errors.NewInvalid(fmt.Sprintf("Set namespace for not-namespaced resource kind: %s", kind))
-		} else {
-			return errors.NewInvalid(fmt.Sprintf("Set no namespace for namespaced resource kind: %s", kind))
-		}
-	}
-
-	client := verber.getRESTClientByType(resourceSpec.ClientType)
-
 	// Do cascade delete by default, as this is what users typically expect.
 	defaultPropagationPolicy := v1.DeletePropagationForeground
 	defaultDeleteOptions := &v1.DeleteOptions{
@@ -114,21 +146,11 @@ func (verber *resourceVerber) Delete(kind string, namespaceSet bool, namespace s
 func (verber *resourceVerber) Put(kind string, namespaceSet bool, namespace string, name string,
 	object *runtime.Unknown) error {
 
-	resourceSpec, ok := api.KindToAPIMapping[kind]
-	if !ok {
-		return errors.NewInvalid(fmt.Sprintf("Unknown resource kind: %s", kind))
-	}
-
-	if namespaceSet != resourceSpec.Namespaced {
-		if namespaceSet {
-			return errors.NewInvalid(fmt.Sprintf("Set namespace for not-namespaced resource kind: %s", kind))
-		} else {
-			return errors.NewInvalid(fmt.Sprintf("Set no namespace for namespaced resource kind: %s", kind))
-		}
+	client, resourceSpec, err := verber.getResourceSpecFromKind(kind, namespaceSet)
+	if err != nil {
+		return err
 	}
 
-	client := verber.getRESTClientByType(resourceSpec.ClientType)
-
 	req := client.Put().
 		Resource(resourceSpec.Resource).
 		Name(name).
@@ -144,20 +166,11 @@ func (verber *resourceVerber) Put(kind string, namespaceSet bool, namespace stri
 
 // Get gets the resource of the given kind in the given namespace with the given name.
 func (verber *resourceVerber) Get(kind string, namespaceSet bool, namespace string, name string) (runtime.Object, error) {
-	resourceSpec, ok := api.KindToAPIMapping[kind]
-	if !ok {
-		return nil, errors.NewInvalid(fmt.Sprintf("Unknown resource kind: %s", kind))
-	}
-
-	if namespaceSet != resourceSpec.Namespaced {
-		if namespaceSet {
-			return nil, errors.NewInvalid(fmt.Sprintf("Set namespace for not-namespaced resource kind: %s", kind))
-		} else {
-			return nil, errors.NewInvalid(fmt.Sprintf("Set no namespace for namespaced resource kind: %s", kind))
-		}
+	client, resourceSpec, err := verber.getResourceSpecFromKind(kind, namespaceSet)
+	if err != nil {
+		return nil, err
 	}
 
-	client := verber.getRESTClientByType(resourceSpec.ClientType)
 	result := &runtime.Unknown{}
 	req := client.Get().Resource(resourceSpec.Resource).Name(name).SetHeader("Accept", "application/json")
 
@@ -165,6 +178,6 @@ func (verber *resourceVerber) Get(kind string, namespaceSet bool, namespace stri
 		req.Namespace(namespace)
 	}
 
-	err := req.Do().Into(result)
+	err = req.Do().Into(result)
 	return result, err
 }
diff --git a/src/app/backend/errors/errors.go b/src/app/backend/errors/errors.go
index b59640bb0..0a03077fe 100644
--- a/src/app/backend/errors/errors.go
+++ b/src/app/backend/errors/errors.go
@@ -55,6 +55,17 @@ func NewInvalid(reason string) *errors.StatusError {
 	}
 }
 
+func NewNotFound(reason string) *errors.StatusError {
+	return &errors.StatusError{
+		ErrStatus: metav1.Status{
+			Status:  metav1.StatusFailure,
+			Code:    http.StatusNotFound,
+			Reason:  metav1.StatusReasonNotFound,
+			Message: reason,
+		},
+	}
+}
+
 func NewInternal(reason string) *errors.StatusError {
 	return &errors.StatusError{ErrStatus: metav1.Status{
 		Status: metav1.StatusFailure,
diff --git a/src/app/backend/handler/apihandler.go b/src/app/backend/handler/apihandler.go
index 6191b0ac8..d1263937e 100644
--- a/src/app/backend/handler/apihandler.go
+++ b/src/app/backend/handler/apihandler.go
@@ -20,9 +20,7 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/kubernetes/dashboard/src/app/backend/plugin"
-
-	"github.com/emicklei/go-restful"
+	restful "github.com/emicklei/go-restful"
 	"github.com/kubernetes/dashboard/src/app/backend/api"
 	"github.com/kubernetes/dashboard/src/app/backend/auth"
 	authApi "github.com/kubernetes/dashboard/src/app/backend/auth/api"
@@ -30,6 +28,7 @@ import (
 	"github.com/kubernetes/dashboard/src/app/backend/errors"
 	"github.com/kubernetes/dashboard/src/app/backend/integration"
 	metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
+	"github.com/kubernetes/dashboard/src/app/backend/plugin"
 	"github.com/kubernetes/dashboard/src/app/backend/resource/clusterrole"
 	"github.com/kubernetes/dashboard/src/app/backend/resource/common"
 	"github.com/kubernetes/dashboard/src/app/backend/resource/configmap"
@@ -548,12 +547,12 @@ func CreateHTTPAPIHandler(iManager integration.IntegrationManager, cManager clie
 			Writes(customresourcedefinition.CustomResourceObjectList{}))
 
 	apiV1Ws.Route(
-		apiV1Ws.GET("/crd/{namespace}/{crd}/object/{name}").
+		apiV1Ws.GET("/crd/{namespace}/{crd}/{object}").
 			To(apiHandler.handleGetCustomResourceObjectDetail).
-			Writes(customresourcedefinition.CustomResourceObjectDetail{}))
+			Writes(customresourcedefinition.CustomResourceObject{}))
 
 	apiV1Ws.Route(
-		apiV1Ws.GET("/crd/{namespace}/{crd}/object/{name}/event").
+		apiV1Ws.GET("/crd/{namespace}/{crd}/{object}/event").
 			To(apiHandler.handleGetCustomResourceObjectEvents).
 			Writes(common.EventList{}))
 
@@ -1350,7 +1349,13 @@ func (apiHandler *APIHandler) handleUpdateReplicasCount(request *restful.Request
 }
 
 func (apiHandler *APIHandler) handleGetResource(request *restful.Request, response *restful.Response) {
-	verber, err := apiHandler.cManager.VerberClient(request)
+	config, err := apiHandler.cManager.Config(request)
+	if err != nil {
+		errors.HandleInternalError(response, err)
+		return
+	}
+
+	verber, err := apiHandler.cManager.VerberClient(request, config)
 	if err != nil {
 		errors.HandleInternalError(response, err)
 		return
@@ -1370,7 +1375,13 @@ func (apiHandler *APIHandler) handleGetResource(request *restful.Request, respon
 
 func (apiHandler *APIHandler) handlePutResource(
 	request *restful.Request, response *restful.Response) {
-	verber, err := apiHandler.cManager.VerberClient(request)
+	config, err := apiHandler.cManager.Config(request)
+	if err != nil {
+		errors.HandleInternalError(response, err)
+		return
+	}
+
+	verber, err := apiHandler.cManager.VerberClient(request, config)
 	if err != nil {
 		errors.HandleInternalError(response, err)
 		return
@@ -1395,7 +1406,13 @@ func (apiHandler *APIHandler) handlePutResource(
 
 func (apiHandler *APIHandler) handleDeleteResource(
 	request *restful.Request, response *restful.Response) {
-	verber, err := apiHandler.cManager.VerberClient(request)
+	config, err := apiHandler.cManager.Config(request)
+	if err != nil {
+		errors.HandleInternalError(response, err)
+		return
+	}
+
+	verber, err := apiHandler.cManager.VerberClient(request, config)
 	if err != nil {
 		errors.HandleInternalError(response, err)
 		return
@@ -2152,7 +2169,7 @@ func (apiHandler *APIHandler) handleGetCustomResourceObjectDetail(request *restf
 		return
 	}
 
-	name := request.PathParameter("name")
+	name := request.PathParameter("object")
 	crdName := request.PathParameter("crd")
 	namespace := parseNamespacePathParameter(request)
 	result, err := customresourcedefinition.GetCustomResourceObjectDetail(apiextensionsclient, namespace, config, crdName, name)
@@ -2173,8 +2190,8 @@ func (apiHandler *APIHandler) handleGetCustomResourceObjectEvents(request *restf
 		return
 	}
 
+	name := request.PathParameter("object")
 	namespace := request.PathParameter("namespace")
-	name := request.PathParameter("name")
 	dataSelect := parseDataSelectPathParameter(request)
 	dataSelect.MetricQuery = dataselect.StandardMetrics
 	result, err := customresourcedefinition.GetEventsForCustomResourceObject(k8sClient, dataSelect, namespace, name)
diff --git a/src/app/backend/resource/customresourcedefinition/client.go b/src/app/backend/resource/customresourcedefinition/client.go
index 824ec6513..b9ca64d34 100644
--- a/src/app/backend/resource/customresourcedefinition/client.go
+++ b/src/app/backend/resource/customresourcedefinition/client.go
@@ -15,14 +15,15 @@
 package customresourcedefinition
 
 import (
+	apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/runtime/serializer"
 	"k8s.io/client-go/rest"
 )
 
-func newRESTClient(config *rest.Config, groupVersion schema.GroupVersion) (*rest.RESTClient, error) {
+func NewRESTClient(config *rest.Config, crd *apiextensions.CustomResourceDefinition) (*rest.RESTClient, error) {
+	groupVersion := getCustomResourceDefinitionGroupVersion(crd)
 	scheme := runtime.NewScheme()
 	schemeBuilder := runtime.NewSchemeBuilder(
 		func(scheme *runtime.Scheme) error {
@@ -30,8 +31,6 @@ func newRESTClient(config *rest.Config, groupVersion schema.GroupVersion) (*rest
 				groupVersion,
 				&metav1.ListOptions{},
 				&metav1.DeleteOptions{},
-				&CustomResourceObject{},
-				&CustomResourceObjectList{},
 			)
 			return nil
 		})
@@ -44,10 +43,5 @@ func newRESTClient(config *rest.Config, groupVersion schema.GroupVersion) (*rest
 	config.ContentType = runtime.ContentTypeJSON
 	config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)}
 
-	client, err := rest.RESTClientFor(config)
-	if err != nil {
-		return nil, err
-	}
-
-	return client, nil
+	return rest.RESTClientFor(config)
 }
diff --git a/src/app/backend/resource/customresourcedefinition/common.go b/src/app/backend/resource/customresourcedefinition/common.go
index 8b8f68c88..7a02ee7e3 100644
--- a/src/app/backend/resource/customresourcedefinition/common.go
+++ b/src/app/backend/resource/customresourcedefinition/common.go
@@ -15,9 +15,9 @@
 package customresourcedefinition
 
 import (
-	"strings"
-
+	"github.com/kubernetes/dashboard/src/app/backend/resource/common"
 	"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
+	api "k8s.io/api/core/v1"
 	apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 )
@@ -54,17 +54,17 @@ func fromCells(cells []dataselect.DataCell) []apiextensions.CustomResourceDefini
 	return std
 }
 
-// The code below allows to perform complex data section on ThirdPartyResourceObject.
+// The code below allows to perform complex data section on CustomResourceObject.
 type CustomResourceObjectCell CustomResourceObject
 
 func (self CustomResourceObjectCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
 	switch name {
 	case dataselect.NameProperty:
-		return dataselect.StdComparableString(self.Metadata.Name)
+		return dataselect.StdComparableString(self.ObjectMeta.Name)
 	case dataselect.CreationTimestampProperty:
-		return dataselect.StdComparableTime(self.Metadata.CreationTimestamp.Time)
+		return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
 	case dataselect.NamespaceProperty:
-		return dataselect.StdComparableString(self.Metadata.Namespace)
+		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
@@ -90,16 +90,22 @@ func fromObjectCells(cells []dataselect.DataCell) []CustomResourceObject {
 // getCustomResourceDefinitionGroupVersion returns first group version of custom resource definition.
 // It's also known as preferredVersion.
 func getCustomResourceDefinitionGroupVersion(crd *apiextensions.CustomResourceDefinition) schema.GroupVersion {
-	version := crd.Spec.Version
-	group := ""
-	if strings.Contains(crd.ObjectMeta.Name, ".") {
-		group = crd.ObjectMeta.Name[strings.Index(crd.ObjectMeta.Name, ".")+1:]
-	} else {
-		group = crd.ObjectMeta.Name
+	return schema.GroupVersion{
+		Group:   crd.Spec.Group,
+		Version: crd.Spec.Version,
 	}
+}
 
-	return schema.GroupVersion{
-		Group:   group,
-		Version: version,
+func getCRDConditions(crd *apiextensions.CustomResourceDefinition) []common.Condition {
+	var conditions []common.Condition
+	for _, condition := range crd.Status.Conditions {
+		conditions = append(conditions, common.Condition{
+			Type:               string(condition.Type),
+			Status:             api.ConditionStatus(condition.Status),
+			LastTransitionTime: condition.LastTransitionTime,
+			Reason:             condition.Reason,
+			Message:            condition.Message,
+		})
 	}
+	return conditions
 }
diff --git a/src/app/backend/resource/customresourcedefinition/detail.go b/src/app/backend/resource/customresourcedefinition/detail.go
index da0f14157..c0fc47ecd 100644
--- a/src/app/backend/resource/customresourcedefinition/detail.go
+++ b/src/app/backend/resource/customresourcedefinition/detail.go
@@ -15,7 +15,7 @@
 package customresourcedefinition
 
 import (
-	"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"
 	apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
@@ -26,14 +26,19 @@ import (
 
 type CustomResourceDefinitionDetail struct {
 	CustomResourceDefinition `json:",inline"`
+
+	Versions   []CustomResourceDefinitionVersion `json:"versions,omitempty"`
+	Conditions []common.Condition                `json:"conditions"`
+	Objects    CustomResourceObjectList          `json:"objects"`
+
+	// List of non-critical errors, that occurred during resource retrieval.
+	Errors []error `json:"errors"`
 }
 
-// CustomResourceDefinition represents a custom resource definition.
-type CustomResourceDefinition struct {
-	ObjectMeta api.ObjectMeta           `json:"objectMeta"`
-	TypeMeta   api.TypeMeta             `json:"typeMeta"`
-	Version    string                   `json:"version"`
-	Objects    CustomResourceObjectList `json:"objects"`
+type CustomResourceDefinitionVersion struct {
+	Name    string `json:"name"`
+	Served  bool   `json:"served"`
+	Storage bool   `json:"storage"`
 }
 
 // GetCustomResourceDefinitionDetail returns detailed information about a custom resource definition.
@@ -41,25 +46,41 @@ func GetCustomResourceDefinitionDetail(client apiextensionsclientset.Interface,
 	customResourceDefinition, err := client.ApiextensionsV1beta1().
 		CustomResourceDefinitions().
 		Get(name, metav1.GetOptions{})
-	if err != nil {
-		return nil, err
+	nonCriticalErrors, criticalError := errors.HandleError(err)
+	if criticalError != nil {
+		return nil, criticalError
 	}
 
 	objects, err := GetCustomResourceObjectList(client, config, &common.NamespaceQuery{}, dataselect.DefaultDataSelect, name)
-	if err != nil {
-		return nil, err
+	nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
+	if criticalError != nil {
+		return nil, criticalError
 	}
 
-	return toCustomResourceDefinitionDetail(customResourceDefinition, objects), nil
+	return toCustomResourceDefinitionDetail(customResourceDefinition, *objects, nonCriticalErrors), nil
 }
 
-func toCustomResourceDefinitionDetail(customResourceDefinition *apiextensions.CustomResourceDefinition, objects CustomResourceObjectList) *CustomResourceDefinitionDetail {
+func toCustomResourceDefinitionDetail(crd *apiextensions.CustomResourceDefinition, objects CustomResourceObjectList, nonCriticalErrors []error) *CustomResourceDefinitionDetail {
 	return &CustomResourceDefinitionDetail{
-		CustomResourceDefinition{
-			ObjectMeta: api.NewObjectMeta(customResourceDefinition.ObjectMeta),
-			TypeMeta:   api.NewTypeMeta(api.ResourceKindCustomResourceDefinition),
-			Version:    customResourceDefinition.Spec.Version,
-			Objects:    objects,
-		},
+		CustomResourceDefinition: toCustomResourceDefinition(crd),
+		Versions:                 getCRDVersions(crd),
+		Conditions:               getCRDConditions(crd),
+		Objects:                  objects,
+		Errors:                   nonCriticalErrors,
+	}
+}
+
+func getCRDVersions(crd *apiextensions.CustomResourceDefinition) []CustomResourceDefinitionVersion {
+	crdVersions := make([]CustomResourceDefinitionVersion, 0, len(crd.Spec.Versions))
+	if len(crd.Spec.Versions) > 0 {
+		for _, version := range crd.Spec.Versions {
+			crdVersions = append(crdVersions, CustomResourceDefinitionVersion{
+				Name:    version.Name,
+				Served:  version.Served,
+				Storage: version.Storage,
+			})
+		}
 	}
+
+	return crdVersions
 }
diff --git a/src/app/backend/resource/customresourcedefinition/list.go b/src/app/backend/resource/customresourcedefinition/list.go
index b2a186eaa..c16e72df4 100644
--- a/src/app/backend/resource/customresourcedefinition/list.go
+++ b/src/app/backend/resource/customresourcedefinition/list.go
@@ -34,6 +34,17 @@ type CustomResourceDefinitionList struct {
 	Errors []error `json:"errors"`
 }
 
+// CustomResourceDefinition represents a custom resource definition.
+type CustomResourceDefinition struct {
+	ObjectMeta  api.ObjectMeta                              `json:"objectMeta"`
+	TypeMeta    api.TypeMeta                                `json:"typeMeta"`
+	Version     string                                      `json:"version,omitempty"`
+	Group       string                                      `json:"group"`
+	Scope       apiextensions.ResourceScope                 `json:"scope"`
+	Names       apiextensions.CustomResourceDefinitionNames `json:"names"`
+	Established apiextensions.ConditionStatus               `json:"established"`
+}
+
 // GetCustomResourceDefinitionList returns all the custom resource definitions in the cluster.
 func GetCustomResourceDefinitionList(client apiextensionsclientset.Interface, dsQuery *dataselect.DataSelectQuery) (*CustomResourceDefinitionList, error) {
 	channel := common.GetCustomResourceDefinitionChannel(client, 1)
@@ -68,8 +79,21 @@ func toCustomResourceDefinitionList(crds []apiextensions.CustomResourceDefinitio
 
 func toCustomResourceDefinition(crd *apiextensions.CustomResourceDefinition) CustomResourceDefinition {
 	return CustomResourceDefinition{
-		ObjectMeta: api.NewObjectMeta(crd.ObjectMeta),
-		TypeMeta:   api.NewTypeMeta(api.ResourceKindCustomResourceDefinition),
-		Version:    crd.Spec.Version,
+		ObjectMeta:  api.NewObjectMeta(crd.ObjectMeta),
+		TypeMeta:    api.NewTypeMeta(api.ResourceKindCustomResourceDefinition),
+		Version:     crd.Spec.Version,
+		Group:       crd.Spec.Group,
+		Scope:       crd.Spec.Scope,
+		Names:       crd.Status.AcceptedNames,
+		Established: getCRDConditionStatus(crd, apiextensions.Established),
+	}
+}
+
+func getCRDConditionStatus(node *apiextensions.CustomResourceDefinition, conditionType apiextensions.CustomResourceDefinitionConditionType) apiextensions.ConditionStatus {
+	for _, condition := range node.Status.Conditions {
+		if condition.Type == conditionType {
+			return condition.Status
+		}
 	}
+	return apiextensions.ConditionUnknown
 }
diff --git a/src/app/backend/resource/customresourcedefinition/objects.go b/src/app/backend/resource/customresourcedefinition/objects.go
index 828abec82..c69d016d9 100644
--- a/src/app/backend/resource/customresourcedefinition/objects.go
+++ b/src/app/backend/resource/customresourcedefinition/objects.go
@@ -15,47 +15,50 @@
 package customresourcedefinition
 
 import (
+	"encoding/json"
+
 	"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"
 	apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/rest"
 )
 
-type CustomResourceObjectDetail struct {
-	CustomResourceObject `json:",inline"`
-}
-
 // CustomResourceObject represents a custom resource object.
 type CustomResourceObject struct {
-	metav1.TypeMeta `json:",inline"`
-	Metadata        metav1.ObjectMeta `json:"metadata,omitempty"`
+	TypeMeta   metav1.TypeMeta   `json:"typeMeta"`
+	ObjectMeta metav1.ObjectMeta `json:"objectMeta"`
 }
 
-func (in *CustomResourceObject) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	} else {
-		return nil
+func (r *CustomResourceObject) UnmarshalJSON(data []byte) error {
+	tempStruct := &struct {
+		metav1.TypeMeta `json:",inline"`
+		ObjectMeta      metav1.ObjectMeta `json:"metadata,omitempty"`
+	}{}
+
+	err := json.Unmarshal(data, &tempStruct)
+	if err != nil {
+		return err
 	}
+
+	r.TypeMeta = tempStruct.TypeMeta
+	r.ObjectMeta = tempStruct.ObjectMeta
+	return nil
 }
 
-func (in *CustomResourceObject) DeepCopy() *CustomResourceObject {
-	if in == nil {
-		return nil
-	}
-	out := new(CustomResourceObject)
-	*out = *in
-	return out
+type CustomResourceObjectDetail struct {
+	CustomResourceObject `json:",inline"`
+
+	// List of non-critical errors, that occurred during resource retrieval.
+	Errors []error `json:"errors"`
 }
 
 // CustomResourceObjectList represents crd objects in a namespace.
 type CustomResourceObjectList struct {
-	ListMeta        api.ListMeta `json:"listMeta"`
-	metav1.TypeMeta `json:",inline"`
+	TypeMeta metav1.TypeMeta `json:"typeMeta"`
+	ListMeta api.ListMeta    `json:"listMeta"`
 
 	// Unordered list of custom resource definitions
 	Items []CustomResourceObject `json:"items"`
@@ -64,83 +67,109 @@ type CustomResourceObjectList struct {
 	Errors []error `json:"errors"`
 }
 
-func (in *CustomResourceObjectList) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	} else {
-		return nil
-	}
-}
+func (r *CustomResourceObjectList) UnmarshalJSON(data []byte) error {
+	tempStruct := &struct {
+		metav1.TypeMeta `json:",inline"`
+		Items           []CustomResourceObject `json:"items"`
+	}{}
 
-func (in *CustomResourceObjectList) DeepCopy() *CustomResourceObjectList {
-	if in == nil {
-		return nil
+	err := json.Unmarshal(data, &tempStruct)
+	if err != nil {
+		return err
 	}
-	out := new(CustomResourceObjectList)
-	*out = *in
-	return out
+
+	r.TypeMeta = tempStruct.TypeMeta
+	r.Items = tempStruct.Items
+	return nil
 }
 
 // GetCustomResourceObjectList gets objects for a CR.
 func GetCustomResourceObjectList(client apiextensionsclientset.Interface, config *rest.Config, namespace *common.NamespaceQuery,
-	dsQuery *dataselect.DataSelectQuery, crdName string) (CustomResourceObjectList, error) {
-	var list CustomResourceObjectList
+	dsQuery *dataselect.DataSelectQuery, crdName string) (*CustomResourceObjectList, error) {
+	var list *CustomResourceObjectList
 
 	customResourceDefinition, err := client.ApiextensionsV1beta1().
 		CustomResourceDefinitions().
 		Get(crdName, metav1.GetOptions{})
 	nonCriticalErrors, criticalError := errors.HandleError(err)
 	if criticalError != nil {
-		return list, criticalError
+		return nil, criticalError
 	}
 
-	restClient, err := newRESTClient(config, getCustomResourceDefinitionGroupVersion(customResourceDefinition))
+	restClient, err := NewRESTClient(config, customResourceDefinition)
 	nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
 	if criticalError != nil {
-		return list, criticalError
+		return nil, criticalError
 	}
 
-	err = restClient.Get().
+	raw, err := restClient.Get().
 		Namespace(namespace.ToRequestParam()).
 		Resource(customResourceDefinition.Spec.Names.Plural).
-		Do().Into(&list)
+		Do().Raw()
+	nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
+	if criticalError != nil {
+		return nil, criticalError
+	}
+
+	err = json.Unmarshal(raw, &list)
 	nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
 	if criticalError != nil {
-		return list, criticalError
+		return nil, criticalError
 	}
+	list.Errors = nonCriticalErrors
 
 	// Return only slice of data, pagination is done here.
 	crdObjectCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toObjectCells(list.Items), dsQuery)
 	list.Items = fromObjectCells(crdObjectCells)
 	list.ListMeta = api.ListMeta{TotalItems: filteredTotal}
-	list.Errors = nonCriticalErrors
+
+	for i := range list.Items {
+		replaceCRDObjectKind(&list.Items[i], customResourceDefinition.Name)
+	}
 
 	return list, nil
 }
 
 // GetCustomResourceObjectDetail returns details of a single object in a CR.
-func GetCustomResourceObjectDetail(client apiextensionsclientset.Interface, namespace *common.NamespaceQuery, config *rest.Config, crdName string, name string) (CustomResourceObjectDetail, error) {
-	var detail CustomResourceObjectDetail
+func GetCustomResourceObjectDetail(client apiextensionsclientset.Interface, namespace *common.NamespaceQuery, config *rest.Config, crdName string, name string) (*CustomResourceObjectDetail, error) {
+	var detail *CustomResourceObjectDetail
 
 	customResourceDefinition, err := client.ApiextensionsV1beta1().
 		CustomResourceDefinitions().
 		Get(crdName, metav1.GetOptions{})
-	if err != nil {
-		return detail, err
+	nonCriticalErrors, criticalError := errors.HandleError(err)
+	if criticalError != nil {
+		return nil, criticalError
 	}
 
-	restClient, err := newRESTClient(config, getCustomResourceDefinitionGroupVersion(customResourceDefinition))
-	if err != nil {
-		return detail, err
+	restClient, err := NewRESTClient(config, customResourceDefinition)
+	nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
+	if criticalError != nil {
+		return nil, criticalError
 	}
 
-	err = restClient.Get().
+	raw, err := restClient.Get().
 		Namespace(namespace.ToRequestParam()).
-		Resource(customResourceDefinition.Spec.Names.Plural).
-		Name(name).Do().Into(&detail)
-	if err != nil {
-		return detail, err
+		Resource(customResourceDefinition.Status.AcceptedNames.Plural).
+		Name(name).Do().Raw()
+	nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
+	if criticalError != nil {
+		return nil, criticalError
+	}
+
+	err = json.Unmarshal(raw, &detail)
+	nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
+	if criticalError != nil {
+		return nil, criticalError
 	}
+	detail.Errors = nonCriticalErrors
 
+	replaceCRDObjectKind(&detail.CustomResourceObject, customResourceDefinition.Name)
 	return detail, nil
 }
+
+// replaceCRDObjectKind sets the object kind to the full name of the CRD.
+// E.g. changes "Foo" to "foos.samplecontroller.k8s.io"
+func replaceCRDObjectKind(object *CustomResourceObject, kind string) {
+	object.TypeMeta.Kind = kind
+}
diff --git a/src/app/frontend/chrome/nav/template.html b/src/app/frontend/chrome/nav/template.html
index 881075013..26ae9d2cf 100644
--- a/src/app/frontend/chrome/nav/template.html
+++ b/src/app/frontend/chrome/nav/template.html
@@ -124,6 +124,15 @@ limitations under the License.
 
     <mat-divider></mat-divider>
 
+    <div class="kd-nav-group">
+      <kd-nav-item class="kd-nav-group-item"
+                   state="/crd"
+                   i18n>Custom Resource Definitions
+      </kd-nav-item>
+    </div>
+
+    <mat-divider></mat-divider>
+
     <div class="kd-nav-group">
       <kd-nav-item class="kd-nav-group-item"
                    state="/settings"
diff --git a/src/app/frontend/chrome/routing.ts b/src/app/frontend/chrome/routing.ts
index c605ff4e9..2bb8bfe7e 100644
--- a/src/app/frontend/chrome/routing.ts
+++ b/src/app/frontend/chrome/routing.ts
@@ -131,6 +131,9 @@ const routes: Routes = [
         loadChildren: 'resource/config/secret/module#SecretModule',
       },
 
+      // Custom resource definitions
+      {path: 'crd', loadChildren: 'crd/module#CrdModule'},
+
       // Others
       {
         path: 'settings',
diff --git a/src/app/frontend/common/components/breadcrumbs/component.ts b/src/app/frontend/common/components/breadcrumbs/component.ts
index 8020a279c..f026fa825 100644
--- a/src/app/frontend/common/components/breadcrumbs/component.ts
+++ b/src/app/frontend/common/components/breadcrumbs/component.ts
@@ -50,7 +50,9 @@ export class BreadcrumbsComponent implements OnInit {
     const currentRoute = this._getCurrentRoute();
     const url = this._router.url.includes('?') ? this._router.url.split('?')[0] : '';
     let urlArray = url.split('/');
-    let routeParamsCount = currentRoute.routeConfig.path.split('/').length;
+    let routeParamsCount = currentRoute.routeConfig.data.routeParamsCount
+      ? +currentRoute.routeConfig.data.routeParamsCount
+      : currentRoute.routeConfig.path.split('/').length;
 
     this.breadcrumbs = [
       {
diff --git a/src/app/frontend/common/components/condition/component.ts b/src/app/frontend/common/components/condition/component.ts
index 340e00d4d..44e822b26 100644
--- a/src/app/frontend/common/components/condition/component.ts
+++ b/src/app/frontend/common/components/condition/component.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {Component, Input} from '@angular/core';
+import {Component, Input, OnInit} from '@angular/core';
 import {MatTableDataSource} from '@angular/material';
 import {Condition} from 'typings/backendapi';
 
@@ -20,12 +20,31 @@ import {Condition} from 'typings/backendapi';
   selector: 'kd-condition-list',
   templateUrl: './template.html',
 })
-export class ConditionListComponent {
+export class ConditionListComponent implements OnInit {
   @Input() initialized: boolean;
   @Input() conditions: Condition[];
+  @Input() showLastProbeTime = true;
+  private columns = {
+    0: 'type',
+    1: 'status',
+    2: 'lastProbeTime',
+    3: 'lastTransitionTime',
+    4: 'reason',
+    5: 'message',
+  };
 
-  getConditionsColumns(): string[] {
-    return ['type', 'status', 'lastProbeTime', 'lastTransitionTime', 'reason', 'message'];
+  ngOnInit(): void {
+    if (!this.showLastProbeTime) {
+      delete this.columns[2];
+    }
+  }
+
+  getConditionsColumns(): {[key: number]: string} {
+    return this.columns;
+  }
+
+  getColumnKeys(): string[] {
+    return Object.values(this.columns);
   }
 
   getDataSource(): MatTableDataSource<Condition> {
diff --git a/src/app/frontend/common/components/condition/template.html b/src/app/frontend/common/components/condition/template.html
index 1ff73cf6d..8f120f06c 100644
--- a/src/app/frontend/common/components/condition/template.html
+++ b/src/app/frontend/common/components/condition/template.html
@@ -79,8 +79,8 @@ limitations under the License.
           <ng-container *ngIf="!condition.message">-</ng-container>
         </mat-cell>
       </ng-container>
-      <mat-header-row *matHeaderRowDef="getConditionsColumns()"></mat-header-row>
-      <mat-row *matRowDef="let row; columns: getConditionsColumns();"></mat-row>
+      <mat-header-row *matHeaderRowDef="getColumnKeys()"></mat-header-row>
+      <mat-row *matRowDef="let row; columns: getColumnKeys();"></mat-row>
     </mat-table>
   </div>
 </kd-card>
diff --git a/src/app/frontend/common/components/module.ts b/src/app/frontend/common/components/module.ts
index 31f327582..be2993868 100644
--- a/src/app/frontend/common/components/module.ts
+++ b/src/app/frontend/common/components/module.ts
@@ -62,6 +62,9 @@ import {ProxyComponent} from './proxy/component';
 import {ResourceQuotaListComponent} from './quotas/component';
 import {ClusterRoleListComponent} from './resourcelist/clusterrole/component';
 import {ConfigMapListComponent} from './resourcelist/configmap/component';
+import {CRDListComponent} from './resourcelist/crd/component';
+import {CRDObjectListComponent} from './resourcelist/crdobject/component';
+import {CRDVersionListComponent} from './resourcelist/crdversion/component';
 import {CronJobListComponent} from './resourcelist/cronjob/component';
 import {DaemonSetListComponent} from './resourcelist/daemonset/component';
 import {DeploymentListComponent} from './resourcelist/deployment/component';
@@ -110,6 +113,9 @@ const components = [
   ContainerCardComponent,
   ConditionListComponent,
   CreatorCardComponent,
+  CRDListComponent,
+  CRDObjectListComponent,
+  CRDVersionListComponent,
   GraphComponent,
   GraphCardComponent,
 
diff --git a/src/app/frontend/common/components/resourcelist/crd/component.ts b/src/app/frontend/common/components/resourcelist/crd/component.ts
new file mode 100644
index 000000000..1e8307f49
--- /dev/null
+++ b/src/app/frontend/common/components/resourcelist/crd/component.ts
@@ -0,0 +1,78 @@
+// 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 {Component, Input} from '@angular/core';
+import {CRD, CRDList} from '@api/backendapi';
+import {Observable} from 'rxjs';
+
+import {ResourceListWithStatuses} from '../../../resources/list';
+import {NotificationsService} from '../../../services/global/notifications';
+import {EndpointManager, Resource} from '../../../services/resource/endpoint';
+import {ResourceService} from '../../../services/resource/resource';
+import {MenuComponent} from '../../list/column/menu/component';
+import {ListGroupIdentifier, ListIdentifier} from '../groupids';
+
+@Component({
+  selector: 'kd-crd-list',
+  templateUrl: './template.html',
+})
+export class CRDListComponent extends ResourceListWithStatuses<CRDList, CRD> {
+  @Input() endpoint = EndpointManager.resource(Resource.crd).list();
+
+  constructor(
+    private readonly crd_: ResourceService<CRDList>,
+    notifications: NotificationsService,
+  ) {
+    super('crd', notifications);
+    this.id = ListIdentifier.crd;
+    this.groupId = ListGroupIdentifier.none;
+
+    // Register action columns.
+    this.registerActionColumn<MenuComponent>('menu', MenuComponent);
+
+    // Register status icon handlers
+    this.registerBinding(this.icon.checkCircle, 'kd-success', this.isInSuccessState);
+    this.registerBinding(this.icon.help, 'kd-muted', this.isInUnknownState);
+    this.registerBinding(this.icon.error, 'kd-error', this.isInErrorState);
+  }
+
+  isNamespaced(crd: CRD): string {
+    return crd.scope === 'Namespaced' ? 'True' : 'False';
+  }
+
+  getResourceObservable(params?: HttpParams): Observable<CRDList> {
+    return this.crd_.get(this.endpoint, undefined, params);
+  }
+
+  map(crdList: CRDList): CRD[] {
+    return crdList.items;
+  }
+
+  isInErrorState(resource: CRD): boolean {
+    return resource.established === 'False';
+  }
+
+  isInUnknownState(resource: CRD): boolean {
+    return resource.established === 'Unknown';
+  }
+
+  isInSuccessState(resource: CRD): boolean {
+    return resource.established === 'True';
+  }
+
+  getDisplayColumns(): string[] {
+    return ['statusicon', 'name', 'group', 'fullName', 'namespaced', 'age'];
+  }
+}
diff --git a/src/app/frontend/common/components/resourcelist/crd/template.html b/src/app/frontend/common/components/resourcelist/crd/template.html
new file mode 100644
index 000000000..fcb10204a
--- /dev/null
+++ b/src/app/frontend/common/components/resourcelist/crd/template.html
@@ -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.
+-->
+
+<kd-card role="table"
+         [hidden]="isHidden()">
+  <div title
+       fxLayout="row"
+       i18n>Custom Resource Definitions</div>
+  <div description><span class="kd-muted-light"
+          i18n>Items:&nbsp;</span>{{totalItems}}</div>
+  <div actions>
+    <kd-card-list-filter></kd-card-list-filter>
+  </div>
+
+  <div content
+       [hidden]="showZeroState()">
+    <div kdLoadingSpinner
+         [isLoading]="isLoading"></div>
+
+    <mat-table [dataSource]="getData()"
+               matSort
+               [matSortActive]="getColumns()[4]"
+               matSortDisableClear
+               matSortDirection="asc">
+      <ng-container [matColumnDef]="getColumns()[0]">
+        <mat-header-cell *matHeaderCellDef></mat-header-cell>
+        <mat-cell *matCellDef="let crd">
+          <mat-icon [ngClass]="getStatus(crd).iconClass">
+            {{getStatus(crd).iconName}}
+          </mat-icon>
+        </mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getColumns()[1]">
+        <mat-header-cell *matHeaderCellDef
+                         mat-sort-header
+                         disableClear="true"
+                         i18n>Name</mat-header-cell>
+        <mat-cell *matCellDef="let crd">
+          <a [routerLink]="getDetailsHref(crd.objectMeta.name)"
+             queryParamsHandling="preserve">{{crd.names.kind}}</a>
+        </mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getColumns()[2]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Group</mat-header-cell>
+        <mat-cell *matCellDef="let crd">{{crd.group}}</mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getColumns()[3]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Full Name</mat-header-cell>
+        <mat-cell *matCellDef="let crd">{{crd.objectMeta.name}}</mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getColumns()[4]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Namespaced</mat-header-cell>
+        <mat-cell *matCellDef="let crd">{{isNamespaced(crd)}}</mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getColumns()[5]">
+        <mat-header-cell *matHeaderCellDef
+                         mat-sort-header
+                         disableClear="true"
+                         i18n>Age</mat-header-cell>
+        <mat-cell *matCellDef="let crd">
+          <kd-date [date]="crd.objectMeta.creationTimestamp"
+                   relative></kd-date>
+        </mat-cell>
+      </ng-container>
+
+      <ng-container *ngFor="let col of getActionColumns()"
+                    [matColumnDef]="col.name">
+        <mat-header-cell *matHeaderCellDef></mat-header-cell>
+        <mat-cell *matCellDef="let crd">
+          <kd-dynamic-cell [component]="col.component"
+                           [resource]="crd"></kd-dynamic-cell>
+        </mat-cell>
+      </ng-container>
+
+      <mat-header-row *matHeaderRowDef="getColumns()"></mat-header-row>
+      <mat-row *matRowDef="let row; columns: getColumns();"></mat-row>
+    </mat-table>
+
+    <mat-paginator [length]="totalItems"
+                   [pageSize]="itemsPerPage"
+                   [hidePageSize]="true"
+                   [showFirstLastButtons]="true"></mat-paginator>
+  </div>
+
+  <div content
+       [hidden]="!showZeroState()">
+    <kd-list-zero-state></kd-list-zero-state>
+  </div>
+</kd-card>
diff --git a/src/app/frontend/common/components/resourcelist/crdobject/component.ts b/src/app/frontend/common/components/resourcelist/crdobject/component.ts
new file mode 100644
index 000000000..961827b52
--- /dev/null
+++ b/src/app/frontend/common/components/resourcelist/crdobject/component.ts
@@ -0,0 +1,58 @@
+// 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, Input} from '@angular/core';
+import {HttpParams} from '@angular/common/http';
+import {Observable} from 'rxjs';
+import {CRDObject, CRDObjectList} from '@api/backendapi';
+import {ResourceListBase} from '../../../resources/list';
+import {NamespacedResourceService} from '../../../services/resource/resource';
+import {NotificationsService} from '../../../services/global/notifications';
+import {ActivatedRoute} from '@angular/router';
+import {ListGroupIdentifier, ListIdentifier} from '../groupids';
+import {MenuComponent} from '../../list/column/menu/component';
+
+@Component({
+  selector: 'kd-crd-object-list',
+  templateUrl: './template.html',
+})
+export class CRDObjectListComponent extends ResourceListBase<CRDObjectList, CRDObject> {
+  @Input() endpoint: string;
+  @Input() crdName: string;
+
+  constructor(
+    private readonly crdObject_: NamespacedResourceService<CRDObjectList>,
+    notifications: NotificationsService,
+    private readonly activatedRoute_: ActivatedRoute,
+  ) {
+    super(`crd/${activatedRoute_.snapshot.params.crdName}`, notifications);
+    this.id = ListIdentifier.crdObject;
+    this.groupId = ListGroupIdentifier.none;
+
+    // Register action columns.
+    this.registerActionColumn<MenuComponent>('menu', MenuComponent);
+  }
+
+  getResourceObservable(params?: HttpParams): Observable<CRDObjectList> {
+    return this.crdObject_.get(this.endpoint, undefined, undefined, params);
+  }
+
+  map(crdObjectList: CRDObjectList): CRDObject[] {
+    return crdObjectList.items;
+  }
+
+  getDisplayColumns(): string[] {
+    return ['name', 'namespace', 'age'];
+  }
+}
diff --git a/src/app/frontend/common/components/resourcelist/crdobject/template.html b/src/app/frontend/common/components/resourcelist/crdobject/template.html
new file mode 100644
index 000000000..423eddcff
--- /dev/null
+++ b/src/app/frontend/common/components/resourcelist/crdobject/template.html
@@ -0,0 +1,88 @@
+<!--
+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.
+-->
+
+<kd-card role="table"
+         [hidden]="isHidden()">
+  <div title
+       fxLayout="row"
+       i18n>Objects</div>
+  <div description>
+    <span class="kd-muted-light"
+          i18n>Items:&nbsp;</span>{{totalItems}}</div>
+  <div actions>
+    <kd-card-list-filter></kd-card-list-filter>
+  </div>
+
+  <div content
+       [hidden]="showZeroState()">
+    <div kdLoadingSpinner
+         [isLoading]="isLoading"></div>
+
+    <mat-table [dataSource]="getData()"
+               matSort
+               matSortActive="age"
+               matSortDisableClear
+               matSortDirection="asc">
+      <ng-container [matColumnDef]="getColumns()[0]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Name</mat-header-cell>
+        <mat-cell *matCellDef="let object">
+          <a [routerLink]="getDetailsHref(object.objectMeta.name, object.objectMeta.namespace)"
+             queryParamsHandling="preserve">
+            {{object.objectMeta.name}}
+          </a>
+        </mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getColumns()[1]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Namespace</mat-header-cell>
+        <mat-cell *matCellDef="let object">{{object.objectMeta.namespace}}</mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getColumns()[2]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Age</mat-header-cell>
+        <mat-cell *matCellDef="let object">
+          <kd-date [date]="object.objectMeta.creationTimestamp"
+                   relative></kd-date>
+        </mat-cell>
+      </ng-container>
+
+      <ng-container *ngFor="let col of getActionColumns()"
+                    [matColumnDef]="col.name">
+        <mat-header-cell *matHeaderCellDef></mat-header-cell>
+        <mat-cell *matCellDef="let crd">
+          <kd-dynamic-cell [component]="col.component"
+                           [resource]="crd"></kd-dynamic-cell>
+        </mat-cell>
+      </ng-container>
+
+      <mat-header-row *matHeaderRowDef="getColumns()"></mat-header-row>
+      <mat-row *matRowDef="let row; columns: getColumns();"></mat-row>
+    </mat-table>
+
+    <mat-paginator [length]="totalItems"
+                   [pageSize]="itemsPerPage"
+                   [hidePageSize]="true"
+                   [showFirstLastButtons]="true"></mat-paginator>
+  </div>
+
+  <div content
+       [hidden]="!showZeroState()">
+    <kd-list-zero-state></kd-list-zero-state>
+  </div>
+</kd-card>
diff --git a/src/app/frontend/common/components/resourcelist/crdversion/component.ts b/src/app/frontend/common/components/resourcelist/crdversion/component.ts
new file mode 100644
index 000000000..e0c23dbb2
--- /dev/null
+++ b/src/app/frontend/common/components/resourcelist/crdversion/component.ts
@@ -0,0 +1,37 @@
+// 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, Input} from '@angular/core';
+import {CRDVersion} from '@api/backendapi';
+import {MatTableDataSource} from '@angular/material';
+
+@Component({
+  selector: 'kd-crd-versions-list',
+  templateUrl: './template.html',
+})
+export class CRDVersionListComponent {
+  @Input() versions: CRDVersion[];
+  @Input() initialized: boolean;
+
+  getDisplayColumns(): string[] {
+    return ['name', 'served', 'storage'];
+  }
+
+  getDataSource(): MatTableDataSource<CRDVersion> {
+    const tableData = new MatTableDataSource<CRDVersion>();
+    tableData.data = this.versions;
+
+    return tableData;
+  }
+}
diff --git a/src/app/frontend/common/components/resourcelist/crdversion/template.html b/src/app/frontend/common/components/resourcelist/crdversion/template.html
new file mode 100644
index 000000000..1110fd5db
--- /dev/null
+++ b/src/app/frontend/common/components/resourcelist/crdversion/template.html
@@ -0,0 +1,56 @@
+<!--
+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.
+-->
+
+<kd-card [initialized]="initialized"
+         role="table">
+  <div title
+       i18n>Versions</div>
+
+  <div description>
+    <div class="kd-inline-property"
+         *ngIf="versions?.length">
+      <span class="kd-muted-light"
+            i18n>Items:&nbsp;</span>
+      <span>{{versions.length}}</span>
+    </div>
+  </div>
+
+  <div content>
+    <mat-table [dataSource]="getDataSource()"
+               class="kd-table-no-footer">
+      <ng-container [matColumnDef]="getDisplayColumns()[0]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Name</mat-header-cell>
+        <mat-cell *matCellDef="let version">{{version.name}}</mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getDisplayColumns()[1]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Served</mat-header-cell>
+        <mat-cell *matCellDef="let version">{{version.served ? "True" : "False"}}</mat-cell>
+      </ng-container>
+
+      <ng-container [matColumnDef]="getDisplayColumns()[2]">
+        <mat-header-cell *matHeaderCellDef
+                         i18n>Storage</mat-header-cell>
+        <mat-cell *matCellDef="let version">{{version.storage ? "True" : "False"}}</mat-cell>
+      </ng-container>
+
+      <mat-header-row *matHeaderRowDef="getDisplayColumns()"></mat-header-row>
+      <mat-row *matRowDef="let row; columns: getDisplayColumns();"></mat-row>
+    </mat-table>
+  </div>
+</kd-card>
diff --git a/src/app/frontend/common/components/resourcelist/groupids.ts b/src/app/frontend/common/components/resourcelist/groupids.ts
index 03a9a3477..ac7662a77 100644
--- a/src/app/frontend/common/components/resourcelist/groupids.ts
+++ b/src/app/frontend/common/components/resourcelist/groupids.ts
@@ -19,6 +19,8 @@ export enum ListIdentifier {
   persistentVolume = 'persistentVolumeList',
   storageClass = 'storageClassList',
   cronJob = 'cronJobList',
+  crd = 'crdList',
+  crdObject = 'crdObjectList',
   job = 'jobList',
   deployment = 'deploymentList',
   daemonSet = 'daemonSetList',
diff --git a/src/app/frontend/common/services/resource/endpoint.ts b/src/app/frontend/common/services/resource/endpoint.ts
index 6af01d626..aee389621 100644
--- a/src/app/frontend/common/services/resource/endpoint.ts
+++ b/src/app/frontend/common/services/resource/endpoint.ts
@@ -17,6 +17,8 @@ const baseHref = 'api/v1';
 export enum Resource {
   job = 'job',
   cronJob = 'cronjob',
+  crd = 'crd',
+  crdObject = 'object',
   daemonSet = 'daemonset',
   deployment = 'deployment',
   pod = 'pod',
@@ -56,7 +58,7 @@ class ResourceEndpoint {
 
   child(resourceName: string, relatedResource: Resource, resourceNamespace?: string): string {
     if (!resourceNamespace) {
-      resourceNamespace = '/:namespace';
+      resourceNamespace = ':namespace';
     }
 
     return `${baseHref}/${this.resource_}${
diff --git a/src/app/frontend/common/services/resource/resource.ts b/src/app/frontend/common/services/resource/resource.ts
index 777081ebc..97ebc2b31 100644
--- a/src/app/frontend/common/services/resource/resource.ts
+++ b/src/app/frontend/common/services/resource/resource.ts
@@ -63,7 +63,7 @@ export class NamespacedResourceService<T> extends ResourceBase<T> {
 
   private getNamespace_(): string {
     const currentNamespace = this.namespace_.current();
-    return this.namespace_.isMultiNamespace(currentNamespace) ? '' : currentNamespace;
+    return this.namespace_.isMultiNamespace(currentNamespace) ? ' ' : currentNamespace;
   }
 
   get(endpoint: string, name?: string, namespace?: string, params?: HttpParams): Observable<T> {
diff --git a/src/app/frontend/crd/crdobject/component.ts b/src/app/frontend/crd/crdobject/component.ts
new file mode 100644
index 000000000..ad275ab49
--- /dev/null
+++ b/src/app/frontend/crd/crdobject/component.ts
@@ -0,0 +1,105 @@
+// 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, ElementRef, OnDestroy, OnInit, Renderer2, ViewChild} from '@angular/core';
+import {ActivatedRoute} from '@angular/router';
+import {MatButtonToggleGroup} from '@angular/material';
+import {HttpClient} from '@angular/common/http';
+import {dump as toYaml} from 'js-yaml';
+import {Subscription} from 'rxjs';
+import {CRDObjectDetail} from '@api/backendapi';
+import {highlightAuto} from 'highlight.js';
+import {ActionbarService, ResourceMeta} from '../../common/services/global/actionbar';
+import {NamespacedResourceService} from '../../common/services/resource/resource';
+import {EndpointManager, Resource} from '../../common/services/resource/endpoint';
+import {NotificationsService} from '../../common/services/global/notifications';
+import {RawResource} from '../../common/resources/rawresource';
+
+enum Modes {
+  JSON = 'json',
+  YAML = 'yaml',
+}
+
+@Component({selector: 'kd-crd-object-detail', templateUrl: './template.html'})
+export class CRDObjectDetailComponent implements OnInit, OnDestroy {
+  @ViewChild('group', {static: true}) buttonToggleGroup: MatButtonToggleGroup;
+  @ViewChild('code', {static: true}) codeRef: ElementRef;
+
+  private objectSubscription_: Subscription;
+  private readonly endpoint_ = EndpointManager.resource(Resource.crd, true);
+  object: CRDObjectDetail;
+  modes = Modes;
+  isInitialized = false;
+  selectedMode = Modes.YAML;
+  objectRaw: {[s: string]: string} = {};
+
+  constructor(
+    private readonly object_: NamespacedResourceService<CRDObjectDetail>,
+    private readonly actionbar_: ActionbarService,
+    private readonly activatedRoute_: ActivatedRoute,
+    private readonly notifications_: NotificationsService,
+    private readonly http_: HttpClient,
+    private readonly renderer_: Renderer2,
+  ) {}
+
+  ngOnInit(): void {
+    const {crdName, namespace, objectName} = this.activatedRoute_.snapshot.params;
+    this.objectSubscription_ = this.object_
+      .get(this.endpoint_.child(crdName, objectName, namespace))
+      .subscribe((d: CRDObjectDetail) => {
+        this.object = d;
+        this.notifications_.pushErrors(d.errors);
+        this.actionbar_.onInit.emit(new ResourceMeta(d.typeMeta.kind, d.objectMeta, d.typeMeta));
+        this.isInitialized = true;
+
+        // Get raw resource
+        const url = RawResource.getUrl(this.object.typeMeta, this.object.objectMeta);
+        this.http_
+          .get(url)
+          .toPromise()
+          .then(response => {
+            this.objectRaw = {
+              json: highlightAuto(`${this.toRawJSON(response)}`, ['json']).value,
+              yaml: highlightAuto(`${toYaml(response)}`, ['yaml']).value,
+            };
+            this.updateText();
+          });
+      });
+
+    this.buttonToggleGroup.valueChange.subscribe((selectedMode: Modes) => {
+      this.selectedMode = selectedMode;
+
+      if (Object.keys(this.objectRaw).length > 0) {
+        this.updateText();
+      }
+    });
+  }
+
+  ngOnDestroy(): void {
+    this.objectSubscription_.unsubscribe();
+    this.actionbar_.onDetailsLeave.emit();
+  }
+
+  private updateText(): void {
+    this.renderer_.setProperty(
+      this.codeRef.nativeElement,
+      'innerHTML',
+      this.objectRaw[this.selectedMode],
+    );
+  }
+
+  private toRawJSON(object: {}): string {
+    return JSON.stringify(object, null, 2);
+  }
+}
diff --git a/src/app/frontend/crd/crdobject/template.html b/src/app/frontend/crd/crdobject/template.html
new file mode 100644
index 000000000..ea6fc9cac
--- /dev/null
+++ b/src/app/frontend/crd/crdobject/template.html
@@ -0,0 +1,34 @@
+<!--
+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.
+-->
+
+<kd-object-meta [initialized]="isInitialized"
+                [objectMeta]="object?.objectMeta"></kd-object-meta>
+
+<kd-card>
+  <div title
+       i18n>Data</div>
+
+  <div content>
+    <mat-button-toggle-group #group="matButtonToggleGroup">
+      <mat-button-toggle [value]="modes.YAML"
+                         [checked]="true">YAML</mat-button-toggle>
+      <mat-button-toggle [value]="modes.JSON">JSON</mat-button-toggle>
+    </mat-button-toggle-group>
+
+    <div class="kd-code-block"
+         #code></div>
+  </div>
+</kd-card>
diff --git a/src/app/frontend/crd/detail/component.ts b/src/app/frontend/crd/detail/component.ts
new file mode 100644
index 000000000..c0d832dbc
--- /dev/null
+++ b/src/app/frontend/crd/detail/component.ts
@@ -0,0 +1,63 @@
+// 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, OnDestroy, OnInit} from '@angular/core';
+import {ActivatedRoute} from '@angular/router';
+import {CRDDetail} from '@api/backendapi';
+import {Subscription} from 'rxjs';
+
+import {ActionbarService, ResourceMeta} from '../../common/services/global/actionbar';
+import {NotificationsService} from '../../common/services/global/notifications';
+import {ResourceService} from '../../common/services/resource/resource';
+import {EndpointManager, Resource} from '../../common/services/resource/endpoint';
+
+@Component({selector: 'kd-crd-detail', templateUrl: './template.html'})
+export class CRDDetailComponent implements OnInit, OnDestroy {
+  private crdSubscription_: Subscription;
+  private readonly endpoint_ = EndpointManager.resource(Resource.crd);
+  crd: CRDDetail;
+  crdObjectEndpoint: string;
+  isInitialized = false;
+
+  constructor(
+    private readonly crd_: ResourceService<CRDDetail>,
+    private readonly actionbar_: ActionbarService,
+    private readonly activatedRoute_: ActivatedRoute,
+    private readonly notifications_: NotificationsService,
+  ) {}
+
+  ngOnInit(): void {
+    const {crdName} = this.activatedRoute_.snapshot.params;
+    this.crdObjectEndpoint = EndpointManager.resource(Resource.crd, true).child(
+      crdName,
+      Resource.crdObject,
+    );
+
+    this.crdSubscription_ = this.crd_
+      .get(this.endpoint_.detail(), crdName)
+      .subscribe((d: CRDDetail) => {
+        this.crd = d;
+        this.notifications_.pushErrors(d.errors);
+        this.actionbar_.onInit.emit(
+          new ResourceMeta('Custom Resource Definition', d.objectMeta, d.typeMeta),
+        );
+        this.isInitialized = true;
+      });
+  }
+
+  ngOnDestroy(): void {
+    this.crdSubscription_.unsubscribe();
+    this.actionbar_.onDetailsLeave.emit();
+  }
+}
diff --git a/src/app/frontend/crd/detail/template.html b/src/app/frontend/crd/detail/template.html
new file mode 100644
index 000000000..3530c2654
--- /dev/null
+++ b/src/app/frontend/crd/detail/template.html
@@ -0,0 +1,91 @@
+<!--
+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.
+-->
+
+<kd-object-meta [initialized]="isInitialized"
+                [objectMeta]="crd?.objectMeta"></kd-object-meta>
+
+<kd-card [initialized]="isInitialized">
+  <div title
+       i18n>Resource Information</div>
+  <div content
+       *ngIf="isInitialized"
+       fxLayout="row wrap">
+    <kd-property *ngIf="crd?.version">
+      <div key
+           i18n>Version</div>
+      <div value>{{crd?.version}}</div>
+    </kd-property>
+    <kd-property>
+      <div key
+           i18n>Scope</div>
+      <div value>{{crd?.scope}}</div>
+    </kd-property>
+    <kd-property>
+      <div key
+           i18n>Group</div>
+      <div value>{{crd?.group}}</div>
+    </kd-property>
+  </div>
+</kd-card>
+
+<kd-card [initialized]="isInitialized">
+  <div title
+       i18n>Accepted Names</div>
+  <div content
+       *ngIf="isInitialized"
+       fxLayout="row wrap">
+    <kd-property>
+      <div key
+           i18n>Plural</div>
+      <div value>{{crd?.names.plural}}</div>
+    </kd-property>
+    <kd-property *ngIf="crd?.names.singular">
+      <div key
+           i18n>Singular</div>
+      <div value>{{crd?.names.singular}}</div>
+    </kd-property>
+    <kd-property>
+      <div key
+           i18n>Kind</div>
+      <div value>{{crd?.names.kind}}</div>
+    </kd-property>
+    <kd-property>
+      <div key
+           i18n>List Kind</div>
+      <div value>{{crd?.names.listKind}}</div>
+    </kd-property>
+    <kd-property *ngIf="crd?.names.shortNames">
+      <div key
+           i18n>Short Names</div>
+      <div value>{{crd?.names.shortNames.join(", ")}}</div>
+    </kd-property>
+    <kd-property *ngIf="crd?.names.categories">
+      <div key
+           i18n>Categories</div>
+      <div value>{{crd?.names.categories.join(", ")}}</div>
+    </kd-property>
+  </div>
+</kd-card>
+
+<kd-crd-object-list [endpoint]="crdObjectEndpoint"></kd-crd-object-list>
+
+<kd-crd-versions-list *ngIf="crd?.versions"
+                      [versions]="crd?.versions"
+                      [initialized]="isInitialized"></kd-crd-versions-list>
+
+<kd-condition-list [conditions]="crd?.conditions"
+                   [showLastProbeTime]="false"
+                   [initialized]="isInitialized"></kd-condition-list>
diff --git a/src/app/frontend/crd/list/component.ts b/src/app/frontend/crd/list/component.ts
new file mode 100644
index 000000000..5f4f5b256
--- /dev/null
+++ b/src/app/frontend/crd/list/component.ts
@@ -0,0 +1,18 @@
+// 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-crd-list-state', template: '<kd-crd-list></kd-crd-list>'})
+export class CRDListComponent {}
diff --git a/src/app/frontend/crd/module.ts b/src/app/frontend/crd/module.ts
new file mode 100644
index 000000000..aee1d3855
--- /dev/null
+++ b/src/app/frontend/crd/module.ts
@@ -0,0 +1,29 @@
+// 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 {CRDRoutingModule} from './routing';
+import {CRDDetailComponent} from './detail/component';
+import {CRDListComponent} from './list/component';
+import {CRDObjectDetailComponent} from './crdobject/component';
+
+@NgModule({
+  imports: [SharedModule, ComponentsModule, CRDRoutingModule],
+  declarations: [CRDListComponent, CRDDetailComponent, CRDObjectDetailComponent],
+})
+export class CrdModule {}
diff --git a/src/app/frontend/crd/routing.ts b/src/app/frontend/crd/routing.ts
new file mode 100644
index 000000000..e23d2b151
--- /dev/null
+++ b/src/app/frontend/crd/routing.ts
@@ -0,0 +1,51 @@
+// 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 {CRDDetailComponent} from './detail/component';
+import {CRDListComponent} from './list/component';
+import {DEFAULT_ACTIONBAR} from '../common/components/actionbars/routing';
+import {CRDObjectDetailComponent} from './crdobject/component';
+
+const CRD_LIST_ROUTE: Route = {
+  path: '',
+  component: CRDListComponent,
+  data: {breadcrumb: 'Custom Resource Definitions'},
+};
+
+const CRD_DETAIL_ROUTE: Route = {
+  path: ':crdName',
+  component: CRDDetailComponent,
+  data: {breadcrumb: '{{ crdName }}', parent: CRD_LIST_ROUTE},
+};
+
+const CRD_OBJECT_DETAIL_ROUTE: Route = {
+  path: ':crdName/:namespace/:objectName',
+  component: CRDObjectDetailComponent,
+  data: {breadcrumb: '{{ objectName }}', routeParamsCount: 2, parent: CRD_DETAIL_ROUTE},
+};
+
+@NgModule({
+  imports: [
+    RouterModule.forChild([
+      CRD_LIST_ROUTE,
+      CRD_DETAIL_ROUTE,
+      CRD_OBJECT_DETAIL_ROUTE,
+      DEFAULT_ACTIONBAR,
+    ]),
+  ],
+})
+export class CRDRoutingModule {}
diff --git a/src/app/frontend/typings/backendapi.d.ts b/src/app/frontend/typings/backendapi.d.ts
index 410439c37..7d8131ffc 100644
--- a/src/app/frontend/typings/backendapi.d.ts
+++ b/src/app/frontend/typings/backendapi.d.ts
@@ -78,6 +78,15 @@ export interface CronJobList extends ResourceList {
   status: Status;
 }
 
+export interface CRDList extends ResourceList {
+  items: CRD[];
+}
+
+export interface CRDObjectList extends ResourceList {
+  typeMeta: TypeMeta;
+  items: CRDObject[];
+}
+
 export interface DaemonSetList extends ResourceList {
   daemonSets: DaemonSet[];
   status: Status;
@@ -133,7 +142,7 @@ export interface PodList extends ResourceList {
   pods: Pod[];
   status: Status;
   podInfo?: PodInfo;
-  cumulativeMetrics: Metric[]|null;
+  cumulativeMetrics: Metric[] | null;
 }
 
 export interface ReplicaSetList extends ResourceList {
@@ -185,6 +194,15 @@ export interface CronJob extends Resource {
   lastSchedule: string;
 }
 
+export interface CRD extends Resource {
+  group: string;
+  scope: string;
+  nameKind: string;
+  established: string;
+}
+
+export interface CRDObject extends Resource {}
+
 export interface DaemonSet extends Resource {
   podInfo: PodInfo;
   containerImages: string[];
@@ -433,6 +451,18 @@ export interface ConfigMapDetail extends ResourceDetail {
   data: StringMap;
 }
 
+export interface CRDDetail extends ResourceDetail {
+  version?: string;
+  group: string;
+  scope: string;
+  names: CRDNames;
+  versions: CRDVersion[];
+  objects: CRDObjectList;
+  conditions: Condition[];
+}
+
+export interface CRDObjectDetail extends ResourceDetail {}
+
 export interface JobDetail extends ResourceDetail {
   podInfo: PodInfo;
   podList: PodList;
@@ -706,6 +736,21 @@ export interface Container {
   args: string[];
 }
 
+export interface CRDNames {
+  plural: string;
+  singular?: string;
+  shortNames?: string[];
+  kind: string;
+  listKind?: string;
+  categories?: string[];
+}
+
+export interface CRDVersion {
+  name: string;
+  served: boolean;
+  storage: boolean;
+}
+
 export interface PodMetrics {
   cpuUsage: number;
   memoryUsage: number;
@@ -778,9 +823,9 @@ export interface NodeTaint {
 }
 
 export interface PortMapping {
-  port: number|null;
+  port: number | null;
   protocol: string;
-  targetPort: number|null;
+  targetPort: number | null;
 }
 
 export interface EnvironmentVariable {
@@ -880,8 +925,8 @@ export interface FlockerVolumeSource {
 }
 
 export interface RollingUpdateStrategy {
-  maxSurge: (number|string);
-  maxUnavailable: (number|string);
+  maxSurge: number | string;
+  maxUnavailable: number | string;
 }
 
 export interface DeploymentInfo {


Test patch:
diff --git a/src/app/backend/auth/manager_test.go b/src/app/backend/auth/manager_test.go
index 484c656e3..f5d9a30ab 100644
--- a/src/app/backend/auth/manager_test.go
+++ b/src/app/backend/auth/manager_test.go
@@ -82,9 +82,9 @@ func (self *fakeClientManager) HasAccess(authInfo api.AuthInfo) error {
 	return self.HasAccessError
 }
 
-func (self *fakeClientManager) VerberClient(req *restful.Request) (clientapi.ResourceVerber, error) {
+func (self *fakeClientManager) VerberClient(req *restful.Request, config *rest.Config) (clientapi.ResourceVerber, error) {
 	return client.NewResourceVerber(nil, nil, nil, nil, nil,
-		nil, nil, nil, nil), nil
+		nil, nil, nil, nil, nil), nil
 }
 
 func (self *fakeClientManager) CanI(req *restful.Request, ssar *v1.SelfSubjectAccessReview) bool {
diff --git a/src/app/backend/client/manager_test.go b/src/app/backend/client/manager_test.go
index 1aa12b5da..6ad1b15ac 100644
--- a/src/app/backend/client/manager_test.go
+++ b/src/app/backend/client/manager_test.go
@@ -22,6 +22,7 @@ import (
 	restful "github.com/emicklei/go-restful"
 	"github.com/kubernetes/dashboard/src/app/backend/args"
 	"github.com/kubernetes/dashboard/src/app/backend/errors"
+	"k8s.io/client-go/rest"
 )
 
 func TestNewClientManager(t *testing.T) {
@@ -284,7 +285,7 @@ func TestClientCmdConfig(t *testing.T) {
 
 func TestVerberClient(t *testing.T) {
 	manager := NewClientManager("", "http://localhost:8080")
-	_, err := manager.VerberClient(&restful.Request{Request: &http.Request{TLS: &tls.ConnectionState{}}})
+	_, err := manager.VerberClient(&restful.Request{Request: &http.Request{TLS: &tls.ConnectionState{}}}, &rest.Config{})
 
 	if err != nil {
 		t.Fatalf("VerberClient(): Expected verber client to be created but got error: %s",
diff --git a/src/app/backend/client/verber_test.go b/src/app/backend/client/verber_test.go
index 25e6c98a5..85b785de6 100644
--- a/src/app/backend/client/verber_test.go
+++ b/src/app/backend/client/verber_test.go
@@ -121,7 +121,10 @@ func TestGetShouldPropagateErrorsAndChoseClient(t *testing.T) {
 }
 
 func TestDeleteShouldThrowErrorOnUnknownResourceKind(t *testing.T) {
-	verber := resourceVerber{client: &FakeRESTClient{}}
+	verber := resourceVerber{
+		client:              &FakeRESTClient{},
+		apiExtensionsClient: &FakeRESTClient{err: errors.NewNotFound("err")},
+	}
 
 	err := verber.Delete("foo", true, "bar", "baz")
 
@@ -131,7 +134,10 @@ func TestDeleteShouldThrowErrorOnUnknownResourceKind(t *testing.T) {
 }
 
 func TestGetShouldThrowErrorOnUnknownResourceKind(t *testing.T) {
-	verber := resourceVerber{client: &FakeRESTClient{}}
+	verber := resourceVerber{
+		client:              &FakeRESTClient{},
+		apiExtensionsClient: &FakeRESTClient{err: errors.NewNotFound("err")},
+	}
 
 	_, err := verber.Get("foo", true, "bar", "baz")
 
@@ -141,7 +147,10 @@ func TestGetShouldThrowErrorOnUnknownResourceKind(t *testing.T) {
 }
 
 func TestPutShouldThrowErrorOnUnknownResourceKind(t *testing.T) {
-	verber := resourceVerber{client: &FakeRESTClient{}}
+	verber := resourceVerber{
+		client:              &FakeRESTClient{},
+		apiExtensionsClient: &FakeRESTClient{err: errors.NewNotFound("err")},
+	}
 
 	err := verber.Put("foo", false, "", "baz", nil)
 
diff --git a/src/app/backend/resource/customresourcedefinition/list_test.go b/src/app/backend/resource/customresourcedefinition/list_test.go
index 30df965ce..ecdfeea5b 100644
--- a/src/app/backend/resource/customresourcedefinition/list_test.go
+++ b/src/app/backend/resource/customresourcedefinition/list_test.go
@@ -51,9 +51,10 @@ func TestGetCustomResourceDefinition(t *testing.T) {
 				ListMeta: api.ListMeta{TotalItems: 1},
 				Items: []CustomResourceDefinition{
 					{
-						ObjectMeta: api.ObjectMeta{Name: "foos.samplecontroller.k8s.io"},
-						TypeMeta:   api.TypeMeta{Kind: api.ResourceKindCustomResourceDefinition},
-						Version:    "v1alpha1",
+						ObjectMeta:  api.ObjectMeta{Name: "foos.samplecontroller.k8s.io"},
+						TypeMeta:    api.TypeMeta{Kind: api.ResourceKindCustomResourceDefinition},
+						Version:     "v1alpha1",
+						Established: apiextensions.ConditionUnknown,
 					},
 				},
 				Errors: []error{},