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

Enhancements: Security Group Search & Spot Instance Provisioning #470

Merged
merged 4 commits into from
Dec 29, 2019
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
45 changes: 27 additions & 18 deletions lib/kitchen/driver/aws/instance_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,26 @@ def initialize(config, ec2, logger)
# can be passed in null, others need to be ommitted if they are null
def ec2_instance_data # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
# Support for looking up security group id and subnet id using tags.

vpc_id = nil
client = ::Aws::EC2::Client.new(region: config[:region])
if config[:subnet_id].nil? && config[:subnet_filter]
config[:subnet_id] = ::Aws::EC2::Client
.new(region: config[:region]).describe_subnets(
filters: [
{
name: "tag:#{config[:subnet_filter][:tag]}",
values: [config[:subnet_filter][:value]],
},
]
)[0][0].subnet_id

if config[:subnet_id].nil?
raise "The subnet tagged '#{config[:subnet_filter][:tag]}\
#{config[:subnet_filter][:value]}' does not exist!"
end
subnets = client.describe_subnets(
filters: [
{
name: "tag:#{config[:subnet_filter][:tag]}",
values: [config[:subnet_filter][:value]],
},
]
).subnets
raise "The subnet tagged '#{config[:subnet_filter][:tag]}:#{config[:subnet_filter][:value]}' does not exist!" unless subnets.any?

vpc_id = subnets[0].vpc_id
config[:subnet_id] = subnets[0].subnet_id
end

if config[:security_group_ids].nil? && config[:security_group_filter]
# => Grab the VPC in the case a Subnet ID rather than Filter was set
vpc_id ||= client.describe_subnets(subnet_ids: [config[:subnet_id]]).subnets[0].vpc_id
security_groups = []
filters = [config[:security_group_filter]].flatten
filters.each do |sg_filter|
Expand All @@ -72,6 +73,10 @@ def ec2_instance_data # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
name: "group-name",
values: [sg_filter[:name]],
},
{
name: "vpc-id",
values: [vpc_id],
},
]
end

Expand All @@ -81,13 +86,17 @@ def ec2_instance_data # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
name: "tag:#{sg_filter[:tag]}",
values: [sg_filter[:value]],
},
{
name: "vpc-id",
values: [vpc_id],
},
]
end

security_group = ::Aws::EC2::Client.new(region: config[:region]).describe_security_groups(r)[0][0]
security_group = client.describe_security_groups(r).security_groups

if security_group
security_groups.push(security_group.group_id)
if security_group.any?
security_group.each { |sg| security_groups.push(sg.group_id) }
else
raise "A Security Group matching the following filter could not be found:\n#{sg_filter}"
end
Expand Down
8 changes: 5 additions & 3 deletions lib/kitchen/driver/ec2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -454,15 +454,16 @@ def submit_spots(state)
expanded = []
end

errs = []
configs.each do |conf|
begin
@config = conf
return submit_spot(state)
rescue
rescue => e
errs.append(e)
end
end

raise "Could not create a spot"
raise ["Could not create a spot instance:", errs].flatten.join("\n")
end

def submit_spot(state)
Expand Down Expand Up @@ -788,6 +789,7 @@ def create_security_group(state)
elsif config[:subnet_filter]
subnets = ec2.client.describe_subnets(filters: [{ name: "tag:#{config[:subnet_filter][:tag]}", values: [config[:subnet_filter][:value]] }]).subnets
raise "Subnets with tag '#{config[:subnet_filter][:tag]}=#{config[:subnet_filter][:value]}' not found during security group creation" if subnets.empty?

subnets.first.vpc_id
else
# Try to check for a default VPC.
Expand Down
30 changes: 29 additions & 1 deletion spec/kitchen/driver/aws/instance_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

describe Kitchen::Driver::Aws::InstanceGenerator do

let(:config) { {} }
let(:config) { { region: "us-east-1" } }
let(:resource) { instance_double(Aws::EC2::Resource) }
let(:ec2) { instance_double(Kitchen::Driver::Aws::Client, resource: resource) }
let(:logger) { instance_double(Logger) }
Expand Down Expand Up @@ -76,6 +76,7 @@
subnets: [
{
subnet_id: "s-123",
vpc_id: "vpc-456",
tags: [{ key: "foo", value: "bar" }],
},
]
Expand Down Expand Up @@ -105,6 +106,7 @@
context "when populated with minimum requirements" do
let(:config) do
{
region: "us-east-1",
instance_type: "micro",
ebs_optimized: true,
image_id: "ami-123",
Expand All @@ -128,6 +130,7 @@
context "when populated with ssh key" do
let(:config) do
{
region: "us-east-1",
instance_type: "micro",
ebs_optimized: true,
image_id: "ami-123",
Expand Down Expand Up @@ -204,6 +207,10 @@
name: "tag:foo",
values: ["bar"],
},
{
name: "vpc-id",
values: ["vpc-456"],
},
]
).and_return(ec2_stub.describe_security_groups)
expect(generator.ec2_instance_data[:security_group_ids]).to eq(["sg-123"])
Expand All @@ -212,6 +219,16 @@

context "when provided a non existing security_group tag filter" do
ec2_stub_whithout_security_group = Aws::EC2::Client.new(stub_responses: true)
ec2_stub_whithout_security_group.stub_responses(
:describe_subnets,
subnets: [
{
subnet_id: "s-123",
vpc_id: "vpc-456",
tags: [{ key: "foo", value: "bar" }],
},
]
)

let(:config) do
{
Expand All @@ -237,6 +254,10 @@
name: "tag:foo",
values: ["bar"],
},
{
name: "vpc-id",
values: ["vpc-456"],
},
]
).and_return(ec2_stub_whithout_security_group.describe_security_groups)

Expand All @@ -249,6 +270,7 @@
context "when passed an empty block_device_mappings" do
let(:config) do
{
region: "us-east-1",
instance_type: "micro",
ebs_optimized: true,
image_id: "ami-123",
Expand Down Expand Up @@ -416,6 +438,7 @@
context "when subnet_id is provided" do
let(:config) do
{
region: "us-east-1",
subnet_id: "s-456",
}
end
Expand All @@ -435,6 +458,7 @@
context "when associate_public_ip is provided" do
let(:config) do
{
region: "us-east-1",
associate_public_ip: true,
}
end
Expand All @@ -458,6 +482,7 @@
context "and subnet is provided" do
let(:config) do
{
region: "us-east-1",
associate_public_ip: true,
subnet_id: "s-456",
}
Expand All @@ -483,6 +508,7 @@
context "and security_group_ids is provided" do
let(:config) do
{
region: "us-east-1",
associate_public_ip: true,
security_group_ids: ["sg-789"],
}
Expand Down Expand Up @@ -522,6 +548,7 @@
context "and private_ip_address is provided" do
let(:config) do
{
region: "us-east-1",
associate_public_ip: true,
private_ip_address: "0.0.0.0",
}
Expand All @@ -548,6 +575,7 @@
context "when provided the maximum config" do
let(:config) do
{
region: "eu-west-1",
availability_zone: "eu-west-1a",
instance_type: "micro",
ebs_optimized: true,
Expand Down