k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/kubelet/kubeletconfig/util/codec/codec.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package codec 18 19 import ( 20 "encoding/json" 21 "fmt" 22 23 "k8s.io/klog/v2" 24 25 // ensure the core apis are installed 26 _ "k8s.io/kubernetes/pkg/apis/core/install" 27 28 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 29 "k8s.io/apimachinery/pkg/runtime" 30 "k8s.io/apimachinery/pkg/runtime/schema" 31 "k8s.io/apimachinery/pkg/runtime/serializer" 32 "k8s.io/component-base/codec" 33 kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" 34 "k8s.io/kubernetes/pkg/kubelet/apis/config/scheme" 35 kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1" 36 ) 37 38 // EncodeKubeletConfig encodes an internal KubeletConfiguration to an external YAML representation. 39 func EncodeKubeletConfig(internal *kubeletconfig.KubeletConfiguration, targetVersion schema.GroupVersion) ([]byte, error) { 40 encoder, err := NewKubeletconfigYAMLEncoder(targetVersion) 41 if err != nil { 42 return nil, err 43 } 44 // encoder will convert to external version 45 data, err := runtime.Encode(encoder, internal) 46 if err != nil { 47 return nil, err 48 } 49 return data, nil 50 } 51 52 // NewKubeletconfigYAMLEncoder returns an encoder that can write objects in the kubeletconfig API group to YAML. 53 func NewKubeletconfigYAMLEncoder(targetVersion schema.GroupVersion) (runtime.Encoder, error) { 54 _, codecs, err := scheme.NewSchemeAndCodecs() 55 if err != nil { 56 return nil, err 57 } 58 mediaType := "application/yaml" 59 info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType) 60 if !ok { 61 return nil, fmt.Errorf("unsupported media type %q", mediaType) 62 } 63 return codecs.EncoderForVersion(info.Serializer, targetVersion), nil 64 } 65 66 // DecodeKubeletConfiguration decodes a serialized KubeletConfiguration to the internal type. 67 func DecodeKubeletConfiguration(kubeletCodecs *serializer.CodecFactory, data []byte) (*kubeletconfig.KubeletConfiguration, error) { 68 var ( 69 obj runtime.Object 70 gvk *schema.GroupVersionKind 71 ) 72 73 // The UniversalDecoder runs defaulting and returns the internal type by default. 74 obj, gvk, err := kubeletCodecs.UniversalDecoder().Decode(data, nil, nil) 75 if err != nil { 76 // Try strict decoding first. If that fails decode with a lenient 77 // decoder, which has only v1beta1 registered, and log a warning. 78 // The lenient path is to be dropped when support for v1beta1 is dropped. 79 if !runtime.IsStrictDecodingError(err) { 80 return nil, fmt.Errorf("failed to decode: %w", err) 81 } 82 83 var lenientErr error 84 _, lenientCodecs, lenientErr := codec.NewLenientSchemeAndCodecs( 85 kubeletconfig.AddToScheme, 86 kubeletconfigv1beta1.AddToScheme, 87 ) 88 89 if lenientErr != nil { 90 return nil, lenientErr 91 } 92 93 obj, gvk, lenientErr = lenientCodecs.UniversalDecoder().Decode(data, nil, nil) 94 if lenientErr != nil { 95 // Lenient decoding failed with the current version, return the 96 // original strict error. 97 return nil, fmt.Errorf("failed lenient decoding: %v", err) 98 } 99 // Continue with the v1beta1 object that was decoded leniently, but emit a warning. 100 klog.InfoS("Using lenient decoding as strict decoding failed", "err", err) 101 } 102 103 internalKC, ok := obj.(*kubeletconfig.KubeletConfiguration) 104 if !ok { 105 return nil, fmt.Errorf("failed to cast object to KubeletConfiguration, unexpected type: %v", gvk) 106 } 107 108 return internalKC, nil 109 } 110 111 // DecodeKubeletConfigurationIntoJSON decodes a serialized KubeletConfiguration to the internal type. 112 func DecodeKubeletConfigurationIntoJSON(kubeletCodecs *serializer.CodecFactory, data []byte) ([]byte, error) { 113 // The UniversalDecoder runs defaulting and returns the internal type by default. 114 obj, _, err := kubeletCodecs.UniversalDecoder().Decode(data, nil, &unstructured.Unstructured{}) 115 if err != nil { 116 return nil, err 117 } 118 119 objT := obj.(*unstructured.Unstructured) 120 121 return json.Marshal(objT.Object) 122 }