Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding parameter to allow containers to be updated only after some number of days have passed since the new image has been published #1884

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add metrics and progress report capabilities for deferred items seper…
…ate from other statuses
pjdubya committed Jan 8, 2024
commit 3c0441b94c9188419f34a6791f0a6f7b6ef276d3
31 changes: 20 additions & 11 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -10,28 +10,31 @@ var metrics *Metrics

// Metric is the data points of a single scan
type Metric struct {
Scanned int
Updated int
Failed int
Scanned int
Updated int
Deferred int
Failed int
}

// Metrics is the handler processing all individual scan metrics
type Metrics struct {
channel chan *Metric
scanned prometheus.Gauge
updated prometheus.Gauge
failed prometheus.Gauge
total prometheus.Counter
skipped prometheus.Counter
channel chan *Metric
scanned prometheus.Gauge
updated prometheus.Gauge
deferred prometheus.Gauge
failed prometheus.Gauge
total prometheus.Counter
skipped prometheus.Counter
}

// NewMetric returns a Metric with the counts taken from the appropriate types.Report fields
func NewMetric(report types.Report) *Metric {
return &Metric{
Scanned: len(report.Scanned()),
// Note: This is for backwards compatibility. ideally, stale containers should be counted separately
Updated: len(report.Updated()) + len(report.Stale()),
Failed: len(report.Failed()),
Updated: len(report.Updated()) + len(report.Stale()),
Deferred: len(report.Deferred()),
Failed: len(report.Failed()),
}
}

@@ -60,6 +63,10 @@ func Default() *Metrics {
Name: "watchtower_containers_updated",
Help: "Number of containers updated by watchtower during the last scan",
}),
deferred: promauto.NewGauge(prometheus.GaugeOpts{
Name: "watchtower_containers_deferred",
Help: "Number of containers deferred by watchtower during the last scan",
}),
failed: promauto.NewGauge(prometheus.GaugeOpts{
Name: "watchtower_containers_failed",
Help: "Number of containers where update failed during the last scan",
@@ -95,13 +102,15 @@ func (metrics *Metrics) HandleUpdate(channel <-chan *Metric) {
metrics.skipped.Inc()
metrics.scanned.Set(0)
metrics.updated.Set(0)
metrics.deferred.Set(0)
metrics.failed.Set(0)
continue
}
// Update metrics with the new values
metrics.total.Inc()
metrics.scanned.Set(float64(change.Scanned))
metrics.updated.Set(float64(change.Updated))
metrics.deferred.Set(float64(change.Deferred))
metrics.failed.Set(float64(change.Failed))
}
}
13 changes: 7 additions & 6 deletions pkg/notifications/json.go
Original file line number Diff line number Diff line change
@@ -23,12 +23,13 @@ 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()),
`scanned`: marshalReports(d.Report.Scanned()),
`updated`: marshalReports(d.Report.Updated()),
`deferred`: marshalReports(d.Report.Deferred()),
`failed`: marshalReports(d.Report.Failed()),
`skipped`: marshalReports(d.Report.Skipped()),
`stale`: marshalReports(d.Report.Stale()),
`fresh`: marshalReports(d.Report.Fresh()),
}
}

3 changes: 2 additions & 1 deletion pkg/notifications/json_test.go
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ var _ = Describe("JSON template", func() {
],
"host": "Mock",
"report": {
"deferred": [],
"failed": [
{
"currentImageId": "01d210000000",
@@ -110,7 +111,7 @@ var _ = Describe("JSON template", func() {
},
"title": "Watchtower updates on Mock"
}`
data := mockDataFromStates(s.UpdatedState, s.FreshState, s.FailedState, s.SkippedState, s.UpdatedState)
data := mockDataFromStates(s.UpdatedState, s.DeferredState, s.FreshState, s.FailedState, s.SkippedState, s.UpdatedState)
Expect(getTemplatedResult(`json.v1`, false, data)).To(MatchJSON(expected))
})
})
2 changes: 2 additions & 0 deletions pkg/notifications/preview/data/data.go
Original file line number Diff line number Diff line change
@@ -72,6 +72,8 @@ func (pb *previewData) addContainer(c containerStatus) {
pb.report.scanned = append(pb.report.scanned, &c)
case UpdatedState:
pb.report.updated = append(pb.report.updated, &c)
case DeferredState:
pb.report.deferred = append(pb.report.deferred, &c)
case FailedState:
pb.report.failed = append(pb.report.failed, &c)
case SkippedState:
32 changes: 20 additions & 12 deletions pkg/notifications/preview/data/report.go
Original file line number Diff line number Diff line change
@@ -10,12 +10,13 @@ import (
type State string

const (
ScannedState State = "scanned"
UpdatedState State = "updated"
FailedState State = "failed"
SkippedState State = "skipped"
StaleState State = "stale"
FreshState State = "fresh"
ScannedState State = "scanned"
UpdatedState State = "updated"
DeferredState State = "deferred"
FailedState State = "failed"
SkippedState State = "skipped"
StaleState State = "stale"
FreshState State = "fresh"
)

// StatesFromString parses a string of state characters and returns a slice of the corresponding report states
@@ -27,6 +28,8 @@ func StatesFromString(str string) []State {
states = append(states, ScannedState)
case 'u':
states = append(states, UpdatedState)
case 'd':
states = append(states, DeferredState)
case 'e':
states = append(states, FailedState)
case 'k':
@@ -43,12 +46,13 @@ func StatesFromString(str string) []State {
}

type report struct {
scanned []types.ContainerReport
updated []types.ContainerReport
failed []types.ContainerReport
skipped []types.ContainerReport
stale []types.ContainerReport
fresh []types.ContainerReport
scanned []types.ContainerReport
updated []types.ContainerReport
deferred []types.ContainerReport
failed []types.ContainerReport
skipped []types.ContainerReport
stale []types.ContainerReport
fresh []types.ContainerReport
}

func (r *report) Scanned() []types.ContainerReport {
@@ -57,6 +61,9 @@ func (r *report) Scanned() []types.ContainerReport {
func (r *report) Updated() []types.ContainerReport {
return r.updated
}
func (r *report) Deferred() []types.ContainerReport {
return r.deferred
}
func (r *report) Failed() []types.ContainerReport {
return r.failed
}
@@ -87,6 +94,7 @@ func (r *report) All() []types.ContainerReport {
}

appendUnique(r.updated)
appendUnique(r.deferred)
appendUnique(r.failed)
appendUnique(r.skipped)
appendUnique(r.stale)
3 changes: 3 additions & 0 deletions pkg/session/container_status.go
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ const (
SkippedState
ScannedState
UpdatedState
DeferredState
FailedState
FreshState
StaleState
@@ -70,6 +71,8 @@ func (u *ContainerStatus) State() string {
return "Scanned"
case UpdatedState:
return "Updated"
case DeferredState:
return "Deferred"
case FailedState:
return "Failed"
case FreshState:
5 changes: 5 additions & 0 deletions pkg/session/progress.go
Original file line number Diff line number Diff line change
@@ -50,6 +50,11 @@ func (m Progress) MarkForUpdate(containerID types.ContainerID) {
m[containerID].state = UpdatedState
}

// MarkForUpdate marks the container identified by containerID for deferral
func (m Progress) MarkDeferred(containerID types.ContainerID) {
m[containerID].state = DeferredState
}

// Report creates a new Report from a Progress instance
func (m Progress) Report() types.Report {
return NewReport(m)
35 changes: 23 additions & 12 deletions pkg/session/report.go
Original file line number Diff line number Diff line change
@@ -7,12 +7,13 @@ import (
)

type report struct {
scanned []types.ContainerReport
updated []types.ContainerReport
failed []types.ContainerReport
skipped []types.ContainerReport
stale []types.ContainerReport
fresh []types.ContainerReport
scanned []types.ContainerReport
updated []types.ContainerReport
deferred []types.ContainerReport
failed []types.ContainerReport
skipped []types.ContainerReport
stale []types.ContainerReport
fresh []types.ContainerReport
}

func (r *report) Scanned() []types.ContainerReport {
@@ -21,6 +22,9 @@ func (r *report) Scanned() []types.ContainerReport {
func (r *report) Updated() []types.ContainerReport {
return r.updated
}
func (r *report) Deferred() []types.ContainerReport {
return r.deferred
}
func (r *report) Failed() []types.ContainerReport {
return r.failed
}
@@ -50,6 +54,7 @@ func (r *report) All() []types.ContainerReport {
}

appendUnique(r.updated)
appendUnique(r.deferred)
appendUnique(r.failed)
appendUnique(r.skipped)
appendUnique(r.stale)
@@ -64,12 +69,13 @@ func (r *report) All() []types.ContainerReport {
// NewReport creates a types.Report from the supplied Progress
func NewReport(progress Progress) types.Report {
report := &report{
scanned: []types.ContainerReport{},
updated: []types.ContainerReport{},
failed: []types.ContainerReport{},
skipped: []types.ContainerReport{},
stale: []types.ContainerReport{},
fresh: []types.ContainerReport{},
scanned: []types.ContainerReport{},
updated: []types.ContainerReport{},
deferred: []types.ContainerReport{},
failed: []types.ContainerReport{},
skipped: []types.ContainerReport{},
stale: []types.ContainerReport{},
fresh: []types.ContainerReport{},
}

for _, update := range progress {
@@ -88,16 +94,21 @@ func NewReport(progress Progress) types.Report {
switch update.state {
case UpdatedState:
report.updated = append(report.updated, update)
case DeferredState:
report.deferred = append(report.deferred, update)
case FailedState:
report.failed = append(report.failed, update)
default:
// TODO: should this be changed to something lke UnknownState since it shouldn't be possible for a container
// to be stale but its state to not be either UpdatedState, DeferredState, or FailedState?
update.state = StaleState
report.stale = append(report.stale, update)
}
}

sort.Sort(sortableContainers(report.scanned))
sort.Sort(sortableContainers(report.updated))
sort.Sort(sortableContainers(report.deferred))
sort.Sort(sortableContainers(report.failed))
sort.Sort(sortableContainers(report.skipped))
sort.Sort(sortableContainers(report.stale))
1 change: 1 addition & 0 deletions pkg/types/report.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ package types
type Report interface {
Scanned() []ContainerReport
Updated() []ContainerReport
Deferred() []ContainerReport
Failed() []ContainerReport
Skipped() []ContainerReport
Stale() []ContainerReport
2 changes: 1 addition & 1 deletion tplprev/main.go
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ func main() {
var states string
var entries string

flag.StringVar(&states, "states", "cccuuueeekkktttfff", "sCanned, Updated, failEd, sKipped, sTale, Fresh")
flag.StringVar(&states, "states", "cccuuudddeeekkktttfff", "sCanned, Updated, Deferred, failEd, sKipped, sTale, Fresh")
flag.StringVar(&entries, "entries", "ewwiiidddd", "Fatal,Error,Warn,Info,Debug,Trace")

flag.Parse()