feat(api): add updates API v2

feat/extended-api
nils måsén 1 year ago
parent 47091761a5
commit 4a922f5a32

@ -113,6 +113,8 @@ func (api *API) Handler() http.Handler {
// EnableUpdates registers the `updates` endpoints // EnableUpdates registers the `updates` endpoints
func (api *API) EnableUpdates(f updates.InvokedFunc, updateLock *sync.Mutex) { func (api *API) EnableUpdates(f updates.InvokedFunc, updateLock *sync.Mutex) {
api.route("/v1/updates").post(updates.PostV1(f, updateLock)) 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 // EnableMetrics registers the `metrics` endpoints

@ -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)
}

@ -2,8 +2,6 @@ package notifications
import ( import (
"encoding/json" "encoding/json"
t "github.com/containrrr/watchtower/pkg/types"
) )
type jsonMap = map[string]interface{} 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{ return json.Marshal(jsonMap{
`report`: report, `report`: d.Report,
`title`: d.Title, `title`: d.Title,
`host`: d.Host, `host`: d.Host,
`entries`: entries, `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{} var _ json.Marshaler = &Data{}

@ -1,6 +1,7 @@
package session package session
import ( import (
"encoding/json"
"sort" "sort"
"github.com/containrrr/watchtower/pkg/types" "github.com/containrrr/watchtower/pkg/types"
@ -61,6 +62,38 @@ func (r *report) All() []types.ContainerReport {
return all 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 // NewReport creates a types.Report from the supplied Progress
func NewReport(progress Progress) types.Report { func NewReport(progress Progress) types.Report {
report := &report{ report := &report{

Loading…
Cancel
Save