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
	urlruntime.Must(devopsv1alpha2.AddToContainer(s.container,
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.DevopsClient,
		s.SonarClient,
		s.KubernetesClient.KubeSphere(),
198 199
		s.S3Client,
		s.Config.DevopsOptions.Host))
S
shaowenchen 已提交
200 201 202 203 204 205
	urlruntime.Must(devopsv1alpha3.AddToContainer(s.container,
		s.DevopsClient,
		s.KubernetesClient.Kubernetes(),
		s.KubernetesClient.KubeSphere(),
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.InformerFactory.KubernetesSharedInformerFactory()))
Z
zryfish 已提交
206 207
	urlruntime.Must(notificationv1.AddToContainer(s.container, s.Config.NotificationOptions.Endpoint))
	urlruntime.Must(alertingv1.AddToContainer(s.container, s.Config.AlertingOptions.Endpoint))
Z
zryfish 已提交
208
	urlruntime.Must(version.AddToContainer(s.container, s.KubernetesClient.Discovery()))
209 210
}

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

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

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

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

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

	return err
Z
zryfish 已提交
234 235
}

W
wanjunlei 已提交
236
func (s *APIServer) buildHandlerChain(stopCh <-chan struct{}) {
Z
zryfish 已提交
237 238 239
	requestInfoResolver := &request.RequestInfoFactory{
		APIPrefixes:          sets.NewString("api", "apis", "kapis", "kapi"),
		GrouplessAPIPrefixes: sets.NewString("api", "kapi"),
H
hongming 已提交
240 241 242 243 244 245 246 247 248 249
		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 已提交
250 251 252
	}

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

W
wanjunlei 已提交
255 256 257 258
	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 已提交
259 260
	}

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

H
hongming 已提交
267 268 269 270 271 272 273 274 275 276
	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 已提交
277
		excludedPaths := []string{"/oauth/*", "/kapis/config.kubesphere.io/*", "/kapis/version"}
H
hongming 已提交
278
		pathAuthorizer, _ := path.NewAuthorizer(excludedPaths)
H
hongming 已提交
279
		amOperator := am.NewReadOnlyOperator(s.InformerFactory)
280
		authorizers = unionauthorizer.New(pathAuthorizer, proxy.NewAuthorizer(s.Config.MultiClusterOptions.Enable), authorizerfactory.NewRBACAuthorizer(amOperator))
H
hongming 已提交
281
	}
Z
zryfish 已提交
282

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

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

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

	discoveryClient := s.KubernetesClient.Kubernetes().Discovery()
H
hongming 已提交
298
	_, apiResourcesList, err := discoveryClient.ServerGroupsAndResources()
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 345
	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 已提交
346 347

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

	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 已提交
369
		{Group: "tenant.kubesphere.io", Version: "v1alpha2", Resource: "workspacetemplates"},
R
runzexia 已提交
370
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "users"},
H
hongming 已提交
371 372 373 374
		{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 已提交
375
		{Group: "cluster.kubesphere.io", Version: "v1alpha1", Resource: "clusters"},
H
hongming 已提交
376
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
377 378 379 380 381 382 383
	}

	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 已提交
384 385
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "pipelines"},
386 387 388 389 390 391
	}

	servicemeshGVRs := []schema.GroupVersionResource{
		{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "strategies"},
		{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "servicepolicies"},
	}
Z
zryfish 已提交
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 426
	// 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 已提交
427
			_, err = appInformerFactory.ForResource(gvr)
428 429 430 431 432 433 434 435 436
			if err != nil {
				return err
			}
		}
	}

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

Z
zhangmin 已提交
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
	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)

456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
	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)

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

	return nil
Z
zryfish 已提交
477 478 479

}

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
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 已提交
500

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

	// 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",
512 513
		getRequestIP(req),
		req.Request.Method,
514
		req.Request.URL,
515 516 517 518 519
		req.Request.Proto,
		resp.StatusCode(),
		resp.ContentLength(),
		time.Since(start)/time.Millisecond,
	)
Z
zryfish 已提交
520 521
}

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
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 已提交
539
}
Z
zryfish 已提交
540 541 542 543 544 545 546

type errorResponder struct{}

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