Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/elastic_whenever/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def run(args)
private

def update_tasks(option, dry_run:)
schedule = Schedule.new(option.schedule_file, option.variables)
schedule = Schedule.new(option.schedule_file, option.verbose, option.variables)
schedule.validate!

cluster = Task::Cluster.new(option, schedule.cluster)
Expand Down
30 changes: 30 additions & 0 deletions lib/elastic_whenever/option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,27 @@ class Option

attr_reader :identifier
attr_reader :mode
attr_reader :verbose
attr_reader :variables
attr_reader :assign_public_ip
attr_reader :launch_type
attr_reader :platform_version
attr_reader :security_groups
attr_reader :subnets
attr_reader :schedule_file

class InvalidOptionException < StandardError; end

def initialize(args)
@identifier = nil
@mode = DRYRUN_MODE
@verbose = false
@variables = []
@assign_public_ip = 'DISABLED'
@launch_type = 'EC2'
@platform_version = 'LATEST'
@security_groups = nil
@subnets = nil
@schedule_file = 'config/schedule.rb'
@profile = nil
@access_key = nil
Expand Down Expand Up @@ -47,6 +59,21 @@ def initialize(args)
@variables << { key: key, value: value }
end
end
opts.on('--assign_public_ip', 'Assign a public IP.') do
@assign_public_ip = 'ENABLED'
end
opts.on('--launch_type launch_type', 'Launch type. Defualt: EC2') do |launch_type|
@launch_type = launch_type
end
opts.on('--security_groups groups', "Example: --security_groups 'sg-2c503655,sg-72f0cb0a'") do |groups|
@security_groups = groups
end
opts.on('--subnets subnets', "Example: --subnets 'subnet-4973d63f,subnet-45827d1d'") do |subnets|
@subnets = subnets
end
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this option needs validation about launch type. For example, If security_groups or subnets are unspecified when launch_type is FARGATE, will they get an error?

Copy link
Copy Markdown
Contributor Author

@avinson avinson Oct 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wata727 I'm still thinking about this/looking into it. fyi, I did discover something kinda terrible about this AWS API in that it does not appear to validate either the subnets or the security groups. If you specify either a non-existent subnet or security group it will accept the event rule and then you'll get "invocation failures" in CloudWatch with no error logs or any indication of what's wrong.

Maybe it makes sense to do this validation in elastic_whenever? I presume that AWS will eventually add this on their end.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avinson Sorry for the late reply.

That's terrible... Perhaps I believe that validation is necessary for a better experience. Considering the behavior of the current AWS API, I think that it makes sense even if without the validation, but I'd like to add it as possible.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avinson @wata727 For now it would be best to add a TODO comment to keep it top of mind.

opts.on('--platform_version version', "For Fargate launch type, optionally specify the platform version. Example: --platform_version 1.2.0") do |version|
@platform_version = version
end
opts.on('-f', '--file schedule_file', 'Default: config/schedule.rb') do |file|
@schedule_file = file
end
Expand All @@ -65,6 +92,9 @@ def initialize(args)
opts.on('-v', '--version', 'Print version') do
@mode = PRINT_VERSION_MODE
end
opts.on('-V', '--verbose', 'Run rake jobs without --silent') do
@verbose = true
end
end.parse(args)

@credentials = if profile
Expand Down
5 changes: 3 additions & 2 deletions lib/elastic_whenever/schedule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ def years
end
using WheneverNumeric

def initialize(file, variables)
def initialize(file, verbose, variables)
@environment = "production"
@verbose = verbose
@tasks = []
@cluster = nil
@task_definition = nil
Expand All @@ -69,7 +70,7 @@ def set(key, value)
end

def every(frequency, options = {}, &block)
@tasks << Task.new(@environment, @bundle_command, schedule_expression(frequency, options)).tap do |task|
@tasks << Task.new(@environment, @verbose, @bundle_command, schedule_expression(frequency, options)).tap do |task|
task.instance_eval(&block)
end
rescue UnsupportedFrequencyException => exn
Expand Down
5 changes: 3 additions & 2 deletions lib/elastic_whenever/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ class Task
attr_reader :commands
attr_reader :expression

def initialize(environment, bundle_command, expression)
def initialize(environment, verbose, bundle_command, expression)
@environment = environment
@verbose_mode = verbose ? '' : "--silent"
@bundle_command = bundle_command.split(" ")
@expression = expression
@commands = []
Expand All @@ -15,7 +16,7 @@ def command(task)
end

def rake(task)
@commands << [@bundle_command, "rake", task, "--silent"].flatten
@commands << [@bundle_command, "rake", task, @verbose_mode].flatten
end

def runner(src)
Expand Down
66 changes: 52 additions & 14 deletions lib/elastic_whenever/task/target.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ class Target
attr_reader :definition
attr_reader :container
attr_reader :commands
attr_reader :assign_public_ip
attr_reader :launch_type
attr_reader :platform_version
attr_reader :security_groups
attr_reader :subnets

class InvalidContainerException < StandardError; end

Expand Down Expand Up @@ -37,25 +42,58 @@ def initialize(option, cluster:, definition:, container:, commands:, rule:, role
@commands = commands
@rule = rule
@role = role
@assign_public_ip = option.assign_public_ip
@launch_type = option.launch_type
@platform_version = option.platform_version
@security_groups = option.security_groups
@subnets = option.subnets
@client = Aws::CloudWatchEvents::Client.new(option.aws_config)
end

def create
client.put_targets(
rule: rule.name,
targets: [
{
id: Digest::SHA1.hexdigest(commands.join("-")),
arn: cluster.arn,
input: input_json(container, commands),
role_arn: role.arn,
ecs_parameters: {
task_definition_arn: definition.arn,
task_count: 1,
if launch_type == 'FARGATE'
client.put_targets(
rule: rule.name,
targets: [
{
id: Digest::SHA1.hexdigest(commands.join("-")),
arn: cluster.arn,
input: input_json(container, commands),
role_arn: role.arn,
ecs_parameters: {
launch_type: launch_type,
task_definition_arn: definition.arn,
task_count: 1,
network_configuration: {
awsvpc_configuration: {
subnets: subnets.split(','),
security_groups: security_groups.split(','),
assign_public_ip: assign_public_ip,
}
},
platform_version: platform_version
}
}
}
]
)
]
)
else
client.put_targets(
rule: rule.name,
targets: [
{
id: Digest::SHA1.hexdigest(commands.join("-")),
arn: cluster.arn,
input: input_json(container, commands),
role_arn: role.arn,
ecs_parameters: {
launch_type: launch_type,
task_definition_arn: definition.arn,
task_count: 1,
}
}
]
)
end
end

private
Expand Down
2 changes: 1 addition & 1 deletion lib/elastic_whenever/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ElasticWhenever
VERSION = "0.3.2"
VERSION = "0.3.3"
end
6 changes: 3 additions & 3 deletions spec/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RSpec.describe ElasticWhenever::CLI do
describe "run" do
let(:task) do
ElasticWhenever::Task.new("production", "bundle exec", "cron(0 0 * * ? *)").tap do |task|
ElasticWhenever::Task.new("production", false, "bundle exec", "cron(0 0 * * ? *)").tap do |task|
task.runner("Hoge.run")
end
end
Expand All @@ -21,7 +21,7 @@
let(:definition) { double(arn: "arn:aws:ecs:us-east-1:123456789:task-definition/wordpress:2", name: "wordpress:2", containers: ["testContainer"]) }
let(:role) { double(arn: "arn:aws:ecs:us-east-1:123456789:role/testRole") }
before do
allow(ElasticWhenever::Schedule).to receive(:new).with((Pathname(__dir__) + "fixtures/schedule.rb").to_s, kind_of(Array)).and_return(schedule)
allow(ElasticWhenever::Schedule).to receive(:new).with((Pathname(__dir__) + "fixtures/schedule.rb").to_s, boolean, kind_of(Array)).and_return(schedule)
allow(ElasticWhenever::Task::Cluster).to receive(:new).with(kind_of(ElasticWhenever::Option), "test").and_return(cluster)
allow(ElasticWhenever::Task::Definition).to receive(:new).with(kind_of(ElasticWhenever::Option), "wordpress:2").and_return(definition)
allow(ElasticWhenever::Task::Role).to receive(:new).with(kind_of(ElasticWhenever::Option)).and_return(role)
Expand Down Expand Up @@ -77,7 +77,7 @@
end

it "receives schedule file name and variables" do
expect(ElasticWhenever::Schedule).to receive(:new).with((Pathname(__dir__) + "fixtures/schedule.rb").to_s, [{ key: "environment", value: "staging" }, { key: "cluster", value: "ecs-test" }])
expect(ElasticWhenever::Schedule).to receive(:new).with((Pathname(__dir__) + "fixtures/schedule.rb").to_s, boolean, [{ key: "environment", value: "staging" }, { key: "cluster", value: "ecs-test" }])

ElasticWhenever::CLI.run(%W(-i test --set environment=staging&cluster=ecs-test --region us-east-1 -f #{(Pathname(__dir__) + "fixtures/schedule.rb").to_s}))
end
Expand Down
6 changes: 3 additions & 3 deletions spec/schedule_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "spec_helper"

RSpec.describe ElasticWhenever::Schedule do
let(:schedule) { ElasticWhenever::Schedule.new((Pathname(__dir__) + "fixtures/schedule.rb").to_s, []) }
let(:schedule) { ElasticWhenever::Schedule.new((Pathname(__dir__) + "fixtures/schedule.rb").to_s, false, []) }

describe "#initialize" do
it "has attributes" do
Expand All @@ -14,7 +14,7 @@
end

context "when received variables from cli" do
let(:schedule) { ElasticWhenever::Schedule.new((Pathname(__dir__) + "fixtures/schedule.rb").to_s, [{ key: "environment", value: "staging" }]) }
let(:schedule) { ElasticWhenever::Schedule.new((Pathname(__dir__) + "fixtures/schedule.rb").to_s, false, [{ key: "environment", value: "staging" }]) }

it "overrides attributes" do
expect(schedule.instance_variable_get(:@environment)).to eq "staging"
Expand All @@ -39,7 +39,7 @@
end

context "when use unsupported method" do
let(:schedule) { ElasticWhenever::Schedule.new((Pathname(__dir__) + "fixtures/unsupported_schedule.rb").to_s, []) }
let(:schedule) { ElasticWhenever::Schedule.new((Pathname(__dir__) + "fixtures/unsupported_schedule.rb").to_s, false, []) }

it "does not have tasks" do
expect(schedule.tasks.count).to eq(0)
Expand Down
8 changes: 4 additions & 4 deletions spec/task_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "spec_helper"

RSpec.describe ElasticWhenever::Task do
let(:task) { ElasticWhenever::Task.new("production", "bundle exec", "cron(0 17 * * ? *)") }
let(:task) { ElasticWhenever::Task.new("production", false, "bundle exec", "cron(0 17 * * ? *)") }

describe "#initialize" do
it "has attributes" do
Expand All @@ -23,7 +23,7 @@
end

context "when unset bundle command" do
let(:task) { ElasticWhenever::Task.new("production", "", "cron(0 17 * * ? *)") }
let(:task) { ElasticWhenever::Task.new("production", false, "", "cron(0 17 * * ? *)") }

it "generates rake commands" do
task.rake("hoge:run")
Expand All @@ -39,7 +39,7 @@
end

context "when unset bundle command" do
let(:task) { ElasticWhenever::Task.new("production", "", "cron(0 17 * * ? *)") }
let(:task) { ElasticWhenever::Task.new("production", false, "", "cron(0 17 * * ? *)") }

it "generates rake commands" do
task.runner("Hoge.run")
Expand All @@ -55,7 +55,7 @@
end

context "when unset bundle command" do
let(:task) { ElasticWhenever::Task.new("production", "", "cron(0 17 * * ? *)") }
let(:task) { ElasticWhenever::Task.new("production", false, "", "cron(0 17 * * ? *)") }

it "generates rake commands" do
task.script("runner.rb")
Expand Down
2 changes: 1 addition & 1 deletion spec/tasks/rule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

describe "convert" do
it "converts scheduled task syntax" do
task = ElasticWhenever::Task.new("production", "bundle exec", "cron(0 0 * * ? *)")
task = ElasticWhenever::Task.new("production", false, "bundle exec", "cron(0 0 * * ? *)")
task.rake "hoge:run"

expect(ElasticWhenever::Task::Rule.convert(option, task)).to have_attributes(
Expand Down
1 change: 1 addition & 0 deletions spec/tasks/target_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
}.to_json,
role_arn: "arn:aws:ecs:us-east-1:123456789:role/testRole",
ecs_parameters: {
launch_type: "EC2",
task_definition_arn: "arn:aws:ecs:us-east-1:123456789:task-definition/wordpress:2",
task_count: 1,
}
Expand Down