func runAtomicPutTest(c *client.Client) { var svc api.Service err := c.Post().Resource("services").Body( &api.Service{ TypeMeta: api.TypeMeta{ APIVersion: latest.Version, }, ObjectMeta: api.ObjectMeta{ Name: "atomicservice", Labels: map[string]string{ "name": "atomicService", }, }, Spec: api.ServiceSpec{ Port: 12345, // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, }, }, ).Do().Into(&svc) if err != nil { glog.Fatalf("Failed creating atomicService: %v", err) } glog.Info("Created atomicService") testLabels := labels.Set{ "foo": "bar", } for i := 0; i < 5; i++ { // a: z, b: y, etc... testLabels[string([]byte{byte('a' + i)})] = string([]byte{byte('z' - i)}) } var wg sync.WaitGroup wg.Add(len(testLabels)) for label, value := range testLabels { go func(l, v string) { for { glog.Infof("Starting to update (%s, %s)", l, v) var tmpSvc api.Service err := c.Get(). Resource("services"). Name(svc.Name). Do(). Into(&tmpSvc) if err != nil { glog.Errorf("Error getting atomicService: %v", err) continue } if tmpSvc.Spec.Selector == nil { tmpSvc.Spec.Selector = map[string]string{l: v} } else { tmpSvc.Spec.Selector[l] = v } glog.Infof("Posting update (%s, %s)", l, v) err = c.Put().Resource("services").Name(svc.Name).Body(&tmpSvc).Do().Error() if err != nil { if errors.IsConflict(err) { glog.Infof("Conflict: (%s, %s)", l, v) // This is what we expect. continue } glog.Errorf("Unexpected error putting atomicService: %v", err) continue } break } glog.Infof("Done update (%s, %s)", l, v) wg.Done() }(label, value) } wg.Wait() if err := c.Get().Resource("services").Name(svc.Name).Do().Into(&svc); err != nil { glog.Fatalf("Failed getting atomicService after writers are complete: %v", err) } if !reflect.DeepEqual(testLabels, labels.Set(svc.Spec.Selector)) { glog.Fatalf("Selector PUTs were not atomic: wanted %v, got %v", testLabels, svc.Spec.Selector) } glog.Info("Atomic PUTs work.") }
func runAtomicPutTest(c *client.Client) { var svc api.Service err := c.Post().Path("services").Body( api.Service{ JSONBase: api.JSONBase{ID: "atomicservice", APIVersion: "v1beta1"}, Port: 12345, Labels: map[string]string{ "name": "atomicService", }, // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, }, ).Do().Into(&svc) if err != nil { glog.Fatalf("Failed creating atomicService: %v", err) } glog.Info("Created atomicService") testLabels := labels.Set{ "foo": "bar", } for i := 0; i < 5; i++ { // a: z, b: y, etc... testLabels[string([]byte{byte('a' + i)})] = string([]byte{byte('z' - i)}) } var wg sync.WaitGroup wg.Add(len(testLabels)) for label, value := range testLabels { go func(l, v string) { for { glog.Infof("Starting to update (%s, %s)", l, v) var tmpSvc api.Service err := c.Get(). Path("services"). Path(svc.ID). PollPeriod(100 * time.Millisecond). Do(). Into(&tmpSvc) if err != nil { glog.Errorf("Error getting atomicService: %v", err) continue } if tmpSvc.Selector == nil { tmpSvc.Selector = map[string]string{l: v} } else { tmpSvc.Selector[l] = v } glog.Infof("Posting update (%s, %s)", l, v) err = c.Put().Path("services").Path(svc.ID).Body(&tmpSvc).Do().Error() if err != nil { if se, ok := err.(*client.StatusErr); ok { if se.Status.Code == http.StatusConflict { glog.Infof("Conflict: (%s, %s)", l, v) // This is what we expect. continue } } glog.Errorf("Unexpected error putting atomicService: %v", err) continue } break } glog.Infof("Done update (%s, %s)", l, v) wg.Done() }(label, value) } wg.Wait() if err := c.Get().Path("services").Path(svc.ID).Do().Into(&svc); err != nil { glog.Fatalf("Failed getting atomicService after writers are complete: %v", err) } if !reflect.DeepEqual(testLabels, labels.Set(svc.Selector)) { glog.Fatalf("Selector PUTs were not atomic: wanted %v, got %v", testLabels, svc.Selector) } glog.Info("Atomic PUTs work.") }