From c05ae6944b862874facad6e8ac54b94e30537325 Mon Sep 17 00:00:00 2001 From: David Siaw Date: Tue, 24 Nov 2020 21:48:01 +0900 Subject: [PATCH] routines to calculate instances required --- app/models/district.rb | 72 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/app/models/district.rb b/app/models/district.rb index 480f17e7..963de8d0 100644 --- a/app/models/district.rb +++ b/app/models/district.rb @@ -109,14 +109,26 @@ def subnets(network = "Private") ).subnets end + def container_instance_arns + @container_instance_arns ||= aws.ecs.list_container_instances( + cluster: name + ).container_instance_arns + end + + def cluster_container_instances + return [] if container_instance_arns.blank? + + @cluster_container_instances ||= aws.ecs.describe_container_instances( + cluster: name, + container_instances: container_instance_arns + ).container_instances + end + def container_instances - arns = aws.ecs.list_container_instances(cluster: name).container_instance_arns - return [] if arns.blank? - container_instances = aws.ecs. - describe_container_instances(cluster: name, container_instances: arns). - container_instances + return [] if cluster_container_instances.blank? + instances = {} - container_instances.each do |ci| + cluster_container_instances.each do |ci| instance = { status: ci.status, container_instance_arn: ci.container_instance_arn, @@ -129,7 +141,7 @@ def container_instances end ec2_instances = aws.ec2.describe_instances( - instance_ids: container_instances.map(&:ec2_instance_id) + instance_ids: cluster_container_instances.map(&:ec2_instance_id) ).reservations.map(&:instances).flatten ec2_instances.each do |ins| @@ -210,6 +222,52 @@ def update_notification_stack private + def total_registered(resource) + container_instances.pluck(:registered_resources) + .flatten + .select {|x| x.name == resource.to_s.upcase} + .sum {|x| x.integer_value} + end + + def demand_structure(resource) + heritages.flat_map(&:services).flat_map do |service| + # map all the containers' memory or cpu + definition = service.send(:backend).send(:ecs_service).task_definition + + # read the total amount requested by definition + total_resource = aws.ecs.describe_task_definition(task_definition: definition) + .task_definition + .container_definitions.sum { |condef| condef.send(resource.to_sym) } + { + count: service.desired_count, + amount: total_resource + } + + end.inject({}) do |x, i| + # aggregate all particular counts into a map + x[i[:amount]] ||= 0 + x[i[:amount]] += i[:count] + x + end + end + + def total_demanded(resource) + demand_structure(resource).sum{|amount, count| count * amount} + end + + def instance_count_demanded(resource) + per_instance = total_registered(resource) / container_instances.count + + # naively determine the number of instances needed for each service + demand_structure(resource).map do |k, v| + (k / 1699.to_f * v).ceil + end.sum + end + + def instances_recommended + [instance_count_demanded(:cpu), instance_count_demanded(:memory)].max + end + def validate_cidr_block if IPAddr.new(cidr_block).to_range.count < 65536 errors.add(:cidr_block, "subnet mask bits must be smaller than or equal to 16")