terraforming 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 732437685979fbd266b3f855c81ffb184be35856
4
- data.tar.gz: 5f3ef26d21cab520886d5a4ebff23e2af13d5b03
3
+ metadata.gz: 3a6da3b6025e72dbde110224ba597ae281004e64
4
+ data.tar.gz: a8ab14e29325070270895d2bd7d9dfc1f456bb64
5
5
  SHA512:
6
- metadata.gz: c564d548f74b3650cf1509388cafd66bc831e705f16c881f05aa8cf5507aa93e35106f15eb5b0f74f77cbacae9f342508751417219e3ae009c94339806d6cd72
7
- data.tar.gz: e451f2a2619e7cad7658fbfc33155fe948edb7e583fb2f4cb914b3b16d9a4dd6a444b98d08ec2301a56cb28bb876aebd2c454bb5797cbbfff864b9fa2e8d69f6
6
+ metadata.gz: 7611a6cc8554f7661ff3c579306becffc4da9ed077e8087b7c1e68e57b14eed25cbdb7d1e8d342fd4c547daf1c1788ed9ec30b22c4eba19c46d66458d8bfbc67
7
+ data.tar.gz: 8435e655557d88686a783ae7045a0ecd8a5deb10514be0645372caf92eb7855f49024b10294be8faeb78caaf6d49be1f18b39009c6d2997611fcfd205de4c1ec
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # [v0.1.2](https://github.com/dtan4/terraforming/releases/tag/v0.1.2) (2015-07-30)
2
+
3
+ ## Fixed
4
+
5
+ - Generate correct tf and tfstate of EC2 #94, #102
6
+ - Handle multiple Route53 record types #99 (thanks @nicgrayson)
7
+ - Generate correct tfstate of ELB #91 (thanks @grosendorf)
8
+
1
9
  # [v0.1.1](https://github.com/dtan4/terraforming/releases/tag/v0.1.1) (2015-07-14)
2
10
 
3
11
  ### Resource
data/README.md CHANGED
@@ -60,8 +60,11 @@ Commands:
60
60
  terraforming dbsg # Database Security Group
61
61
  terraforming dbsn # Database Subnet Group
62
62
  terraforming ec2 # EC2
63
+ terraforming ecc # ElastiCache Cluster
64
+ terraforming ecsn # ElastiCache Subnet Group
63
65
  terraforming elb # ELB
64
66
  terraforming iamg # IAM Group
67
+ terraforming iamgm # IAM Group Membership
65
68
  terraforming iamgp # IAM Group Policy
66
69
  terraforming iamip # IAM Instance Profile
67
70
  terraforming iamp # IAM Policy
@@ -21,25 +21,31 @@ module Terraforming
21
21
 
22
22
  def tfstate(tfstate_base)
23
23
  resources = instances.inject({}) do |result, instance|
24
+ in_vpc = in_vpc?(instance)
25
+ block_devices = block_devices_of(instance)
26
+
24
27
  attributes = {
25
28
  "ami"=> instance.image_id,
26
29
  "associate_public_ip_address"=> "true",
27
30
  "availability_zone"=> instance.placement.availability_zone,
28
- "ebs_block_device.#"=> instance.block_device_mappings.length.to_s,
31
+ "ebs_block_device.#"=> ebs_block_devices_in(block_devices, instance).length.to_s,
29
32
  "ebs_optimized"=> instance.ebs_optimized.to_s,
30
- "ephemeral_block_device.#"=> "0",
33
+ "ephemeral_block_device.#" => "0", # Terraform 0.6.1 cannot fetch this field from AWS
31
34
  "id"=> instance.instance_id,
32
35
  "instance_type"=> instance.instance_type,
33
36
  "private_dns"=> instance.private_dns_name,
34
37
  "private_ip"=> instance.private_ip_address,
35
38
  "public_dns"=> instance.public_dns_name,
36
39
  "public_ip"=> instance.public_ip_address,
37
- "root_block_device.#"=> instance.root_device_name ? "1" : "0",
38
- "security_groups.#"=> instance.security_groups.length.to_s,
40
+ "root_block_device.#"=> root_block_devices_in(block_devices, instance).length.to_s,
41
+ "security_groups.#"=> in_vpc ? "0" : instance.security_groups.length.to_s,
39
42
  "source_dest_check"=> instance.source_dest_check.to_s,
40
- "subnet_id"=> instance.subnet_id,
41
- "tenancy"=> instance.placement.tenancy
43
+ "tenancy"=> instance.placement.tenancy,
44
+ "vpc_security_group_ids.#"=> in_vpc ? instance.security_groups.length.to_s : "0",
42
45
  }
46
+
47
+ attributes["subnet_id"] = instance.subnet_id if in_vpc?(instance)
48
+
43
49
  result["aws_instance.#{module_name_of(instance)}"] = {
44
50
  "type" => "aws_instance",
45
51
  "primary" => {
@@ -59,13 +65,53 @@ module Terraforming
59
65
 
60
66
  private
61
67
 
68
+ def block_device_ids_of(instance)
69
+ instance.block_device_mappings.map { |bdm| bdm.ebs.volume_id }
70
+ end
71
+
72
+ def block_devices_of(instance)
73
+ @client.describe_volumes(volume_ids: block_device_ids_of(instance)).volumes
74
+ end
75
+
76
+ def block_device_mapping_of(instance, volume_id)
77
+ instance.block_device_mappings.select { |bdm| bdm.ebs.volume_id == volume_id }[0]
78
+ end
79
+
80
+ def ebs_block_devices_in(block_devices, instance)
81
+ block_devices.reject do |bd|
82
+ root_block_device?(block_device_mapping_of(instance, bd.volume_id), instance)
83
+ end
84
+ end
85
+
86
+ #
87
+ # NOTE(dtan4):
88
+ # Original logic is here:
89
+ # https://github.com/hashicorp/terraform/blob/281e4d3e67f66daab9cdb1f7c8b6f602d949e5ee/builtin/providers/aws/resource_aws_instance.go#L481-L501
90
+ #
91
+ def in_vpc?(instance)
92
+ vpc_security_groups_of(instance).length > 0 ||
93
+ (instance.subnet_id && instance.subnet_id != "" && instance.security_groups.length == 0)
94
+ end
95
+
62
96
  def instances
63
- @client.describe_instances.reservations.map(&:instances).flatten
97
+ @client.describe_instances.reservations.map(&:instances).flatten.reject { |instance| instance.state.name == "terminated" }
64
98
  end
65
99
 
66
100
  def module_name_of(instance)
67
101
  normalize_module_name(name_from_tag(instance, instance.instance_id))
68
102
  end
103
+
104
+ def root_block_device?(block_device_mapping, instance)
105
+ block_device_mapping.device_name == instance.root_device_name
106
+ end
107
+
108
+ def root_block_devices_in(block_devices, instance)
109
+ block_devices.select { |bd| root_block_device?(block_device_mapping_of(instance, bd.volume_id), instance) }
110
+ end
111
+
112
+ def vpc_security_groups_of(instance)
113
+ instance.security_groups.select { |security_group| /\Asg-/ =~ security_group.group_id }
114
+ end
69
115
  end
70
116
  end
71
117
  end
@@ -28,16 +28,21 @@ module Terraforming
28
28
  "connection_draining_timeout" => load_balancer_attributes.connection_draining.timeout.to_s,
29
29
  "cross_zone_load_balancing" => load_balancer_attributes.cross_zone_load_balancing.enabled.to_s,
30
30
  "dns_name" => load_balancer.dns_name,
31
- "health_check.#" => "1",
32
31
  "id" => load_balancer.load_balancer_name,
33
32
  "idle_timeout" => load_balancer_attributes.connection_settings.idle_timeout.to_s,
34
33
  "instances.#" => load_balancer.instances.length.to_s,
35
- "listener.#" => load_balancer.listener_descriptions.length.to_s,
36
34
  "name" => load_balancer.load_balancer_name,
37
- "security_groups.#" => load_balancer.security_groups.length.to_s,
38
35
  "source_security_group" => load_balancer.source_security_group.group_name,
39
- "subnets.#" => load_balancer.subnets.length.to_s,
40
36
  }
37
+
38
+ attributes.merge!(healthcheck_attributes_of(load_balancer))
39
+ attributes.merge!(listeners_attributes_of(load_balancer))
40
+ attributes.merge!(sg_attributes_of(load_balancer))
41
+ attributes.merge!(subnets_attributes_of(load_balancer))
42
+ attributes.merge!(instances_attributes_of(load_balancer))
43
+ attributes.merge!(tags_attributes_of(load_balancer))
44
+
45
+
41
46
  result["aws_elb.#{module_name_of(load_balancer)}"] = {
42
47
  "type" => "aws_elb",
43
48
  "primary" => {
@@ -52,6 +57,108 @@ module Terraforming
52
57
  generate_tfstate(resources, tfstate_base)
53
58
  end
54
59
 
60
+ def healthcheck_attributes_of(elb)
61
+ hashcode = healthcheck_hashcode_of(elb.health_check)
62
+ attributes = {
63
+ # Now each ELB supports one heatlhcheck
64
+ "health_check.#" => "1",
65
+ "health_check.#{hashcode}.healthy_threshold" => elb.health_check.healthy_threshold.to_s,
66
+ "health_check.#{hashcode}.interval" => elb.health_check.interval.to_s,
67
+ "health_check.#{hashcode}.target" => elb.health_check.target,
68
+ "health_check.#{hashcode}.timeout" => elb.health_check.timeout.to_s,
69
+ "health_check.#{hashcode}.unhealthy_threshold" => elb.health_check.unhealthy_threshold.to_s
70
+ }
71
+
72
+ attributes
73
+ end
74
+
75
+ def healthcheck_hashcode_of(health_check)
76
+ string =
77
+ "#{health_check.healthy_threshold}-" <<
78
+ "#{health_check.unhealthy_threshold}-" <<
79
+ "#{health_check.target}-" <<
80
+ "#{health_check.interval}-" <<
81
+ "#{health_check.timeout}-"
82
+
83
+ Zlib.crc32(string)
84
+ end
85
+
86
+ def tags_attributes_of(elb)
87
+ tags = @client.describe_tags(load_balancer_names: [elb.load_balancer_name]).tag_descriptions.first.tags
88
+ attributes = {"tags.#" => tags.length.to_s}
89
+
90
+ tags.each do |tag|
91
+ attributes["tags.#{tag.key}"] = tag.value
92
+ end
93
+
94
+ attributes
95
+ end
96
+
97
+ def instances_attributes_of(elb)
98
+ attributes = {"instances.#" => elb.instances.length.to_s}
99
+
100
+ elb.instances.each do |instance|
101
+ attributes["instances.#{Zlib.crc32(instance.instance_id)}"] = instance.instance_id
102
+ end
103
+
104
+ attributes
105
+ end
106
+
107
+ def subnets_attributes_of(elb)
108
+ attributes = {"subnets.#" => elb.subnets.length.to_s}
109
+
110
+ elb.subnets.each do |subnet_id|
111
+ attributes["subnets.#{Zlib.crc32(subnet_id)}"] = subnet_id
112
+ end
113
+
114
+ attributes
115
+ end
116
+
117
+ def sg_attributes_of(elb)
118
+ attributes = {"security_groups.#" => elb.security_groups.length.to_s}
119
+
120
+ elb.security_groups.each do |sg_id|
121
+ attributes["security_groups.#{Zlib.crc32(sg_id)}"] = sg_id
122
+ end
123
+
124
+ attributes
125
+ end
126
+
127
+ def listeners_attributes_of(elb)
128
+ attributes = {"listener.#" => elb.listener_descriptions.length.to_s}
129
+
130
+ elb.listener_descriptions.each do |listener_description|
131
+ attributes.merge!(listener_attributes_of(listener_description.listener))
132
+ end
133
+
134
+ attributes
135
+ end
136
+
137
+ def listener_attributes_of(listener)
138
+ hashcode = listener_hashcode_of(listener)
139
+
140
+ attributes = {
141
+ "listener.#{hashcode}.instance_port" => listener.instance_port.to_s,
142
+ "listener.#{hashcode}.instance_protocol" => listener.instance_protocol.downcase,
143
+ "listener.#{hashcode}.lb_port" => listener.load_balancer_port.to_s,
144
+ "listener.#{hashcode}.lb_protocol" => listener.protocol.downcase,
145
+ "listener.#{hashcode}.ssl_certificate_id" => listener.ssl_certificate_id
146
+ }
147
+
148
+ attributes
149
+ end
150
+
151
+ def listener_hashcode_of(listener)
152
+ string =
153
+ "#{listener.instance_port}-" <<
154
+ "#{listener.instance_protocol.downcase}-" <<
155
+ "#{listener.load_balancer_port}-" <<
156
+ "#{listener.protocol.downcase}-" <<
157
+ "#{listener.ssl_certificate_id}-"
158
+
159
+ Zlib.crc32(string)
160
+ end
161
+
55
162
  def load_balancers
56
163
  @client.describe_load_balancers.load_balancer_descriptions
57
164
  end
@@ -77,7 +77,7 @@ module Terraforming
77
77
  end
78
78
 
79
79
  def module_name_of(record)
80
- normalize_module_name(name_of(record.name))
80
+ normalize_module_name(name_of(record.name) + "-" + record.type)
81
81
  end
82
82
 
83
83
  def zone_id_of(hosted_zone)
@@ -5,16 +5,35 @@ resource "aws_instance" "<%= module_name_of(instance) %>" {
5
5
  ebs_optimized = <%= instance.ebs_optimized %>
6
6
  instance_type = "<%= instance.instance_type %>"
7
7
  key_name = "<%= instance.key_name %>"
8
- security_groups = <%= instance.security_groups.map { |sg| sg.group_id }.inspect %>
8
+ <%- if in_vpc?(instance) -%>
9
9
  subnet_id = "<%= instance.subnet_id %>"
10
+ vpc_security_group_ids = <%= instance.security_groups.map { |sg| sg.group_id }.inspect %>
11
+ <%- else -%>
12
+ security_groups = <%= instance.security_groups.map { |sg| sg.group_name }.inspect %>
13
+ <%- end -%>
10
14
  associate_public_ip_address = true
11
15
  private_ip = "<%= instance.private_ip_address %>"
12
16
  source_dest_check = <%= instance.source_dest_check %>
13
17
 
14
- <% instance.block_device_mappings.each do |block_device| -%>
18
+ <% block_devices_of(instance).each do |block_device| -%>
19
+ <%- mapping = block_device_mapping_of(instance, block_device.volume_id) -%>
20
+ <%- if root_block_device?(mapping, instance) -%>
21
+ root_block_device {
22
+ volume_type = "<%= block_device.volume_type %>"
23
+ volume_size = <%= block_device.size %>
24
+ iops = <%= block_device.iops %>
25
+ delete_on_termination = <%= mapping.ebs.delete_on_termination %>
26
+ }
27
+ <%- else -%>
15
28
  ebs_block_device {
16
- device_name = "<%= block_device.device_name %>"
29
+ device_name = "<%= mapping.device_name %>"
30
+ snapshot_id = "<%= block_device.snapshot_id %>"
31
+ volume_type = "<%= block_device.volume_type %>"
32
+ volume_size = <%= block_device.size %>
33
+ iops = <%= block_device.iops %>
34
+ delete_on_termination = <%= mapping.ebs.delete_on_termination %>
17
35
  }
36
+ <% end -%>
18
37
 
19
38
  <% end -%>
20
39
  tags {
@@ -31,6 +31,12 @@ resource "aws_elb" "<%= module_name_of(load_balancer) %>" {
31
31
  target = "<%= load_balancer.health_check.target %>"
32
32
  timeout = <%= load_balancer.health_check.timeout %>
33
33
  }
34
+
35
+ tags {
36
+ <% @client.describe_tags(load_balancer_names: [load_balancer.load_balancer_name]).tag_descriptions.first.tags.each do |tag| -%>
37
+ <%= tag.key %> = "<%= tag.value %>"
38
+ <% end -%>
39
+ }
34
40
  }
35
41
 
36
42
  <% end -%>
@@ -1,3 +1,3 @@
1
1
  module Terraforming
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terraforming
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daisuke Fujita
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-14 00:00:00.000000000 Z
11
+ date: 2015-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -258,9 +258,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
258
  version: '0'
259
259
  requirements: []
260
260
  rubyforge_project:
261
- rubygems_version: 2.4.7
261
+ rubygems_version: 2.4.5
262
262
  signing_key:
263
263
  specification_version: 4
264
264
  summary: Export existing AWS resources to Terraform style (tf, tfstate)
265
265
  test_files: []
266
- has_rdoc: