add controllers
change kiali mux to go-restful add knative add health api
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"kubesphere.io/kubesphere/pkg/controller/destinationrule"
|
||||
"kubesphere.io/kubesphere/pkg/controller/virtualservice"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/simple/controller/namespace"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"time"
|
||||
@@ -35,7 +35,7 @@ func AddControllers(mgr manager.Manager, cfg *rest.Config, stopCh <-chan struct{
|
||||
return err
|
||||
}
|
||||
|
||||
informerFactory := informers.SharedInformerFactory()
|
||||
informerFactory := informers.NewSharedInformerFactory(kubeClient, defaultResync)
|
||||
istioInformer := istioinformers.NewSharedInformerFactory(istioclient, defaultResync)
|
||||
|
||||
servicemeshclient, err := servicemeshclientset.NewForConfig(cfg)
|
||||
|
||||
@@ -30,14 +30,25 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var metricsAddr, kubeConfigPath, masterURL string
|
||||
var (
|
||||
masterURL string
|
||||
kubeconfig string
|
||||
metricsAddr string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&masterURL, "master-url", "", "only need if out of cluster")
|
||||
flag.StringVar(&kubeconfig, "kubeconfig", "", "only need if out of cluster")
|
||||
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
logf.SetLogger(logf.ZapLogger(false))
|
||||
log := logf.Log.WithName("controller-manager")
|
||||
|
||||
kubeConfig, err := clientcmd.BuildConfigFromFlags(masterURL, kubeConfigPath)
|
||||
cfg, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to build kubeconfig")
|
||||
os.Exit(1)
|
||||
@@ -46,7 +57,7 @@ func main() {
|
||||
stopCh := signals.SetupSignalHandler()
|
||||
|
||||
log.Info("setting up manager")
|
||||
mgr, err := manager.New(kubeConfig, manager.Options{})
|
||||
mgr, err := manager.New(cfg, manager.Options{})
|
||||
if err != nil {
|
||||
log.Error(err, "unable to set up overall controller manager")
|
||||
os.Exit(1)
|
||||
@@ -64,7 +75,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := app.AddControllers(mgr, kubeConfig, stopCh); err != nil {
|
||||
if err := app.AddControllers(mgr, cfg, stopCh); err != nil {
|
||||
log.Error(err, "unable to register controllers to the manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -122,11 +122,12 @@ func initializeESClientConfig() {
|
||||
db := mysql.Client()
|
||||
if !db.HasTable(&logging.OutputDBBinding{}) {
|
||||
// Panic
|
||||
log.Fatal("Flyway migration is not completed")
|
||||
log.Print("Flyway migration is not completed")
|
||||
}
|
||||
|
||||
err := db.Find(&outputs).Error
|
||||
if err != nil {
|
||||
log.Printf("get logging config failed. Error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
docker build -f build/ks-apiserver/Dockerfile -t kubespheredev/ks-apiserver:latest .
|
||||
docker build -f build/ks-iam/Dockerfile -t kubespheredev/ks-iam:latest .
|
||||
|
||||
docker build -f build/controller-manager/Dockerfile -t kubespheredev/controller-manager:latest .
|
||||
docker build -f build/controller-manager/Dockerfile -t kubespheredev/ks-controller-manager:latest .
|
||||
|
||||
@@ -68,8 +68,8 @@ func addWebService(c *restful.Container) error {
|
||||
To(metrics.GetWorkloadMetrics).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get workload metrics from a specific namespace").
|
||||
Param(webservice.PathParameter("namespace", "name of the namespace")).
|
||||
Param(webservice.PathParameter("workload", "name of the workload")).
|
||||
Param(webservice.PathParameter("namespace", "name of the namespace").Required(true)).
|
||||
Param(webservice.PathParameter("workload", "name of the workload").Required(true)).
|
||||
Param(webservice.QueryParameter("filters[]", "type of metrics type, e.g. request_count, request_duration, request_error_count")).
|
||||
Param(webservice.QueryParameter("queryTime", "from which UNIX time to extract metrics")).
|
||||
Param(webservice.QueryParameter("duration", "metrics duration, in seconds")).
|
||||
@@ -87,7 +87,7 @@ func addWebService(c *restful.Container) error {
|
||||
To(metrics.GetNamespaceMetrics).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get workload metrics from a specific namespace").
|
||||
Param(webservice.PathParameter("namespace", "name of the namespace")).
|
||||
Param(webservice.PathParameter("namespace", "name of the namespace").Required(true)).
|
||||
Param(webservice.QueryParameter("filters[]", "type of metrics type, e.g. request_count, request_duration, request_error_count")).
|
||||
Param(webservice.QueryParameter("queryTime", "from which UNIX time to extract metrics")).
|
||||
Param(webservice.QueryParameter("duration", "metrics duration, in seconds")).
|
||||
@@ -105,7 +105,7 @@ func addWebService(c *restful.Container) error {
|
||||
To(metrics.GetNamespaceGraph).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get service graph for a specific namespace").
|
||||
Param(webservice.PathParameter("namespace", "name of a namespace")).
|
||||
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
|
||||
Param(webservice.QueryParameter("graphType", "type of the generated service graph, eg. ")).
|
||||
Param(webservice.QueryParameter("groupBy", "group nodes by kind")).
|
||||
Param(webservice.QueryParameter("queryTime", "from which time point, default now")).
|
||||
@@ -118,7 +118,7 @@ func addWebService(c *restful.Container) error {
|
||||
To(metrics.GetNamespacesGraph).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get service graph for a specific namespace").
|
||||
Param(webservice.PathParameter("namespace", "name of a namespace")).
|
||||
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
|
||||
Param(webservice.QueryParameter("graphType", "type of the generated service graph, eg. ")).
|
||||
Param(webservice.QueryParameter("groupBy", "group nodes by kind")).
|
||||
Param(webservice.QueryParameter("queryTime", "from which time point, default now")).
|
||||
@@ -126,6 +126,39 @@ func addWebService(c *restful.Container) error {
|
||||
Param(webservice.QueryParameter("namespaces", "names of namespaces")).
|
||||
Writes(errors.Error{})).Produces(restful.MIME_JSON)
|
||||
|
||||
// Get workloads health
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/workloads/{workload}/health").
|
||||
To(metrics.GetWorkloadHealth).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get workload health").
|
||||
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
|
||||
Param(webservice.PathParameter("workload", "workload name").Required(true)).
|
||||
Param(webservice.QueryParameter("rateInterval", "the rate interval used for fetching error rate").DefaultValue("10m").Required(true)).
|
||||
Param(webservice.QueryParameter("queryTime", "the time to use for query")).
|
||||
Writes(errors.Error{})).Produces(restful.MIME_JSON)
|
||||
|
||||
// Get app health
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/apps/{app}/health").
|
||||
To(metrics.GetAppHealth).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get workload health").
|
||||
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
|
||||
Param(webservice.PathParameter("app", "app name").Required(true)).
|
||||
Param(webservice.QueryParameter("rateInterval", "the rate interval used for fetching error rate").DefaultValue("10m").Required(true)).
|
||||
Param(webservice.QueryParameter("queryTime", "the time to use for query")).
|
||||
Writes(errors.Error{})).Produces(restful.MIME_JSON)
|
||||
|
||||
// Get service health
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/services/{service}/health").
|
||||
To(metrics.GetServiceHealth).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Doc("Get workload health").
|
||||
Param(webservice.PathParameter("namespace", "name of a namespace").Required(true)).
|
||||
Param(webservice.PathParameter("service", "service name").Required(true)).
|
||||
Param(webservice.QueryParameter("rateInterval", "the rate interval used for fetching error rate").DefaultValue("10m").Required(true)).
|
||||
Param(webservice.QueryParameter("queryTime", "the time to use for query")).
|
||||
Writes(errors.Error{})).Produces(restful.MIME_JSON)
|
||||
|
||||
c.Add(webservice)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ApiRootPath = "/apis"
|
||||
ApiRootPath = "/kapis"
|
||||
)
|
||||
|
||||
// container holds all webservice of apiserver
|
||||
|
||||
@@ -48,3 +48,18 @@ func GetNamespaceGraph(request *restful.Request, response *restful.Response) {
|
||||
func GetNamespacesGraph(request *restful.Request, response *restful.Response) {
|
||||
handlers.GraphNamespaces(request, response)
|
||||
}
|
||||
|
||||
// Get workload health
|
||||
func GetWorkloadHealth(request *restful.Request, response *restful.Response) {
|
||||
handlers.WorkloadHealth(request, response)
|
||||
}
|
||||
|
||||
// Get app health
|
||||
func GetAppHealth(request *restful.Request, response *restful.Response) {
|
||||
handlers.AppHealth(request, response)
|
||||
}
|
||||
|
||||
// Get service health
|
||||
func GetServiceHealth(request *restful.Request, response *restful.Response) {
|
||||
handlers.ServiceHealth(request, response)
|
||||
}
|
||||
|
||||
@@ -139,10 +139,6 @@ func (v *DestinationRuleController) Run(workers int, stopCh <-chan struct{}) {
|
||||
go wait.Until(v.worker, v.workerLoopPeriod, stopCh)
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
}()
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
@@ -222,9 +218,9 @@ func (v *DestinationRuleController) syncService(key string) error {
|
||||
}
|
||||
|
||||
subset := v1alpha3.Subset{
|
||||
Name: util.NormalizeVersionName(name),
|
||||
Name: util.NormalizeVersionName(version),
|
||||
Labels: map[string]string{
|
||||
util.VersionLabel: name,
|
||||
util.VersionLabel: version,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -239,10 +235,15 @@ func (v *DestinationRuleController) syncService(key string) error {
|
||||
Name: service.Name,
|
||||
Labels: service.Labels,
|
||||
},
|
||||
Spec: v1alpha3.DestinationRuleSpec{
|
||||
Host: name,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
log.Error(err, "Couldn't get destinationrule for service", "key", key)
|
||||
return err
|
||||
}
|
||||
log.Error(err, "Couldn't get destinationrule for service", "key", key)
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
createDestinationRule := len(currentDestinationRule.Spec.Subsets) == 0
|
||||
|
||||
@@ -18,6 +18,7 @@ func getAppNameByStrategy(strategy *v1alpha2.Strategy) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// if virtualservice not specified with port number, then fill with service first port
|
||||
func fillDestinationPort(vs *v1alpha3.VirtualService, service *v1.Service) error {
|
||||
|
||||
if len(service.Spec.Ports) == 0 {
|
||||
@@ -27,14 +28,22 @@ func fillDestinationPort(vs *v1alpha3.VirtualService, service *v1.Service) error
|
||||
// fill http port
|
||||
for i := range vs.Spec.Http {
|
||||
for j := range vs.Spec.Http[i].Route {
|
||||
vs.Spec.Http[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
|
||||
if vs.Spec.Http[i].Route[j].Destination.Port.Number == 0 {
|
||||
vs.Spec.Http[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
|
||||
}
|
||||
}
|
||||
|
||||
if vs.Spec.Http[i].Mirror != nil && vs.Spec.Http[i].Mirror.Port.Number == 0 {
|
||||
vs.Spec.Http[i].Mirror.Port.Number = uint32(service.Spec.Ports[0].Port)
|
||||
}
|
||||
}
|
||||
|
||||
// fill tcp port
|
||||
for i := range vs.Spec.Tcp {
|
||||
for j := range vs.Spec.Tcp[i].Route {
|
||||
vs.Spec.Tcp[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
|
||||
if vs.Spec.Tcp[i].Route[j].Destination.Port.Number == 0 {
|
||||
vs.Spec.Tcp[i].Route[j].Destination.Port.Number = uint32(service.Spec.Ports[0].Port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ const (
|
||||
// resource with these following labels considered as part of servicemesh
|
||||
var ApplicationLabels = [...]string{
|
||||
ApplicationNameLabel,
|
||||
ApplicationVersionLabel,
|
||||
ServiceMeshEnabledLabel,
|
||||
AppLabel,
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ func NewVirtualServiceController(serviceInformer coreinformers.ServiceInformer,
|
||||
}
|
||||
|
||||
func (v *VirtualServiceController) Start(stopCh <-chan struct{}) error {
|
||||
v.Run(5, stopCh)
|
||||
v.Run(1, stopCh)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -147,10 +147,6 @@ func (v *VirtualServiceController) Run(workers int, stopCh <-chan struct{}) {
|
||||
go wait.Until(v.worker, v.workerLoopPeriod, stopCh)
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
}()
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
@@ -202,7 +198,6 @@ func (v *VirtualServiceController) syncService(key string) error {
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -278,9 +273,7 @@ func (v *VirtualServiceController) syncService(key string) error {
|
||||
if len(vs.Spec.Http) > 0 || len(vs.Spec.Tcp) > 0 {
|
||||
_, err := v.virtualServiceClient.NetworkingV1alpha3().VirtualServices(namespace).Create(vs)
|
||||
if err != nil {
|
||||
|
||||
v.eventRecorder.Eventf(vs, v1.EventTypeWarning, "FailedToCreateVirtualService", "Failed to create virtualservice for service %v/%v: %v", service.Namespace, service.Name, err)
|
||||
|
||||
log.Error(err, "create virtualservice for service failed.", "service", service)
|
||||
return err
|
||||
}
|
||||
@@ -288,7 +281,6 @@ func (v *VirtualServiceController) syncService(key string) error {
|
||||
log.Info("service doesn't have a tcp port.")
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -328,7 +320,6 @@ func (v *VirtualServiceController) addDestinationRule(obj interface{}) {
|
||||
|
||||
func (v *VirtualServiceController) deleteStrategy(obj interface{}) {
|
||||
// nothing to do right now
|
||||
|
||||
}
|
||||
|
||||
func (v *VirtualServiceController) handleErr(err error, key interface{}) {
|
||||
@@ -343,7 +334,7 @@ func (v *VirtualServiceController) handleErr(err error, key interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
log.V(0).Info("Dropping service %q out of the queue: %v", "key", key, "error", err)
|
||||
log.V(4).Info("Dropping service out of the queue.", "key", key, "error", err)
|
||||
v.queue.Forget(key)
|
||||
utilruntime.HandleError(err)
|
||||
}
|
||||
|
||||
@@ -20,13 +20,10 @@ package k8s
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
@@ -37,10 +34,12 @@ var (
|
||||
k8sClient *kubernetes.Clientset
|
||||
k8sClientOnce sync.Once
|
||||
KubeConfig *rest.Config
|
||||
masterURL string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&kubeConfigFile, "kubeconfig", fmt.Sprintf("%s/.kube/config", os.Getenv("HOME")), "path to kubeconfig file")
|
||||
flag.StringVar(&kubeConfigFile, "kubeconfig", "", "path to kubeconfig file")
|
||||
flag.StringVar(&masterURL, "master-url","", "kube-apiserver url, only needed when out of cluster")
|
||||
}
|
||||
|
||||
func Client() *kubernetes.Clientset {
|
||||
@@ -63,18 +62,8 @@ func Client() *kubernetes.Clientset {
|
||||
|
||||
func Config() (kubeConfig *rest.Config, err error) {
|
||||
|
||||
if kubeConfigFile == "" {
|
||||
if env := os.Getenv("KUBECONFIG"); env != "" {
|
||||
kubeConfigFile = env
|
||||
} else {
|
||||
if home, err := homedir.Dir(); err == nil {
|
||||
kubeConfigFile = fmt.Sprintf("%s/.kube/config", home)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = os.Stat(kubeConfigFile); err == nil {
|
||||
kubeConfig, err = clientcmd.BuildConfigFromFlags("", kubeConfigFile)
|
||||
kubeConfig, err = clientcmd.BuildConfigFromFlags(masterURL, kubeConfigFile)
|
||||
} else {
|
||||
kubeConfig, err = rest.InClusterConfig()
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ package namespace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/golang/glog"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -36,6 +37,8 @@ import (
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
)
|
||||
|
||||
var log = logf.Log.WithName("namespace-controller")
|
||||
|
||||
const threadiness = 2
|
||||
|
||||
var (
|
||||
@@ -54,18 +57,18 @@ type NamespaceController struct {
|
||||
}
|
||||
|
||||
func NewNamespaceController(
|
||||
kubeclientset kubernetes.Interface,
|
||||
clientset kubernetes.Interface,
|
||||
namespaceInformer coreinformers.NamespaceInformer,
|
||||
roleInformer rbacinformers.RoleInformer) *NamespaceController {
|
||||
|
||||
controller := &NamespaceController{
|
||||
clientset: kubeclientset,
|
||||
clientset: clientset,
|
||||
namespaceInformer: namespaceInformer,
|
||||
roleInformer: roleInformer,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespaces"),
|
||||
}
|
||||
|
||||
glog.Info("setting up event handlers")
|
||||
log.V(3).Info("setting up event handlers")
|
||||
|
||||
namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: controller.handleObject,
|
||||
@@ -86,29 +89,24 @@ func NewNamespaceController(
|
||||
}
|
||||
|
||||
func (c *NamespaceController) Start(stopCh <-chan struct{}) error {
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.workqueue.ShutDown()
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.workqueue.ShutDown()
|
||||
|
||||
// Start the informer factories to begin populating the informer caches
|
||||
glog.Info("starting namespace controller")
|
||||
log.V(3).Info("starting namespace controller")
|
||||
defer glog.Info("shutting down namespace controller")
|
||||
|
||||
// Wait for the caches to be synced before starting workers
|
||||
glog.Info("waiting for informer caches to sync")
|
||||
if ok := cache.WaitForCacheSync(stopCh, c.namespaceInformer.Informer().HasSynced, c.roleInformer.Informer().HasSynced); !ok {
|
||||
glog.Fatalf("controller exit with error: failed to wait for caches to sync")
|
||||
}
|
||||
// Wait for the caches to be synced before starting workers
|
||||
log.Info("waiting for informer caches to sync")
|
||||
if ok := cache.WaitForCacheSync(stopCh, c.namespaceInformer.Informer().HasSynced, c.roleInformer.Informer().HasSynced); !ok {
|
||||
glog.Fatalf("controller exit with error: failed to wait for caches to sync")
|
||||
}
|
||||
|
||||
glog.Info("starting workers")
|
||||
log.V(3).Info("starting workers")
|
||||
for i := 0; i < threadiness; i++ {
|
||||
go wait.Until(c.runWorker, time.Second, stopCh)
|
||||
}
|
||||
|
||||
for i := 0; i < threadiness; i++ {
|
||||
go wait.Until(c.runWorker, time.Second, stopCh)
|
||||
}
|
||||
|
||||
glog.Info("started workers")
|
||||
<-stopCh
|
||||
glog.Info("shutting down workers")
|
||||
}()
|
||||
<-stopCh
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -142,7 +140,7 @@ func (c *NamespaceController) processNextWorkItem() bool {
|
||||
}
|
||||
|
||||
c.workqueue.Forget(obj)
|
||||
glog.Infof("successfully namespace synced '%s'", namespace)
|
||||
log.V(4).Info("successfully namespace synced ", "namespace", namespace)
|
||||
return nil
|
||||
}(obj)
|
||||
|
||||
|
||||
105
vendor/github.com/kiali/kiali/handlers/health.go
generated
vendored
105
vendor/github.com/kiali/kiali/handlers/health.go
generated
vendored
@@ -1,10 +1,10 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"github.com/kiali/kiali/business"
|
||||
@@ -15,25 +15,25 @@ import (
|
||||
const defaultHealthRateInterval = "10m"
|
||||
|
||||
// NamespaceHealth is the API handler to get app-based health of every services in the given namespace
|
||||
func NamespaceHealth(w http.ResponseWriter, r *http.Request) {
|
||||
func NamespaceHealth(request *restful.Request, response *restful.Response) {
|
||||
// Get business layer
|
||||
business, err := business.Get()
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
p := namespaceHealthParams{}
|
||||
if ok, err := p.extract(r); !ok {
|
||||
if ok, err := p.extract(request); !ok {
|
||||
// Bad request
|
||||
RespondWithError(w, http.StatusBadRequest, err)
|
||||
RespondWithError(response.ResponseWriter, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Adjust rate interval
|
||||
rateInterval, err := adjustRateInterval(business, p.Namespace, p.RateInterval, p.QueryTime)
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -41,86 +41,86 @@ func NamespaceHealth(w http.ResponseWriter, r *http.Request) {
|
||||
case "app":
|
||||
health, err := business.Health.GetNamespaceAppHealth(p.Namespace, rateInterval, p.QueryTime)
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Error while fetching app health: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Error while fetching app health: "+err.Error())
|
||||
return
|
||||
}
|
||||
RespondWithJSON(w, http.StatusOK, health)
|
||||
RespondWithJSON(response.ResponseWriter, http.StatusOK, health)
|
||||
case "service":
|
||||
health, err := business.Health.GetNamespaceServiceHealth(p.Namespace, rateInterval, p.QueryTime)
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Error while fetching service health: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Error while fetching service health: "+err.Error())
|
||||
return
|
||||
}
|
||||
RespondWithJSON(w, http.StatusOK, health)
|
||||
RespondWithJSON(response.ResponseWriter, http.StatusOK, health)
|
||||
case "workload":
|
||||
health, err := business.Health.GetNamespaceWorkloadHealth(p.Namespace, rateInterval, p.QueryTime)
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Error while fetching workload health: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Error while fetching workload health: "+err.Error())
|
||||
return
|
||||
}
|
||||
RespondWithJSON(w, http.StatusOK, health)
|
||||
RespondWithJSON(response.ResponseWriter, http.StatusOK, health)
|
||||
}
|
||||
}
|
||||
|
||||
// AppHealth is the API handler to get health of a single app
|
||||
func AppHealth(w http.ResponseWriter, r *http.Request) {
|
||||
func AppHealth(request *restful.Request, response *restful.Response) {
|
||||
business, err := business.Get()
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
p := appHealthParams{}
|
||||
p.extract(r)
|
||||
p.extract(request)
|
||||
rateInterval, err := adjustRateInterval(business, p.Namespace, p.RateInterval, p.QueryTime)
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
health, err := business.Health.GetAppHealth(p.Namespace, p.App, rateInterval, p.QueryTime)
|
||||
handleHealthResponse(w, health, err)
|
||||
handleHealthResponse(response.ResponseWriter, health, err)
|
||||
}
|
||||
|
||||
// WorkloadHealth is the API handler to get health of a single workload
|
||||
func WorkloadHealth(w http.ResponseWriter, r *http.Request) {
|
||||
func WorkloadHealth(request *restful.Request, response *restful.Response) {
|
||||
business, err := business.Get()
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
p := workloadHealthParams{}
|
||||
p.extract(r)
|
||||
p.extract(request)
|
||||
rateInterval, err := adjustRateInterval(business, p.Namespace, p.RateInterval, p.QueryTime)
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
return
|
||||
}
|
||||
p.RateInterval = rateInterval
|
||||
|
||||
health, err := business.Health.GetWorkloadHealth(p.Namespace, p.Workload, rateInterval, p.QueryTime)
|
||||
handleHealthResponse(w, health, err)
|
||||
handleHealthResponse(response.ResponseWriter, health, err)
|
||||
}
|
||||
|
||||
// ServiceHealth is the API handler to get health of a single service
|
||||
func ServiceHealth(w http.ResponseWriter, r *http.Request) {
|
||||
func ServiceHealth(request *restful.Request, response *restful.Response) {
|
||||
business, err := business.Get()
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Services initialization error: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
p := serviceHealthParams{}
|
||||
p.extract(r)
|
||||
p.extract(request)
|
||||
rateInterval, err := adjustRateInterval(business, p.Namespace, p.RateInterval, p.QueryTime)
|
||||
if err != nil {
|
||||
RespondWithError(w, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
RespondWithError(response.ResponseWriter, http.StatusInternalServerError, "Adjust rate interval error: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
health, err := business.Health.GetServiceHealth(p.Namespace, p.Service, rateInterval, p.QueryTime)
|
||||
handleHealthResponse(w, health, err)
|
||||
handleHealthResponse(response.ResponseWriter, health, err)
|
||||
}
|
||||
|
||||
func handleHealthResponse(w http.ResponseWriter, health interface{}, err error) {
|
||||
@@ -152,14 +152,12 @@ type baseHealthParams struct {
|
||||
QueryTime time.Time
|
||||
}
|
||||
|
||||
func (p *baseHealthParams) baseExtract(r *http.Request, vars map[string]string) {
|
||||
func (p *baseHealthParams) baseExtract(request *restful.Request) {
|
||||
p.RateInterval = defaultHealthRateInterval
|
||||
p.QueryTime = util.Clock.Now()
|
||||
queryParams := r.URL.Query()
|
||||
if rateIntervals, ok := queryParams["rateInterval"]; ok && len(rateIntervals) > 0 {
|
||||
p.RateInterval = rateIntervals[0]
|
||||
}
|
||||
p.Namespace = vars["namespace"]
|
||||
|
||||
p.RateInterval = request.QueryParameter("rateInterval")
|
||||
p.Namespace = request.PathParameters()["namespace"]
|
||||
}
|
||||
|
||||
// namespaceHealthParams holds the path and query parameters for NamespaceHealth
|
||||
@@ -175,19 +173,17 @@ type namespaceHealthParams struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
func (p *namespaceHealthParams) extract(r *http.Request) (bool, string) {
|
||||
vars := mux.Vars(r)
|
||||
p.baseExtract(r, vars)
|
||||
func (p *namespaceHealthParams) extract(request *restful.Request) (bool, string) {
|
||||
p.baseExtract(request)
|
||||
p.Type = "app"
|
||||
queryParams := r.URL.Query()
|
||||
if healthTypes, ok := queryParams["type"]; ok && len(healthTypes) > 0 {
|
||||
if healthTypes[0] != "app" && healthTypes[0] != "service" && healthTypes[0] != "workload" {
|
||||
// Bad request
|
||||
return false, "Bad request, query parameter 'type' must be one of ['app','service','workload']"
|
||||
}
|
||||
p.Type = healthTypes[0]
|
||||
tp := request.QueryParameter("type")
|
||||
switch tp {
|
||||
case "app", "service", "workload":
|
||||
p.Type = tp
|
||||
return true, ""
|
||||
}
|
||||
return true, ""
|
||||
|
||||
return false, "Bad request, query parameter 'type' must be one of ['app','service','workload']"
|
||||
}
|
||||
|
||||
// appHealthParams holds the path and query parameters for AppHealth
|
||||
@@ -201,10 +197,9 @@ type appHealthParams struct {
|
||||
App string `json:"app"`
|
||||
}
|
||||
|
||||
func (p *appHealthParams) extract(r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
p.baseExtract(r, vars)
|
||||
p.App = vars["app"]
|
||||
func (p *appHealthParams) extract(request *restful.Request) {
|
||||
p.baseExtract(request)
|
||||
p.App = request.PathParameter("app")
|
||||
}
|
||||
|
||||
// serviceHealthParams holds the path and query parameters for ServiceHealth
|
||||
@@ -218,10 +213,9 @@ type serviceHealthParams struct {
|
||||
Service string `json:"service"`
|
||||
}
|
||||
|
||||
func (p *serviceHealthParams) extract(r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
p.baseExtract(r, vars)
|
||||
p.Service = vars["service"]
|
||||
func (p *serviceHealthParams) extract(request *restful.Request) {
|
||||
p.baseExtract(request)
|
||||
p.Service = request.PathParameter("service")
|
||||
}
|
||||
|
||||
// workloadHealthParams holds the path and query parameters for WorkloadHealth
|
||||
@@ -235,10 +229,9 @@ type workloadHealthParams struct {
|
||||
Workload string `json:"workload"`
|
||||
}
|
||||
|
||||
func (p *workloadHealthParams) extract(r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
p.baseExtract(r, vars)
|
||||
p.Workload = vars["workload"]
|
||||
func (p *workloadHealthParams) extract(request *restful.Request) {
|
||||
p.baseExtract(request)
|
||||
p.Workload = request.PathParameter("workload")
|
||||
}
|
||||
|
||||
func adjustRateInterval(business *business.Layer, namespace, rateInterval string, queryTime time.Time) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user