apiserver.go 22.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"
23 24 25 26
	"net/http"
	rt "runtime"
	"time"

Z
zryfish 已提交
27
	"github.com/emicklei/go-restful"
28 29
	"k8s.io/apimachinery/pkg/runtime/schema"
	urlruntime "k8s.io/apimachinery/pkg/util/runtime"
Z
zryfish 已提交
30
	"k8s.io/apimachinery/pkg/util/sets"
H
hongming 已提交
31
	unionauth "k8s.io/apiserver/pkg/authentication/request/union"
Z
zryfish 已提交
32
	"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
33
	"k8s.io/klog"
H
hongming 已提交
34 35 36
	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 已提交
37
	typesv1beta1 "kubesphere.io/kubesphere/pkg/apis/types/v1beta1"
W
wanjunlei 已提交
38
	audit "kubesphere.io/kubesphere/pkg/apiserver/auditing"
H
update  
hongming 已提交
39
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/basic"
Z
zryfish 已提交
40
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/jwttoken"
H
update  
hongming 已提交
41 42
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/anonymous"
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/basictoken"
R
runzexia 已提交
43
	"kubesphere.io/kubesphere/pkg/apiserver/authentication/request/bearertoken"
H
hongming 已提交
44
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
H
hongming 已提交
45
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizerfactory"
H
hongming 已提交
46
	authorizationoptions "kubesphere.io/kubesphere/pkg/apiserver/authorization/options"
H
hongming 已提交
47 48
	"kubesphere.io/kubesphere/pkg/apiserver/authorization/path"
	unionauthorizer "kubesphere.io/kubesphere/pkg/apiserver/authorization/union"
49
	apiserverconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
Z
zryfish 已提交
50 51 52
	"kubesphere.io/kubesphere/pkg/apiserver/dispatch"
	"kubesphere.io/kubesphere/pkg/apiserver/filters"
	"kubesphere.io/kubesphere/pkg/apiserver/request"
Z
zryfish 已提交
53
	"kubesphere.io/kubesphere/pkg/informers"
Z
zryfish 已提交
54
	alertingv1 "kubesphere.io/kubesphere/pkg/kapis/alerting/v1"
55
	clusterkapisv1alpha1 "kubesphere.io/kubesphere/pkg/kapis/cluster/v1alpha1"
56
	configv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/config/v1alpha2"
R
fmt  
runzexia 已提交
57
	devopsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha2"
S
shaowenchen 已提交
58
	devopsv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha3"
H
hongming 已提交
59
	iamapi "kubesphere.io/kubesphere/pkg/kapis/iam/v1alpha2"
R
runzexia 已提交
60
	monitoringv1alpha3 "kubesphere.io/kubesphere/pkg/kapis/monitoring/v1alpha3"
Z
zryfish 已提交
61
	notificationv1 "kubesphere.io/kubesphere/pkg/kapis/notification/v1"
H
hongming 已提交
62
	"kubesphere.io/kubesphere/pkg/kapis/oauth"
63 64 65
	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 已提交
66
	resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3"
67
	servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
H
hongming 已提交
68
	tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
69
	terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
Z
zryfish 已提交
70
	"kubesphere.io/kubesphere/pkg/kapis/version"
H
update  
hongming 已提交
71
	"kubesphere.io/kubesphere/pkg/models/iam/am"
72
	"kubesphere.io/kubesphere/pkg/models/iam/group"
H
update  
hongming 已提交
73
	"kubesphere.io/kubesphere/pkg/models/iam/im"
R
root 已提交
74
	"kubesphere.io/kubesphere/pkg/simple/client/auditing"
Z
zryfish 已提交
75 76
	"kubesphere.io/kubesphere/pkg/simple/client/cache"
	"kubesphere.io/kubesphere/pkg/simple/client/devops"
J
junotx 已提交
77
	"kubesphere.io/kubesphere/pkg/simple/client/events"
Z
zryfish 已提交
78 79 80 81 82
	"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 已提交
83
	"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
Z
zryfish 已提交
84
	utilnet "kubesphere.io/kubesphere/pkg/utils/net"
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() {
H
hongming 已提交
169 170 171 172
	imOperator := im.NewOperator(s.KubernetesClient.KubeSphere(), s.InformerFactory, s.Config.AuthenticationOptions)
	amOperator := am.NewOperator(s.InformerFactory, s.KubernetesClient.KubeSphere(), s.KubernetesClient.Kubernetes())
	rbacAuthorizer := authorizerfactory.NewRBACAuthorizer(amOperator)

173
	urlruntime.Must(configv1alpha2.AddToContainer(s.container, s.Config))
174
	urlruntime.Must(resourcev1alpha3.AddToContainer(s.container, s.InformerFactory))
H
huanggze 已提交
175
	urlruntime.Must(monitoringv1alpha3.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.MonitoringClient, s.InformerFactory, s.OpenpitrixClient))
176 177
	urlruntime.Must(openpitrixv1.AddToContainer(s.container, s.InformerFactory, s.OpenpitrixClient))
	urlruntime.Must(operationsv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes()))
H
hongming 已提交
178 179 180
	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(),
H
hongming 已提交
181
		s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient, amOperator, rbacAuthorizer))
182
	urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config()))
183 184 185 186 187 188
	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 已提交
189
	urlruntime.Must(iamapi.AddToContainer(s.container, imOperator,
H
hongming 已提交
190
		am.NewOperator(s.InformerFactory, s.KubernetesClient.KubeSphere(), s.KubernetesClient.Kubernetes()),
191
		group.New(s.InformerFactory, s.KubernetesClient.KubeSphere(), s.KubernetesClient.Kubernetes()),
R
runzexia 已提交
192
		s.Config.AuthenticationOptions))
Z
zryfish 已提交
193

H
hongming 已提交
194
	urlruntime.Must(oauth.AddToContainer(s.container, imOperator,
Z
zryfish 已提交
195 196 197 198 199 200 201 202
		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()),
203
		s.Config.AuthenticationOptions))
Z
zryfish 已提交
204
	urlruntime.Must(servicemeshv1alpha2.AddToContainer(s.container))
205 206 207 208 209
	urlruntime.Must(devopsv1alpha2.AddToContainer(s.container,
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.DevopsClient,
		s.SonarClient,
		s.KubernetesClient.KubeSphere(),
210 211
		s.S3Client,
		s.Config.DevopsOptions.Host))
S
shaowenchen 已提交
212 213 214 215 216 217
	urlruntime.Must(devopsv1alpha3.AddToContainer(s.container,
		s.DevopsClient,
		s.KubernetesClient.Kubernetes(),
		s.KubernetesClient.KubeSphere(),
		s.InformerFactory.KubeSphereSharedInformerFactory(),
		s.InformerFactory.KubernetesSharedInformerFactory()))
Z
zryfish 已提交
218 219
	urlruntime.Must(notificationv1.AddToContainer(s.container, s.Config.NotificationOptions.Endpoint))
	urlruntime.Must(alertingv1.AddToContainer(s.container, s.Config.AlertingOptions.Endpoint))
Z
zryfish 已提交
220
	urlruntime.Must(version.AddToContainer(s.container, s.KubernetesClient.Discovery()))
221 222
}

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

Z
zryfish 已提交
225
	err = s.waitForResourceSync(stopCh)
226 227 228 229 230 231
	if err != nil {
		return err
	}

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

233 234 235 236 237
	go func() {
		<-stopCh
		_ = s.Server.Shutdown(ctx)
	}()

Z
zryfish 已提交
238
	klog.V(0).Infof("Start listening on %s", s.Server.Addr)
239
	if s.Server.TLSConfig != nil {
Z
zryfish 已提交
240
		err = s.Server.ListenAndServeTLS("", "")
241
	} else {
Z
zryfish 已提交
242
		err = s.Server.ListenAndServe()
243
	}
Z
zryfish 已提交
244 245

	return err
Z
zryfish 已提交
246 247
}

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

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

W
wanjunlei 已提交
267 268
	if s.Config.AuditingOptions.Enable {
		handler = filters.WithAuditing(handler,
269
			audit.NewAuditing(s.InformerFactory, s.Config.AuditingOptions.WebhookUrl, stopCh))
W
wanjunlei 已提交
270 271
	}

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

288
	handler = filters.WithAuthorization(handler, authorizers)
H
hongming 已提交
289 290 291 292 293
	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)
	}
294

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

305 306 307 308
func (s *APIServer) waitForResourceSync(stopCh <-chan struct{}) error {
	klog.V(0).Info("Start cache objects")

	discoveryClient := s.KubernetesClient.Kubernetes().Discovery()
H
hongming 已提交
309
	_, apiResourcesList, err := discoveryClient.ServerGroupsAndResources()
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 352 353 354 355 356
	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 已提交
357 358

		{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"},
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
	}

	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 已提交
380
		{Group: "tenant.kubesphere.io", Version: "v1alpha2", Resource: "workspacetemplates"},
R
runzexia 已提交
381
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "users"},
H
hongming 已提交
382 383
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "globalroles"},
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "globalrolebindings"},
384 385
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "groups"},
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "groupbindings"},
H
hongming 已提交
386 387
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "workspaceroles"},
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "workspacerolebindings"},
Z
zryfish 已提交
388
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "loginrecords"},
389 390
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "groups"},
		{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "groupbindings"},
Z
zryfish 已提交
391
		{Group: "cluster.kubesphere.io", Version: "v1alpha1", Resource: "clusters"},
H
hongming 已提交
392
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
393 394 395 396 397 398 399
	}

	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 已提交
400 401
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "devopsprojects"},
		{Group: "devops.kubesphere.io", Version: "v1alpha3", Resource: "pipelines"},
402 403 404 405 406 407
	}

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

Z
zryfish 已提交
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
	// federated resources on cached in multi cluster setup
	federatedResourceGVRs := []schema.GroupVersionResource{
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedClusterRole),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedClusterRoleBindingBinding),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedNamespace),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedService),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedDeployment),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedSecret),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedConfigmap),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedStatefulSet),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedIngress),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedResourceQuota),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedPersistentVolumeClaim),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedWorkspace),
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedUser),
424
		typesv1beta1.SchemeGroupVersion.WithResource(typesv1beta1.ResourcePluralFederatedApplication),
Z
zryfish 已提交
425 426
	}

427 428 429 430 431 432 433 434 435 436
	// 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 已提交
437
	if s.Config.MultiClusterOptions.Enable {
Z
zryfish 已提交
438
		ksGVRs = append(ksGVRs, federatedResourceGVRs...)
H
hongming 已提交
439 440
	}

441 442 443 444
	for _, gvr := range ksGVRs {
		if !isResourceExists(gvr) {
			klog.Warningf("resource %s not exists in the cluster", gvr)
		} else {
Z
zryfish 已提交
445
			_, err = ksInformerFactory.ForResource(gvr)
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
			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 已提交
465
			_, err = appInformerFactory.ForResource(gvr)
466 467 468 469 470 471 472 473 474
			if err != nil {
				return err
			}
		}
	}

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

Z
zhangmin 已提交
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
	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)

494 495
	apiextensionsInformerFactory := s.InformerFactory.ApiExtensionSharedInformerFactory()
	apiextensionsGVRs := []schema.GroupVersionResource{
496
		{Group: "apiextensions.k8s.io", Version: "v1beta1", Resource: "customresourcedefinitions"},
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
	}

	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)

512 513 514
	klog.V(0).Info("Finished caching objects")

	return nil
Z
zryfish 已提交
515 516 517

}

518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
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 已提交
538

539 540 541
func logRequestAndResponse(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
	start := time.Now()
	chain.ProcessFilter(req, resp)
542 543 544 545 546 547 548 549

	// 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 已提交
550
		utilnet.GetRequestIP(req.Request),
551
		req.Request.Method,
552
		req.Request.URL,
553 554 555 556 557
		req.Request.Proto,
		resp.StatusCode(),
		resp.ContentLength(),
		time.Since(start)/time.Millisecond,
	)
Z
zryfish 已提交
558 559
}

Z
zryfish 已提交
560 561 562 563 564 565
type errorResponder struct{}

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