diff --git a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/httpserver.go b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/httpserver.go new file mode 100644 index 0000000000..21237eae37 --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/httpserver.go @@ -0,0 +1,30 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * 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 httpsvr + +import ( + "github.com/emicklei/go-restful" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +// HttpServerClient http server client +type HttpServerClient struct { + Mgr manager.Manager +} + +func InitRouters(ws *restful.WebService, httpServerClient *HttpServerClient) { + ws.Route(ws.GET("/api/v1/ingresss").To(httpServerClient.listIngress)) + ws.Route(ws.GET("/api/v1/portpools").To(httpServerClient.listPortPool)) + ws.Route(ws.GET("/api/v1/listeners/{condition}/{namespace}/{name}").To(httpServerClient.listListener)) + +} diff --git a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/ingress.go b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/ingress.go new file mode 100644 index 0000000000..9090bb0783 --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/ingress.go @@ -0,0 +1,32 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * 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 httpsvr + +import ( + "context" + + "github.com/emicklei/go-restful" + + "github.com/Tencent/bk-bcs/bcs-common/common/blog" + networkextensionv1 "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/kubernetes/apis/networkextension/v1" +) + +func (h *HttpServerClient) listIngress(request *restful.Request, response *restful.Response) { + ingressList := &networkextensionv1.IngressList{} + if err := h.Mgr.GetClient().List(context.Background(), ingressList); err != nil { + blog.Errorf("list ext ingresses failed when collect metrics, err %s", err.Error()) + return + } + data := CreateResponseData(nil, "success", ingressList) + _, _ = response.Write([]byte(data)) +} diff --git a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/listener.go b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/listener.go new file mode 100644 index 0000000000..e0fe5060dd --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/listener.go @@ -0,0 +1,92 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * 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 httpsvr + +import ( + "context" + "github.com/Tencent/bk-bcs/bcs-common/common/blog" + networkextensionv1 "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/kubernetes/apis/networkextension/v1" + "github.com/emicklei/go-restful" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8slabels "k8s.io/apimachinery/pkg/labels" + k8sapitypes "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (h *HttpServerClient) listListener(request *restful.Request, response *restful.Response) { + + var data string + switch request.PathParameter("condition") { + case "ingress": + ingress := &networkextensionv1.Ingress{} + if err := h.Mgr.GetClient().Get(context.Background(), k8sapitypes.NamespacedName{ + Name: request.PathParameter("name"), + Namespace: request.PathParameter("namespace"), + }, ingress); err != nil { + if k8serrors.IsNotFound(err) { + blog.Infof("ingress %s/%s not found", request.PathParameter("namespace"), request.PathParameter("name")) + data = CreateResponseData(err, "failed", nil) + break + } + } + existedListenerList := &networkextensionv1.ListenerList{} + selector, err := k8smetav1.LabelSelectorAsSelector(k8smetav1.SetAsLabelSelector(k8slabels.Set(map[string]string{ + ingress.Name: networkextensionv1.LabelValueForIngressName, + networkextensionv1.LabelKeyForIsSegmentListener: networkextensionv1.LabelValueFalse, + }))) + err = h.Mgr.GetClient().List(context.TODO(), existedListenerList, &client.ListOptions{ + Namespace: ingress.Namespace, + LabelSelector: selector}) + if err != nil { + blog.Errorf("list listeners filter by ingress %s failed, err %s", + request.PathParameter("name"), err.Error()) + data = CreateResponseData(err, "failed", nil) + break + } + data = CreateResponseData(nil, "success", existedListenerList) + case "portpool": + portPool := &networkextensionv1.PortPool{} + if err := h.Mgr.GetClient().Get(context.Background(), k8sapitypes.NamespacedName{ + Name: request.PathParameter("name"), + Namespace: request.PathParameter("namespace"), + }, portPool); err != nil { + if k8serrors.IsNotFound(err) { + blog.Infof("portpool %s/%s not found", request.PathParameter("namespace"), request.PathParameter("name")) + data = CreateResponseData(err, "failed", nil) + break + } + } + result := make(map[string]*networkextensionv1.ListenerList, 0) + for i := range portPool.Spec.PoolItems { + existedListenerList := &networkextensionv1.ListenerList{} + selector, err := k8smetav1.LabelSelectorAsSelector(k8smetav1.SetAsLabelSelector(k8slabels.Set(map[string]string{ + portPool.Spec.PoolItems[i].ItemName: networkextensionv1.LabelValueForPortPoolItemName, + networkextensionv1.LabelKeyForIsSegmentListener: networkextensionv1.LabelValueFalse, + }))) + err = h.Mgr.GetClient().List(context.TODO(), existedListenerList, &client.ListOptions{ + Namespace: request.PathParameter("namespace"), + LabelSelector: selector}) + if err != nil { + blog.Errorf("list listeners filter by port pool item %s failed, err %s", + portPool.Spec.PoolItems[i].ItemName, err.Error()) + data = CreateResponseData(err, "failed", nil) + break + } + result[portPool.Spec.PoolItems[i].ItemName] = existedListenerList + } + data = CreateResponseData(nil, "success", result) + } + + _, _ = response.Write([]byte(data)) +} diff --git a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/portpool.go b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/portpool.go new file mode 100644 index 0000000000..3cbc81a23b --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/portpool.go @@ -0,0 +1,31 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * 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 httpsvr + +import ( + "context" + + "github.com/emicklei/go-restful" + + "github.com/Tencent/bk-bcs/bcs-common/common/blog" + networkextensionv1 "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/kubernetes/apis/networkextension/v1" +) + +func (h *HttpServerClient) listPortPool(request *restful.Request, response *restful.Response) { + poolList := &networkextensionv1.PortPoolList{} + if err := h.Mgr.GetClient().List(context.Background(), poolList); err != nil { + blog.Errorf("list port pool failed when collect metrics, err %s", err.Error()) + } + data := CreateResponseData(nil, "success", poolList) + _, _ = response.Write([]byte(data)) +} diff --git a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/util.go b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/util.go new file mode 100644 index 0000000000..9126af1316 --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr/util.go @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * 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 httpsvr + +import ( + "errors" + + "github.com/Tencent/bk-bcs/bcs-common/common" + bhttp "github.com/Tencent/bk-bcs/bcs-common/common/http" +) + +// CreateResponseData common response +func CreateResponseData(err error, msg string, data interface{}) string { + var rpyErr error + if err != nil { + rpyErr = bhttp.InternalError(common.BcsErrMesosSchedCommon, msg) + } else { + rpyErr = errors.New(bhttp.GetRespone(common.BcsSuccess, common.BcsSuccessStr, data)) + } + + // blog.V(3).Infof("createRespone: %s", rpyErr.Error()) + + return rpyErr.Error() +} diff --git a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/option/option.go b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/option/option.go index 2d52b40374..4c0d1cb868 100644 --- a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/option/option.go +++ b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/option/option.go @@ -69,4 +69,23 @@ type ControllerOption struct { // ConflictCheckOpen if false, skip all conflict checking about ingress and port pool ConflictCheckOpen bool + + HttpServerPort uint + + Conf Conf + + ServCert ServCert +} +type Conf struct { + ServCert ServCert + InsecureAddress string + InsecurePort uint + VerifyClientTLS bool +} +type ServCert struct { + CAFile string + CertFile string + KeyFile string + CertPasswd string + IsSSL bool } diff --git a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/main.go b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/main.go index b32e162819..ddc56d4289 100644 --- a/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/main.go +++ b/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/main.go @@ -28,8 +28,10 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/manager" "github.com/Tencent/bk-bcs/bcs-common/common/blog" + "github.com/Tencent/bk-bcs/bcs-common/common/http/httpserver" "github.com/Tencent/bk-bcs/bcs-common/common/http/ipv6server" clbv1 "github.com/Tencent/bk-bcs/bcs-k8s/kubedeprecated/apis/clb/v1" ingressctrl "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/ingresscontroller" @@ -44,6 +46,7 @@ import ( "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/constant" "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/eventer" "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/generator" + "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/httpsvr" "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/option" "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/portpoolcache" "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-network/bcs-ingress-controller/internal/webhookserver" @@ -106,6 +109,8 @@ func main() { flag.BoolVar(&opts.ConflictCheckOpen, "conflict_check_open", true, "if false, "+ "skip all conflict checking about ingress and port pool") + flag.UintVar(&opts.HttpServerPort, "port", 8082, "port for ingress controller http server") + flag.Parse() opts.Verbosity = int32(verbosity) @@ -334,7 +339,15 @@ func main() { metrics.Registry.MustRegister(collector) blog.Infof("starting manager") - if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + + err = initHttpServer(opts, mgr) + if err != nil { + blog.Errorf("init http server failed: %v", err.Error()) + os.Exit(1) + } + + blog.Infof("starting http server") + if err = mgr.Start(ctrl.SetupSignalHandler()); err != nil { blog.Errorf("problem running manager, err %s", err.Error()) os.Exit(1) } @@ -364,3 +377,28 @@ func runPrometheusMetrics(op *option.ControllerOption) { } }() } + +//initHttpServer init ingress controller http server +func initHttpServer(op *option.ControllerOption, mgr manager.Manager) error { + server := httpserver.NewHttpServer(op.HttpServerPort, op.Address, "") + if op.Conf.ServCert.IsSSL { + server.SetSsl(op.Conf.ServCert.CAFile, op.Conf.ServCert.CertFile, op.Conf.ServCert.KeyFile, + op.Conf.ServCert.CertPasswd) + } + + server.SetInsecureServer(op.Conf.InsecureAddress, op.Conf.InsecurePort) + ws := server.NewWebService("/ingresscontroller", nil) + httpServerClient := &httpsvr.HttpServerClient{ + mgr, + } + httpsvr.InitRouters(ws, httpServerClient) + + router := server.GetRouter() + webContainer := server.GetWebContainer() + router.Handle("/ingresscontroller/{sub_path:.*}", webContainer) + if err := server.ListenAndServeMux(op.Conf.VerifyClientTLS); err != nil { + return fmt.Errorf("http ListenAndServe error %s", err.Error()) + } + return nil + +}