// containerRef returns an *api.ObjectReference which references the given container within the // given pod. Returns an error if the reference can't be constructed or the container doesn't // actually belong to the pod. // TODO: Pods that came to us by static config or over HTTP have no selfLink set, which makes // this fail and log an error. Figure out how we want to identify these pods to the rest of the // system. func containerRef(pod *api.BoundPod, container *api.Container) (*api.ObjectReference, error) { fieldPath, err := fieldPath(pod, container) if err != nil { // TODO: figure out intelligent way to refer to containers that we implicitly // start (like the network container). This is not a good way, ugh. fieldPath = "implicitly required container " + container.Name } ref, err := api.GetPartialReference(pod, fieldPath) if err != nil { return nil, err } return ref, nil }
func TestEventf(t *testing.T) { testPod := &api.Pod{ ObjectMeta: api.ObjectMeta{ SelfLink: "/api/version/pods/foo", Name: "foo", Namespace: "baz", UID: "bar", }, } testPod2 := &api.Pod{ ObjectMeta: api.ObjectMeta{ SelfLink: "/api/version/pods/foo", Name: "foo", Namespace: "baz", UID: "differentUid", }, } testRef, err := api.GetPartialReference(testPod, "desiredState.manifest.containers[2]") testRef2, err := api.GetPartialReference(testPod2, "desiredState.manifest.containers[3]") if err != nil { t.Fatal(err) } table := []struct { obj runtime.Object reason string messageFmt string elements []interface{} expect *api.Event expectLog string expectUpdate bool }{ { obj: testRef, 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: "version", FieldPath: "desiredState.manifest.containers[2]", }, Reason: "Started", Message: "some verbose message: 1", Source: api.EventSource{Component: "eventTest"}, Count: 1, }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"desiredState.manifest.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { obj: testPod, reason: "Killed", messageFmt: "some other 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: "version", }, Reason: "Killed", Message: "some other verbose message: 1", Source: api.EventSource{Component: "eventTest"}, Count: 1, }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): reason: 'Killed' some other verbose message: 1`, expectUpdate: false, }, { obj: testRef, 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: "version", FieldPath: "desiredState.manifest.containers[2]", }, Reason: "Started", Message: "some verbose message: 1", Source: api.EventSource{Component: "eventTest"}, Count: 2, }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"desiredState.manifest.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { obj: testRef2, 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: "differentUid", APIVersion: "version", FieldPath: "desiredState.manifest.containers[3]", }, Reason: "Started", Message: "some verbose message: 1", Source: api.EventSource{Component: "eventTest"}, Count: 1, }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"desiredState.manifest.containers[3]"}): reason: 'Started' some verbose message: 1`, expectUpdate: false, }, { obj: testRef, 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: "version", FieldPath: "desiredState.manifest.containers[2]", }, Reason: "Started", Message: "some verbose message: 1", Source: api.EventSource{Component: "eventTest"}, Count: 3, }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"desiredState.manifest.containers[2]"}): reason: 'Started' some verbose message: 1`, expectUpdate: true, }, { obj: testRef2, reason: "Stopped", 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: "differentUid", APIVersion: "version", FieldPath: "desiredState.manifest.containers[3]", }, Reason: "Stopped", Message: "some verbose message: 1", Source: api.EventSource{Component: "eventTest"}, Count: 1, }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"desiredState.manifest.containers[3]"}): reason: 'Stopped' some verbose message: 1`, expectUpdate: false, }, { obj: testRef2, reason: "Stopped", 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: "differentUid", APIVersion: "version", FieldPath: "desiredState.manifest.containers[3]", }, Reason: "Stopped", Message: "some verbose message: 1", Source: api.EventSource{Component: "eventTest"}, Count: 2, }, expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"desiredState.manifest.containers[3]"}): reason: 'Stopped' some verbose message: 1`, expectUpdate: true, }, } for _, item := range table { called := make(chan struct{}) testEvents := testEventSink{ OnCreate: func(event *api.Event) (*api.Event, error) { returnEvent, _ := validateEvent(event, item.expect, t) if item.expectUpdate { t.Errorf("Expected event update(), got event create()") } called <- struct{}{} return returnEvent, nil }, OnUpdate: func(event *api.Event) (*api.Event, error) { returnEvent, _ := validateEvent(event, item.expect, t) if !item.expectUpdate { t.Errorf("Expected event create(), got event update()") } called <- struct{}{} return returnEvent, nil }, } eventBroadcaster := NewBroadcaster() sinkWatcher := eventBroadcaster.StartRecordingToSink(&testEvents) logWatcher1 := eventBroadcaster.StartLogging(t.Logf) // Prove that it is useful logWatcher2 := eventBroadcaster.StartLogging(func(formatter string, args ...interface{}) { if e, a := item.expectLog, fmt.Sprintf(formatter, args...); e != a { t.Errorf("Expected '%v', got '%v'", e, a) } called <- struct{}{} }) recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "eventTest"}) recorder.Eventf(item.obj, item.reason, item.messageFmt, item.elements...) <-called <-called sinkWatcher.Stop() logWatcher1.Stop() logWatcher2.Stop() } }
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 status, reason string messageFmt string elements []interface{} expect *api.Event expectLog string }{ { obj: testRef, 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", FieldPath: "desiredState.manifest.containers[2]", }, 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:"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 { called := make(chan struct{}) testEvents := testEventRecorder{ OnEvent: func(event *api.Event) (*api.Event, error) { a := *event // Just check that the timestamp was set. if a.Timestamp.IsZero() { t.Errorf("timestamp wasn't set") } a.Timestamp = item.expect.Timestamp // Check that name has the right prefix. if n, en := a.Name, item.expect.Name; !strings.HasPrefix(n, en) { t.Errorf("Name '%v' does not contain prefix '%v'", n, en) } a.Name = item.expect.Name if e, a := item.expect, &a; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectDiff(e, a)) } called <- struct{}{} return event, nil }, } recorder := record.StartRecording(&testEvents, "eventTest") logger := record.StartLogging(t.Logf) // Prove that it is useful logger2 := record.StartLogging(func(formatter string, args ...interface{}) { if e, a := item.expectLog, fmt.Sprintf(formatter, args...); e != a { t.Errorf("Expected '%v', got '%v'", e, a) } called <- struct{}{} }) record.Eventf(item.obj, item.status, item.reason, item.messageFmt, item.elements...) <-called <-called recorder.Stop() logger.Stop() logger2.Stop() } }