Merge pull request #20814 from deads2k/restmapper-errors

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-02-13 15:53:22 -08:00
commit 53d9f9ecab
8 changed files with 526 additions and 111 deletions

View File

@ -281,6 +281,27 @@ runTests() {
fi
stop-proxy
#########################
# RESTMapper evaluation #
#########################
kube::log::status "Testing RESTMapper"
RESTMAPPER_ERROR_FILE="${KUBE_TEMP}/restmapper-error"
### Non-existent resource type should give a recognizeable error
# Pre-condition: None
# Command
kubectl get "${kube_flags[@]}" unknownresourcetype 2>${RESTMAPPER_ERROR_FILE} || true
if grep -q "the server doesn't have a resource type" "${RESTMAPPER_ERROR_FILE}"; then
kube::log::status "\"kubectl get unknownresourcetype\" returns error as expected: $(cat ${RESTMAPPER_ERROR_FILE})"
else
kube::log::status "\"kubectl get unknownresourcetype\" returns unexpected error or non-error: $(cat ${RESTMAPPER_ERROR_FILE})"
exit 1
fi
rm "${RESTMAPPER_ERROR_FILE}"
# Post-condition: None
###########################
# POD creation / deletion #
###########################

72
pkg/api/meta/errors.go Normal file
View File

@ -0,0 +1,72 @@
/*
Copyright 2014 The Kubernetes Authors 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 meta
import (
"fmt"
"k8s.io/kubernetes/pkg/api/unversioned"
)
// AmbiguousResourceError is returned if the RESTMapper finds multiple matches for a resource
type AmbiguousResourceError struct {
PartialResource unversioned.GroupVersionResource
MatchingResources []unversioned.GroupVersionResource
MatchingKinds []unversioned.GroupVersionKind
}
func (e *AmbiguousResourceError) Error() string {
switch {
case len(e.MatchingKinds) > 0 && len(e.MatchingResources) > 0:
return fmt.Sprintf("%v matches multiple resources %v and kinds %v", e.PartialResource, e.MatchingResources, e.MatchingKinds)
case len(e.MatchingKinds) > 0:
return fmt.Sprintf("%v matches multiple kinds %v", e.PartialResource, e.MatchingKinds)
case len(e.MatchingResources) > 0:
return fmt.Sprintf("%v matches multiple resources %v", e.PartialResource, e.MatchingResources)
}
return fmt.Sprintf("%v matches multiple resources or kinds", e.PartialResource)
}
func IsAmbiguousResourceError(err error) bool {
if err == nil {
return false
}
_, ok := err.(*AmbiguousResourceError)
return ok
}
// NoResourceMatchError is returned if the RESTMapper can't find any match for a resource
type NoResourceMatchError struct {
PartialResource unversioned.GroupVersionResource
}
func (e *NoResourceMatchError) Error() string {
return fmt.Sprintf("no matches for %v", e.PartialResource)
}
func IsNoResourceMatchError(err error) bool {
if err == nil {
return false
}
_, ok := err.(*NoResourceMatchError)
return ok
}

View File

@ -0,0 +1,131 @@
/*
Copyright 2014 The Kubernetes Authors 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 meta
import (
"fmt"
"strings"
"k8s.io/kubernetes/pkg/api/unversioned"
)
// MultiRESTMapper is a wrapper for multiple RESTMappers.
type MultiRESTMapper []RESTMapper
func (m MultiRESTMapper) String() string {
nested := []string{}
for _, t := range m {
currString := fmt.Sprintf("%v", t)
splitStrings := strings.Split(currString, "\n")
nested = append(nested, strings.Join(splitStrings, "\n\t"))
}
return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t"))
}
// ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod)
// This implementation supports multiple REST schemas and return the first match.
func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
for _, t := range m {
singular, err = t.ResourceSingularizer(resource)
if err == nil {
return
}
}
return
}
func (m MultiRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
for _, t := range m {
gvrs, err := t.ResourcesFor(resource)
// ignore "no match" errors, but any other error percolates back up
if !IsNoResourceMatchError(err) {
return gvrs, err
}
}
return nil, &NoResourceMatchError{PartialResource: resource}
}
// KindsFor provides the Kind mappings for the REST resources. This implementation supports multiple REST schemas and returns
// the first match.
func (m MultiRESTMapper) KindsFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
for _, t := range m {
gvks, err := t.KindsFor(resource)
// ignore "no match" errors, but any other error percolates back up
if !IsNoResourceMatchError(err) {
return gvks, err
}
}
return nil, &NoResourceMatchError{PartialResource: resource}
}
func (m MultiRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
for _, t := range m {
gvr, err := t.ResourceFor(resource)
// ignore "no match" errors, but any other error percolates back up
if !IsNoResourceMatchError(err) {
return gvr, err
}
}
return unversioned.GroupVersionResource{}, &NoResourceMatchError{PartialResource: resource}
}
// KindsFor provides the Kind mapping for the REST resources. This implementation supports multiple REST schemas and returns
// the first match.
func (m MultiRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
for _, t := range m {
gvk, err := t.KindFor(resource)
// ignore "no match" errors, but any other error percolates back up
if !IsNoResourceMatchError(err) {
return gvk, err
}
}
return unversioned.GroupVersionKind{}, &NoResourceMatchError{PartialResource: resource}
}
// RESTMapping provides the REST mapping for the resource based on the
// kind and version. This implementation supports multiple REST schemas and
// return the first match.
func (m MultiRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (mapping *RESTMapping, err error) {
for _, t := range m {
mapping, err = t.RESTMapping(gk, versions...)
if err == nil {
return
}
}
return
}
// AliasesForResource finds the first alias response for the provided mappers.
func (m MultiRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) {
for _, t := range m {
if aliases, ok = t.AliasesForResource(alias); ok {
return
}
}
return nil, false
}
// ResourceIsValid takes a string (either group/kind or kind) and checks if it's a valid resource
func (m MultiRESTMapper) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
for _, t := range m {
if t.ResourceIsValid(resource) {
return true
}
}
return false
}

View File

@ -0,0 +1,238 @@
/*
Copyright 2014 The Kubernetes Authors 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 meta
import (
"errors"
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api/unversioned"
)
func TestMultiRESTMapperResourceForErrorHandling(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input unversioned.GroupVersionResource
result unversioned.GroupVersionResource
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: unversioned.GroupVersionResource{},
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: unversioned.GroupVersionResource{},
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{resourceFor: unversioned.GroupVersionResource{Resource: "unused"}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: unversioned.GroupVersionResource{},
err: errors.New("fail on this"),
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.ResourceFor(tc.input)
if e, a := tc.result, actualResult; e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
if e, a := tc.err.Error(), actualErr.Error(); e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
}
}
func TestMultiRESTMapperResourcesForErrorHandling(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input unversioned.GroupVersionResource
result []unversioned.GroupVersionResource
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "unused"}}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: nil,
err: errors.New("fail on this"),
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.ResourcesFor(tc.input)
if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
if e, a := tc.err.Error(), actualErr.Error(); e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
}
}
func TestMultiRESTMapperKindsForErrorHandling(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input unversioned.GroupVersionResource
result []unversioned.GroupVersionKind
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: nil,
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "unused"}}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: nil,
err: errors.New("fail on this"),
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.KindsFor(tc.input)
if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
if e, a := tc.err.Error(), actualErr.Error(); e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
}
}
func TestMultiRESTMapperKindForErrorHandling(t *testing.T) {
tcs := []struct {
name string
mapper MultiRESTMapper
input unversioned.GroupVersionResource
result unversioned.GroupVersionKind
err error
}{
{
name: "empty",
mapper: MultiRESTMapper{},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: unversioned.GroupVersionKind{},
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "ignore not found",
mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: unversioned.GroupVersionKind{},
err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
},
{
name: "accept first failure",
mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{kindFor: unversioned.GroupVersionKind{Kind: "unused"}}},
input: unversioned.GroupVersionResource{Resource: "foo"},
result: unversioned.GroupVersionKind{},
err: errors.New("fail on this"),
},
}
for _, tc := range tcs {
actualResult, actualErr := tc.mapper.KindFor(tc.input)
if e, a := tc.result, actualResult; e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
if e, a := tc.err.Error(), actualErr.Error(); e != a {
t.Errorf("%s: expected %v, got %v", tc.name, e, a)
}
}
}
type fixedRESTMapper struct {
resourcesFor []unversioned.GroupVersionResource
kindsFor []unversioned.GroupVersionKind
resourceFor unversioned.GroupVersionResource
kindFor unversioned.GroupVersionKind
err error
}
func (m fixedRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
return "", m.err
}
func (m fixedRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
return m.resourcesFor, m.err
}
func (m fixedRESTMapper) KindsFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
return m.kindsFor, m.err
}
func (m fixedRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
return m.resourceFor, m.err
}
func (m fixedRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
return m.kindFor, m.err
}
func (m fixedRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (mapping *RESTMapping, err error) {
return nil, m.err
}
func (m fixedRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) {
return nil, false
}
func (m fixedRESTMapper) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
return false
}

View File

@ -243,7 +243,7 @@ func (m *DefaultRESTMapper) ResourcesFor(resource unversioned.GroupVersionResour
}
if len(ret) == 0 {
return nil, fmt.Errorf("no resource %v has been defined; known resources: %v", resource, m.pluralToSingular)
return nil, &NoResourceMatchError{PartialResource: resource}
}
sort.Sort(resourceByPreferredGroupVersion{ret, m.defaultGroupVersions})
@ -259,7 +259,7 @@ func (m *DefaultRESTMapper) ResourceFor(resource unversioned.GroupVersionResourc
return resources[0], nil
}
return unversioned.GroupVersionResource{}, fmt.Errorf("%v is ambiguous, got: %v", resource, resources)
return unversioned.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources}
}
func (m *DefaultRESTMapper) KindsFor(input unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error) {
@ -309,7 +309,7 @@ func (m *DefaultRESTMapper) KindsFor(input unversioned.GroupVersionResource) ([]
}
if len(ret) == 0 {
return nil, fmt.Errorf("no kind %v has been defined; known resources: %v", resource, m.pluralToSingular)
return nil, &NoResourceMatchError{PartialResource: input}
}
sort.Sort(kindByPreferredGroupVersion{ret, m.defaultGroupVersions})
@ -340,7 +340,7 @@ func (m *DefaultRESTMapper) KindFor(resource unversioned.GroupVersionResource) (
return oneKindPerGroup[0], nil
}
return unversioned.GroupVersionKind{}, fmt.Errorf("%v is ambiguous, got: %v", resource, kinds)
return unversioned.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds}
}
type kindByPreferredGroupVersion struct {
@ -519,106 +519,3 @@ func (m *DefaultRESTMapper) ResourceIsValid(resource unversioned.GroupVersionRes
_, err := m.KindFor(resource)
return err == nil
}
// MultiRESTMapper is a wrapper for multiple RESTMappers.
type MultiRESTMapper []RESTMapper
func (m MultiRESTMapper) String() string {
nested := []string{}
for _, t := range m {
currString := fmt.Sprintf("%v", t)
splitStrings := strings.Split(currString, "\n")
nested = append(nested, strings.Join(splitStrings, "\n\t"))
}
return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t"))
}
// ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod)
// This implementation supports multiple REST schemas and return the first match.
func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
for _, t := range m {
singular, err = t.ResourceSingularizer(resource)
if err == nil {
return
}
}
return
}
func (m MultiRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionResource, err error) {
for _, t := range m {
gvk, err = t.ResourcesFor(resource)
if err == nil {
return
}
}
return
}
// KindsFor provides the Kind mappings for the REST resources. This implementation supports multiple REST schemas and returns
// the first match.
func (m MultiRESTMapper) KindsFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
for _, t := range m {
gvk, err = t.KindsFor(resource)
if err == nil {
return
}
}
return
}
func (m MultiRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (gvk unversioned.GroupVersionResource, err error) {
for _, t := range m {
gvk, err = t.ResourceFor(resource)
if err == nil {
return
}
}
return
}
// KindsFor provides the Kind mapping for the REST resources. This implementation supports multiple REST schemas and returns
// the first match.
func (m MultiRESTMapper) KindFor(resource unversioned.GroupVersionResource) (gvk unversioned.GroupVersionKind, err error) {
for _, t := range m {
gvk, err = t.KindFor(resource)
if err == nil {
return
}
}
return
}
// RESTMapping provides the REST mapping for the resource based on the
// kind and version. This implementation supports multiple REST schemas and
// return the first match.
func (m MultiRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (mapping *RESTMapping, err error) {
for _, t := range m {
mapping, err = t.RESTMapping(gk, versions...)
if err == nil {
return
}
}
return
}
// AliasesForResource finds the first alias response for the provided mappers.
func (m MultiRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) {
for _, t := range m {
if aliases, ok = t.AliasesForResource(alias); ok {
return
}
}
return nil, false
}
// ResourceIsValid takes a string (either group/kind or kind) and checks if it's a valid resource
func (m MultiRESTMapper) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
for _, t := range m {
if t.ResourceIsValid(resource) {
return true
}
}
return false
}

View File

@ -148,7 +148,7 @@ func TestRESTMapperKindsFor(t *testing.T) {
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
},
ExpectedKindErr: "is ambiguous",
ExpectedKindErr: " matches multiple kinds ",
},
{
@ -188,7 +188,7 @@ func TestRESTMapperKindsFor(t *testing.T) {
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
},
ExpectedKindErr: "is ambiguous",
ExpectedKindErr: " matches multiple kinds ",
},
}
for _, testCase := range testCases {
@ -260,7 +260,7 @@ func TestRESTMapperResourcesFor(t *testing.T) {
{Group: "second-group", Version: "first-version", Resource: "my-kinds"},
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
},
ExpectedResourceErr: "is ambiguous",
ExpectedResourceErr: " matches multiple resources ",
},
{
@ -300,7 +300,7 @@ func TestRESTMapperResourcesFor(t *testing.T) {
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
{Group: "second-group", Version: "first-version", Resource: "my-kinds"},
},
ExpectedResourceErr: "is ambiguous",
ExpectedResourceErr: " matches multiple resources ",
},
}
for _, testCase := range testCases {

View File

@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/kubectl"
@ -118,6 +119,22 @@ func checkErr(err error, handleErr func(string)) {
handleErr(MultilineError(prefix, errs))
}
if meta.IsNoResourceMatchError(err) {
noMatch := err.(*meta.NoResourceMatchError)
switch {
case len(noMatch.PartialResource.Group) > 0 && len(noMatch.PartialResource.Version) > 0:
handleErr(fmt.Sprintf("the server doesn't have a resource type %q in group %q and version %q", noMatch.PartialResource.Resource, noMatch.PartialResource.Group, noMatch.PartialResource.Version))
case len(noMatch.PartialResource.Group) > 0:
handleErr(fmt.Sprintf("the server doesn't have a resource type %q in group %q", noMatch.PartialResource.Resource, noMatch.PartialResource.Group))
case len(noMatch.PartialResource.Version) > 0:
handleErr(fmt.Sprintf("the server doesn't have a resource type %q in version %q", noMatch.PartialResource.Resource, noMatch.PartialResource.Version))
default:
handleErr(fmt.Sprintf("the server doesn't have a resource type %q", noMatch.PartialResource.Resource))
}
return
}
// handle multiline errors
if clientcmd.IsConfigurationInvalid(err) {
handleErr(MultilineError("Error in configuration: ", err))

View File

@ -28,8 +28,10 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/testapi"
apitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/validation/field"
)
@ -302,6 +304,43 @@ func TestCheckInvalidErr(t *testing.T) {
}
}
func TestCheckNoResourceMatchError(t *testing.T) {
tests := []struct {
err error
expected string
}{
{
&meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}},
`the server doesn't have a resource type "foo"`,
},
{
&meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Version: "theversion", Resource: "foo"}},
`the server doesn't have a resource type "foo" in version "theversion"`,
},
{
&meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Group: "thegroup", Version: "theversion", Resource: "foo"}},
`the server doesn't have a resource type "foo" in group "thegroup" and version "theversion"`,
},
{
&meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Group: "thegroup", Resource: "foo"}},
`the server doesn't have a resource type "foo" in group "thegroup"`,
},
}
var errReturned string
errHandle := func(err string) {
errReturned = err
}
for _, test := range tests {
checkErr(test.err, errHandle)
if errReturned != test.expected {
t.Fatalf("Got: %s, expected: %s", errReturned, test.expected)
}
}
}
func TestDumpReaderToFile(t *testing.T) {
testString := "TEST STRING"
tempFile, err := ioutil.TempFile("", "hlpers_test_dump_")