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 }