diff --git a/README.md b/README.md index 5475dfc1..81696811 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ Commands: terraforming igw # Internet Gateway terraforming lc # Launch Configuration terraforming nacl # Network ACL + terraforming nat # NAT Gateway terraforming nif # Network Interface terraforming opwcl # OpsWorks Custom Layer terraforming opws # OpsWorks Stack diff --git a/lib/terraforming.rb b/lib/terraforming.rb index 707a2c48..5b411ed5 100644 --- a/lib/terraforming.rb +++ b/lib/terraforming.rb @@ -39,6 +39,7 @@ require "terraforming/resource/iam_user_policy" require "terraforming/resource/launch_configuration" require "terraforming/resource/internet_gateway" +require "terraforming/resource/nat_gateway" require "terraforming/resource/network_acl" require "terraforming/resource/network_interface" require "terraforming/resource/opsworks_custom_layer" diff --git a/lib/terraforming/cli.rb b/lib/terraforming/cli.rb index dad4409f..27dc60b2 100644 --- a/lib/terraforming/cli.rb +++ b/lib/terraforming/cli.rb @@ -116,6 +116,11 @@ def nacl execute(Terraforming::Resource::NetworkACL, options) end + desc "nat", "NAT Gateway" + def nat + execute(Terraforming::Resource::NATGateway, options) + end + desc "nif", "Network Interface" def nif execute(Terraforming::Resource::NetworkInterface, options) diff --git a/lib/terraforming/resource/nat_gateway.rb b/lib/terraforming/resource/nat_gateway.rb new file mode 100644 index 00000000..87024d33 --- /dev/null +++ b/lib/terraforming/resource/nat_gateway.rb @@ -0,0 +1,57 @@ +module Terraforming + module Resource + class NATGateway + include Terraforming::Util + + def self.tf(client: Aws::EC2::Client.new) + self.new(client).tf + end + + def self.tfstate(client: Aws::EC2::Client.new) + self.new(client).tfstate + end + + def initialize(client) + @client = client + end + + def tf + apply_template(@client, "tf/nat_gateway") + end + + def tfstate + nat_gateways.inject({}) do |resources, nat_gateway| + next resources if nat_gateway.nat_gateway_addresses.empty? + + attributes = { + "id" => nat_gateway.nat_gateway_id, + "allocation_id" => nat_gateway.nat_gateway_addresses[0].allocation_id, + "subnet_id" => nat_gateway.subnet_id, + "network_inferface_id" => nat_gateway.nat_gateway_addresses[0].network_interface_id, + "private_ip" => nat_gateway.nat_gateway_addresses[0].private_ip, + "public_ip" => nat_gateway.nat_gateway_addresses[0].public_ip, + } + resources["aws_nat_gateway.#{module_name_of(nat_gateway)}"] = { + "type" => "aws_nat_gateway", + "primary" => { + "id" => nat_gateway.nat_gateway_id, + "attributes" => attributes + } + } + + resources + end + end + + private + + def nat_gateways + @client.describe_nat_gateways.nat_gateways + end + + def module_name_of(nat_gateway) + normalize_module_name(nat_gateway.nat_gateway_id) + end + end + end +end diff --git a/lib/terraforming/template/tf/nat_gateway.erb b/lib/terraforming/template/tf/nat_gateway.erb new file mode 100644 index 00000000..87ee7aaa --- /dev/null +++ b/lib/terraforming/template/tf/nat_gateway.erb @@ -0,0 +1,9 @@ +<% nat_gateways.each do |nat_gateway| -%> +<% unless nat_gateway.nat_gateway_addresses.empty? -%> +resource "aws_nat_gateway" "<%= module_name_of(nat_gateway) %>" { + allocation_id = "<%= nat_gateway.nat_gateway_addresses[0].allocation_id %>" + subnet_id = "<%= nat_gateway.subnet_id %>" +} + +<% end -%> +<% end -%> diff --git a/spec/lib/terraforming/resource/nat_gateway_spec.rb b/spec/lib/terraforming/resource/nat_gateway_spec.rb new file mode 100644 index 00000000..4a09cf50 --- /dev/null +++ b/spec/lib/terraforming/resource/nat_gateway_spec.rb @@ -0,0 +1,92 @@ +require "spec_helper" + +module Terraforming + module Resource + describe NATGateway do + let(:client) do + Aws::EC2::Client.new(stub_responses: true) + end + + let(:nat_gateways) do + [ + { + nat_gateway_id: "nat-0c5b68b2c4d64e037", + subnet_id: "subnet-cd5645f7", + nat_gateway_addresses: [ + allocation_id: "eipalloc-b02a3c79", + network_interface_id: "eni-03d4046f", + private_ip: "10.0.3.6", + public_ip: "52.5.3.67", + ] + }, + { + nat_gateway_id: "nat-0c5b68b2c4d64ea12", + subnet_id: "subnet-cd564c9e", + nat_gateway_addresses: [ + allocation_id: "eipalloc-a03a3c79", + network_interface_id: "eni-b6e4046f", + private_ip: "10.0.4.6", + public_ip: "54.4.5.68", + ] + } + ] + end + + before do + client.stub_responses(:describe_nat_gateways, nat_gateways: nat_gateways) + end + + describe ".tf" do + it "should generate tf" do + expect(described_class.tf(client: client)).to eq <<-EOS +resource "aws_nat_gateway" "nat-0c5b68b2c4d64e037" { + allocation_id = "eipalloc-b02a3c79" + subnet_id = "subnet-cd5645f7" +} + +resource "aws_nat_gateway" "nat-0c5b68b2c4d64ea12" { + allocation_id = "eipalloc-a03a3c79" + subnet_id = "subnet-cd564c9e" +} + + EOS + end + end + + describe ".tfstate" do + it "should generate tfstate" do + expect(described_class.tfstate(client: client)).to eq({ + "aws_nat_gateway.nat-0c5b68b2c4d64e037" => { + "type" => "aws_nat_gateway", + "primary" => { + "id" => "nat-0c5b68b2c4d64e037", + "attributes" => { + "id" => "nat-0c5b68b2c4d64e037", + "allocation_id" => "eipalloc-b02a3c79", + "subnet_id" => "subnet-cd5645f7", + "network_inferface_id" => "eni-03d4046f", + "private_ip" => "10.0.3.6", + "public_ip" => "52.5.3.67", + } + } + }, + "aws_nat_gateway.nat-0c5b68b2c4d64ea12" => { + "type" => "aws_nat_gateway", + "primary" => { + "id" => "nat-0c5b68b2c4d64ea12", + "attributes" => { + "id" => "nat-0c5b68b2c4d64ea12", + "allocation_id" => "eipalloc-a03a3c79", + "subnet_id" => "subnet-cd564c9e", + "network_inferface_id" => "eni-b6e4046f", + "private_ip" => "10.0.4.6", + "public_ip" => "54.4.5.68", + } + } + }, + }) + end + end + end + end +end