0、interfaces

  1. // 一个序列化器的名字
  2. type Identifier string
  3. // 编码一个obj
  4. type Encoder interface {
  5. // 如果版本不相容或者版本未定义,需要抛出异常
  6. Encode(obj Object, w io.Writer) error
  7. // 为了兼容CacheableObject,定义Encode函数需要形式如下:
  8. // func (e *MyEncoder) Encode(obj Object, w io.Writer) error {
  9. // if co, ok := obj.(CacheableObject); ok {
  10. // return co.CacheEncode(e.Identifier(), e.doEncode, w)
  11. // }
  12. // return e.doEncode(obj, w)
  13. // }
  14. Identifier() Identifier
  15. }
  16. // 解码一个obj
  17. type Decoder interface {
  18. // 解码器将尝试将data解码为固有的类型或者提供的默认类型
  19. // 它返回一个解码后的obj和其gvk信息
  20. // 如果into非nil,则into将会作为目标类型。解码器将选择使用给定的obj而不用重新生成一个
  21. // 当前into对象不保证会被填充。返回的obi不保证匹配into
  22. // 如果提供了默认值,则他们将会被应用到数据里面。否则into的类型将会被用于决策使用何种版本的obj
  23. Decode(data []byte, defaults *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error)
  24. }
  25. // 核心接口
  26. type Serializer interface {
  27. Encoder
  28. Decoder
  29. }
  30. type Codec Serializer
  31. type Framer interface {
  32. NewFrameReader(r io.ReadCloser) io.ReadCloser
  33. NewFrameWriter(w io.Writer) io.Writer
  34. }
  35. // 对一个序列化器的信息描述
  36. type SerializerInfo struct {
  37. // 类型 -> application/json
  38. MediaType string
  39. // application in application/json
  40. MediaTypeType string
  41. // json in application/json
  42. MediaTypeSubType string
  43. // 是否可以安全的编码为utf8格式
  44. EncodesAsText bool
  45. // 具体的序列化器
  46. Serializer Serializer
  47. // 可读性较高的序列化器(用于json格式)
  48. PrettySerializer Serializer
  49. // 流式序列化器
  50. StreamSerializer *StreamSerializerInfo
  51. }
  52. // 包含多种格式的序列化器,apiserver的handler持有的就是此接口
  53. // 实际就是CodecFactory
  54. type NegotiatedSerializer interface {
  55. // 支持的所有类型的序列化器
  56. SupportedMediaTypes() []SerializerInfo
  57. // 返回一个编码器并保证将对象写入到给定的gv中
  58. EncoderForVersion(serializer Encoder, gv GroupVersioner) Encoder
  59. // 返回一个解码器并保证将对象写入到给定的gv中(此处的GroupVersioner一般为给定的__internal版本)
  60. DecoderToVersion(serializer Decoder, gv GroupVersioner) Decoder
  61. }
  62. // 判断data是否符合自己的格式要求
  63. type RecognizingDecoder interface {
  64. runtime.Decoder
  65. RecognizesData(peek io.Reader) (ok, unknown bool, err error)
  66. }
  67. // 通常用于rest客户端
  68. type ClientNegotiator interface {
  69. Encoder(contentType string, params map[string]string) (Encoder, error)
  70. Decoder(contentType string, params map[string]string) (Decoder, error)
  71. StreamDecoder(contentType string, params map[string]string) (Decoder, Serializer, Framer, error)
  72. }
  73. // 存储的序列化器,可用于存储restful obj
  74. type StorageSerializer interface {
  75. SupportedMediaTypes() []SerializerInfo
  76. UniversalDeserializer() Decoder
  77. EncoderForVersion(serializer Encoder, gv GroupVersioner) Encoder
  78. DecoderToVersion(serializer Decoder, gv GroupVersioner) Decoder
  79. }
  80. // ParameterCodec defines methods for serializing and deserializing API objects to url.Values and
  81. // performing any necessary conversion. Unlike the normal Codec, query parameters are not self describing
  82. // and the desired version must be specified.
  83. type ParameterCodec interface {
  84. // DecodeParameters takes the given url.Values in the specified group version and decodes them
  85. // into the provided object, or returns an error.
  86. DecodeParameters(parameters url.Values, from schema.GroupVersion, into Object) error
  87. // EncodeParameters encodes the provided object as query parameters or returns an error.
  88. EncodeParameters(obj Object, to schema.GroupVersion) (url.Values, error)
  89. }
  90. // StreamSerializerInfo contains information about a specific stream serialization format
  91. type StreamSerializerInfo struct {
  92. // EncodesAsText indicates this serializer can be encoded to UTF-8 safely.
  93. EncodesAsText bool
  94. // Serializer is the top level object serializer for this type when streaming
  95. Serializer
  96. // Framer is the factory for retrieving streams that separate objects on the wire
  97. Framer
  98. }
  99. // 暂时不清楚这两个接口的作用
  100. type NestedObjectEncoder interface {
  101. EncodeNestedObjects(e Encoder) error
  102. }
  103. type NestedObjectDecoder interface {
  104. DecodeNestedObjects(d Decoder) error
  105. }

1、serializerType

  1. // 每一种序列化器对应一个具体的serializerType
  2. type serializerType struct {
  3. AcceptContentTypes []string // 可接受的类型
  4. ContentType string
  5. FileExtensions []string
  6. EncodesAsText bool
  7. Serializer runtime.Serializer
  8. PrettySerializer runtime.Serializer
  9. AcceptStreamContentTypes []string
  10. StreamContentType string
  11. Framer runtime.Framer
  12. StreamSerializer runtime.Serializer
  13. }
  14. // 默认初始化了3中序列化器
  15. // json/yaml/protobuf(其中json/yaml其实用的是一个实现struct json.Serializer)
  16. func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType {
  17. jsonSerializer := json.NewSerializerWithOptions(
  18. mf, scheme, scheme,
  19. json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},
  20. )
  21. jsonSerializerType := serializerType{
  22. AcceptContentTypes: []string{runtime.ContentTypeJSON},
  23. ContentType: runtime.ContentTypeJSON,
  24. FileExtensions: []string{"json"},
  25. EncodesAsText: true,
  26. Serializer: jsonSerializer,
  27. Framer: json.Framer,
  28. StreamSerializer: jsonSerializer,
  29. }
  30. if options.Pretty {
  31. jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions(
  32. mf, scheme, scheme,
  33. json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict},
  34. )
  35. }
  36. yamlSerializer := json.NewSerializerWithOptions(
  37. mf, scheme, scheme,
  38. json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict},
  39. )
  40. protoSerializer := protobuf.NewSerializer(scheme, scheme)
  41. protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)
  42. serializers := []serializerType{
  43. jsonSerializerType,
  44. {
  45. AcceptContentTypes: []string{runtime.ContentTypeYAML},
  46. ContentType: runtime.ContentTypeYAML,
  47. FileExtensions: []string{"yaml"},
  48. EncodesAsText: true,
  49. Serializer: yamlSerializer,
  50. },
  51. {
  52. AcceptContentTypes: []string{runtime.ContentTypeProtobuf},
  53. ContentType: runtime.ContentTypeProtobuf,
  54. FileExtensions: []string{"pb"},
  55. Serializer: protoSerializer,
  56. Framer: protobuf.LengthDelimitedFramer,
  57. StreamSerializer: protoRawSerializer,
  58. },
  59. }
  60. for _, fn := range serializerExtensions {
  61. if serializer, ok := fn(scheme); ok {
  62. serializers = append(serializers, serializer)
  63. }
  64. }
  65. return serializers
  66. }

2、RecognizingDecoder

  1. func NewDecoder(decoders ...runtime.Decoder) runtime.Decoder {
  2. return &decoder{
  3. decoders: decoders,
  4. }
  5. }
  6. type decoder struct {
  7. decoders []runtime.Decoder
  8. }
  9. var _ RecognizingDecoder = &decoder{}
  10. func (d *decoder) RecognizesData(peek io.Reader) (bool, bool, error) {
  11. var (
  12. lastErr error
  13. anyUnknown bool
  14. )
  15. data, _ := bufio.NewReaderSize(peek, 1024).Peek(1024)
  16. for _, r := range d.decoders {
  17. switch t := r.(type) {
  18. case RecognizingDecoder:
  19. ok, unknown, err := t.RecognizesData(bytes.NewBuffer(data))
  20. if err != nil {
  21. lastErr = err
  22. continue
  23. }
  24. anyUnknown = anyUnknown || unknown
  25. if !ok {
  26. continue
  27. }
  28. return true, false, nil
  29. }
  30. }
  31. return false, anyUnknown, lastErr
  32. }
  33. func (d *decoder) Decode(data []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
  34. var (
  35. lastErr error
  36. skipped []runtime.Decoder
  37. )
  38. // try recognizers, record any decoders we need to give a chance later
  39. for _, r := range d.decoders {
  40. switch t := r.(type) {
  41. case RecognizingDecoder:
  42. buf := bytes.NewBuffer(data)
  43. ok, unknown, err := t.RecognizesData(buf)
  44. if err != nil {
  45. lastErr = err
  46. continue
  47. }
  48. if unknown {
  49. skipped = append(skipped, t)
  50. continue
  51. }
  52. if !ok {
  53. continue
  54. }
  55. return r.Decode(data, gvk, into)
  56. default:
  57. skipped = append(skipped, t)
  58. }
  59. }
  60. for _, r := range skipped {
  61. out, actual, err := r.Decode(data, gvk, into)
  62. if err != nil {
  63. lastErr = err
  64. continue
  65. }
  66. return out, actual, nil
  67. }
  68. if lastErr == nil {
  69. lastErr = fmt.Errorf("no serialization format matched the provided data")
  70. }
  71. return nil, nil, lastErr
  72. }

3、CodecFactory

  1. type CodecFactory struct {
  2. // scheme对象
  3. scheme *runtime.Scheme
  4. // 所有的序列化器
  5. serializers []serializerType
  6. // 普遍的解码器,集成了所有的编码器,挨个匹配看是否数据类型是否能匹配到解码器
  7. // 找到则解码,否则抛出异常
  8. universal runtime.Decoder
  9. // 所有ContentType的序列化器
  10. accepts []runtime.SerializerInfo
  11. // 核心序列化器,默认为json序列化器
  12. legacySerializer runtime.Serializer
  13. }
  14. func NewCodecFactory(scheme *runtime.Scheme, mutators ...CodecFactoryOptionsMutator) CodecFactory {
  15. options := CodecFactoryOptions{Pretty: true}
  16. for _, fn := range mutators {
  17. fn(&options)
  18. }
  19. // 获取所有的序列化器
  20. serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory, options)
  21. return newCodecFactory(scheme, serializers)
  22. }
  23. // 新建一个newCodecFactory
  24. func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) CodecFactory {
  25. decoders := make([]runtime.Decoder, 0, len(serializers))
  26. var accepts []runtime.SerializerInfo
  27. alreadyAccepted := make(map[string]struct{})
  28. var legacySerializer runtime.Serializer
  29. for _, d := range serializers {
  30. decoders = append(decoders, d.Serializer)
  31. for _, mediaType := range d.AcceptContentTypes {
  32. if _, ok := alreadyAccepted[mediaType]; ok {
  33. continue
  34. }
  35. alreadyAccepted[mediaType] = struct{}{}
  36. info := runtime.SerializerInfo{
  37. MediaType: d.ContentType,
  38. EncodesAsText: d.EncodesAsText,
  39. Serializer: d.Serializer,
  40. PrettySerializer: d.PrettySerializer,
  41. }
  42. mediaType, _, err := mime.ParseMediaType(info.MediaType)
  43. if err != nil {
  44. panic(err)
  45. }
  46. parts := strings.SplitN(mediaType, "/", 2)
  47. info.MediaTypeType = parts[0]
  48. info.MediaTypeSubType = parts[1]
  49. if d.StreamSerializer != nil {
  50. info.StreamSerializer = &runtime.StreamSerializerInfo{
  51. Serializer: d.StreamSerializer,
  52. EncodesAsText: d.EncodesAsText,
  53. Framer: d.Framer,
  54. }
  55. }
  56. accepts = append(accepts, info)
  57. if mediaType == runtime.ContentTypeJSON {
  58. legacySerializer = d.Serializer
  59. }
  60. }
  61. }
  62. if legacySerializer == nil {
  63. legacySerializer = serializers[0].Serializer
  64. }
  65. return CodecFactory{
  66. scheme: scheme,
  67. serializers: serializers,
  68. universal: recognizer.NewDecoder(decoders...),
  69. accepts: accepts,
  70. legacySerializer: legacySerializer,
  71. }
  72. }
  73. // 支持的所有序列化器
  74. // apiserver一般会调用此函数获取所有的序列化器并根据request的类型进行匹配查找
  75. // 然后再将找到的序列化器作为参数再调用CodecFactory的Encode/Decode函数
  76. func (f CodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
  77. return f.accepts
  78. }
  79. // 此方法编码为指定版本,解码为内部版本,固定为json格式。
  80. // 此方法已经废弃。apiserver和client应该先确定一个具体的序列化器,然后调用CodecForVersions方法
  81. // 如果只是想读数据,则应该调用UniversalDecoder()方法
  82. func (f CodecFactory) LegacyCodec(version ...schema.GroupVersion) runtime.Codec {
  83. return versioning.NewDefaultingCodecForScheme(f.scheme, f.legacySerializer, f.universal, schema.GroupVersions(version), runtime.InternalGroupVersioner)
  84. }
  85. // UniversalDeserializer can convert any stored data recognized by this factory into a Go object that satisfies
  86. // runtime.Object. It does not perform conversion. It does not perform defaulting.
  87. func (f CodecFactory) UniversalDeserializer() runtime.Decoder {
  88. return f.universal
  89. }
  90. // UniversalDecoder returns a runtime.Decoder capable of decoding all known API objects in all known formats. Used
  91. // by clients that do not need to encode objects but want to deserialize API objects stored on disk. Only decodes
  92. // objects in groups registered with the scheme. The GroupVersions passed may be used to select alternate
  93. // versions of objects to return - by default, runtime.APIVersionInternal is used. If any versions are specified,
  94. // unrecognized groups will be returned in the version they are encoded as (no conversion). This decoder performs
  95. // defaulting.
  96. func (f CodecFactory) UniversalDecoder(versions ...schema.GroupVersion) runtime.Decoder {
  97. var versioner runtime.GroupVersioner
  98. if len(versions) == 0 {
  99. versioner = runtime.InternalGroupVersioner
  100. } else {
  101. versioner = schema.GroupVersions(versions)
  102. }
  103. return f.CodecForVersions(nil, f.universal, nil, versioner)
  104. }
  105. // CodecForVersions creates a codec with the provided serializer. If an object is decoded and its group is not in the list,
  106. // it will default to runtime.APIVersionInternal. If encode is not specified for an object's group, the object is not
  107. // converted. If encode or decode are nil, no conversion is performed.
  108. func (f CodecFactory) CodecForVersions(encoder runtime.Encoder, decoder runtime.Decoder, encode runtime.GroupVersioner, decode runtime.GroupVersioner) runtime.Codec {
  109. // TODO: these are for backcompat, remove them in the future
  110. if encode == nil {
  111. encode = runtime.DisabledGroupVersioner
  112. }
  113. if decode == nil {
  114. decode = runtime.InternalGroupVersioner
  115. }
  116. return versioning.NewDefaultingCodecForScheme(f.scheme, encoder, decoder, encode, decode)
  117. }
  118. func (f CodecFactory) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
  119. return f.CodecForVersions(nil, decoder, nil, gv)
  120. }
  121. func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
  122. return f.CodecForVersions(encoder, nil, gv, nil)
  123. }
  124. // 不带转换器的编码工厂(返回的为WithoutVersionDecoder结构体)
  125. func (f CodecFactory) WithoutConversion() runtime.NegotiatedSerializer {
  126. return WithoutConversionCodecFactory{f}
  127. }
  128. // CodecFactory配置项
  129. type CodecFactoryOptions struct {
  130. Strict bool // 是否为严格模式
  131. Pretty bool // 是否需要开启可读性系列化器
  132. }
  133. type CodecFactoryOptionsMutator func(*CodecFactoryOptions)
  134. func EnablePretty(options *CodecFactoryOptions) {
  135. options.Pretty = true
  136. }
  137. func DisablePretty(options *CodecFactoryOptions) {
  138. options.Pretty = false
  139. }
  140. func EnableStrict(options *CodecFactoryOptions) {
  141. options.Strict = true
  142. }
  143. func DisableStrict(options *CodecFactoryOptions) {
  144. options.Strict = false
  145. }

4、VersioningCodec

  1. // encoder/decoder 一般是由外部调用者利用CodecFactory获取给定类型的序列化器
  2. // 然后再传入到此
  3. // encodeVersion/decodeVersion一般为内部版本(即RequeScope里面的HubGroupVersion)
  4. // 若decodeVersion为nil,则默认为runtime.InternalGroupVersioner
  5. func NewDefaultingCodecForScheme(
  6. scheme *runtime.Scheme,
  7. encoder runtime.Encoder,
  8. decoder runtime.Decoder,
  9. encodeVersion runtime.GroupVersioner,
  10. decodeVersion runtime.GroupVersioner,
  11. ) runtime.Codec {
  12. return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion, scheme.Name())
  13. }
  14. func NewCodec(
  15. encoder runtime.Encoder,
  16. decoder runtime.Decoder,
  17. convertor runtime.ObjectConvertor,
  18. creater runtime.ObjectCreater,
  19. typer runtime.ObjectTyper,
  20. defaulter runtime.ObjectDefaulter,
  21. encodeVersion runtime.GroupVersioner,
  22. decodeVersion runtime.GroupVersioner,
  23. originalSchemeName string,
  24. ) runtime.Codec {
  25. internal := &codec{
  26. encoder: encoder,
  27. decoder: decoder,
  28. convertor: convertor,
  29. creater: creater,
  30. typer: typer,
  31. defaulter: defaulter,
  32. encodeVersion: encodeVersion,
  33. decodeVersion: decodeVersion,
  34. identifier: identifier(encodeVersion, encoder),
  35. originalSchemeName: originalSchemeName,
  36. }
  37. return internal
  38. }
  39. type codec struct {
  40. encoder runtime.Encoder
  41. decoder runtime.Decoder
  42. convertor runtime.ObjectConvertor
  43. creater runtime.ObjectCreater
  44. typer runtime.ObjectTyper
  45. defaulter runtime.ObjectDefaulter
  46. encodeVersion runtime.GroupVersioner
  47. decodeVersion runtime.GroupVersioner
  48. identifier runtime.Identifier
  49. originalSchemeName string
  50. }
  51. // Decode尝试解码obj然后尝试转换为内部版本
  52. // defaultGVK 为当前请求路径下的gvk(即安装api时候指定的scope里面的kind)
  53. // 若是从etcd读取出来的数据,则一般defaultGVK为空
  54. // into 为安装api时候指定的scope里面NamedCreater创建的对象(一般为内部版本对象)
  55. // into是我们的目标对象,需要将data转换为into obj
  56. func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
  57. decodeInto := into
  58. if into != nil {
  59. // 若into为Unstructured obj且gv信息为空
  60. // 将decodeInto实力化一份
  61. if _, ok := into.(runtime.Unstructured); ok && !into.GetObjectKind().GroupVersionKind().GroupVersion().Empty() {
  62. decodeInto = reflect.New(reflect.TypeOf(into).Elem()).Interface().(runtime.Object)
  63. }
  64. }
  65. obj, gvk, err := c.decoder.Decode(data, defaultGVK, decodeInto)
  66. if err != nil {
  67. return nil, gvk, err
  68. }
  69. // 不清楚作用
  70. if d, ok := obj.(runtime.NestedObjectDecoder); ok {
  71. if err := d.DecodeNestedObjects(runtime.WithoutVersionDecoder{Decoder: c.decoder}); err != nil {
  72. return nil, gvk, err
  73. }
  74. }
  75. if into != nil {
  76. if c.defaulter != nil {
  77. c.defaulter.Default(obj)
  78. }
  79. // Short-circuit conversion if the into object is same object
  80. if into == obj {
  81. return into, gvk, nil
  82. }
  83. if err := c.convertor.Convert(obj, into, c.decodeVersion); err != nil {
  84. return nil, gvk, err
  85. }
  86. return into, gvk, nil
  87. }
  88. if c.defaulter != nil {
  89. c.defaulter.Default(obj)
  90. }
  91. out, err := c.convertor.ConvertToVersion(obj, c.decodeVersion)
  92. if err != nil {
  93. return nil, gvk, err
  94. }
  95. return out, gvk, nil
  96. }
  97. func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
  98. if co, ok := obj.(runtime.CacheableObject); ok {
  99. return co.CacheEncode(c.Identifier(), c.doEncode, w)
  100. }
  101. return c.doEncode(obj, w)
  102. }
  103. func (c *codec) doEncode(obj runtime.Object, w io.Writer) error {
  104. switch obj := obj.(type) {
  105. case *runtime.Unknown:
  106. return c.encoder.Encode(obj, w)
  107. case runtime.Unstructured:
  108. // An unstructured list can contain objects of multiple group version kinds. don't short-circuit just
  109. // because the top-level type matches our desired destination type. actually send the object to the converter
  110. // to give it a chance to convert the list items if needed.
  111. if _, ok := obj.(*unstructured.UnstructuredList); !ok {
  112. // avoid conversion roundtrip if GVK is the right one already or is empty (yes, this is a hack, but the old behaviour we rely on in kubectl)
  113. objGVK := obj.GetObjectKind().GroupVersionKind()
  114. if len(objGVK.Version) == 0 {
  115. return c.encoder.Encode(obj, w)
  116. }
  117. targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
  118. if !ok {
  119. return runtime.NewNotRegisteredGVKErrForTarget(c.originalSchemeName, objGVK, c.encodeVersion)
  120. }
  121. if targetGVK == objGVK {
  122. return c.encoder.Encode(obj, w)
  123. }
  124. }
  125. }
  126. gvks, isUnversioned, err := c.typer.ObjectKinds(obj)
  127. if err != nil {
  128. return err
  129. }
  130. objectKind := obj.GetObjectKind()
  131. old := objectKind.GroupVersionKind()
  132. // restore the old GVK after encoding
  133. defer objectKind.SetGroupVersionKind(old)
  134. if c.encodeVersion == nil || isUnversioned {
  135. if e, ok := obj.(runtime.NestedObjectEncoder); ok {
  136. if err := e.EncodeNestedObjects(runtime.WithVersionEncoder{Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
  137. return err
  138. }
  139. }
  140. objectKind.SetGroupVersionKind(gvks[0])
  141. return c.encoder.Encode(obj, w)
  142. }
  143. // Perform a conversion if necessary
  144. out, err := c.convertor.ConvertToVersion(obj, c.encodeVersion)
  145. if err != nil {
  146. return err
  147. }
  148. if e, ok := out.(runtime.NestedObjectEncoder); ok {
  149. if err := e.EncodeNestedObjects(runtime.WithVersionEncoder{Version: c.encodeVersion, Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
  150. return err
  151. }
  152. }
  153. // Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
  154. return c.encoder.Encode(out, w)
  155. }
  156. func (c *codec) Identifier() runtime.Identifier {
  157. return c.identifier
  158. }
  159. var identifiersMap sync.Map
  160. type codecIdentifier struct {
  161. EncodeGV string `json:"encodeGV,omitempty"`
  162. Encoder string `json:"encoder,omitempty"`
  163. Name string `json:"name,omitempty"`
  164. }
  165. func identifier(encodeGV runtime.GroupVersioner, encoder runtime.Encoder) runtime.Identifier {
  166. result := codecIdentifier{
  167. Name: "versioning",
  168. }
  169. if encodeGV != nil {
  170. result.EncodeGV = encodeGV.Identifier()
  171. }
  172. if encoder != nil {
  173. result.Encoder = string(encoder.Identifier())
  174. }
  175. if id, ok := identifiersMap.Load(result); ok {
  176. return id.(runtime.Identifier)
  177. }
  178. identifier, err := json.Marshal(result)
  179. if err != nil {
  180. klog.Fatalf("Failed marshaling identifier for codec: %v", err)
  181. }
  182. identifiersMap.Store(result, runtime.Identifier(identifier))
  183. return runtime.Identifier(identifier)
  184. }