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

Poetrify #1

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{ pkgs ? import <nixpkgs> {} }:
let
overrides = import ./overrides.nix { inherit pkgs; };
in pkgs.poetry2nix.mkPoetryApplication {
projectDir = ./.;
overrides = pkgs.poetry2nix.overrides.withDefaults overrides;
}
103 changes: 68 additions & 35 deletions nixops_datadog/datadog_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,87 +4,120 @@
import os
import time

GENERATED = 'NIXOPS GENERATED'
GENERATED = "NIXOPS GENERATED"

def initializeDatadog(api_key = None, app_key = None):
if not api_key: api_key = os.environ.get('DATADOG_API_KEY')
if not app_key: app_key = os.environ.get('DATADOG_APP_KEY')

def initializeDatadog(api_key=None, app_key=None):
if not api_key:
api_key = os.environ.get("DATADOG_API_KEY")
if not app_key:
app_key = os.environ.get("DATADOG_APP_KEY")
if not api_key or not app_key:
raise Exception("please set the datadog apiKey and appKey options (or the environment variables DATADOG_API_KEY and DATADOG_APP_KEY)")
options = {'api_key': api_key.rstrip(), 'app_key': app_key.rstrip()}
raise Exception(
"please set the datadog apiKey and appKey options (or the environment variables DATADOG_API_KEY and DATADOG_APP_KEY)"
)
options = {"api_key": api_key.rstrip(), "app_key": app_key.rstrip()}
initialize(**options)
return (api, options)


def get_template_variables(defn):
variables = defn.config['templateVariables']
variables = defn.config["templateVariables"]
template_variables = []
for var in variables:
tvariable = {}
tvariable['name'] = var['name']
tvariable['prefix'] = var['prefix']
tvariable['default'] = var['default']
tvariable["name"] = var["name"]
tvariable["prefix"] = var["prefix"]
tvariable["default"] = var["default"]
template_variables.append(tvariable)
return template_variables


def get_base_url():
return "https://app.datadoghq.com/"


def get_active_downtimes(uuid):
downtimes = api.Downtime.get_all()
if 'errors' in downtimes:
raise Exception("Failed getting downtimes: "+downtimes['errors'])
downtimes = filter(lambda dt: dt['scope'] == [ 'uuid:{}'.format(uuid) ] and dt['active'] and dt['message']==GENERATED, downtimes)
if "errors" in downtimes:
raise Exception("Failed getting downtimes: " + downtimes["errors"])
downtimes = filter(
lambda dt: dt["scope"] == ["uuid:{}".format(uuid)]
and dt["active"]
and dt["message"] == GENERATED,
downtimes,
)
return downtimes


def create_downtime(depl):
if not depl.datadog_downtime: return
if not depl.datadog_downtime:
return

dts = get_active_downtimes(depl.uuid)
start = int(time.time())
end = start + depl.datadog_downtime_seconds

if len(dts) == 0:
dt = api.Downtime.create(
scope='uuid:{}'.format(depl.uuid),
start=start,
end=end,
message=GENERATED
scope="uuid:{}".format(depl.uuid), start=start, end=end, message=GENERATED
)
depl.logger.log("created Datadog downtime with id {}".format(dt['id']))
depl.logger.log("created Datadog downtime with id {}".format(dt["id"]))
elif len(dts) == 1:
api.Downtime.update(
dts[0]['id'],
scope='uuid:{}'.format(depl.uuid),
dts[0]["id"],
scope="uuid:{}".format(depl.uuid),
start=start,
end=end,
message=GENERATED
message=GENERATED,
)
depl.logger.log('updated Datadog downtime with id {}'.format(dts[0]['id']))
depl.logger.log("updated Datadog downtime with id {}".format(dts[0]["id"]))
else:
raise Exception("Found more than one active Datadog downtimes with scope uuid:{}.".format(depl.uuid))
raise Exception(
"Found more than one active Datadog downtimes with scope uuid:{}.".format(
depl.uuid
)
)


def delete_downtime(depl):
if not depl.datadog_downtime: return
if not depl.datadog_downtime:
return
initializeDatadog()

dts = get_active_downtimes(depl.uuid)

if len(dts) == 0:
depl.logger.warn("Could not find an active Datadog downtime with scope uuid:{}.".format(depl.uuid))
depl.logger.warn(
"Could not find an active Datadog downtime with scope uuid:{}.".format(
depl.uuid
)
)
elif len(dts) == 1:
depl.logger.log("deleting Datadog downtime with id {}".format(dts[0]['id']))
api.Downtime.delete(dts[0]['id'])
depl.logger.log("deleting Datadog downtime with id {}".format(dts[0]["id"]))
api.Downtime.delete(dts[0]["id"])
else:
if depl.logger.confirm("Found more than one Datadog downtimes with scope uuid:{}, would you like to delete them all? If no, nixops will not delete any.".format(depl.uuid)):
if depl.logger.confirm(
"Found more than one Datadog downtimes with scope uuid:{}, would you like to delete them all? If no, nixops will not delete any.".format(
depl.uuid
)
):
for dt in dts:
depl.logger.log("deleting Datadog downtime with id {}".format(dt['id']))
api.Downtime.delete(dt['id'])
depl.logger.log("deleting Datadog downtime with id {}".format(dt["id"]))
api.Downtime.delete(dt["id"])


def create_event(depl, title, text='', tags=[]):
if not depl.datadog_notify: return
def create_event(depl, title, text="", tags=[]):
if not depl.datadog_notify:
return
initializeDatadog()

try:
api.Event.create(title=title, text=text, tags=tags + [ 'uuid:{}'.format(depl.uuid), 'deployment:{}'.format(depl.name)])
api.Event.create(
title=title,
text=text,
tags=tags
+ ["uuid:{}".format(depl.uuid), "deployment:{}".format(depl.name)],
)
except:
depl.logger.warn('Failed creating event in datadog, ignoring.')
depl.logger.warn("Failed creating event in datadog, ignoring.")
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 2 additions & 8 deletions nixops_datadog/plugin.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import os.path
import nixops.plugins


@nixops.plugins.hookimpl
def nixexprs():
expr_path = os.path.realpath(os.path.dirname(__file__) + "/../../../../share/nix/nixops-datadog")
if not os.path.exists(expr_path):
expr_path = os.path.realpath(os.path.dirname(__file__) + "/../../../../../share/nix/nixops-datadog")
if not os.path.exists(expr_path):
expr_path = os.path.dirname(__file__) + "/../nix"
return [os.path.dirname(__file__) + "/nix"]

return [
expr_path
]

@nixops.plugins.hookimpl
def load():
Expand Down
6 changes: 3 additions & 3 deletions nixops_datadog/resources/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import datadog_monitor
import datadog_screenboard
import datadog_timeboard
from . import datadog_monitor
from . import datadog_screenboard
from . import datadog_timeboard
112 changes: 73 additions & 39 deletions nixops_datadog/resources/datadog_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,22 @@ def get_resource_type(cls):
def show_type(self):
return "{0}".format(self.get_type())


class DatadogMonitorState(nixops.resources.ResourceState):
"""State of a Datadog monitor"""

state = nixops.util.attr_property("state", nixops.resources.ResourceState.MISSING, int)
state = nixops.util.attr_property(
"state", nixops.resources.ResourceState.MISSING, int
)
api_key = nixops.util.attr_property("apiKey", None)
app_key = nixops.util.attr_property("appKey", None)
monitor_name = nixops.util.attr_property("name", None)
monitor_type = nixops.util.attr_property("type", None)
query = nixops.util.attr_property("query", None)
message = nixops.util.attr_property("message", None)
monitor_id = nixops.util.attr_property("monitorId", None)
options = nixops.util.attr_property("monitorOptions",[],'json')
tags = nixops.util.attr_property("monitorTags", None, 'json')
options = nixops.util.attr_property("monitorOptions", [], "json")
tags = nixops.util.attr_property("monitorTags", None, "json")

@classmethod
def get_type(cls):
Expand All @@ -43,7 +46,7 @@ def __init__(self, depl, name, id):
nixops.resources.ResourceState.__init__(self, depl, name, id)
self._dd_api = None
self._key_options = None
self._monitor_url = nixops_datadog.datadog_utils.get_base_url()+"monitors#"
self._monitor_url = nixops_datadog.datadog_utils.get_base_url() + "monitors#"

def _exists(self):
return self.state != self.MISSING
Expand All @@ -60,74 +63,105 @@ def get_definition_prefix(self):
return "resources.datadogMonitors."

def get_physical_spec(self):
return {'url': self._monitor_url + self.monitor_id } if self.monitor_id else {}
return {"url": self._monitor_url + self.monitor_id} if self.monitor_id else {}

def prefix_definition(self, attr):
return {('resources', 'datadogMonitors'): attr}
return {("resources", "datadogMonitors"): attr}

def connect(self, app_key, api_key):
if self._dd_api: return
self._dd_api, self._key_options = nixops_datadog.datadog_utils.initializeDatadog(app_key=app_key, api_key=api_key)
if self._dd_api:
return
(
self._dd_api,
self._key_options,
) = nixops_datadog.datadog_utils.initializeDatadog(
app_key=app_key, api_key=api_key
)

def create_monitor(self, defn, options):
response = self._dd_api.Monitor.create(
type=defn.config['type'], query=defn.config['query'], name=defn.config['name'],
message=defn.config['message'], options=options, tags=defn.config['monitorTags'])
if 'errors' in response:
raise Exception(str(response['errors']))
type=defn.config["type"],
query=defn.config["query"],
name=defn.config["name"],
message=defn.config["message"],
options=options,
tags=defn.config["monitorTags"],
)
if "errors" in response:
raise Exception(str(response["errors"]))
else:
return response['id']
return response["id"]

def monitor_exist(self, id):
result = self._dd_api.Monitor.get(id)
if 'errors' in result:
if "errors" in result:
return False
else:
return True

def create(self, defn, check, allow_reboot, allow_recreate):
monitor_id = None
self.connect(app_key=defn.config['appKey'], api_key=defn.config['apiKey'])
options = json.loads(defn.config['monitorOptions'])
silenced = defn.config['silenced']
if silenced!=None: options['silenced'] = ast.literal_eval(silenced)
self.connect(app_key=defn.config["appKey"], api_key=defn.config["apiKey"])
options = json.loads(defn.config["monitorOptions"])
silenced = defn.config["silenced"]
if silenced != None:
options["silenced"] = ast.literal_eval(silenced)
if self.state != self.UP:
self.log("creating datadog monitor '{0}...'".format(defn.config['name']))
self.log("creating datadog monitor '{0}...'".format(defn.config["name"]))
monitor_id = self.create_monitor(defn=defn, options=options)

if self.state == self.UP:
if self.monitor_exist(self.monitor_id) == False:
self.warn("monitor with id {0} doesn't exist anymore.. recreating ...".format(self.monitor_id))
self.warn(
"monitor with id {0} doesn't exist anymore.. recreating ...".format(
self.monitor_id
)
)
monitor_id = self.create_monitor(defn=defn, options=options)
else:
self.log("updating datadog monitor '{0}...'".format(defn.config['name']))
self.log(
"updating datadog monitor '{0}...'".format(defn.config["name"])
)
response = self._dd_api.Monitor.update(
self.monitor_id, query=defn.config['query'], name=defn.config['name'],
message=defn.config['message'], options=options, tags=defn.config['monitorTags'])
if 'errors' in response:
raise Exception(str(response['errors']))
self.monitor_id,
query=defn.config["query"],
name=defn.config["name"],
message=defn.config["message"],
options=options,
tags=defn.config["monitorTags"],
)
if "errors" in response:
raise Exception(str(response["errors"]))

with self.depl._db:
self.state = self.UP
self.api_key = defn.config['apiKey']
self.app_key = defn.config['appKey']
self.monitor_name = defn.config['name']
self.monitor_type = defn.config['type']
self.query = defn.config['query']
self.message = defn.config['message']
self.options = defn.config['monitorOptions']
self.tags = defn.config['monitorTags']
if monitor_id != None: self.monitor_id = monitor_id
self.api_key = defn.config["apiKey"]
self.app_key = defn.config["appKey"]
self.monitor_name = defn.config["name"]
self.monitor_type = defn.config["type"]
self.query = defn.config["query"]
self.message = defn.config["message"]
self.options = defn.config["monitorOptions"]
self.tags = defn.config["monitorTags"]
if monitor_id != None:
self.monitor_id = monitor_id

def destroy(self, wipe=False):
if self.state == self.UP:
self.connect(self.app_key,self.api_key)
self.connect(self.app_key, self.api_key)
if self.monitor_exist(self.monitor_id) == False:
self.warn("datadog monitor with id {0} already deleted".format(self.monitor_id))
self.warn(
"datadog monitor with id {0} already deleted".format(
self.monitor_id
)
)
else:
self.log("deleting datadog monitor ‘{0}’...".format(self.monitor_name))
response = self._dd_api.Monitor.delete(self.monitor_id)
if 'errors' in response.keys():
raise Exception("there was errors while deleting the monitor: {}".format(
str(response['errors'])))
if "errors" in response.keys():
raise Exception(
"there was errors while deleting the monitor: {}".format(
str(response["errors"])
)
)
return True