Skip to content

Commit

Permalink
Merge pull request #79 from K-Phoen/status-management
Browse files Browse the repository at this point in the history
Status management
  • Loading branch information
K-Phoen authored Oct 10, 2021
2 parents a38da46 + 493ac1f commit b1fece8
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 2 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,32 @@ docker run --rm -it -v $(pwd):/workspace kphoen/dark-converter:latest convert-ya
docker run --rm -it -v $(pwd):/workspace kphoen/dark-converter:latest convert-k8s-manifest -i dashboard.json -o converted-dashboard.yaml --folder Dark --namespace monitoring test-dashboard
```

## Integrating with ArgoCD

ArgoCD supports [health checks for custom resources](https://argo-cd.readthedocs.io/en/stable/operator-manual/health/#way-1-define-a-custom-health-check-in-argocd-cm-configmap).
To enable it for GrafanaDashboards, add the following code to your `argo-cm` ConfigMap:

```
data:
resource.customizations.health.k8s.kevingomez.fr_GrafanaDashboard: |
hs = {}
if obj.status ~= nil then
if obj.status.status ~= "OK" then
hs.status = "Degraded"
hs.message = obj.status.message
return hs
else
hs.status = "Healthy"
hs.message = obj.status.message
return hs
end
end
hs.status = "Progressing"
hs.message = "Status unknown"
return hs
```

## Adopters

[Companies using DARK](ADOPTERS.md).
Expand Down
36 changes: 34 additions & 2 deletions internal/controller.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"context"
"fmt"
"strings"
"time"
Expand All @@ -12,6 +13,7 @@ import (
listers "github.com/K-Phoen/dark/internal/pkg/generated/listers/controller/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
Expand Down Expand Up @@ -165,6 +167,9 @@ func (c *Controller) processNextWorkItem() bool {
// put back on the workqueue and attempted again after a back-off
// period.
defer c.workqueue.Done(obj)

ctx := context.Background()

var key string
var ok bool
// We expect strings to come off the workqueue. These are of the
Expand All @@ -191,7 +196,7 @@ func (c *Controller) processNextWorkItem() bool {
} else {
// Run the syncHandler, passing it the namespace/name string of the
// GrafanaDashboard resource to be synced.
if err := c.syncHandler(key); err != nil {
if err := c.syncHandler(ctx, key); err != nil {
// Put the item back on the workqueue to handle any transient errors.
c.workqueue.AddRateLimited(key)
return fmt.Errorf("error syncing '%s': %w, requeuing", key, err)
Expand All @@ -217,7 +222,7 @@ func (c *Controller) processNextWorkItem() bool {
// syncHandler compares the actual state with the desired, and attempts to
// converge the two. It then updates the Status block of the GrafanaDashboard resource
// with the current status of the resource.
func (c *Controller) syncHandler(key string) error {
func (c *Controller) syncHandler(ctx context.Context, key string) error {
// Convert the namespace/name string into a distinct namespace and name
namespace, name, err := cache.SplitMetaNamespaceKey(key)
if err != nil {
Expand All @@ -242,14 +247,41 @@ func (c *Controller) syncHandler(key string) error {
if err := c.dashboardCreator.FromRawSpec(dashboard.Folder, dashboard.ObjectMeta.Name, dashboard.Spec.Raw); err != nil {
utilruntime.HandleError(fmt.Errorf("could not create '%s' dashboard from spec: %w", dashboard.ObjectMeta.Name, err))
c.recorder.Event(dashboard, corev1.EventTypeWarning, WarningNotSynced, fmt.Sprintf("could not create dashboard from spec: %s", err))
c.updateDashboardStatus(ctx, dashboard, err)

return nil
}

c.recorder.Event(dashboard, corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced)
c.updateDashboardStatus(ctx, dashboard, nil)

return nil
}

func (c *Controller) updateDashboardStatus(ctx context.Context, dashboard *v1.GrafanaDashboard, err error) {
// NEVER modify objects from the store. It's a read-only, local cache.
// You can use DeepCopy() to make a deep copy of original object and modify this copy
// Or create a copy manually for better performance
dashboardCopy := dashboard.DeepCopy()

if err == nil {
dashboardCopy.Status.Status = "OK"
dashboardCopy.Status.Message = "Synchronized"
} else {
dashboardCopy.Status.Status = "Error"
dashboardCopy.Status.Message = err.Error()
}

// If the CustomResourceSubresources feature gate is not enabled,
// we must use Update instead of UpdateStatus to update the Status block of the Foo resource.
// UpdateStatus will not allow changes to the Spec of the resource,
// which is ideal for ensuring nothing other than resource status has been updated.
_, err = c.darkClientSet.ControllerV1().GrafanaDashboards(dashboardCopy.Namespace).UpdateStatus(ctx, dashboardCopy, metav1.UpdateOptions{})
if err != nil {
klog.Info(fmt.Sprintf("error while updating dashboard status: %s", err))
}
}

func (c *Controller) deletionHandler(uid string) {
if err := c.dashboardCreator.Delete(uid); err != nil {
utilruntime.HandleError(fmt.Errorf("dashboard '%s' in work queue could not be deleted", uid))
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/apis/controller/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type GrafanaDashboard struct {

// GrafanaDashboardStatus is the status for a GrafanaDashboard resource
type GrafanaDashboardStatus struct {
Status string `json:"status"`
Message string `json:"message"`
}

Expand Down
1 change: 1 addition & 0 deletions internal/pkg/apis/controller/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions k8s/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ spec:
# One and only one version must be marked as the storage version.
storage: true

additionalPrinterColumns:
- jsonPath: .status.status
name: Status
type: string
- jsonPath: .status.message
name: Message
type: string

subresources:
status: {}

Expand All @@ -31,6 +39,13 @@ spec:
spec:
type: object
x-kubernetes-preserve-unknown-fields: true
status:
type: object
properties:
message:
type: string
status:
type: string

names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
Expand Down

0 comments on commit b1fece8

Please sign in to comment.