func (w *Worker) DoWork(rawEvent []byte, eventHandlers map[string]EventHandler, apiClient *client.RancherClient, workers chan *Worker) { defer func() { workers <- w }() event := &Event{} err := json.Unmarshal(rawEvent, &event) if err != nil { log.WithFields(log.Fields{ "err": err, }).Error("Error unmarshalling event") return } if event.Name != "ping" { log.WithFields(log.Fields{ "event": string(rawEvent[:]), }).Debug("Processing event.") } unlocker := locks.Lock(event.ResourceId) if unlocker == nil { log.WithFields(log.Fields{ "resourceId": event.ResourceId, }).Debug("Resource locked. Dropping event") return } defer unlocker.Unlock() if fn, ok := eventHandlers[event.Name]; ok { err = fn(event, apiClient) if err != nil { log.WithFields(log.Fields{ "eventName": event.Name, "eventId": event.Id, "resourceId": event.ResourceId, "err": err, }).Error("Error processing event") reply := &client.Publish{ Name: event.ReplyTo, PreviousIds: []string{event.Id}, Transitioning: "error", TransitioningMessage: err.Error(), } _, err := apiClient.Publish.Create(reply) if err != nil { log.WithFields(log.Fields{ "err": err, }).Error("Error sending error-reply") } } } else { log.WithFields(log.Fields{ "eventName": event.Name, }).Warn("No event handler registered for event") } }
func (h *StartHandler) Handle(event *docker.APIEvents) error { // Note: event.ID == container's ID lock := locks.Lock("start." + event.ID) if lock == nil { log.Infof("Container locked. Can't run StartHandler. ID: [%s]", event.ID) return nil } defer lock.Unlock() c, err := h.Client.InspectContainer(event.ID) if err != nil { return err } rancherIP, err := h.getRancherIP(c) if err != nil { return err } if rancherIP == "" { if c.Config.Labels[RancherDns] == "true" { return setupResolvConf(c) } return nil } if !c.State.Running { log.Infof("Container [%s] not running. Can't assign IP [%s].", c.ID, rancherIP) return nil } pid := c.State.Pid log.Infof("Assigning IP [%s], ContainerId [%s], Pid [%v]", rancherIP, event.ID, pid) if err := configureIP(strconv.Itoa(pid), rancherIP); err != nil { // If it stopped running, don't return error c, inspectErr := h.Client.InspectContainer(event.ID) if inspectErr != nil { log.Warn("Failed to inspect container: ", event.ID, inspectErr) return err } if !c.State.Running { log.Infof("Container [%s] not running. Can't assign IP [%s].", c.ID, rancherIP) return nil } return err } return setupResolvConf(c) }
func TestLocking(t *testing.T) { dockerClient := prep(t) eventId := "fake id" lock := locks.Lock("start." + eventId) handler := &StartHandler{Client: dockerClient} event := &docker.APIEvents{ID: eventId} if err := handler.Handle(event); err != nil { // If the lock didn't work, this would fail because of the fake id. t.Fatal(err) } lock.Unlock() if err := handler.Handle(event); err == nil { // Unlocked, should return error t.Fatal(err) } }
func (h *SendToRancherHandler) Handle(event *docker.APIEvents) error { // rancher_state_watcher sends a simulated event to the event router to initiate ip injection. // This event should not be sent. if event.From == simulatedEvent { return nil } // Note: event.ID == container's ID lock := locks.Lock(event.Status + event.ID) if lock == nil { log.Warnf("Container locked. Can't run SendToRancherHandler. Event: [%s], ID: [%s]", event.Status, event.ID) return nil } defer lock.Unlock() container, err := h.client.InspectContainer(event.ID) if err != nil { if _, ok := err.(*docker.NoSuchContainer); !ok { return err } } containerEvent := &rclient.ContainerEvent{ ExternalStatus: event.Status, ExternalId: event.ID, ExternalFrom: event.From, ExternalTimestamp: int64(event.Time), ReportedHostUuid: h.hostUuid, } if container != nil { containerEvent.DockerInspect = container } if _, err := h.rancher.ContainerEvent.Create(containerEvent); err != nil { return err } return nil }