Unify validation logic for create and update paths

Ensure ObjectMeta is consistently validated on both create and update

Make PortalIP uncleareable
This commit is contained in:
Clayton Coleman
2015-01-27 18:55:54 -05:00
parent 72cc17b41c
commit a0356bca96
9 changed files with 334 additions and 114 deletions

View File

@@ -42,7 +42,7 @@ func TestMinionRegistryREST(t *testing.T) {
c, err := ms.Create(ctx, &api.Node{ObjectMeta: api.ObjectMeta{Name: "baz"}})
if err != nil {
t.Errorf("insert failed")
t.Fatalf("insert failed: %v", err)
}
obj := <-c
if !api.HasObjectMetaSystemFieldValues(&obj.Object.(*api.Node).ObjectMeta) {
@@ -57,7 +57,7 @@ func TestMinionRegistryREST(t *testing.T) {
c, err = ms.Delete(ctx, "bar")
if err != nil {
t.Errorf("delete failed")
t.Fatalf("delete failed")
}
obj = <-c
if s, ok := obj.Object.(*api.Status); !ok || s.Status != api.StatusSuccess {
@@ -69,7 +69,7 @@ func TestMinionRegistryREST(t *testing.T) {
_, err = ms.Delete(ctx, "bar")
if err != ErrDoesNotExist {
t.Errorf("delete returned wrong error")
t.Fatalf("delete returned wrong error")
}
list, err := ms.List(ctx, labels.Everything(), labels.Everything())
@@ -103,7 +103,7 @@ func TestMinionRegistryHealthCheck(t *testing.T) {
c, err := ms.Create(ctx, &api.Node{ObjectMeta: api.ObjectMeta{Name: "m1"}})
if err != nil {
t.Errorf("insert failed")
t.Fatalf("insert failed: %v", err)
}
result := <-c
if m, ok := result.Object.(*api.Node); !ok || m.Name != "m1" {

View File

@@ -84,7 +84,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE
if !api.ValidNamespace(ctx, &service.ObjectMeta) {
return nil, errors.NewConflict("service", service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context"))
}
if errs := validation.ValidateService(service, rs.registry, ctx); len(errs) > 0 {
if errs := validation.ValidateService(service); len(errs) > 0 {
return nil, errors.NewInvalid("service", service.Name, errs)
}
@@ -226,20 +226,21 @@ func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE
if !api.ValidNamespace(ctx, &service.ObjectMeta) {
return nil, errors.NewConflict("service", service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context"))
}
if errs := validation.ValidateService(service, rs.registry, ctx); len(errs) > 0 {
oldService, err := rs.registry.GetService(ctx, service.Name)
if err != nil {
return nil, err
}
// Copy over non-user fields
// TODO: this should be a Status field, since the end user does not set it.
// TODO: make this a merge function
service.Spec.ProxyPort = oldService.Spec.ProxyPort
if errs := validation.ValidateServiceUpdate(oldService, service); len(errs) > 0 {
return nil, errors.NewInvalid("service", service.Name, errs)
}
return apiserver.MakeAsync(func() (runtime.Object, error) {
cur, err := rs.registry.GetService(ctx, service.Name)
if err != nil {
return nil, err
}
if service.Spec.PortalIP != "" && service.Spec.PortalIP != cur.Spec.PortalIP {
el := errors.ValidationErrorList{errors.NewFieldInvalid("spec.portalIP", service.Spec.PortalIP, "field is immutable")}
return nil, errors.NewInvalid("service", service.Name, el)
}
// Copy over non-user fields.
service.Spec.ProxyPort = cur.Spec.ProxyPort
// TODO: check to see if external load balancer status changed
err = rs.registry.UpdateService(ctx, service)
if err != nil {

View File

@@ -118,7 +118,7 @@ func TestServiceRegistryUpdate(t *testing.T) {
ctx := api.NewDefaultContext()
registry := registrytest.NewServiceRegistry()
registry.CreateService(ctx, &api.Service{
ObjectMeta: api.ObjectMeta{Name: "foo"},
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault},
Spec: api.ServiceSpec{
Port: 6502,
Selector: map[string]string{"bar": "baz1"},
@@ -132,12 +132,12 @@ func TestServiceRegistryUpdate(t *testing.T) {
Selector: map[string]string{"bar": "baz2"},
},
})
if err != nil {
t.Fatalf("Expected no error: %v", err)
}
if c == nil {
t.Errorf("Expected non-nil channel")
}
if err != nil {
t.Errorf("Expected no error")
}
updated_svc := <-c
updated_service := updated_svc.Object.(*api.Service)
if updated_service.Name != "foo" {
@@ -531,11 +531,9 @@ func TestServiceRegistryIPUpdate(t *testing.T) {
update.Spec.Port = 6503
update.Spec.PortalIP = "1.2.3.76" // error
c, _ = rest.Update(ctx, update)
result := <-c
st := result.Object.(*api.Status)
if st.Reason != api.StatusReasonInvalid {
t.Errorf("Expected to get an invalid error, got %v", st)
_, err := rest.Update(ctx, update)
if err == nil || !errors.IsInvalid(err) {
t.Error("Unexpected error type: %v", err)
}
}