Adding retry logic around service updates

pull/6/head
Kris Rousey 2015-07-10 13:38:37 -07:00
parent affba42a05
commit aca4559bbd
1 changed files with 43 additions and 12 deletions

View File

@ -26,6 +26,7 @@ import (
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
@ -366,8 +367,9 @@ var _ = Describe("Services", func() {
t.CreateWebserverRC(1)
By("changing service " + serviceName + " to type=NodePort")
service.Spec.Type = api.ServiceTypeNodePort
service, err = c.Services(ns).Update(service)
service, err = updateService(c, ns, serviceName, func(s *api.Service) {
s.Spec.Type = api.ServiceTypeNodePort
})
Expect(err).NotTo(HaveOccurred())
if service.Spec.Type != api.ServiceTypeNodePort {
@ -394,7 +396,9 @@ var _ = Describe("Services", func() {
By("changing service " + serviceName + " to type=LoadBalancer")
service.Spec.Type = api.ServiceTypeLoadBalancer
service, err = c.Services(ns).Update(service)
service, err = updateService(c, ns, serviceName, func(s *api.Service) {
s.Spec.Type = api.ServiceTypeLoadBalancer
})
Expect(err).NotTo(HaveOccurred())
// Wait for the load balancer to be created asynchronously
@ -430,8 +434,9 @@ var _ = Describe("Services", func() {
//Check for (unlikely) assignment at bottom of range
nodePort2 = nodePort1 + 1
}
service.Spec.Ports[0].NodePort = nodePort2
service, err = c.Services(ns).Update(service)
service, err = updateService(c, ns, serviceName, func(s *api.Service) {
s.Spec.Ports[0].NodePort = nodePort2
})
Expect(err).NotTo(HaveOccurred())
if service.Spec.Type != api.ServiceTypeLoadBalancer {
@ -459,9 +464,10 @@ var _ = Describe("Services", func() {
testNotReachable(ip, nodePort1)
By("changing service " + serviceName + " back to type=ClusterIP")
service.Spec.Type = api.ServiceTypeClusterIP
service.Spec.Ports[0].NodePort = 0
service, err = c.Services(ns).Update(service)
service, err = updateService(c, ns, serviceName, func(s *api.Service) {
s.Spec.Type = api.ServiceTypeClusterIP
s.Spec.Ports[0].NodePort = 0
})
Expect(err).NotTo(HaveOccurred())
if service.Spec.Type != api.ServiceTypeClusterIP {
@ -548,8 +554,9 @@ var _ = Describe("Services", func() {
testLoadBalancerReachable(ingress, 80)
By("changing service " + serviceName + " to type=NodePort")
service.Spec.Type = api.ServiceTypeNodePort
service, err = c.Services(ns).Update(service)
service, err = updateService(c, ns, serviceName, func(s *api.Service) {
s.Spec.Type = api.ServiceTypeNodePort
})
Expect(err).NotTo(HaveOccurred())
if service.Spec.Type != api.ServiceTypeNodePort {
@ -674,8 +681,9 @@ var _ = Describe("Services", func() {
}
}
By(fmt.Sprintf("changing service "+serviceName+" to out-of-range NodePort %d", outOfRangeNodePort))
service.Spec.Ports[0].NodePort = outOfRangeNodePort
result, err := t.Client.Services(t.Namespace).Update(service)
result, err := updateService(c, ns, serviceName, func(s *api.Service) {
s.Spec.Ports[0].NodePort = outOfRangeNodePort
})
if err == nil {
Failf("failed to prevent update of service with out-of-range NodePort: %v", result)
}
@ -797,6 +805,29 @@ var _ = Describe("Services", func() {
})
})
// updateService fetches a service, calls the update function on it,
// and then attempts to send the updated service. It retries up to 2
// times in the face of timeouts and conflicts.
func updateService(c *client.Client, namespace, serviceName string, update func(*api.Service)) (*api.Service, error) {
var service *api.Service
var err error
for i := 0; i < 3; i++ {
service, err = c.Services(namespace).Get(serviceName)
if err != nil {
return service, err
}
update(service)
service, err = c.Services(namespace).Update(service)
if !errors.IsConflict(err) && !errors.IsServerTimeout(err) {
return service, err
}
}
return service, err
}
func waitForLoadBalancerIngress(c *client.Client, serviceName, namespace string) (*api.Service, error) {
// TODO: once support ticket 21807001 is resolved, reduce this timeout back to something reasonable
const timeout = 20 * time.Minute