|
@@ -3,6 +3,7 @@ package server
|
|
import (
|
|
import (
|
|
"bufio"
|
|
"bufio"
|
|
"bytes"
|
|
"bytes"
|
|
|
|
+ "time"
|
|
|
|
|
|
"encoding/base64"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"encoding/json"
|
|
@@ -23,7 +24,9 @@ import (
|
|
"github.com/docker/docker/daemon"
|
|
"github.com/docker/docker/daemon"
|
|
"github.com/docker/docker/daemon/networkdriver/bridge"
|
|
"github.com/docker/docker/daemon/networkdriver/bridge"
|
|
"github.com/docker/docker/engine"
|
|
"github.com/docker/docker/engine"
|
|
|
|
+ "github.com/docker/docker/pkg/jsonmessage"
|
|
"github.com/docker/docker/pkg/parsers"
|
|
"github.com/docker/docker/pkg/parsers"
|
|
|
|
+ "github.com/docker/docker/pkg/parsers/filters"
|
|
"github.com/docker/docker/pkg/stdcopy"
|
|
"github.com/docker/docker/pkg/stdcopy"
|
|
"github.com/docker/docker/pkg/streamformatter"
|
|
"github.com/docker/docker/pkg/streamformatter"
|
|
"github.com/docker/docker/pkg/version"
|
|
"github.com/docker/docker/pkg/version"
|
|
@@ -324,13 +327,104 @@ func getEvents(eng *engine.Engine, version version.Version, w http.ResponseWrite
|
|
if err := parseForm(r); err != nil {
|
|
if err := parseForm(r); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
+ var since int64 = -1
|
|
|
|
+ if r.Form.Get("since") != "" {
|
|
|
|
+ s, err := strconv.ParseInt(r.Form.Get("since"), 10, 64)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ since = s
|
|
|
|
+ }
|
|
|
|
|
|
- var job = eng.Job("events")
|
|
|
|
- streamJSON(job, w, true)
|
|
|
|
- job.Setenv("since", r.Form.Get("since"))
|
|
|
|
- job.Setenv("until", r.Form.Get("until"))
|
|
|
|
- job.Setenv("filters", r.Form.Get("filters"))
|
|
|
|
- return job.Run()
|
|
|
|
|
|
+ var until int64 = -1
|
|
|
|
+ if r.Form.Get("until") != "" {
|
|
|
|
+ u, err := strconv.ParseInt(r.Form.Get("until"), 10, 64)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ until = u
|
|
|
|
+ }
|
|
|
|
+ timer := time.NewTimer(0)
|
|
|
|
+ timer.Stop()
|
|
|
|
+ if until > 0 {
|
|
|
|
+ dur := time.Unix(until, 0).Sub(time.Now())
|
|
|
|
+ timer = time.NewTimer(dur)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ef, err := filters.FromParam(r.Form.Get("filters"))
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ isFiltered := func(field string, filter []string) bool {
|
|
|
|
+ if len(filter) == 0 {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ for _, v := range filter {
|
|
|
|
+ if v == field {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ if strings.Contains(field, ":") {
|
|
|
|
+ image := strings.Split(field, ":")
|
|
|
|
+ if image[0] == v {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ d := getDaemon(eng)
|
|
|
|
+ es := d.EventsService
|
|
|
|
+ w.Header().Set("Content-Type", "application/json")
|
|
|
|
+ enc := json.NewEncoder(utils.NewWriteFlusher(w))
|
|
|
|
+
|
|
|
|
+ getContainerId := func(cn string) string {
|
|
|
|
+ c, err := d.Get(cn)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return ""
|
|
|
|
+ }
|
|
|
|
+ return c.ID
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sendEvent := func(ev *jsonmessage.JSONMessage) error {
|
|
|
|
+ //incoming container filter can be name,id or partial id, convert and replace as a full container id
|
|
|
|
+ for i, cn := range ef["container"] {
|
|
|
|
+ ef["container"][i] = getContainerId(cn)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if isFiltered(ev.Status, ef["event"]) || isFiltered(ev.From, ef["image"]) ||
|
|
|
|
+ isFiltered(ev.ID, ef["container"]) {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return enc.Encode(ev)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ current, l := es.Subscribe()
|
|
|
|
+ defer es.Evict(l)
|
|
|
|
+ for _, ev := range current {
|
|
|
|
+ if ev.Time < since {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ if err := sendEvent(ev); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for {
|
|
|
|
+ select {
|
|
|
|
+ case ev := <-l:
|
|
|
|
+ jev, ok := ev.(*jsonmessage.JSONMessage)
|
|
|
|
+ if !ok {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ if err := sendEvent(jev); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ case <-timer.C:
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
func getImagesHistory(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
func getImagesHistory(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|