lib/autoloads/genova/ecs/task/client.rb
require 'deep_merge/rails_compat'
module Genova
module Ecs
module Task
class Client
def initialize(logger)
@ecs_client = Aws::ECS::Client.new
@cipher = Genova::Utils::Cipher.new(logger)
@logger = logger
end
def register(path, task_overrides = {}, params = {})
raise IOError, "File does not exist. [#{path}]" unless File.file?(path)
yaml = YAML.unsafe_load(File.read(path))
task_definition = Oj.load(Oj.dump(yaml), symbol_keys: true)
merge_task_parameters!(task_definition, task_overrides) if task_overrides.present?
replace_parameter_variables!(task_definition, params)
decrypt_environment_variables!(task_definition)
task_definition[:tags] = [] if task_definition[:tags].nil?
task_definition[:tags] << { key: 'genova.version', value: Version::STRING }
task_definition[:tags] << { key: 'genova.build', value: params[:tag] }
result = @ecs_client.register_task_definition(task_definition)
@logger.info("Task created. [#{result[:task_definition][:task_definition_arn]}]")
result[:task_definition]
end
private
def merge_task_parameters!(task_definition, task_overrides)
# https://github.com/metaps/genova/issues/291
task_definition.deep_merge!(task_overrides.except(:container_definitions))
# Parameters consisting of arrays initialize the parent side of the merge.
# https://github.com/metaps/genova/issues/283
reset_array!(task_definition, task_overrides, :requires_compatibilities)
override_container_definitions!(task_definition, task_overrides)
task_definition
end
def reset_array!(task_definition, task_overrides, *params)
return unless task_definition.dig(*params).present?
return unless task_overrides.dig(*params).present?
if params.size > 1
value = task_definition.dig(*params[0..params.size - 2])
value[params[params.size - 1]] = []
else
task_definition[params[0]] = []
end
end
def override_container_definitions!(task_definition, task_overrides)
(task_overrides[:container_definitions] || []).each_with_index do |override_container_definition, index|
container_definition = task_definition[:container_definitions].find { |k, _v| k[:name] == override_container_definition[:name] }
next unless container_definition.present?
reset_array!(task_definition, task_overrides, :container_definitions, index, :command)
reset_array!(task_definition, task_overrides, :container_definitions, index, :entry_point)
reset_array!(task_definition, task_overrides, :container_definitions, index, :links)
reset_array!(task_definition, task_overrides, :container_definitions, index, :dns_servers)
reset_array!(task_definition, task_overrides, :container_definitions, index, :dns_search_domains)
reset_array!(task_definition, task_overrides, :container_definitions, index, :default_security_options)
reset_array!(task_definition, task_overrides, :container_definitions, index, :health_check, :command)
reset_array!(task_definition, task_overrides, :container_definitions, index, :linux_parameters, :capabilities, :add)
reset_array!(task_definition, task_overrides, :container_definitions, index, :linux_parameters, :capabilities, :drop)
merge_container_environment!(container_definition, override_container_definition)
container_definition.deeper_merge!(override_container_definition)
end
end
def merge_container_environment!(container_definition, override_container_definition)
return unless container_definition[:environment].present? && override_container_definition[:environment].present?
override_container_definition[:environment].each do |environment|
container_definition[:environment].delete_if { |k, _v| k[:name] == environment[:name] }
end
end
def replace_parameter_variables!(variables, params = {})
variables.each do |variable|
if variable.instance_of?(Array) || variable.instance_of?(Hash)
replace_parameter_variables!(variable, params)
elsif variable.instance_of?(String)
params.each do |replace_key, replace_value|
variable.gsub!("{{#{replace_key}}}", replace_value)
end
end
end
end
def decrypt_environment_variables!(task_definition)
raise Exceptions::TaskDefinitionValidationError, '\'container_definitions\' is undefined.' unless task_definition.key?(:container_definitions)
task_definition[:container_definitions].each do |container_definition|
next unless container_definition.key?(:environment)
container_definition[:environment].each do |environment|
if environment[:value].instance_of?(String)
environment[:value] = @cipher.decrypt(environment[:value]) if @cipher.encrypt_format?(environment[:value])
else
# https://github.com/naomichi-y/ecs_deployer/issues/6
environment[:value] = environment[:value].to_s
end
end
end
end
end
end
end
end