require 'applb/dsl/checker' require 'applb/dsl/attributes' require 'applb/dsl/listeners' require 'applb/dsl/target_groups' module Applb class DSL class EC2 class LoadBalancer include Applb::DSL::Checker include Applb::TemplateHelper class Result ATTRIBUTES = %i/name instances scheme subnets security_groups tags ip_address_type attributes target_groups listeners load_balancer_arn/ attr_accessor *ATTRIBUTES def initialize(context) @context = context @options = context.options end def to_h Hash[ATTRIBUTES.sort.map { |name| [name, public_send(name)] }] end CREATE_KEYS = %i/name subnets security_groups scheme tags ip_address_type/ def create_option to_h.select { |k, _| CREATE_KEYS.include?(k) } end def create Applb.logger.info "Create ELB v2 #{name}" return if @options[:dry_run] client.create_load_balancer(create_option).load_balancers.first end def aws(aws_lb) @aws_lb = aws_lb self end def subnets_updated? subnets.sort != @aws_lb.availability_zones.map(&:subnet_id).sort end def security_groups_updated? security_groups.sort != @aws_lb.security_groups.sort end def ip_address_type_updated? ip_address_type != @aws_lb.ip_address_type end def modify_subnets return unless subnets_updated? Applb.logger.info("Modify #{name} subnets") diff = Applb::Utils.diff( @aws_lb.availability_zones.map(&:subnet_id).sort, subnets.sort, color: @options[:color], ) Applb.logger.info("\n#{diff}") return if @options[:dry_run] client.set_subnets( load_balancer_arn: @aws_lb.load_balancer_arn, subnets: subnets, ).availability_zones end def modify_security_groups return unless security_groups_updated? Applb.logger.info "Modify #{name} security_groups" diff = Applb::Utils.diff( @aws_lb.security_groups.sort, security_groups.sort, color: @options[:color], ) Applb.logger.info("\n#{diff}") return if @options[:dry_run] client.set_security_groups( load_balancer_arn: @aws_lb.load_balancer_arn, security_groups: security_groups, ).security_group_ids end def modify_ip_address_type return unless ip_address_type_updated? Applb.logger.info "Modify #{name} ip_address_type" diff = Applb::Utils.diff( @aws_lb.ip_address_type, ip_address_type, color: @options[:color], ) Applb.logger.info("\n#{diff}") return if @options[:dry_run] client.set_ip_address_type( load_balancer_arn: @aws_lb.load_balancer_arn, ip_address_type: ip_address_type, ).ip_address_type end def modify_load_balancer_attributes attrs = attributes.map do |attr| {key: attr[:key], value: attr[:value].to_s} end log_enabled = attrs.find { |attr| attr[:key] == 'access_logs.s3.enabled' }[:value] if log_enabled.to_s == 'false' attrs.reject! do |attr| %w/access_logs.s3.bucket access_logs.s3.prefix/.include?(attr[:key]) end end dsl_hash = attrs.map { |a| a.to_h }.sort { |a, b| a[:key] <=> b[:key] } aws_attributes = client.describe_load_balancer_attributes( load_balancer_arn: @aws_lb.load_balancer_arn, ).attributes aws_hash = aws_attributes.map { |a| a.to_h }.sort { |a, b| a[:key] <=> b[:key] } aws_log_enabled = aws_attributes.find { |attr| attr[:key] == 'access_logs.s3.enabled' }[:value] if aws_log_enabled == 'false' aws_hash.reject! do |attr| %w/access_logs.s3.bucket access_logs.s3.prefix/.include?(attr[:key]) end end return if dsl_hash == aws_hash Applb.logger.info "Modify #{name} load_balancer_attributes" Applb.logger.info("\n#{Applb::Utils.diff(aws_hash, dsl_hash, color: @options[:color])}") return if @options[:dry_run] client.modify_load_balancer_attributes( load_balancer_arn: @aws_lb.load_balancer_arn, attributes: attrs, ).attributes end private def client @client ||= Applb::ClientWrapper.new(@options) end end def initialize(context, name, vpc_id, &block) @name = name @vpc_id = vpc_id @context = context.merge(name: name) @result = Result.new(@context) @result.name = name @result.attributes = Attributes.new(@context, @name) {}.result @result.instances = [] @result.target_groups = [] @result.listeners = [] instance_eval(&block) end def result required(:subnets, @result.subnets) required(:security_groups, @result.security_groups) @result end private def subnets(*subnets) @result.subnets = subnets end def security_groups(*security_groups) @result.security_groups = security_groups end def scheme(scheme) @result.scheme = scheme end def tags(tags) @result.tags = tags.map { |k, v| { key: k, value: v } } end def ip_address_type(ip_address_type) @result.ip_address_type = ip_address_type end def attributes(&block) @result.attributes = Attributes.new(@context, @name, &block).result end def target_groups(&block) @result.target_groups = TargetGroups.new(@context, @name, &block).result end def listeners(&block) @result.listeners = Listeners.new(@context, @name, &block).result end end end end end