Documentation ¶
Overview ¶
Package runtime includes helper functions for working with API objects that follow the kubernetes API object conventions, which are:
- Your API objects have a common metadata struct member, JSONBase.
- Your code refers to an internal set of API objects.
- In a separate package, you have an external set of API objects.
- The external set is considered to be versioned, and no breaking changes are ever made to it (fields may be added but not changed or removed).
- As your api evolves, you'll make an additional versioned package with every major change.
- Versioned packages have conversion functions which convert to and from the internal version.
- You'll continue to support older versions according to your deprecation policy, and you can easily provide a program/library to update old versions into new versions because of 5.
- All of your serializations and deserializations are handled in a centralized place.
Package runtime provides a conversion helper to make 5 easy, and the Encode/Decode/DecodeInto trio to accomplish 7. You can also register additional "codecs" which use a version of your choice. It's recommended that you register your types with runtime in your package's init function.
As a bonus, a few common types useful from all api objects and versions are provided in types.go.
Index ¶
- func CodecGetYAML(codec Codec, obj Object) (tag string, value interface{})
- func CodecMarshalJSON(codec Codec, obj Object) ([]byte, error)
- func EncodeOrDie(codec Codec, obj Object) string
- func ObjectDiff(a, b Object) string
- func VersionAndKind(data []byte) (version, kind string, err error)
- type Codec
- type Decoder
- type EmbeddedObject
- type Encoder
- type JSONBase
- type JSONBaseInterface
- type Object
- type PluginBase
- type RawExtension
- type ResourceVersioner
- type Scheme
- func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error
- func (s *Scheme) AddKnownTypeWithName(version, kind string, obj Object)
- func (s *Scheme) AddKnownTypes(version string, types ...Object)
- func (s *Scheme) Convert(in, out interface{}) error
- func (s *Scheme) Copy(obj Object) (Object, error)
- func (s *Scheme) CopyOrDie(obj Object) Object
- func (s *Scheme) Decode(data []byte) (Object, error)
- func (s *Scheme) DecodeInto(data []byte, obj Object) error
- func (s *Scheme) EncodeToVersion(obj Object, destVersion string) (data []byte, err error)
- func (s *Scheme) KnownTypes(version string) map[string]reflect.Type
- func (s *Scheme) New(versionName, typeName string) (Object, error)
- type Unknown
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CodecGetYAML ¶
GetYAML implements the yaml.Getter interface.
func CodecMarshalJSON ¶
MarshalJSON implements the json.Marshaler interface.
func EncodeOrDie ¶
EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
func ObjectDiff ¶
func VersionAndKind ¶
VersionAndKind will return the APIVersion and Kind of the given wire-format enconding of an APIObject, or an error.
Types ¶
type Decoder ¶
type Decoder interface { Decode(data []byte) (Object, error) DecodeInto(data []byte, obj Object) error }
Decoder defines methods for deserializing API objects into a given type
type EmbeddedObject ¶
type EmbeddedObject struct {
Object
}
EmbeddedObject has appropriate encoder and decoder functions, such that on the wire, it's stored as a []byte, but in memory, the contained object is accessable as an Object via the Get() function. Only valid API objects may be stored via EmbeddedObject. The purpose of this is to allow an API object of type known only at runtime to be embedded within other API objects.
Note that object assumes that you've registered all of your api types with the api package.
EmbeddedObject and RawExtension can be used together to allow for API object extensions: see the comment for RawExtension.
type JSONBase ¶
type JSONBase struct { Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` ID string `json:"id,omitempty" yaml:"id,omitempty"` CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` ResourceVersion uint64 `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` }
JSONBase is shared by all top level objects. The proper way to use it is to inline it in your type, like this:
type MyAwesomeAPIObject struct { runtime.JSONBase `yaml:",inline" json:",inline"` ... // other fields }
func (*MyAwesomeAPIObject) IsAnAPIObject() {}
JSONBase is provided here for convenience. You may use it directly from this package or define your own with the same fields.
type JSONBaseInterface ¶
type JSONBaseInterface interface { ID() string SetID(ID string) APIVersion() string SetAPIVersion(version string) Kind() string SetKind(kind string) ResourceVersion() uint64 SetResourceVersion(version uint64) }
JSONBaseInterface lets you work with a JSONBase from any of the versioned or internal APIObjects.
func FindJSONBase ¶
func FindJSONBase(obj Object) (JSONBaseInterface, error)
FindJSONBase takes an arbitary api type, returns pointer to its JSONBase field. obj must be a pointer to an api type.
type Object ¶
type Object interface { // This function is used only to enforce membership. It's never called. // TODO: Consider mass rename in the future to make it do something useful. IsAnAPIObject() }
All api types must support the Object interface. It's deliberately tiny so that this is not an onerous burden. Implement it with a pointer reciever; this will allow us to use the go compiler to check the one thing about our objects that it's capable of checking for us.
func CodecSetYAML ¶
SetYAML implements the yaml.Setter interface.
func CodecUnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface.
func ExtractList ¶
Extract list returns obj's Items element as an array of runtime.Objects. Returns an error if obj is not a List type (does not have an Items member).
type PluginBase ¶
type PluginBase struct {
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
}
PluginBase is like JSONBase, but it's intended for plugin objects that won't ever be encoded except while embedded in other objects.
type RawExtension ¶
type RawExtension struct {
RawJSON []byte
}
RawExtension is used with EmbeddedObject to do a two-phase encoding of extension objects.
To use this, make a field which has RawExtension as its type in your external, versioned struct, and EmbeddedObject in your internal struct. You also need to register your various plugin types.
// Internal package:
type MyAPIObject struct { runtime.JSONBase `yaml:",inline" json:",inline"` MyPlugin runtime.EmbeddedObject `json:"myPlugin" yaml:"myPlugin"` }
type PluginA struct { runtime.PluginBase `yaml:",inline" json:",inline"` AOption string `yaml:"aOption" json:"aOption"` }
// External package:
type MyAPIObject struct { runtime.JSONBase `yaml:",inline" json:",inline"` MyPlugin runtime.RawExtension `json:"myPlugin" yaml:"myPlugin"` }
type PluginA struct { runtime.PluginBase `yaml:",inline" json:",inline"` AOption string `yaml:"aOption" json:"aOption"` }
// On the wire, the JSON will look something like this:
{ "kind":"MyAPIObject", "apiVersion":"v1beta1", "myPlugin": { "kind":"PluginA", "aOption":"foo", }, }
So what happens? Decode first uses json or yaml to unmarshal the serialized data into your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. The next step is to copy (using pkg/conversion) into the internal struct. The runtime package's DefaultScheme has conversion functions installed which will unpack the JSON stored in RawExtension, turning it into the correct object type, and storing it in the EmbeddedObject. (TODO: In the case where the object is of an unknown type, a runtime.Unknown object will be created and stored.)
func (*RawExtension) GetYAML ¶
func (re *RawExtension) GetYAML() (tag string, value interface{})
GetYAML implements the yaml.Getter interface.
func (*RawExtension) MarshalJSON ¶
func (re *RawExtension) MarshalJSON() ([]byte, error)
func (*RawExtension) SetYAML ¶
func (re *RawExtension) SetYAML(tag string, value interface{}) bool
SetYAML implements the yaml.Setter interface.
func (*RawExtension) UnmarshalJSON ¶
func (re *RawExtension) UnmarshalJSON(in []byte) error
type ResourceVersioner ¶
type ResourceVersioner interface { SetResourceVersion(obj Object, version uint64) error ResourceVersion(obj Object) (uint64, error) }
ResourceVersioner provides methods for setting and retrieving the resource version from an API object.
func NewJSONBaseResourceVersioner ¶
func NewJSONBaseResourceVersioner() ResourceVersioner
NewJSONBaseResourceVersioner returns a resourceVersioner that can set or retrieve ResourceVersion on objects derived from JSONBase.
type Scheme ¶
type Scheme struct {
// contains filtered or unexported fields
}
Scheme defines methods for serializing and deserializing API objects. It is an adaptation of conversion's Scheme for our API objects.
func NewScheme ¶
func NewScheme() *Scheme
NewScheme creates a new Scheme. This scheme is pluggable by default.
func (*Scheme) AddConversionFuncs ¶
AddConversionFuncs adds a function to the list of conversion functions. The given function should know how to convert between two API objects. We deduce how to call it from the types of its two parameters; see the comment for Converter.Register.
Note that, if you need to copy sub-objects that didn't change, it's safe to call Convert() inside your conversionFuncs, as long as you don't start a conversion chain that's infinitely recursive.
Also note that the default behavior, if you don't add a conversion function, is to sanely copy fields that have the same names. It's OK if the destination type has extra fields, but it must not remove any. So you only need to add a conversion function for things with changed/removed fields.
func (*Scheme) AddKnownTypeWithName ¶
AddKnownTypeWithName is like AddKnownTypes, but it lets you specify what this type should be encoded as. Useful for testing when you don't want to make multiple packages to define your structs.
func (*Scheme) AddKnownTypes ¶
AddKnownTypes registers the types of the arguments to the marshaller of the package api. Encode() refuses the object unless its type is registered with AddKnownTypes.
func (*Scheme) Convert ¶
Convert will attempt to convert in into out. Both must be pointers. For easy testing of conversion functions. Returns an error if the conversion isn't possible.
func (*Scheme) Copy ¶
Copy does a deep copy of an API object. Useful mostly for tests. TODO(dbsmith): implement directly instead of via Encode/Decode
func (*Scheme) Decode ¶
Decode converts a YAML or JSON string back into a pointer to an api object. Deduces the type based upon the APIVersion and Kind fields, which are set by Encode. Only versioned objects (APIVersion != "") are accepted. The object will be converted into the in-memory unversioned type before being returned.
func (*Scheme) DecodeInto ¶
DecodeInto parses a YAML or JSON string and stores it in obj. Returns an error if data.Kind is set and doesn't match the type of obj. Obj should be a pointer to an api type. If obj's APIVersion doesn't match that in data, an attempt will be made to convert data into obj's version.
func (*Scheme) EncodeToVersion ¶
EncodeToVersion turns the given api object into an appropriate JSON string. Will return an error if the object doesn't have an embedded JSONBase. Obj may be a pointer to a struct, or a struct. If a struct, a copy must be made. If a pointer, the object may be modified before encoding, but will be put back into its original state before returning.
Memory/wire format differences:
- Having to keep track of the Kind and APIVersion fields makes tests very annoying, so the rule is that they are set only in wire format (json), not when in native (memory) format. This is possible because both pieces of information are implicit in the go typed object.
- An exception: note that, if there are embedded API objects of known type, for example, PodList{... Items []Pod ...}, these embedded objects must be of the same version of the object they are embedded within, and their APIVersion and Kind must both be empty.
- Note that the exception does not apply to the APIObject type, which recursively does Encode()/Decode(), and is capable of expressing any API object.
- Only versioned objects should be encoded. This means that, if you pass a native object, Encode will convert it to a versioned object. For example, an api.Pod will get converted to a v1beta1.Pod. However, if you pass in an object that's already versioned (v1beta1.Pod), Encode will not modify it.
The purpose of the above complex conversion behavior is to allow us to change the memory format yet not break compatibility with any stored objects, whether they be in our storage layer (e.g., etcd), or in user's config files.
type Unknown ¶
type Unknown struct { JSONBase `yaml:",inline" json:",inline"` // RawJSON will hold the complete JSON of the object which couldn't be matched // with a registered type. Most likely, nothing should be done with this // except for passing it through the system. RawJSON []byte }
Unknown allows api objects with unknown types to be passed-through. This can be used to deal with the API objects from a plug-in. Unknown objects still have functioning JSONBase features-- kind, version, resourceVersion, etc. TODO: Not implemented yet!
func (*Unknown) IsAnAPIObject ¶
func (*Unknown) IsAnAPIObject()