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