未验证 提交 a436feb2 编写于 作者: M Marcin Maciaszczyk 提交者: GitHub

Add network policy support (#5307)

* Add backend

* Goimports files

* Add frontend

* Add network policy list to cluster overview

* Fix routings

* Add more info

* Display more data

* Display ingress and egress data

* Add networking client
上级 32b697c2
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -432,6 +432,10 @@
<context context-type="sourcefile">../src/app/frontend/resource/cluster/namespace/detail/template.html</context>
<context context-type="linenumber">22</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/cluster/networkpolicy/detail/template.html</context>
<context context-type="linenumber">22</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/cluster/node/detail/template.html</context>
<context context-type="linenumber">24</context>
......@@ -906,6 +910,10 @@
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/serviceaccount/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/networkpolicy/template.html</context>
<context context-type="linenumber">23</context>
</context-group>
</trans-unit>
<trans-unit id="cff1428d10d59d14e45edec3c735a27b5482db59" datatype="html">
<source>Name</source>
......@@ -1017,6 +1025,10 @@
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/serviceaccount/template.html</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/networkpolicy/template.html</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/workloads/deployment/detail/template.html</context>
<context context-type="linenumber">223</context>
......@@ -1100,6 +1112,10 @@
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/serviceaccount/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/networkpolicy/template.html</context>
<context context-type="linenumber">54</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/workloads/deployment/detail/template.html</context>
<context context-type="linenumber">231</context>
......@@ -1183,6 +1199,10 @@
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/serviceaccount/template.html</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/networkpolicy/template.html</context>
<context context-type="linenumber">60</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/workloads/deployment/detail/template.html</context>
<context context-type="linenumber">254</context>
......@@ -1330,6 +1350,10 @@
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/serviceaccount/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/networkpolicy/template.html</context>
<context context-type="linenumber">70</context>
</context-group>
</trans-unit>
<trans-unit id="13785977f5a140004dd7cdb29f604b685374d1db" datatype="html">
<source>Cluster Roles</source>
......@@ -2318,6 +2342,13 @@
<context context-type="linenumber">26</context>
</context-group>
</trans-unit>
<trans-unit id="a4f6d660f2cc1c8c680a96e39c719b48c8ebe17a" datatype="html">
<source>Network Policies</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/common/components/resourcelist/networkpolicy/template.html</context>
<context context-type="linenumber">21</context>
</context-group>
</trans-unit>
<trans-unit id="67d3a6c50ed8a188e19ea8c541a56f0e35620e5c" datatype="html">
<source>Cluster
</source>
......@@ -2342,12 +2373,20 @@
<context context-type="linenumber">35</context>
</context-group>
</trans-unit>
<trans-unit id="bce7cd9302197070e1782d38622dbb351ad84b69" datatype="html">
<source>Network Policies
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">41</context>
</context-group>
</trans-unit>
<trans-unit id="9151fc3bbb78ca19bf93221148fb6f75c9adec73" datatype="html">
<source>Nodes
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">40</context>
<context context-type="linenumber">46</context>
</context-group>
</trans-unit>
<trans-unit id="53fa14e4e66a4b88531ac5852644edf4c93430c5" datatype="html">
......@@ -2355,7 +2394,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">45</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit id="5deee9cd9fabadb49eb1e3fcae70ff560e41ba27" datatype="html">
......@@ -2363,7 +2402,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">51</context>
<context context-type="linenumber">57</context>
</context-group>
</trans-unit>
<trans-unit id="d49c812d67b965bd0a172844e265f55567c812ad" datatype="html">
......@@ -2371,7 +2410,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">56</context>
<context context-type="linenumber">62</context>
</context-group>
</trans-unit>
<trans-unit id="6d9edf35ea416301631125005b66c9440397176d" datatype="html">
......@@ -2379,7 +2418,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">65</context>
<context context-type="linenumber">71</context>
</context-group>
</trans-unit>
<trans-unit id="787093faa4cfa59c1499dca2cfc6e804f1838ab1" datatype="html">
......@@ -2387,7 +2426,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">70</context>
<context context-type="linenumber">76</context>
</context-group>
</trans-unit>
<trans-unit id="d094e262a8d26c66b5eb9f7dbf501cd711c1306f" datatype="html">
......@@ -2395,7 +2434,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">81</context>
</context-group>
</trans-unit>
<trans-unit id="a862522a568898e032031f6728be4eec8edeb61b" datatype="html">
......@@ -2403,7 +2442,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">80</context>
<context context-type="linenumber">86</context>
</context-group>
</trans-unit>
<trans-unit id="702b6f15c86ce19a17aa8ae644658c852d3c1c08" datatype="html">
......@@ -2411,7 +2450,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">91</context>
</context-group>
</trans-unit>
<trans-unit id="03ff2fadee6736ca0b92abdfe0f19db0d0b2c3f8" datatype="html">
......@@ -2419,7 +2458,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">90</context>
<context context-type="linenumber">96</context>
</context-group>
</trans-unit>
<trans-unit id="6fed5420d42fcfbd09dfb4777c207274dd4f0c0a" datatype="html">
......@@ -2427,7 +2466,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">95</context>
<context context-type="linenumber">101</context>
</context-group>
</trans-unit>
<trans-unit id="5a60417d6a34e8c0655cb0678071c60ca8119aad" datatype="html">
......@@ -2435,7 +2474,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">100</context>
<context context-type="linenumber">106</context>
</context-group>
</trans-unit>
<trans-unit id="1bc563edf644be0e1f682694e543cc8608575562" datatype="html">
......@@ -2443,7 +2482,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">105</context>
<context context-type="linenumber">111</context>
</context-group>
</trans-unit>
<trans-unit id="22c030ecbaceb4c5cf969f5ca360d7e6c6384a6d" datatype="html">
......@@ -2451,7 +2490,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">112</context>
<context context-type="linenumber">118</context>
</context-group>
</trans-unit>
<trans-unit id="7b4d1721251562683d614269b06ebbe3af811a00" datatype="html">
......@@ -2459,7 +2498,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">117</context>
<context context-type="linenumber">123</context>
</context-group>
</trans-unit>
<trans-unit id="5502d7f80d7951086a85d2da478f3f13763939d5" datatype="html">
......@@ -2467,7 +2506,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">122</context>
<context context-type="linenumber">128</context>
</context-group>
</trans-unit>
<trans-unit id="be3dcec436583ff66cce312fd2074779d8851f54" datatype="html">
......@@ -2475,7 +2514,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">129</context>
<context context-type="linenumber">135</context>
</context-group>
</trans-unit>
<trans-unit id="990cffc29a7adb5ec1110b0176c8c12fff756eba" datatype="html">
......@@ -2483,7 +2522,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">134</context>
<context context-type="linenumber">140</context>
</context-group>
</trans-unit>
<trans-unit id="74be5bc42681451056aacf13382e5b29c62bd903" datatype="html">
......@@ -2491,7 +2530,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">139</context>
<context context-type="linenumber">145</context>
</context-group>
</trans-unit>
<trans-unit id="755417c37ab5d459cd2443b3776aaaca7ec87f90" datatype="html">
......@@ -2499,7 +2538,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">144</context>
<context context-type="linenumber">150</context>
</context-group>
</trans-unit>
<trans-unit id="f2f9d18ebacb9e3bcb996d8176609e306864265e" datatype="html">
......@@ -2507,7 +2546,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">153</context>
<context context-type="linenumber">159</context>
</context-group>
</trans-unit>
<trans-unit id="9b39398e6c7a9dfb5cd43f405598934244f8bd17" datatype="html">
......@@ -2515,7 +2554,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">166</context>
<context context-type="linenumber">172</context>
</context-group>
</trans-unit>
<trans-unit id="03511cfe5e28ed3380ab198c13cf62ebde1e89e6" datatype="html">
......@@ -2523,7 +2562,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">177</context>
<context context-type="linenumber">183</context>
</context-group>
</trans-unit>
<trans-unit id="c2fa735eb6b1b2c10171c5acb818f6e0975a9406" datatype="html">
......@@ -2531,7 +2570,7 @@
</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/chrome/nav/template.html</context>
<context context-type="linenumber">183</context>
<context context-type="linenumber">189</context>
</context-group>
</trans-unit>
<trans-unit id="01269ce8051398188d50367ead1831407e77d504" datatype="html">
......@@ -2623,6 +2662,34 @@
<context context-type="linenumber">23</context>
</context-group>
</trans-unit>
<trans-unit id="a21b5b669ab3f36e0f83e9a025c26662fd0616e8" datatype="html">
<source>Pod Selector</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/cluster/networkpolicy/detail/template.html</context>
<context context-type="linenumber">28</context>
</context-group>
</trans-unit>
<trans-unit id="2ebd4e9210644c0f1da612d5c2ef1bbdab9652fd" datatype="html">
<source>Policy Types</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/cluster/networkpolicy/detail/template.html</context>
<context context-type="linenumber">36</context>
</context-group>
</trans-unit>
<trans-unit id="1ebb4252343531346acc2530c2002fc639dd6926" datatype="html">
<source>Ingress Rules</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/cluster/networkpolicy/detail/template.html</context>
<context context-type="linenumber">47</context>
</context-group>
</trans-unit>
<trans-unit id="21a53832d275152e4ad8dfa9371ebbefbf693c87" datatype="html">
<source>Egress Rules</source>
<context-group purpose="location">
<context context-type="sourcefile">../src/app/frontend/resource/cluster/networkpolicy/detail/template.html</context>
<context context-type="linenumber">59</context>
</context-group>
</trans-unit>
<trans-unit id="8a3abe0df530103020a480befe1757e3b1776e7b" datatype="html">
<source>Pod CIDR</source>
<context-group purpose="location">
......
此差异已折叠。
此差异已折叠。
......@@ -143,6 +143,7 @@ const (
ResourceKindRoleBinding = "rolebinding"
ResourceKindPlugin = "plugin"
ResourceKindEndpoint = "endpoint"
ResourceKindNetworkPolicy = "networkpolicy"
)
// Scalable method return whether ResourceKind is scalable.
......@@ -179,6 +180,7 @@ const (
ClientTypeStorageClient = "storageclient"
ClientTypeRbacClient = "rbacclient"
ClientTypeAPIExtensionsClient = "apiextensionsclient"
ClientTypeNetworkingClient = "networkingclient"
ClientTypePluginsClient = "plugin"
)
......@@ -221,6 +223,7 @@ var KindToAPIMapping = map[string]APIMapping{
ResourceKindStatefulSet: {"statefulsets", ClientTypeAppsClient, true},
ResourceKindStorageClass: {"storageclasses", ClientTypeStorageClient, false},
ResourceKindEndpoint: {"endpoints", ClientTypeDefault, true},
ResourceKindNetworkPolicy: {"networkpolicies", ClientTypeNetworkingClient, true},
ResourceKindClusterRole: {"clusterroles", ClientTypeRbacClient, false},
ResourceKindPlugin: {"plugins", ClientTypePluginsClient, true},
}
......
......@@ -87,7 +87,7 @@ func (self *fakeClientManager) HasAccess(authInfo api.AuthInfo) 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
return client.NewResourceVerber(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil), nil
}
func (self *fakeClientManager) CanI(req *restful.Request, ssar *v1.SelfSubjectAccessReview) bool {
......
......@@ -275,6 +275,7 @@ func (self *clientManager) VerberClient(req *restful.Request, config *rest.Confi
k8sClient.AutoscalingV1().RESTClient(),
k8sClient.StorageV1().RESTClient(),
k8sClient.RbacV1().RESTClient(),
k8sClient.NetworkingV1().RESTClient(),
apiextensionsRestClient,
pluginsclient.DashboardV1alpha1().RESTClient(),
config), nil
......
......@@ -41,6 +41,7 @@ type resourceVerber struct {
autoscalingClient RESTClient
storageClient RESTClient
rbacClient RESTClient
networkingClient RESTClient
apiExtensionsClient RESTClient
pluginsClient RESTClient
config *restclient.Config
......@@ -69,6 +70,8 @@ func (verber *resourceVerber) getRESTClientByType(clientType api.ClientType) RES
return verber.storageClient
case api.ClientTypeRbacClient:
return verber.rbacClient
case api.ClientTypeNetworkingClient:
return verber.networkingClient
case api.ClientTypeAPIExtensionsClient:
return verber.apiExtensionsClient
case api.ClientTypePluginsClient:
......@@ -164,9 +167,9 @@ 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, pluginsClient RESTClient, config *restclient.Config) clientapi.ResourceVerber {
func NewResourceVerber(client, extensionsClient, appsClient, batchClient, betaBatchClient, autoscalingClient, storageClient, rbacClient, networkingClient, apiExtensionsClient, pluginsClient RESTClient, config *restclient.Config) clientapi.ResourceVerber {
return &resourceVerber{client, extensionsClient, appsClient,
batchClient, betaBatchClient, autoscalingClient, storageClient, rbacClient, apiExtensionsClient, pluginsClient, config}
batchClient, betaBatchClient, autoscalingClient, storageClient, rbacClient, networkingClient, apiExtensionsClient, pluginsClient, config}
}
// Delete deletes the resource of the given kind in the given namespace with the given name.
......
......@@ -20,6 +20,8 @@ import (
"strconv"
"strings"
"github.com/kubernetes/dashboard/src/app/backend/resource/networkpolicy"
"github.com/kubernetes/dashboard/src/app/backend/handler/parser"
"github.com/kubernetes/dashboard/src/app/backend/resource/customresourcedefinition/types"
......@@ -480,6 +482,19 @@ func CreateHTTPAPIHandler(iManager integration.IntegrationManager, cManager clie
To(apiHandler.handleGetIngressDetail).
Writes(ingress.IngressDetail{}))
apiV1Ws.Route(
apiV1Ws.GET("/networkpolicy").
To(apiHandler.handleGetNetworkPolicyList).
Writes(networkpolicy.NetworkPolicyList{}))
apiV1Ws.Route(
apiV1Ws.GET("/networkpolicy/{namespace}").
To(apiHandler.handleGetNetworkPolicyList).
Writes(networkpolicy.NetworkPolicyList{}))
apiV1Ws.Route(
apiV1Ws.GET("/networkpolicy/{namespace}/{networkpolicy}").
To(apiHandler.handleGetNetworkPolicyDetail).
Writes(networkpolicy.NetworkPolicyDetail{}))
apiV1Ws.Route(
apiV1Ws.GET("/statefulset").
To(apiHandler.handleGetStatefulSetList).
......@@ -1048,6 +1063,40 @@ func (apiHandler *APIHandler) handleGetServicePods(request *restful.Request, res
response.WriteHeaderAndEntity(http.StatusOK, result)
}
func (apiHandler *APIHandler) handleGetNetworkPolicyList(request *restful.Request, response *restful.Response) {
k8sClient, err := apiHandler.cManager.Client(request)
if err != nil {
errors.HandleInternalError(response, err)
return
}
namespace := parseNamespacePathParameter(request)
dataSelect := parser.ParseDataSelectPathParameter(request)
result, err := networkpolicy.GetNetworkPolicyList(k8sClient, namespace, dataSelect)
if err != nil {
errors.HandleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusOK, result)
}
func (apiHandler *APIHandler) handleGetNetworkPolicyDetail(request *restful.Request, response *restful.Response) {
k8sClient, err := apiHandler.cManager.Client(request)
if err != nil {
errors.HandleInternalError(response, err)
return
}
namespace := request.PathParameter("namespace")
name := request.PathParameter("networkpolicy")
result, err := networkpolicy.GetNetworkPolicyDetail(k8sClient, namespace, name)
if err != nil {
errors.HandleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusOK, result)
}
func (apiHandler *APIHandler) handleGetNodeList(request *restful.Request, response *restful.Response) {
k8sClient, err := apiHandler.cManager.Client(request)
if err != nil {
......
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package networkpolicy
import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
v1 "k8s.io/api/networking/v1"
)
type ServiceAccountCell v1.NetworkPolicy
func (self ServiceAccountCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
switch name {
case dataselect.NameProperty:
return dataselect.StdComparableString(self.ObjectMeta.Name)
case dataselect.CreationTimestampProperty:
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
case dataselect.NamespaceProperty:
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
default:
// If name is not supported then just return a constant dummy value, sort will have no effect.
return nil
}
}
func toCells(std []v1.NetworkPolicy) []dataselect.DataCell {
cells := make([]dataselect.DataCell, len(std))
for i := range std {
cells[i] = ServiceAccountCell(std[i])
}
return cells
}
func fromCells(cells []dataselect.DataCell) []v1.NetworkPolicy {
std := make([]v1.NetworkPolicy, len(cells))
for i := range std {
std[i] = v1.NetworkPolicy(cells[i].(ServiceAccountCell))
}
return std
}
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package networkpolicy
import (
"context"
"log"
v1 "k8s.io/api/networking/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
client "k8s.io/client-go/kubernetes"
)
// NetworkPolicyDetail contains detailed information about a network policy.
type NetworkPolicyDetail struct {
NetworkPolicy `json:",inline"`
PodSelector metaV1.LabelSelector `json:"podSelector"`
Ingress []v1.NetworkPolicyIngressRule `json:"ingress,omitempty"`
Egress []v1.NetworkPolicyEgressRule `json:"egress,omitempty"`
PolicyTypes []v1.PolicyType `json:"policyTypes,omitempty"`
Errors []error `json:"errors"`
}
// GetNetworkPolicyDetail returns detailed information about a network policy.
func GetNetworkPolicyDetail(client client.Interface, namespace, name string) (*NetworkPolicyDetail, error) {
log.Printf("Getting details of %s network policy in %s namespace", name, namespace)
raw, err := client.NetworkingV1().NetworkPolicies(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
return getNetworkPolicyDetail(raw), nil
}
func getNetworkPolicyDetail(np *v1.NetworkPolicy) *NetworkPolicyDetail {
return &NetworkPolicyDetail{
NetworkPolicy: toNetworkPolicy(np),
PodSelector: np.Spec.PodSelector,
Ingress: np.Spec.Ingress,
Egress: np.Spec.Egress,
PolicyTypes: np.Spec.PolicyTypes,
}
}
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package networkpolicy
import (
"context"
v1 "k8s.io/api/networking/v1"
client "k8s.io/client-go/kubernetes"
"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"
)
// NetworkPolicy contains an information about single network policy in the list.
type NetworkPolicy struct {
api.ObjectMeta `json:"objectMeta"`
api.TypeMeta `json:"typeMeta"`
}
// NetworkPolicyList contains a list of network policies.
type NetworkPolicyList struct {
api.ListMeta `json:"listMeta"`
Items []NetworkPolicy `json:"items"`
Errors []error `json:"errors"`
}
// GetNetworkPolicyList lists network policies from given namespace using given data select query.
func GetNetworkPolicyList(client client.Interface, namespace *common.NamespaceQuery,
dsQuery *dataselect.DataSelectQuery) (*NetworkPolicyList, error) {
saList, err := client.NetworkingV1().NetworkPolicies(namespace.ToRequestParam()).List(context.TODO(),
api.ListEverything)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
return toNetworkPolicyList(saList.Items, nonCriticalErrors, dsQuery), nil
}
func toNetworkPolicy(sa *v1.NetworkPolicy) NetworkPolicy {
return NetworkPolicy{
ObjectMeta: api.NewObjectMeta(sa.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindNetworkPolicy),
}
}
func toNetworkPolicyList(networkPolicys []v1.NetworkPolicy, nonCriticalErrors []error,
dsQuery *dataselect.DataSelectQuery) *NetworkPolicyList {
newNetworkPolicyList := &NetworkPolicyList{
ListMeta: api.ListMeta{TotalItems: len(networkPolicys)},
Items: make([]NetworkPolicy, 0),
Errors: nonCriticalErrors,
}
saCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(networkPolicys), dsQuery)
networkPolicys = fromCells(saCells)
newNetworkPolicyList.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for _, sa := range networkPolicys {
newNetworkPolicyList.Items = append(newNetworkPolicyList.Items, toNetworkPolicy(&sa))
}
return newNetworkPolicyList
}
......@@ -34,6 +34,12 @@ limitations under the License.
id="nav-namespace"
i18n>Namespaces
</kd-nav-item>
<kd-nav-item class="kd-nav-item"
state="/networkpolicy"
id="nav-network-policy"
[namespaced]="true"
i18n>Network Policies
</kd-nav-item>
<kd-nav-item class="kd-nav-item"
state="/node"
id="nav-node"
......
......@@ -42,6 +42,10 @@ const routes: Routes = [
path: 'namespace',
loadChildren: () => import('resource/cluster/namespace/module').then(m => m.NamespaceModule),
},
{
path: 'networkpolicy',
loadChildren: () => import('resource/cluster/networkpolicy/module').then(m => m.NetworkPolicyModule),
},
{
path: 'node',
loadChildren: () => import('resource/cluster/node/module').then(m => m.NodeModule),
......@@ -50,6 +54,10 @@ const routes: Routes = [
path: 'persistentvolume',
loadChildren: () => import('resource/cluster/persistentvolume/module').then(m => m.PersistentVolumeModule),
},
{
path: 'serviceaccount',
loadChildren: () => import('resource/cluster/serviceaccount/module').then(m => m.ServiceAccountModule),
},
{
path: 'storageclass',
loadChildren: () => import('resource/cluster/storageclass/module').then(m => m.StorageClassModule),
......@@ -136,10 +144,6 @@ const routes: Routes = [
path: 'secret',
loadChildren: () => import('resource/config/secret/module').then(m => m.SecretModule),
},
{
path: 'serviceaccount',
loadChildren: () => import('resource/cluster/serviceaccount/module').then(m => m.ServiceAccountModule),
},
// Custom resource definitions
{
......
......@@ -95,6 +95,7 @@ import {UploadFileComponent} from './uploadfile/component';
import {WorkloadStatusComponent} from './workloadstatus/component';
import {ZeroStateComponent} from './zerostate/component';
import {ServiceAccountListComponent} from './resourcelist/serviceaccount/component';
import {NetworkPolicyListComponent} from './resourcelist/networkpolicy/component';
const components = [
ActionbarDetailActionsComponent,
......@@ -174,6 +175,7 @@ const components = [
UploadFileComponent,
ZeroStateComponent,
WorkloadStatusComponent,
NetworkPolicyListComponent,
];
@NgModule({
......
......@@ -30,6 +30,7 @@ export enum ListIdentifier {
ingress = 'ingressList',
service = 'serviceList',
serviceAccount = 'serviceAccountList',
networkPolicy = 'networkPolicyList',
configMap = 'configMapList',
persistentVolumeClaim = 'persistentVolumeClaimList',
secret = 'secretList',
......
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {HttpParams} from '@angular/common/http';
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {NetworkPolicy, NetworkPolicyList} from 'typings/backendapi';
import {ResourceListBase} from '../../../resources/list';
import {NotificationsService} from '../../../services/global/notifications';
import {EndpointManager, Resource} from '../../../services/resource/endpoint';
import {NamespacedResourceService} from '../../../services/resource/resource';
import {MenuComponent} from '../../list/column/menu/component';
import {ListGroupIdentifier, ListIdentifier} from '../groupids';
@Component({
selector: 'kd-network-policy-list',
templateUrl: './template.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NetworkPolicyListComponent extends ResourceListBase<NetworkPolicyList, NetworkPolicy> {
@Input() endpoint = EndpointManager.resource(Resource.networkPolicy, true).list();
constructor(
private readonly networkPolicy_: NamespacedResourceService<NetworkPolicyList>,
notifications: NotificationsService,
cdr: ChangeDetectorRef,
) {
super('networkpolicy', notifications, cdr);
this.id = ListIdentifier.networkPolicy;
this.groupId = ListGroupIdentifier.config;
// Register action columns.
this.registerActionColumn<MenuComponent>('menu', MenuComponent);
// Register dynamic columns.
this.registerDynamicColumn('namespace', 'name', this.shouldShowNamespaceColumn_.bind(this));
}
getResourceObservable(params?: HttpParams): Observable<NetworkPolicyList> {
return this.networkPolicy_.get(this.endpoint, undefined, undefined, params);
}
map(networkPolicyList: NetworkPolicyList): NetworkPolicy[] {
return networkPolicyList.items;
}
getDisplayColumns(): string[] {
return ['name', 'labels', 'created'];
}
private shouldShowNamespaceColumn_(): boolean {
return this.namespaceService_.areMultipleNamespacesSelected();
}
}
<!--
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>Network Policies</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="created"
matSortDisableClear
matSortDirection="asc">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef
mat-sort-header
disableClear="true"
i18n>Name</mat-header-cell>
<mat-cell *matCellDef="let serviceAccount">
<a [routerLink]="getDetailsHref(serviceAccount.objectMeta.name, serviceAccount.objectMeta.namespace)"
queryParamsHandling="preserve">
{{serviceAccount.objectMeta.name}}
</a>
</mat-cell>
</ng-container>
<ng-container *ngIf="shouldShowColumn('namespace')"
matColumnDef="namespace">
<mat-header-cell *matHeaderCellDef
i18n>Namespace</mat-header-cell>
<mat-cell *matCellDef="let serviceAccount">{{serviceAccount.objectMeta.namespace}}</mat-cell>
</ng-container>
<ng-container matColumnDef="labels">
<mat-header-cell *matHeaderCellDef
i18n>Labels</mat-header-cell>
<mat-cell *matCellDef="let serviceAccount">
<kd-chips [map]="serviceAccount.objectMeta.labels"></kd-chips>
</mat-cell>
</ng-container>
<ng-container matColumnDef="created">
<mat-header-cell *matHeaderCellDef
mat-sort-header
disableClear="true"
i18n>Created</mat-header-cell>
<mat-cell *matCellDef="let serviceAccount">
<kd-date [date]="serviceAccount.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 serviceAccount">
<kd-dynamic-cell [component]="col.component"
[resource]="serviceAccount"></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>
......@@ -15,6 +15,6 @@
@import '../../../variables';
.kd-ace {
height: 50 * $baseline-grid;
height: 45 * $baseline-grid;
width: 100%;
}
......@@ -41,6 +41,7 @@ export enum Resource {
ingress = 'ingress',
service = 'service',
serviceAccount = 'serviceaccount',
networkPolicy = 'networkpolicy',
event = 'event',
container = 'container',
plugin = 'plugin',
......
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'rxjs/add/operator/startWith';
import {Component, OnDestroy, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {NetworkPolicyDetail} from '@api/backendapi';
import {Subscription} from 'rxjs/Subscription';
import {ActionbarService, ResourceMeta} from '../../../../common/services/global/actionbar';
import {NotificationsService} from '../../../../common/services/global/notifications';
import {EndpointManager, Resource} from '../../../../common/services/resource/endpoint';
import {NamespacedResourceService} from '../../../../common/services/resource/resource';
import {dump} from 'js-yaml';
@Component({
selector: 'kd-network-policy-detail',
templateUrl: './template.html',
})
export class NetworkPolicyDetailComponent implements OnInit, OnDestroy {
private networkPolicySubscription_: Subscription;
private readonly endpoint_ = EndpointManager.resource(Resource.networkPolicy, true);
networkPolicy: NetworkPolicyDetail;
isInitialized = false;
constructor(
private readonly networkPolicy_: NamespacedResourceService<NetworkPolicyDetail>,
private readonly actionbar_: ActionbarService,
private readonly activatedRoute_: ActivatedRoute,
private readonly notifications_: NotificationsService,
) {}
ngOnInit(): void {
const resourceName = this.activatedRoute_.snapshot.params.resourceName;
const resourceNamespace = this.activatedRoute_.snapshot.params.resourceNamespace;
this.networkPolicySubscription_ = this.networkPolicy_
.get(this.endpoint_.detail(), resourceName, resourceNamespace)
.subscribe((d: NetworkPolicyDetail) => {
this.networkPolicy = d;
this.notifications_.pushErrors(d.errors);
this.actionbar_.onInit.emit(new ResourceMeta('Network Policy', d.objectMeta, d.typeMeta));
this.isInitialized = true;
});
}
ngOnDestroy(): void {
this.networkPolicySubscription_.unsubscribe();
this.actionbar_.onDetailsLeave.emit();
}
stringify(data: any): string {
return dump(data);
}
}
<!--
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]="networkPolicy?.objectMeta"></kd-object-meta>
<kd-card [initialized]="isInitialized">
<div title
i18n>Resource information</div>
<div content
*ngIf="isInitialized"
fxLayout="row wrap">
<kd-property *ngIf="networkPolicy?.podSelector">
<div key
i18n>Pod Selector</div>
<div value>
<kd-chips [map]="networkPolicy?.podSelector.matchLabels"></kd-chips>
</div>
</kd-property>
<kd-property *ngIf="networkPolicy?.podSelector">
<div key
i18n>Policy Types</div>
<div value>
<kd-chips [map]="networkPolicy?.policyTypes"></kd-chips>
</div>
</kd-property>
</div>
</kd-card>
<kd-card *ngIf="networkPolicy?.ingress"
role="table">
<div title
i18n>Ingress Rules</div>
<div content>
<kd-text-input [text]="stringify(networkPolicy.ingress)"
[readOnly]="true"
[border]="false"
mode="yaml"></kd-text-input>
</div>
</kd-card>
<kd-card *ngIf="networkPolicy?.egress"
role="table">
<div title
i18n>Egress Rules</div>
<div content>
<kd-text-input [text]="stringify(networkPolicy.egress)"
[readOnly]="true"
[border]="false"
mode="yaml"></kd-text-input>
</div>
</kd-card>
// 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-network-policy-list-state',
template: '<kd-network-policy-list></kd-network-policy-list>',
})
export class NetworkPolicyListComponent {}
// 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 {NetworkPolicyDetailComponent} from './detail/component';
import {NetworkPolicyListComponent} from './list/component';
import {NetworkPolicyRoutingModule} from './routing';
@NgModule({
imports: [SharedModule, ComponentsModule, NetworkPolicyRoutingModule],
declarations: [NetworkPolicyListComponent, NetworkPolicyDetailComponent],
})
export class NetworkPolicyModule {}
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {NgModule} from '@angular/core';
import {Route, RouterModule} from '@angular/router';
import {DEFAULT_ACTIONBAR} from '../../../common/components/actionbars/routing';
import {CLUSTER_ROUTE} from '../routing';
import {NetworkPolicyDetailComponent} from './detail/component';
import {NetworkPolicyListComponent} from './list/component';
const NETWORK_POLICY_LIST_ROUTE: Route = {
path: '',
component: NetworkPolicyListComponent,
data: {
breadcrumb: 'Network Policies',
parent: CLUSTER_ROUTE,
},
};
const NETWORK_POLICY_DETAIL_ROUTE: Route = {
path: ':resourceNamespace/:resourceName',
component: NetworkPolicyDetailComponent,
data: {
breadcrumb: '{{ resourceName }}',
parent: NETWORK_POLICY_LIST_ROUTE,
},
};
@NgModule({
imports: [RouterModule.forChild([NETWORK_POLICY_LIST_ROUTE, NETWORK_POLICY_DETAIL_ROUTE, DEFAULT_ACTIONBAR])],
exports: [RouterModule],
})
export class NetworkPolicyRoutingModule {}
......@@ -16,7 +16,7 @@ import {NgModule} from '@angular/core';
import {Route, RouterModule} from '@angular/router';
import {DEFAULT_ACTIONBAR} from '../../../common/components/actionbars/routing';
import {CONFIG_ROUTE} from '../../config/routing';
import {CLUSTER_ROUTE} from '../routing';
import {ServiceAccountDetailComponent} from './detail/component';
import {ServiceAccountListComponent} from './list/component';
......@@ -26,7 +26,7 @@ const SERVICEACCOUNT_LIST_ROUTE: Route = {
component: ServiceAccountListComponent,
data: {
breadcrumb: 'Service Accounts',
parent: CONFIG_ROUTE,
parent: CLUSTER_ROUTE,
},
};
......
......@@ -19,6 +19,8 @@ limitations under the License.
[hideable]="true"></kd-cluster-role-list>
<kd-namespace-list (onchange)="onListUpdate($event)"
[hideable]="true"></kd-namespace-list>
<kd-network-policy-list (onchange)="onListUpdate($event)"
[hideable]="true"></kd-network-policy-list>
<kd-node-list (onchange)="onListUpdate($event)"
[hideable]="true"></kd-node-list>
<kd-persistent-volume-list (onchange)="onListUpdate($event)"
......
......@@ -127,6 +127,10 @@ export interface ServiceAccountList extends ResourceList {
items: ServiceAccount[];
}
export interface NetworkPolicyList extends ResourceList {
items: NetworkPolicy[];
}
export interface JobList extends ResourceList {
cumulativeMetrics: Metric[] | null;
jobs: Job[];
......@@ -201,6 +205,8 @@ export type ConfigMap = Resource;
export type ServiceAccount = Resource;
export type NetworkPolicy = Resource;
export interface Controller extends Resource {
pods: PodInfo;
containerImages: string[];
......@@ -456,6 +462,13 @@ export type ServiceAccountDetail = ResourceDetail;
export type IngressDetail = ResourceDetail;
export interface NetworkPolicyDetail extends ResourceDetail {
podSelector: LabelSelector;
ingress?: any;
egress?: any;
policyTypes?: string[];
}
export interface PersistentVolumeClaimDetail extends ResourceDetail {
status: string;
volume: string;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册