func validateEvent(actualEvent *api.Event, expectedEvent *api.Event, t *testing.T) (*api.Event, error) { expectCompression := expectedEvent.Count > 1 // Just check that the timestamp was set. if actualEvent.FirstTimestamp.IsZero() || actualEvent.LastTimestamp.IsZero() { t.Errorf("timestamp wasn't set: %#v", *actualEvent) } if actualEvent.FirstTimestamp.Equal(actualEvent.LastTimestamp.Time) { if expectCompression { t.Errorf("FirstTimestamp (%q) and LastTimestamp (%q) must be equal to indicate only one occurance of the event, but were different. Actual Event: %#v", actualEvent.FirstTimestamp, actualEvent.LastTimestamp, *actualEvent) } } else { if !expectCompression { t.Errorf("FirstTimestamp (%q) and LastTimestamp (%q) must be different to indicate event compression happened, but were the same. Actual Event: %#v", actualEvent.FirstTimestamp, actualEvent.LastTimestamp, *actualEvent) } } actualFirstTimestamp := actualEvent.FirstTimestamp actualLastTimestamp := actualEvent.LastTimestamp // Temp clear time stamps for comparison because actual values don't matter for comparison actualEvent.FirstTimestamp = expectedEvent.FirstTimestamp actualEvent.LastTimestamp = expectedEvent.LastTimestamp // Check that name has the right prefix. if n, en := actualEvent.Name, expectedEvent.Name; !strings.HasPrefix(n, en) { t.Errorf("Name '%v' does not contain prefix '%v'", n, en) } actualEvent.Name = expectedEvent.Name if e, a := expectedEvent, actualEvent; !reflect.DeepEqual(e, a) { t.Errorf("diff: %s", util.ObjectGoPrintDiff(e, a)) } actualEvent.FirstTimestamp = actualFirstTimestamp actualEvent.LastTimestamp = actualLastTimestamp return actualEvent, nil }
// Log an event to the etcd backend. func (kl *Kubelet) LogEvent(event *api.Event) error { if kl.EtcdClient == nil { return fmt.Errorf("no etcd client connection.") } event.Timestamp = time.Now().Unix() data, err := json.Marshal(event) if err != nil { return err } var response *etcd.Response response, err = kl.EtcdClient.AddChild(fmt.Sprintf("/events/%s", event.Container.Name), string(data), 60*60*48 /* 2 days */) // TODO(bburns) : examine response here. if err != nil { glog.Errorf("Error writing event: %s\n", err) if response != nil { glog.Infof("Response was: %#v\n", *response) } } return err }
// recordEvent attempts to write event to a sink. It returns true if the event // was successfully recorded or discarded, false if it should be retried. // If updateExistingEvent is false, it creates a new event, otherwise it updates // existing event. func recordEvent(sink EventSink, event *api.Event, updateExistingEvent bool) bool { var newEvent *api.Event var err error if updateExistingEvent { newEvent, err = sink.Update(event) } // Update can fail because the event may have been removed and it no longer exists. if !updateExistingEvent || (updateExistingEvent && isKeyNotFoundError(err)) { // Making sure that ResourceVersion is empty on creation event.ResourceVersion = "" newEvent, err = sink.Create(event) } if err == nil { addOrUpdateEvent(newEvent) return true } // If we can't contact the server, then hold everything while we keep trying. // Otherwise, something about the event is malformed and we should abandon it. switch err.(type) { case *client.RequestConstructionError: // We will construct the request the same next time, so don't keep trying. glog.Errorf("Unable to construct event '%#v': '%v' (will not retry!)", event, err) return true case *errors.StatusError: if errors.IsAlreadyExists(err) { glog.V(5).Infof("Server rejected event '%#v': '%v' (will not retry!)", event, err) } else { glog.Errorf("Server rejected event '%#v': '%v' (will not retry!)", event, err) } return true case *errors.UnexpectedObjectError: // We don't expect this; it implies the server's response didn't match a // known pattern. Go ahead and retry. default: // This case includes actual http transport errors. Go ahead and retry. } glog.Errorf("Unable to write event: '%v' (may retry after sleeping)", err) return false }