- Ruby 3.3
- EC2 Instances
- RDS DB Instance
IAM > Policies > Create policy > JSON >
[copy + paste]
> Next > Policy name:start-stop-instance-policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances",
"rds:StartDBInstance",
"rds:StopDBInstance"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
IAM > Roles > Create role > Trusted entity type:
AWS service
> Use case:Lambda
> Next > Role name:start-stop-instance-role
default (not change)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
}
}
]
}
IAM > Roles >
start-stop-instance-role
> Add permissions > Attach policies >start-stop-instance-policy
Lambda > Create function > Function name:
start_instances
Environment variables
BASTION_ID = "i-0a1b2c3d4e5f6g7h8",
DEV_APP_ID = "i-9j8h7g6f5e4d3c2b1a0",
RDS_INSTANCE_ID = "dev-instance",
REGION = "us-east-1",
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/..."
# ruby version: 3.3
require 'aws-sdk-ec2'
require 'aws-sdk-rds'
def lambda_handler(*)
# Environment variables
bastion_id = ENV.fetch('BASTION_ID')
dev_app_id = ENV.fetch('DEV_APP_ID')
rds_instance_id = ENV.fetch('RDS_INSTANCE_ID')
region = ENV.fetch('REGION')
slack_webhook_url = ENV.fetch('SLACK_WEBHOOK_URL')
# Create AWS Clients
ec2_client = Aws::EC2::Client.new(region:)
rds_client = Aws::RDS::Client.new(region:)
# Start instances
ec2_client.start_instances(instance_ids: [bastion_id, dev_app_id])
rds_client.start_db_instance(db_instance_identifier: rds_instance_id)
# Create slack message
message = {
blocks: [
{
type: 'header',
text: {
type: 'plain_text',
text: ':coffee: Instances successfully connected'
}
},
{
type: 'section',
text: {
type: 'mrkdwn',
text: "*Detalhes:*\n" \
"• *Bastion ID:* `#{bastion_id}`\n" \
"• *Dev App ID:* `#{dev_app_id}`\n" \
"• *RDS Instance ID:* `#{rds_instance_id}`"
}
},
{
type: 'section',
text: {
type: 'mrkdwn',
text: 'The system will be available in 10 minutes.'
},
accessory: {
type: 'button',
text: {
type: 'plain_text',
text: ':computer: Google'
},
url: 'https://google.com',
style: 'primary'
}
}
]
}
# Send slack message
uri = URI(slack_webhook_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request.content_type = 'application/json'
request.body = message.to_json
http.request(request)
# Return success message from Lambda
{
status: 200,
message: 'Instances successfully connected.'
}
end
Lambda > Functions >
start_instances
> Add trigger > EventBridge > Create a new rule > Rule name:start_instances_event
# Start DEV instance at 05:30h, from Monday to Friday (GMT-3).
cron(30 8 ? * MON-FRI *)
Lambda > Create function > Function name:
stop_instances
Environment variables
BASTION_ID = "i-0a1b2c3d4e5f6g7h8",
DEV_APP_ID = "i-9j8h7g6f5e4d3c2b1a0",
RDS_INSTANCE_ID = "dev-instance",
REGION = "us-east-1",
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/..."
# ruby version: 3.3
require 'aws-sdk-ec2'
require 'aws-sdk-rds'
def lambda_handler(*)
# Environment variables
bastion_id = ENV.fetch('BASTION_ID')
dev_app_id = ENV.fetch('DEV_APP_ID')
rds_instance_id = ENV.fetch('RDS_INSTANCE_ID')
region = ENV.fetch('REGION')
slack_webhook_url = ENV.fetch('SLACK_WEBHOOK_URL')
# Create AWS Clients
ec2_client = Aws::EC2::Client.new(region:)
rds_client = Aws::RDS::Client.new(region:)
# Stop instances
ec2_client.stop_instances(instance_ids: [bastion_id, dev_app_id])
rds_client.stop_db_instance(db_instance_identifier: rds_instance_id)
# Create slack message
message = {
blocks: [
{
type: 'header',
text: {
type: 'plain_text',
text: ':crescent_moon: Instances successfully disconnected'
}
},
{
type: 'section',
text: {
type: 'mrkdwn',
text: "*Detalhes:*\n" \
"• *Bastion ID:* `#{bastion_id}`\n" \
"• *Dev App ID:* `#{dev_app_id}`\n" \
"• *RDS Instance ID:* `#{rds_instance_id}`"
}
}
]
}
# Send slack message
uri = URI(slack_webhook_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request.content_type = 'application/json'
request.body = message.to_json
http.request(request)
# Return success message from Lambda
{
status: 200,
message: 'Instances successfully disconnected.'
}
end
Lambda > Functions >
stop_instances
> Add trigger > EventBridge > Create a new rule > Rule name:stop_instances_event
# Stop DEV instance at 20:00h, from Monday to Friday (GMT-3).
cron(00 23 ? * MON-FRI *)
References: