diff --git a/pkg/api/types.go b/pkg/api/types.go index 219dbf997c5..d7c0e6e3cf6 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -985,6 +985,13 @@ type ObjectReference struct { FieldPath string `json:"fieldPath,omitempty"` } +type EventSource struct { + // Component from which the event is generated. + Component string `json:"component,omitempty"` + // Host name on which the event is generated. + Host string `json:"host,omitempty"` +} + // Event is a report of an event somewhere in the cluster. // TODO: Decide whether to store these separately or with the object they apply to. type Event struct { @@ -1014,8 +1021,7 @@ type Event struct { Message string `json:"message,omitempty"` // Optional. The component reporting this event. Should be a short machine understandable string. - // TODO: provide exact specification for format. - Source string `json:"source,omitempty"` + Source EventSource `json:"source,omitempty"` // The time at which the client recorded the event. (Time of server receipt is in TypeMeta.) Timestamp util.Time `json:"timestamp,omitempty"` diff --git a/pkg/api/v1beta1/conversion.go b/pkg/api/v1beta1/conversion.go index 9d9789aa74a..f4ff1f5a854 100644 --- a/pkg/api/v1beta1/conversion.go +++ b/pkg/api/v1beta1/conversion.go @@ -548,7 +548,9 @@ func init() { return nil }, - // Event Status -> Condition + // Event Status <-> Condition + // Event Source <-> Source.Component + // Event Host <-> Source.Host // TODO: remove this when it becomes possible to specify a field name conversion on a specific type func(in *newer.Event, out *Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { @@ -560,7 +562,8 @@ func init() { out.Status = in.Condition out.Reason = in.Reason out.Message = in.Message - out.Source = in.Source + out.Source = in.Source.Component + out.Host = in.Source.Host out.Timestamp = in.Timestamp return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, @@ -574,7 +577,8 @@ func init() { out.Condition = in.Status out.Reason = in.Reason out.Message = in.Message - out.Source = in.Source + out.Source.Component = in.Source + out.Source.Host = in.Host out.Timestamp = in.Timestamp return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, diff --git a/pkg/api/v1beta1/types.go b/pkg/api/v1beta1/types.go index a4a747df47d..fa4eebac2f3 100644 --- a/pkg/api/v1beta1/types.go +++ b/pkg/api/v1beta1/types.go @@ -817,6 +817,8 @@ type Event struct { // Optional. The component reporting this event. Should be a short machine understandable string. // TODO: provide exact specification for format. Source string `json:"source,omitempty" description:"component reporting this event; short machine understandable string"` + // Host name on which the event is generated. + Host string `json:"host,omitempty"` // The time at which the client recorded the event. (Time of server receipt is in TypeMeta.) Timestamp util.Time `json:"timestamp,omitempty" description:"time at which the client recorded the event"` diff --git a/pkg/api/v1beta2/conversion.go b/pkg/api/v1beta2/conversion.go index 51874f36eff..10e4ad98b0c 100644 --- a/pkg/api/v1beta2/conversion.go +++ b/pkg/api/v1beta2/conversion.go @@ -464,7 +464,9 @@ func init() { return nil }, - // Event Status -> Condition + // Event Status <-> Condition + // Event Source <-> Source.Component + // Event Host <-> Source.Host // TODO: remove this when it becomes possible to specify a field name conversion on a specific type func(in *newer.Event, out *Event, s conversion.Scope) error { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { @@ -476,7 +478,8 @@ func init() { out.Status = in.Condition out.Reason = in.Reason out.Message = in.Message - out.Source = in.Source + out.Source = in.Source.Component + out.Host = in.Source.Host out.Timestamp = in.Timestamp return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, @@ -490,7 +493,8 @@ func init() { out.Condition = in.Status out.Reason = in.Reason out.Message = in.Message - out.Source = in.Source + out.Source.Component = in.Source + out.Source.Host = in.Host out.Timestamp = in.Timestamp return s.Convert(&in.InvolvedObject, &out.InvolvedObject, 0) }, diff --git a/pkg/api/v1beta2/types.go b/pkg/api/v1beta2/types.go index fcbb4c05a7f..7438f264fa8 100644 --- a/pkg/api/v1beta2/types.go +++ b/pkg/api/v1beta2/types.go @@ -791,6 +791,9 @@ type Event struct { // TODO: provide exact specification for format. Source string `json:"source,omitempty" description:"component reporting this event; short machine understandable string"` + // Host name on which the event is generated. + Host string `json:"host,omitempty"` + // The time at which the client recorded the event. (Time of server receipt is in TypeMeta.) Timestamp util.Time `json:"timestamp,omitempty" description:"time at which the client recorded the event"` } diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index c1f3da6c8d8..daf7b01b42d 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -1003,6 +1003,13 @@ type ObjectReference struct { FieldPath string `json:"fieldPath,omitempty"` } +type EventSource struct { + // Component from which the event is generated. + Component string `json:"component,omitempty"` + // Host name on which the event is generated. + Host string `json:"host,omitempty"` +} + // Event is a report of an event somewhere in the cluster. // TODO: Decide whether to store these separately or with the object they apply to. type Event struct { @@ -1032,8 +1039,7 @@ type Event struct { Message string `json:"message,omitempty"` // Optional. The component reporting this event. Should be a short machine understandable string. - // TODO: provide exact specification for format. - Source string `json:"source,omitempty"` + Source EventSource `json:"source,omitempty"` // The time at which the client recorded the event. (Time of server receipt is in TypeMeta.) Timestamp util.Time `json:"timestamp,omitempty"` diff --git a/pkg/client/record/event.go b/pkg/client/record/event.go index d86aee0340b..0cd6a3df403 100644 --- a/pkg/client/record/event.go +++ b/pkg/client/record/event.go @@ -41,13 +41,13 @@ type EventRecorder interface { // StartRecording starts sending events to recorder. Call once while initializing // your binary. Subsequent calls will be ignored. The return value can be ignored // or used to stop recording, if desired. -func StartRecording(recorder EventRecorder, sourceName string) watch.Interface { +func StartRecording(recorder EventRecorder, source api.EventSource) watch.Interface { return GetEvents(func(event *api.Event) { // Make a copy before modification, because there could be multiple listeners. // Events are safe to copy like this. eventCopy := *event event = &eventCopy - event.Source = sourceName + event.Source = source try := 0 for { try++ diff --git a/pkg/client/record/event_test.go b/pkg/client/record/event_test.go index bf2a62abf5d..8383424a509 100644 --- a/pkg/client/record/event_test.go +++ b/pkg/client/record/event_test.go @@ -89,7 +89,7 @@ func TestEventf(t *testing.T) { Condition: "Running", Reason: "Started", Message: "some verbose message: 1", - Source: "eventTest", + Source: api.EventSource{Component: "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`, }, @@ -114,7 +114,7 @@ func TestEventf(t *testing.T) { Condition: "Running", Reason: "Started", Message: "some verbose message: 1", - Source: "eventTest", + Source: api.EventSource{Component: "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`, }, @@ -142,7 +142,7 @@ func TestEventf(t *testing.T) { return event, nil }, } - recorder := record.StartRecording(&testEvents, "eventTest") + recorder := record.StartRecording(&testEvents, api.EventSource{Component: "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 { @@ -223,7 +223,7 @@ func TestWriteEventError(t *testing.T) { return event, nil }, }, - "eventTest", + api.EventSource{Component: "eventTest"}, ).Stop() for caseName := range table { diff --git a/pkg/kubectl/describe_test.go b/pkg/kubectl/describe_test.go index 178083919d0..e965effd57c 100644 --- a/pkg/kubectl/describe_test.go +++ b/pkg/kubectl/describe_test.go @@ -69,17 +69,17 @@ func TestPodDescribeResultsSorted(t *testing.T) { EventsList: api.EventList{ Items: []api.Event{ { - Source: "kubelet", + Source: api.EventSource{Component: "kubelet"}, Message: "Item 1", Timestamp: util.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), }, { - Source: "scheduler", + Source: api.EventSource{Component: "scheduler"}, Message: "Item 2", Timestamp: util.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), }, { - Source: "kubelet", + Source: api.EventSource{Component: "kubelet"}, Message: "Item 3", Timestamp: util.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), }, diff --git a/pkg/kubectl/resource_printer_test.go b/pkg/kubectl/resource_printer_test.go index ef5effbe003..c8972a054a3 100644 --- a/pkg/kubectl/resource_printer_test.go +++ b/pkg/kubectl/resource_printer_test.go @@ -463,17 +463,17 @@ func TestPrintEventsResultSorted(t *testing.T) { obj := api.EventList{ Items: []api.Event{ { - Source: "kubelet", + Source: api.EventSource{Component: "kubelet"}, Message: "Item 1", Timestamp: util.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), }, { - Source: "scheduler", + Source: api.EventSource{Component: "scheduler"}, Message: "Item 2", Timestamp: util.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), }, { - Source: "kubelet", + Source: api.EventSource{Component: "kubelet"}, Message: "Item 3", Timestamp: util.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), }, diff --git a/pkg/kubectl/sorted_event_list_test.go b/pkg/kubectl/sorted_event_list_test.go index 62716183924..7307a8038ea 100644 --- a/pkg/kubectl/sorted_event_list_test.go +++ b/pkg/kubectl/sorted_event_list_test.go @@ -54,17 +54,17 @@ func TestSortableEvents(t *testing.T) { // Arrange list := SortableEvents([]api.Event{ { - Source: "kubelet", + Source: api.EventSource{Component: "kubelet"}, Message: "Item 1", Timestamp: util.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), }, { - Source: "scheduler", + Source: api.EventSource{Component: "scheduler"}, Message: "Item 2", Timestamp: util.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), }, { - Source: "kubelet", + Source: api.EventSource{Component: "kubelet"}, Message: "Item 3", Timestamp: util.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), }, diff --git a/pkg/kubelet/util.go b/pkg/kubelet/util.go index 5a400df46d3..cc6aa5834ce 100644 --- a/pkg/kubelet/util.go +++ b/pkg/kubelet/util.go @@ -23,6 +23,7 @@ import ( "path" "strconv" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client/record" @@ -132,7 +133,11 @@ func SetupEventSending(authPath string, apiServerList util.StringList) { // Send events to APIserver if there is a client. hostname := util.GetHostname("") glog.Infof("Sending events to APIserver.") - record.StartRecording(apiClient.Events(""), "kubelet:"+hostname) + record.StartRecording(apiClient.Events(""), + api.EventSource{ + Component: "kubelet", + Host: hostname, + }) } } } diff --git a/pkg/registry/event/rest.go b/pkg/registry/event/rest.go index 8ca30daa46f..511ee5e40ee 100644 --- a/pkg/registry/event/rest.go +++ b/pkg/registry/event/rest.go @@ -109,7 +109,7 @@ func (rs *REST) getAttrs(obj runtime.Object) (objLabels, objFields labels.Set, e "condition": event.Condition, "status": event.Condition, // TODO: remove me when we version fields "reason": event.Reason, - "source": event.Source, + "source": event.Source.Component, }, nil } diff --git a/pkg/registry/event/rest_test.go b/pkg/registry/event/rest_test.go index cb9557e3fff..aa73051b7ab 100644 --- a/pkg/registry/event/rest_test.go +++ b/pkg/registry/event/rest_test.go @@ -145,7 +145,7 @@ func TestRESTgetAttrs(t *testing.T) { }, Condition: "Tested", Reason: "ForTesting", - Source: "test", + Source: api.EventSource{Component: "test"}, } label, field, err := rest.getAttrs(eventA) if err != nil { diff --git a/plugin/cmd/kube-scheduler/scheduler.go b/plugin/cmd/kube-scheduler/scheduler.go index 35c250b448f..757e745e11e 100644 --- a/plugin/cmd/kube-scheduler/scheduler.go +++ b/plugin/cmd/kube-scheduler/scheduler.go @@ -22,6 +22,7 @@ import ( "net/http" "strconv" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client/record" _ "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz" @@ -57,7 +58,7 @@ func main() { glog.Fatalf("Invalid API configuration: %v", err) } - record.StartRecording(kubeClient.Events(""), "scheduler") + record.StartRecording(kubeClient.Events(""), api.EventSource{Component: "scheduler"}) go http.ListenAndServe(net.JoinHostPort(address.String(), strconv.Itoa(*port)), nil)