生成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)
// enumerate all supported versions, get the kinds, and register with the mapper how to address
// our resources.
for _, gv := range defaultGroupVersions {
for kind, oType := range scheme.KnownTypes(gv) {
gvk := gv.WithKind(kind)
// TODO: Remove import path check.
// We check the import path because we currently stuff both "api" and "extensions" objects
// into the same group within Scheme since Scheme has no notion of groups yet.
if !strings.Contains(oType.PkgPath(), importPathPrefix) || ignoredKinds.Has(kind) {
continue
}
scope := meta.RESTScopeNamespace
//***/pkg/api/install/install.go中定义***//
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,
}
//***向registered.DefaultAPIRegistrationManager注册groupMeta***//
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 {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
//***全局资源***//
rootScoped := sets.NewString(
"Node",
"Namespace",
"PersistentVolume",
"ComponentStatus",
)
// these kinds should be excluded from the list of resources
ignoredKinds := sets.NewString(
"ListOptions",
"DeleteOptions",
"Status",
"PodLogOptions",
"PodExecOptions",
"PodAttachOptions",
"PodProxyOptions",
"NodeProxyOptions",
"ServiceProxyOptions",
"ThirdPartyResource",
"ThirdPartyResourceData",
"ThirdPartyResourceList")
//***调用的是/api/mapper.go中的NewDefaultRESTMapper()***//
//***externalVersions: [v1]***//
mapper := api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
return mapper
}
//***返回v1对应的VersionInterfaces,包含api.Scheme和accessor***//
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
// Instantiates a DefaultRESTMapper based on types registered in api.Scheme
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
}
//***向api.Scheme注册***//
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
//***调用相应的Scheme添加函数***//
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
}
//***注册具体版本的类型,如:v1beta1.AddToScheme***//
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
}
//***注册内部版本的类型,如:apps.AddToScheme***//
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]
//***向groupMeta添加interfacesFor()函数***//
if err := groupMeta.AddVersionInterfaces(
unversioned.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName},
&meta.VersionInterfaces{
ObjectConvertor: scheme,
MetadataAccessor: accessor,
},
); err != nil {
return err
}
}
//***定义InterfacesFor***//
groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor
//***生成RESTMapper***//
groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta)
//***向APIRegistrationManager注册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 {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
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机制来。

当然,现在只需知道有这些概念即可。