生成DefaultRESTMapper入口
上次介绍了DefaultRESTMapper的具体实现,本次将简要分析代码何处生成了DefaultRESTMapper。生成DefaultRESTMapper的入口定义在/pkg/api/mapper.go:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 
  | func NewDefaultRESTMapperFromScheme(defaultGroupVersions []unversioned.GroupVersion, interfacesFunc meta.VersionInterfacesFunc, 	importPathPrefix string, ignoredKinds, rootScoped sets.String, scheme *runtime.Scheme) *meta.DefaultRESTMapper { 	mapper := meta.NewDefaultRESTMapper(defaultGroupVersions, interfacesFunc) 	 	 	for _, gv := range defaultGroupVersions { 		for kind, oType := range scheme.KnownTypes(gv) { 			gvk := gv.WithKind(kind) 			 			 			 			if !strings.Contains(oType.PkgPath(), importPathPrefix) || ignoredKinds.Has(kind) { 				continue 			} 			scope := meta.RESTScopeNamespace 			 			if rootScoped.Has(kind) { 				scope = meta.RESTScopeRoot 			} 			mapper.Add(gvk, scope) 		} 	} 	return mapper } 
  | 
NewDefaultRESTMapperFromScheme()函数依据传入的defaultGroupVersions和interfacesFunc参数生成mapper,然后把在Scheme中defaultGroupVersions下的资源注册到mapper中。这里的Scheme即api.Scheme,全部的类都会注册到api.Scheme中。所以可以依据defaultGroupVersions来区别DefaultRESTMapper。
v1的DefaultRESTMapper
现在来看下v1的DefaultRESTMapper。在所有的/install/install.go文件中,都会生成groupMeta,并向registered.DefaultAPIRegistrationManager注册。这个groupMeta中包含一个DefaultRESTMapper。
来看/pkg/api/install/install.go中enableVersions()函数。其中传入的参数externalVersions就是var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion},即v1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 
  | func enableVersions(externalVersions []unversioned.GroupVersion) error { 	addVersionsToScheme(externalVersions...) 	preferredExternalVersion := externalVersions[0] 	groupMeta := apimachinery.GroupMeta{ 		GroupVersion:  preferredExternalVersion, 		GroupVersions: externalVersions, 		RESTMapper:    newRESTMapper(externalVersions), 		SelfLinker:    runtime.SelfLinker(accessor), 		InterfacesFor: interfacesFor, 	} 	 	if err := registered.RegisterGroup(groupMeta); err != nil { 		return err 	} 	return nil } 
  | 
所以,groupMeta中的RESTMapper是通过newRESTMapper()生成的。newRESTMapper()定义在/pkg/api/install/install.go中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 
  | func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper { 	 	 	 	rootScoped := sets.NewString( 		"Node", 		"Namespace", 		"PersistentVolume", 		"ComponentStatus", 	) 	 	ignoredKinds := sets.NewString( 		"ListOptions", 		"DeleteOptions", 		"Status", 		"PodLogOptions", 		"PodExecOptions", 		"PodAttachOptions", 		"PodProxyOptions", 		"NodeProxyOptions", 		"ServiceProxyOptions", 		"ThirdPartyResource", 		"ThirdPartyResourceData", 		"ThirdPartyResourceList") 	 	 	mapper := api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) 	return mapper } func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) { 	switch version { 	case v1.SchemeGroupVersion: 		return &meta.VersionInterfaces{ 			ObjectConvertor:  api.Scheme, 			MetadataAccessor: accessor, 		}, nil 	default: 		g, _ := registered.Group(api.GroupName) 		return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions) 	} } 
  | 
可以看到newRESTMapper()调用了api.NewDefaultRESTMapper()来生成mapper。api.NewDefaultRESTMapper()定义在/pkg/api/mapper.go中:
1 2 3 4 5 
  | func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, interfacesFunc meta.VersionInterfacesFunc, 	importPathPrefix string, ignoredKinds, rootScoped sets.String) *meta.DefaultRESTMapper { 	return NewDefaultRESTMapperFromScheme(defaultGroupVersions, interfacesFunc, importPathPrefix, ignoredKinds, rootScoped, Scheme) } 
  | 
这下明了了,NewDefaultRESTMapper()调用了入口函数NewDefaultRESTMapperFromScheme()。
/apis下的DefaultRESTMapper
这里是指放在/pkg/apis下面的GroupVersion。在apis下面的GroupVersion,采用了apimachinery机制来管理包和版本的信息。感觉v1也可以用apimachinery机制来管理,毕竟都要注册到registered.DefaultAPIRegistrationManager中。
先来看/pkg/apis/apps/install/install.go中的init()函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
  | func init() { 	if err := announced.NewGroupMetaFactory( 		&announced.GroupMetaFactoryArgs{ 			GroupName:                  apps.GroupName, 			VersionPreferenceOrder:     []string{v1beta1.SchemeGroupVersion.Version}, 			ImportPrefix:               "k8s.io/kubernetes/pkg/apis/apps", 			AddInternalObjectsToScheme: apps.AddToScheme, 		}, 		announced.VersionToSchemeFunc{ 			v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, 		}, 	).Announce().RegisterAndEnable(); err != nil { 		panic(err) 	} } 
  | 
再来看/pkg/apimachinery/announced/group_factory.go中的RegisterAndEnable()函数:
1 2 3 4 5 6 7 8 9 10 11 
  | func (gmf *GroupMetaFactory) RegisterAndEnable() error { 	if err := gmf.Register(registered.DefaultAPIRegistrationManager); err != nil { 		return err 	} 	 	if err := gmf.Enable(registered.DefaultAPIRegistrationManager, api.Scheme); err != nil { 		return err 	} 	return nil } 
  | 
接着看Enable()函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 
  | func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error { 	externalVersions := []unversioned.GroupVersion{} 	for _, v := range gmf.prioritizedVersionList { 		if !m.IsAllowedVersion(v) { 			continue 		} 		externalVersions = append(externalVersions, v) 		if err := m.EnableVersions(v); err != nil { 			return err 		} 		 		gmf.VersionArgs[v.Version].AddToScheme(scheme) 	} 	if len(externalVersions) == 0 { 		glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName) 		return nil 	} 	 	if gmf.GroupArgs.AddInternalObjectsToScheme != nil { 		gmf.GroupArgs.AddInternalObjectsToScheme(scheme) 	} 	preferredExternalVersion := externalVersions[0] 	accessor := meta.NewAccessor() 	groupMeta := &apimachinery.GroupMeta{ 		GroupVersion:  preferredExternalVersion, 		GroupVersions: externalVersions, 		SelfLinker:    runtime.SelfLinker(accessor), 	} 	for _, v := range externalVersions { 		gvf := gmf.VersionArgs[v.Version] 		 		if err := groupMeta.AddVersionInterfaces( 			unversioned.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName}, 			&meta.VersionInterfaces{ 				ObjectConvertor:  scheme, 				MetadataAccessor: accessor, 			}, 		); err != nil { 			return err 		} 	} 	 	groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor 	 	groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta) 	 	if err := m.RegisterGroup(*groupMeta); err != nil { 		return err 	} 	return nil } 
  | 
生成Mapper的语句为:groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta),所以来看gmf的newRESTMapper()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
  | func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []unversioned.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper { 	 	 	rootScoped := sets.NewString() 	if gmf.GroupArgs.RootScopedKinds != nil { 		rootScoped = gmf.GroupArgs.RootScopedKinds 	} 	ignoredKinds := sets.NewString() 	if gmf.GroupArgs.IgnoredKinds != nil { 		ignoredKinds = gmf.GroupArgs.IgnoredKinds 	} 	return api.NewDefaultRESTMapperFromScheme( 		externalVersions, 		groupMeta.InterfacesFor, 		gmf.GroupArgs.ImportPrefix, 		ignoredKinds, 		rootScoped, 		scheme, 	) } 
  | 
可以发现,DefaultRESTMapper的生成入口函数出现了。当然,这里仅以RESTMapper作为主线进行分析,详细的apimachinery机制以后会介绍。
总结
在总结中,梳理下DefaultRESTMapper在系统中的位置。在系统中,有一个DefaultAPIRegistrationManager管理着系统中所有GroupVersion的信息,这些信息由groupMeta承载,而groupMeta中就有DefaultRESTMapper。所以v1和/apis中的GroupVersion都会生成自己DefaultRESTMapper,不同的是/apis中的GroupVersion把一切交由apimachinery机制来。
当然,现在只需知道有这些概念即可。