fix tests broken by stronger validation

This commit is contained in:
Tim Hockin 2015-03-31 11:13:44 -07:00
parent b420871a11
commit e19f4939b1
2 changed files with 179 additions and 271 deletions

View File

@ -23,96 +23,86 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
) )
func makeValidService() api.Service {
return api.Service{
ObjectMeta: api.ObjectMeta{
Name: "valid",
Namespace: "default",
Labels: map[string]string{},
Annotations: map[string]string{},
ResourceVersion: "1",
},
Spec: api.ServiceSpec{
Selector: map[string]string{"key": "val"},
SessionAffinity: "None",
Ports: []api.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675}},
},
}
}
// TODO: This should be done on types that are not part of our API
func TestBeforeUpdate(t *testing.T) { func TestBeforeUpdate(t *testing.T) {
tests := []struct { testCases := []struct {
old runtime.Object name string
obj runtime.Object tweakSvc func(oldSvc, newSvc *api.Service) // given basic valid services, each test case can customize them
expectErr bool expectErr bool
}{ }{
{ {
obj: &api.Service{ name: "no change",
ObjectMeta: api.ObjectMeta{ tweakSvc: func(oldSvc, newSvc *api.Service) {
Name: "foo", // nothing
ResourceVersion: "1",
Namespace: "#$%%invalid",
},
}, },
old: &api.Service{}, expectErr: false,
expectErr: true,
}, },
{ {
obj: &api.Service{ name: "change port",
ObjectMeta: api.ObjectMeta{ tweakSvc: func(oldSvc, newSvc *api.Service) {
Name: "foo", newSvc.Spec.Ports[0].Port++
ResourceVersion: "1",
Namespace: "valid",
},
}, },
old: &api.Service{ expectErr: false,
ObjectMeta: api.ObjectMeta{ },
Name: "bar", {
ResourceVersion: "1", name: "bad namespace",
Namespace: "valid", tweakSvc: func(oldSvc, newSvc *api.Service) {
}, newSvc.Namespace = "#$%%invalid"
}, },
expectErr: true, expectErr: true,
}, },
{ {
obj: &api.Service{ name: "change name",
ObjectMeta: api.ObjectMeta{ tweakSvc: func(oldSvc, newSvc *api.Service) {
Name: "foo", newSvc.Name += "2"
ResourceVersion: "1",
Namespace: "valid",
},
Spec: api.ServiceSpec{
PortalIP: "1.2.3.4",
},
},
old: &api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
ResourceVersion: "1",
Namespace: "valid",
},
Spec: api.ServiceSpec{
PortalIP: "4.3.2.1",
},
}, },
expectErr: true, expectErr: true,
}, },
{ {
obj: &api.Service{ name: "change portal IP",
ObjectMeta: api.ObjectMeta{ tweakSvc: func(oldSvc, newSvc *api.Service) {
Name: "foo", oldSvc.Spec.PortalIP = "1.2.3.4"
ResourceVersion: "1", newSvc.Spec.PortalIP = "4.3.2.1"
Namespace: api.NamespaceDefault,
},
Spec: api.ServiceSpec{
PortalIP: "1.2.3.4",
Selector: map[string]string{"foo": "bar"},
},
}, },
old: &api.Service{ expectErr: true,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
ResourceVersion: "1", name: "change selectpor",
Namespace: api.NamespaceDefault, tweakSvc: func(oldSvc, newSvc *api.Service) {
}, newSvc.Spec.Selector = map[string]string{"newkey": "newvalue"}
Spec: api.ServiceSpec{
PortalIP: "1.2.3.4",
Selector: map[string]string{"bar": "foo"},
},
}, },
expectErr: false,
}, },
} }
for _, test := range tests {
for _, tc := range testCases {
oldSvc := makeValidService()
newSvc := makeValidService()
tc.tweakSvc(&oldSvc, &newSvc)
ctx := api.NewDefaultContext() ctx := api.NewDefaultContext()
err := BeforeUpdate(Services, ctx, test.obj, test.old) err := BeforeUpdate(Services, ctx, runtime.Object(&oldSvc), runtime.Object(&newSvc))
if test.expectErr && err == nil { if tc.expectErr && err == nil {
t.Errorf("unexpected non-error for %v", test) t.Errorf("unexpected non-error for %q", tc.name)
} }
if !test.expectErr && err != nil { if !tc.expectErr && err != nil {
t.Errorf("unexpected error: %v for %v -> %v", err, test.obj, test.old) t.Errorf("unexpected error for %q: %v", tc.name, err)
} }
} }
} }

View File

@ -1223,190 +1223,207 @@ func TestValidatePodUpdate(t *testing.T) {
} }
} }
func makeValidService() api.Service {
return api.Service{
ObjectMeta: api.ObjectMeta{
Name: "valid",
Namespace: "valid",
Labels: map[string]string{},
Annotations: map[string]string{},
ResourceVersion: "1",
},
Spec: api.ServiceSpec{
Selector: map[string]string{"key": "val"},
SessionAffinity: "None",
Ports: []api.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675}},
},
}
}
func TestValidateService(t *testing.T) { func TestValidateService(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
makeSvc func(svc *api.Service) // given a basic valid service, each test case can customize it tweakSvc func(svc *api.Service) // given a basic valid service, each test case can customize it
numErrs int numErrs int
}{ }{
{ {
name: "missing namespace", name: "missing namespace",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Namespace = "" s.Namespace = ""
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid namespace", name: "invalid namespace",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Namespace = "-123" s.Namespace = "-123"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "missing name", name: "missing name",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Name = "" s.Name = ""
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid name", name: "invalid name",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Name = "-123" s.Name = "-123"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "too long name", name: "too long name",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Name = strings.Repeat("a", 25) s.Name = strings.Repeat("a", 25)
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid generateName", name: "invalid generateName",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.GenerateName = "-123" s.GenerateName = "-123"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "too long generateName", name: "too long generateName",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.GenerateName = strings.Repeat("a", 25) s.GenerateName = strings.Repeat("a", 25)
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid label", name: "invalid label",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Labels["NoUppercaseOrSpecialCharsLike=Equals"] = "bar" s.Labels["NoUppercaseOrSpecialCharsLike=Equals"] = "bar"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid annotation", name: "invalid annotation",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Annotations["NoSpecialCharsLike=Equals"] = "bar" s.Annotations["NoSpecialCharsLike=Equals"] = "bar"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "nil selector", name: "nil selector",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Selector = nil s.Spec.Selector = nil
}, },
numErrs: 0, numErrs: 0,
}, },
{ {
name: "invalid selector", name: "invalid selector",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Selector["NoSpecialCharsLike=Equals"] = "bar" s.Spec.Selector["NoSpecialCharsLike=Equals"] = "bar"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "missing session affinity", name: "missing session affinity",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.SessionAffinity = "" s.Spec.SessionAffinity = ""
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "missing ports", name: "missing ports",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports = nil s.Spec.Ports = nil
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "empty port[0] name", name: "empty port[0] name",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Name = "" s.Spec.Ports[0].Name = ""
}, },
numErrs: 0, numErrs: 0,
}, },
{ {
name: "empty port[1] name", name: "empty port[1] name",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "", Protocol: "TCP", Port: 12345}) s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "", Protocol: "TCP", Port: 12345})
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid port name", name: "invalid port name",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Name = "INVALID" s.Spec.Ports[0].Name = "INVALID"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "missing protocol", name: "missing protocol",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Protocol = "" s.Spec.Ports[0].Protocol = ""
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid protocol", name: "invalid protocol",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Protocol = "INVALID" s.Spec.Ports[0].Protocol = "INVALID"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid portal ip", name: "invalid portal ip",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.PortalIP = "invalid" s.Spec.PortalIP = "invalid"
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "missing port", name: "missing port",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Port = 0 s.Spec.Ports[0].Port = 0
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid port", name: "invalid port",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Port = 65536 s.Spec.Ports[0].Port = 65536
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid TargetPort int", name: "invalid TargetPort int",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(65536) s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(65536)
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid publicIPs localhost", name: "invalid publicIPs localhost",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.PublicIPs = []string{"127.0.0.1"} s.Spec.PublicIPs = []string{"127.0.0.1"}
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "invalid publicIPs", name: "invalid publicIPs",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.PublicIPs = []string{"0.0.0.0"} s.Spec.PublicIPs = []string{"0.0.0.0"}
}, },
numErrs: 1, numErrs: 1,
}, },
{ {
name: "valid publicIPs host", name: "valid publicIPs host",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.PublicIPs = []string{"myhost.mydomain"} s.Spec.PublicIPs = []string{"myhost.mydomain"}
}, },
numErrs: 0, numErrs: 0,
}, },
{ {
name: "dup port name", name: "dup port name",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Name = "p" s.Spec.Ports[0].Name = "p"
s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "p", Port: 12345}) s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "p", Port: 12345})
}, },
@ -1414,14 +1431,14 @@ func TestValidateService(t *testing.T) {
}, },
{ {
name: "valid 1", name: "valid 1",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
// do nothing // do nothing
}, },
numErrs: 0, numErrs: 0,
}, },
{ {
name: "valid 2", name: "valid 2",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].Protocol = "UDP" s.Spec.Ports[0].Protocol = "UDP"
s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(12345) s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(12345)
}, },
@ -1429,21 +1446,21 @@ func TestValidateService(t *testing.T) {
}, },
{ {
name: "valid 3", name: "valid 3",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromString("http") s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromString("http")
}, },
numErrs: 0, numErrs: 0,
}, },
{ {
name: "valid portal ip - none ", name: "valid portal ip - none ",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.PortalIP = "None" s.Spec.PortalIP = "None"
}, },
numErrs: 0, numErrs: 0,
}, },
{ {
name: "valid portal ip - empty", name: "valid portal ip - empty",
makeSvc: func(s *api.Service) { tweakSvc: func(s *api.Service) {
s.Spec.PortalIP = "" s.Spec.PortalIP = ""
s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromString("http") s.Spec.Ports[0].TargetPort = util.NewIntOrStringFromString("http")
}, },
@ -1452,20 +1469,8 @@ func TestValidateService(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
svc := api.Service{ svc := makeValidService()
ObjectMeta: api.ObjectMeta{ tc.tweakSvc(&svc)
Name: "valid",
Namespace: "valid",
Labels: map[string]string{},
Annotations: map[string]string{},
},
Spec: api.ServiceSpec{
Selector: map[string]string{"key": "val"},
SessionAffinity: "None",
Ports: []api.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675}},
},
}
tc.makeSvc(&svc)
errs := ValidateService(&svc) errs := ValidateService(&svc)
if len(errs) != tc.numErrs { if len(errs) != tc.numErrs {
t.Errorf("Unexpected error list for case %q: %v", tc.name, utilerrors.NewAggregate(errs)) t.Errorf("Unexpected error list for case %q: %v", tc.name, utilerrors.NewAggregate(errs))
@ -2173,172 +2178,85 @@ func TestValidateMinionUpdate(t *testing.T) {
} }
func TestValidateServiceUpdate(t *testing.T) { func TestValidateServiceUpdate(t *testing.T) {
tests := []struct { testCases := []struct {
oldService api.Service name string
service api.Service tweakSvc func(oldSvc, newSvc *api.Service) // given basic valid services, each test case can customize them
valid bool numErrs int
}{ }{
{ // 0 {
api.Service{}, name: "no change",
api.Service{}, tweakSvc: func(oldSvc, newSvc *api.Service) {
true}, // do nothing
{ // 1
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo"}},
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "bar"},
}, false},
{ // 2
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{"foo": "bar"},
},
}, },
api.Service{ numErrs: 0,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
Labels: map[string]string{"foo": "baz"}, name: "change name",
}, tweakSvc: func(oldSvc, newSvc *api.Service) {
}, true}, newSvc.Name += "2"
{ // 3
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
}, },
api.Service{ numErrs: 1,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
Labels: map[string]string{"foo": "baz"}, name: "change namespace",
}, tweakSvc: func(oldSvc, newSvc *api.Service) {
}, true}, newSvc.Namespace += "2"
{ // 4
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{"bar": "foo"},
},
}, },
api.Service{ numErrs: 1,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
Labels: map[string]string{"foo": "baz"}, name: "change label valid",
}, tweakSvc: func(oldSvc, newSvc *api.Service) {
}, true}, newSvc.Labels["key"] = "other-value"
{ // 5
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Annotations: map[string]string{"bar": "foo"},
},
}, },
api.Service{ numErrs: 0,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
Annotations: map[string]string{"foo": "baz"}, name: "add label",
}, tweakSvc: func(oldSvc, newSvc *api.Service) {
}, true}, newSvc.Labels["key2"] = "value2"
{ // 6
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Spec: api.ServiceSpec{
Selector: map[string]string{"foo": "baz"},
},
}, },
api.Service{ numErrs: 0,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
}, name: "change portal IP",
Spec: api.ServiceSpec{ tweakSvc: func(oldSvc, newSvc *api.Service) {
Selector: map[string]string{"foo": "baz"}, oldSvc.Spec.PortalIP = "1.2.3.4"
}, newSvc.Spec.PortalIP = "8.6.7.5"
}, true},
{ // 7
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{"bar": "foo"},
},
Spec: api.ServiceSpec{
PortalIP: "127.0.0.1",
},
}, },
api.Service{ numErrs: 1,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
Labels: map[string]string{"bar": "fooobaz"}, name: "remove portal IP",
}, tweakSvc: func(oldSvc, newSvc *api.Service) {
Spec: api.ServiceSpec{ oldSvc.Spec.PortalIP = "1.2.3.4"
PortalIP: "new", newSvc.Spec.PortalIP = ""
},
}, false},
{ // 8
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{"bar": "foo"},
},
Spec: api.ServiceSpec{
PortalIP: "127.0.0.1",
},
}, },
api.Service{ numErrs: 1,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
Labels: map[string]string{"bar": "fooobaz"}, name: "change affinity",
}, tweakSvc: func(oldSvc, newSvc *api.Service) {
Spec: api.ServiceSpec{ newSvc.Spec.SessionAffinity = "ClientIP"
PortalIP: "",
},
}, false},
{ // 9
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{"bar": "foo"},
},
Spec: api.ServiceSpec{
PortalIP: "127.0.0.1",
},
}, },
api.Service{ numErrs: 0,
ObjectMeta: api.ObjectMeta{ },
Name: "foo", {
Labels: map[string]string{"bar": "fooobaz"}, name: "remove affinity",
}, tweakSvc: func(oldSvc, newSvc *api.Service) {
Spec: api.ServiceSpec{ newSvc.Spec.SessionAffinity = ""
PortalIP: "127.0.0.2",
},
}, false},
{ // 10
api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{"foo": "baz"},
},
}, },
api.Service{ numErrs: 1,
ObjectMeta: api.ObjectMeta{ },
Name: "foo",
Labels: map[string]string{"Foo": "baz"},
},
}, true},
} }
for i, test := range tests {
test.oldService.ObjectMeta.ResourceVersion = "1" for _, tc := range testCases {
test.service.ObjectMeta.ResourceVersion = "1" oldSvc := makeValidService()
errs := ValidateServiceUpdate(&test.oldService, &test.service) newSvc := makeValidService()
if test.valid && len(errs) > 0 { tc.tweakSvc(&oldSvc, &newSvc)
t.Errorf("%d: Unexpected error: %v", i, errs) errs := ValidateServiceUpdate(&oldSvc, &newSvc)
t.Logf("%#v vs %#v", test.oldService.ObjectMeta, test.service.ObjectMeta) if len(errs) != tc.numErrs {
} t.Errorf("Unexpected error list for case %q: %v", tc.name, utilerrors.NewAggregate(errs))
if !test.valid && len(errs) == 0 {
t.Errorf("%d: Unexpected non-error", i)
} }
} }
} }