Object

Overview

api-machinery-object-relation.svg
Object 实例如下所示,基本都在 pkg/apis 目录下,自己查找即可。
image.png

Unstructured

image.png
Unstructured 与 Object 配合使用的场景如下
image.png
实例图如下
api-machinery-unstructured.svg

Scheme

Builder

scheme-builder.svg

Scheme

看一下 Scheme 的定义,前四项都是在维护 reflect.Type 与 schema.GroupVersionKind 的关系。defaulterFuncs 用于构建默认对象。

  1. type Scheme struct {
  2. // versionMap allows one to figure out the go type of an object with
  3. // the given version and name.
  4. gvkToType map[schema.GroupVersionKind]reflect.Type
  5. // typeToGroupVersion allows one to find metadata for a given go object.
  6. // The reflect.Type we index by should *not* be a pointer.
  7. typeToGVK map[reflect.Type][]schema.GroupVersionKind
  8. // unversionedTypes are transformed without conversion in ConvertToVersion.
  9. unversionedTypes map[reflect.Type]schema.GroupVersionKind
  10. // unversionedKinds are the names of kinds that can be created in the context of any group
  11. // or version
  12. // TODO: resolve the status of unversioned types.
  13. unversionedKinds map[string]reflect.Type
  14. // Map from version and resource to the corresponding func to convert
  15. // resource field labels in that version to internal version.
  16. fieldLabelConversionFuncs map[schema.GroupVersionKind]FieldLabelConversionFunc
  17. // defaulterFuncs is an array of interfaces to be called with an object to provide defaulting
  18. // the provided object must be a pointer.
  19. defaulterFuncs map[reflect.Type]func(interface{})
  20. // converter stores all registered conversion functions. It also has
  21. // default converting behavior.
  22. converter *conversion.Converter
  23. // versionPriority is a map of groups to ordered lists of versions for those groups indicating the
  24. // default priorities of these versions as registered in the scheme
  25. versionPriority map[string][]string
  26. // observedVersions keeps track of the order we've seen versions during type registration
  27. observedVersions []schema.GroupVersion
  28. // schemeName is the name of this scheme. If you don't specify a name, the stack of the NewScheme caller will be used.
  29. // This is useful for error reporting to indicate the origin of the scheme.
  30. schemeName string
  31. }

FieldLabelConversionFunc 用于将 label、value 转换为内部 label、value。

  1. type FieldLabelConversionFunc func(label, value string) (internalLabel, internalValue string, err error)

AddKnownTypes

AddKnownTypes 只需要注意一个问题,即从传入的 GroupVersion 通过 reflect.Type 的 Name 方法返回值作为 Kind 生成 GroupVersionKind,请看简化后的示例 Reflect Name Sample,示例代码可在 Go Playground 下执行。

scheme-add-known-types.svg

AddUnversionedTypes

AddUnversionedTypes 原理如下。可以将 Unversioned Type 理解为一个 Object 挂载在一个 Group 上,且 Version 永不更新。

scheme-add-unversioned.svg

nameFunc

nameFunc 原理如下,只要注意返回类型优先为 Internal Type 就可以了。

scheme-name-func.svg

Others

Conversion

Landscape

conversion-landscape.svg

typePair 用来表示源类型与目标类型的组合;typeNamePair 存储类型及类型名称;DefaultNameFunc 用做默认的类型到 Name 的转换方法。ConversionFunc 定义了对象转换方法。

Core Function Definitions

DefaultNameFunc 实现如下所示

  1. var DefaultNameFunc = func(t reflect.Type) string { return t.Name() }

ConversionFunc 声明如下所示

  1. type ConversionFunc func(a, b interface{}, scope Scope) error

FieldMappingFunc 将 key 转换为源结构及目标结构中的 Field

  1. type FieldMappingFunc func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string)

ConversionFuncs

conversion-funcs.svg

Converter

converter.svg

将下列方法做简要说明:

doConversion

Converter 在执行对象转换方法时,如 ConvertDefaultConvert 允许传入一个 Meta 对象,并执行 doConversion 方法,在这个方法中构建 scope 对象。
converter-conversion.svg

Scope

scope-landscape.svg

defaultConvert

defaultConvert 处理默认的类型变换,传入的 sv, dv 已经经由 EnforcePtr 确保为可寻址。这部分代码是对 Go 中 reflect 包近乎完美的应用。
首先,处理基本类型的转换,即可通过 AssignableToConvertibleTo 转换的类型。

  1. switch st.Kind() {
  2. case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct:
  3. // 这些类型后续处理
  4. default:
  5. // This should handle all simple types.
  6. if st.AssignableTo(dt) {
  7. dv.Set(sv)
  8. return nil
  9. }
  10. if st.ConvertibleTo(dt) {
  11. dv.Set(sv.Convert(dt))
  12. return nil
  13. }
  14. }

然后根据 dv.Kind() 分别进行处理。

dv.Kind() -> reflect.Struct

直接返回 convertKV 方法的结果,但是,需要注意,首先将 sv、dv 分别转化为 Key/Value 的形式。toKVValue 方法请自行研究。

  1. return c.convertKV(toKVValue(sv), toKVValue(dv), scope)

dv.Kind() -> reflect.Slice
  1. case reflect.Slice:
  2. if sv.IsNil() {
  3. // Don't make a zero-length slice.
  4. dv.Set(reflect.Zero(dt))
  5. return nil
  6. }
  7. dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap()))
  8. for i := 0; i < sv.Len(); i++ {
  9. scope.setIndices(i, i)
  10. if err := c.convert(sv.Index(i), dv.Index(i), scope); err != nil {
  11. return err
  12. }
  13. }

dv.Kind() -> reflect.Ptr
  1. case reflect.Ptr:
  2. if sv.IsNil() {
  3. // Don't copy a nil ptr!
  4. dv.Set(reflect.Zero(dt))
  5. return nil
  6. }
  7. dv.Set(reflect.New(dt.Elem()))
  8. switch st.Kind() {
  9. case reflect.Ptr, reflect.Interface:
  10. return c.convert(sv.Elem(), dv.Elem(), scope)
  11. default:
  12. return c.convert(sv, dv.Elem(), scope)
  13. }

dv.Kind() -> reflect.Interface
  1. case reflect.Interface:
  2. if sv.IsNil() {
  3. // Don't copy a nil interface!
  4. dv.Set(reflect.Zero(dt))
  5. return nil
  6. }
  7. tmpdv := reflect.New(sv.Elem().Type()).Elem()
  8. if err := c.convert(sv.Elem(), tmpdv, scope); err != nil {
  9. return err
  10. }
  11. dv.Set(reflect.ValueOf(tmpdv.Interface()))
  12. return nil

dv.Kind() -> reflect.Map
  1. case reflect.Map:
  2. if sv.IsNil() {
  3. // Don't copy a nil ptr!
  4. dv.Set(reflect.Zero(dt))
  5. return nil
  6. }
  7. dv.Set(reflect.MakeMap(dt))
  8. for _, sk := range sv.MapKeys() {
  9. dk := reflect.New(dt.Key()).Elem()
  10. if err := c.convert(sk, dk, scope); err != nil {
  11. return err
  12. }
  13. dkv := reflect.New(dt.Elem()).Elem()
  14. scope.setKeys(sk.Interface(), dk.Interface())
  15. if err := c.convert(sv.MapIndex(sk), dkv, scope); err != nil {
  16. return err
  17. }
  18. dv.SetMapIndex(dk, dkv)
  19. }