github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/helper.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors All rights reserved. 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 runtime 18 19 import ( 20 "fmt" 21 "io" 22 "reflect" 23 24 "k8s.io/kubernetes/pkg/api/unversioned" 25 "k8s.io/kubernetes/pkg/conversion" 26 "k8s.io/kubernetes/pkg/util/errors" 27 ) 28 29 type objectTyperToTyper struct { 30 typer ObjectTyper 31 } 32 33 func (t objectTyperToTyper) ObjectKind(obj Object) (*unversioned.GroupVersionKind, bool, error) { 34 gvk, err := t.typer.ObjectKind(obj) 35 if err != nil { 36 return nil, false, err 37 } 38 unversionedType, ok := t.typer.IsUnversioned(obj) 39 if !ok { 40 // ObjectTyper violates its contract 41 return nil, false, fmt.Errorf("typer returned a kind for %v, but then reported it was not in the scheme with IsUnversioned", reflect.TypeOf(obj)) 42 } 43 return &gvk, unversionedType, nil 44 } 45 46 // ObjectTyperToTyper casts the old typer interface to the new typer interface 47 func ObjectTyperToTyper(typer ObjectTyper) Typer { 48 return objectTyperToTyper{typer: typer} 49 } 50 51 // unsafeObjectConvertor implements ObjectConvertor using the unsafe conversion path. 52 type unsafeObjectConvertor struct { 53 *Scheme 54 } 55 56 var _ ObjectConvertor = unsafeObjectConvertor{} 57 58 // ConvertToVersion converts in to the provided outVersion without copying the input first, which 59 // is only safe if the output object is not mutated or reused. 60 func (c unsafeObjectConvertor) ConvertToVersion(in Object, outVersion unversioned.GroupVersion) (Object, error) { 61 return c.Scheme.UnsafeConvertToVersion(in, outVersion) 62 } 63 64 // UnsafeObjectConvertor performs object conversion without copying the object structure, 65 // for use when the converted object will not be reused or mutated. Primarily for use within 66 // versioned codecs, which use the external object for serialization but do not return it. 67 func UnsafeObjectConvertor(scheme *Scheme) ObjectConvertor { 68 return unsafeObjectConvertor{scheme} 69 } 70 71 // fieldPtr puts the address of fieldName, which must be a member of v, 72 // into dest, which must be an address of a variable to which this field's 73 // address can be assigned. 74 func FieldPtr(v reflect.Value, fieldName string, dest interface{}) error { 75 field := v.FieldByName(fieldName) 76 if !field.IsValid() { 77 return fmt.Errorf("couldn't find %v field in %#v", fieldName, v.Interface()) 78 } 79 v, err := conversion.EnforcePtr(dest) 80 if err != nil { 81 return err 82 } 83 field = field.Addr() 84 if field.Type().AssignableTo(v.Type()) { 85 v.Set(field) 86 return nil 87 } 88 if field.Type().ConvertibleTo(v.Type()) { 89 v.Set(field.Convert(v.Type())) 90 return nil 91 } 92 return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), v.Type()) 93 } 94 95 // EncodeList ensures that each object in an array is converted to a Unknown{} in serialized form. 96 // TODO: accept a content type. 97 func EncodeList(e Encoder, objects []Object, overrides ...unversioned.GroupVersion) error { 98 var errs []error 99 for i := range objects { 100 data, err := Encode(e, objects[i], overrides...) 101 if err != nil { 102 errs = append(errs, err) 103 continue 104 } 105 // TODO: Set ContentEncoding and ContentType. 106 objects[i] = &Unknown{Raw: data} 107 } 108 return errors.NewAggregate(errs) 109 } 110 111 func decodeListItem(obj *Unknown, decoders []Decoder) (Object, error) { 112 for _, decoder := range decoders { 113 // TODO: Decode based on ContentType. 114 obj, err := Decode(decoder, obj.Raw) 115 if err != nil { 116 if IsNotRegisteredError(err) { 117 continue 118 } 119 return nil, err 120 } 121 return obj, nil 122 } 123 // could not decode, so leave the object as Unknown, but give the decoders the 124 // chance to set Unknown.TypeMeta if it is available. 125 for _, decoder := range decoders { 126 if err := DecodeInto(decoder, obj.Raw, obj); err == nil { 127 return obj, nil 128 } 129 } 130 return obj, nil 131 } 132 133 // DecodeList alters the list in place, attempting to decode any objects found in 134 // the list that have the Unknown type. Any errors that occur are returned 135 // after the entire list is processed. Decoders are tried in order. 136 func DecodeList(objects []Object, decoders ...Decoder) []error { 137 errs := []error(nil) 138 for i, obj := range objects { 139 switch t := obj.(type) { 140 case *Unknown: 141 decoded, err := decodeListItem(t, decoders) 142 if err != nil { 143 errs = append(errs, err) 144 break 145 } 146 objects[i] = decoded 147 } 148 } 149 return errs 150 } 151 152 // MultiObjectTyper returns the types of objects across multiple schemes in order. 153 type MultiObjectTyper []ObjectTyper 154 155 var _ ObjectTyper = MultiObjectTyper{} 156 157 func (m MultiObjectTyper) ObjectKind(obj Object) (gvk unversioned.GroupVersionKind, err error) { 158 for _, t := range m { 159 gvk, err = t.ObjectKind(obj) 160 if err == nil { 161 return 162 } 163 } 164 return 165 } 166 167 func (m MultiObjectTyper) ObjectKinds(obj Object) (gvks []unversioned.GroupVersionKind, err error) { 168 for _, t := range m { 169 gvks, err = t.ObjectKinds(obj) 170 if err == nil { 171 return 172 } 173 } 174 return 175 } 176 177 func (m MultiObjectTyper) Recognizes(gvk unversioned.GroupVersionKind) bool { 178 for _, t := range m { 179 if t.Recognizes(gvk) { 180 return true 181 } 182 } 183 return false 184 } 185 186 func (m MultiObjectTyper) IsUnversioned(obj Object) (bool, bool) { 187 for _, t := range m { 188 if unversioned, ok := t.IsUnversioned(obj); ok { 189 return unversioned, true 190 } 191 } 192 return false, false 193 } 194 195 // SetZeroValue would set the object of objPtr to zero value of its type. 196 func SetZeroValue(objPtr Object) error { 197 v, err := conversion.EnforcePtr(objPtr) 198 if err != nil { 199 return err 200 } 201 v.Set(reflect.Zero(v.Type())) 202 return nil 203 } 204 205 // DefaultFramer is valid for any stream that can read objects serially without 206 // any separation in the stream. 207 var DefaultFramer = defaultFramer{} 208 209 type defaultFramer struct{} 210 211 func (defaultFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser { return r } 212 func (defaultFramer) NewFrameWriter(w io.Writer) io.Writer { return w }