feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 KubeSphere 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 v1alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apiserver/pkg/util/flushwriter"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"kubesphere.io/api/gateway/v1alpha1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
operator "kubesphere.io/kubesphere/pkg/models/gateway"
|
||||
"kubesphere.io/kubesphere/pkg/models/logging"
|
||||
servererr "kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/gateway"
|
||||
loggingclient "kubesphere.io/kubesphere/pkg/simple/client/logging"
|
||||
conversionsv1 "kubesphere.io/kubesphere/pkg/utils/conversions/core/v1"
|
||||
"kubesphere.io/kubesphere/pkg/utils/stringutils"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
options *gateway.Options
|
||||
gw operator.GatewayOperator
|
||||
factory informers.InformerFactory
|
||||
lo logging.LoggingOperator
|
||||
}
|
||||
|
||||
// newHandler create an instance of the handler
|
||||
func newHandler(options *gateway.Options, cache cache.Cache, client client.Client, factory informers.InformerFactory, k8sClient kubernetes.Interface, loggingClient loggingclient.Client) *handler {
|
||||
conversionsv1.RegisterConversions(scheme.Scheme)
|
||||
// Do not register Gateway scheme globally. Which will cause conflict in ks-controller-manager.
|
||||
v1alpha1.AddToScheme(client.Scheme())
|
||||
var lo logging.LoggingOperator
|
||||
if loggingClient != nil {
|
||||
lo = logging.NewLoggingOperator(loggingClient)
|
||||
}
|
||||
return &handler{
|
||||
options: options,
|
||||
factory: factory,
|
||||
gw: operator.NewGatewayOperator(client, cache, options, factory, k8sClient),
|
||||
lo: lo,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) Create(request *restful.Request, response *restful.Response) {
|
||||
ns := request.PathParameter("namespace")
|
||||
var gateway v1alpha1.Gateway
|
||||
|
||||
err := request.ReadEntity(&gateway)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
created, err := h.gw.CreateGateway(ns, &gateway)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(created)
|
||||
}
|
||||
|
||||
func (h *handler) Update(request *restful.Request, response *restful.Response) {
|
||||
ns := request.PathParameter("namespace")
|
||||
var gateway v1alpha1.Gateway
|
||||
err := request.ReadEntity(&gateway)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
updated, err := h.gw.UpdateGateway(ns, &gateway)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(updated)
|
||||
}
|
||||
|
||||
func (h *handler) Get(request *restful.Request, response *restful.Response) {
|
||||
ns := request.PathParameter("namespace")
|
||||
gateway, err := h.gw.GetGateways(ns)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
response.WriteEntity(gateway)
|
||||
}
|
||||
|
||||
func (h *handler) Delete(request *restful.Request, response *restful.Response) {
|
||||
ns := request.PathParameter("namespace")
|
||||
|
||||
err := h.gw.DeleteGateway(ns)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) Upgrade(request *restful.Request, response *restful.Response) {
|
||||
ns := request.PathParameter("namespace")
|
||||
|
||||
g, err := h.gw.UpgradeGateway(ns)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(g)
|
||||
}
|
||||
|
||||
func (h *handler) List(request *restful.Request, response *restful.Response) {
|
||||
queryParam := query.ParseQueryParameter(request)
|
||||
|
||||
result, err := h.gw.ListGateways(queryParam)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) ListPods(request *restful.Request, response *restful.Response) {
|
||||
queryParam := query.ParseQueryParameter(request)
|
||||
ns := request.PathParameter("namespace")
|
||||
|
||||
result, err := h.gw.GetPods(ns, queryParam)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) PodLog(request *restful.Request, response *restful.Response) {
|
||||
|
||||
podNamespace := request.PathParameter("namespace")
|
||||
podID := request.PathParameter("pod")
|
||||
|
||||
query := request.Request.URL.Query()
|
||||
logOptions := &corev1.PodLogOptions{}
|
||||
if err := scheme.ParameterCodec.DecodeParameters(query, corev1.SchemeGroupVersion, logOptions); err != nil {
|
||||
api.HandleError(response, request, fmt.Errorf("unable to decode query"))
|
||||
return
|
||||
}
|
||||
|
||||
fw := flushwriter.Wrap(response.ResponseWriter)
|
||||
err := h.gw.GetPodLogs(request.Request.Context(), podNamespace, podID, logOptions, fw)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) PodLogSearch(request *restful.Request, response *restful.Response) {
|
||||
if h.lo == nil {
|
||||
api.HandleError(response, request, fmt.Errorf("logging isn't enabled"))
|
||||
return
|
||||
}
|
||||
|
||||
ns := request.PathParameter("namespace")
|
||||
logQuery, err := loggingv1alpha2.ParseQueryParameter(request)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
// ES log will be filtered by pods and namespace by default.
|
||||
pods, err := h.gw.GetPods(ns, &query.Query{})
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
var podfilter []string
|
||||
namespaceCreateTimeMap := make(map[string]*time.Time)
|
||||
var ar loggingv1alpha2.APIResponse
|
||||
|
||||
for _, p := range pods.Items {
|
||||
pod, ok := p.(*corev1.Pod)
|
||||
if ok {
|
||||
podfilter = append(podfilter, pod.Name)
|
||||
namespaceCreateTimeMap[pod.Namespace] = nil
|
||||
}
|
||||
}
|
||||
|
||||
sf := loggingclient.SearchFilter{
|
||||
NamespaceFilter: namespaceCreateTimeMap,
|
||||
PodFilter: podfilter,
|
||||
PodSearch: stringutils.Split(logQuery.PodSearch, ","),
|
||||
ContainerSearch: stringutils.Split(logQuery.ContainerSearch, ","),
|
||||
ContainerFilter: stringutils.Split(logQuery.ContainerFilter, ","),
|
||||
LogSearch: stringutils.Split(logQuery.LogSearch, ","),
|
||||
Starttime: logQuery.StartTime,
|
||||
Endtime: logQuery.EndTime,
|
||||
}
|
||||
|
||||
noHit := len(namespaceCreateTimeMap) == 0 || len(podfilter) == 0
|
||||
|
||||
if logQuery.Operation == loggingv1alpha2.OperationExport {
|
||||
response.Header().Set(restful.HEADER_ContentType, "text/plain")
|
||||
response.Header().Set("Content-Disposition", "attachment")
|
||||
if noHit {
|
||||
return
|
||||
}
|
||||
|
||||
err = h.lo.ExportLogs(sf, response)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if noHit {
|
||||
ar.Logs = &loggingclient.Logs{}
|
||||
}
|
||||
|
||||
ar, err = h.lo.SearchLogs(sf, logQuery.From, logQuery.Size, logQuery.Sort)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
response.WriteEntity(ar)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 KubeSphere 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 v1alpha1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"kubesphere.io/api/gateway/v1alpha1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/gateway"
|
||||
loggingclient "kubesphere.io/kubesphere/pkg/simple/client/logging"
|
||||
)
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: "gateway.kubesphere.io", Version: "v1alpha1"}
|
||||
|
||||
func AddToContainer(container *restful.Container, options *gateway.Options, cache cache.Cache, client client.Client, factory informers.InformerFactory, k8sClient kubernetes.Interface, loggingClient loggingclient.Client) error {
|
||||
ws := runtime.NewWebService(GroupVersion)
|
||||
|
||||
handler := newHandler(options, cache, client, factory, k8sClient, loggingClient)
|
||||
|
||||
// register gateway apis
|
||||
ws.Route(ws.POST("/namespaces/{namespace}/gateways").
|
||||
To(handler.Create).
|
||||
Doc("Create a gateway for a specified namespace.").
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Param(ws.BodyParameter("gateway", "Gateway specification")).
|
||||
Returns(http.StatusOK, api.StatusOK, v1alpha1.Gateway{}).
|
||||
Reads(v1alpha1.Gateway{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
ws.Route(ws.DELETE("/namespaces/{namespace}/gateways/").
|
||||
To(handler.Delete).
|
||||
Doc("Delete the specified gateway in namespace.").
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
ws.Route(ws.PUT("/namespaces/{namespace}/gateways/").
|
||||
To(handler.Update).
|
||||
Doc("Update gateway for a specified namespace.").
|
||||
Reads(v1alpha1.Gateway{}).
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Param(ws.BodyParameter("gateway", "Gateway specification")).
|
||||
Returns(http.StatusOK, api.StatusOK, v1alpha1.Gateway{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/gateways/").
|
||||
To(handler.Get).
|
||||
Doc("Retrieve gateways details.").
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Returns(http.StatusOK, api.StatusOK, v1alpha1.Gateway{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
|
||||
ws.Route(ws.POST("/namespaces/{namespace}/gateways/{gateway}/upgrade").
|
||||
To(handler.Upgrade).
|
||||
Doc("Upgrade the legacy Project Gateway to the CRD based Gateway.").
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Returns(http.StatusOK, api.StatusOK, v1alpha1.Gateway{}).
|
||||
Reads(v1alpha1.Gateway{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
|
||||
ws.Route(ws.GET("/gateways/").
|
||||
To(handler.List).
|
||||
Doc("List Gateway details.").
|
||||
Returns(http.StatusOK, api.StatusOK, v1alpha1.Gateway{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/gateways/{gateway}/pods").
|
||||
To(handler.ListPods).
|
||||
Doc("Retrieve gateways workload pods.").
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Returns(http.StatusOK, api.StatusOK, v1alpha1.Gateway{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/gateways/{gateway}/pods/{pod}/log").
|
||||
To(handler.PodLog).
|
||||
Doc("Retrieve log of the gateway's pod").
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Param(ws.PathParameter("pod", "the pod name of the gateway")).
|
||||
Returns(http.StatusOK, api.StatusOK, v1alpha1.Gateway{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/gateways/{gateway}/logs").
|
||||
To(handler.PodLogSearch).
|
||||
Doc("Retrieve log of the gateway's pod from ES").
|
||||
Param(ws.PathParameter("namespace", "the watching namespace of the gateway")).
|
||||
Param(ws.PathParameter("gateway", "the name of the gateway")).
|
||||
Returns(http.StatusOK, api.StatusOK, loggingv1alpha2.APIResponse{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GatewayTag}))
|
||||
|
||||
container.Add(ws)
|
||||
return nil
|
||||
}
|
||||
179
pkg/kapis/gateway/v1alpha2/handler.go
Normal file
179
pkg/kapis/gateway/v1alpha2/handler.go
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/klog/v2"
|
||||
"kubesphere.io/api/gateway/v1alpha2"
|
||||
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
)
|
||||
|
||||
const (
|
||||
MasterLabel = "node-role.kubernetes.io/control-plane"
|
||||
SvcNameAnnotation = "gateway.kubesphere.io/service-name"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
cache runtimeclient.Reader
|
||||
}
|
||||
|
||||
func (h *handler) ListIngressClassScopes(req *restful.Request, resp *restful.Response) {
|
||||
currentNs := req.PathParameter("namespace")
|
||||
ctx := req.Request.Context()
|
||||
|
||||
ingressClassScopeList := v1alpha2.IngressClassScopeList{}
|
||||
err := h.cache.List(ctx, &ingressClassScopeList)
|
||||
if err != nil {
|
||||
api.HandleError(resp, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
var ret []v1alpha2.IngressClassScope
|
||||
for _, item := range ingressClassScopeList.Items {
|
||||
namespaces := item.Spec.Scope.Namespaces
|
||||
nsSelector := item.Spec.Scope.NamespaceSelector
|
||||
|
||||
// Specify all namespace
|
||||
if len(namespaces) == 0 && nsSelector == "" {
|
||||
_ = h.setStatus(ctx, &item)
|
||||
ret = append(ret, item)
|
||||
continue
|
||||
}
|
||||
|
||||
// Specify namespaces
|
||||
if len(namespaces) > 0 {
|
||||
for _, n := range namespaces {
|
||||
if n == currentNs {
|
||||
_ = h.setStatus(ctx, &item)
|
||||
ret = append(ret, item)
|
||||
break
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Specify namespaceSelector
|
||||
if nsSelector != "" {
|
||||
nsList := corev1.NamespaceList{}
|
||||
_ = h.cache.List(ctx, &nsList, &runtimeclient.ListOptions{LabelSelector: Selector(nsSelector)})
|
||||
for _, n := range nsList.Items {
|
||||
if n.Name == currentNs {
|
||||
_ = h.setStatus(ctx, &item)
|
||||
ret = append(ret, item)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp.WriteEntity(ret)
|
||||
}
|
||||
|
||||
func Selector(s string) labels.Selector {
|
||||
if selector, err := labels.Parse(s); err != nil {
|
||||
return labels.Everything()
|
||||
} else {
|
||||
return selector
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getMasterNodeIp(ctx context.Context) []string {
|
||||
internalIps := []string{}
|
||||
masters := &corev1.NodeList{}
|
||||
err := h.cache.List(ctx, masters, &runtimeclient.ListOptions{
|
||||
LabelSelector: labels.SelectorFromSet(
|
||||
labels.Set{
|
||||
MasterLabel: "",
|
||||
})})
|
||||
|
||||
if err != nil {
|
||||
klog.Info(err)
|
||||
return internalIps
|
||||
}
|
||||
|
||||
for _, node := range masters.Items {
|
||||
for _, address := range node.Status.Addresses {
|
||||
if address.Type == corev1.NodeInternalIP {
|
||||
internalIps = append(internalIps, address.Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
return internalIps
|
||||
}
|
||||
|
||||
func (h *handler) setStatus(ctx context.Context, ics *v1alpha2.IngressClassScope) (e error) {
|
||||
svcKeyStr, exists := ics.Annotations[SvcNameAnnotation]
|
||||
if !exists {
|
||||
klog.Errorf("Name: %s, Annotation %s not found", ics.Name, SvcNameAnnotation)
|
||||
return nil
|
||||
}
|
||||
|
||||
svcKeyParts := strings.SplitN(svcKeyStr, "/", 2)
|
||||
if len(svcKeyParts) != 2 {
|
||||
klog.Errorf("Name: %s, Invalid %s annotation, should follow the namespace/name format", ics.Name, SvcNameAnnotation)
|
||||
return nil
|
||||
}
|
||||
|
||||
svc := corev1.Service{}
|
||||
key := types.NamespacedName{
|
||||
Namespace: svcKeyParts[0],
|
||||
Name: svcKeyParts[1],
|
||||
}
|
||||
|
||||
if err := h.cache.Get(ctx, key, &svc); err != nil {
|
||||
klog.Errorf("Failed to fetch svc %s, %v", key.String(), err)
|
||||
return err
|
||||
}
|
||||
|
||||
// append selected node ip as loadBalancer ingress ip
|
||||
if svc.Spec.Type != corev1.ServiceTypeLoadBalancer && len(svc.Status.LoadBalancer.Ingress) == 0 {
|
||||
rips := h.getMasterNodeIp(ctx)
|
||||
for _, rip := range rips {
|
||||
gIngress := corev1.LoadBalancerIngress{
|
||||
IP: rip,
|
||||
}
|
||||
svc.Status.LoadBalancer.Ingress = append(svc.Status.LoadBalancer.Ingress, gIngress)
|
||||
}
|
||||
}
|
||||
|
||||
status := unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"loadBalancer": svc.Status.LoadBalancer,
|
||||
"service": svc.Spec.Ports,
|
||||
},
|
||||
}
|
||||
|
||||
target, err := status.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ics.Status.Raw != nil {
|
||||
//merge with origin status
|
||||
patch, err := jsonpatch.CreateMergePatch([]byte(`{}`), target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
modified, err := jsonpatch.MergePatch(ics.Status.Raw, patch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ics.Status.Raw = modified
|
||||
}
|
||||
ics.Status.Raw = target
|
||||
return nil
|
||||
}
|
||||
49
pkg/kapis/gateway/v1alpha2/register.go
Normal file
49
pkg/kapis/gateway/v1alpha2/register.go
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
gatewayv1alpha2 "kubesphere.io/api/gateway/v1alpha2"
|
||||
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/rest"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
GroupName = "gateway.kubesphere.io"
|
||||
Version = "v1alpha2"
|
||||
)
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: Version}
|
||||
|
||||
func NewHandler(cache runtimeclient.Reader) rest.Handler {
|
||||
return &handler{
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFakeHandler() rest.Handler {
|
||||
return &handler{}
|
||||
}
|
||||
|
||||
func (h *handler) AddToContainer(container *restful.Container) error {
|
||||
ws := runtime.NewWebService(GroupVersion)
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/availableingressclassscopes").
|
||||
To(h.ListIngressClassScopes).
|
||||
Doc("List ingressClassScope available for the namespace").
|
||||
Param(ws.PathParameter("namespace", "The specified namespace.")).
|
||||
Returns(http.StatusOK, api.StatusOK, []gatewayv1alpha2.IngressClassScope{}))
|
||||
|
||||
container.Add(ws)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user