mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 22:17:14 +00:00
Add Object type to runtime, make runtime test pass.
This commit is contained in:
parent
0c6adde92e
commit
77edb91032
@ -21,21 +21,21 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.AddKnownTypes("",
|
||||
PodList{},
|
||||
Pod{},
|
||||
ReplicationControllerList{},
|
||||
ReplicationController{},
|
||||
ServiceList{},
|
||||
Service{},
|
||||
MinionList{},
|
||||
Minion{},
|
||||
Status{},
|
||||
ServerOpList{},
|
||||
ServerOp{},
|
||||
ContainerManifestList{},
|
||||
Endpoints{},
|
||||
EndpointsList{},
|
||||
Binding{},
|
||||
runtime.DefaultScheme.AddKnownTypes("",
|
||||
&PodList{},
|
||||
&Pod{},
|
||||
&ReplicationControllerList{},
|
||||
&ReplicationController{},
|
||||
&ServiceList{},
|
||||
&Service{},
|
||||
&MinionList{},
|
||||
&Minion{},
|
||||
&Status{},
|
||||
&ServerOpList{},
|
||||
&ServerOp{},
|
||||
&ContainerManifestList{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
&Binding{},
|
||||
)
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ type ContainerManifestList struct {
|
||||
Items []ContainerManifest `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ContainerManifestList) IsAnAPIObject() {}
|
||||
|
||||
// Volume represents a named volume in a pod that may be accessed by any containers in the pod.
|
||||
type Volume struct {
|
||||
// Required: This must be a DNS_LABEL. Each volume in a pod must have
|
||||
@ -287,6 +289,8 @@ type PodList struct {
|
||||
Items []Pod `json:"items" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*PodList) IsAnAPIObject() {}
|
||||
|
||||
// Pod is a collection of containers, used as either input (create, update) or as output (list, get).
|
||||
type Pod struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@ -295,6 +299,8 @@ type Pod struct {
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
|
||||
type ReplicationControllerState struct {
|
||||
Replicas int `json:"replicas" yaml:"replicas"`
|
||||
@ -308,6 +314,8 @@ type ReplicationControllerList struct {
|
||||
Items []ReplicationController `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationControllerList) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationController represents the configuration of a replication controller.
|
||||
type ReplicationController struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@ -315,6 +323,8 @@ type ReplicationController struct {
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationController) IsAnAPIObject() {}
|
||||
|
||||
// PodTemplate holds the information used for creating pods.
|
||||
type PodTemplate struct {
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
@ -327,6 +337,8 @@ type ServiceList struct {
|
||||
Items []Service `json:"items" yaml:"items"`
|
||||
}
|
||||
|
||||
func (*ServiceList) IsAnAPIObject() {}
|
||||
|
||||
// Service is a named abstraction of software service (for example, mysql) consisting of local port
|
||||
// (for example 3306) that the proxy listens on, and the selector that determines which pods
|
||||
// will answer requests sent through the proxy.
|
||||
@ -346,6 +358,8 @@ type Service struct {
|
||||
ContainerPort util.IntOrString `json:"containerPort,omitempty" yaml:"containerPort,omitempty"`
|
||||
}
|
||||
|
||||
func (*Service) IsAnAPIObject() {}
|
||||
|
||||
// Endpoints is a collection of endpoints that implement the actual service, for example:
|
||||
// Name: "mysql", Endpoints: ["10.10.1.1:1909", "10.10.2.2:8834"]
|
||||
type Endpoints struct {
|
||||
@ -353,12 +367,16 @@ type Endpoints struct {
|
||||
Endpoints []string `json:"endpoints,omitempty" yaml:"endpoints,omitempty"`
|
||||
}
|
||||
|
||||
func (*Endpoints) IsAnAPIObject() {}
|
||||
|
||||
// EndpointsList is a list of endpoints.
|
||||
type EndpointsList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
Items []Endpoints `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*EndpointsList) IsAnAPIObject() {}
|
||||
|
||||
// Minion is a worker node in Kubernetenes.
|
||||
// The name of the minion according to etcd is in JSONBase.ID.
|
||||
type Minion struct {
|
||||
@ -367,12 +385,16 @@ type Minion struct {
|
||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||
}
|
||||
|
||||
func (*Minion) IsAnAPIObject() {}
|
||||
|
||||
// MinionList is a list of minions.
|
||||
type MinionList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
Items []Minion `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
|
||||
// Binding is written by a scheduler to cause a pod to be bound to a host.
|
||||
type Binding struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@ -380,6 +402,8 @@ type Binding struct {
|
||||
Host string `json:"host" yaml:"host"`
|
||||
}
|
||||
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
|
||||
// Status is a return value for calls that don't return other objects.
|
||||
// TODO: this could go in apiserver, but I'm including it here so clients needn't
|
||||
// import both.
|
||||
@ -403,6 +427,8 @@ type Status struct {
|
||||
Code int `json:"code,omitempty" yaml:"code,omitempty"`
|
||||
}
|
||||
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
|
||||
// StatusDetails is a set of additional properties that MAY be set by the
|
||||
// server to provide additional information about a response. The Reason
|
||||
// field of a Status object defines what attributes will be set. Clients
|
||||
@ -539,12 +565,16 @@ type ServerOp struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
|
||||
func (*ServerOp) IsAnAPIObject() {}
|
||||
|
||||
// ServerOpList is a list of operations, as delivered to API clients.
|
||||
type ServerOpList struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Items []ServerOp `yaml:"items,omitempty" json:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ServerOpList) IsAnAPIObject() {}
|
||||
|
||||
// WatchEvent objects are streamed from the api server in response to a watch request.
|
||||
type WatchEvent struct {
|
||||
// The type of the watch event; added, modified, or deleted.
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.AddConversionFuncs(
|
||||
runtime.DefaultScheme.AddConversionFuncs(
|
||||
// EnvVar's Key is deprecated in favor of Name.
|
||||
func(in *newer.EnvVar, out *EnvVar, s conversion.Scope) error {
|
||||
out.Value = in.Value
|
||||
|
@ -21,21 +21,21 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.AddKnownTypes("v1beta1",
|
||||
PodList{},
|
||||
Pod{},
|
||||
ReplicationControllerList{},
|
||||
ReplicationController{},
|
||||
ServiceList{},
|
||||
Service{},
|
||||
MinionList{},
|
||||
Minion{},
|
||||
Status{},
|
||||
ServerOpList{},
|
||||
ServerOp{},
|
||||
ContainerManifestList{},
|
||||
Endpoints{},
|
||||
EndpointsList{},
|
||||
Binding{},
|
||||
runtime.DefaultScheme.AddKnownTypes("v1beta1",
|
||||
&PodList{},
|
||||
&Pod{},
|
||||
&ReplicationControllerList{},
|
||||
&ReplicationController{},
|
||||
&ServiceList{},
|
||||
&Service{},
|
||||
&MinionList{},
|
||||
&Minion{},
|
||||
&Status{},
|
||||
&ServerOpList{},
|
||||
&ServerOp{},
|
||||
&ContainerManifestList{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
&Binding{},
|
||||
)
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ type ContainerManifestList struct {
|
||||
Items []ContainerManifest `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ContainerManifestList) IsAnAPIObject() {}
|
||||
|
||||
// Volume represents a named volume in a pod that may be accessed by any containers in the pod.
|
||||
type Volume struct {
|
||||
// Required: This must be a DNS_LABEL. Each volume in a pod must have
|
||||
@ -243,6 +245,8 @@ type JSONBase struct {
|
||||
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
|
||||
}
|
||||
|
||||
func (*JSONBase) IsAnAPIObject() {}
|
||||
|
||||
// PodStatus represents a status of a pod.
|
||||
type PodStatus string
|
||||
|
||||
@ -298,6 +302,8 @@ type PodList struct {
|
||||
Items []Pod `json:"items" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*PodList) IsAnAPIObject() {}
|
||||
|
||||
// Pod is a collection of containers, used as either input (create, update) or as output (list, get).
|
||||
type Pod struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@ -306,6 +312,8 @@ type Pod struct {
|
||||
CurrentState PodState `json:"currentState,omitempty" yaml:"currentState,omitempty"`
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
|
||||
type ReplicationControllerState struct {
|
||||
Replicas int `json:"replicas" yaml:"replicas"`
|
||||
@ -319,6 +327,8 @@ type ReplicationControllerList struct {
|
||||
Items []ReplicationController `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationControllerList) IsAnAPIObject() {}
|
||||
|
||||
// ReplicationController represents the configuration of a replication controller.
|
||||
type ReplicationController struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@ -326,6 +336,8 @@ type ReplicationController struct {
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (*ReplicationController) IsAnAPIObject() {}
|
||||
|
||||
// PodTemplate holds the information used for creating pods.
|
||||
type PodTemplate struct {
|
||||
DesiredState PodState `json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
|
||||
@ -338,6 +350,8 @@ type ServiceList struct {
|
||||
Items []Service `json:"items" yaml:"items"`
|
||||
}
|
||||
|
||||
func (*ServiceList) IsAnAPIObject() {}
|
||||
|
||||
// Service is a named abstraction of software service (for example, mysql) consisting of local port
|
||||
// (for example 3306) that the proxy listens on, and the selector that determines which pods
|
||||
// will answer requests sent through the proxy.
|
||||
@ -357,6 +371,8 @@ type Service struct {
|
||||
ContainerPort util.IntOrString `json:"containerPort,omitempty" yaml:"containerPort,omitempty"`
|
||||
}
|
||||
|
||||
func (*Service) IsAnAPIObject() {}
|
||||
|
||||
// Endpoints is a collection of endpoints that implement the actual service, for example:
|
||||
// Name: "mysql", Endpoints: ["10.10.1.1:1909", "10.10.2.2:8834"]
|
||||
type Endpoints struct {
|
||||
@ -364,12 +380,16 @@ type Endpoints struct {
|
||||
Endpoints []string `json:"endpoints,omitempty" yaml:"endpoints,omitempty"`
|
||||
}
|
||||
|
||||
func (*Endpoints) IsAnAPIObject() {}
|
||||
|
||||
// EndpointsList is a list of endpoints.
|
||||
type EndpointsList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
Items []Endpoints `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*EndpointsList) IsAnAPIObject() {}
|
||||
|
||||
// Minion is a worker node in Kubernetenes.
|
||||
// The name of the minion according to etcd is in JSONBase.ID.
|
||||
type Minion struct {
|
||||
@ -378,6 +398,8 @@ type Minion struct {
|
||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||
}
|
||||
|
||||
func (*Minion) IsAnAPIObject() {}
|
||||
|
||||
// MinionList is a list of minions.
|
||||
type MinionList struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@ -387,6 +409,8 @@ type MinionList struct {
|
||||
Items []Minion `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
|
||||
// Binding is written by a scheduler to cause a pod to be bound to a host.
|
||||
type Binding struct {
|
||||
JSONBase `json:",inline" yaml:",inline"`
|
||||
@ -394,6 +418,8 @@ type Binding struct {
|
||||
Host string `json:"host" yaml:"host"`
|
||||
}
|
||||
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
|
||||
// Status is a return value for calls that don't return other objects.
|
||||
// TODO: this could go in apiserver, but I'm including it here so clients needn't
|
||||
// import both.
|
||||
@ -417,6 +443,8 @@ type Status struct {
|
||||
Code int `json:"code,omitempty" yaml:"code,omitempty"`
|
||||
}
|
||||
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
|
||||
// StatusDetails is a set of additional properties that MAY be set by the
|
||||
// server to provide additional information about a response. The Reason
|
||||
// field of a Status object defines what attributes will be set. Clients
|
||||
@ -540,12 +568,16 @@ type ServerOp struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
|
||||
func (*ServerOp) IsAnAPIObject() {}
|
||||
|
||||
// ServerOpList is a list of operations, as delivered to API clients.
|
||||
type ServerOpList struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Items []ServerOp `yaml:"items,omitempty" json:"items,omitempty"`
|
||||
}
|
||||
|
||||
func (*ServerOpList) IsAnAPIObject() {}
|
||||
|
||||
// WatchEvent objects are streamed from the api server in response to a watch request.
|
||||
type WatchEvent struct {
|
||||
// The type of the watch event; added, modified, or deleted.
|
||||
|
@ -33,7 +33,7 @@ func (a *EmbeddedObject) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
obj, err := Decode(b)
|
||||
obj, err := Codec.Decode(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -48,7 +48,7 @@ func (a EmbeddedObject) MarshalJSON() ([]byte, error) {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
return Encode(a.Object)
|
||||
return Codec.Encode(a.Object)
|
||||
}
|
||||
|
||||
// SetYAML implements the yaml.Setter interface.
|
||||
@ -67,7 +67,7 @@ func (a *EmbeddedObject) SetYAML(tag string, value interface{}) bool {
|
||||
if err != nil {
|
||||
panic("yaml can't reverse its own object")
|
||||
}
|
||||
obj, err := Decode(b)
|
||||
obj, err := Codec.Decode(b)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@ -82,7 +82,7 @@ func (a EmbeddedObject) GetYAML() (tag string, value interface{}) {
|
||||
return
|
||||
}
|
||||
// Encode returns JSON, which is conveniently a subset of YAML.
|
||||
v, err := Encode(a.Object)
|
||||
v, err := Codec.Encode(a.Object)
|
||||
if err != nil {
|
||||
panic("impossible to encode API object!")
|
||||
}
|
||||
|
@ -22,14 +22,19 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type EmbeddedTest struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Object EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"`
|
||||
EmptyObject EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
|
||||
}
|
||||
|
||||
func (*EmbeddedTest) IsAnAPIObject() {}
|
||||
|
||||
func TestEmbeddedObject(t *testing.T) {
|
||||
type EmbeddedTest struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
Object EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"`
|
||||
EmptyObject EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
|
||||
}
|
||||
AddKnownTypes("", EmbeddedTest{})
|
||||
AddKnownTypes("v1beta1", EmbeddedTest{})
|
||||
// TODO(dbsmith) fix EmbeddedObject to not use DefaultScheme.
|
||||
s := DefaultScheme
|
||||
s.AddKnownTypes("", &EmbeddedTest{})
|
||||
s.AddKnownTypes("v1beta1", &EmbeddedTest{})
|
||||
|
||||
outer := &EmbeddedTest{
|
||||
JSONBase: JSONBase{ID: "outer"},
|
||||
@ -40,14 +45,14 @@ func TestEmbeddedObject(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
wire, err := Encode(outer)
|
||||
wire, err := s.Encode(outer)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected encode error '%v'", err)
|
||||
}
|
||||
|
||||
t.Logf("Wire format is:\n%v\n", string(wire))
|
||||
|
||||
decoded, err := Decode(wire)
|
||||
decoded, err := s.Decode(wire)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected decode error %v", err)
|
||||
}
|
||||
|
@ -27,38 +27,56 @@ import (
|
||||
// codec defines methods for serializing and deserializing API
|
||||
// objects.
|
||||
type codec interface {
|
||||
Encode(obj interface{}) (data []byte, err error)
|
||||
Decode(data []byte) (interface{}, error)
|
||||
DecodeInto(data []byte, obj interface{}) error
|
||||
Encode(obj Object) (data []byte, err error)
|
||||
Decode(data []byte) (Object, error)
|
||||
DecodeInto(data []byte, obj Object) error
|
||||
}
|
||||
|
||||
// resourceVersioner provides methods for setting and retrieving
|
||||
// the resource version from an API object.
|
||||
type resourceVersioner interface {
|
||||
SetResourceVersion(obj interface{}, version uint64) error
|
||||
ResourceVersion(obj interface{}) (uint64, error)
|
||||
SetResourceVersion(obj Object, version uint64) error
|
||||
ResourceVersion(obj Object) (uint64, error)
|
||||
}
|
||||
|
||||
var ResourceVersioner resourceVersioner = NewJSONBaseResourceVersioner()
|
||||
var conversionScheme = conversion.NewScheme()
|
||||
var Codec codec = conversionScheme
|
||||
var DefaultScheme = NewScheme("", "v1beta1")
|
||||
var Codec codec = DefaultScheme
|
||||
|
||||
func init() {
|
||||
conversionScheme.InternalVersion = ""
|
||||
conversionScheme.ExternalVersion = "v1beta1"
|
||||
conversionScheme.MetaInsertionFactory = metaInsertion{}
|
||||
// Scheme defines methods for serializing and deserializing API objects. It
|
||||
// is an adaptation of conversion's Scheme for our API objects.
|
||||
type Scheme struct {
|
||||
raw *conversion.Scheme
|
||||
}
|
||||
|
||||
// NewScheme creates a new Scheme. A default scheme is provided and accessible
|
||||
// as the "DefaultScheme" variable.
|
||||
func NewScheme(internalVersion, externalVersion string) *Scheme {
|
||||
s := &Scheme{conversion.NewScheme()}
|
||||
s.raw.InternalVersion = internalVersion
|
||||
s.raw.ExternalVersion = externalVersion
|
||||
s.raw.MetaInsertionFactory = metaInsertion{}
|
||||
return s
|
||||
}
|
||||
|
||||
// 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 AddKnownTypes(version string, types ...interface{}) {
|
||||
conversionScheme.AddKnownTypes(version, types...)
|
||||
func (s *Scheme) AddKnownTypes(version string, types ...Object) {
|
||||
interfaces := make([]interface{}, len(types))
|
||||
for i := range types {
|
||||
interfaces[i] = types[i]
|
||||
}
|
||||
s.raw.AddKnownTypes(version, interfaces...)
|
||||
}
|
||||
|
||||
// New returns a new API object of the given version ("" for internal
|
||||
// representation) and name, or an error if it hasn't been registered.
|
||||
func New(versionName, typeName string) (interface{}, error) {
|
||||
return conversionScheme.NewObject(versionName, typeName)
|
||||
func (s *Scheme) New(versionName, typeName string) (Object, error) {
|
||||
obj, err := s.raw.NewObject(versionName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(Object), nil
|
||||
}
|
||||
|
||||
// AddConversionFuncs adds a function to the list of conversion functions. The given
|
||||
@ -73,20 +91,20 @@ func New(versionName, typeName string) (interface{}, error) {
|
||||
// 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 AddConversionFuncs(conversionFuncs ...interface{}) error {
|
||||
return conversionScheme.AddConversionFuncs(conversionFuncs...)
|
||||
func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error {
|
||||
return s.raw.AddConversionFuncs(conversionFuncs...)
|
||||
}
|
||||
|
||||
// Convert will attempt to convert in into out. Both must be pointers to API objects.
|
||||
// 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 Convert(in, out interface{}) error {
|
||||
return conversionScheme.Convert(in, out)
|
||||
func (s *Scheme) Convert(in, out interface{}) error {
|
||||
return s.raw.Convert(in, out)
|
||||
}
|
||||
|
||||
// FindJSONBase takes an arbitary api type, returns pointer to its JSONBase field.
|
||||
// obj must be a pointer to an api type.
|
||||
func FindJSONBase(obj interface{}) (JSONBaseInterface, error) {
|
||||
func FindJSONBase(obj Object) (JSONBaseInterface, error) {
|
||||
v, err := enforcePtr(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -108,8 +126,8 @@ func FindJSONBase(obj interface{}) (JSONBaseInterface, error) {
|
||||
}
|
||||
|
||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
|
||||
func EncodeOrDie(obj interface{}) string {
|
||||
return conversionScheme.EncodeOrDie(obj)
|
||||
func (s *Scheme) EncodeOrDie(obj Object) string {
|
||||
return s.raw.EncodeOrDie(obj)
|
||||
}
|
||||
|
||||
// Encode turns the given api object into an appropriate JSON string.
|
||||
@ -146,14 +164,14 @@ func EncodeOrDie(obj interface{}) string {
|
||||
// default will be needed, to allow operating in clusters that haven't yet
|
||||
// upgraded.
|
||||
//
|
||||
func Encode(obj interface{}) (data []byte, err error) {
|
||||
return conversionScheme.Encode(obj)
|
||||
func (s *Scheme) Encode(obj Object) (data []byte, err error) {
|
||||
return s.raw.Encode(obj)
|
||||
}
|
||||
|
||||
// enforcePtr ensures that obj is a pointer of some sort. Returns a reflect.Value of the
|
||||
// dereferenced pointer, ensuring that it is settable/addressable.
|
||||
// Returns an error if this is not possible.
|
||||
func enforcePtr(obj interface{}) (reflect.Value, error) {
|
||||
func enforcePtr(obj Object) (reflect.Value, error) {
|
||||
v := reflect.ValueOf(obj)
|
||||
if v.Kind() != reflect.Ptr {
|
||||
return reflect.Value{}, fmt.Errorf("expected pointer, but got %v", v.Type().Name())
|
||||
@ -181,8 +199,12 @@ func VersionAndKind(data []byte) (version, kind string, err error) {
|
||||
// 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 Decode(data []byte) (interface{}, error) {
|
||||
return conversionScheme.Decode(data)
|
||||
func (s *Scheme) Decode(data []byte) (Object, error) {
|
||||
obj, err := s.raw.Decode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(Object), nil
|
||||
}
|
||||
|
||||
// DecodeInto parses a YAML or JSON string and stores it in obj. Returns an error
|
||||
@ -190,22 +212,22 @@ func Decode(data []byte) (interface{}, error) {
|
||||
// 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 DecodeInto(data []byte, obj interface{}) error {
|
||||
return conversionScheme.DecodeInto(data, obj)
|
||||
func (s *Scheme) DecodeInto(data []byte, obj Object) error {
|
||||
return s.raw.DecodeInto(data, obj)
|
||||
}
|
||||
|
||||
// Does a deep copy of an API object. Useful mostly for tests.
|
||||
// TODO(dbsmith): implement directly instead of via Encode/Decode
|
||||
func Copy(obj interface{}) (interface{}, error) {
|
||||
data, err := Encode(obj)
|
||||
func (s *Scheme) Copy(obj Object) (Object, error) {
|
||||
data, err := s.Encode(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Decode(data)
|
||||
return s.Decode(data)
|
||||
}
|
||||
|
||||
func CopyOrDie(obj interface{}) interface{} {
|
||||
newObj, err := Copy(obj)
|
||||
func (s *Scheme) CopyOrDie(obj Object) Object {
|
||||
newObj, err := s.Copy(obj)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -25,31 +25,13 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func TestEncode_NonPtr(t *testing.T) {
|
||||
pod := api.Pod{
|
||||
Labels: map[string]string{"name": "foo"},
|
||||
}
|
||||
obj := interface{}(pod)
|
||||
data, err := runtime.Encode(obj)
|
||||
obj2, err2 := runtime.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
}
|
||||
if _, ok := obj2.(*api.Pod); !ok {
|
||||
t.Fatalf("Got wrong type")
|
||||
}
|
||||
if !reflect.DeepEqual(obj2, &pod) {
|
||||
t.Errorf("Expected:\n %#v,\n Got:\n %#v", &pod, obj2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode_Ptr(t *testing.T) {
|
||||
func TestEncode(t *testing.T) {
|
||||
pod := &api.Pod{
|
||||
Labels: map[string]string{"name": "foo"},
|
||||
}
|
||||
obj := interface{}(pod)
|
||||
data, err := runtime.Encode(obj)
|
||||
obj2, err2 := runtime.Decode(data)
|
||||
obj := runtime.Object(pod)
|
||||
data, err := runtime.DefaultScheme.Encode(obj)
|
||||
obj2, err2 := runtime.DefaultScheme.Decode(data)
|
||||
if err != nil || err2 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v'", err, err2)
|
||||
}
|
||||
@ -63,11 +45,11 @@ func TestEncode_Ptr(t *testing.T) {
|
||||
|
||||
func TestBadJSONRejection(t *testing.T) {
|
||||
badJSONMissingKind := []byte(`{ }`)
|
||||
if _, err := runtime.Decode(badJSONMissingKind); err == nil {
|
||||
if _, err := runtime.DefaultScheme.Decode(badJSONMissingKind); err == nil {
|
||||
t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind)
|
||||
}
|
||||
badJSONUnknownType := []byte(`{"kind": "bar"}`)
|
||||
if _, err1 := runtime.Decode(badJSONUnknownType); err1 == nil {
|
||||
if _, err1 := runtime.DefaultScheme.Decode(badJSONUnknownType); err1 == nil {
|
||||
t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
|
||||
}
|
||||
/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)
|
||||
|
@ -29,7 +29,7 @@ func NewJSONBaseResourceVersioner() resourceVersioner {
|
||||
|
||||
type jsonBaseResourceVersioner struct{}
|
||||
|
||||
func (v jsonBaseResourceVersioner) ResourceVersion(obj interface{}) (uint64, error) {
|
||||
func (v jsonBaseResourceVersioner) ResourceVersion(obj Object) (uint64, error) {
|
||||
json, err := FindJSONBase(obj)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -37,7 +37,7 @@ func (v jsonBaseResourceVersioner) ResourceVersion(obj interface{}) (uint64, err
|
||||
return json.ResourceVersion(), nil
|
||||
}
|
||||
|
||||
func (v jsonBaseResourceVersioner) SetResourceVersion(obj interface{}, version uint64) error {
|
||||
func (v jsonBaseResourceVersioner) SetResourceVersion(obj Object, version uint64) error {
|
||||
json, err := FindJSONBase(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -77,20 +77,20 @@ func TestGenericJSONBase(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type MyAPIObject struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
|
||||
func (*MyAPIObject) IsAnAPIObject() {}
|
||||
|
||||
type MyIncorrectlyMarkedAsAPIObject struct {
|
||||
}
|
||||
|
||||
func (*MyIncorrectlyMarkedAsAPIObject) IsAnAPIObject() {}
|
||||
|
||||
func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
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"`
|
||||
}
|
||||
type MyAPIObject struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
}
|
||||
type T struct {
|
||||
Object interface{}
|
||||
Object
|
||||
Expected uint64
|
||||
}
|
||||
testCases := map[string]T{
|
||||
@ -110,10 +110,10 @@ func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
}
|
||||
|
||||
failingCases := map[string]struct {
|
||||
Object interface{}
|
||||
Object
|
||||
Expected uint64
|
||||
}{
|
||||
"not a valid object to try": {JSONBase{ResourceVersion: 1}, 1},
|
||||
"not a valid object to try": {&MyIncorrectlyMarkedAsAPIObject{}, 1},
|
||||
}
|
||||
for key, testCase := range failingCases {
|
||||
_, err := versioning.ResourceVersion(testCase.Object)
|
||||
@ -123,7 +123,7 @@ func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
}
|
||||
|
||||
setCases := map[string]struct {
|
||||
Object interface{}
|
||||
Object
|
||||
Expected uint64
|
||||
}{
|
||||
"pointer to api object with version": {&MyAPIObject{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
|
||||
@ -140,17 +140,4 @@ func TestResourceVersionerOfAPI(t *testing.T) {
|
||||
t.Errorf("%s: expected %d, got %d", key, 5, actual)
|
||||
}
|
||||
}
|
||||
|
||||
failingSetCases := map[string]struct {
|
||||
Object interface{}
|
||||
Expected uint64
|
||||
}{
|
||||
"empty api object": {MyAPIObject{}, 0},
|
||||
"api object with version": {MyAPIObject{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
|
||||
}
|
||||
for key, testCase := range failingSetCases {
|
||||
if err := versioning.SetResourceVersion(testCase.Object, 5); err == nil {
|
||||
t.Errorf("%s: unexpected non-error", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,15 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
// 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.
|
||||
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()
|
||||
}
|
||||
|
||||
// Note that the types provided in this file are not versioned and are intended to be
|
||||
// safe to use from within all versions of every API object.
|
||||
|
||||
@ -29,8 +38,9 @@ import (
|
||||
// runtime.JSONBase `yaml:",inline" json:",inline"`
|
||||
// ... // other fields
|
||||
// }
|
||||
// func (*MyAwesomeAPIObject) IsAnAPIObject() {}
|
||||
//
|
||||
// JSONBase is provided here for convenience. You may use it directlly from this package or define
|
||||
// JSONBase is provided here for convenience. You may use it directly from this package or define
|
||||
// your own with the same fields.
|
||||
//
|
||||
type JSONBase struct {
|
||||
@ -43,17 +53,16 @@ type JSONBase struct {
|
||||
}
|
||||
|
||||
// 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 interface{}
|
||||
// via the Get() function. Only objects having a JSONBase may be stored via Object.
|
||||
// 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.
|
||||
//
|
||||
// Note that objects will be serialized into the api package's default external versioned type;
|
||||
// this should be fixed in the future to use the version of the current Codec instead.
|
||||
// TODO(dbsmith): Stop using runtime.Codec, use the codec appropriate for the conversion (I have a plan).
|
||||
type EmbeddedObject struct {
|
||||
Object interface{}
|
||||
Object
|
||||
}
|
||||
|
||||
// Extension allows api objects with unknown types to be passed-through. This can be used
|
||||
@ -61,4 +70,8 @@ type EmbeddedObject struct {
|
||||
// JSONBase features-- kind, version, resourceVersion, etc.
|
||||
// TODO: Not implemented yet
|
||||
type Extension struct {
|
||||
JSONBase `yaml:",inline" json:",inline"`
|
||||
// RawJSON to go here.
|
||||
}
|
||||
|
||||
func (*Extension) IsAnAPIObject() {}
|
||||
|
Loading…
Reference in New Issue
Block a user