Skip to content

[Datadog::Monitors::Monitor] Add backward compatibility for TypeConfiguration and ID parsing #200

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

Open
wants to merge 3 commits into
base: datadog-monitors-monitor-3.1.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions datadog-monitors-monitor-handler/.rpdk-config
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"typeName": "Datadog::Monitors::Monitor",
"language": "python37",
"runtime": "python3.7",
"language": "python39",
"runtime": "python3.9",
"entrypoint": "datadog_monitors_monitor.handlers.resource",
"testEntrypoint": "datadog_monitors_monitor.handlers.test_entrypoint",
"settings": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
{
"properties": {
"DatadogCredentials": {
"$ref": "#/definitions/DatadogCredentials"
}
},
"additionalProperties": false,
"definitions": {
"Creator": {
"type": "object",
"properties": {
"Name": {
"description": "Name of the creator of the monitor",
"type": "string"
},
"Handle": {
"description": "Handle of the creator of the monitor",
"type": "string"
},
"Email": {
"description": "Email of the creator of the monitor",
"type": "string"
}
}
},
"MonitorThresholds": {
"type": "object",
"properties": {
"Critical": {
"description": "Threshold value for triggering an alert",
"type": "number"
},
"CriticalRecovery": {
"description": "Threshold value for recovering from an alert state",
"type": "number"
},
"OK": {
"description": "Threshold value for recovering from an alert state",
"type": "number"
},
"Warning": {
"description": "Threshold value for triggering a warning",
"type": "number"
},
"WarningRecovery": {
"description": "Threshold value for recovering from a warning state",
"type": "number"
}
}
},
"MonitorThresholdWindows": {
"type": "object",
"properties": {
"TriggerWindow": {
"description": "How long a metric must be anomalous before triggering an alert",
"type": "string"
},
"RecoveryWindow": {
"description": "How long an anomalous metric must be normal before recovering from an alert state",
"type": "string"
}
}
},
"MonitorOptions": {
"type": "object",
"properties": {
"EnableLogsSample": {
"description": "Whether or not to include a sample of the logs",
"type": "boolean"
},
"EscalationMessage": {
"description": "Message to include with a re-notification when renotify_interval is set",
"type": "string"
},
"EvaluationDelay": {
"description": "Time in seconds to delay evaluation",
"type": "integer"
},
"IncludeTags": {
"description": "Whether or not to include triggering tags into notification title",
"type": "boolean"
},
"Locked": {
"description": "Whether or not changes to this monitor should be restricted to the creator or admins",
"type": "boolean"
},
"MinLocationFailed": {
"description": "Number of locations allowed to fail before triggering alert",
"type": "integer"
},
"NewHostDelay": {
"description": "Time in seconds to allow a host to start reporting data before starting the evaluation of monitor results",
"type": "integer"
},
"NoDataTimeframe": {
"description": "Number of minutes data stopped reporting before notifying",
"type": "integer"
},
"NotifyAudit": {
"description": "Whether or not to notify tagged users when changes are made to the monitor",
"type": "boolean"
},
"NotifyNoData": {
"description": "Whether or not to notify when data stops reporting",
"type": "boolean"
},
"RenotifyInterval": {
"description": "Number of minutes after the last notification before the monitor re-notifies on the current status",
"type": "integer"
},
"RequireFullWindow": {
"description": "Whether or not the monitor requires a full window of data before it is evaluated",
"type": "boolean"
},
"SyntheticsCheckID": {
"description": "ID of the corresponding synthetics check",
"type": "integer"
},
"Thresholds": {
"description": "The threshold definitions",
"$ref": "#/definitions/MonitorThresholds"
},
"ThresholdWindows": {
"description": "The threshold window definitions",
"$ref": "#/definitions/MonitorThresholdWindows"
},
"TimeoutH": {
"description": "Number of hours of the monitor not reporting data before it automatically resolves",
"type": "integer"
}
}
},
"DatadogCredentials": {
"description": "Credentials for the Datadog API",
"properties": {
"ApiKey": {
"description": "Datadog API key",
"type": "string"
},
"ApplicationKey": {
"description": "Datadog application key",
"type": "string"
},
"ApiURL": {
"description": "Datadog API URL (defaults to https://api.datadoghq.com) Use https://api.datadoghq.eu for EU accounts.",
"type": "string"
}
},
"required": [
"ApiKey",
"ApplicationKey"
],
"type": "object",
"additionalProperties": false
}
},
"typeName": "Datadog::Monitors::Monitor"
}
32 changes: 25 additions & 7 deletions datadog-monitors-monitor-handler/datadog-monitors-monitor.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
{
"typeName": "Datadog::Monitors::Monitor",
"description": "Datadog Monitor 3.0.0",
"description": "Datadog Monitor 3.1.0b2",
"typeConfiguration": {
"properties": {
"DatadogCredentials": {
"$ref": "#/definitions/DatadogCredentials"
}
},
"additionalProperties": false
},
"definitions": {
"Creator": {
"type": "object",
Expand Down Expand Up @@ -125,9 +133,7 @@
"type": "integer"
}
}
}
},
"properties": {
},
"DatadogCredentials": {
"description": "Credentials for the Datadog API",
"properties": {
Expand All @@ -148,14 +154,27 @@
"ApiKey",
"ApplicationKey"
],
"type": "object"
"type": "object",
"additionalProperties": false
}
},
"properties": {
"DatadogCredentials": {
"$ref": "#/definitions/DatadogCredentials"
},
"Creator": {
"$ref": "#/definitions/Creator"
},
"Id": {
"description": "ID of the monitor",
"type": "integer"
"oneOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"Message": {
"description": "A message to include with notifications for the monitor",
Expand Down Expand Up @@ -216,7 +235,6 @@
}
},
"required": [
"DatadogCredentials",
"Query",
"Type"
],
Expand Down
4 changes: 2 additions & 2 deletions datadog-monitors-monitor-handler/docs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Datadog::Monitors::Monitor

Datadog Monitor 3.0.0
Datadog Monitor 3.1.0b2

## Syntax

Expand Down Expand Up @@ -46,7 +46,7 @@ Properties:

Credentials for the Datadog API

_Required_: Yes
_Required_: No

_Type_: <a href="datadogcredentials.md">DatadogCredentials</a>

Expand Down
2 changes: 1 addition & 1 deletion datadog-monitors-monitor-handler/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
git+https://github.com/datadog/datadog-cloudformation-resources.git@datadog-cloudformation-common-python-0.0.4#egg=datadog_cloudformation_common&subdirectory=datadog-cloudformation-common-python
git+https://github.com/datadog/datadog-cloudformation-resources.git@datadog-cloudformation-common-python-0.0.6#egg=datadog_cloudformation_common&subdirectory=datadog-cloudformation-common-python
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
from typing import Any, MutableMapping, Optional
from typing import Any, MutableMapping, Optional, Union, Tuple

from cloudformation_cli_python_lib import (
Action,
Expand All @@ -23,15 +23,17 @@
from .models import Creator, MonitorOptions, MonitorThresholdWindows, \
MonitorThresholds, \
ResourceHandlerRequest, \
ResourceModel
ResourceModel, \
DatadogCredentials, \
TypeConfigurationModel
from .version import __version__

# Use this logger to forward log messages to CloudWatch Logs.
LOG = logging.getLogger(__name__)
TYPE_NAME = "Datadog::Monitors::Monitor"
TELEMETRY_TYPE_NAME = "monitors-monitor"

resource = Resource(TYPE_NAME, ResourceModel)
resource = Resource(TYPE_NAME, ResourceModel, TypeConfigurationModel)
test_entrypoint = resource.test_entrypoint


Expand All @@ -43,15 +45,11 @@ def read_handler(
) -> ProgressEvent:
LOG.info("Starting %s Read Handler", TYPE_NAME)
model = request.desiredResourceState
with v1_client(
model.DatadogCredentials.ApiKey,
model.DatadogCredentials.ApplicationKey,
model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
TELEMETRY_TYPE_NAME,
__version__,
) as api_client:

api_key, app_key, api_url = get_auth(model.DatadogCredentials, request.typeConfiguration)
with v1_client(api_key, app_key, api_url, TELEMETRY_TYPE_NAME, __version__) as api_client:
api_instance = MonitorsApi(api_client)
monitor_id = model.Id
monitor_id = get_id(model.Id)
try:
monitor = api_instance.get_monitor(monitor_id)
except ApiException as e:
Expand Down Expand Up @@ -115,7 +113,7 @@ def read_handler(
TriggerWindow=tw.trigger_window if hasattr(tw, "trigger_window") else None,
RecoveryWindow=tw.recovery_window if hasattr(tw, "recovery_window") else None,
)
model.Id = monitor.id
model.Id = get_id(monitor.id)

return ProgressEvent(
status=OperationStatus.SUCCESS,
Expand Down Expand Up @@ -145,16 +143,11 @@ def update_handler(
if options:
monitor.options = options

with v1_client(
model.DatadogCredentials.ApiKey,
model.DatadogCredentials.ApplicationKey,
model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
TELEMETRY_TYPE_NAME,
__version__,
) as api_client:
api_key, app_key, api_url = get_auth(model.DatadogCredentials, request.typeConfiguration)
with v1_client(api_key, app_key, api_url, TELEMETRY_TYPE_NAME, __version__) as api_client:
api_instance = MonitorsApi(api_client)
try:
api_instance.update_monitor(model.Id, monitor)
api_instance.update_monitor(get_id(model.Id), monitor)
except ApiException as e:
LOG.error("Exception when calling MonitorsApi->update_monitor: %s\n", e)
return ProgressEvent(
Expand All @@ -173,16 +166,11 @@ def delete_handler(
LOG.info("Starting %s Delete Handler", TYPE_NAME)
model = request.desiredResourceState

with v1_client(
model.DatadogCredentials.ApiKey,
model.DatadogCredentials.ApplicationKey,
model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
TELEMETRY_TYPE_NAME,
__version__,
) as api_client:
api_key, app_key, api_url = get_auth(model.DatadogCredentials, request.typeConfiguration)
with v1_client(api_key, app_key, api_url, TELEMETRY_TYPE_NAME, __version__) as api_client:
api_instance = MonitorsApi(api_client)
try:
api_instance.delete_monitor(model.Id)
api_instance.delete_monitor(get_id(model.Id))
except ApiException as e:
LOG.error("Exception when calling MonitorsApi->delete_monitor: %s\n", e)
return ProgressEvent(
Expand Down Expand Up @@ -217,13 +205,8 @@ def create_handler(
if options:
monitor.options = options

with v1_client(
model.DatadogCredentials.ApiKey,
model.DatadogCredentials.ApplicationKey,
model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
TELEMETRY_TYPE_NAME,
__version__,
) as api_client:
api_key, app_key, api_url = get_auth(model.DatadogCredentials, request.typeConfiguration)
with v1_client(api_key, app_key, api_url, TELEMETRY_TYPE_NAME, __version__) as api_client:
api_instance = MonitorsApi(api_client)
try:
monitor_resp = api_instance.create_monitor(monitor)
Expand All @@ -233,7 +216,7 @@ def create_handler(
status=OperationStatus.FAILED, resourceModel=model, message=f"Error creating monitor: {e}"
)

model.Id = monitor_resp.id
model.Id = get_id(monitor_resp.id)
return read_handler(session, request, callback_context)


Expand Down Expand Up @@ -298,3 +281,23 @@ def build_monitor_options_from_model(model: ResourceModel) -> ApiMonitorOptions:
options.threshold_windows.recovery_window = model.Options.ThresholdWindows.RecoveryWindow

return options


def get_id(_id: Union[str, int]) -> int:
if isinstance(_id, str):
return int(float(_id))
return _id


def get_auth(
dd_credentials: Optional[DatadogCredentials],
type_configuration: Optional[TypeConfigurationModel]
) -> Tuple[str, str, str]:
if dd_credentials:
return dd_credentials.ApiKey, \
dd_credentials.ApplicationKey, \
dd_credentials.ApiURL or "https://api.datadoghq.com"
else:
return type_configuration.DatadogCredentials.ApiKey, \
type_configuration.DatadogCredentials.ApplicationKey, \
type_configuration.DatadogCredentials.ApiURL or "https://api.datadoghq.com"
Loading
Loading