func newWatcher(kr *kregistry) (registry.Watcher, error) { svi := kr.client.Services(api.NamespaceAll) services, err := svi.List(labels.Everything(), fields.Everything()) if err != nil { return nil, err } watch, err := svi.Watch(labels.Everything(), fields.Everything(), services.ResourceVersion) if err != nil { return nil, err } w := &watcher{ registry: kr, watcher: watch, } go func() { for event := range watch.ResultChan() { w.update(event) } }() return w, nil }
func TestRequestWatch(t *testing.T) { testCases := []struct { Request *Request Err bool ErrFn func(error) bool Empty bool }{ { Request: &Request{err: errors.New("bail")}, Err: true, }, { Request: &Request{baseURL: &url.URL{}, pathPrefix: "%"}, Err: true, }, { Request: &Request{ client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, errors.New("err") }), baseURL: &url.URL{}, }, Err: true, }, { Request: &Request{ content: ContentConfig{GroupVersion: testapi.Default.GroupVersion(), Codec: testapi.Default.Codec()}, client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusForbidden, Body: ioutil.NopCloser(bytes.NewReader([]byte{})), }, nil }), baseURL: &url.URL{}, }, Err: true, ErrFn: func(err error) bool { return apierrors.IsForbidden(err) }, }, { Request: &Request{ content: ContentConfig{GroupVersion: testapi.Default.GroupVersion(), Codec: testapi.Default.Codec()}, client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusUnauthorized, Body: ioutil.NopCloser(bytes.NewReader([]byte{})), }, nil }), baseURL: &url.URL{}, }, Err: true, ErrFn: func(err error) bool { return apierrors.IsUnauthorized(err) }, }, { Request: &Request{ content: ContentConfig{GroupVersion: testapi.Default.GroupVersion(), Codec: testapi.Default.Codec()}, client: clientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusUnauthorized, Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &unversioned.Status{ Status: unversioned.StatusFailure, Reason: unversioned.StatusReasonUnauthorized, })))), }, nil }), baseURL: &url.URL{}, }, Err: true, ErrFn: func(err error) bool { return apierrors.IsUnauthorized(err) }, }, { Request: &Request{ client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, io.EOF }), baseURL: &url.URL{}, }, Empty: true, }, { Request: &Request{ client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, &url.Error{Err: io.EOF} }), baseURL: &url.URL{}, }, Empty: true, }, { Request: &Request{ client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, errors.New("http: can't write HTTP request on broken connection") }), baseURL: &url.URL{}, }, Empty: true, }, { Request: &Request{ client: clientFunc(func(req *http.Request) (*http.Response, error) { return nil, errors.New("foo: connection reset by peer") }), baseURL: &url.URL{}, }, Empty: true, }, } for i, testCase := range testCases { t.Logf("testcase %v", testCase.Request) testCase.Request.backoffMgr = &NoBackoff{} watch, err := testCase.Request.Watch() hasErr := err != nil if hasErr != testCase.Err { t.Errorf("%d: expected %t, got %t: %v", i, testCase.Err, hasErr, err) continue } if testCase.ErrFn != nil && !testCase.ErrFn(err) { t.Errorf("%d: error not valid: %v", i, err) } if hasErr && watch != nil { t.Errorf("%d: watch should be nil when error is returned", i) continue } if testCase.Empty { _, ok := <-watch.ResultChan() if ok { t.Errorf("%d: expected the watch to be empty: %#v", i, watch) } } } }
func TestPersistentVolumeClaimBinder(t *testing.T) { _, s := runAMaster(t) defer s.Close() deleteAllEtcdKeys() binderClient := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Default.Version()}) testClient := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Default.Version()}) binder := volumeclaimbinder.NewPersistentVolumeClaimBinder(binderClient, 1*time.Second) binder.Run() defer binder.Stop() for _, volume := range createTestVolumes() { _, err := testClient.PersistentVolumes().Create(volume) if err != nil { t.Fatalf("Unexpected error: %v", err) } } volumes, err := testClient.PersistentVolumes().List(labels.Everything(), fields.Everything()) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(volumes.Items) != 2 { t.Errorf("expected 2 PVs, got %#v", len(volumes.Items)) } for _, claim := range createTestClaims() { _, err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Create(claim) if err != nil { t.Fatalf("Unexpected error: %v", err) } } claims, err := testClient.PersistentVolumeClaims(api.NamespaceDefault).List(labels.Everything(), fields.Everything()) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(claims.Items) != 3 { t.Errorf("expected 3 PVCs, got %#v", len(claims.Items)) } // the binder will eventually catch up and set status on Claims watch, err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Watch(labels.Everything(), fields.Everything(), "0") if err != nil { t.Fatalf("Couldn't subscribe to PersistentVolumeClaims: %v", err) } defer watch.Stop() // Wait for claim01 and claim02 to become bound claim01Pending := true claim02Pending := true for claim01Pending || claim02Pending { event := <-watch.ResultChan() claim := event.Object.(*api.PersistentVolumeClaim) if claim.Spec.VolumeName != "" && claim.Status.Phase != "Bound" { if claim.Name == "claim01" { claim01Pending = false } else if claim.Name == "claim02" { claim02Pending = false } } } for _, claim := range createTestClaims() { claim, err := testClient.PersistentVolumeClaims(api.NamespaceDefault).Get(claim.Name) if err != nil { t.Fatalf("Unexpected error: %v", err) } if (claim.Name == "claim01" || claim.Name == "claim02") && claim.Spec.VolumeName == "" { t.Errorf("Expected claim to be bound: %+v", claim) } if claim.Name == "claim03" && claim.Spec.VolumeName != "" { t.Errorf("Expected claim03 to be unbound: %v", claim) } } }