Skip to content

Commit

Permalink
Present check plugin info on webpage
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuckal777 committed Jan 11, 2024
1 parent 85b5992 commit be523f2
Show file tree
Hide file tree
Showing 14 changed files with 42 additions and 18 deletions.
8 changes: 8 additions & 0 deletions plugin/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,18 @@ func Passed(info map[string]any) CheckResult {
return CheckResult{Passed: true, Info: info}
}

func PassedWithReason(reason string) CheckResult {
return CheckResult{Passed: true, Info: map[string]any{"reason": reason}}
}

func Failed(info map[string]any) CheckResult {
return CheckResult{Passed: false, Info: info}
}

func FailedWithReason(reason string) CheckResult {
return CheckResult{Passed: false, Info: map[string]any{"reason": reason}}
}

// Checker is the interface that check plugins need to implement.
// Check plugins have to be idempotent, as they are invoked multiple times.
// A zero-initialized check plugin should not actually work as it is used
Expand Down
6 changes: 3 additions & 3 deletions plugin/impl/affinity.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (a *Affinity) Check(params plugin.Parameters) (plugin.CheckResult, error) {
return plugin.Failed(nil), err
}
if operationalCount >= a.MinOperational {
return plugin.Passed(map[string]any{"reason": "minOperational exceeded"}), nil
return plugin.PassedWithReason("minOperational exceeded"), nil
}
}
currentAffinity, err := hasAffinityPod(params.Node.Name, &params)
Expand All @@ -81,7 +81,7 @@ func (a *Affinity) Check(params plugin.Parameters) (plugin.CheckResult, error) {
}
// current node does not have any relevant pods, so pass
if !currentAffinity {
return plugin.Passed(nil), nil
return plugin.PassedWithReason("no pods with affinity"), nil
}
return checkOther(&params, nodeStates)
}
Expand Down Expand Up @@ -137,7 +137,7 @@ func checkOther(params *plugin.Parameters, nodeStates nodeStateMap) (plugin.Chec
return plugin.Failed(nil), fmt.Errorf("failed to check if node %v has affinity pods: %w", params.Node.Name, err)
}
if !nodeAffinity {
return plugin.Failed(nil), nil
return plugin.FailedWithReason("pods without affinity on: " + node.Name), nil
}
}
// all other nodes have relevant pods as well, so pass
Expand Down
4 changes: 3 additions & 1 deletion plugin/impl/annotation.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package impl

import (
"fmt"

"github.com/sapcc/maintenance-controller/plugin"
"github.com/sapcc/ucfgwrap"
)
Expand Down Expand Up @@ -51,7 +53,7 @@ func (h *HasAnnotation) ID() string {
func (h *HasAnnotation) Check(params plugin.Parameters) (plugin.CheckResult, error) {
val, ok := params.Node.Annotations[h.Key]
if !ok {
return plugin.Failed(nil), nil
return plugin.FailedWithReason(fmt.Sprintf("annotation %s not present", h.Key)), nil
}
if h.Value == "" {
return plugin.Passed(nil), nil
Expand Down
4 changes: 3 additions & 1 deletion plugin/impl/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package impl

import (
"fmt"

"github.com/sapcc/maintenance-controller/plugin"
"github.com/sapcc/ucfgwrap"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -55,7 +57,7 @@ func (c *Condition) Check(params plugin.Parameters) (plugin.CheckResult, error)
return plugin.CheckResult{Passed: condition.Status == v1.ConditionStatus(c.Status)}, nil
}
}
return plugin.Failed(nil), nil
return plugin.FailedWithReason(fmt.Sprintf("condition %s not present", c.Type)), nil
}

func (c *Condition) OnTransition(params plugin.Parameters) error {
Expand Down
4 changes: 2 additions & 2 deletions plugin/impl/kubernikus.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ func (kc *KubernikusCount) Check(params plugin.Parameters) (plugin.CheckResult,
specCount += nodePool.Size
}
if len(nodeList.Items) >= specCount {
return plugin.Passed(nil), nil
return plugin.PassedWithReason("found equal or more nodes than specified by nodepool"), nil
}
return plugin.Failed(nil), nil
return plugin.FailedWithReason("found less nodes than specified by nodepool"), nil
}

func (kc *KubernikusCount) fetchKluster(params *plugin.Parameters) (kluster, error) {
Expand Down
4 changes: 3 additions & 1 deletion plugin/impl/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package impl

import (
"fmt"

"github.com/sapcc/maintenance-controller/plugin"
"github.com/sapcc/ucfgwrap"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -51,7 +53,7 @@ func (h *HasLabel) ID() string {
func (h *HasLabel) Check(params plugin.Parameters) (plugin.CheckResult, error) {
val, ok := params.Node.Labels[h.Key]
if !ok {
return plugin.Failed(nil), nil
return plugin.FailedWithReason(fmt.Sprintf("label %s not present", h.Key)), nil
}
if h.Value == "" {
return plugin.Passed(nil), nil
Expand Down
5 changes: 3 additions & 2 deletions plugin/impl/maxmaintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ func (m *MaxMaintenance) checkInternal(params plugin.Parameters, nodes []corev1.
}
nodes = filtered
}
info := map[string]any{"maintained": len(nodes), "max": m.MaxNodes}
if len(nodes) >= m.MaxNodes {
return plugin.Failed(nil), nil
return plugin.Failed(info), nil
}
return plugin.Passed(nil), nil
return plugin.Passed(info), nil
}

func (m *MaxMaintenance) filterProfileName(nodes []corev1.Node) []corev1.Node {
Expand Down
4 changes: 3 additions & 1 deletion plugin/impl/nodecount.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ func (n *NodeCount) Check(params plugin.Parameters) (plugin.CheckResult, error)
if err != nil {
return plugin.Failed(nil), err
}
return plugin.CheckResult{Passed: len(nodeList.Items) >= n.Count}, nil
current := len(nodeList.Items)
info := map[string]any{"current": current, "expected": n.Count}
return plugin.CheckResult{Passed: current >= n.Count, Info: info}, nil
}

func (n *NodeCount) OnTransition(params plugin.Parameters) error {
Expand Down
1 change: 1 addition & 0 deletions plugin/impl/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func (pi *PrometheusInstant) Check(params plugin.Parameters) (plugin.CheckResult
return plugin.Failed(info), fmt.Errorf("result does not contain exactly one element")
}
value := float64(vector[0].Value)
info["value"] = value
evaluable, err := gval.Full().NewEvaluable(pi.Expr)
if err != nil {
return plugin.Failed(info), err
Expand Down
3 changes: 2 additions & 1 deletion plugin/impl/semver.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ func (cs *ClusterSemver) Check(params plugin.Parameters) (plugin.CheckResult, er
maxVersion = version
}
}
return plugin.CheckResult{Passed: ownVersion.LT(maxVersion)}, nil
info := map[string]any{"own": ownVersion.String(), "max": maxVersion.String()}
return plugin.CheckResult{Passed: ownVersion.LT(maxVersion), Info: info}, nil
}

func filterByProfile(nodes []v1.Node, profile string) []v1.Node {
Expand Down
7 changes: 5 additions & 2 deletions plugin/impl/stagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,20 @@ func (s *Stagger) ID() string {
// Check asserts that since the last successful check is a certain time has passed.
func (s *Stagger) Check(params plugin.Parameters) (plugin.CheckResult, error) {
s.grabIndex = noGrab
availableIn := make([]time.Duration, 0)
for i := 0; i < s.Parallel; i++ {
lease, err := s.getOrCreateLease(i, &params)
if err != nil {
return plugin.Failed(nil), err
}
if time.Since(lease.Spec.RenewTime.Time) > time.Duration(*lease.Spec.LeaseDurationSeconds)*time.Second {
leaseDuration := time.Duration(*lease.Spec.LeaseDurationSeconds) * time.Second
if time.Since(lease.Spec.RenewTime.Time) > leaseDuration {
s.grabIndex = i
return plugin.Passed(nil), nil
}
availableIn = append(availableIn, leaseDuration-time.Since(lease.Spec.RenewTime.Time))
}
return plugin.Failed(nil), nil
return plugin.Failed(map[string]any{"availableIn": availableIn}), nil
}

func (s *Stagger) getOrCreateLease(idx int, params *plugin.Parameters) (coordinationv1.Lease, error) {
Expand Down
4 changes: 2 additions & 2 deletions plugin/impl/timewindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (tw *TimeWindow) checkInternal(current time.Time) plugin.CheckResult {
}
}
if !containsWeekday {
return plugin.Failed(nil)
return plugin.FailedWithReason("current day of week forbidden")
}
isExcluded := false
for _, exclude := range tw.Exclude {
Expand All @@ -115,7 +115,7 @@ func (tw *TimeWindow) checkInternal(current time.Time) plugin.CheckResult {
}
}
if isExcluded {
return plugin.Failed(nil)
return plugin.FailedWithReason("day/month forbidden")
}
// It is required to set the date to the configured values only keeping the time
compare := time.Date(tw.Start.Year(), tw.Start.Month(), tw.Start.Day(), current.Hour(),
Expand Down
4 changes: 2 additions & 2 deletions plugin/impl/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (w *Wait) Check(params plugin.Parameters) (plugin.CheckResult, error) {
if time.Since(params.LastTransition) > w.Duration {
return plugin.Passed(nil), nil
}
return plugin.Failed(nil), nil
return plugin.Failed(map[string]any{"available_in": w.Duration - time.Since(params.LastTransition)}), nil
}

func (w *Wait) OnTransition(params plugin.Parameters) error {
Expand Down Expand Up @@ -137,7 +137,7 @@ func (we *WaitExclude) checkInternal(params *plugin.Parameters, now time.Time) p
if since > we.Duration {
return plugin.Passed(nil)
}
return plugin.Failed(nil)
return plugin.Failed(map[string]any{"available_in": we.Duration - since})
}

func (we *WaitExclude) isExcluded(weekday time.Weekday) bool {
Expand Down
2 changes: 2 additions & 0 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ <h3 x-text="`${profile.name}: ${profile.state}`"></h3>
<th>Instance</th>
<th>Type</th>
<th>Passed</th>
<th>Notes</th>
</tr>
</thead>
<tbody x-data="{get plugins() { return entries(transition.chain.info); }}">
Expand All @@ -141,6 +142,7 @@ <h3 x-text="`${profile.name}: ${profile.state}`"></h3>
<td x-text="plugin[0]"></td>
<td x-text="plugin[1].id"></td>
<td x-text="plugin[1].passed"></td>
<td x-text="JSON.stringify(plugin[1].info)"></td>
</tr>
</template>
</tbody>
Expand Down

0 comments on commit be523f2

Please sign in to comment.