Combine pkg/apitools and pkg/api/common and call the result pkg/runtime

This commit is contained in:
Daniel Smith
2014-09-02 10:55:27 -07:00
parent 099c8fd36f
commit a63966e73c
44 changed files with 218 additions and 237 deletions

View File

@@ -1,19 +0,0 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package common provides types useful for all versions of any object
// that conforms to the kubernetes API object expectations.
package common

View File

@@ -1,92 +0,0 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package common
import (
"gopkg.in/v1/yaml"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
)
// Encode()/Decode() are the canonical way of converting an API object to/from
// wire format. This file provides utility functions which permit doing so
// recursively, such that API objects of types known only at run time can be
// embedded within other API types.
// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *Object) UnmarshalJSON(b []byte) error {
// Handle JSON's "null": Decode() doesn't expect it.
if len(b) == 4 && string(b) == "null" {
a.Object = nil
return nil
}
obj, err := apitools.Decode(b)
if err != nil {
return err
}
a.Object = obj
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (a Object) MarshalJSON() ([]byte, error) {
if a.Object == nil {
// Encode unset/nil objects as JSON's "null".
return []byte("null"), nil
}
return apitools.Encode(a.Object)
}
// SetYAML implements the yaml.Setter interface.
func (a *Object) SetYAML(tag string, value interface{}) bool {
if value == nil {
a.Object = nil
return true
}
// Why does the yaml package send value as a map[interface{}]interface{}?
// It's especially frustrating because encoding/json does the right thing
// by giving a []byte. So here we do the embarrasing thing of re-encode and
// de-encode the right way.
// TODO: Write a version of Decode that uses reflect to turn this value
// into an API object.
b, err := yaml.Marshal(value)
if err != nil {
panic("yaml can't reverse its own object")
}
obj, err := apitools.Decode(b)
if err != nil {
return false
}
a.Object = obj
return true
}
// GetYAML implements the yaml.Getter interface.
func (a Object) GetYAML() (tag string, value interface{}) {
if a.Object == nil {
value = "null"
return
}
// Encode returns JSON, which is conveniently a subset of YAML.
v, err := apitools.Encode(a.Object)
if err != nil {
panic("impossible to encode API object!")
}
return tag, v
}

View File

@@ -1,75 +0,0 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package common
import (
"encoding/json"
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
)
func TestObject(t *testing.T) {
type EmbeddedTest struct {
JSONBase `yaml:",inline" json:",inline"`
Object Object `yaml:"object,omitempty" json:"object,omitempty"`
EmptyObject Object `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
}
apitools.AddKnownTypes("", EmbeddedTest{})
apitools.AddKnownTypes("v1beta1", EmbeddedTest{})
outer := &EmbeddedTest{
JSONBase: JSONBase{ID: "outer"},
Object: Object{
&EmbeddedTest{
JSONBase: JSONBase{ID: "inner"},
},
},
}
wire, err := apitools.Encode(outer)
if err != nil {
t.Fatalf("Unexpected encode error '%v'", err)
}
t.Logf("Wire format is:\n%v\n", string(wire))
decoded, err := apitools.Decode(wire)
if err != nil {
t.Fatalf("Unexpected decode error %v", err)
}
if e, a := outer, decoded; !reflect.DeepEqual(e, a) {
t.Errorf("Expected: %#v but got %#v", e, a)
}
// test JSON decoding, too, since apitools.Decode uses yaml unmarshalling.
var decodedViaJSON EmbeddedTest
err = json.Unmarshal(wire, &decodedViaJSON)
if err != nil {
t.Fatalf("Unexpected decode error %v", err)
}
// Things that Decode would have done for us:
decodedViaJSON.Kind = ""
decodedViaJSON.APIVersion = ""
if e, a := outer, &decodedViaJSON; !reflect.DeepEqual(e, a) {
t.Errorf("Expected: %#v but got %#v", e, a)
}
}

View File

@@ -1,61 +0,0 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package common
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
// 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 {
// common.JSONBase `yaml:",inline" json:",inline"`
// ... // other fields
// }
//
// JSONBase is provided here for convenience. You may use it directlly from this package or define
// your own with the same fields.
//
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"`
}
// Object 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.
// 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.
type Object struct {
Object interface{}
}
// Extension allows api objects with unknown types to be passed-through. This can be used
// to deal with the API objects from a plug-in. Extension objects still have functioning
// JSONBase features-- kind, version, resourceVersion, etc.
// TODO: Not implemented yet
type Extension struct {
}

View File

@@ -17,11 +17,11 @@ limitations under the License.
package api
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func init() {
apitools.AddKnownTypes("",
runtime.AddKnownTypes("",
PodList{},
Pod{},
ReplicationControllerList{},

View File

@@ -25,7 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/fsouza/go-dockerclient"
"github.com/google/gofuzz"
@@ -108,20 +108,20 @@ func objDiff(a, b interface{}) string {
func runTest(t *testing.T, source interface{}) {
name := reflect.TypeOf(source).Elem().Name()
apiObjectFuzzer.Fuzz(source)
j, err := apitools.FindJSONBase(source)
j, err := runtime.FindJSONBase(source)
if err != nil {
t.Fatalf("Unexpected error %v for %#v", err, source)
}
j.SetKind("")
j.SetAPIVersion("")
data, err := apitools.Encode(source)
data, err := runtime.Encode(source)
if err != nil {
t.Errorf("%v: %v (%#v)", name, err, source)
return
}
obj2, err := apitools.Decode(data)
obj2, err := runtime.Decode(data)
if err != nil {
t.Errorf("%v: %v", name, err)
return
@@ -132,7 +132,7 @@ func runTest(t *testing.T, source interface{}) {
}
}
obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface()
err = apitools.DecodeInto(data, obj3)
err = runtime.DecodeInto(data, obj3)
if err != nil {
t.Errorf("2: %v: %v", name, err)
return
@@ -174,8 +174,8 @@ func TestEncode_NonPtr(t *testing.T) {
Labels: map[string]string{"name": "foo"},
}
obj := interface{}(pod)
data, err := apitools.Encode(obj)
obj2, err2 := apitools.Decode(data)
data, err := runtime.Encode(obj)
obj2, err2 := runtime.Decode(data)
if err != nil || err2 != nil {
t.Fatalf("Failure: '%v' '%v'", err, err2)
}
@@ -192,8 +192,8 @@ func TestEncode_Ptr(t *testing.T) {
Labels: map[string]string{"name": "foo"},
}
obj := interface{}(pod)
data, err := apitools.Encode(obj)
obj2, err2 := apitools.Decode(data)
data, err := runtime.Encode(obj)
obj2, err2 := runtime.Decode(data)
if err != nil || err2 != nil {
t.Fatalf("Failure: '%v' '%v'", err, err2)
}
@@ -207,11 +207,11 @@ func TestEncode_Ptr(t *testing.T) {
func TestBadJSONRejection(t *testing.T) {
badJSONMissingKind := []byte(`{ }`)
if _, err := apitools.Decode(badJSONMissingKind); err == nil {
if _, err := runtime.Decode(badJSONMissingKind); err == nil {
t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind)
}
badJSONUnknownType := []byte(`{"kind": "bar"}`)
if _, err1 := apitools.Decode(badJSONUnknownType); err1 == nil {
if _, err1 := runtime.Decode(badJSONUnknownType); err1 == nil {
t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
}
/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)

View File

@@ -17,7 +17,7 @@ limitations under the License.
package api
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/common"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/fsouza/go-dockerclient"
@@ -522,5 +522,5 @@ type WatchEvent struct {
// For added or modified objects, this is the new object; for deleted objects,
// it's the state of the object immediately prior to its deletion.
Object common.Object
Object runtime.Object
}

View File

@@ -19,14 +19,14 @@ package v1beta1
import (
// Alias this so it can be easily changed when we cut the next version.
newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func init() {
// Shortcut for sub-conversions. TODO: This should possibly be refactored
// such that this convert function is passed to each conversion func.
Convert := apitools.Convert
apitools.AddConversionFuncs(
Convert := runtime.Convert
runtime.AddConversionFuncs(
// EnvVar's Key is deprecated in favor of Name.
func(in *newer.EnvVar, out *EnvVar) error {
out.Value = in.Value

View File

@@ -22,10 +22,10 @@ import (
newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
var Convert = apitools.Convert
var Convert = runtime.Convert
func TestEnvConversion(t *testing.T) {
nonCanonical := []v1beta1.EnvVar{

View File

@@ -17,11 +17,11 @@ limitations under the License.
package v1beta1
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func init() {
apitools.AddKnownTypes("v1beta1",
runtime.AddKnownTypes("v1beta1",
PodList{},
Pod{},
ReplicationControllerList{},

View File

@@ -17,7 +17,7 @@ limitations under the License.
package v1beta1
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/common"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/GoogleCloudPlatform/kubernetes/third_party/docker-api-structs"
@@ -522,5 +522,5 @@ type WatchEvent struct {
// For added or modified objects, this is the new object; for deleted objects,
// it's the state of the object immediately prior to its deletion.
Object common.Object
Object runtime.Object
}