diff --git a/.github/workflows/cd-helm.yml b/.github/workflows/cd-helm.yml index bed80fefbf8..8307d10467f 100644 --- a/.github/workflows/cd-helm.yml +++ b/.github/workflows/cd-helm.yml @@ -34,7 +34,6 @@ jobs: with: version: v3.12.1 - uses: helm/chart-testing-action@v2.6.1 - - run: ct lint --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }} - uses: helm/kind-action@v1.9.0 with: node_image: kindest/node:v1.29.0 diff --git a/modules/api/Makefile b/modules/api/Makefile index 8e7bd56f77d..ff28811e1fd 100644 --- a/modules/api/Makefile +++ b/modules/api/Makefile @@ -61,7 +61,8 @@ fix-go: $(PRE) .PHONY: run run: build @$(API_DIST_BINARY) \ - --kubeconfig=$(KUBECONFIG) + --kubeconfig=$(KUBECONFIG) \ + --metrics-provider=none .PHONY: schema schema: --ensure-kind-cluster build --swagger diff --git a/modules/api/pkg/handler/apihandler.go b/modules/api/pkg/handler/apihandler.go index 87322e13672..e6b3f991554 100644 --- a/modules/api/pkg/handler/apihandler.go +++ b/modules/api/pkg/handler/apihandler.go @@ -994,6 +994,12 @@ func CreateHTTPAPIHandler(iManager integration.Manager) (*restful.Container, err Returns(http.StatusOK, "OK", clusterrolebinding.ClusterRoleBindingDetail{})) // Role + apiV1Ws.Route( + apiV1Ws.GET("/role").To(apiHandler.handleGetRoleList). + // docs + Doc("returns a list of Roles from all namespace"). + Writes(role.RoleList{}). + Returns(http.StatusOK, "OK", role.RoleList{})) apiV1Ws.Route( apiV1Ws.GET("/role/{namespace}").To(apiHandler.handleGetRoleList). // docs @@ -1011,6 +1017,12 @@ func CreateHTTPAPIHandler(iManager integration.Manager) (*restful.Container, err Returns(http.StatusOK, "OK", role.RoleDetail{})) // RoleBinding + apiV1Ws.Route( + apiV1Ws.GET("/rolebinding").To(apiHandler.handleGetRoleBindingList). + // docs + Doc("returns a list of RoleBindings from all namespace"). + Writes(rolebinding.RoleBindingList{}). + Returns(http.StatusOK, "OK", rolebinding.RoleBindingList{})) apiV1Ws.Route( apiV1Ws.GET("/rolebinding/{namespace}").To(apiHandler.handleGetRoleBindingList). // docs diff --git a/modules/api/pkg/resource/dataselect/dataselect.go b/modules/api/pkg/resource/dataselect/dataselect.go index 8429ff89c92..d998eef2281 100644 --- a/modules/api/pkg/resource/dataselect/dataselect.go +++ b/modules/api/pkg/resource/dataselect/dataselect.go @@ -15,9 +15,10 @@ package dataselect import ( - "log" "sort" + "k8s.io/klog/v2" + metricapi "k8s.io/dashboard/api/pkg/integration/metric/api" "k8s.io/dashboard/errors" ) @@ -129,7 +130,7 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) ( metricPromises := make([]metricapi.MetricPromises, 0) if metricClient == nil { - return metricPromises, errors.NewInternal("No metric client provided. Skipping metrics.") + return metricPromises, nil } metricNames := self.DataSelectQuery.MetricQuery.MetricNames @@ -142,7 +143,7 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) ( // make sure data cells support metrics metricDataCell, ok := dataCell.(MetricDataCell) if !ok { - log.Printf("Data cell does not implement MetricDataCell. Skipping. %v", dataCell) + klog.V(0).InfoS("Data cell does not implement MetricDataCell. Skipping.", "dataCell", dataCell) continue } @@ -162,7 +163,11 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) ( func (self *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataSelector { metricPromisesList, err := self.getMetrics(metricClient) if err != nil { - log.Print(err) + klog.ErrorS(err, "error during getting metrics") + return self + } + + if len(metricPromisesList) == 0 { return self } @@ -180,13 +185,17 @@ func (self *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataS func (self *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClient) *DataSelector { metricPromisesList, err := self.getMetrics(metricClient) if err != nil { - log.Print(err) + klog.ErrorS(err, "error during getting metrics") + return self + } + + if len(metricPromisesList) == 0 { return self } metricNames := self.DataSelectQuery.MetricQuery.MetricNames if metricNames == nil { - log.Print("No metrics specified. Skipping metrics.") + klog.V(1).Info("Metrics names not provided. Skipping.") return self } diff --git a/modules/api/pkg/resource/node/detail.go b/modules/api/pkg/resource/node/detail.go index 6e61c9b19c0..1fa0cdc2ba0 100644 --- a/modules/api/pkg/resource/node/detail.go +++ b/modules/api/pkg/resource/node/detail.go @@ -84,6 +84,7 @@ type NodeDetail struct { Node `json:",inline"` // NodePhase is the current lifecycle phase of the node. + // Deprecated Phase v1.NodePhase `json:"phase"` // PodCIDR represents the pod IP range assigned to the node. @@ -339,8 +340,10 @@ func toNodeDetail(node v1.Node, pods *pod.PodList, eventList *common.EventList, Node: Node{ ObjectMeta: types.NewObjectMeta(node.ObjectMeta), TypeMeta: types.NewTypeMeta(types.ResourceKindNode), + Ready: getNodeConditionStatus(node, v1.NodeReady), AllocatedResources: allocatedResources, }, + // TODO: Remove deprecated field Phase: node.Status.Phase, ProviderID: node.Spec.ProviderID, PodCIDR: node.Spec.PodCIDR, diff --git a/modules/api/pkg/resource/node/detail_test.go b/modules/api/pkg/resource/node/detail_test.go index f3bcc46f031..08108911a1c 100644 --- a/modules/api/pkg/resource/node/detail_test.go +++ b/modules/api/pkg/resource/node/detail_test.go @@ -64,6 +64,7 @@ func TestGetNodeDetail(t *testing.T) { PodCapacity: 0, PodFraction: 0, }, + Ready: v1.ConditionUnknown, }, PodCIDR: "127.0.0.1", ProviderID: "ID-1", diff --git a/modules/api/pkg/resource/pod/common_test.go b/modules/api/pkg/resource/pod/common_test.go index eeeb964bd73..3c94078c36a 100644 --- a/modules/api/pkg/resource/pod/common_test.go +++ b/modules/api/pkg/resource/pod/common_test.go @@ -40,9 +40,10 @@ func TestToPodPodStatusFailed(t *testing.T) { } expected := Pod{ - TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, - Status: string(v1.PodFailed), - Warnings: []common.Event{}, + TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, + Status: string(v1.PodFailed), + Warnings: []common.Event{}, + ContainerStatuses: make([]ContainerStatus, 0), } actual := toPod(pod, &MetricsByPod{}, []common.Event{}) @@ -67,9 +68,10 @@ func TestToPodPodStatusSucceeded(t *testing.T) { } expected := Pod{ - TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, - Status: string(v1.PodSucceeded), - Warnings: []common.Event{}, + TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, + Status: string(v1.PodSucceeded), + Warnings: []common.Event{}, + ContainerStatuses: make([]ContainerStatus, 0), } actual := toPod(pod, &MetricsByPod{}, []common.Event{}) @@ -98,9 +100,10 @@ func TestToPodPodStatusRunning(t *testing.T) { } expected := Pod{ - TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, - Status: string(v1.PodRunning), - Warnings: []common.Event{}, + TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, + Status: string(v1.PodRunning), + Warnings: []common.Event{}, + ContainerStatuses: make([]ContainerStatus, 0), } actual := toPod(pod, &MetricsByPod{}, []common.Event{}) @@ -125,9 +128,10 @@ func TestToPodPodStatusPending(t *testing.T) { } expected := Pod{ - TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, - Status: string(v1.PodPending), - Warnings: []common.Event{}, + TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, + Status: string(v1.PodPending), + Warnings: []common.Event{}, + ContainerStatuses: make([]ContainerStatus, 0), } actual := toPod(pod, &MetricsByPod{}, []common.Event{}) @@ -165,6 +169,14 @@ func TestToPodContainerStates(t *testing.T) { TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, Status: "Terminated", Warnings: []common.Event{}, + ContainerStatuses: []ContainerStatus{ + { + State: Terminated, + }, + { + State: Waiting, + }, + }, } actual := toPod(pod, &MetricsByPod{}, []common.Event{}) @@ -184,8 +196,9 @@ func TestToPod(t *testing.T) { { pod: &v1.Pod{}, metrics: &MetricsByPod{}, expected: Pod{ - TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, - Warnings: []common.Event{}, + TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, + Warnings: []common.Event{}, + ContainerStatuses: make([]ContainerStatus, 0), }, }, { pod: &v1.Pod{ @@ -199,7 +212,8 @@ func TestToPod(t *testing.T) { Name: "test-pod", Namespace: "test-namespace", }, - Warnings: []common.Event{}, + Warnings: []common.Event{}, + ContainerStatuses: make([]ContainerStatus, 0), }, }, } diff --git a/modules/api/pkg/resource/pod/container.go b/modules/api/pkg/resource/pod/container.go new file mode 100644 index 00000000000..58dabb6804b --- /dev/null +++ b/modules/api/pkg/resource/pod/container.go @@ -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. + +package pod + +import ( + v1 "k8s.io/api/core/v1" +) + +type ContainerStatus struct { + Name string `json:"name"` + State ContainerState `json:"state"` + Ready bool `json:"ready"` +} + +type ContainerState string + +const ( + Waiting ContainerState = "Waiting" + Running ContainerState = "Running" + Terminated ContainerState = "Terminated" + Unknown ContainerState = "Unknown" +) + +func ToContainerStatuses(containerStatuses []v1.ContainerStatus) []ContainerStatus { + result := make([]ContainerStatus, len(containerStatuses)) + for i, c := range containerStatuses { + result[i] = ContainerStatus{ + Name: c.Name, + State: toContainerState(c.State), + Ready: c.Ready, + } + } + + return result +} + +func toContainerState(state v1.ContainerState) ContainerState { + if state.Waiting != nil { + return Waiting + } + + if state.Terminated != nil { + return Terminated + } + + if state.Running != nil { + return Running + } + + return Unknown +} diff --git a/modules/api/pkg/resource/pod/list.go b/modules/api/pkg/resource/pod/list.go index 07b997bb8ee..d601a954cf9 100644 --- a/modules/api/pkg/resource/pod/list.go +++ b/modules/api/pkg/resource/pod/list.go @@ -73,6 +73,8 @@ type Pod struct { // ContainerImages holds a list of the Pod images. ContainerImages []string `json:"containerImages"` + + ContainerStatuses []ContainerStatus `json:"containerStatuses"` } var EmptyPodList = &PodList{ @@ -155,13 +157,14 @@ func ToPodList(pods []v1.Pod, events []v1.Event, nonCriticalErrors []error, dsQu func toPod(pod *v1.Pod, metrics *MetricsByPod, warnings []common.Event) Pod { podDetail := Pod{ - ObjectMeta: types.NewObjectMeta(pod.ObjectMeta), - TypeMeta: types.NewTypeMeta(types.ResourceKindPod), - Warnings: warnings, - Status: getPodStatus(*pod), - RestartCount: getRestartCount(*pod), - NodeName: pod.Spec.NodeName, - ContainerImages: common.GetContainerImages(&pod.Spec), + ObjectMeta: types.NewObjectMeta(pod.ObjectMeta), + TypeMeta: types.NewTypeMeta(types.ResourceKindPod), + Warnings: warnings, + Status: getPodStatus(*pod), + RestartCount: getRestartCount(*pod), + NodeName: pod.Spec.NodeName, + ContainerImages: common.GetContainerImages(&pod.Spec), + ContainerStatuses: ToContainerStatuses(append(pod.Status.InitContainerStatuses, pod.Status.ContainerStatuses...)), } if m, exists := metrics.MetricsMap[pod.UID]; exists { diff --git a/modules/api/pkg/resource/pod/list_test.go b/modules/api/pkg/resource/pod/list_test.go index 54477be9f22..07c7f8fd2ce 100644 --- a/modules/api/pkg/resource/pod/list_test.go +++ b/modules/api/pkg/resource/pod/list_test.go @@ -102,8 +102,9 @@ func TestGetPodListFromChannels(t *testing.T) { Labels: map[string]string{"key": "value"}, CreationTimestamp: metav1.Unix(111, 222), }, - TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, - Warnings: []common.Event{}, + TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, + Warnings: []common.Event{}, + ContainerStatuses: make([]pod.ContainerStatus, 0), }}, Errors: []error{}, }, diff --git a/modules/api/pkg/resource/service/pods_test.go b/modules/api/pkg/resource/service/pods_test.go index a4d88882693..ade80b16a36 100644 --- a/modules/api/pkg/resource/service/pods_test.go +++ b/modules/api/pkg/resource/service/pods_test.go @@ -58,8 +58,9 @@ func TestGetServicePods(t *testing.T) { Name: "pod-1", UID: "test-uid", Namespace: "ns-1"}, - TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, - Warnings: []common.Event{}, + TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod}, + Warnings: []common.Event{}, + ContainerStatuses: make([]pod.ContainerStatus, 0), }, }, Errors: []error{}, diff --git a/modules/api/schema/swagger.json b/modules/api/schema/swagger.json index a883e1dbd5a..57abf1eb3c7 100644 --- a/modules/api/schema/swagger.json +++ b/modules/api/schema/swagger.json @@ -3680,7 +3680,7 @@ } } }, - "/api/v1/ingress/{namespace}/{ingress}/event": { + "/api/v1/ingress/{namespace}/{name}": { "get": { "consumes": [ "application/json" @@ -3688,8 +3688,8 @@ "produces": [ "application/json" ], - "summary": "returns a list of Events for Ingress", - "operationId": "handleGetIngressEvent", + "summary": "returns detailed information about Ingress", + "operationId": "handleGetIngressDetail", "parameters": [ { "type": "string", @@ -3737,7 +3737,7 @@ { "type": "string", "description": "name of the Ingress", - "name": "ingress", + "name": "name", "in": "path", "required": true } @@ -3746,13 +3746,13 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/common.EventList" + "$ref": "#/definitions/ingress.IngressDetail" } } } } }, - "/api/v1/ingress/{namespace}/{name}": { + "/api/v1/ingress/{namespace}/{name}/event": { "get": { "consumes": [ "application/json" @@ -3760,8 +3760,8 @@ "produces": [ "application/json" ], - "summary": "returns detailed information about Ingress", - "operationId": "handleGetIngressDetail", + "summary": "returns a list of Events for Ingress", + "operationId": "handleGetIngressEvent", "parameters": [ { "type": "string", @@ -3809,7 +3809,7 @@ { "type": "string", "description": "name of the Ingress", - "name": "name", + "name": "ingress", "in": "path", "required": true } @@ -3818,7 +3818,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/ingress.IngressDetail" + "$ref": "#/definitions/common.EventList" } } } @@ -7124,6 +7124,64 @@ } } }, + "/api/v1/role": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "returns a list of Roles from all namespace", + "operationId": "handleGetRoleList", + "parameters": [ + { + "type": "string", + "description": "Comma delimited string used to apply filtering: 'propertyName,filterValue'", + "name": "filterBy", + "in": "query" + }, + { + "type": "string", + "description": "Name of the column to sort by", + "name": "sortBy", + "in": "query" + }, + { + "type": "string", + "description": "Number of items to return when pagination is applied", + "name": "itemsPerPage", + "in": "query" + }, + { + "type": "string", + "description": "Page number to return items from", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "Metric names to download", + "name": "metricNames", + "in": "query" + }, + { + "type": "string", + "description": "Aggregations to be performed for each metric (default: sum)", + "name": "aggregations", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/role.RoleList" + } + } + } + } + }, "/api/v1/role/{namespace}": { "get": { "consumes": [ @@ -7261,6 +7319,64 @@ } } }, + "/api/v1/rolebinding": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "returns a list of RoleBindings from all namespace", + "operationId": "handleGetRoleBindingList", + "parameters": [ + { + "type": "string", + "description": "Comma delimited string used to apply filtering: 'propertyName,filterValue'", + "name": "filterBy", + "in": "query" + }, + { + "type": "string", + "description": "Name of the column to sort by", + "name": "sortBy", + "in": "query" + }, + { + "type": "string", + "description": "Number of items to return when pagination is applied", + "name": "itemsPerPage", + "in": "query" + }, + { + "type": "string", + "description": "Page number to return items from", + "name": "page", + "in": "query" + }, + { + "type": "string", + "description": "Metric names to download", + "name": "metricNames", + "in": "query" + }, + { + "type": "string", + "description": "Aggregations to be performed for each metric (default: sum)", + "name": "aggregations", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/rolebinding.RoleBindingList" + } + } + } + } + }, "/api/v1/rolebinding/{namespace}": { "get": { "consumes": [ @@ -10280,11 +10396,11 @@ }, "deployment.DeploymentDetail": { "required": [ + "containerImages", "initContainerImages", "objectMeta", "typeMeta", "pods", - "containerImages", "selector", "statusInfo", "conditions", @@ -10599,13 +10715,13 @@ }, "horizontalpodautoscaler.HorizontalPodAutoscalerDetail": { "required": [ + "targetCPUUtilizationPercentage", + "objectMeta", "typeMeta", "scaleTargetRef", "minReplicas", "maxReplicas", "currentCPUUtilizationPercentage", - "targetCPUUtilizationPercentage", - "objectMeta", "currentReplicas", "desiredReplicas", "lastScaleTime" @@ -10732,10 +10848,10 @@ }, "ingress.IngressDetail": { "required": [ - "hosts", "objectMeta", "typeMeta", "endpoints", + "hosts", "spec", "status", "errors" @@ -10882,13 +10998,13 @@ }, "job.JobDetail": { "required": [ + "initContainerImages", + "parallelism", + "jobStatus", "objectMeta", "typeMeta", "podInfo", "containerImages", - "initContainerImages", - "parallelism", - "jobStatus", "completions", "errors" ], @@ -11138,9 +11254,9 @@ }, "namespace.NamespaceDetail": { "required": [ + "typeMeta", "phase", "objectMeta", - "typeMeta", "resourceQuotaList", "resourceLimits", "errors" @@ -11382,10 +11498,10 @@ }, "node.NodeDetail": { "required": [ - "objectMeta", - "typeMeta", "ready", "allocatedResources", + "objectMeta", + "typeMeta", "phase", "podCIDR", "providerID", @@ -11558,16 +11674,16 @@ }, "persistentvolume.PersistentVolumeDetail": { "required": [ + "claim", + "objectMeta", "capacity", - "accessModes", + "reclaimPolicy", + "storageClass", "mountOptions", "status", "typeMeta", - "reclaimPolicy", - "storageClass", - "claim", + "accessModes", "reason", - "objectMeta", "message", "persistentVolumeSource" ], @@ -11685,13 +11801,13 @@ }, "persistentvolumeclaim.PersistentVolumeClaimDetail": { "required": [ + "storageClass", + "objectMeta", + "typeMeta", "status", "volume", "capacity", - "accessModes", - "storageClass", - "objectMeta", - "typeMeta" + "accessModes" ], "properties": { "accessModes": { @@ -11812,6 +11928,24 @@ } } }, + "pod.ContainerStatus": { + "required": [ + "name", + "state", + "ready" + ], + "properties": { + "name": { + "type": "string" + }, + "ready": { + "type": "boolean" + }, + "state": { + "type": "string" + } + } + }, "pod.EnvVar": { "required": [ "name", @@ -11839,7 +11973,8 @@ "metrics", "warnings", "nodeName", - "containerImages" + "containerImages", + "containerStatuses" ], "properties": { "containerImages": { @@ -11848,6 +11983,12 @@ "type": "string" } }, + "containerStatuses": { + "type": "array", + "items": { + "$ref": "#/definitions/pod.ContainerStatus" + } + }, "metrics": { "$ref": "#/definitions/pod.PodMetrics" }, @@ -12095,11 +12236,11 @@ }, "replicaset.ReplicaSetDetail": { "required": [ - "initContainerImages", "objectMeta", "typeMeta", "podInfo", "containerImages", + "initContainerImages", "selector", "horizontalPodAutoscalerList", "errors" @@ -12209,11 +12350,11 @@ }, "replicationcontroller.ReplicationControllerDetail": { "required": [ + "containerImages", + "initContainerImages", "objectMeta", "typeMeta", "podInfo", - "containerImages", - "initContainerImages", "labelSelector", "errors" ], @@ -12416,8 +12557,8 @@ }, "role.RoleDetail": { "required": [ - "typeMeta", "objectMeta", + "typeMeta", "rules", "errors" ], @@ -12878,11 +13019,11 @@ }, "statefulset.StatefulSetDetail": { "required": [ + "initContainerImages", "objectMeta", "typeMeta", "podInfo", "containerImages", - "initContainerImages", "errors" ], "properties": { @@ -13034,12 +13175,12 @@ }, "types.CustomResourceDefinitionDetail": { "required": [ + "established", "objectMeta", "typeMeta", "group", "scope", "names", - "established", "conditions", "objects", "subresources", diff --git a/modules/common/csrf/middleware_gin.go b/modules/common/csrf/middleware_gin.go index b0b7621b7e3..dabe8584c0a 100644 --- a/modules/common/csrf/middleware_gin.go +++ b/modules/common/csrf/middleware_gin.go @@ -15,7 +15,6 @@ package csrf import ( - "fmt" "net/http" "github.com/gin-gonic/gin" @@ -36,7 +35,6 @@ func Gin() *GinMiddlewares { type GinMiddlewares struct{} func (in *GinMiddlewares) CSRF(options ...GinCSRFOption) gin.HandlerFunc { - fmt.Println("registering new middleware") middleware := &GinCSRFMiddleware{ actionGetter: defaultGinCSRFActionGetter, runCondition: defaultGinCSRFRunCondition, diff --git a/modules/web/schema/schema.graphql b/modules/web/schema/schema.graphql index 61eb2a000bd..26dbf364dd8 100755 --- a/modules/web/schema/schema.graphql +++ b/modules/web/schema/schema.graphql @@ -1,3 +1,17 @@ +# 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. + schema @transport(subgraph: "api", kind: "rest") { query: Query mutation: Mutation @@ -652,12 +666,12 @@ type Query { """namespace of the Ingress""" namespace: String! ): ingress_IngressList @httpOperation(subgraph: "api", path: "/api/v1/ingress", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") @httpOperation(subgraph: "api", path: "/api/v1/ingress/{args.namespace}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") - """returns a list of Events for Ingress""" - handleGetIngressEvent( + """returns detailed information about Ingress""" + handleGetIngressDetail( """namespace of the Ingress""" namespace: String! """name of the Ingress""" - ingress: String! + name: String! """ Comma delimited string used to apply filtering: 'propertyName,filterValue' """ @@ -672,13 +686,11 @@ type Query { metricNames: String """Aggregations to be performed for each metric (default: sum)""" aggregations: String - ): common_EventList @httpOperation(subgraph: "api", path: "/api/v1/ingress/{args.namespace}/{args.ingress}/event", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") - """returns detailed information about Ingress""" - handleGetIngressDetail( + ): ingress_IngressDetail @httpOperation(subgraph: "api", path: "/api/v1/ingress/{args.namespace}/{args.name}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") + """returns a list of Events for Ingress""" + handleGetIngressEvent( """namespace of the Ingress""" namespace: String! - """name of the Ingress""" - name: String! """ Comma delimited string used to apply filtering: 'propertyName,filterValue' """ @@ -693,7 +705,7 @@ type Query { metricNames: String """Aggregations to be performed for each metric (default: sum)""" aggregations: String - ): ingress_IngressDetail @httpOperation(subgraph: "api", path: "/api/v1/ingress/{args.namespace}/{args.name}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") + ): common_EventList @httpOperation(subgraph: "api", path: "/api/v1/ingress/{args.namespace}/{name}/event", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") """returns a list of IngressClasses""" handleGetIngressClassList( """ @@ -1476,8 +1488,6 @@ type Query { ): service_ServiceList @httpOperation(subgraph: "api", path: "/api/v1/replicationcontroller/{args.namespace}/{args.replicationController}/service", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") """returns a list of Roles in a namespace""" handleGetRoleList( - """namespace of the Role""" - namespace: String! """ Comma delimited string used to apply filtering: 'propertyName,filterValue' """ @@ -1492,7 +1502,9 @@ type Query { metricNames: String """Aggregations to be performed for each metric (default: sum)""" aggregations: String - ): role_RoleList @httpOperation(subgraph: "api", path: "/api/v1/role/{args.namespace}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") + """namespace of the Role""" + namespace: String! + ): role_RoleList @httpOperation(subgraph: "api", path: "/api/v1/role", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") @httpOperation(subgraph: "api", path: "/api/v1/role/{args.namespace}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") """returns detailed information about Role""" handleGetRoleDetail( """namespace of the Role""" @@ -1516,8 +1528,6 @@ type Query { ): role_RoleDetail @httpOperation(subgraph: "api", path: "/api/v1/role/{args.namespace}/{args.name}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") """returns a list of RoleBindings in a namespace""" handleGetRoleBindingList( - """namespace of the RoleBinding""" - namespace: String! """ Comma delimited string used to apply filtering: 'propertyName,filterValue' """ @@ -1532,7 +1542,9 @@ type Query { metricNames: String """Aggregations to be performed for each metric (default: sum)""" aggregations: String - ): rolebinding_RoleBindingList @httpOperation(subgraph: "api", path: "/api/v1/rolebinding/{args.namespace}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") + """namespace of the RoleBinding""" + namespace: String! + ): rolebinding_RoleBindingList @httpOperation(subgraph: "api", path: "/api/v1/rolebinding", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") @httpOperation(subgraph: "api", path: "/api/v1/rolebinding/{args.namespace}", operationSpecificHeaders: "{\"Content-Type\":\"application/json\",\"Accept\":\"application/json\"}", httpMethod: GET, queryParamArgMap: "{\"filterBy\":\"filterBy\",\"sortBy\":\"sortBy\",\"itemsPerPage\":\"itemsPerPage\",\"page\":\"page\",\"metricNames\":\"metricNames\",\"aggregations\":\"aggregations\"}") """returns detailed information about RoleBinding""" handleGetRoleBindingDetail( """namespace of the RoleBinding""" @@ -2386,6 +2398,7 @@ type pod_PodList { type pod_Pod { containerImages: [String]! + containerStatuses: [pod_ContainerStatus]! metrics: pod_PodMetrics! nodeName: String! objectMeta: types_ObjectMeta! @@ -2395,6 +2408,12 @@ type pod_Pod { warnings: [common_Event]! } +type pod_ContainerStatus { + name: String! + ready: Boolean! + state: String! +} + type pod_PodMetrics { cpuUsage: Int! cpuUsageHistory: [api_MetricPoint]!