Skip to content

Commit

Permalink
add monitors
Browse files Browse the repository at this point in the history
  • Loading branch information
tbavelier committed Jan 24, 2025
1 parent 090df80 commit fadc293
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 15 deletions.
3 changes: 2 additions & 1 deletion api/datadoghq/v1alpha1/datadoggenericresource_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type SupportedResourcesType string

// When adding a new type, make sure to update the kubebuilder validation enum marker
const (
Monitor SupportedResourcesType = "monitor"
Notebook SupportedResourcesType = "notebook"
SyntheticsAPITest SupportedResourcesType = "synthetics_api_test"
SyntheticsBrowserTest SupportedResourcesType = "synthetics_browser_test"
Expand All @@ -22,7 +23,7 @@ const (
// +k8s:openapi-gen=true
type DatadogGenericResourceSpec struct {
// Type is the type of the API object
// +kubebuilder:validation:Enum=notebook;synthetics_api_test;synthetics_browser_test
// +kubebuilder:validation:Enum=monitor;notebook;synthetics_api_test;synthetics_browser_test
Type SupportedResourcesType `json:"type"`
// JsonSpec is the specification of the API object
JsonSpec string `json:"jsonSpec"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
)

var allowedCustomResourcesEnumMap = map[SupportedResourcesType]string{
Monitor: "",
Notebook: "",
SyntheticsAPITest: "",
SyntheticsBrowserTest: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ spec:
type:
description: Type is the type of the API object
enum:
- monitor
- notebook
- synthetics_api_test
- synthetics_browser_test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"type": {
"description": "Type is the type of the API object",
"enum": [
"monitor",
"notebook",
"synthetics_api_test",
"synthetics_browser_test"
Expand Down
21 changes: 10 additions & 11 deletions internal/controller/datadoggenericresource/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,23 @@ type Reconciler struct {
client client.Client
datadogSyntheticsClient *datadogV1.SyntheticsApi
datadogNotebooksClient *datadogV1.NotebooksApi
// TODO: add other clients
datadogAuth context.Context
scheme *runtime.Scheme
log logr.Logger
recorder record.EventRecorder
datadogMonitorsClient *datadogV1.MonitorsApi
datadogAuth context.Context
scheme *runtime.Scheme
log logr.Logger
recorder record.EventRecorder
}

func NewReconciler(client client.Client, ddClient datadogclient.DatadogGenericClient, scheme *runtime.Scheme, log logr.Logger, recorder record.EventRecorder) *Reconciler {
return &Reconciler{
client: client,
datadogSyntheticsClient: ddClient.SyntheticsClient,
datadogNotebooksClient: ddClient.NotebooksClient,
// TODO: add other clients
// datadogOtherClient: ddClient.OtherClient,
datadogAuth: ddClient.Auth,
scheme: scheme,
log: log,
recorder: recorder,
datadogMonitorsClient: ddClient.MonitorsClient,
datadogAuth: ddClient.Auth,
scheme: scheme,
log: log,
recorder: recorder,
}
}

Expand Down
84 changes: 84 additions & 0 deletions internal/controller/datadoggenericresource/monitors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package datadoggenericresource

import (
"context"

"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
"github.com/DataDog/datadog-operator/api/datadoghq/v1alpha1"
"github.com/go-logr/logr"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type MonitorHandler struct{}
type MonitorCRUDClient struct {
client *datadogV1.MonitorsApi
}

func (c *MonitorCRUDClient) createResource(auth context.Context, unmarshaledSpec any) (any, error) {
v := unmarshaledSpec.(*datadogV1.Monitor)
monitor, _, err := c.client.CreateMonitor(auth, *v)
return monitor, err
}

func (c *MonitorCRUDClient) getResource(auth context.Context, resourceStringID string) error {
monitorID, err := resourceStringToInt64ID(resourceStringID)
if err != nil {
return err
}
_, _, err = c.client.GetMonitor(auth, monitorID)
if err != nil {
return translateClientError(err, "error getting monitor")
}
return nil
}

func (c *MonitorCRUDClient) updateResource(auth context.Context, resourceStringID string, unmarshaledSpec any) (any, error) {
monitorID, err := resourceStringToInt64ID(resourceStringID)
if err != nil {
return nil, err
}
v := unmarshaledSpec.(*datadogV1.MonitorUpdateRequest)
monitor, _, err := c.client.UpdateMonitor(auth, monitorID, *v)
return monitor, err
}

func (c *MonitorCRUDClient) deleteResource(auth context.Context, resourceStringID string) error {
monitorID, err := resourceStringToInt64ID(resourceStringID)
if err != nil {
return err
}
if _, _, err = c.client.DeleteMonitor(auth, monitorID); err != nil {
return translateClientError(err, "error deleting monitor")
}
return nil
}

func (h *MonitorHandler) createResourcefunc(r *Reconciler, logger logr.Logger, instance *v1alpha1.DatadogGenericResource, status *v1alpha1.DatadogGenericResourceStatus, now metav1.Time, hash string) error {
resource, err := CreateResource(r.datadogAuth, &MonitorCRUDClient{client: r.datadogMonitorsClient}, instance)
if err != nil {
logger.Error(err, "error creating monitor")
updateErrStatus(status, now, v1alpha1.DatadogSyncStatusCreateError, "CreatingCustomResource", err)
return err
}
createdMonitor := resource.(datadogV1.Monitor)
logger.Info("created a new monitor", "monitor Id", createdMonitor.GetId())
status.Id = resourceInt64ToStringID(createdMonitor.GetId())
createdTime := metav1.NewTime(*createdMonitor.Created)
status.Created = &createdTime
status.LastForceSyncTime = &createdTime
status.Creator = *createdMonitor.GetCreator().Handle
status.SyncStatus = v1alpha1.DatadogSyncStatusOK
status.CurrentHash = hash
return nil
}

func (h *MonitorHandler) getResourcefunc(r *Reconciler, instance *v1alpha1.DatadogGenericResource) error {
return GetResource(r.datadogAuth, &MonitorCRUDClient{client: r.datadogMonitorsClient}, instance)
}
func (h *MonitorHandler) updateResourcefunc(r *Reconciler, instance *v1alpha1.DatadogGenericResource) error {
_, err := UpdateResource(r.datadogAuth, &MonitorCRUDClient{client: r.datadogMonitorsClient}, instance)
return err
}
func (h *MonitorHandler) deleteResourcefunc(r *Reconciler, instance *v1alpha1.DatadogGenericResource) error {
return DeleteResource(r.datadogAuth, &MonitorCRUDClient{client: r.datadogMonitorsClient}, instance)
}
6 changes: 6 additions & 0 deletions internal/controller/datadoggenericresource/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func apiCreateAndUpdateStatus(r *Reconciler, logger logr.Logger, instance *v1alp

func getHandler(resourceType v1alpha1.SupportedResourcesType) ResourceHandler {
switch resourceType {
case v1alpha1.Monitor:
return &MonitorHandler{}
case v1alpha1.Notebook:
return &NotebookHandler{}
case v1alpha1.SyntheticsAPITest, v1alpha1.SyntheticsBrowserTest:
Expand All @@ -75,6 +77,8 @@ func createUnmarshaler(instance *v1alpha1.DatadogGenericResource) any {
resourceSpec := instance.Spec.JsonSpec
var result any
switch resourceType {
case v1alpha1.Monitor:
result = &datadogV1.Monitor{}
case v1alpha1.Notebook:
result = &datadogV1.NotebookCreateRequest{}
case v1alpha1.SyntheticsAPITest:
Expand Down Expand Up @@ -106,6 +110,8 @@ func updateUnmarshaler(instance *v1alpha1.DatadogGenericResource) any {
resourceSpec := instance.Spec.JsonSpec
var result any
switch resourceType {
case v1alpha1.Monitor:
result = &datadogV1.MonitorUpdateRequest{}
case v1alpha1.Notebook:
result = &datadogV1.NotebookUpdateRequest{}
case v1alpha1.SyntheticsAPITest:
Expand Down
12 changes: 9 additions & 3 deletions pkg/datadogclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ func InitDatadogDashboardClient(logger logr.Logger, creds config.Creds) (Datadog
type DatadogGenericClient struct {
SyntheticsClient *datadogV1.SyntheticsApi
NotebooksClient *datadogV1.NotebooksApi
// TODO: other clients depending on the resource
Auth context.Context
MonitorsClient *datadogV1.MonitorsApi
Auth context.Context
}

// InitDatadogGenericClient initializes the Datadog Generic API Client and establishes credentials.
Expand All @@ -112,13 +112,19 @@ func InitDatadogGenericClient(logger logr.Logger, creds config.Creds) (DatadogGe
apiClient := datadogapi.NewAPIClient(configV1)
syntheticsClient := datadogV1.NewSyntheticsApi(apiClient)
notebooksClient := datadogV1.NewNotebooksApi(apiClient)
monitorsClient := datadogV1.NewMonitorsApi(apiClient)

authV1, err := setupAuth(logger, creds)
if err != nil {
return DatadogGenericClient{}, err
}

return DatadogGenericClient{SyntheticsClient: syntheticsClient, NotebooksClient: notebooksClient, Auth: authV1}, nil
return DatadogGenericClient{
SyntheticsClient: syntheticsClient,
NotebooksClient: notebooksClient,
MonitorsClient: monitorsClient,
Auth: authV1,
}, nil
}

func setupAuth(logger logr.Logger, creds config.Creds) (context.Context, error) {
Expand Down

0 comments on commit fadc293

Please sign in to comment.