Skip to content

Commit

Permalink
review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
ConsoleCatzirl committed Apr 12, 2024
1 parent 6498043 commit dcd7f7a
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 9 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ Protection should be used to prevent instances from being effected.

### Parameters

| Parameter Name | Default Value | Allowed Values |
|----------------|---------------|-----------------------|
| Ec2Action | "STOP" | "STOP" or "TERMINATE" |
| Parameter Name | Default Value | Allowed Values |
|----------------|--------------------|-----------------------|
| Ec2Action | "STOP" | "STOP" or "TERMINATE" |
| Schedule | cron(0 2 * * ? \*) | EventBridge schedule |

#### Ec2Action

The EC2 action to take on running instances: either stop or terminate.

#### Schedule

When to run the lambda, the default is daily at 2am UTC. Must be an EventBridge schedule.
Format details: https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html

### Running

This lambda is triggered by a scheduled CloudWatch event at 2am UTC (8pm PST).
Expand Down
11 changes: 10 additions & 1 deletion ec2_terminator/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime
import json
import logging
import os
import time

import boto3

Expand Down Expand Up @@ -55,6 +55,15 @@ def list_instances(region):
and tag['Value'] == IGNORE_TAG_VALUE:
ignore = True
break

# also skip instances less than an hour old
if not ignore and 'LaunchTime' in ec2:
launch = ec2['LaunchTime']
now = datetime.datetime.now(launch.tzinfo)
age = now - launch
if age < datetime.timedelta(hours=1):
ignore = True

if ignore:
LOG.debug(f"Ignoring instance {ec2_id}")
continue
Expand Down
2 changes: 1 addition & 1 deletion template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Resources:
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: ManageVolumes
- Sid: ManageInstances
Effect: Allow
Resource: "*"
Action:
Expand Down
45 changes: 41 additions & 4 deletions tests/unit/test_handler.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import json
import os

Expand Down Expand Up @@ -65,6 +66,25 @@ def mock_ignore_tag_response():
]
}



@pytest.fixture()
def mock_ignore_age_response():
return {
'Reservations': [
{
'Instances': [
{
'InstanceId': 'ignore-instance',
'State': {'Name': 'running'},
'LaunchTime': datetime.datetime.now()
}
]
}
]
}


@pytest.fixture()
def mock_no_instances_response():
return {
Expand Down Expand Up @@ -175,10 +195,10 @@ def test_no_instances(mocker,
assert data["message"] == "No running or stopped instances found"


def test_ignore_instance(mocker,
stub_ec2_client,
mock_region_response,
mock_ignore_tag_response):
def test_ignore_tag_instance(mocker,
stub_ec2_client,
mock_region_response,
mock_ignore_tag_response):
magic_client = mocker.MagicMock(return_value=stub_ec2_client)
mocker.patch('boto3.client', magic_client)

Expand All @@ -193,6 +213,23 @@ def test_ignore_instance(mocker,
assert data["message"] == "No running or stopped instances found"


def test_ignore_age_instance(mocker,
stub_ec2_client,
mock_region_response,
mock_ignore_age_response):
magic_client = mocker.MagicMock(return_value=stub_ec2_client)
mocker.patch('boto3.client', magic_client)

with Stubber(stub_ec2_client) as stubber:
stubber.add_response('describe_regions', mock_region_response)
stubber.add_response('describe_instances', mock_ignore_age_response)
ret = app.lambda_handler(None, None)
data = json.loads(ret["body"])

assert ret["statusCode"] == 200
assert "message" in ret["body"]
assert data["message"] == "No running or stopped instances found"

def test_terminate_failed(mocker,
stub_ec2_client,
mock_region_response,
Expand Down

0 comments on commit dcd7f7a

Please sign in to comment.