Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] ELBv2 Support #265

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ Lint/UselessAssignment:
# Configuration parameters: CountKeywordArgs.
Metrics/ParameterLists:
Max: 15

Metrics/LineLength:
Max: 100
16 changes: 16 additions & 0 deletions libraries/elbv2.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require File.join(File.dirname(__FILE__), 'ec2')

module Opscode
module Aws
module ElbV2
include Opscode::Aws::Ec2

def elbv2
require_aws_sdk

Chef::Log.debug('Initializing the ElasticLoadBalancingV2 Client')
@elbv2 ||= create_aws_interface(::Aws::ElasticLoadBalancingV2::Client)
end
end
end
end
Empty file added providers/elastic_lb_v2.rb
Empty file.
82 changes: 82 additions & 0 deletions resources/elastic_lb_v2.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Prerequisites: None

include Opscode::Aws::ElbV2

actions :create, :delete
default_action :create

property :aws_access_key, String
property :aws_secret_access_key, String
property :aws_session_token, String
property :aws_assume_role_arn, String
property :aws_role_session_name, String
property :region, String

property :name, String
property :subnets, Array, required: true
property :tags, Hash
property :scheme, callbacks: {
'Scheme must be either internet-facing or internal' => lambda do |scheme|
%w(internet-facing internal).include? scheme
end
}

load_current_value do
current_value_does_not_exist! unless lb
subnets lb.availability_zones.map(&:subnet_id)
raise 'Scheme of an existing LB cannot be modified' unless scheme == lb.scheme
scheme lb.scheme
tags current_tags_hash
end

action :create do
if lb
converge_if_changed :subnets do
converge_by("Modify the subnets associated with #{name}") do
elbv2.set_subnets(load_balancer_arn: lb.load_balancer_arn, subnets: subnets)
end
end

converge_if_changed :tags do
converge_by("Modify the tags associated with #{name}") do
tags_to_add = Hash[*(tags.to_a - current_tags_hash.to_a).flatten].map { |k, v| { k => v } }
tags_to_remove = Hash[*(current_tags_hash.to_a - tags.to_a).flatten].map { |k, v| { k => v } }

elbv2.add_tags resource_arns: [lb.load_balancer_arn], tags: tags_to_add
elbv2.remove_tags resource_arns: [lb.load_balancer_arn], tags: tags_to_remove
end
end
else
converge_by("Create v2 load balancer #{name}") do
elbv2.create_load_balancer(
name: name,
subnets: subnets,
security_groups: security_groups,
scheme: scheme,
tags: tags
)
end
end
end

action :delete do
return unless lb
converge_by("Removing v2 load balancer #{name}") do
elbv2.delete_load_balancer load_balacer_arn: lb.load_balancer_arn
end
end

def lb
@lb ||= begin
elbv2.describe_load_balancers(names: [name]).load_balancers.first
rescue Aws::ElasticLoadBalancingV2::Errors::LoadBalancerNotFound
nil
end
end

def current_tags_hash
@current_tags_hash ||= begin
tag_object = elbv2.describe_tags(resource_arns: [lb.load_balancer_arn])
tag_object.tag_descriptions.first.tags.each_with_object { |tag, memo| memo[tag.key] = tag.value }
end
end
3 changes: 3 additions & 0 deletions resources/elastic_lb_v2_listener.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Prerequisites:
# - load_balancer_arn
# - target_group_arn
99 changes: 99 additions & 0 deletions resources/elastic_lb_v2_target_group.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Prerequisites: None

include Opscode::Aws::ElbV2

actions :create, :delete
default_action :create

property :aws_access_key, String
property :aws_secret_access_key, String
property :aws_session_token, String
property :aws_assume_role_arn, String
property :aws_role_session_name, String
property :region, String

property :name, String
property :vpc_id, String, required: true
property :health_check, Hash
property :tags, Hash
property :protocol, String, required: true, callbacks: {
'Protocol must be either HTTP or HTTPS' => ->(pr) { pr =~ /^https?$/ }
}
property :port, required: true, callbacks: {
'Port must be a number between 1 and 65535' => lambda do |cur_port|
cur_port = cur_port.to_i
cur_port > 0 && cur_port < 2**16
end
}

load_current_value do
current_value_does_not_exist! unless tg
raise 'VPC ID of an existing target group cannot be modified' unless vpc_id == tg.vpc_id
tags current_tags_hash
health_check health_check_hash
end

action :create do
if tg
converge_if_changed :tags do
converge_by("Modify the tags associated with #{name}") do
tags_to_add = Hash[*(tags.to_a - current_tags_hash.to_a).flatten].map { |k, v| { k => v } }
tags_to_remove = Hash[*(current_tags_hash.to_a - tags.to_a).flatten].map { |k, v| { k => v } }

elbv2.add_tags resource_arns: [tg.target_group_arn], tags: tags_to_add
elbv2.remove_tags resource_arns: [tg.target_group_arn], tags: tags_to_remove
end
end

converge_if_changed :health_check do
elbv2.modify_target_group health_check_hash.merge target_group_arn: tg.target_group_arn
end
else
converge_by("Create target group #{name}") do
elbv2.create_target_group(
name: name,
subnets: subnets,
security_groups: security_groups,
scheme: scheme,
tags: tags
)
end
end
end

action :delete do
return unless tg
converge_by("Removing target group #{name}") do
elbv2.delete_target_group target_group_arn: tg.target_group_arn
end
end

def tg
@tg ||= begin
elbv2.describe_target_groups(names: [name]).target_groups.first
rescue Aws::ElasticLoadBalancingV2::Errors::TargetGroupNotFound
nil
end
end

def health_check_hash
output = { matcher: { http_code: tg.matcher.http_code } }

%i(
health_check_protocol
health_check_port
health_check_interval_seconds
health_check_timeout_seconds
healthy_threshold_count
unhealthy_threshold_count
health_check_path
).each { |key_sym| output[key_sym] = tg.send key_sym }
output
end

def current_tags_hash
@current_tags_hash ||= begin
tag_object = elbv2.describe_tags(resource_arns: [tg.target_group_arn])
tag_object.tag_descriptions.first.tags.each_with_object { |tag, memo| memo[tag.key] = tag.value }
end
end