Skip to content

Commit 942f713

Browse files
committed
feat(terraform): add documentdb scheduler
This commit introduces a new feature to our Terraform configuration, enabling the addition of a Documentdb scheduler module. This module allows for the automated stopping or starting of Documentdb clusters based on predefined tags. By leveraging this scheduler, we can effectively manage the usage and costs associated with our Documentdb clusters, ensuring they are active only when needed and maximizing resource efficiency.
1 parent 7f8a896 commit 942f713

File tree

5 files changed

+126
-1
lines changed

5 files changed

+126
-1
lines changed

main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ resource "aws_lambda_function" "this" {
274274
SCHEDULE_ACTION = var.schedule_action
275275
TAG_KEY = local.scheduler_tag["key"]
276276
TAG_VALUE = local.scheduler_tag["value"]
277+
DOCUMENTDB_SCHEDULE = tostring(var.documentdb_schedule)
277278
EC2_SCHEDULE = tostring(var.ec2_schedule)
278279
ECS_SCHEDULE = tostring(var.ecs_schedule)
279280
RDS_SCHEDULE = tostring(var.rds_schedule)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""documentdb instances scheduler."""
4+
5+
from typing import Dict, List
6+
7+
import boto3
8+
9+
from botocore.exceptions import ClientError
10+
11+
from .exceptions import documentdb_exception
12+
from .filter_resources_by_tags import FilterByTags
13+
14+
15+
class DocumentDBScheduler:
16+
"""documentdb scheduler."""
17+
18+
def __init__(self, region_name=None) -> None:
19+
"""Initialize documentdb scheduler."""
20+
if region_name:
21+
self.documentdb = boto3.client("docdb", region_name=region_name)
22+
else:
23+
self.documentdb = boto3.client("docdb")
24+
self.tag_api = FilterByTags(region_name=region_name)
25+
26+
def stop(self, aws_tags: List[Dict]) -> None:
27+
"""Aws documentdb cluster stop function.
28+
29+
Stop documentdb clusters with defined tags.
30+
31+
:param list[map] aws_tags:
32+
Aws tags to use for filter resources.
33+
For example:
34+
[
35+
{
36+
'Key': 'string',
37+
'Values': [
38+
'string',
39+
]
40+
}
41+
]
42+
"""
43+
for cluster_arn in self.tag_api.get_resources("rds:cluster", aws_tags):
44+
cluster_id = cluster_arn.split(":")[-1]
45+
try:
46+
self.documentdb.stop_db_cluster(DBClusterIdentifier=cluster_id)
47+
print(f"Stop documentdb cluster {cluster_id}")
48+
except ClientError as exc:
49+
documentdb_exception("documentdb cluster", cluster_id, exc)
50+
51+
def start(self, aws_tags: List[Dict]) -> None:
52+
"""Aws documentdb cluster start function.
53+
54+
Start documentdb clusters with defined tags.
55+
56+
:param list[map] aws_tags:
57+
Aws tags to use for filter resources.
58+
For example:
59+
[
60+
{
61+
'Key': 'string',
62+
'Values': [
63+
'string',
64+
]
65+
}
66+
]
67+
"""
68+
for cluster_arn in self.tag_api.get_resources("rds:cluster", aws_tags):
69+
cluster_id = cluster_arn.split(":")[-1]
70+
try:
71+
self.documentdb.start_db_cluster(DBClusterIdentifier=cluster_id)
72+
print(f"Start documentdb cluster {cluster_id}")
73+
except ClientError as exc:
74+
documentdb_exception("documentdb cluster", cluster_id, exc)

package/scheduler/exceptions.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,49 @@
55
import logging
66

77

8+
def documentdb_exception(resource_name: str, resource_id: str, exception) -> None:
9+
"""Exception raised during execution of documentdb scheduler.
10+
11+
Log instance, spot instance and autoscaling groups exceptions
12+
on the specific aws resources.
13+
14+
:param str resource_name:
15+
Aws resource name
16+
:param str resource_id:
17+
Aws resource id
18+
:param str exception:
19+
Human readable string describing the exception
20+
"""
21+
info_codes = ["InvalidDBClusterStateFault"]
22+
warning_codes = [
23+
"InvalidDBClusterStateFault",
24+
"DBClusterNotFoundFault",
25+
"DBClusterParameterGroupNotFound",
26+
]
27+
28+
if exception.response["Error"]["Code"] in info_codes:
29+
logging.info(
30+
"%s %s: %s",
31+
resource_name,
32+
resource_id,
33+
exception,
34+
)
35+
elif exception.response["Error"]["Code"] in warning_codes:
36+
logging.warning(
37+
"%s %s: %s",
38+
resource_name,
39+
resource_id,
40+
exception,
41+
)
42+
else:
43+
logging.error(
44+
"Unexpected error on %s %s: %s",
45+
resource_name,
46+
resource_id,
47+
exception,
48+
)
49+
50+
851
def ec2_exception(resource_name: str, resource_id: str, exception) -> None:
952
"""Exception raised during execution of ec2 scheduler.
1053

package/scheduler/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from .autoscaling_handler import AutoscalingScheduler
88
from .cloudwatch_handler import CloudWatchAlarmScheduler
9+
from .documentdb_handler import DocumentDBScheduler
910
from .ecs_handler import EcsScheduler
1011
from .instance_handler import InstanceScheduler
1112
from .rds_handler import RdsScheduler
@@ -34,6 +35,7 @@ def lambda_handler(event, context):
3435

3536
_strategy = {}
3637
_strategy[AutoscalingScheduler] = os.getenv("AUTOSCALING_SCHEDULE")
38+
_strategy[DocumentDBScheduler] = os.getenv("DOCUMENTDB_SCHEDULE")
3739
_strategy[InstanceScheduler] = os.getenv("EC2_SCHEDULE")
3840
_strategy[EcsScheduler] = os.getenv("ECS_SCHEDULE")
3941
_strategy[RdsScheduler] = os.getenv("RDS_SCHEDULE")

variables.tf

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,18 @@ variable "ec2_schedule" {
6767
default = false
6868
}
6969

70+
variable "documentdb_schedule" {
71+
description = "Enable scheduling on documentdb resources"
72+
type = bool
73+
default = false
74+
}
75+
7076
variable "ecs_schedule" {
7177
description = "Enable scheduling on ecs services"
7278
type = bool
7379
default = false
7480
}
7581

76-
7782
variable "rds_schedule" {
7883
description = "Enable scheduling on rds resources"
7984
type = any

0 commit comments

Comments
 (0)