diff --git a/pkg/api/ref.go b/pkg/api/ref.go index b1a46267b16..12cff2ca82b 100644 --- a/pkg/api/ref.go +++ b/pkg/api/ref.go @@ -62,6 +62,16 @@ func GetReference(obj runtime.Object) (*ObjectReference, error) { }, nil } +// GetPartialReference is exactly like GetReference, but allows you to set the FieldPath. +func GetPartialReference(obj runtime.Object, fieldPath string) (*ObjectReference, error) { + ref, err := GetReference(obj) + if err != nil { + return nil, err + } + ref.FieldPath = fieldPath + return ref, nil +} + // Allow clients to preemptively get a reference to an API object and pass it to places that // intend only to get a reference to that object. This simplifies the event recording interface. func (*ObjectReference) IsAnAPIObject() {} diff --git a/pkg/api/ref_test.go b/pkg/api/ref_test.go index 428ff37d7ad..b8097582108 100644 --- a/pkg/api/ref_test.go +++ b/pkg/api/ref_test.go @@ -31,6 +31,7 @@ func TestGetReference(t *testing.T) { table := map[string]struct { obj runtime.Object ref *ObjectReference + fieldPath string shouldErr bool }{ "pod": { @@ -42,12 +43,14 @@ func TestGetReference(t *testing.T) { SelfLink: "/api/v1beta1/pods/foo", }, }, + fieldPath: ".desiredState.containers[0]", ref: &ObjectReference{ Kind: "Pod", APIVersion: "v1beta1", Name: "foo", UID: "bar", ResourceVersion: "42", + FieldPath: ".desiredState.containers[0]", }, }, "serviceList": { @@ -85,7 +88,7 @@ func TestGetReference(t *testing.T) { } for name, item := range table { - ref, err := GetReference(item.obj) + ref, err := GetPartialReference(item.obj, item.fieldPath) if e, a := item.shouldErr, (err != nil); e != a { t.Errorf("%v: expected %v, got %v", name, e, a) continue diff --git a/pkg/client/record/event.go b/pkg/client/record/event.go index 61c969cc543..e962bdcacd2 100644 --- a/pkg/client/record/event.go +++ b/pkg/client/record/event.go @@ -91,7 +91,8 @@ const queueLen = 1000 var events = watch.NewMux(queueLen) // Event constructs an event from the given information and puts it in the queue for sending. -// 'object' is the object this event is about; 'fieldPath', if not "", locates a part of 'object'. +// 'object' is the object this event is about. Event will make a reference-- or you may also +// pass a reference to the object directly. // 'status' is the new status of the object. 'reason' is the reason it now has this status. // Both 'status' and 'reason' should be short and unique; they will be used to automate // handling of events, so imagine people writing switch statements to handle them. You want to @@ -99,13 +100,12 @@ var events = watch.NewMux(queueLen) // 'message' is intended to be human readable. // // The resulting event will be created in the same namespace as the reference object. -func Event(object runtime.Object, fieldPath, status, reason, message string) { +func Event(object runtime.Object, status, reason, message string) { ref, err := api.GetReference(object) if err != nil { - glog.Errorf("Could not construct reference to: %#v due to: %v", object, err) + glog.Errorf("Could not construct reference to: '%#v' due to: '%v'. Will not report event: '%v' '%v' '%v'", object, err, status, reason, message) return } - ref.FieldPath = fieldPath t := util.Now() e := &api.Event{ @@ -124,6 +124,6 @@ func Event(object runtime.Object, fieldPath, status, reason, message string) { } // Eventf is just like Event, but with Sprintf for the message field. -func Eventf(object runtime.Object, fieldPath, status, reason, messageFmt string, args ...interface{}) { - Event(object, fieldPath, status, reason, fmt.Sprintf(messageFmt, args...)) +func Eventf(object runtime.Object, status, reason, messageFmt string, args ...interface{}) { + Event(object, status, reason, fmt.Sprintf(messageFmt, args...)) } diff --git a/pkg/client/record/event_test.go b/pkg/client/record/event_test.go index 69ae0b31513..84d08fcfbef 100644 --- a/pkg/client/record/event_test.go +++ b/pkg/client/record/event_test.go @@ -45,24 +45,28 @@ func (t *testEventRecorder) clearOnEvent() { } func TestEventf(t *testing.T) { + testPod := &api.Pod{ + ObjectMeta: api.ObjectMeta{ + SelfLink: "/api/v1beta1/pods/foo", + Name: "foo", + Namespace: "baz", + UID: "bar", + }, + } + testRef, err := api.GetPartialReference(testPod, "desiredState.manifest.containers[2]") + if err != nil { + t.Fatal(err) + } table := []struct { - obj runtime.Object - fieldPath, status, reason string - messageFmt string - elements []interface{} - expect *api.Event - expectLog string + obj runtime.Object + status, reason string + messageFmt string + elements []interface{} + expect *api.Event + expectLog string }{ { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - SelfLink: "/api/v1beta1/pods/foo", - Name: "foo", - Namespace: "baz", - UID: "bar", - }, - }, - fieldPath: "desiredState.manifest.containers[2]", + obj: testRef, status: "running", reason: "started", messageFmt: "some verbose message: %v", @@ -87,6 +91,31 @@ func TestEventf(t *testing.T) { }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1beta1", ResourceVersion:"", FieldPath:"desiredState.manifest.containers[2]"}): status: 'running', reason: 'started' some verbose message: 1`, }, + { + obj: testPod, + status: "running", + reason: "started", + messageFmt: "some verbose message: %v", + elements: []interface{}{1}, + expect: &api.Event{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Namespace: "baz", + }, + InvolvedObject: api.ObjectReference{ + Kind: "Pod", + Name: "foo", + Namespace: "baz", + UID: "bar", + APIVersion: "v1beta1", + }, + Status: "running", + Reason: "started", + Message: "some verbose message: 1", + Source: "eventTest", + }, + expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1beta1", ResourceVersion:"", FieldPath:""}): status: 'running', reason: 'started' some verbose message: 1`, + }, } for _, item := range table { @@ -120,7 +149,7 @@ func TestEventf(t *testing.T) { called <- struct{}{} }) - record.Eventf(item.obj, item.fieldPath, item.status, item.reason, item.messageFmt, item.elements...) + record.Eventf(item.obj, item.status, item.reason, item.messageFmt, item.elements...) <-called <-called diff --git a/plugin/pkg/scheduler/scheduler.go b/plugin/pkg/scheduler/scheduler.go index 2341e60deff..8bf83b1a3b3 100644 --- a/plugin/pkg/scheduler/scheduler.go +++ b/plugin/pkg/scheduler/scheduler.go @@ -68,7 +68,7 @@ func (s *Scheduler) scheduleOne() { pod := s.config.NextPod() dest, err := s.config.Algorithm.Schedule(*pod, s.config.MinionLister) if err != nil { - record.Eventf(pod, "", string(api.PodPending), "failedScheduling", "Error scheduling: %v", err) + record.Eventf(pod, string(api.PodPending), "failedScheduling", "Error scheduling: %v", err) s.config.Error(pod, err) return } @@ -78,9 +78,9 @@ func (s *Scheduler) scheduleOne() { Host: dest, } if err := s.config.Binder.Bind(b); err != nil { - record.Eventf(pod, "", string(api.PodPending), "failedScheduling", "Binding rejected: %v", err) + record.Eventf(pod, string(api.PodPending), "failedScheduling", "Binding rejected: %v", err) s.config.Error(pod, err) return } - record.Eventf(pod, "", string(api.PodPending), "scheduled", "Successfully assigned %v to %v", pod.Name, dest) + record.Eventf(pod, string(api.PodPending), "scheduled", "Successfully assigned %v to %v", pod.Name, dest) }