-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from SonicGarden/kzkn-20231013-eventbridge-sch…
…eduler [review] EventBridge Scheduler のスケジュール登録
- Loading branch information
Showing
14 changed files
with
416 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: Ruby | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
|
||
jobs: | ||
rspec: | ||
runs-on: ubuntu-latest | ||
env: | ||
BUNDLE_JOBS: 4 | ||
BUNDLE_RETRY: 3 | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
ruby: ["3.0", "3.1", "3.2"] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/cache@v3 | ||
with: | ||
path: /home/runner/bundle | ||
key: bundle-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }} | ||
restore-keys: | | ||
bundle-${{ matrix.ruby }}- | ||
- name: Set up Ruby | ||
uses: ruby/setup-ruby@v1 | ||
with: | ||
ruby-version: ${{ matrix.ruby }} | ||
bundler-cache: true | ||
- name: Run rspec | ||
run: bundle exec rspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
--require spec_helper |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
require 'net/http' | ||
require 'json' | ||
require 'aws-sdk-ec2' | ||
|
||
module SgFargateRails | ||
class CurrentEcsTask | ||
def cluster_arn | ||
metadata[:Cluster] | ||
end | ||
|
||
def task_definition_arn | ||
"#{cluster_arn.split(":cluster/")[0]}:task-definition/#{metadata[:Family]}:#{metadata[:Revision]}" | ||
end | ||
|
||
def cfn_stack_name | ||
"#{ENV['COPILOT_APPLICATION_NAME']}-#{ENV['COPILOT_ENVIRONMENT_NAME']}" | ||
end | ||
|
||
def security_group_ids | ||
@security_group_ids ||= fetch_security_group_ids | ||
end | ||
|
||
def public_subnet_ids | ||
@public_subnet_ids ||= fetch_public_subnet_ids | ||
end | ||
|
||
private | ||
|
||
def metadata | ||
@metadata ||= begin | ||
response = Net::HTTP.get(URI.parse("#{ENV['ECS_CONTAINER_METADATA_URI']}/task")) | ||
JSON.parse(response, symbolize_names: true) | ||
end | ||
end | ||
|
||
def region | ||
ENV['AWS_REGION'] || 'ap-northeast-1' | ||
end | ||
|
||
def ec2_client | ||
@ec2_client ||= Aws::EC2::Client.new(region: region, credentials: credentials) | ||
end | ||
|
||
def credentials | ||
@credentials ||= Aws::ECSCredentials.new(retries: 3) | ||
end | ||
|
||
def fetch_security_group_ids | ||
security_group_params = { | ||
filters: [ | ||
{ | ||
name: 'tag:aws:cloudformation:logical-id', | ||
values: ['EnvironmentSecurityGroup'], | ||
}, | ||
{ | ||
name: 'tag:aws:cloudformation:stack-name', | ||
values: [cfn_stack_name], | ||
} | ||
], | ||
} | ||
resp = ec2_client.describe_security_groups(security_group_params) | ||
resp.to_h[:security_groups].map { |group| group[:group_id] } | ||
end | ||
|
||
def fetch_public_subnet_ids | ||
subnet_params = { | ||
filters: [ | ||
{ | ||
name: 'tag:aws:cloudformation:logical-id', | ||
values: %w[PublicSubnet1 PublicSubnet2], | ||
}, | ||
{ | ||
name: 'tag:aws:cloudformation:stack-name', | ||
values: [cfn_stack_name], | ||
}, | ||
], | ||
} | ||
resp = ec2_client.describe_subnets(subnet_params) | ||
resp.to_h[:subnets].map { |subnet| subnet[:subnet_id] } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
require "aws-sdk-scheduler" | ||
|
||
module SgFargateRails | ||
class EventBridgeSchedule | ||
CONTAINER_TYPES = { | ||
'small' => { cpu: '512', memory: '1024', }, | ||
'medium' => { cpu: '1024', memory: '2048', }, | ||
'large' => { cpu: '2048', memory: '4096', }, | ||
}.freeze | ||
|
||
attr_reader :name | ||
|
||
def initialize(name, cron, command, container_type) | ||
@name = name | ||
@cron = cron | ||
@command = command | ||
@container_type = container_type | ||
end | ||
|
||
def create_run_task(group_name:, cluster_arn:, task_definition_arn:, network_configuration:) | ||
params = { | ||
name: @name, | ||
state: 'ENABLED', | ||
flexible_time_window: { mode: 'OFF' }, | ||
group_name: group_name, | ||
schedule_expression: @cron, | ||
schedule_expression_timezone: timezone, | ||
target: { | ||
arn: cluster_arn, | ||
ecs_parameters: { | ||
task_count: 1, | ||
task_definition_arn: task_definition_arn, | ||
launch_type: 'FARGATE', | ||
network_configuration: network_configuration | ||
}, | ||
input: input_overrides_json, | ||
retry_policy: { | ||
maximum_event_age_in_seconds: 120, | ||
maximum_retry_attempts: 2, | ||
}, | ||
role_arn: role_arn_for(group_name, cluster_arn), | ||
}, | ||
} | ||
client.create_schedule(params) | ||
end | ||
|
||
def input_overrides_json | ||
type = convert_container_type | ||
if type | ||
{ | ||
**type, | ||
"containerOverrides": [ | ||
{ | ||
"name": "rails", | ||
**type, | ||
"command": container_command, | ||
} | ||
] | ||
}.to_json | ||
else | ||
{ | ||
"containerOverrides": [ | ||
{ | ||
"name": "rails", | ||
"command": container_command, | ||
} | ||
] | ||
}.to_json | ||
end | ||
end | ||
|
||
def convert_container_type | ||
CONTAINER_TYPES[@container_type] | ||
end | ||
|
||
def container_command | ||
%w[bundle exec] + @command.split(' ') | ||
end | ||
|
||
private | ||
|
||
def timezone | ||
ENV['TZ'] || 'Asia/Tokyo' | ||
end | ||
|
||
def role_arn_for(group_name, cluster_arn) | ||
account_id = cluster_arn.split(':')[4] | ||
"arn:aws:iam::#{account_id}:role/#{group_name}-eventbridge-scheduler-role" | ||
end | ||
|
||
def client | ||
self.class.client | ||
end | ||
|
||
class << self | ||
def parse(filename) | ||
schedules = YAML.unsafe_load(File.open(filename))[environment] | ||
schedules.map { |name, info| EventBridgeSchedule.new(name, info['cron'], info['command'], info['container_type']) if name != '<<' } | ||
end | ||
|
||
def delete_all!(group_name) | ||
client.list_schedules(group_name: group_name, max_results: 100).schedules.each do |schedule| | ||
client.delete_schedule(name: schedule.name, group_name: group_name) | ||
Rails.logger.info "[EventBridgeSchedule] Deleted #{group_name}/#{schedule.name}" | ||
end | ||
end | ||
|
||
def client | ||
@client ||= Aws::Scheduler::Client.new(region: region, credentials: credentials) | ||
end | ||
|
||
def environment | ||
ENV['RAILS_ENV'] | ||
end | ||
|
||
def region | ||
ENV['AWS_REGION'] || 'ap-northeast-1' | ||
end | ||
|
||
def credentials | ||
Aws::ECSCredentials.new(retries: 3) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
module SgFargateRails | ||
VERSION = "0.1.8" | ||
VERSION = "0.1.9" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
namespace :sg_fargate_rails do | ||
require 'sg_fargate_rails' | ||
|
||
desc 'EventBridge Schedules' | ||
task recreate_schedules: :environment do | ||
ecs_task = SgFargateRails::CurrentEcsTask.new | ||
Rails.logger.info "[INFO] security_group_ids: #{ecs_task.security_group_ids}" | ||
Rails.logger.info "[INFO] subnet_ids: #{ecs_task.public_subnet_ids}" | ||
|
||
group_name = ecs_task.cfn_stack_name | ||
Rails.logger.info "[EventBridgeSchedule] Clear all schedules in #{group_name}" | ||
SgFargateRails::EventBridgeSchedule.delete_all!(group_name) | ||
|
||
Rails.logger.info "[EventBridgeSchedule] Register schedules in #{group_name}" | ||
config_file = Rails.root.join('config/eventbridge_schedules.yml') | ||
SgFargateRails::EventBridgeSchedule.parse(config_file).each do |schedule| | ||
Rails.logger.info "[EventBridgeSchedule] Register schedule #{schedule.name} in #{group_name}" | ||
# TODO: この辺で AWS の API Limit などのエラーが発生するとスケジュールが消えたままとなるので、エラーの内容に応じてリトライなどのエラー処理が必要 | ||
schedule.create_run_task( | ||
group_name: group_name, | ||
cluster_arn: ecs_task.cluster_arn, | ||
task_definition_arn: ecs_task.task_definition_arn, | ||
network_configuration: { | ||
awsvpc_configuration: { | ||
assign_public_ip: 'ENABLED', | ||
security_groups: ecs_task.security_group_ids, | ||
subnets: ecs_task.public_subnet_ids, | ||
}, | ||
} | ||
) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
common: &common | ||
|
||
staging: | ||
<<: *common | ||
|
||
production: | ||
<<: *common |
Oops, something went wrong.