什么是Scheme
如果说RESTMapper管理的是GVR和GVK的关系,那么Scheme管理的就是GVK和Type的关系。系统中所有的Type都要注册到Scheme中,当然目前系统只有一个Scheme,即api.Scheme,定义在/pkg/api/register.go中:
1 2
| var Scheme = runtime.NewScheme()
|
我们先来看下Scheme结构体的定义,Scheme结构体定义在/pkg/runtime/scheme.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
| type Scheme struct { gvkToType map[unversioned.GroupVersionKind]reflect.Type typeToGVK map[reflect.Type][]unversioned.GroupVersionKind unversionedTypes map[reflect.Type]unversioned.GroupVersionKind unversionedKinds map[string]reflect.Type fieldLabelConversionFuncs map[string]map[string]FieldLabelConversionFunc defaulterFuncs map[reflect.Type]func(interface{}) // converter stores all registered conversion functions. It also has // default coverting behavior. //***聚合converter结构体***// converter *conversion.Converter // cloner stores all registered copy functions. It also has default // deep copy behavior. //***Fankang***// //***聚合cloner结构体***// cloner *conversion.Cloner }
|
可以看出,Scheme除了管理GVK和Type的关系,还管理有默认设置函数,并聚合了converter及cloner。我们来详细看下每个字段的含义:
- gvkToType: 存储gvk和Type的关系,一个gvk只能对应一个Type;
- typeToGVK:存储Type和gvk的关系,一个type可能对应多个GVK;
- unversionedTypes:记录unversioned的Type和GVK的关系,unversioned无需版本转换;
- unversionedKinds:记录unversioned的GVK和Type的关系;
- fieldLabelConversionFuncs:管理field selector的转换,如旧版本v1的spec.host需要转换成spec.nodeName(详见在/pkg/api/v1/conversion.go中的addConversionFuncs()函数);
- defaulterFuncs:存储Type及其对应的默认值设置函数;
- converter:用来转换不同版本的结构体值;
- cloner:用来获取结构体值的拷贝。
Kubernetes内部组件的流通的结构体值使用的是内部版本,所有的外部版本都要向内部版本进行转换;内部版本必须转换成外部版本才能进行输出。外部版本之间不能直接转换。
从Scheme的定义可以看出,Scheme是个converter,也是个cloner,关于converter和cloner,后续分析。
NewScheme()
NewScheme()可以生成一个新的Scheme,其中cloner调用conversion.NewCloner()初始化,converter调用conversion.NewConverter()初始化。
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
| func NewScheme() *Scheme { s := &Scheme{ gvkToType: map[unversioned.GroupVersionKind]reflect.Type{}, typeToGVK: map[reflect.Type][]unversioned.GroupVersionKind{}, unversionedTypes: map[reflect.Type]unversioned.GroupVersionKind{}, unversionedKinds: map[string]reflect.Type{}, cloner: conversion.NewCloner(), fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{}, defaulterFuncs: map[reflect.Type]func(interface{}){}, } s.converter = conversion.NewConverter(s.nameFunc) s.AddConversionFuncs(DefaultEmbeddedConversions()...) if err := s.AddConversionFuncs(DefaultStringConversions...); err != nil { panic(err) } if err := s.RegisterInputDefaults(&map[string][]string{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil { panic(err) } if err := s.RegisterInputDefaults(&url.Values{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil { panic(err) } return s }
|
AddUnversionedTypes()
AddUnversionedTypes()方法可以向Scheme注册unvertioned type,方法先调用AddKnownTypes(),然后填充unversionedTypes和unversionedKinds两个map,在/api/register.go中有调用。Unversioned type不需要进行转换。
1 2 3 4 5 6 7 8 9 10 11 12
| func (s *Scheme) AddUnversionedTypes(version unversioned.GroupVersion, types ...Object) { s.AddKnownTypes(version, types...) for _, obj := range types { t := reflect.TypeOf(obj).Elem() gvk := version.WithKind(t.Name()) s.unversionedTypes[t] = gvk if _, ok := s.unversionedKinds[gvk.Kind]; ok { panic(fmt.Sprintf("%v has already been registered as unversioned kind %q - kind name must be unique", reflect.TypeOf(t), gvk.Kind)) } s.unversionedKinds[gvk.Kind] = t } }
|
AddKnownTypes()
AddKnownTypes()为Scheme的type注册函数,参数为GV及types,其中types和GV先组成GVK,然后向gvkToType和typeToGVK填充Type和GVK的关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| func (s *Scheme) AddKnownTypes(gv unversioned.GroupVersion, types ...Object) { if len(gv.Version) == 0 { panic(fmt.Sprintf("version is required on all types: %s %v", gv, types[0])) } for _, obj := range types { t := reflect.TypeOf(obj) if t.Kind() != reflect.Ptr { panic("All types must be pointers to structs.") } t = t.Elem() if t.Kind() != reflect.Struct { panic("All types must be pointers to structs.") } gvk := gv.WithKind(t.Name()) s.gvkToType[gvk] = t s.typeToGVK[t] = append(s.typeToGVK[t], gvk) } }
|
AddKnownTypeWithName()
AddKnownTypeWithName()可以指定object对应的gvk。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| func (s *Scheme) AddKnownTypeWithName(gvk unversioned.GroupVersionKind, obj Object) { t := reflect.TypeOf(obj) if len(gvk.Version) == 0 { panic(fmt.Sprintf("version is required on all types: %s %v", gvk, t)) } if t.Kind() != reflect.Ptr { panic("All types must be pointers to structs.") } t = t.Elem() if t.Kind() != reflect.Struct { panic("All types must be pointers to structs.") } s.gvkToType[gvk] = t s.typeToGVK[t] = append(s.typeToGVK[t], gvk) }
|
KnownTypes()
KnownTypes()返回Scheme中具体版本下的gvk和type的map关系。
1 2 3 4 5 6 7 8 9 10 11 12 13
| func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type { types := make(map[string]reflect.Type) for gvk, t := range s.gvkToType { if gv != gvk.GroupVersion() { continue } types[gvk.Kind] = t } return types }
|
AllKnownTypes()
AllKnownTypes()返回Scheme中所有版本的gvk和type的map关系。
1 2 3 4
| func (s *Scheme) AllKnownTypes() map[unversioned.GroupVersionKind]reflect.Type { return s.gvkToType }
|
ObjectKind() ObjectKinds()
ObjectKinds()通过obj的type获取对应的GVK(可能存在多个GVK);ObjectKind()则在ObjectKinds()的基础上返回第一个GVk。
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
| func (s *Scheme) ObjectKind(obj Object) (unversioned.GroupVersionKind, bool, error) { gvks, unversionedType, err := s.ObjectKinds(obj) if err != nil { return unversioned.GroupVersionKind{}, false, err } return gvks[0], unversionedType, nil } func (s *Scheme) ObjectKinds(obj Object) ([]unversioned.GroupVersionKind, bool, error) { v, err := conversion.EnforcePtr(obj) if err != nil { return nil, false, err } t := v.Type() gvks, ok := s.typeToGVK[t] if !ok { return nil, false, NewNotRegisteredErr(unversioned.GroupVersionKind{}, t) } _, unversionedType := s.unversionedTypes[t] return gvks, unversionedType, nil }
|
Recognizes()
Recognizes()判断GVK在Scheme中是否有注册。
1 2 3 4
| func (s *Scheme) Recognizes(gvk unversioned.GroupVersionKind) bool { _, exists := s.gvkToType[gvk] return exists }
|
IsUnversioned()
IsUnversioned()判断obj是否属于unversioned。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| func (s *Scheme) IsUnversioned(obj Object) (bool, bool) { v, err := conversion.EnforcePtr(obj) if err != nil { return false, false } t := v.Type() if _, ok := s.typeToGVK[t]; !ok { return false, false } _, ok := s.unversionedTypes[t] return ok, true }
|
New()
New()可以创建一个gvk类型的结构体值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| func (s *Scheme) New(kind unversioned.GroupVersionKind) (Object, error) { if t, exists := s.gvkToType[kind]; exists { return reflect.New(t).Interface().(Object), nil } if t, exists := s.unversionedKinds[kind.Kind]; exists { return reflect.New(t).Interface().(Object), nil } return nil, NewNotRegisteredErr(kind, nil) }
|
AddGenericConversionFunc()
AddGenericConversionFunc()是对converter的AddGenericConversionFunc()方法的封装,关于converter将在以后分析。
1 2 3 4 5
| func (s *Scheme) AddGenericConversionFunc(fn conversion.GenericConversionFunc) { s.converter.AddGenericConversionFunc(fn) }
|
AddIgnoredConversionType()
AddIgnoredConversionType()是对converter的RegisterIgnoredConversion()方法的封闭,关于converter将在以后分析。
1 2 3 4
| func (s *Scheme) AddIgnoredConversionType(from, to interface{}) error { return s.converter.RegisterIgnoredConversion(from, to) }
|
AddConversionFuncs()
AddConversionFuncs()可以向converter注册转换函数,关于converter将在以后分析。
1 2 3 4 5 6 7 8 9 10
| func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error { for _, f := range conversionFuncs { if err := s.converter.RegisterConversionFunc(f); err != nil { return err } } return nil }
|
AddGeneratedConversionFuncs()
AddGeneratedConversionFuncs()可以向converter注册GeneratedConversionFuncs,其中GeneratedConversionFuncs为自动生成的转换函数,关于converter将在以后分析。
1 2 3 4 5 6 7 8 9
| func (s *Scheme) AddGeneratedConversionFuncs(conversionFuncs ...interface{}) error { for _, f := range conversionFuncs { if err := s.converter.RegisterGeneratedConversionFunc(f); err != nil { return err } } return nil }
|
AddDeepCopyFuncs()
AddDeepCopyFuncs()可以向cloner注册克隆函数,关于cloner将在以后分析。
1 2 3 4 5 6 7 8 9 10
| func (s *Scheme) AddDeepCopyFuncs(deepCopyFuncs ...interface{}) error { for _, f := range deepCopyFuncs { if err := s.cloner.RegisterDeepCopyFunc(f); err != nil { return err } } return nil }
|
AddGeneratedDeepCopyFuncs()
AddGeneratedDeepCopyFuncs()可以向cloner注册GeneratedDeepCopyFuncs,其中GeneratedDeepCopyFuncs为自动生成的克隆函数,关于cloner将在以后分析。
1 2 3 4 5 6 7 8 9
| func (s *Scheme) AddGeneratedDeepCopyFuncs(deepCopyFuncs ...conversion.GeneratedDeepCopyFunc) error { for _, fn := range deepCopyFuncs { if err := s.cloner.RegisterGeneratedDeepCopyFunc(fn); err != nil { return err } } return nil }
|
AddFieldLabelConversionFunc()
AddFieldLabelConversionFunc()可以向Scheme注册field selector转换函数。
1 2 3 4 5 6 7 8 9
| func (s *Scheme) AddFieldLabelConversionFunc(version, kind string, conversionFunc FieldLabelConversionFunc) error { if s.fieldLabelConversionFuncs[version] == nil { s.fieldLabelConversionFuncs[version] = map[string]FieldLabelConversionFunc{} } s.fieldLabelConversionFuncs[version][kind] = conversionFunc return nil }
|
AddStructFieldConversion()
AddStructFieldConversion()可以向converter注册struct字段转换函数,关于cloner将在以后分析。
1 2 3 4
| func (s *Scheme) AddStructFieldConversion(srcFieldType interface{}, srcFieldName string, destFieldType interface{}, destFieldName string) error { return s.converter.SetStructFieldCopy(srcFieldType, srcFieldName, destFieldType, destFieldName) }
|
RegisterInputDefaults()可以向convertor注册转换发生缺省时默认的处理方式函数。
1 2 3
| func (s *Scheme) RegisterInputDefaults(in interface{}, fn conversion.FieldMappingFunc, defaultFlags conversion.FieldMatchingFlags) error { return s.converter.RegisterInputDefaults(in, fn, defaultFlags) }
|
AddDefaultingFuncs()
AddDefaultingFuncs()可以向converter注册DefaultingFunc函数,DefaultingFunc函数可以设置相关结构体值的默认值。
1 2 3 4 5 6 7 8 9 10
| func (s *Scheme) AddDefaultingFuncs(defaultingFuncs ...interface{}) error { for _, f := range defaultingFuncs { err := s.converter.RegisterDefaultingFunc(f) if err != nil { return err } } return nil }
|
Default()
Default()可以对object设置默认值。
1 2 3 4 5 6
| func (s *Scheme) Default(src Object) { if fn, ok := s.defaulterFuncs[reflect.TypeOf(src)]; ok { fn(src) } }
|
Copy()
Copy()是对cloner.DeepCopy()的封装,可以拷贝一个object。
1 2 3 4 5 6 7 8 9 10 11 12 13
| func (s *Scheme) Copy(src Object) (Object, error) { dst, err := s.DeepCopy(src) if err != nil { return nil, err } return dst.(Object), nil } func (s *Scheme) DeepCopy(src interface{}) (interface{}, error) { return s.cloner.DeepCopy(src) }
|
Convert()
Convert()是对converter.Convert()的封装。
1 2 3 4 5 6 7 8 9
| func (s *Scheme) Convert(in, out interface{}, context interface{}) error { flags, meta := s.generateConvertMeta(in) meta.Context = context if flags == 0 { flags = conversion.AllowDifferentFieldTypeNames } return s.converter.Convert(in, out, flags, meta) }
|
ConvertFieldLabel()
ConvertFieldLabel()可以对field selector进行转换。
1 2 3 4 5 6 7 8 9 10 11
| func (s *Scheme) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { if s.fieldLabelConversionFuncs[version] == nil { return "", "", fmt.Errorf("No field label conversion function found for version: %s", version) } conversionFunc, ok := s.fieldLabelConversionFuncs[version][kind] if !ok { return "", "", fmt.Errorf("No field label conversion function found for version %s and kind %s", version, kind) } return conversionFunc(label, value) }
|
ConvertToVersion()
ConvertToVersion()可以把in转换成合适的版本。
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| func (s *Scheme) ConvertToVersion(in Object, target GroupVersioner) (Object, error) { return s.convertToVersion(true, in, target) } func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) (Object, error) { t := reflect.TypeOf(in) if t.Kind() != reflect.Ptr { return nil, fmt.Errorf("only pointer types may be converted: %v", t) } t = t.Elem() if t.Kind() != reflect.Struct { return nil, fmt.Errorf("only pointers to struct types may be converted: %v", t) } kinds, ok := s.typeToGVK[t] if !ok || len(kinds) == 0 { return nil, NewNotRegisteredErr(unversioned.GroupVersionKind{}, t) } gvk, ok := target.KindForGroupVersionKinds(kinds) if !ok { if unversionedKind, ok := s.unversionedTypes[t]; ok { if gvk, ok := target.KindForGroupVersionKinds([]unversioned.GroupVersionKind{unversionedKind}); ok { return copyAndSetTargetKind(copy, s, in, gvk) } return copyAndSetTargetKind(copy, s, in, unversionedKind) } return nil, fmt.Errorf("%v is not suitable for converting to %q", t, target) } for _, kind := range kinds { if gvk == kind { return copyAndSetTargetKind(copy, s, in, gvk) } } if unversionedKind, ok := s.unversionedTypes[t]; ok { if gvk, ok := target.KindForGroupVersionKinds([]unversioned.GroupVersionKind{unversionedKind}); ok { return copyAndSetTargetKind(copy, s, in, gvk) } return copyAndSetTargetKind(copy, s, in, unversionedKind) } out, err := s.New(gvk) if err != nil { return nil, err } if copy { copied, err := s.Copy(in) if err != nil { return nil, err } in = copied } flags, meta := s.generateConvertMeta(in) meta.Context = target if err := s.converter.Convert(in, out, flags, meta); err != nil { return nil, err } setTargetKind(out, gvk) return out, nil }
|