apiserver.go 20.2 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"
H
hongming 已提交
33
	typesv1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1"
W
wanjunlei 已提交
34
	audit "kubesphere.io/kubesphere/pkg/apiserver/auditing"
H
update  
hongming 已提交
35
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/basic"
Z
zryfish 已提交
36
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/jwttoken"
H
update  
hongming 已提交
37 38
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/anonymous"
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/basictoken"
R
runzexia 已提交
39
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/bearertoken"
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 44
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/path"
	unionauthorizer "kubesphere.io/kubesphere/pkg/apiserver/authorization/union"
45
	apiserverconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
Z
zryfish 已提交
46 47 48
	"kubesphere.io/kubesphere/pkg/apiserver/dispatch"
	"kubesphere.io/kubesphere/pkg/apiserver/filters"
	"kubesphere.io/kubesphere/pkg/apiserver/request"
Z
zryfish 已提交
49
	"kubesphere.io/kubesphere/pkg/informers"
Z
zryfish 已提交
50
	alertingv1 "kubesphere.io/kubesphere/pkg/kapis/alerting/v1"
51
	clusterkapisv1alpha1 "kubesphere.io/kubesphere/pkg/kapis/cluster/v1alpha1"
52
	configv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/config/v1alpha2"
R
fmt  
runzexia 已提交
53
	devopsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha2"
S
shaowenchen 已提交
54
	devopsv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha3"
H
hongming 已提交
55
	iamapi "kubesphere.io/kubesphere/pkg/kapis/iam/v1alpha2"
R
runzexia 已提交
56
	monitoringv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/monitoring/v1alpha3"
Z
zryfish 已提交
57
	notificationv1 "kubesphere.io/kubesphere/pkg/kapis/notification/v1"
H
hongming 已提交
58
	"kubesphere.io/kubesphere/pkg/kapis/oauth"
59 60 61
	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 已提交
62
	resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3"
63
	servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
H
hongming 已提交
64
	tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
65
	terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
Z
zryfish 已提交
66
	"kubesphere.io/kubesphere/pkg/kapis/version"
H
update  
hongming 已提交
67
	"kubesphere.io/kubesphere/pkg/models/iam/am"
H
update  
hongming 已提交
68
	"kubesphere.io/kubesphere/pkg/models/iam/im"
R
root 已提交
69
	"kubesphere.io/kubesphere/pkg/simple/client/auditing"
Z
zryfish 已提交
70 71
	"kubesphere.io/kubesphere/pkg/simple/client/cache"
	"kubesphere.io/kubesphere/pkg/simple/client/devops"
J
junotx 已提交
72
	"kubesphere.io/kubesphere/pkg/simple/client/events"
Z
zryfish 已提交
73 74 75 76 77
	"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 已提交
78
	"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
Z
zryfish 已提交
79
	utilnet "kubesphere.io/kubesphere/pkg/utils/net"
80 81 82
	"net/http"
	rt "runtime"
	"time"
Z
zryfish 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
)

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
99
	ServerCount int
Z
zryfish 已提交
100 101

	//
102 103
	Server *http.Server

104
	Config *apiserverconfig.Config
Z
zryfish 已提交
105 106 107 108 109

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

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

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

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

	// monitoring client set
	MonitoringClient monitoring.Interface

	//
	OpenpitrixClient openpitrix.Client

	//
	LoggingClient logging.Interface

	//
	DevopsClient devops.Interface

	//
	S3Client s3.Interface

R
runzexia 已提交
134
	SonarClient sonarqube.SonarInterface
J
junotx 已提交
135 136

	EventsClient events.Client
R
root 已提交
137 138

	AuditingClient auditing.Client
139 140
}

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

	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 已提交
152 153 154 155 156 157
	for _, ws := range s.container.RegisteredWebServices() {
		klog.V(2).Infof("%s", ws.RootPath())
	}

	s.Server.Handler = s.container

W
wanjunlei 已提交
158
	s.buildHandlerChain(stopCh)
Z
zryfish 已提交
159

160 161 162
	return nil
}

163 164 165
// 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.
166
func (s *APIServer) installKubeSphereAPIs() {
167
	urlruntime.Must(configv1alpha2.AddToContainer(s.container, s.Config))
168
	urlruntime.Must(resourcev1alpha3.AddToContainer(s.container, s.InformerFactory))
H
huanggze 已提交
169
	urlruntime.Must(monitoringv1alpha3.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.MonitoringClient, s.InformerFactory, s.OpenpitrixClient))
170 171
	urlruntime.Must(openpitrixv1.AddToContainer(s.container, s.InformerFactory, s.OpenpitrixClient))
	urlruntime.Must(operationsv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes()))
H
hongming 已提交
172 173 174
	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 已提交
175
		s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient))
176
	urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config()))
177 178 179 180 181 182
	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 已提交
183 184
	imOperator := im.NewOperator(s.KubernetesClient.KubeSphere(), s.InformerFactory, s.Config.AuthenticationOptions)
	urlruntime.Must(iamapi.AddToContainer(s.container, imOperator,
H
hongming 已提交
185
		am.NewOperator(s.InformerFactory, s.KubernetesClient.KubeSphere(), s.KubernetesClient.Kubernetes()),
R
runzexia 已提交
186
		s.Config.AuthenticationOptions))
Z
zryfish 已提交
187

H
hongming 已提交
188
	urlruntime.Must(oauth.AddToContainer(s.container, imOperator,
Z
zryfish 已提交
189 190 191 192 193 194 195 196
		im.NewTokenOperator(
			s.CacheClient,
			s.Config.AuthenticationOptions),
		im.NewPasswordAuthenticator(
			s.KubernetesClient.KubeSphere(),
			s.InformerFactory.KubeSphereSharedInformerFactory().Iam().V1alpha2().Users().Lister(),
			s.Config.AuthenticationOptions),
		im.NewLoginRecorder(s.KubernetesClient.KubeSphere()),
197
		s.Config.AuthenticationOptions))
Z
zryfish 已提交
198
	urlruntime.Must(servicemeshv1alpha2.AddToContainer(s.container))
199 200 201 202 203
	urlruntime.Must(devopsv1alpha2.AddToContainer(s.container,
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.DevopsClient,
		s.SonarClient,
		s.KubernetesClient.KubeSphere(),
204 205
		s.S3Client,
		s.Config.DevopsOptions.Host))
S
shaowenchen 已提交
206 207 208 209 210 211
	urlruntime.Must(devopsv1alpha3.AddToContainer(s.container,
		s.DevopsClient,
		s.KubernetesClient.Kubernetes(),
		s.KubernetesClient.KubeSphere(),
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.InformerFactory.KubernetesSharedInformerFactory()))
Z
zryfish 已提交
212 213
	urlruntime.Must(notificationv1.AddToContainer(s.container, s.Config.NotificationOptions.Endpoint))
	urlruntime.Must(alertingv1.AddToContainer(s.container, s.Config.AlertingOptions.Endpoint))
Z
zryfish 已提交
214
	urlruntime.Must(version.AddToContainer(s.container, s.KubernetesClient.Discovery()))
215 216
}

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

Z
zryfish 已提交
219
	err = s.waitForResourceSync(stopCh)
220 221 222 223 224 225
	if err != nil {
		return err
	}

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

227 228 229 230 231
	go func() {
		<-stopCh
		_ = s.Server.Shutdown(ctx)
	}()

Z
zryfish 已提交
232
	klog.V(0).Infof("Start listening on %s", s.Server.Addr)
233
	if s.Server.TLSConfig != nil {
Z
zryfish 已提交
234
		err = s.Server.ListenAndServeTLS("", "")
235
	} else {
Z
zryfish 已提交
236
		err = s.Server.ListenAndServe()
237
	}
Z
zryfish 已提交
238 239

	return err
Z
zryfish 已提交
240 241
}

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

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

W
wanjunlei 已提交
261 262 263 264
	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 已提交
265 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)
H
hongming 已提交
280
		authorizers = unionauthorizer.New(pathAuthorizer, authorizerfactory.NewRBACAuthorizer(amOperator))
H
hongming 已提交
281
	}
Z
zryfish 已提交
282

283
	handler = filters.WithAuthorization(handler, authorizers)
H
hongming 已提交
284 285 286 287 288
	if s.Config.MultiClusterOptions.Enable {
		clusterDispatcher := dispatch.NewClusterDispatch(s.InformerFactory.KubeSphereSharedInformerFactory().Cluster().V1alpha1().Clusters(),
			s.InformerFactory.KubeSphereSharedInformerFactory().Cluster().V1alpha1().Clusters().Lister())
		handler = filters.WithMultipleClusterDispatcher(handler, clusterDispatcher)
	}
289

Z
zryfish 已提交
290
	loginRecorder := im.NewLoginRecorder(s.KubernetesClient.KubeSphere())
291
	// authenticators are unordered
H
update  
hongming 已提交
292
	authn := unionauth.New(anonymous.NewAuthenticator(),
Z
zryfish 已提交
293 294 295
		basictoken.New(basic.NewBasicAuthenticator(im.NewPasswordAuthenticator(s.KubernetesClient.KubeSphere(), s.InformerFactory.KubeSphereSharedInformerFactory().Iam().V1alpha2().Users().Lister(), s.Config.AuthenticationOptions))),
		bearertoken.New(jwttoken.NewTokenAuthenticator(im.NewTokenOperator(s.CacheClient, s.Config.AuthenticationOptions))))
	handler = filters.WithAuthentication(handler, authn, loginRecorder)
296
	handler = filters.WithRequestInfo(handler, requestInfoResolver)
Z
zryfish 已提交
297 298 299
	s.Server.Handler = handler
}

300 301 302 303
func (s *APIServer) waitForResourceSync(stopCh <-chan struct{}) error {
	klog.V(0).Info("Start cache objects")

	discoveryClient := s.KubernetesClient.Kubernetes().Discovery()
H
hongming 已提交
304
	_, apiResourcesList, err := discoveryClient.ServerGroupsAndResources()
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 346 347 348 349 350 351
	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 已提交
352 353

		{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"},
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
	}

	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 已提交
375
		{Group: "tenant.kubesphere.io", Version: "v1alpha2", Resource: "workspacetemplates"},
R
runzexia 已提交
376
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "users"},
H
hongming 已提交
377 378 379 380
		{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 已提交
381
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "loginrecords"},
Z
zryfish 已提交
382
		{Group: "cluster.kubesphere.io", Version: "v1alpha1", Resource: "clusters"},
H
hongming 已提交
383
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
384 385 386 387 388 389 390
	}

	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 已提交
391 392
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "pipelines"},
393 394 395 396 397 398
	}

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

400 401 402 403 404 405 406 407 408 409
	// 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...)
	}

H
hongming 已提交
410 411 412 413
	if s.Config.MultiClusterOptions.Enable {
		ksGVRs = append(ksGVRs, typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcesPluralFedNamespace))
	}

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
	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 已提交
438
			_, err = appInformerFactory.ForResource(gvr)
439 440 441 442 443 444 445 446 447
			if err != nil {
				return err
			}
		}
	}

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

Z
zhangmin 已提交
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
	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)

467 468
	apiextensionsInformerFactory := s.InformerFactory.ApiExtensionSharedInformerFactory()
	apiextensionsGVRs := []schema.GroupVersionResource{
469
		{Group: "apiextensions.k8s.io", Version: "v1beta1", Resource: "customresourcedefinitions"},
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
	}

	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)

485 486 487
	klog.V(0).Info("Finished caching objects")

	return nil
Z
zryfish 已提交
488 489 490

}

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
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 已提交
511

512 513 514
func logRequestAndResponse(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
	start := time.Now()
	chain.ProcessFilter(req, resp)
515 516 517 518 519 520 521 522

	// 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",
Z
zryfish 已提交
523
		utilnet.GetRequestIP(req.Request),
524
		req.Request.Method,
525
		req.Request.URL,
526 527 528 529 530
		req.Request.Proto,
		resp.StatusCode(),
		resp.ContentLength(),
		time.Since(start)/time.Millisecond,
	)
Z
zryfish 已提交
531 532
}

Z
zryfish 已提交
533 534 535 536 537 538
type errorResponder struct{}

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