Merge pull request #1125 from lavalamp/fixApi

pkg/api: Separation of concerns
pull/6/head
Daniel Smith 2014-09-02 11:47:31 -07:00
commit 597099af18
55 changed files with 604 additions and 355 deletions

View File

@ -3,7 +3,6 @@ language: go
go:
- 1.3
- 1.2
- tip
install:
- go get code.google.com/p/go.tools/cmd/cover

View File

@ -31,6 +31,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubecfg"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
verflag "github.com/GoogleCloudPlatform/kubernetes/pkg/version/flag"
@ -237,7 +238,7 @@ func executeAPIRequest(method string, c *client.Client) bool {
if err != nil {
glog.Fatalf("error obtaining resource version for update: %v", err)
}
jsonBase, err := api.FindJSONBase(obj)
jsonBase, err := runtime.FindJSONBase(obj)
if err != nil {
glog.Fatalf("error finding json base for update: %v", err)
}
@ -257,16 +258,16 @@ func executeAPIRequest(method string, c *client.Client) bool {
if setBody {
if version != 0 {
data := readConfig(storage)
obj, err := api.Decode(data)
obj, err := runtime.Decode(data)
if err != nil {
glog.Fatalf("error setting resource version: %v", err)
}
jsonBase, err := api.FindJSONBase(obj)
jsonBase, err := runtime.FindJSONBase(obj)
if err != nil {
glog.Fatalf("error setting resource version: %v", err)
}
jsonBase.SetResourceVersion(version)
data, err = api.Encode(obj)
data, err = runtime.Encode(obj)
if err != nil {
glog.Fatalf("error setting resource version: %v", err)
}

View File

@ -26,25 +26,27 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/golang/glog"
)
func validateObject(obj interface{}) (errors []error) {
switch t := obj.(type) {
case *api.ReplicationController:
errors = api.ValidateManifest(&t.DesiredState.PodTemplate.DesiredState.Manifest)
errors = validation.ValidateManifest(&t.DesiredState.PodTemplate.DesiredState.Manifest)
case *api.ReplicationControllerList:
for i := range t.Items {
errors = append(errors, validateObject(&t.Items[i])...)
}
case *api.Service:
errors = api.ValidateService(t)
errors = validation.ValidateService(t)
case *api.ServiceList:
for i := range t.Items {
errors = append(errors, validateObject(&t.Items[i])...)
}
case *api.Pod:
errors = api.ValidateManifest(&t.DesiredState.Manifest)
errors = validation.ValidateManifest(&t.DesiredState.Manifest)
case *api.PodList:
for i := range t.Items {
errors = append(errors, validateObject(&t.Items[i])...)
@ -101,7 +103,7 @@ func TestApiExamples(t *testing.T) {
return
}
tested += 1
if err := api.DecodeInto(data, expectedType); err != nil {
if err := runtime.DecodeInto(data, expectedType); err != nil {
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
return
}
@ -135,7 +137,7 @@ func TestExamples(t *testing.T) {
return
}
tested += 1
if err := api.DecodeInto(data, expectedType); err != nil {
if err := runtime.DecodeInto(data, expectedType); err != nil {
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
return
}
@ -166,14 +168,14 @@ func TestReadme(t *testing.T) {
}
for _, json := range match[1:] {
expectedType := &api.Pod{}
if err := api.DecodeInto([]byte(json), expectedType); err != nil {
if err := runtime.DecodeInto([]byte(json), expectedType); err != nil {
t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
return
}
if errors := validateObject(expectedType); len(errors) > 0 {
t.Errorf("%s did not validate correctly: %v", path, errors)
}
encoded, err := api.Encode(expectedType)
encoded, err := runtime.Encode(expectedType)
if err != nil {
t.Errorf("Could not encode object: %v", err)
continue

View File

@ -14,6 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package api includes all types used to communicate between the various
// parts of the Kubernetes system.
// Package api contains the latest (or "internal") version of the
// Kubernetes API objects. This is the API objects as represented in memory.
// The contract presented to clients is located in the versioned packages,
// which are sub-directories. The first one is "v1beta1". Those packages
// describe how a particular version is serialized to storage/network.
package api

40
pkg/api/register.go Normal file
View File

@ -0,0 +1,40 @@
/*
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 api
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func init() {
runtime.AddKnownTypes("",
PodList{},
Pod{},
ReplicationControllerList{},
ReplicationController{},
ServiceList{},
Service{},
MinionList{},
Minion{},
Status{},
ServerOpList{},
ServerOp{},
ContainerManifestList{},
Endpoints{},
Binding{},
)
}

View File

@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/fsouza/go-dockerclient"
"github.com/google/gofuzz"
@ -107,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 := api.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 := api.Encode(source)
data, err := runtime.Encode(source)
if err != nil {
t.Errorf("%v: %v (%#v)", name, err, source)
return
}
obj2, err := api.Decode(data)
obj2, err := runtime.Decode(data)
if err != nil {
t.Errorf("%v: %v", name, err)
return
@ -131,7 +132,7 @@ func runTest(t *testing.T, source interface{}) {
}
}
obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface()
err = api.DecodeInto(data, obj3)
err = runtime.DecodeInto(data, obj3)
if err != nil {
t.Errorf("2: %v: %v", name, err)
return
@ -173,8 +174,8 @@ func TestEncode_NonPtr(t *testing.T) {
Labels: map[string]string{"name": "foo"},
}
obj := interface{}(pod)
data, err := api.Encode(obj)
obj2, err2 := api.Decode(data)
data, err := runtime.Encode(obj)
obj2, err2 := runtime.Decode(data)
if err != nil || err2 != nil {
t.Fatalf("Failure: '%v' '%v'", err, err2)
}
@ -191,8 +192,8 @@ func TestEncode_Ptr(t *testing.T) {
Labels: map[string]string{"name": "foo"},
}
obj := interface{}(pod)
data, err := api.Encode(obj)
obj2, err2 := api.Decode(data)
data, err := runtime.Encode(obj)
obj2, err2 := runtime.Decode(data)
if err != nil || err2 != nil {
t.Fatalf("Failure: '%v' '%v'", err, err2)
}
@ -206,11 +207,11 @@ func TestEncode_Ptr(t *testing.T) {
func TestBadJSONRejection(t *testing.T) {
badJSONMissingKind := []byte(`{ }`)
if _, err := api.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 := api.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,6 +17,7 @@ limitations under the License.
package api
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/fsouza/go-dockerclient"
@ -521,14 +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 APIObject
}
// APIObject 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 APIObject.
// The purpose of this is to allow an API object of type known only at runtime to be
// embedded within other API objects.
type APIObject struct {
Object interface{}
Object runtime.Object
}

View File

@ -19,15 +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"
// Also import under original name for Convert and AddConversionFuncs.
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"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 := api.Convert
api.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,9 +22,10 @@ import (
newer "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
var Convert = newer.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/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func init() {
api.AddKnownTypes("v1beta1",
runtime.AddKnownTypes("v1beta1",
PodList{},
Pod{},
ReplicationControllerList{},

View File

@ -17,6 +17,7 @@ limitations under the License.
package v1beta1
import (
"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"
@ -521,14 +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 APIObject
}
// APIObject 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 APIObject.
// The purpose of this is to allow an API object of type known only at runtime to be
// embedded within other API objects.
type APIObject struct {
Object interface{}
Object runtime.Object
}

19
pkg/api/validation/doc.go Normal file
View File

@ -0,0 +1,19 @@
/*
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 validation has functions for validating the correctness of api
// objects and explaining what is wrong with them when they aren't valid.
package validation

View File

@ -14,17 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package api
package validation
import (
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
errs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
func validateVolumes(volumes []Volume) (util.StringSet, errs.ErrorList) {
func validateVolumes(volumes []api.Volume) (util.StringSet, errs.ErrorList) {
allErrs := errs.ErrorList{}
allNames := util.StringSet{}
@ -51,7 +52,7 @@ func validateVolumes(volumes []Volume) (util.StringSet, errs.ErrorList) {
return allNames, allErrs
}
func validateSource(source *VolumeSource) errs.ErrorList {
func validateSource(source *api.VolumeSource) errs.ErrorList {
numVolumes := 0
allErrs := errs.ErrorList{}
if source.HostDirectory != nil {
@ -68,7 +69,7 @@ func validateSource(source *VolumeSource) errs.ErrorList {
return allErrs
}
func validateHostDir(hostDir *HostDirectory) errs.ErrorList {
func validateHostDir(hostDir *api.HostDirectory) errs.ErrorList {
allErrs := errs.ErrorList{}
if hostDir.Path == "" {
allErrs = append(allErrs, errs.NewNotFound("path", hostDir.Path))
@ -78,7 +79,7 @@ func validateHostDir(hostDir *HostDirectory) errs.ErrorList {
var supportedPortProtocols = util.NewStringSet("TCP", "UDP")
func validatePorts(ports []Port) errs.ErrorList {
func validatePorts(ports []api.Port) errs.ErrorList {
allErrs := errs.ErrorList{}
allNames := util.StringSet{}
@ -112,7 +113,7 @@ func validatePorts(ports []Port) errs.ErrorList {
return allErrs
}
func validateEnv(vars []EnvVar) errs.ErrorList {
func validateEnv(vars []api.EnvVar) errs.ErrorList {
allErrs := errs.ErrorList{}
for i := range vars {
@ -129,7 +130,7 @@ func validateEnv(vars []EnvVar) errs.ErrorList {
return allErrs
}
func validateVolumeMounts(mounts []VolumeMount, volumes util.StringSet) errs.ErrorList {
func validateVolumeMounts(mounts []api.VolumeMount, volumes util.StringSet) errs.ErrorList {
allErrs := errs.ErrorList{}
for i := range mounts {
@ -150,7 +151,7 @@ func validateVolumeMounts(mounts []VolumeMount, volumes util.StringSet) errs.Err
// AccumulateUniquePorts runs an extraction function on each Port of each Container,
// accumulating the results and returning an error if any ports conflict.
func AccumulateUniquePorts(containers []Container, accumulator map[int]bool, extract func(*Port) int) errs.ErrorList {
func AccumulateUniquePorts(containers []api.Container, accumulator map[int]bool, extract func(*api.Port) int) errs.ErrorList {
allErrs := errs.ErrorList{}
for ci := range containers {
@ -174,12 +175,12 @@ func AccumulateUniquePorts(containers []Container, accumulator map[int]bool, ext
// checkHostPortConflicts checks for colliding Port.HostPort values across
// a slice of containers.
func checkHostPortConflicts(containers []Container) errs.ErrorList {
func checkHostPortConflicts(containers []api.Container) errs.ErrorList {
allPorts := map[int]bool{}
return AccumulateUniquePorts(containers, allPorts, func(p *Port) int { return p.HostPort })
return AccumulateUniquePorts(containers, allPorts, func(p *api.Port) int { return p.HostPort })
}
func validateContainers(containers []Container, volumes util.StringSet) errs.ErrorList {
func validateContainers(containers []api.Container, volumes util.StringSet) errs.ErrorList {
allErrs := errs.ErrorList{}
allNames := util.StringSet{}
@ -219,7 +220,7 @@ var supportedManifestVersions = util.NewStringSet("v1beta1", "v1beta2")
// This includes checking formatting and uniqueness. It also canonicalizes the
// structure by setting default values and implementing any backwards-compatibility
// tricks.
func ValidateManifest(manifest *ContainerManifest) errs.ErrorList {
func ValidateManifest(manifest *api.ContainerManifest) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(manifest.Version) == 0 {
@ -233,13 +234,13 @@ func ValidateManifest(manifest *ContainerManifest) errs.ErrorList {
return allErrs
}
func ValidatePodState(podState *PodState) errs.ErrorList {
func ValidatePodState(podState *api.PodState) errs.ErrorList {
allErrs := errs.ErrorList(ValidateManifest(&podState.Manifest)).Prefix("manifest")
if podState.RestartPolicy.Type == "" {
podState.RestartPolicy.Type = RestartAlways
} else if podState.RestartPolicy.Type != RestartAlways &&
podState.RestartPolicy.Type != RestartOnFailure &&
podState.RestartPolicy.Type != RestartNever {
podState.RestartPolicy.Type = api.RestartAlways
} else if podState.RestartPolicy.Type != api.RestartAlways &&
podState.RestartPolicy.Type != api.RestartOnFailure &&
podState.RestartPolicy.Type != api.RestartNever {
allErrs = append(allErrs, errs.NewNotSupported("restartPolicy.type", podState.RestartPolicy.Type))
}
@ -247,7 +248,7 @@ func ValidatePodState(podState *PodState) errs.ErrorList {
}
// ValidatePod tests if required fields in the pod are set.
func ValidatePod(pod *Pod) errs.ErrorList {
func ValidatePod(pod *api.Pod) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(pod.ID) == 0 {
allErrs = append(allErrs, errs.NewRequired("id", pod.ID))
@ -257,7 +258,7 @@ func ValidatePod(pod *Pod) errs.ErrorList {
}
// ValidateService tests if required fields in the service are set.
func ValidateService(service *Service) errs.ErrorList {
func ValidateService(service *api.Service) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(service.ID) == 0 {
allErrs = append(allErrs, errs.NewRequired("id", service.ID))
@ -274,7 +275,7 @@ func ValidateService(service *Service) errs.ErrorList {
}
// ValidateReplicationController tests if required fields in the replication controller are set.
func ValidateReplicationController(controller *ReplicationController) errs.ErrorList {
func ValidateReplicationController(controller *api.ReplicationController) errs.ErrorList {
allErrs := errs.ErrorList{}
if len(controller.ID) == 0 {
allErrs = append(allErrs, errs.NewRequired("id", controller.ID))

View File

@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package api
package validation
import (
"strings"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
@ -33,11 +34,11 @@ func expectPrefix(t *testing.T, prefix string, errs errors.ErrorList) {
}
func TestValidateVolumes(t *testing.T) {
successCase := []Volume{
successCase := []api.Volume{
{Name: "abc"},
{Name: "123", Source: &VolumeSource{HostDirectory: &HostDirectory{"/mnt/path2"}}},
{Name: "abc-123", Source: &VolumeSource{HostDirectory: &HostDirectory{"/mnt/path3"}}},
{Name: "empty", Source: &VolumeSource{EmptyDirectory: &EmptyDirectory{}}},
{Name: "123", Source: &api.VolumeSource{HostDirectory: &api.HostDirectory{"/mnt/path2"}}},
{Name: "abc-123", Source: &api.VolumeSource{HostDirectory: &api.HostDirectory{"/mnt/path3"}}},
{Name: "empty", Source: &api.VolumeSource{EmptyDirectory: &api.EmptyDirectory{}}},
}
names, errs := validateVolumes(successCase)
if len(errs) != 0 {
@ -48,14 +49,14 @@ func TestValidateVolumes(t *testing.T) {
}
errorCases := map[string]struct {
V []Volume
V []api.Volume
T errors.ValidationErrorType
F string
}{
"zero-length name": {[]Volume{{Name: ""}}, errors.ValidationErrorTypeRequired, "[0].name"},
"name > 63 characters": {[]Volume{{Name: strings.Repeat("a", 64)}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not a DNS label": {[]Volume{{Name: "a.b.c"}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not unique": {[]Volume{{Name: "abc"}, {Name: "abc"}}, errors.ValidationErrorTypeDuplicate, "[1].name"},
"zero-length name": {[]api.Volume{{Name: ""}}, errors.ValidationErrorTypeRequired, "[0].name"},
"name > 63 characters": {[]api.Volume{{Name: strings.Repeat("a", 64)}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not a DNS label": {[]api.Volume{{Name: "a.b.c"}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not unique": {[]api.Volume{{Name: "abc"}, {Name: "abc"}}, errors.ValidationErrorTypeDuplicate, "[1].name"},
}
for k, v := range errorCases {
_, errs := validateVolumes(v.V)
@ -75,7 +76,7 @@ func TestValidateVolumes(t *testing.T) {
}
func TestValidatePorts(t *testing.T) {
successCase := []Port{
successCase := []api.Port{
{Name: "abc", ContainerPort: 80, HostPort: 80, Protocol: "TCP"},
{Name: "123", ContainerPort: 81, HostPort: 81},
{Name: "easy", ContainerPort: 82, Protocol: "TCP"},
@ -88,7 +89,7 @@ func TestValidatePorts(t *testing.T) {
t.Errorf("expected success: %v", errs)
}
nonCanonicalCase := []Port{
nonCanonicalCase := []api.Port{
{ContainerPort: 80},
}
if errs := validatePorts(nonCanonicalCase); len(errs) != 0 {
@ -99,20 +100,20 @@ func TestValidatePorts(t *testing.T) {
}
errorCases := map[string]struct {
P []Port
P []api.Port
T errors.ValidationErrorType
F string
}{
"name > 63 characters": {[]Port{{Name: strings.Repeat("a", 64), ContainerPort: 80}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not a DNS label": {[]Port{{Name: "a.b.c", ContainerPort: 80}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not unique": {[]Port{
"name > 63 characters": {[]api.Port{{Name: strings.Repeat("a", 64), ContainerPort: 80}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not a DNS label": {[]api.Port{{Name: "a.b.c", ContainerPort: 80}}, errors.ValidationErrorTypeInvalid, "[0].name"},
"name not unique": {[]api.Port{
{Name: "abc", ContainerPort: 80},
{Name: "abc", ContainerPort: 81},
}, errors.ValidationErrorTypeDuplicate, "[1].name"},
"zero container port": {[]Port{{ContainerPort: 0}}, errors.ValidationErrorTypeRequired, "[0].containerPort"},
"invalid container port": {[]Port{{ContainerPort: 65536}}, errors.ValidationErrorTypeInvalid, "[0].containerPort"},
"invalid host port": {[]Port{{ContainerPort: 80, HostPort: 65536}}, errors.ValidationErrorTypeInvalid, "[0].hostPort"},
"invalid protocol": {[]Port{{ContainerPort: 80, Protocol: "ICMP"}}, errors.ValidationErrorTypeNotSupported, "[0].protocol"},
"zero container port": {[]api.Port{{ContainerPort: 0}}, errors.ValidationErrorTypeRequired, "[0].containerPort"},
"invalid container port": {[]api.Port{{ContainerPort: 65536}}, errors.ValidationErrorTypeInvalid, "[0].containerPort"},
"invalid host port": {[]api.Port{{ContainerPort: 80, HostPort: 65536}}, errors.ValidationErrorTypeInvalid, "[0].hostPort"},
"invalid protocol": {[]api.Port{{ContainerPort: 80, Protocol: "ICMP"}}, errors.ValidationErrorTypeNotSupported, "[0].protocol"},
}
for k, v := range errorCases {
errs := validatePorts(v.P)
@ -131,7 +132,7 @@ func TestValidatePorts(t *testing.T) {
}
func TestValidateEnv(t *testing.T) {
successCase := []EnvVar{
successCase := []api.EnvVar{
{Name: "abc", Value: "value"},
{Name: "ABC", Value: "value"},
{Name: "AbC_123", Value: "value"},
@ -141,7 +142,7 @@ func TestValidateEnv(t *testing.T) {
t.Errorf("expected success: %v", errs)
}
errorCases := map[string][]EnvVar{
errorCases := map[string][]api.EnvVar{
"zero-length name": {{Name: ""}},
"name not a C identifier": {{Name: "a.b.c"}},
}
@ -155,7 +156,7 @@ func TestValidateEnv(t *testing.T) {
func TestValidateVolumeMounts(t *testing.T) {
volumes := util.NewStringSet("abc", "123", "abc-123")
successCase := []VolumeMount{
successCase := []api.VolumeMount{
{Name: "abc", MountPath: "/foo"},
{Name: "123", MountPath: "/foo"},
{Name: "abc-123", MountPath: "/bar"},
@ -164,7 +165,7 @@ func TestValidateVolumeMounts(t *testing.T) {
t.Errorf("expected success: %v", errs)
}
errorCases := map[string][]VolumeMount{
errorCases := map[string][]api.VolumeMount{
"empty name": {{Name: "", MountPath: "/foo"}},
"name not found": {{Name: "", MountPath: "/foo"}},
"empty mountpath": {{Name: "abc", MountPath: ""}},
@ -179,7 +180,7 @@ func TestValidateVolumeMounts(t *testing.T) {
func TestValidateContainers(t *testing.T) {
volumes := util.StringSet{}
successCase := []Container{
successCase := []api.Container{
{Name: "abc", Image: "image"},
{Name: "123", Image: "image"},
{Name: "abc-123", Image: "image"},
@ -188,7 +189,7 @@ func TestValidateContainers(t *testing.T) {
t.Errorf("expected success: %v", errs)
}
errorCases := map[string][]Container{
errorCases := map[string][]api.Container{
"zero-length name": {{Name: "", Image: "image"}},
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image"}},
"name not a DNS label": {{Name: "a.b.c", Image: "image"}},
@ -198,14 +199,14 @@ func TestValidateContainers(t *testing.T) {
},
"zero-length image": {{Name: "abc", Image: ""}},
"host port not unique": {
{Name: "abc", Image: "image", Ports: []Port{{ContainerPort: 80, HostPort: 80}}},
{Name: "def", Image: "image", Ports: []Port{{ContainerPort: 81, HostPort: 80}}},
{Name: "abc", Image: "image", Ports: []api.Port{{ContainerPort: 80, HostPort: 80}}},
{Name: "def", Image: "image", Ports: []api.Port{{ContainerPort: 81, HostPort: 80}}},
},
"invalid env var name": {
{Name: "abc", Image: "image", Env: []EnvVar{{Name: "ev.1"}}},
{Name: "abc", Image: "image", Env: []api.EnvVar{{Name: "ev.1"}}},
},
"unknown volume name": {
{Name: "abc", Image: "image", VolumeMounts: []VolumeMount{{Name: "anything", MountPath: "/foo"}}},
{Name: "abc", Image: "image", VolumeMounts: []api.VolumeMount{{Name: "anything", MountPath: "/foo"}}},
},
}
for k, v := range errorCases {
@ -216,16 +217,16 @@ func TestValidateContainers(t *testing.T) {
}
func TestValidateManifest(t *testing.T) {
successCases := []ContainerManifest{
successCases := []api.ContainerManifest{
{Version: "v1beta1", ID: "abc"},
{Version: "v1beta2", ID: "123"},
{Version: "V1BETA1", ID: "abc.123.do-re-mi"},
{
Version: "v1beta1",
ID: "abc",
Volumes: []Volume{{Name: "vol1", Source: &VolumeSource{HostDirectory: &HostDirectory{"/mnt/vol1"}}},
{Name: "vol2", Source: &VolumeSource{HostDirectory: &HostDirectory{"/mnt/vol2"}}}},
Containers: []Container{
Volumes: []api.Volume{{Name: "vol1", Source: &api.VolumeSource{HostDirectory: &api.HostDirectory{"/mnt/vol1"}}},
{Name: "vol2", Source: &api.VolumeSource{HostDirectory: &api.HostDirectory{"/mnt/vol2"}}}},
Containers: []api.Container{
{
Name: "abc",
Image: "image",
@ -233,17 +234,17 @@ func TestValidateManifest(t *testing.T) {
WorkingDir: "/tmp",
Memory: 1,
CPU: 1,
Ports: []Port{
Ports: []api.Port{
{Name: "p1", ContainerPort: 80, HostPort: 8080},
{Name: "p2", ContainerPort: 81},
{ContainerPort: 82},
},
Env: []EnvVar{
Env: []api.EnvVar{
{Name: "ev1", Value: "val1"},
{Name: "ev2", Value: "val2"},
{Name: "EV3", Value: "val3"},
},
VolumeMounts: []VolumeMount{
VolumeMounts: []api.VolumeMount{
{Name: "vol1", MountPath: "/foo"},
{Name: "vol1", MountPath: "/bar"},
},
@ -257,18 +258,18 @@ func TestValidateManifest(t *testing.T) {
}
}
errorCases := map[string]ContainerManifest{
errorCases := map[string]api.ContainerManifest{
"empty version": {Version: "", ID: "abc"},
"invalid version": {Version: "bogus", ID: "abc"},
"invalid volume name": {
Version: "v1beta1",
ID: "abc",
Volumes: []Volume{{Name: "vol.1"}},
Volumes: []api.Volume{{Name: "vol.1"}},
},
"invalid container name": {
Version: "v1beta1",
ID: "abc",
Containers: []Container{{Name: "ctr.1", Image: "image"}},
Containers: []api.Container{{Name: "ctr.1", Image: "image"}},
},
}
for k, v := range errorCases {
@ -279,40 +280,40 @@ func TestValidateManifest(t *testing.T) {
}
func TestValidatePod(t *testing.T) {
errs := ValidatePod(&Pod{
JSONBase: JSONBase{ID: "foo"},
errs := ValidatePod(&api.Pod{
JSONBase: api.JSONBase{ID: "foo"},
Labels: map[string]string{
"foo": "bar",
},
DesiredState: PodState{
Manifest: ContainerManifest{Version: "v1beta1", ID: "abc"},
RestartPolicy: RestartPolicy{Type: "RestartAlways"},
DesiredState: api.PodState{
Manifest: api.ContainerManifest{Version: "v1beta1", ID: "abc"},
RestartPolicy: api.RestartPolicy{Type: "RestartAlways"},
},
})
if len(errs) != 0 {
t.Errorf("Unexpected non-zero error list: %#v", errs)
}
errs = ValidatePod(&Pod{
JSONBase: JSONBase{ID: "foo"},
errs = ValidatePod(&api.Pod{
JSONBase: api.JSONBase{ID: "foo"},
Labels: map[string]string{
"foo": "bar",
},
DesiredState: PodState{
Manifest: ContainerManifest{Version: "v1beta1", ID: "abc"},
DesiredState: api.PodState{
Manifest: api.ContainerManifest{Version: "v1beta1", ID: "abc"},
},
})
if len(errs) != 0 {
t.Errorf("Unexpected non-zero error list: %#v", errs)
}
errs = ValidatePod(&Pod{
JSONBase: JSONBase{ID: "foo"},
errs = ValidatePod(&api.Pod{
JSONBase: api.JSONBase{ID: "foo"},
Labels: map[string]string{
"foo": "bar",
},
DesiredState: PodState{
Manifest: ContainerManifest{Version: "v1beta1", ID: "abc"},
RestartPolicy: RestartPolicy{Type: "WhatEver"},
DesiredState: api.PodState{
Manifest: api.ContainerManifest{Version: "v1beta1", ID: "abc"},
RestartPolicy: api.RestartPolicy{Type: "WhatEver"},
},
})
if len(errs) != 1 {
@ -323,8 +324,8 @@ func TestValidatePod(t *testing.T) {
func TestValidateService(t *testing.T) {
// This test should fail because the port number is invalid i.e.
// the Port field has a default value of 0.
errs := ValidateService(&Service{
JSONBase: JSONBase{ID: "foo"},
errs := ValidateService(&api.Service{
JSONBase: api.JSONBase{ID: "foo"},
Selector: map[string]string{
"foo": "bar",
},
@ -333,9 +334,9 @@ func TestValidateService(t *testing.T) {
t.Errorf("Unexpected error list: %#v", errs)
}
errs = ValidateService(&Service{
errs = ValidateService(&api.Service{
Port: 6502,
JSONBase: JSONBase{ID: "foo"},
JSONBase: api.JSONBase{ID: "foo"},
Selector: map[string]string{
"foo": "bar",
},
@ -344,7 +345,7 @@ func TestValidateService(t *testing.T) {
t.Errorf("Unexpected non-zero error list: %#v", errs)
}
errs = ValidateService(&Service{
errs = ValidateService(&api.Service{
Port: 6502,
Selector: map[string]string{
"foo": "bar",
@ -354,15 +355,15 @@ func TestValidateService(t *testing.T) {
t.Errorf("Unexpected error list: %#v", errs)
}
errs = ValidateService(&Service{
errs = ValidateService(&api.Service{
Port: 6502,
JSONBase: JSONBase{ID: "foo"},
JSONBase: api.JSONBase{ID: "foo"},
})
if len(errs) != 1 {
t.Errorf("Unexpected error list: %#v", errs)
}
errs = ValidateService(&Service{})
errs = ValidateService(&api.Service{})
if len(errs) != 3 {
t.Errorf("Unexpected error list: %#v", errs)
}
@ -370,26 +371,26 @@ func TestValidateService(t *testing.T) {
func TestValidateReplicationController(t *testing.T) {
validSelector := map[string]string{"a": "b"}
validPodTemplate := PodTemplate{
DesiredState: PodState{
Manifest: ContainerManifest{
validPodTemplate := api.PodTemplate{
DesiredState: api.PodState{
Manifest: api.ContainerManifest{
Version: "v1beta1",
},
},
Labels: validSelector,
}
successCases := []ReplicationController{
successCases := []api.ReplicationController{
{
JSONBase: JSONBase{ID: "abc"},
DesiredState: ReplicationControllerState{
JSONBase: api.JSONBase{ID: "abc"},
DesiredState: api.ReplicationControllerState{
ReplicaSelector: validSelector,
PodTemplate: validPodTemplate,
},
},
{
JSONBase: JSONBase{ID: "abc-123"},
DesiredState: ReplicationControllerState{
JSONBase: api.JSONBase{ID: "abc-123"},
DesiredState: api.ReplicationControllerState{
ReplicaSelector: validSelector,
PodTemplate: validPodTemplate,
},
@ -401,36 +402,36 @@ func TestValidateReplicationController(t *testing.T) {
}
}
errorCases := map[string]ReplicationController{
errorCases := map[string]api.ReplicationController{
"zero-length ID": {
JSONBase: JSONBase{ID: ""},
DesiredState: ReplicationControllerState{
JSONBase: api.JSONBase{ID: ""},
DesiredState: api.ReplicationControllerState{
ReplicaSelector: validSelector,
PodTemplate: validPodTemplate,
},
},
"empty selector": {
JSONBase: JSONBase{ID: "abc"},
DesiredState: ReplicationControllerState{
JSONBase: api.JSONBase{ID: "abc"},
DesiredState: api.ReplicationControllerState{
PodTemplate: validPodTemplate,
},
},
"selector_doesnt_match": {
JSONBase: JSONBase{ID: "abc"},
DesiredState: ReplicationControllerState{
JSONBase: api.JSONBase{ID: "abc"},
DesiredState: api.ReplicationControllerState{
ReplicaSelector: map[string]string{"foo": "bar"},
PodTemplate: validPodTemplate,
},
},
"invalid manifest": {
JSONBase: JSONBase{ID: "abc"},
DesiredState: ReplicationControllerState{
JSONBase: api.JSONBase{ID: "abc"},
DesiredState: api.ReplicationControllerState{
ReplicaSelector: validSelector,
},
},
"negative_replicas": {
JSONBase: JSONBase{ID: "abc"},
DesiredState: ReplicationControllerState{
JSONBase: api.JSONBase{ID: "abc"},
DesiredState: api.ReplicationControllerState{
Replicas: -1,
ReplicaSelector: validSelector,
},

View File

@ -32,6 +32,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
@ -40,11 +41,11 @@ func convert(obj interface{}) (interface{}, error) {
return obj, nil
}
var codec = api.Codec
var codec = runtime.Codec
func init() {
api.AddKnownTypes("", Simple{}, SimpleList{})
api.AddKnownTypes("v1beta1", Simple{}, SimpleList{})
runtime.AddKnownTypes("", Simple{}, SimpleList{})
runtime.AddKnownTypes("v1beta1", Simple{}, SimpleList{})
}
type Simple struct {
@ -696,7 +697,7 @@ func TestWriteJSONDecodeError(t *testing.T) {
type T struct {
Value string
}
writeJSON(http.StatusOK, api.Codec, &T{"Undecodable"}, w)
writeJSON(http.StatusOK, runtime.Codec, &T{"Undecodable"}, w)
}))
status := expectApiStatus(t, "GET", server.URL, nil, http.StatusInternalServerError)
if status.Reason != api.StatusReasonUnknown {

View File

@ -26,6 +26,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
@ -112,7 +113,7 @@ func (w *WatchServer) HandleWS(ws *websocket.Conn) {
}
err := websocket.JSON.Send(ws, &api.WatchEvent{
Type: event.Type,
Object: api.APIObject{event.Object},
Object: runtime.Object{event.Object},
})
if err != nil {
// Client disconnect.
@ -159,7 +160,7 @@ func (self *WatchServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
err := encoder.Encode(&api.WatchEvent{
Type: event.Type,
Object: api.APIObject{event.Object},
Object: runtime.Object{event.Object},
})
if err != nil {
// Client disconnect.

View File

@ -20,7 +20,7 @@ import (
"reflect"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/golang/glog"
@ -81,7 +81,7 @@ func (gc *Reflector) watchHandler(w watch.Interface, resourceVersion *uint64) {
glog.Errorf("expected type %v, but watch event object had type %v", e, a)
continue
}
jsonBase, err := api.FindJSONBase(event.Object)
jsonBase, err := runtime.FindJSONBase(event.Object)
if err != nil {
glog.Errorf("unable to understand watch event %#v", event)
continue

View File

@ -28,6 +28,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
@ -216,7 +217,7 @@ func (c *RESTClient) doRequest(request *http.Request) ([]byte, error) {
// Did the server give us a status response?
isStatusResponse := false
var status api.Status
if err := api.DecodeInto(body, &status); err == nil && status.Status != "" {
if err := runtime.DecodeInto(body, &status); err == nil && status.Status != "" {
isStatusResponse = true
}

View File

@ -27,6 +27,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
)
@ -308,7 +309,7 @@ func TestCreateController(t *testing.T) {
func body(obj interface{}, raw *string) *string {
if obj != nil {
bs, _ := api.Encode(obj)
bs, _ := runtime.Encode(obj)
body := string(bs)
return &body
}
@ -470,7 +471,7 @@ func TestDoRequest(t *testing.T) {
func TestDoRequestAccepted(t *testing.T) {
status := api.Status{Status: api.StatusWorking}
expectedBody, _ := api.Encode(status)
expectedBody, _ := runtime.Encode(status)
fakeHandler := util.FakeHandler{
StatusCode: 202,
ResponseBody: string(expectedBody),
@ -507,7 +508,7 @@ func TestDoRequestAccepted(t *testing.T) {
func TestDoRequestAcceptedSuccess(t *testing.T) {
status := api.Status{Status: api.StatusSuccess}
expectedBody, _ := api.Encode(status)
expectedBody, _ := runtime.Encode(status)
fakeHandler := util.FakeHandler{
StatusCode: 202,
ResponseBody: string(expectedBody),
@ -527,7 +528,7 @@ func TestDoRequestAcceptedSuccess(t *testing.T) {
if err != nil {
t.Errorf("Unexpected error %#v", err)
}
statusOut, err := api.Decode(body)
statusOut, err := runtime.Decode(body)
if err != nil {
t.Errorf("Unexpected error %#v", err)
}

View File

@ -29,6 +29,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
@ -204,7 +205,7 @@ func (r *Request) Body(obj interface{}) *Request {
case io.Reader:
r.body = t
default:
data, err := api.Encode(obj)
data, err := runtime.Encode(obj)
if err != nil {
r.err = err
return r
@ -317,7 +318,7 @@ func (r Result) Get() (interface{}, error) {
if r.err != nil {
return nil, r.err
}
return api.Decode(r.body)
return runtime.Decode(r.body)
}
// Into stores the result into obj, if possible.
@ -325,7 +326,7 @@ func (r Result) Into(obj interface{}) error {
if r.err != nil {
return r.err
}
return api.DecodeInto(r.body, obj)
return runtime.DecodeInto(r.body, obj)
}
// Error returns the error executing the request, nil if no error occurred.

View File

@ -30,6 +30,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
@ -37,7 +38,7 @@ import (
func TestDoRequestNewWay(t *testing.T) {
reqBody := "request body"
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := api.Encode(expectedObj)
expectedBody, _ := runtime.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@ -70,9 +71,9 @@ func TestDoRequestNewWay(t *testing.T) {
func TestDoRequestNewWayReader(t *testing.T) {
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
reqBodyExpected, _ := api.Encode(reqObj)
reqBodyExpected, _ := runtime.Encode(reqObj)
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := api.Encode(expectedObj)
expectedBody, _ := runtime.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@ -107,9 +108,9 @@ func TestDoRequestNewWayReader(t *testing.T) {
func TestDoRequestNewWayObj(t *testing.T) {
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
reqBodyExpected, _ := api.Encode(reqObj)
reqBodyExpected, _ := runtime.Encode(reqObj)
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := api.Encode(expectedObj)
expectedBody, _ := runtime.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@ -143,7 +144,7 @@ func TestDoRequestNewWayObj(t *testing.T) {
func TestDoRequestNewWayFile(t *testing.T) {
reqObj := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
reqBodyExpected, err := api.Encode(reqObj)
reqBodyExpected, err := runtime.Encode(reqObj)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -159,7 +160,7 @@ func TestDoRequestNewWayFile(t *testing.T) {
}
expectedObj := &api.Service{Port: 12345}
expectedBody, _ := api.Encode(expectedObj)
expectedBody, _ := runtime.Encode(expectedObj)
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(expectedBody),
@ -294,7 +295,7 @@ func TestPolling(t *testing.T) {
callNumber := 0
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, err := api.Encode(objects[callNumber])
data, err := runtime.Encode(objects[callNumber])
if err != nil {
t.Errorf("Unexpected encode error")
}
@ -400,7 +401,7 @@ func TestWatch(t *testing.T) {
encoder := json.NewEncoder(w)
for _, item := range table {
encoder.Encode(&api.WatchEvent{item.t, api.APIObject{item.obj}})
encoder.Encode(&api.WatchEvent{item.t, runtime.Object{item.obj}})
flusher.Flush()
}
}))

View File

@ -29,6 +29,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
@ -108,7 +109,7 @@ func validateSyncReplication(t *testing.T, fakePodControl *FakePodControl, expec
}
func TestSyncReplicationControllerDoesNothing(t *testing.T) {
body, _ := api.Encode(newPodList(2))
body, _ := runtime.Encode(newPodList(2))
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(body),
@ -128,7 +129,7 @@ func TestSyncReplicationControllerDoesNothing(t *testing.T) {
}
func TestSyncReplicationControllerDeletes(t *testing.T) {
body, _ := api.Encode(newPodList(2))
body, _ := runtime.Encode(newPodList(2))
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(body),
@ -148,7 +149,7 @@ func TestSyncReplicationControllerDeletes(t *testing.T) {
}
func TestSyncReplicationControllerCreates(t *testing.T) {
body, _ := api.Encode(newPodList(0))
body, _ := runtime.Encode(newPodList(0))
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(body),
@ -168,7 +169,7 @@ func TestSyncReplicationControllerCreates(t *testing.T) {
}
func TestCreateReplica(t *testing.T) {
body, _ := api.Encode(api.Pod{})
body, _ := runtime.Encode(api.Pod{})
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(body),
@ -291,7 +292,7 @@ func TestSyncronize(t *testing.T) {
}
fakeControllerHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: api.EncodeOrDie(&api.ReplicationControllerList{
ResponseBody: runtime.EncodeOrDie(&api.ReplicationControllerList{
Items: []api.ReplicationController{
controllerSpec1,
controllerSpec2,

View File

@ -20,7 +20,7 @@ import (
"fmt"
"reflect"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
type Parser struct {
@ -44,11 +44,11 @@ func (p *Parser) ToWireFormat(data []byte, storage string) ([]byte, error) {
}
obj := reflect.New(prototypeType).Interface()
err := api.DecodeInto(data, obj)
err := runtime.DecodeInto(data, obj)
if err != nil {
return nil, err
}
return api.Encode(obj)
return runtime.Encode(obj)
}
func (p *Parser) SupportedWireStorage() []string {

View File

@ -20,6 +20,7 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"gopkg.in/v1/yaml"
)
@ -32,7 +33,7 @@ func TestParseBadStorage(t *testing.T) {
}
func DoParseTest(t *testing.T, storage string, obj interface{}, p *Parser) {
jsonData, _ := api.Encode(obj)
jsonData, _ := runtime.Encode(obj)
yamlData, _ := yaml.Marshal(obj)
t.Logf("Intermediate yaml:\n%v\n", string(yamlData))
t.Logf("Intermediate json:\n%v\n", string(jsonData))
@ -119,8 +120,8 @@ type TestParseType struct {
}
func TestParseCustomType(t *testing.T) {
api.AddKnownTypes("", TestParseType{})
api.AddKnownTypes("v1beta1", TestParseType{})
runtime.AddKnownTypes("", TestParseType{})
runtime.AddKnownTypes("v1beta1", TestParseType{})
parser := NewParser(map[string]interface{}{
"custom": TestParseType{},
})

View File

@ -22,6 +22,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
@ -52,7 +53,7 @@ func (s *ProxyServer) Serve() error {
func (s *ProxyServer) doError(w http.ResponseWriter, err error) {
w.WriteHeader(http.StatusInternalServerError)
w.Header().Add("Content-type", "application/json")
data, _ := api.Encode(api.Status{
data, _ := runtime.Encode(api.Status{
Status: api.StatusFailure,
Message: fmt.Sprintf("internal error: %#v", err),
})

View File

@ -27,6 +27,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/golang/glog"
"gopkg.in/v1/yaml"
)
@ -49,7 +50,7 @@ func (i *IdentityPrinter) Print(data []byte, w io.Writer) error {
// PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer.
func (i *IdentityPrinter) PrintObj(obj interface{}, output io.Writer) error {
data, err := api.Encode(obj)
data, err := runtime.Encode(obj)
if err != nil {
return err
}
@ -258,7 +259,7 @@ func (h *HumanReadablePrinter) Print(data []byte, output io.Writer) error {
return fmt.Errorf("unexpected object with no 'kind' field: %s", data)
}
obj, err := api.Decode(data)
obj, err := runtime.Decode(data)
if err != nil {
return err
}
@ -290,7 +291,7 @@ type TemplatePrinter struct {
// Print parses the data as JSON, and re-formats it with the Go Template.
func (t *TemplatePrinter) Print(data []byte, w io.Writer) error {
obj, err := api.Decode(data)
obj, err := runtime.Decode(data)
if err != nil {
return err
}

View File

@ -25,6 +25,7 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"gopkg.in/v1/yaml"
)
@ -95,7 +96,7 @@ func TestIdentityPrinter(t *testing.T) {
}
buff.Reset()
printer.PrintObj(obj, buff)
objOut, err := api.Decode([]byte(buff.String()))
objOut, err := runtime.Decode([]byte(buff.String()))
if err != nil {
t.Errorf("Unexpeted error: %#v", err)
}

View File

@ -23,6 +23,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/coreos/go-etcd/etcd"
)
@ -35,7 +36,7 @@ func TestGetEtcdData(t *testing.T) {
fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{
R: &etcd.Response{
Node: &etcd.Node{
Value: api.EncodeOrDie(&api.ContainerManifestList{
Value: runtime.EncodeOrDie(&api.ContainerManifestList{
Items: []api.ContainerManifest{{ID: "foo"}},
}),
ModifiedIndex: 1,
@ -78,7 +79,7 @@ func TestGetEtcd(t *testing.T) {
fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{
R: &etcd.Response{
Node: &etcd.Node{
Value: api.EncodeOrDie(&api.ContainerManifestList{
Value: runtime.EncodeOrDie(&api.ContainerManifestList{
Items: []api.ContainerManifest{manifest},
}),
ModifiedIndex: 1,
@ -112,7 +113,7 @@ func TestWatchEtcd(t *testing.T) {
fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{
R: &etcd.Response{
Node: &etcd.Node{
Value: api.EncodeOrDie(&api.ContainerManifestList{}),
Value: runtime.EncodeOrDie(&api.ContainerManifestList{}),
ModifiedIndex: 2,
},
},

View File

@ -24,6 +24,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
@ -69,7 +70,7 @@ func (s *SourceURL) extractFromURL() error {
var manifest api.ContainerManifest
singleErr := yaml.Unmarshal(data, &manifest)
if singleErr == nil {
if errs := api.ValidateManifest(&manifest); len(errs) > 0 {
if errs := validation.ValidateManifest(&manifest); len(errs) > 0 {
singleErr = fmt.Errorf("invalid manifest: %v", errs)
}
}
@ -90,7 +91,7 @@ func (s *SourceURL) extractFromURL() error {
// done at the end. Hence not returning early here.
if multiErr == nil {
for _, manifest := range manifests {
if errs := api.ValidateManifest(&manifest); len(errs) > 0 {
if errs := validation.ValidateManifest(&manifest); len(errs) > 0 {
multiErr = fmt.Errorf("invalid manifest: %v", errs)
break
}

View File

@ -28,6 +28,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@ -600,7 +601,7 @@ func filterHostPortConflicts(pods []Pod) []Pod {
extract := func(p *api.Port) int { return p.HostPort }
for i := range pods {
pod := &pods[i]
if errs := api.AccumulateUniquePorts(pod.Manifest.Containers, ports, extract); len(errs) != 0 {
if errs := validation.AccumulateUniquePorts(pod.Manifest.Containers, ports, extract); len(errs) != 0 {
glog.Warningf("Pod %s has conflicting ports, ignoring: %v", GetPodFullName(pod), errs)
continue
}

View File

@ -17,8 +17,8 @@ limitations under the License.
package kubelet
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
@ -26,7 +26,7 @@ func ValidatePod(pod *Pod) (errors []error) {
if !util.IsDNSSubdomain(pod.Name) {
errors = append(errors, apierrs.NewInvalid("Pod.Name", pod.Name))
}
if errs := api.ValidateManifest(&pod.Manifest); len(errs) != 0 {
if errs := validation.ValidateManifest(&pod.Manifest); len(errs) != 0 {
errors = append(errors, errs...)
}
return errors

View File

@ -20,7 +20,6 @@ import (
"net/http"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
@ -32,6 +31,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
servicecontroller "github.com/GoogleCloudPlatform/kubernetes/pkg/service"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
@ -136,5 +136,5 @@ func (m *Master) API_v1beta1() (map[string]apiserver.RESTStorage, apiserver.Code
for k, v := range m.storage {
storage[k] = v
}
return storage, api.Codec
return storage, runtime.Codec
}

View File

@ -39,6 +39,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd"
@ -132,7 +133,7 @@ func (s ConfigSourceEtcd) GetServices() ([]api.Service, []api.Endpoints, error)
// and create a Service entry for it.
for i, node := range response.Node.Nodes {
var svc api.Service
err = api.DecodeInto([]byte(node.Value), &svc)
err = runtime.DecodeInto([]byte(node.Value), &svc)
if err != nil {
glog.Errorf("Failed to load Service: %s (%#v)", node.Value, err)
continue
@ -165,7 +166,7 @@ func (s ConfigSourceEtcd) GetEndpoints(service string) (api.Endpoints, error) {
}
// Parse all the endpoint specifications in this value.
var e api.Endpoints
err = api.DecodeInto([]byte(response.Node.Value), &e)
err = runtime.DecodeInto([]byte(response.Node.Value), &e)
return e, err
}
@ -175,7 +176,7 @@ func etcdResponseToService(response *etcd.Response) (*api.Service, error) {
return nil, fmt.Errorf("invalid response from etcd: %#v", response)
}
var svc api.Service
err := api.DecodeInto([]byte(response.Node.Value), &svc)
err := runtime.DecodeInto([]byte(response.Node.Value), &svc)
if err != nil {
return nil, err
}
@ -229,7 +230,7 @@ func (s ConfigSourceEtcd) ProcessChange(response *etcd.Response) {
func (s ConfigSourceEtcd) ProcessEndpointResponse(response *etcd.Response) {
glog.Infof("Processing a change in endpoint configuration... %s", *response)
var endpoints api.Endpoints
err := api.DecodeInto([]byte(response.Node.Value), &endpoints)
err := runtime.DecodeInto([]byte(response.Node.Value), &endpoints)
if err != nil {
glog.Errorf("Failed to parse service out of etcd key: %v : %+v", response.Node.Value, err)
return

View File

@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func TestNewBindingStorage(t *testing.T) {
@ -37,12 +38,12 @@ func TestNewBindingStorage(t *testing.T) {
PodID: "foo",
Host: "bar",
}
body, err := api.Encode(binding)
body, err := runtime.Encode(binding)
if err != nil {
t.Fatalf("Unexpected encode error %v", err)
}
obj := b.New()
err = api.DecodeInto(body, obj)
err = runtime.DecodeInto(body, obj)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

View File

@ -21,6 +21,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
@ -59,7 +60,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
}
// Pod Manifest ID should be assigned by the pod API
controller.DesiredState.PodTemplate.DesiredState.Manifest.ID = ""
if errs := api.ValidateReplicationController(controller); len(errs) > 0 {
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("replicationController", controller.ID, errs)
}
@ -118,7 +119,7 @@ func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
if !ok {
return nil, fmt.Errorf("not a replication controller: %#v", obj)
}
if errs := api.ValidateReplicationController(controller); len(errs) > 0 {
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("replicationController", controller.ID, errs)
}
return apiserver.MakeAsync(func() (interface{}, error) {

View File

@ -28,6 +28,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func TestListControllersError(t *testing.T) {
@ -111,13 +112,13 @@ func TestControllerDecode(t *testing.T) {
ID: "foo",
},
}
body, err := api.Encode(controller)
body, err := runtime.Encode(controller)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
controllerOut := storage.New()
if err := api.DecodeInto(body, controllerOut); err != nil {
if err := runtime.DecodeInto(body, controllerOut); err != nil {
t.Errorf("unexpected error: %v", err)
}

View File

@ -23,6 +23,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/constraint"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
@ -44,8 +45,8 @@ func NewRegistry(client tools.EtcdClient) *Registry {
registry := &Registry{
EtcdHelper: tools.EtcdHelper{
client,
api.Codec,
api.ResourceVersioner,
runtime.Codec,
runtime.ResourceVersioner,
},
}
registry.manifestFactory = &BasicManifestFactory{
@ -267,7 +268,7 @@ func (r *Registry) CreateController(controller api.ReplicationController) error
// UpdateController replaces an existing ReplicationController.
func (r *Registry) UpdateController(controller api.ReplicationController) error {
return r.SetObj(makeControllerKey(controller.ID), controller)
return r.SetObj(makeControllerKey(controller.ID), &controller)
}
// DeleteController deletes a ReplicationController specified by its ID.
@ -352,7 +353,7 @@ func (r *Registry) DeleteService(name string) error {
// UpdateService replaces an existing Service.
func (r *Registry) UpdateService(svc api.Service) error {
return r.SetObj(makeServiceKey(svc.ID), svc)
return r.SetObj(makeServiceKey(svc.ID), &svc)
}
// WatchServices begins watching for new, changed, or deleted service configurations.

View File

@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/coreos/go-etcd/etcd"
@ -40,7 +41,7 @@ func NewTestEtcdRegistry(client tools.EtcdClient) *Registry {
func TestEtcdGetPod(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.Set("/registry/pods/foo", api.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
fakeClient.Set("/registry/pods/foo", runtime.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
pod, err := registry.GetPod("foo")
if err != nil {
@ -76,7 +77,7 @@ func TestEtcdCreatePod(t *testing.T) {
},
E: tools.EtcdErrorNotFound,
}
fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{}), 0)
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(&api.ContainerManifestList{}), 0)
registry := NewTestEtcdRegistry(fakeClient)
err := registry.CreatePod(api.Pod{
JSONBase: api.JSONBase{
@ -107,7 +108,7 @@ func TestEtcdCreatePod(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
var pod api.Pod
err = api.DecodeInto([]byte(resp.Node.Value), &pod)
err = runtime.DecodeInto([]byte(resp.Node.Value), &pod)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -121,7 +122,7 @@ func TestEtcdCreatePod(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
err = api.DecodeInto([]byte(resp.Node.Value), &manifests)
err = runtime.DecodeInto([]byte(resp.Node.Value), &manifests)
if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" {
t.Errorf("Unexpected manifest list: %#v", manifests)
}
@ -132,7 +133,7 @@ func TestEtcdCreatePodAlreadyExisting(t *testing.T) {
fakeClient.Data["/registry/pods/foo"] = tools.EtcdResponseWithError{
R: &etcd.Response{
Node: &etcd.Node{
Value: api.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}),
Value: runtime.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}),
},
},
E: nil,
@ -234,7 +235,7 @@ func TestEtcdCreatePodWithContainersNotFound(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
var pod api.Pod
err = api.DecodeInto([]byte(resp.Node.Value), &pod)
err = runtime.DecodeInto([]byte(resp.Node.Value), &pod)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -248,7 +249,7 @@ func TestEtcdCreatePodWithContainersNotFound(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
err = api.DecodeInto([]byte(resp.Node.Value), &manifests)
err = runtime.DecodeInto([]byte(resp.Node.Value), &manifests)
if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" {
t.Errorf("Unexpected manifest list: %#v", manifests)
}
@ -263,7 +264,7 @@ func TestEtcdCreatePodWithExistingContainers(t *testing.T) {
},
E: tools.EtcdErrorNotFound,
}
fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(api.ContainerManifestList{
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(api.ContainerManifestList{
Items: []api.ContainerManifest{
{ID: "bar"},
},
@ -299,7 +300,7 @@ func TestEtcdCreatePodWithExistingContainers(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
var pod api.Pod
err = api.DecodeInto([]byte(resp.Node.Value), &pod)
err = runtime.DecodeInto([]byte(resp.Node.Value), &pod)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -313,7 +314,7 @@ func TestEtcdCreatePodWithExistingContainers(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
err = api.DecodeInto([]byte(resp.Node.Value), &manifests)
err = runtime.DecodeInto([]byte(resp.Node.Value), &manifests)
if len(manifests.Items) != 2 || manifests.Items[1].ID != "foo" {
t.Errorf("Unexpected manifest list: %#v", manifests)
}
@ -324,11 +325,11 @@ func TestEtcdDeletePod(t *testing.T) {
fakeClient.TestIndex = true
key := "/registry/pods/foo"
fakeClient.Set(key, api.EncodeOrDie(api.Pod{
fakeClient.Set(key, runtime.EncodeOrDie(api.Pod{
JSONBase: api.JSONBase{ID: "foo"},
DesiredState: api.PodState{Host: "machine"},
}), 0)
fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(&api.ContainerManifestList{
Items: []api.ContainerManifest{
{ID: "foo"},
},
@ -349,7 +350,7 @@ func TestEtcdDeletePod(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
var manifests api.ContainerManifestList
api.DecodeInto([]byte(response.Node.Value), &manifests)
runtime.DecodeInto([]byte(response.Node.Value), &manifests)
if len(manifests.Items) != 0 {
t.Errorf("Unexpected container set: %s, expected empty", response.Node.Value)
}
@ -360,11 +361,11 @@ func TestEtcdDeletePodMultipleContainers(t *testing.T) {
fakeClient.TestIndex = true
key := "/registry/pods/foo"
fakeClient.Set(key, api.EncodeOrDie(api.Pod{
fakeClient.Set(key, runtime.EncodeOrDie(api.Pod{
JSONBase: api.JSONBase{ID: "foo"},
DesiredState: api.PodState{Host: "machine"},
}), 0)
fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{
fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(&api.ContainerManifestList{
Items: []api.ContainerManifest{
{ID: "foo"},
{ID: "bar"},
@ -387,7 +388,7 @@ func TestEtcdDeletePodMultipleContainers(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
var manifests api.ContainerManifestList
api.DecodeInto([]byte(response.Node.Value), &manifests)
runtime.DecodeInto([]byte(response.Node.Value), &manifests)
if len(manifests.Items) != 1 {
t.Fatalf("Unexpected manifest set: %#v, expected empty", manifests)
}
@ -444,13 +445,13 @@ func TestEtcdListPods(t *testing.T) {
Node: &etcd.Node{
Nodes: []*etcd.Node{
{
Value: api.EncodeOrDie(api.Pod{
Value: runtime.EncodeOrDie(api.Pod{
JSONBase: api.JSONBase{ID: "foo"},
DesiredState: api.PodState{Host: "machine"},
}),
},
{
Value: api.EncodeOrDie(api.Pod{
Value: runtime.EncodeOrDie(api.Pod{
JSONBase: api.JSONBase{ID: "bar"},
DesiredState: api.PodState{Host: "machine"},
}),
@ -519,10 +520,10 @@ func TestEtcdListControllers(t *testing.T) {
Node: &etcd.Node{
Nodes: []*etcd.Node{
{
Value: api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}),
Value: runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}),
},
{
Value: api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "bar"}}),
Value: runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "bar"}}),
},
},
},
@ -542,7 +543,7 @@ func TestEtcdListControllers(t *testing.T) {
func TestEtcdGetController(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.Set("/registry/controllers/foo", api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
ctrl, err := registry.GetController("foo")
if err != nil {
@ -606,7 +607,7 @@ func TestEtcdCreateController(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
var ctrl api.ReplicationController
err = api.DecodeInto([]byte(resp.Node.Value), &ctrl)
err = runtime.DecodeInto([]byte(resp.Node.Value), &ctrl)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -618,7 +619,7 @@ func TestEtcdCreateController(t *testing.T) {
func TestEtcdCreateControllerAlreadyExisting(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.Set("/registry/controllers/foo", api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
err := registry.CreateController(api.ReplicationController{
@ -635,7 +636,7 @@ func TestEtcdUpdateController(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.TestIndex = true
resp, _ := fakeClient.Set("/registry/controllers/foo", api.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
resp, _ := fakeClient.Set("/registry/controllers/foo", runtime.EncodeOrDie(api.ReplicationController{JSONBase: api.JSONBase{ID: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
err := registry.UpdateController(api.ReplicationController{
JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex},
@ -661,10 +662,10 @@ func TestEtcdListServices(t *testing.T) {
Node: &etcd.Node{
Nodes: []*etcd.Node{
{
Value: api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}),
Value: runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}),
},
{
Value: api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "bar"}}),
Value: runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "bar"}}),
},
},
},
@ -698,7 +699,7 @@ func TestEtcdCreateService(t *testing.T) {
}
var service api.Service
err = api.DecodeInto([]byte(resp.Node.Value), &service)
err = runtime.DecodeInto([]byte(resp.Node.Value), &service)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -710,7 +711,7 @@ func TestEtcdCreateService(t *testing.T) {
func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.Set("/registry/services/specs/foo", api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
err := registry.CreateService(api.Service{
JSONBase: api.JSONBase{ID: "foo"},
@ -722,7 +723,7 @@ func TestEtcdCreateServiceAlreadyExisting(t *testing.T) {
func TestEtcdGetService(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.Set("/registry/services/specs/foo", api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
service, err := registry.GetService("foo")
if err != nil {
@ -774,7 +775,7 @@ func TestEtcdUpdateService(t *testing.T) {
fakeClient := tools.NewFakeEtcdClient(t)
fakeClient.TestIndex = true
resp, _ := fakeClient.Set("/registry/services/specs/foo", api.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
resp, _ := fakeClient.Set("/registry/services/specs/foo", runtime.EncodeOrDie(api.Service{JSONBase: api.JSONBase{ID: "foo"}}), 0)
registry := NewTestEtcdRegistry(fakeClient)
testService := api.Service{
JSONBase: api.JSONBase{ID: "foo", ResourceVersion: resp.Node.ModifiedIndex},
@ -811,7 +812,7 @@ func TestEtcdGetEndpoints(t *testing.T) {
Endpoints: []string{"127.0.0.1:34855"},
}
fakeClient.Set("/registry/services/endpoints/foo", api.EncodeOrDie(endpoints), 0)
fakeClient.Set("/registry/services/endpoints/foo", runtime.EncodeOrDie(endpoints), 0)
got, err := registry.GetEndpoints("foo")
if err != nil {
@ -832,7 +833,7 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
Endpoints: []string{"baz", "bar"},
}
fakeClient.Set("/registry/services/endpoints/foo", api.EncodeOrDie(api.Endpoints{}), 0)
fakeClient.Set("/registry/services/endpoints/foo", runtime.EncodeOrDie(api.Endpoints{}), 0)
err := registry.UpdateEndpoints(endpoints)
if err != nil {
@ -844,7 +845,7 @@ func TestEtcdUpdateEndpoints(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
var endpointsOut api.Endpoints
err = api.DecodeInto([]byte(response.Node.Value), &endpointsOut)
err = runtime.DecodeInto([]byte(response.Node.Value), &endpointsOut)
if !reflect.DeepEqual(endpoints, endpointsOut) {
t.Errorf("Unexpected endpoints: %#v, expected %#v", endpointsOut, endpoints)
}

View File

@ -20,7 +20,7 @@ import (
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
fake_cloud "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
)
func TestCloudList(t *testing.T) {

View File

@ -23,6 +23,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
@ -68,7 +69,7 @@ func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
pod.ID = uuid.NewUUID().String()
}
pod.DesiredState.Manifest.ID = pod.ID
if errs := api.ValidatePod(pod); len(errs) > 0 {
if errs := validation.ValidatePod(pod); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("pod", pod.ID, errs)
}
@ -135,7 +136,7 @@ func (rs RegistryStorage) New() interface{} {
func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
pod := obj.(*api.Pod)
if errs := api.ValidatePod(pod); len(errs) > 0 {
if errs := validation.ValidatePod(pod); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("pod", pod.ID, errs)
}
return apiserver.MakeAsync(func() (interface{}, error) {

View File

@ -27,6 +27,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/fake"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/fsouza/go-dockerclient"
)
@ -177,13 +178,13 @@ func TestPodDecode(t *testing.T) {
ID: "foo",
},
}
body, err := api.Encode(expected)
body, err := runtime.Encode(expected)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
actual := storage.New()
if err := api.DecodeInto(body, actual); err != nil {
if err := runtime.DecodeInto(body, actual); err != nil {
t.Errorf("unexpected error: %v", err)
}

View File

@ -23,6 +23,7 @@ import (
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
@ -49,7 +50,7 @@ func NewRegistryStorage(registry Registry, cloud cloudprovider.Interface, machin
func (rs *RegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
srv := obj.(*api.Service)
if errs := api.ValidateService(srv); len(errs) > 0 {
if errs := validation.ValidateService(srv); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("service", srv.ID, errs)
}
@ -155,7 +156,7 @@ func GetServiceEnvironmentVariables(registry Registry, machine string) ([]api.En
func (rs *RegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
srv := obj.(*api.Service)
if errs := api.ValidateService(srv); len(errs) > 0 {
if errs := validation.ValidateService(srv); len(errs) > 0 {
return nil, apiserver.NewInvalidErr("service", srv.ID, errs)
}
return apiserver.MakeAsync(func() (interface{}, error) {

44
pkg/runtime/doc.go Normal file
View File

@ -0,0 +1,44 @@
/*
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 runtime includes helper functions for working with API objects
// that follow the kubernetes API object conventions, which are:
//
// 0. Your API objects have a common metadata struct member, JSONBase.
// 1. Your code refers to an internal set of API objects.
// 2. In a separate package, you have an external set of API objects.
// 3. 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).
// 4. As your api evolves, you'll make an additional versioned package
// with every major change.
// 5. Versioned packages have conversion functions which convert to
// and from the internal version.
// 6. 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.
// 7. 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.
package runtime

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package api
package runtime
import (
"fmt"
@ -39,34 +39,14 @@ type resourceVersioner interface {
ResourceVersion(obj interface{}) (uint64, error)
}
var Codec codec
var ResourceVersioner resourceVersioner
var ResourceVersioner resourceVersioner = NewJSONBaseResourceVersioner()
var conversionScheme = conversion.NewScheme()
var Codec codec = conversionScheme
func init() {
conversionScheme.InternalVersion = ""
conversionScheme.ExternalVersion = "v1beta1"
conversionScheme.MetaInsertionFactory = metaInsertion{}
AddKnownTypes("",
PodList{},
Pod{},
ReplicationControllerList{},
ReplicationController{},
ServiceList{},
Service{},
MinionList{},
Minion{},
Status{},
ServerOpList{},
ServerOp{},
ContainerManifestList{},
Endpoints{},
Binding{},
)
Codec = conversionScheme
ResourceVersioner = NewJSONBaseResourceVersioner()
}
// AddKnownTypes registers the types of the arguments to the marshaller of the package api.
@ -127,23 +107,6 @@ func FindJSONBase(obj interface{}) (JSONBaseInterface, error) {
return g, nil
}
// FindJSONBaseRO takes an arbitary api type, return a copy of its JSONBase field.
// obj may be a pointer to an api type, or a non-pointer struct api type.
func FindJSONBaseRO(obj interface{}) (JSONBase, error) {
v := reflect.ValueOf(obj)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return JSONBase{}, fmt.Errorf("expected struct, but got %v (%#v)", v.Type().Name(), v.Interface())
}
jsonBase := v.FieldByName("JSONBase")
if !jsonBase.IsValid() {
return JSONBase{}, fmt.Errorf("struct %v lacks embedded JSON type", v.Type().Name())
}
return jsonBase.Interface().(JSONBase), nil
}
// 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)

View File

@ -0,0 +1,77 @@
/*
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 runtime_test
import (
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"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) {
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 TestBadJSONRejection(t *testing.T) {
badJSONMissingKind := []byte(`{ }`)
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 := runtime.Decode(badJSONUnknownType); err1 == nil {
t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType)
}
/*badJSONKindMismatch := []byte(`{"kind": "Pod"}`)
if err2 := DecodeInto(badJSONKindMismatch, &Minion{}); err2 == nil {
t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch)
}*/
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package api
package runtime
import (
"fmt"
@ -30,11 +30,11 @@ func NewJSONBaseResourceVersioner() resourceVersioner {
type jsonBaseResourceVersioner struct{}
func (v jsonBaseResourceVersioner) ResourceVersion(obj interface{}) (uint64, error) {
json, err := FindJSONBaseRO(obj)
json, err := FindJSONBase(obj)
if err != nil {
return 0, err
}
return json.ResourceVersion, nil
return json.ResourceVersion(), nil
}
func (v jsonBaseResourceVersioner) SetResourceVersion(obj interface{}, version uint64) error {

View File

@ -14,14 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package api
package runtime
import (
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
func TestGenericJSONBase(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"`
}
j := JSONBase{
ID: "foo",
APIVersion: "a",
@ -68,13 +78,25 @@ func TestGenericJSONBase(t *testing.T) {
}
func TestResourceVersionerOfAPI(t *testing.T) {
testCases := map[string]struct {
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{}
Expected uint64
}{
"empty api object": {Service{}, 0},
"api object with version": {Service{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
"pointer to api object with version": {&Service{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
}
testCases := map[string]T{
"empty api object": {&MyAPIObject{}, 0},
"api object with version": {&MyAPIObject{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
"pointer to api object with version": {&MyAPIObject{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
}
versioning := NewJSONBaseResourceVersioner()
for key, testCase := range testCases {
@ -104,7 +126,7 @@ func TestResourceVersionerOfAPI(t *testing.T) {
Object interface{}
Expected uint64
}{
"pointer to api object with version": {&Service{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
"pointer to api object with version": {&MyAPIObject{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
}
for key, testCase := range setCases {
if err := versioning.SetResourceVersion(testCase.Object, 5); err != nil {
@ -123,8 +145,8 @@ func TestResourceVersionerOfAPI(t *testing.T) {
Object interface{}
Expected uint64
}{
"empty api object": {Service{}, 0},
"api object with version": {Service{JSONBase: JSONBase{ResourceVersion: 1}}, 1},
"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 {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package api
package runtime
import (
"gopkg.in/v1/yaml"
@ -26,7 +26,7 @@ import (
// embedded within other API types.
// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *APIObject) UnmarshalJSON(b []byte) error {
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
@ -42,7 +42,7 @@ func (a *APIObject) UnmarshalJSON(b []byte) error {
}
// MarshalJSON implements the json.Marshaler interface.
func (a APIObject) MarshalJSON() ([]byte, error) {
func (a Object) MarshalJSON() ([]byte, error) {
if a.Object == nil {
// Encode unset/nil objects as JSON's "null".
return []byte("null"), nil
@ -52,7 +52,7 @@ func (a APIObject) MarshalJSON() ([]byte, error) {
}
// SetYAML implements the yaml.Setter interface.
func (a *APIObject) SetYAML(tag string, value interface{}) bool {
func (a *Object) SetYAML(tag string, value interface{}) bool {
if value == nil {
a.Object = nil
return true
@ -76,7 +76,7 @@ func (a *APIObject) SetYAML(tag string, value interface{}) bool {
}
// GetYAML implements the yaml.Getter interface.
func (a APIObject) GetYAML() (tag string, value interface{}) {
func (a Object) GetYAML() (tag string, value interface{}) {
if a.Object == nil {
value = "null"
return

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package api
package runtime
import (
"encoding/json"
@ -22,18 +22,18 @@ import (
"testing"
)
func TestAPIObject(t *testing.T) {
func TestObject(t *testing.T) {
type EmbeddedTest struct {
JSONBase `yaml:",inline" json:",inline"`
Object APIObject `yaml:"object,omitempty" json:"object,omitempty"`
EmptyObject APIObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
Object Object `yaml:"object,omitempty" json:"object,omitempty"`
EmptyObject Object `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"`
}
AddKnownTypes("", EmbeddedTest{})
AddKnownTypes("v1beta1", EmbeddedTest{})
outer := &EmbeddedTest{
JSONBase: JSONBase{ID: "outer"},
Object: APIObject{
Object: Object{
&EmbeddedTest{
JSONBase: JSONBase{ID: "inner"},
},
@ -56,7 +56,7 @@ func TestAPIObject(t *testing.T) {
t.Errorf("Expected: %#v but got %#v", e, a)
}
// test JSON decoding, too, since api.Decode uses yaml unmarshalling.
// test JSON decoding, too, since Decode uses yaml unmarshalling.
var decodedViaJSON EmbeddedTest
err = json.Unmarshal(wire, &decodedViaJSON)
if err != nil {

64
pkg/runtime/types.go Normal file
View File

@ -0,0 +1,64 @@
/*
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 runtime
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
// 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.
// 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
// }
//
// 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

@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
@ -35,7 +36,7 @@ func TestDecoder(t *testing.T) {
expect := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
go func() {
err := encoder.Encode(api.WatchEvent{watch.Added, api.APIObject{expect}})
err := encoder.Encode(api.WatchEvent{watch.Added, runtime.Object{expect}})
if err != nil {
t.Errorf("Unexpected error %v", err)
}

View File

@ -25,6 +25,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd"
)
@ -40,8 +41,8 @@ type TestResource struct {
}
var scheme *conversion.Scheme
var codec = api.Codec
var versioner = api.ResourceVersioner
var codec = runtime.Codec
var versioner = runtime.ResourceVersioner
func init() {
scheme = conversion.NewScheme()
@ -184,13 +185,13 @@ func TestSetObj(t *testing.T) {
}
func TestSetObjWithVersion(t *testing.T) {
obj := api.Pod{JSONBase: api.JSONBase{ID: "foo", ResourceVersion: 1}}
obj := &api.Pod{JSONBase: api.JSONBase{ID: "foo", ResourceVersion: 1}}
fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true
fakeClient.Data["/some/key"] = EtcdResponseWithError{
R: &etcd.Response{
Node: &etcd.Node{
Value: api.EncodeOrDie(obj),
Value: runtime.EncodeOrDie(obj),
ModifiedIndex: 1,
},
},
@ -235,7 +236,7 @@ func TestAtomicUpdate(t *testing.T) {
fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true
codec := scheme
helper := EtcdHelper{fakeClient, codec, api.NewJSONBaseResourceVersioner()}
helper := EtcdHelper{fakeClient, codec, runtime.NewJSONBaseResourceVersioner()}
// Create a new node.
fakeClient.ExpectNotFoundGet("/some/key")
@ -289,7 +290,7 @@ func TestAtomicUpdate(t *testing.T) {
func TestAtomicUpdateNoChange(t *testing.T) {
fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true
helper := EtcdHelper{fakeClient, scheme, api.NewJSONBaseResourceVersioner()}
helper := EtcdHelper{fakeClient, scheme, runtime.NewJSONBaseResourceVersioner()}
// Create a new node.
fakeClient.ExpectNotFoundGet("/some/key")
@ -321,7 +322,7 @@ func TestAtomicUpdate_CreateCollision(t *testing.T) {
fakeClient := NewFakeEtcdClient(t)
fakeClient.TestIndex = true
codec := scheme
helper := EtcdHelper{fakeClient, codec, api.NewJSONBaseResourceVersioner()}
helper := EtcdHelper{fakeClient, codec, runtime.NewJSONBaseResourceVersioner()}
fakeClient.ExpectNotFoundGet("/some/key")

View File

@ -23,6 +23,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/coreos/go-etcd/etcd"
)
@ -47,62 +48,62 @@ func TestWatchInterpretations(t *testing.T) {
}{
"create": {
actions: []string{"create", "get"},
nodeValue: api.EncodeOrDie(podBar),
nodeValue: runtime.EncodeOrDie(podBar),
expectEmit: true,
expectType: watch.Added,
expectObject: podBar,
},
"create but filter blocks": {
actions: []string{"create", "get"},
nodeValue: api.EncodeOrDie(podFoo),
nodeValue: runtime.EncodeOrDie(podFoo),
expectEmit: false,
},
"delete": {
actions: []string{"delete"},
prevNodeValue: api.EncodeOrDie(podBar),
prevNodeValue: runtime.EncodeOrDie(podBar),
expectEmit: true,
expectType: watch.Deleted,
expectObject: podBar,
},
"delete but filter blocks": {
actions: []string{"delete"},
nodeValue: api.EncodeOrDie(podFoo),
nodeValue: runtime.EncodeOrDie(podFoo),
expectEmit: false,
},
"modify appears to create 1": {
actions: []string{"set", "compareAndSwap"},
nodeValue: api.EncodeOrDie(podBar),
nodeValue: runtime.EncodeOrDie(podBar),
expectEmit: true,
expectType: watch.Added,
expectObject: podBar,
},
"modify appears to create 2": {
actions: []string{"set", "compareAndSwap"},
prevNodeValue: api.EncodeOrDie(podFoo),
nodeValue: api.EncodeOrDie(podBar),
prevNodeValue: runtime.EncodeOrDie(podFoo),
nodeValue: runtime.EncodeOrDie(podBar),
expectEmit: true,
expectType: watch.Added,
expectObject: podBar,
},
"modify appears to delete": {
actions: []string{"set", "compareAndSwap"},
prevNodeValue: api.EncodeOrDie(podBar),
nodeValue: api.EncodeOrDie(podFoo),
prevNodeValue: runtime.EncodeOrDie(podBar),
nodeValue: runtime.EncodeOrDie(podFoo),
expectEmit: true,
expectType: watch.Deleted,
expectObject: podBar, // Should return last state that passed the filter!
},
"modify modifies": {
actions: []string{"set", "compareAndSwap"},
prevNodeValue: api.EncodeOrDie(podBar),
nodeValue: api.EncodeOrDie(podBaz),
prevNodeValue: runtime.EncodeOrDie(podBar),
nodeValue: runtime.EncodeOrDie(podBaz),
expectEmit: true,
expectType: watch.Modified,
expectObject: podBaz,
},
"modify ignores": {
actions: []string{"set", "compareAndSwap"},
nodeValue: api.EncodeOrDie(podFoo),
nodeValue: runtime.EncodeOrDie(podFoo),
expectEmit: false,
},
}
@ -258,7 +259,7 @@ func TestWatchEtcdState(t *testing.T) {
{
Action: "create",
Node: &etcd.Node{
Value: string(api.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
},
},
},
@ -272,12 +273,12 @@ func TestWatchEtcdState(t *testing.T) {
{
Action: "compareAndSwap",
Node: &etcd.Node{
Value: string(api.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
CreatedIndex: 1,
ModifiedIndex: 2,
},
PrevNode: &etcd.Node{
Value: string(api.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
CreatedIndex: 1,
ModifiedIndex: 1,
},
@ -294,7 +295,7 @@ func TestWatchEtcdState(t *testing.T) {
R: &etcd.Response{
Action: "get",
Node: &etcd.Node{
Value: string(api.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
CreatedIndex: 1,
ModifiedIndex: 1,
},
@ -307,12 +308,12 @@ func TestWatchEtcdState(t *testing.T) {
{
Action: "compareAndSwap",
Node: &etcd.Node{
Value: string(api.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"127.0.0.1:9000"}})),
CreatedIndex: 1,
ModifiedIndex: 2,
},
PrevNode: &etcd.Node{
Value: string(api.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
Value: string(runtime.EncodeOrDie(&api.Endpoints{JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{}})),
CreatedIndex: 1,
ModifiedIndex: 1,
},
@ -369,7 +370,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
EtcdResponseWithError{
R: &etcd.Response{
Node: &etcd.Node{
Value: api.EncodeOrDie(pod),
Value: runtime.EncodeOrDie(pod),
CreatedIndex: 1,
ModifiedIndex: 1,
},
@ -384,7 +385,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
EtcdResponseWithError{
R: &etcd.Response{
Node: &etcd.Node{
Value: api.EncodeOrDie(pod),
Value: runtime.EncodeOrDie(pod),
CreatedIndex: 1,
ModifiedIndex: 2,
},
@ -442,13 +443,13 @@ func TestWatchListFromZeroIndex(t *testing.T) {
Dir: true,
Nodes: etcd.Nodes{
&etcd.Node{
Value: api.EncodeOrDie(pod),
Value: runtime.EncodeOrDie(pod),
CreatedIndex: 1,
ModifiedIndex: 1,
Nodes: etcd.Nodes{},
},
&etcd.Node{
Value: api.EncodeOrDie(pod),
Value: runtime.EncodeOrDie(pod),
CreatedIndex: 2,
ModifiedIndex: 2,
Nodes: etcd.Nodes{},

View File

@ -27,6 +27,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
@ -112,7 +113,7 @@ func TestPollMinions(t *testing.T) {
ml := &api.MinionList{Items: item.minions}
handler := util.FakeHandler{
StatusCode: 200,
ResponseBody: api.EncodeOrDie(ml),
ResponseBody: runtime.EncodeOrDie(ml),
T: t,
}
mux := http.NewServeMux()
@ -139,7 +140,7 @@ func TestDefaultErrorFunc(t *testing.T) {
testPod := &api.Pod{JSONBase: api.JSONBase{ID: "foo"}}
handler := util.FakeHandler{
StatusCode: 200,
ResponseBody: api.EncodeOrDie(testPod),
ResponseBody: runtime.EncodeOrDie(testPod),
T: t,
}
mux := http.NewServeMux()
@ -258,7 +259,7 @@ func TestBind(t *testing.T) {
t.Errorf("Unexpected error: %v", err)
continue
}
expectedBody := api.EncodeOrDie(item.binding)
expectedBody := runtime.EncodeOrDie(item.binding)
handler.ValidateRequest(t, "/api/v1beta1/bindings", "POST", &expectedBody)
}
}

View File

@ -22,6 +22,7 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
@ -83,9 +84,9 @@ func TestExtractObj(t *testing.T) {
func TestWatch(t *testing.T) {
client := newEtcdClient()
helper := tools.EtcdHelper{Client: client, Codec: api.Codec, ResourceVersioner: api.ResourceVersioner}
helper := tools.EtcdHelper{Client: client, Codec: runtime.Codec, ResourceVersioner: runtime.ResourceVersioner}
withEtcdKey(func(key string) {
resp, err := client.Set(key, api.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
resp, err := client.Set(key, runtime.EncodeOrDie(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}