Merge pull request #6830 from derekwaynecarr/improve_error_msg

Improve error message when name is omitted but generateName is available
This commit is contained in:
Daniel Smith
2015-04-16 17:21:43 -07:00
17 changed files with 184 additions and 81 deletions

View File

@@ -21,14 +21,16 @@ import (
)
type attributesRecord struct {
kind string
namespace string
resource string
operation string
object runtime.Object
}
func NewAttributesRecord(object runtime.Object, namespace, resource, operation string) Attributes {
func NewAttributesRecord(object runtime.Object, kind, namespace, resource, operation string) Attributes {
return &attributesRecord{
kind: kind,
namespace: namespace,
resource: resource,
operation: operation,
@@ -36,6 +38,10 @@ func NewAttributesRecord(object runtime.Object, namespace, resource, operation s
}
}
func (record *attributesRecord) GetKind() string {
return record.kind
}
func (record *attributesRecord) GetNamespace() string {
return record.namespace
}

48
pkg/admission/errors.go Normal file
View File

@@ -0,0 +1,48 @@
/*
Copyright 2015 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 admission
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
)
// NewForbidden is a utility function to return a well-formatted admission control error response
func NewForbidden(a Attributes, internalError error) error {
// do not double wrap an error of same type
if apierrors.IsForbidden(internalError) {
return internalError
}
name := "Unknown"
kind := a.GetKind()
obj := a.GetObject()
if obj != nil {
objectMeta, err := api.ObjectMetaFor(obj)
if err != nil {
return apierrors.NewForbidden(kind, name, err)
}
// this is necessary because name object name generation has not occurred yet
if len(objectMeta.Name) > 0 {
name = objectMeta.Name
} else if len(objectMeta.GenerateName) > 0 {
name = objectMeta.GenerateName
}
}
return apierrors.NewForbidden(kind, name, internalError)
}

View File

@@ -27,6 +27,7 @@ type Attributes interface {
GetResource() string
GetOperation() string
GetObject() runtime.Object
GetKind() string
}
// Interface is an abstract, pluggable interface for Admission Control decisions.

View File

@@ -40,6 +40,8 @@ type Interface interface {
SetNamespace(namespace string)
Name() string
SetName(name string)
GenerateName() string
SetGenerateName(name string)
UID() types.UID
SetUID(uid types.UID)
ResourceVersion() string
@@ -79,6 +81,9 @@ type MetadataAccessor interface {
Name(obj runtime.Object) (string, error)
SetName(obj runtime.Object, name string) error
GenerateName(obj runtime.Object) (string, error)
SetGenerateName(obj runtime.Object, name string) error
UID(obj runtime.Object) (types.UID, error)
SetUID(obj runtime.Object, uid types.UID) error

View File

@@ -178,6 +178,23 @@ func (resourceAccessor) SetName(obj runtime.Object, name string) error {
return nil
}
func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) {
accessor, err := Accessor(obj)
if err != nil {
return "", err
}
return accessor.GenerateName(), nil
}
func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetGenerateName(name)
return nil
}
func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) {
accessor, err := Accessor(obj)
if err != nil {
@@ -268,6 +285,7 @@ func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) e
type genericAccessor struct {
namespace *string
name *string
generateName *string
uid *types.UID
apiVersion *string
kind *string
@@ -305,6 +323,20 @@ func (a genericAccessor) SetName(name string) {
*a.name = name
}
func (a genericAccessor) GenerateName() string {
if a.generateName == nil {
return ""
}
return *a.generateName
}
func (a genericAccessor) SetGenerateName(generateName string) {
if a.generateName == nil {
return
}
*a.generateName = generateName
}
func (a genericAccessor) UID() types.UID {
if a.uid == nil {
return ""
@@ -392,6 +424,9 @@ func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error {
if err := runtime.FieldPtr(v, "Name", &a.name); err != nil {
return err
}
if err := runtime.FieldPtr(v, "GenerateName", &a.generateName); err != nil {
return err
}
if err := runtime.FieldPtr(v, "UID", &a.uid); err != nil {
return err
}

View File

@@ -29,6 +29,7 @@ func TestGenericTypeMeta(t *testing.T) {
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
GenerateName string `json:"generateName,omitempty"`
UID string `json:"uid,omitempty"`
CreationTimestamp util.Time `json:"creationTimestamp,omitempty"`
SelfLink string `json:"selfLink,omitempty"`
@@ -44,6 +45,7 @@ func TestGenericTypeMeta(t *testing.T) {
TypeMeta{
Namespace: "bar",
Name: "foo",
GenerateName: "prefix",
UID: "uid",
APIVersion: "a",
Kind: "b",
@@ -63,6 +65,9 @@ func TestGenericTypeMeta(t *testing.T) {
if e, a := "foo", accessor.Name(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "prefix", accessor.GenerateName(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "uid", string(accessor.UID()); e != a {
t.Errorf("expected %v, got %v", e, a)
}
@@ -92,6 +97,7 @@ func TestGenericTypeMeta(t *testing.T) {
accessor.SetNamespace("baz")
accessor.SetName("bar")
accessor.SetGenerateName("generate")
accessor.SetUID("other")
accessor.SetAPIVersion("c")
accessor.SetKind("d")
@@ -105,6 +111,9 @@ func TestGenericTypeMeta(t *testing.T) {
if e, a := "bar", j.Name; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "generate", j.GenerateName; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "other", j.UID; e != a {
t.Errorf("expected %v, got %v", e, a)
}
@@ -135,6 +144,7 @@ type InternalTypeMeta struct {
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
GenerateName string `json:"generateName,omitempty"`
UID string `json:"uid,omitempty"`
CreationTimestamp util.Time `json:"creationTimestamp,omitempty"`
SelfLink string `json:"selfLink,omitempty"`
@@ -154,6 +164,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) {
InternalTypeMeta{
Namespace: "bar",
Name: "foo",
GenerateName: "prefix",
UID: "uid",
APIVersion: "a",
Kind: "b",
@@ -178,6 +189,13 @@ func TestGenericTypeMetaAccessor(t *testing.T) {
if e, a := "foo", name; e != a {
t.Errorf("expected %v, got %v", e, a)
}
generateName, err := accessor.GenerateName(j)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if e, a := "prefix", generateName; e != a {
t.Errorf("expected %v, got %v", e, a)
}
uid, err := accessor.UID(j)
if err != nil {
t.Errorf("unexpected error: %v", err)
@@ -234,6 +252,9 @@ func TestGenericTypeMetaAccessor(t *testing.T) {
if err := accessor.SetName(j, "bar"); err != nil {
t.Errorf("unexpected error: %v", err)
}
if err := accessor.SetGenerateName(j, "generate"); err != nil {
t.Errorf("unexpected error: %v", err)
}
if err := accessor.SetUID(j, "other"); err != nil {
t.Errorf("unexpected error: %v", err)
}
@@ -264,6 +285,9 @@ func TestGenericTypeMetaAccessor(t *testing.T) {
if e, a := "bar", j.TypeMeta.Name; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "generate", j.TypeMeta.GenerateName; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "other", j.TypeMeta.UID; e != a {
t.Errorf("expected %v, got %v", e, a)
}
@@ -295,6 +319,7 @@ func TestGenericObjectMeta(t *testing.T) {
type ObjectMeta struct {
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
GenerateName string `json:"generateName,omitempty"`
UID string `json:"uid,omitempty"`
CreationTimestamp util.Time `json:"creationTimestamp,omitempty"`
SelfLink string `json:"selfLink,omitempty"`
@@ -314,6 +339,7 @@ func TestGenericObjectMeta(t *testing.T) {
ObjectMeta{
Namespace: "bar",
Name: "foo",
GenerateName: "prefix",
UID: "uid",
ResourceVersion: "1",
SelfLink: "some/place/only/we/know",
@@ -331,6 +357,9 @@ func TestGenericObjectMeta(t *testing.T) {
if e, a := "foo", accessor.Name(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "prefix", accessor.GenerateName(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "uid", string(accessor.UID()); e != a {
t.Errorf("expected %v, got %v", e, a)
}
@@ -355,6 +384,7 @@ func TestGenericObjectMeta(t *testing.T) {
accessor.SetNamespace("baz")
accessor.SetName("bar")
accessor.SetGenerateName("generate")
accessor.SetUID("other")
accessor.SetAPIVersion("c")
accessor.SetKind("d")
@@ -370,6 +400,9 @@ func TestGenericObjectMeta(t *testing.T) {
if e, a := "bar", j.Name; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "generate", j.GenerateName; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "other", j.UID; e != a {
t.Errorf("expected %v, got %v", e, a)
}

View File

@@ -216,7 +216,7 @@ func CreateResource(r rest.Creater, scope RequestScope, typer runtime.ObjectType
return
}
err = admit.Admit(admission.NewAttributesRecord(obj, namespace, scope.Resource, "CREATE"))
err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind, namespace, scope.Resource, "CREATE"))
if err != nil {
errorJSON(err, scope.Codec, w)
return
@@ -262,7 +262,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, typer runtime.ObjectTyper
obj := r.New()
// PATCH requires same permission as UPDATE
err = admit.Admit(admission.NewAttributesRecord(obj, namespace, scope.Resource, "UPDATE"))
err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind, namespace, scope.Resource, "UPDATE"))
if err != nil {
errorJSON(err, scope.Codec, w)
return
@@ -362,7 +362,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType
return
}
err = admit.Admit(admission.NewAttributesRecord(obj, namespace, scope.Resource, "UPDATE"))
err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind, namespace, scope.Resource, "UPDATE"))
if err != nil {
errorJSON(err, scope.Codec, w)
return
@@ -423,7 +423,7 @@ func DeleteResource(r rest.GracefulDeleter, checkBody bool, scope RequestScope,
}
}
err = admit.Admit(admission.NewAttributesRecord(nil, namespace, scope.Resource, "DELETE"))
err = admit.Admit(admission.NewAttributesRecord(nil, scope.Kind, namespace, scope.Resource, "DELETE"))
if err != nil {
errorJSON(err, scope.Codec, w)
return