apiserver.go 20.0 KB
Newer Older
H
hongming 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
Copyright 2019 The 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.
*/

Z
zryfish 已提交
17 18 19
package apiserver

import (
20 21 22
	"bytes"
	"context"
	"fmt"
Z
zryfish 已提交
23
	"github.com/emicklei/go-restful"
24 25
	"k8s.io/apimachinery/pkg/runtime/schema"
	urlruntime "k8s.io/apimachinery/pkg/util/runtime"
Z
zryfish 已提交
26
	"k8s.io/apimachinery/pkg/util/sets"
H
hongming 已提交
27
	unionauth "k8s.io/apiserver/pkg/authentication/request/union"
Z
zryfish 已提交
28
	"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
29
	"k8s.io/klog"
H
hongming 已提交
30 31 32
	clusterv1alpha1 "kubesphere.io/kubesphere/pkg/apis/cluster/v1alpha1"
	iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
	tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
W
wanjunlei 已提交
33
	audit "kubesphere.io/kubesphere/pkg/apiserver/auditing"
H
update  
hongming 已提交
34
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/basic"
Z
zryfish 已提交
35
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/jwttoken"
H
update  
hongming 已提交
36 37
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/anonymous"
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/basictoken"
R
runzexia 已提交
38
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/bearertoken"
H
update  
hongming 已提交
39
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/token"
H
hongming 已提交
40
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
H
hongming 已提交
41
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizerfactory"
H
hongming 已提交
42
	authorizationoptions "kubesphere.io/kubesphere/pkg/apiserver/authorization/options"
H
hongming 已提交
43
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/path"
44
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/proxy"
H
hongming 已提交
45
	unionauthorizer "kubesphere.io/kubesphere/pkg/apiserver/authorization/union"
46
	apiserverconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
Z
zryfish 已提交
47 48 49
	"kubesphere.io/kubesphere/pkg/apiserver/dispatch"
	"kubesphere.io/kubesphere/pkg/apiserver/filters"
	"kubesphere.io/kubesphere/pkg/apiserver/request"
Z
zryfish 已提交
50
	"kubesphere.io/kubesphere/pkg/informers"
Z
zryfish 已提交
51
	alertingv1 "kubesphere.io/kubesphere/pkg/kapis/alerting/v1"
52
	clusterkapisv1alpha1 "kubesphere.io/kubesphere/pkg/kapis/cluster/v1alpha1"
53
	configv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/config/v1alpha2"
R
fmt  
runzexia 已提交
54
	devopsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha2"
S
shaowenchen 已提交
55
	devopsv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha3"
H
hongming 已提交
56
	iamapi "kubesphere.io/kubesphere/pkg/kapis/iam/v1alpha2"
R
runzexia 已提交
57
	monitoringv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/monitoring/v1alpha3"
Z
zryfish 已提交
58
	notificationv1 "kubesphere.io/kubesphere/pkg/kapis/notification/v1"
H
hongming 已提交
59
	"kubesphere.io/kubesphere/pkg/kapis/oauth"
60 61 62
	openpitrixv1 "kubesphere.io/kubesphere/pkg/kapis/openpitrix/v1"
	operationsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/operations/v1alpha2"
	resourcesv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha2"
Z
zryfish 已提交
63
	resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3"
64
	servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
H
hongming 已提交
65
	tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
66
	terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
Z
zryfish 已提交
67
	"kubesphere.io/kubesphere/pkg/kapis/version"
H
update  
hongming 已提交
68
	"kubesphere.io/kubesphere/pkg/models/iam/am"
H
update  
hongming 已提交
69
	"kubesphere.io/kubesphere/pkg/models/iam/im"
R
root 已提交
70
	"kubesphere.io/kubesphere/pkg/simple/client/auditing"
Z
zryfish 已提交
71 72
	"kubesphere.io/kubesphere/pkg/simple/client/cache"
	"kubesphere.io/kubesphere/pkg/simple/client/devops"
J
junotx 已提交
73
	"kubesphere.io/kubesphere/pkg/simple/client/events"
Z
zryfish 已提交
74 75 76 77 78
	"kubesphere.io/kubesphere/pkg/simple/client/k8s"
	"kubesphere.io/kubesphere/pkg/simple/client/logging"
	"kubesphere.io/kubesphere/pkg/simple/client/monitoring"
	"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
	"kubesphere.io/kubesphere/pkg/simple/client/s3"
R
runzexia 已提交
79
	"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
80 81 82 83 84
	"net"
	"net/http"
	rt "runtime"
	"strings"
	"time"
Z
zryfish 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
)

const (
	// ApiRootPath defines the root path of all KubeSphere apis.
	ApiRootPath = "/kapis"

	// MimeMergePatchJson is the mime header used in merge request
	MimeMergePatchJson = "application/merge-patch+json"

	//
	MimeJsonPatchJson = "application/json-patch+json"
)

type APIServer struct {

	// number of kubesphere apiserver
101
	ServerCount int
Z
zryfish 已提交
102 103

	//
104 105
	Server *http.Server

106
	Config *apiserverconfig.Config
Z
zryfish 已提交
107 108 109 110 111

	// webservice container, where all webservice defines
	container *restful.Container

	// kubeClient is a collection of all kubernetes(include CRDs) objects clientset
112
	KubernetesClient k8s.Client
Z
zryfish 已提交
113 114 115

	// informerFactory is a collection of all kubernetes(include CRDs) objects informers,
	// mainly for fast query
116
	InformerFactory informers.InformerFactory
Z
zryfish 已提交
117 118

	// cache is used for short lived objects, like session
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
	CacheClient cache.Interface

	// monitoring client set
	MonitoringClient monitoring.Interface

	//
	OpenpitrixClient openpitrix.Client

	//
	LoggingClient logging.Interface

	//
	DevopsClient devops.Interface

	//
	S3Client s3.Interface

R
runzexia 已提交
136
	SonarClient sonarqube.SonarInterface
J
junotx 已提交
137 138

	EventsClient events.Client
R
root 已提交
139 140

	AuditingClient auditing.Client
141 142
}

W
wanjunlei 已提交
143
func (s *APIServer) PrepareRun(stopCh <-chan struct{}) error {
144 145 146 147 148 149 150 151 152 153

	s.container = restful.NewContainer()
	s.container.Filter(logRequestAndResponse)
	s.container.Router(restful.CurlyRouter{})
	s.container.RecoverHandler(func(panicReason interface{}, httpWriter http.ResponseWriter) {
		logStackOnRecover(panicReason, httpWriter)
	})

	s.installKubeSphereAPIs()

Z
zryfish 已提交
154 155 156 157 158 159
	for _, ws := range s.container.RegisteredWebServices() {
		klog.V(2).Infof("%s", ws.RootPath())
	}

	s.Server.Handler = s.container

W
wanjunlei 已提交
160
	s.buildHandlerChain(stopCh)
Z
zryfish 已提交
161

162 163 164
	return nil
}

165 166 167
// Install all kubesphere api groups
// Installation happens before all informers start to cache objects, so
//   any attempt to list objects using listers will get empty results.
168
func (s *APIServer) installKubeSphereAPIs() {
169
	urlruntime.Must(configv1alpha2.AddToContainer(s.container, s.Config))
170
	urlruntime.Must(resourcev1alpha3.AddToContainer(s.container, s.InformerFactory))
H
huanggze 已提交
171
	urlruntime.Must(monitoringv1alpha3.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.MonitoringClient, s.InformerFactory, s.OpenpitrixClient))
172 173
	urlruntime.Must(openpitrixv1.AddToContainer(s.container, s.InformerFactory, s.OpenpitrixClient))
	urlruntime.Must(operationsv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes()))
H
hongming 已提交
174 175 176
	urlruntime.Must(resourcesv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.InformerFactory,
		s.KubernetesClient.Master()))
	urlruntime.Must(tenantv1alpha2.AddToContainer(s.container, s.InformerFactory, s.KubernetesClient.Kubernetes(),
R
root 已提交
177
		s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient))
178
	urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config()))
179 180 181 182 183 184
	urlruntime.Must(clusterkapisv1alpha1.AddToContainer(s.container,
		s.InformerFactory.KubernetesSharedInformerFactory(),
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.Config.MultiClusterOptions.ProxyPublishService,
		s.Config.MultiClusterOptions.ProxyPublishAddress,
		s.Config.MultiClusterOptions.AgentImage))
H
hongming 已提交
185 186
	imOperator := im.NewOperator(s.KubernetesClient.KubeSphere(), s.InformerFactory, s.Config.AuthenticationOptions)
	urlruntime.Must(iamapi.AddToContainer(s.container, imOperator,
H
hongming 已提交
187
		am.NewOperator(s.InformerFactory, s.KubernetesClient.KubeSphere(), s.KubernetesClient.Kubernetes()),
R
runzexia 已提交
188
		s.Config.AuthenticationOptions))
H
hongming 已提交
189
	urlruntime.Must(oauth.AddToContainer(s.container, imOperator,
190 191
		token.NewJwtTokenIssuer(token.DefaultIssuerName, s.Config.AuthenticationOptions, s.CacheClient),
		s.Config.AuthenticationOptions))
Z
zryfish 已提交
192
	urlruntime.Must(servicemeshv1alpha2.AddToContainer(s.container))
193 194 195 196 197 198
	urlruntime.Must(devopsv1alpha2.AddToContainer(s.container,
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.DevopsClient,
		s.SonarClient,
		s.KubernetesClient.KubeSphere(),
		s.S3Client))
S
shaowenchen 已提交
199 200 201 202 203 204
	urlruntime.Must(devopsv1alpha3.AddToContainer(s.container,
		s.DevopsClient,
		s.KubernetesClient.Kubernetes(),
		s.KubernetesClient.KubeSphere(),
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.InformerFactory.KubernetesSharedInformerFactory()))
Z
zryfish 已提交
205 206
	urlruntime.Must(notificationv1.AddToContainer(s.container, s.Config.NotificationOptions.Endpoint))
	urlruntime.Must(alertingv1.AddToContainer(s.container, s.Config.AlertingOptions.Endpoint))
Z
zryfish 已提交
207
	urlruntime.Must(version.AddToContainer(s.container, s.KubernetesClient.Discovery()))
208 209
}

Z
zryfish 已提交
210
func (s *APIServer) Run(stopCh <-chan struct{}) (err error) {
211

Z
zryfish 已提交
212
	err = s.waitForResourceSync(stopCh)
213 214 215 216 217 218
	if err != nil {
		return err
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
Z
zryfish 已提交
219

220 221 222 223 224
	go func() {
		<-stopCh
		_ = s.Server.Shutdown(ctx)
	}()

Z
zryfish 已提交
225
	klog.V(0).Infof("Start listening on %s", s.Server.Addr)
226
	if s.Server.TLSConfig != nil {
Z
zryfish 已提交
227
		err = s.Server.ListenAndServeTLS("", "")
228
	} else {
Z
zryfish 已提交
229
		err = s.Server.ListenAndServe()
230
	}
Z
zryfish 已提交
231 232

	return err
Z
zryfish 已提交
233 234
}

W
wanjunlei 已提交
235
func (s *APIServer) buildHandlerChain(stopCh <-chan struct{}) {
Z
zryfish 已提交
236 237 238
	requestInfoResolver := &request.RequestInfoFactory{
		APIPrefixes:          sets.NewString("api", "apis", "kapis", "kapi"),
		GrouplessAPIPrefixes: sets.NewString("api", "kapi"),
H
hongming 已提交
239 240 241 242 243 244 245 246 247 248
		GlobalResources: []schema.GroupResource{
			iamv1alpha2.Resource(iamv1alpha2.ResourcesPluralUser),
			iamv1alpha2.Resource(iamv1alpha2.ResourcesPluralGlobalRole),
			iamv1alpha2.Resource(iamv1alpha2.ResourcesPluralGlobalRoleBinding),
			tenantv1alpha1.Resource(tenantv1alpha1.ResourcePluralWorkspace),
			tenantv1alpha2.Resource(tenantv1alpha1.ResourcePluralWorkspace),
			tenantv1alpha2.Resource(clusterv1alpha1.ResourcesPluralCluster),
			clusterv1alpha1.Resource(clusterv1alpha1.ResourcesPluralCluster),
			resourcev1alpha3.Resource(clusterv1alpha1.ResourcesPluralCluster),
		},
Z
zryfish 已提交
249 250 251
	}

	handler := s.Server.Handler
H
update  
hongming 已提交
252
	handler = filters.WithKubeAPIServer(handler, s.KubernetesClient.Config(), &errorResponder{})
R
runzexia 已提交
253

W
wanjunlei 已提交
254 255 256 257
	if s.Config.AuditingOptions.Enable {
		handler = filters.WithAuditing(handler,
			audit.NewAuditing(s.InformerFactory.KubeSphereSharedInformerFactory().Auditing().V1alpha1().Webhooks().Lister(),
				s.Config.AuditingOptions.WebhookUrl, stopCh))
W
wanjunlei 已提交
258 259
	}

Z
zryfish 已提交
260
	if s.Config.MultiClusterOptions.Enable {
261 262
		clusterDispatcher := dispatch.NewClusterDispatch(s.InformerFactory.KubeSphereSharedInformerFactory().Cluster().V1alpha1().Clusters(),
			s.InformerFactory.KubeSphereSharedInformerFactory().Cluster().V1alpha1().Clusters().Lister())
Z
zryfish 已提交
263 264
		handler = filters.WithMultipleClusterDispatcher(handler, clusterDispatcher)
	}
H
hongming 已提交
265

H
hongming 已提交
266 267 268 269 270 271 272 273 274 275
	var authorizers authorizer.Authorizer

	switch s.Config.AuthorizationOptions.Mode {
	case authorizationoptions.AlwaysAllow:
		authorizers = authorizerfactory.NewAlwaysAllowAuthorizer()
	case authorizationoptions.AlwaysDeny:
		authorizers = authorizerfactory.NewAlwaysDenyAuthorizer()
	default:
		fallthrough
	case authorizationoptions.RBAC:
Z
zryfish 已提交
276
		excludedPaths := []string{"/oauth/*", "/kapis/config.kubesphere.io/*", "/kapis/version"}
H
hongming 已提交
277
		pathAuthorizer, _ := path.NewAuthorizer(excludedPaths)
H
hongming 已提交
278
		amOperator := am.NewReadOnlyOperator(s.InformerFactory)
279
		authorizers = unionauthorizer.New(pathAuthorizer, proxy.NewAuthorizer(s.Config.MultiClusterOptions.Enable), authorizerfactory.NewRBACAuthorizer(amOperator))
H
hongming 已提交
280
	}
Z
zryfish 已提交
281

282 283 284
	handler = filters.WithAuthorization(handler, authorizers)

	// authenticators are unordered
H
update  
hongming 已提交
285
	authn := unionauth.New(anonymous.NewAuthenticator(),
H
hongming 已提交
286
		basictoken.New(basic.NewBasicAuthenticator(im.NewOperator(s.KubernetesClient.KubeSphere(), s.InformerFactory, s.Config.AuthenticationOptions))),
287
		bearertoken.New(jwttoken.NewTokenAuthenticator(token.NewJwtTokenIssuer(token.DefaultIssuerName, s.Config.AuthenticationOptions, s.CacheClient))))
H
update  
hongming 已提交
288
	handler = filters.WithAuthentication(handler, authn)
289
	handler = filters.WithRequestInfo(handler, requestInfoResolver)
Z
zryfish 已提交
290 291 292
	s.Server.Handler = handler
}

293 294 295 296
func (s *APIServer) waitForResourceSync(stopCh <-chan struct{}) error {
	klog.V(0).Info("Start cache objects")

	discoveryClient := s.KubernetesClient.Kubernetes().Discovery()
H
hongming 已提交
297
	_, apiResourcesList, err := discoveryClient.ServerGroupsAndResources()
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
	if err != nil {
		return err
	}

	isResourceExists := func(resource schema.GroupVersionResource) bool {
		for _, apiResource := range apiResourcesList {
			if apiResource.GroupVersion == resource.GroupVersion().String() {
				for _, rsc := range apiResource.APIResources {
					if rsc.Name == resource.Resource {
						return true
					}
				}
			}
		}
		return false
	}

	// resources we have to create informer first
	k8sGVRs := []schema.GroupVersionResource{
		{Group: "", Version: "v1", Resource: "namespaces"},
		{Group: "", Version: "v1", Resource: "nodes"},
		{Group: "", Version: "v1", Resource: "resourcequotas"},
		{Group: "", Version: "v1", Resource: "pods"},
		{Group: "", Version: "v1", Resource: "services"},
		{Group: "", Version: "v1", Resource: "persistentvolumeclaims"},
		{Group: "", Version: "v1", Resource: "secrets"},
		{Group: "", Version: "v1", Resource: "configmaps"},

		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "roles"},
		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "rolebindings"},
		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles"},
		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"},

		{Group: "apps", Version: "v1", Resource: "deployments"},
		{Group: "apps", Version: "v1", Resource: "daemonsets"},
		{Group: "apps", Version: "v1", Resource: "replicasets"},
		{Group: "apps", Version: "v1", Resource: "statefulsets"},
		{Group: "apps", Version: "v1", Resource: "controllerrevisions"},

		{Group: "storage.k8s.io", Version: "v1", Resource: "storageclasses"},

		{Group: "batch", Version: "v1", Resource: "jobs"},
		{Group: "batch", Version: "v1beta1", Resource: "cronjobs"},

		{Group: "extensions", Version: "v1beta1", Resource: "ingresses"},

		{Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"},
D
Duan Jiong 已提交
345 346

		{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"},
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
	}

	for _, gvr := range k8sGVRs {
		if !isResourceExists(gvr) {
			klog.Warningf("resource %s not exists in the cluster", gvr)
		} else {
			_, err := s.InformerFactory.KubernetesSharedInformerFactory().ForResource(gvr)
			if err != nil {
				klog.Errorf("cannot create informer for %s", gvr)
				return err
			}
		}
	}

	s.InformerFactory.KubernetesSharedInformerFactory().Start(stopCh)
	s.InformerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(stopCh)

	ksInformerFactory := s.InformerFactory.KubeSphereSharedInformerFactory()

	ksGVRs := []schema.GroupVersionResource{
		{Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"},
H
hongming 已提交
368
		{Group: "tenant.kubesphere.io", Version: "v1alpha2", Resource: "workspacetemplates"},
R
runzexia 已提交
369
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "users"},
H
hongming 已提交
370 371 372 373
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "globalroles"},
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "globalrolebindings"},
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "workspaceroles"},
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "workspacerolebindings"},
Z
zryfish 已提交
374
		{Group: "cluster.kubesphere.io", Version: "v1alpha1", Resource: "clusters"},
H
hongming 已提交
375
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
376 377 378 379 380 381 382
	}

	devopsGVRs := []schema.GroupVersionResource{
		{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibinaries"},
		{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"},
		{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2iruns"},
		{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"},
S
shaowenchen 已提交
383 384
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "pipelines"},
385 386 387 388 389 390
	}

	servicemeshGVRs := []schema.GroupVersionResource{
		{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "strategies"},
		{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "servicepolicies"},
	}
Z
zryfish 已提交
391

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
	// skip caching devops resources if devops not enabled
	if s.DevopsClient != nil {
		ksGVRs = append(ksGVRs, devopsGVRs...)
	}

	// skip caching servicemesh resources if servicemesh not enabled
	if s.KubernetesClient.Istio() != nil {
		ksGVRs = append(ksGVRs, servicemeshGVRs...)
	}

	for _, gvr := range ksGVRs {
		if !isResourceExists(gvr) {
			klog.Warningf("resource %s not exists in the cluster", gvr)
		} else {
			_, err := ksInformerFactory.ForResource(gvr)
			if err != nil {
				return err
			}
		}
	}

	ksInformerFactory.Start(stopCh)
	ksInformerFactory.WaitForCacheSync(stopCh)

	appInformerFactory := s.InformerFactory.ApplicationSharedInformerFactory()

	appGVRs := []schema.GroupVersionResource{
		{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"},
	}

	for _, gvr := range appGVRs {
		if !isResourceExists(gvr) {
			klog.Warningf("resource %s not exists in the cluster", gvr)
		} else {
Z
zryfish 已提交
426
			_, err = appInformerFactory.ForResource(gvr)
427 428 429 430 431 432 433 434 435
			if err != nil {
				return err
			}
		}
	}

	appInformerFactory.Start(stopCh)
	appInformerFactory.WaitForCacheSync(stopCh)

Z
zhangmin 已提交
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
	snapshotInformerFactory := s.InformerFactory.SnapshotSharedInformerFactory()
	snapshotGVRs := []schema.GroupVersionResource{
		{Group: "snapshot.storage.k8s.io", Version: "v1beta1", Resource: "volumesnapshotclasses"},
		{Group: "snapshot.storage.k8s.io", Version: "v1beta1", Resource: "volumesnapshots"},
		{Group: "snapshot.storage.k8s.io", Version: "v1beta1", Resource: "volumesnapshotcontents"},
	}
	for _, gvr := range snapshotGVRs {
		if !isResourceExists(gvr) {
			klog.Warningf("resource %s not exists in the cluster", gvr)
		} else {
			_, err = snapshotInformerFactory.ForResource(gvr)
			if err != nil {
				return err
			}
		}
	}
	snapshotInformerFactory.Start(stopCh)
	snapshotInformerFactory.WaitForCacheSync(stopCh)

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
	apiextensionsInformerFactory := s.InformerFactory.ApiExtensionSharedInformerFactory()
	apiextensionsGVRs := []schema.GroupVersionResource{
		{Group: "apiextensions.k8s.io", Version: "v1", Resource: "customresourcedefinitions"},
	}

	for _, gvr := range apiextensionsGVRs {
		if !isResourceExists(gvr) {
			klog.Warningf("resource %s not exists in the cluster", gvr)
		} else {
			_, err = apiextensionsInformerFactory.ForResource(gvr)
			if err != nil {
				return err
			}
		}
	}
	apiextensionsInformerFactory.Start(stopCh)
	apiextensionsInformerFactory.WaitForCacheSync(stopCh)

473 474 475
	klog.V(0).Info("Finished caching objects")

	return nil
Z
zryfish 已提交
476 477 478

}

479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
func logStackOnRecover(panicReason interface{}, w http.ResponseWriter) {
	var buffer bytes.Buffer
	buffer.WriteString(fmt.Sprintf("recover from panic situation: - %v\r\n", panicReason))
	for i := 2; ; i += 1 {
		_, file, line, ok := rt.Caller(i)
		if !ok {
			break
		}
		buffer.WriteString(fmt.Sprintf("    %s:%d\r\n", file, line))
	}
	klog.Errorln(buffer.String())

	headers := http.Header{}
	if ct := w.Header().Get("Content-Type"); len(ct) > 0 {
		headers.Set("Accept", ct)
	}

	w.WriteHeader(http.StatusInternalServerError)
	w.Write([]byte("Internal server error"))
}
Z
zryfish 已提交
499

500 501 502
func logRequestAndResponse(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
	start := time.Now()
	chain.ProcessFilter(req, resp)
503 504 505 506 507 508 509 510

	// Always log error response
	logWithVerbose := klog.V(4)
	if resp.StatusCode() > http.StatusBadRequest {
		logWithVerbose = klog.V(0)
	}

	logWithVerbose.Infof("%s - \"%s %s %s\" %d %d %dms",
511 512
		getRequestIP(req),
		req.Request.Method,
513
		req.Request.URL,
514 515 516 517 518
		req.Request.Proto,
		resp.StatusCode(),
		resp.ContentLength(),
		time.Since(start)/time.Millisecond,
	)
Z
zryfish 已提交
519 520
}

521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
func getRequestIP(req *restful.Request) string {
	address := strings.Trim(req.Request.Header.Get("X-Real-Ip"), " ")
	if address != "" {
		return address
	}

	address = strings.Trim(req.Request.Header.Get("X-Forwarded-For"), " ")
	if address != "" {
		return address
	}

	address, _, err := net.SplitHostPort(req.Request.RemoteAddr)
	if err != nil {
		return req.Request.RemoteAddr
	}

	return address
Z
zryfish 已提交
538
}
Z
zryfish 已提交
539 540 541 542 543 544 545

type errorResponder struct{}

func (e *errorResponder) Error(w http.ResponseWriter, req *http.Request, err error) {
	klog.Error(err)
	responsewriters.InternalError(w, req, err)
}