生成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机制来。
当然,现在只需知道有这些概念即可。