func TestWatchHTTP(t *testing.T) { simpleStorage := &SimpleRESTStorage{} handler := handle(map[string]rest.Storage{"simples": simpleStorage}) server := httptest.NewServer(handler) defer server.Close() client := http.Client{} dest, _ := url.Parse(server.URL) dest.Path = "/api/version/watch/simples" dest.RawQuery = "" request, err := http.NewRequest("GET", dest.String(), nil) if err != nil { t.Errorf("unexpected error: %v", err) } response, err := client.Do(request) if err != nil { t.Errorf("unexpected error: %v", err) } if response.StatusCode != http.StatusOK { t.Errorf("Unexpected response %#v", response) } decoder := json.NewDecoder(response.Body) for i, item := range watchTestTable { // Send simpleStorage.fakeWatch.Action(item.t, item.obj) // Test receive var got watchJSON err := decoder.Decode(&got) if err != nil { t.Fatalf("%d: Unexpected error: %v", i, err) } if got.Type != item.t { t.Errorf("%d: Unexpected type: %v", i, got.Type) } t.Logf("obj: %v", string(got.Object)) gotObj, err := codec.Decode(got.Object) if err != nil { t.Fatalf("Decode error: %v", err) } t.Logf("obj: %#v", gotObj) if _, err := api.GetReference(gotObj); err != nil { t.Errorf("Unable to construct reference: %v", err) } if e, a := item.obj, gotObj; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } } simpleStorage.fakeWatch.Stop() var got watchJSON err = decoder.Decode(&got) if err == nil { t.Errorf("Unexpected non-error") } }
func (recorder *recorderImpl) generateEvent(object runtime.Object, timestamp unversioned.Time, reason, message string) { ref, err := api.GetReference(object) if err != nil { glog.Errorf("Could not construct reference to: '%#v' due to: '%v'. Will not report event: '%v' '%v'", object, err, reason, message) return } event := makeEvent(ref, reason, message) event.Source = recorder.source recorder.Action(watch.Added, event) }
func TestWatchWebsocket(t *testing.T) { simpleStorage := &SimpleRESTStorage{} _ = rest.Watcher(simpleStorage) // Give compile error if this doesn't work. handler := handle(map[string]rest.Storage{"simples": simpleStorage}) server := httptest.NewServer(handler) defer server.Close() dest, _ := url.Parse(server.URL) dest.Scheme = "ws" // Required by websocket, though the server never sees it. dest.Path = "/api/version/watch/simples" dest.RawQuery = "" ws, err := websocket.Dial(dest.String(), "", "http://localhost") if err != nil { t.Errorf("unexpected error: %v", err) } try := func(action watch.EventType, object runtime.Object) { // Send simpleStorage.fakeWatch.Action(action, object) // Test receive var got watchJSON err := websocket.JSON.Receive(ws, &got) if err != nil { t.Fatalf("Unexpected error: %v", err) } if got.Type != action { t.Errorf("Unexpected type: %v", got.Type) } gotObj, err := codec.Decode(got.Object) if err != nil { t.Fatalf("Decode error: %v", err) } if _, err := api.GetReference(gotObj); err != nil { t.Errorf("Unable to construct reference: %v", err) } if e, a := object, gotObj; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } } for _, item := range watchTestTable { try(item.t, item.obj) } simpleStorage.fakeWatch.Stop() var got watchJSON err = websocket.JSON.Receive(ws, &got) if err == nil { t.Errorf("Unexpected non-error") } }
func getPodsAnnotationSet(template *api.PodTemplateSpec, object runtime.Object) (labels.Set, error) { desiredAnnotations := make(labels.Set) for k, v := range template.Annotations { desiredAnnotations[k] = v } createdByRef, err := api.GetReference(object) if err != nil { return desiredAnnotations, fmt.Errorf("unable to get controller reference: %v", err) } createdByRefJson, err := latest.GroupOrDie("").Codec.Encode(&api.SerializedReference{ Reference: *createdByRef, }) if err != nil { return desiredAnnotations, fmt.Errorf("unable to serialize controller reference: %v", err) } desiredAnnotations[CreatedByAnnotation] = string(createdByRefJson) return desiredAnnotations, nil }
// Search finds events about the specified object. The namespace of the // object must match this event's client namespace unless the event client // was made with the "" namespace. func (e *events) Search(objOrRef runtime.Object) (*api.EventList, error) { ref, err := api.GetReference(objOrRef) if err != nil { return nil, err } if e.namespace != "" && ref.Namespace != e.namespace { return nil, fmt.Errorf("won't be able to find any events of namespace '%v' in namespace '%v'", ref.Namespace, e.namespace) } stringRefKind := string(ref.Kind) var refKind *string if stringRefKind != "" { refKind = &stringRefKind } stringRefUID := string(ref.UID) var refUID *string if stringRefUID != "" { refUID = &stringRefUID } fieldSelector := e.GetFieldSelector(&ref.Name, &ref.Namespace, refKind, refUID) return e.List(labels.Everything(), fieldSelector) }
func syncClaim(volumeIndex *persistentVolumeOrderedIndex, binderClient binderClient, claim *api.PersistentVolumeClaim) (err error) { glog.V(5).Infof("Synchronizing PersistentVolumeClaim[%s]\n", claim.Name) // claims can be in one of the following states: // // ClaimPending -- default value -- not bound to a claim. A volume that matches the claim may not exist. // ClaimBound -- bound to a volume. claim.Status.VolumeRef != nil currentPhase := claim.Status.Phase nextPhase := currentPhase switch currentPhase { // pending claims await a matching volume case api.ClaimPending: volume, err := volumeIndex.FindBestMatchForClaim(claim) if err != nil { return err } if volume == nil { return fmt.Errorf("A volume match does not exist for persistent claim: %s", claim.Name) } // make a binding reference to the claim. // triggers update of the claim in this controller, which builds claim status claim.Spec.VolumeName = volume.Name // TODO: make this similar to Pod's binding both with BindingREST subresource and GuaranteedUpdate helper in etcd.go claim, err = binderClient.UpdatePersistentVolumeClaim(claim) if err == nil { nextPhase = api.ClaimBound glog.V(5).Infof("PersistentVolumeClaim[%s] is bound\n", claim.Name) } else { // Rollback by unsetting the ClaimRef on the volume pointer. // the volume in the index will be unbound again and ready to be matched. claim.Spec.VolumeName = "" // Rollback by restoring original phase to claim pointer nextPhase = api.ClaimPending return fmt.Errorf("Error updating volume: %+v\n", err) } case api.ClaimBound: volume, err := binderClient.GetPersistentVolume(claim.Spec.VolumeName) if err != nil { return fmt.Errorf("Unexpected error getting persistent volume: %v\n", err) } if volume.Spec.ClaimRef == nil { glog.V(5).Infof("Rebuilding bind on pv.Spec.ClaimRef\n") claimRef, err := api.GetReference(claim) if err != nil { return fmt.Errorf("Unexpected error getting claim reference: %v\n", err) } volume.Spec.ClaimRef = claimRef _, err = binderClient.UpdatePersistentVolume(volume) if err != nil { return fmt.Errorf("Unexpected error saving PersistentVolume.Status: %+v", err) } } // all "actuals" are transferred from PV to PVC so the user knows what // type of volume they actually got for their claim. // Volumes cannot have zero AccessModes, so checking that a claim has access modes // is sufficient to tell us if these values have already been set. if len(claim.Status.AccessModes) == 0 { claim.Status.Phase = api.ClaimBound claim.Status.AccessModes = volume.Spec.AccessModes claim.Status.Capacity = volume.Spec.Capacity _, err := binderClient.UpdatePersistentVolumeClaimStatus(claim) if err != nil { return fmt.Errorf("Unexpected error saving claim status: %+v", err) } } } if currentPhase != nextPhase { claim.Status.Phase = nextPhase binderClient.UpdatePersistentVolumeClaimStatus(claim) } return nil }