diff --git a/pkg/api/api.go b/pkg/api/api.go index 36d9077..72e631d 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -113,6 +113,8 @@ func (api *API) Handler() http.Handler { // EnableUpdates registers the `updates` endpoints func (api *API) EnableUpdates(f updates.InvokedFunc, updateLock *sync.Mutex) { api.route("/v1/updates").post(updates.PostV1(f, updateLock)) + api.route("/v2/updates/apply").post(updates.PostV2Apply(f, updateLock)) + api.route("/v2/updates/check").post(updates.PostV2Check(f, updateLock)) } // EnableMetrics registers the `metrics` endpoints diff --git a/pkg/api/updates/updates_v2.go b/pkg/api/updates/updates_v2.go new file mode 100644 index 0000000..a6dc0ed --- /dev/null +++ b/pkg/api/updates/updates_v2.go @@ -0,0 +1,37 @@ +package updates + +import ( + . "github.com/containrrr/watchtower/pkg/api/prelude" + "github.com/containrrr/watchtower/pkg/filters" + "github.com/containrrr/watchtower/pkg/types" + log "github.com/sirupsen/logrus" + "sync" +) + +func postV2(onInvoke InvokedFunc, updateLock *sync.Mutex, monitorOnly bool) HandlerFunc { + return func(c *Context) Response { + log.Info("Updates triggered by HTTP API request.") + + images := parseImages(c.Request.URL) + + if updateLock.TryLock() { + defer updateLock.Unlock() + + result := onInvoke(func(up *types.UpdateParams) { + up.Filter = filters.FilterByImage(images, up.Filter) + up.MonitorOnly = monitorOnly + }) + return OK(result) + } else { + return Error(ErrUpdateRunning) + } + } +} + +func PostV2Check(onInvoke InvokedFunc, updateLock *sync.Mutex) HandlerFunc { + return postV2(onInvoke, updateLock, true) +} + +func PostV2Apply(onInvoke InvokedFunc, updateLock *sync.Mutex) HandlerFunc { + return postV2(onInvoke, updateLock, false) +} diff --git a/pkg/notifications/json.go b/pkg/notifications/json.go index 20da92b..4d6246c 100644 --- a/pkg/notifications/json.go +++ b/pkg/notifications/json.go @@ -2,8 +2,6 @@ package notifications import ( "encoding/json" - - t "github.com/containrrr/watchtower/pkg/types" ) type jsonMap = map[string]interface{} @@ -20,42 +18,12 @@ func (d Data) MarshalJSON() ([]byte, error) { } } - var report jsonMap - if d.Report != nil { - report = jsonMap{ - `scanned`: marshalReports(d.Report.Scanned()), - `updated`: marshalReports(d.Report.Updated()), - `failed`: marshalReports(d.Report.Failed()), - `skipped`: marshalReports(d.Report.Skipped()), - `stale`: marshalReports(d.Report.Stale()), - `fresh`: marshalReports(d.Report.Fresh()), - } - } - return json.Marshal(jsonMap{ - `report`: report, + `report`: d.Report, `title`: d.Title, `host`: d.Host, `entries`: entries, }) } -func marshalReports(reports []t.ContainerReport) []jsonMap { - jsonReports := make([]jsonMap, len(reports)) - for i, report := range reports { - jsonReports[i] = jsonMap{ - `id`: report.ID().ShortID(), - `name`: report.Name(), - `currentImageId`: report.CurrentImageID().ShortID(), - `latestImageId`: report.LatestImageID().ShortID(), - `imageName`: report.ImageName(), - `state`: report.State(), - } - if errorMessage := report.Error(); errorMessage != "" { - jsonReports[i][`error`] = errorMessage - } - } - return jsonReports -} - var _ json.Marshaler = &Data{} diff --git a/pkg/session/report.go b/pkg/session/report.go index 707eb91..1af1918 100644 --- a/pkg/session/report.go +++ b/pkg/session/report.go @@ -1,6 +1,7 @@ package session import ( + "encoding/json" "sort" "github.com/containrrr/watchtower/pkg/types" @@ -61,6 +62,38 @@ func (r *report) All() []types.ContainerReport { return all } +type jsonMap = map[string]interface{} + +// MarshalJSON implements json.Marshaler +func (r *report) MarshalJSON() ([]byte, error) { + return json.Marshal(jsonMap{ + `scanned`: marshalReports(r.Scanned()), + `updated`: marshalReports(r.Updated()), + `failed`: marshalReports(r.Failed()), + `skipped`: marshalReports(r.Skipped()), + `stale`: marshalReports(r.Stale()), + `fresh`: marshalReports(r.Fresh()), + }) +} + +func marshalReports(reports []types.ContainerReport) []jsonMap { + jsonReports := make([]jsonMap, len(reports)) + for i, report := range reports { + jsonReports[i] = jsonMap{ + `id`: report.ID().ShortID(), + `name`: report.Name(), + `currentImageId`: report.CurrentImageID().ShortID(), + `latestImageId`: report.LatestImageID().ShortID(), + `imageName`: report.ImageName(), + `state`: report.State(), + } + if errorMessage := report.Error(); errorMessage != "" { + jsonReports[i][`error`] = errorMessage + } + } + return jsonReports +} + // NewReport creates a types.Report from the supplied Progress func NewReport(progress Progress) types.Report { report := &report{