terraforming 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -1
- data/README.md +12 -2
- data/lib/terraforming.rb +4 -0
- data/lib/terraforming/cli.rb +33 -20
- data/lib/terraforming/resource/db_parameter_group.rb +5 -5
- data/lib/terraforming/resource/db_security_group.rb +5 -5
- data/lib/terraforming/resource/db_subnet_group.rb +5 -5
- data/lib/terraforming/resource/ec2.rb +5 -5
- data/lib/terraforming/resource/elb.rb +9 -5
- data/lib/terraforming/resource/iam_group.rb +5 -5
- data/lib/terraforming/resource/iam_group_policy.rb +6 -6
- data/lib/terraforming/resource/iam_instance_profile.rb +52 -0
- data/lib/terraforming/resource/iam_policy.rb +6 -6
- data/lib/terraforming/resource/iam_role.rb +53 -0
- data/lib/terraforming/resource/iam_role_policy.rb +69 -0
- data/lib/terraforming/resource/iam_user.rb +5 -5
- data/lib/terraforming/resource/iam_user_policy.rb +6 -6
- data/lib/terraforming/resource/network_acl.rb +10 -5
- data/lib/terraforming/resource/rds.rb +5 -5
- data/lib/terraforming/resource/route53_record.rb +5 -5
- data/lib/terraforming/resource/route53_zone.rb +5 -5
- data/lib/terraforming/resource/s3.rb +5 -5
- data/lib/terraforming/resource/security_group.rb +86 -7
- data/lib/terraforming/resource/subnet.rb +5 -5
- data/lib/terraforming/resource/vpc.rb +5 -5
- data/lib/terraforming/template/tf/elb.erb +4 -1
- data/lib/terraforming/template/tf/iam_group_policy.erb +1 -1
- data/lib/terraforming/template/tf/iam_instance_profile.erb +8 -0
- data/lib/terraforming/template/tf/iam_policy.erb +1 -1
- data/lib/terraforming/template/tf/iam_role.erb +10 -0
- data/lib/terraforming/template/tf/iam_role_policy.erb +10 -0
- data/lib/terraforming/template/tf/iam_user_policy.erb +1 -1
- data/lib/terraforming/template/tf/network_acl.erb +2 -1
- data/lib/terraforming/template/tf/security_group.erb +11 -2
- data/lib/terraforming/util.rb +21 -6
- data/lib/terraforming/version.rb +1 -1
- data/terraforming.gemspec +1 -1
- metadata +11 -12
@@ -3,12 +3,12 @@ module Terraforming
|
|
3
3
|
class Route53Zone
|
4
4
|
include Terraforming::Util
|
5
5
|
|
6
|
-
def self.tf(client
|
6
|
+
def self.tf(client: Aws::Route53::Client.new)
|
7
7
|
self.new(client).tf
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.tfstate(client
|
11
|
-
self.new(client).tfstate
|
10
|
+
def self.tfstate(client: Aws::Route53::Client.new, tfstate_base: nil)
|
11
|
+
self.new(client).tfstate(tfstate_base)
|
12
12
|
end
|
13
13
|
|
14
14
|
def initialize(client)
|
@@ -19,7 +19,7 @@ module Terraforming
|
|
19
19
|
apply_template(@client, "tf/route53_zone")
|
20
20
|
end
|
21
21
|
|
22
|
-
def tfstate
|
22
|
+
def tfstate(tfstate_base)
|
23
23
|
resources = hosted_zones.inject({}) do |result, hosted_zone|
|
24
24
|
zone_id = zone_id_of(hosted_zone)
|
25
25
|
|
@@ -41,7 +41,7 @@ module Terraforming
|
|
41
41
|
result
|
42
42
|
end
|
43
43
|
|
44
|
-
generate_tfstate(resources)
|
44
|
+
generate_tfstate(resources, tfstate_base)
|
45
45
|
end
|
46
46
|
|
47
47
|
private
|
@@ -3,12 +3,12 @@ module Terraforming
|
|
3
3
|
class S3
|
4
4
|
include Terraforming::Util
|
5
5
|
|
6
|
-
def self.tf(client
|
6
|
+
def self.tf(client: Aws::S3::Client.new)
|
7
7
|
self.new(client).tf
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.tfstate(client
|
11
|
-
self.new(client).tfstate
|
10
|
+
def self.tfstate(client: Aws::S3::Client.new, tfstate_base: nil)
|
11
|
+
self.new(client).tfstate(tfstate_base)
|
12
12
|
end
|
13
13
|
|
14
14
|
def initialize(client)
|
@@ -19,7 +19,7 @@ module Terraforming
|
|
19
19
|
apply_template(@client, "tf/s3")
|
20
20
|
end
|
21
21
|
|
22
|
-
def tfstate
|
22
|
+
def tfstate(tfstate_base)
|
23
23
|
resources = buckets.inject({}) do |result, bucket|
|
24
24
|
result["aws_s3_bucket.#{module_name_of(bucket)}"] = {
|
25
25
|
"type" => "aws_s3_bucket",
|
@@ -36,7 +36,7 @@ module Terraforming
|
|
36
36
|
result
|
37
37
|
end
|
38
38
|
|
39
|
-
generate_tfstate(resources)
|
39
|
+
generate_tfstate(resources, tfstate_base)
|
40
40
|
end
|
41
41
|
|
42
42
|
private
|
@@ -3,12 +3,12 @@ module Terraforming
|
|
3
3
|
class SecurityGroup
|
4
4
|
include Terraforming::Util
|
5
5
|
|
6
|
-
def self.tf(client
|
6
|
+
def self.tf(client: Aws::EC2::Client.new)
|
7
7
|
self.new(client).tf
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.tfstate(client
|
11
|
-
self.new(client).tfstate
|
10
|
+
def self.tfstate(client: Aws::EC2::Client.new, tfstate_base: nil)
|
11
|
+
self.new(client).tfstate(tfstate_base)
|
12
12
|
end
|
13
13
|
|
14
14
|
def initialize(client)
|
@@ -19,17 +19,20 @@ module Terraforming
|
|
19
19
|
apply_template(@client, "tf/security_group")
|
20
20
|
end
|
21
21
|
|
22
|
-
def tfstate
|
22
|
+
def tfstate(tfstate_base)
|
23
23
|
resources = security_groups.inject({}) do |result, security_group|
|
24
24
|
attributes = {
|
25
25
|
"description" => security_group.description,
|
26
|
-
"egress.#" => security_group.ip_permissions_egress.length.to_s,
|
27
26
|
"id" => security_group.group_id,
|
28
|
-
"ingress.#" => security_group.ip_permissions.length.to_s,
|
29
27
|
"name" => security_group.group_name,
|
30
28
|
"owner_id" => security_group.owner_id,
|
31
29
|
"vpc_id" => security_group.vpc_id || "",
|
32
30
|
}
|
31
|
+
|
32
|
+
attributes.merge!(tags_attributes_of(security_group))
|
33
|
+
attributes.merge!(egress_attributes_of(security_group))
|
34
|
+
attributes.merge!(ingress_attributes_of(security_group))
|
35
|
+
|
33
36
|
result["aws_security_group.#{module_name_of(security_group)}"] = {
|
34
37
|
"type" => "aws_security_group",
|
35
38
|
"primary" => {
|
@@ -41,18 +44,94 @@ module Terraforming
|
|
41
44
|
result
|
42
45
|
end
|
43
46
|
|
44
|
-
generate_tfstate(resources)
|
47
|
+
generate_tfstate(resources, tfstate_base)
|
45
48
|
end
|
46
49
|
|
47
50
|
private
|
48
51
|
|
52
|
+
def ingress_attributes_of(security_group)
|
53
|
+
attributes = { "ingress.#" => security_group.ip_permissions.length.to_s }
|
54
|
+
|
55
|
+
security_group.ip_permissions.each do |permission|
|
56
|
+
attributes.merge!(permission_attributes_of(security_group, permission, "ingress"))
|
57
|
+
end
|
58
|
+
|
59
|
+
attributes
|
60
|
+
end
|
61
|
+
|
62
|
+
def egress_attributes_of(security_group)
|
63
|
+
attributes = { "egress.#" => security_group.ip_permissions_egress.length.to_s }
|
64
|
+
|
65
|
+
security_group.ip_permissions_egress.each do |permission|
|
66
|
+
attributes.merge!(permission_attributes_of(security_group, permission, "egress"))
|
67
|
+
end
|
68
|
+
|
69
|
+
attributes
|
70
|
+
end
|
71
|
+
|
72
|
+
def group_hashcode_of(group)
|
73
|
+
Zlib.crc32(group)
|
74
|
+
end
|
75
|
+
|
49
76
|
def module_name_of(security_group)
|
50
77
|
normalize_module_name("#{security_group.group_id}-#{security_group.group_name}")
|
51
78
|
end
|
52
79
|
|
80
|
+
def permission_attributes_of(security_group, permission, type)
|
81
|
+
hashcode = permission_hashcode_of(security_group, permission)
|
82
|
+
security_groups = security_groups_in(permission).reject { |group_id| group_id == security_group.group_id }
|
83
|
+
|
84
|
+
attributes = {
|
85
|
+
"#{type}.#{hashcode}.from_port" => (permission.from_port || 0).to_s,
|
86
|
+
"#{type}.#{hashcode}.to_port" => (permission.to_port || 0).to_s,
|
87
|
+
"#{type}.#{hashcode}.protocol" => permission.ip_protocol,
|
88
|
+
"#{type}.#{hashcode}.cidr_blocks.#" => permission.ip_ranges.length.to_s,
|
89
|
+
"#{type}.#{hashcode}.security_groups.#" => security_groups.length.to_s,
|
90
|
+
"#{type}.#{hashcode}.self" => self_referenced_permission?(security_group, permission).to_s,
|
91
|
+
}
|
92
|
+
|
93
|
+
permission.ip_ranges.each_with_index do |range, index|
|
94
|
+
attributes["#{type}.#{hashcode}.cidr_blocks.#{index}"] = range.cidr_ip
|
95
|
+
end
|
96
|
+
|
97
|
+
security_groups.each do |group|
|
98
|
+
attributes["#{type}.#{hashcode}.security_groups.#{group_hashcode_of(group)}"] = group
|
99
|
+
end
|
100
|
+
|
101
|
+
attributes
|
102
|
+
end
|
103
|
+
|
104
|
+
def permission_hashcode_of(security_group, permission)
|
105
|
+
string =
|
106
|
+
"#{permission.from_port || 0}-" <<
|
107
|
+
"#{permission.to_port || 0}-" <<
|
108
|
+
"#{permission.ip_protocol}-" <<
|
109
|
+
"#{self_referenced_permission?(security_group, permission).to_s}-"
|
110
|
+
|
111
|
+
permission.ip_ranges.each { |range| string << "#{range.cidr_ip}-" }
|
112
|
+
security_groups_in(permission).each { |group| string << "#{group}-" }
|
113
|
+
|
114
|
+
Zlib.crc32(string)
|
115
|
+
end
|
116
|
+
|
117
|
+
def self_referenced_permission?(security_group, permission)
|
118
|
+
security_groups_in(permission).include?(security_group.group_id)
|
119
|
+
end
|
120
|
+
|
53
121
|
def security_groups
|
54
122
|
@client.describe_security_groups.security_groups
|
55
123
|
end
|
124
|
+
|
125
|
+
def security_groups_in(permission)
|
126
|
+
permission.user_id_group_pairs.map { |range| range.group_id }
|
127
|
+
end
|
128
|
+
|
129
|
+
def tags_attributes_of(security_group)
|
130
|
+
tags = security_group.tags
|
131
|
+
attributes = { "tags.#" => tags.length.to_s }
|
132
|
+
tags.each { |tag| attributes["tags.#{tag.key}"] = tag.value }
|
133
|
+
attributes
|
134
|
+
end
|
56
135
|
end
|
57
136
|
end
|
58
137
|
end
|
@@ -3,12 +3,12 @@ module Terraforming
|
|
3
3
|
class Subnet
|
4
4
|
include Terraforming::Util
|
5
5
|
|
6
|
-
def self.tf(client
|
6
|
+
def self.tf(client: Aws::EC2::Client.new)
|
7
7
|
self.new(client).tf
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.tfstate(client
|
11
|
-
self.new(client).tfstate
|
10
|
+
def self.tfstate(client: Aws::EC2::Client.new, tfstate_base: nil)
|
11
|
+
self.new(client).tfstate(tfstate_base)
|
12
12
|
end
|
13
13
|
|
14
14
|
def initialize(client)
|
@@ -19,7 +19,7 @@ module Terraforming
|
|
19
19
|
apply_template(@client, "tf/subnet")
|
20
20
|
end
|
21
21
|
|
22
|
-
def tfstate
|
22
|
+
def tfstate(tfstate_base)
|
23
23
|
resources = subnets.inject({}) do |result, subnet|
|
24
24
|
attributes = {
|
25
25
|
"availability_zone" => subnet.availability_zone,
|
@@ -40,7 +40,7 @@ module Terraforming
|
|
40
40
|
result
|
41
41
|
end
|
42
42
|
|
43
|
-
generate_tfstate(resources)
|
43
|
+
generate_tfstate(resources, tfstate_base)
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
@@ -3,12 +3,12 @@ module Terraforming
|
|
3
3
|
class VPC
|
4
4
|
include Terraforming::Util
|
5
5
|
|
6
|
-
def self.tf(client
|
6
|
+
def self.tf(client: Aws::EC2::Client.new)
|
7
7
|
self.new(client).tf
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.tfstate(client
|
11
|
-
self.new(client).tfstate
|
10
|
+
def self.tfstate(client: Aws::EC2::Client.new, tfstate_base: nil)
|
11
|
+
self.new(client).tfstate(tfstate_base)
|
12
12
|
end
|
13
13
|
|
14
14
|
def initialize(client)
|
@@ -19,7 +19,7 @@ module Terraforming
|
|
19
19
|
apply_template(@client, "tf/vpc")
|
20
20
|
end
|
21
21
|
|
22
|
-
def tfstate
|
22
|
+
def tfstate(tfstate_base)
|
23
23
|
resources = vpcs.inject({}) do |result, vpc|
|
24
24
|
attributes = {
|
25
25
|
"cidr_block" => vpc.cidr_block,
|
@@ -40,7 +40,7 @@ module Terraforming
|
|
40
40
|
result
|
41
41
|
end
|
42
42
|
|
43
|
-
generate_tfstate(resources)
|
43
|
+
generate_tfstate(resources, tfstate_base)
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
@@ -2,8 +2,11 @@
|
|
2
2
|
<%- load_balancer_attributes = load_balancer_attributes_of(load_balancer) -%>
|
3
3
|
resource "aws_elb" "<%= module_name_of(load_balancer) %>" {
|
4
4
|
name = "<%= load_balancer.load_balancer_name %>"
|
5
|
-
|
5
|
+
<%- if vpc_elb?(load_balancer) -%>
|
6
6
|
subnets = <%= load_balancer.subnets.inspect %>
|
7
|
+
<%- else -%>
|
8
|
+
availability_zones = <%= load_balancer.availability_zones.inspect %>
|
9
|
+
<%- end -%>
|
7
10
|
security_groups = <%= load_balancer.security_groups.inspect %>
|
8
11
|
instances = <%= load_balancer.instances.map { |instance| instance.instance_id }.inspect %>
|
9
12
|
cross_zone_load_balancing = <%= load_balancer_attributes.cross_zone_load_balancing.enabled %>
|
@@ -3,7 +3,7 @@ resource "aws_iam_group_policy" "<%= policy.policy_name %>" {
|
|
3
3
|
name = "<%= policy.policy_name %>"
|
4
4
|
group = "<%= policy.group_name %>"
|
5
5
|
policy = <<POLICY
|
6
|
-
<%=
|
6
|
+
<%= prettify_policy(policy.policy_document) %>
|
7
7
|
POLICY
|
8
8
|
}
|
9
9
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<% iam_instance_profiles.each do |profile| -%>
|
2
|
+
resource "aws_iam_instance_profile" "<%= profile.instance_profile_name %>" {
|
3
|
+
name = "<%= profile.instance_profile_name %>"
|
4
|
+
path = "<%= profile.path %>"
|
5
|
+
roles = <%= profile.roles.map { |role| role.role_name }.inspect %>
|
6
|
+
}
|
7
|
+
|
8
|
+
<% end -%>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% iam_roles.each do |role| -%>
|
2
|
+
resource "aws_iam_role" "<%= role.role_name %>" {
|
3
|
+
name = "<%= role.role_name %>"
|
4
|
+
path = "<%= role.path %>"
|
5
|
+
assume_role_policy = <<POLICY
|
6
|
+
<%= prettify_policy(role.assume_role_policy_document) %>
|
7
|
+
POLICY
|
8
|
+
}
|
9
|
+
|
10
|
+
<% end -%>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% iam_role_policies.each do |policy| -%>
|
2
|
+
resource "aws_iam_role_policy" "<%= policy.policy_name %>" {
|
3
|
+
name = "<%= policy.policy_name %>"
|
4
|
+
role = "<%= policy.role_name %>"
|
5
|
+
policy = <<POLICY
|
6
|
+
<%= prettify_policy(policy.policy_document) %>
|
7
|
+
POLICY
|
8
|
+
}
|
9
|
+
|
10
|
+
<% end -%>
|
@@ -3,7 +3,7 @@ resource "aws_iam_user_policy" "<%= policy.policy_name %>" {
|
|
3
3
|
name = "<%= policy.policy_name %>"
|
4
4
|
user = "<%= policy.user_name %>"
|
5
5
|
policy = <<POLICY
|
6
|
-
<%=
|
6
|
+
<%= prettify_policy(policy.policy_document) %>
|
7
7
|
POLICY
|
8
8
|
}
|
9
9
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<% network_acls.each do |network_acl| -%>
|
2
2
|
resource "aws_network_acl" "<%= module_name_of(network_acl) %>" {
|
3
|
-
vpc_id
|
3
|
+
vpc_id = "<%= network_acl.vpc_id %>"
|
4
|
+
subnet_ids = <%= subnet_ids_of(network_acl).inspect %>
|
4
5
|
|
5
6
|
<% ingresses_of(network_acl).each do |ingress| -%>
|
6
7
|
ingress {
|
@@ -5,6 +5,7 @@ resource "aws_security_group" "<%= module_name_of(security_group) %>" {
|
|
5
5
|
vpc_id = "<%= security_group.vpc_id || '' %>"
|
6
6
|
|
7
7
|
<% security_group.ip_permissions.each do |permission| -%>
|
8
|
+
<%- security_groups = security_groups_in(permission).reject { |group_id| group_id == security_group.group_id } -%>
|
8
9
|
ingress {
|
9
10
|
from_port = <%= permission.from_port || 0 %>
|
10
11
|
to_port = <%= permission.to_port || 0 %>
|
@@ -13,7 +14,11 @@ resource "aws_security_group" "<%= module_name_of(security_group) %>" {
|
|
13
14
|
cidr_blocks = <%= permission.ip_ranges.map { |range| range.cidr_ip }.inspect %>
|
14
15
|
<%- end -%>
|
15
16
|
<%- if permission.user_id_group_pairs.length > 0 -%>
|
16
|
-
|
17
|
+
<%- self_referenced = self_referenced_permission?(security_group, permission) -%>
|
18
|
+
<%- unless self_referenced -%>
|
19
|
+
security_groups = <%= security_groups.inspect %>
|
20
|
+
<%- end -%>
|
21
|
+
self = <%= self_referenced %>
|
17
22
|
<%- end -%>
|
18
23
|
}
|
19
24
|
|
@@ -28,7 +33,11 @@ resource "aws_security_group" "<%= module_name_of(security_group) %>" {
|
|
28
33
|
cidr_blocks = <%= permission.ip_ranges.map { |range| range.cidr_ip }.inspect %>
|
29
34
|
<%- end -%>
|
30
35
|
<%- if permission.user_id_group_pairs.length > 0 -%>
|
31
|
-
|
36
|
+
<%- self_referenced = self_referenced_permission?(security_group, permission) -%>
|
37
|
+
<%- unless self_referenced -%>
|
38
|
+
security_groups = <%= security_groups_in(permission).inspect %>
|
39
|
+
<%- end -%>
|
40
|
+
self = <%= self_referenced %>
|
32
41
|
<%- end -%>
|
33
42
|
}
|
34
43
|
|
data/lib/terraforming/util.rb
CHANGED
@@ -17,22 +17,37 @@ module Terraforming
|
|
17
17
|
File.join(File.expand_path(File.dirname(__FILE__)), "template", template_name) << ".erb"
|
18
18
|
end
|
19
19
|
|
20
|
-
def generate_tfstate(resources)
|
21
|
-
tfstate =
|
20
|
+
def generate_tfstate(resources, tfstate_base = nil)
|
21
|
+
tfstate = tfstate_base || tfstate_skeleton
|
22
|
+
tfstate["serial"] = tfstate["serial"] + 1
|
23
|
+
tfstate["modules"][0]["resources"] = tfstate["modules"][0]["resources"].merge(resources)
|
24
|
+
JSON.pretty_generate(tfstate)
|
25
|
+
end
|
26
|
+
|
27
|
+
def prettify_policy(policy_document, breakline = false)
|
28
|
+
json = JSON.pretty_generate(JSON.parse(CGI.unescape(policy_document)))
|
29
|
+
|
30
|
+
if breakline
|
31
|
+
json[-1] != "\n" ? json << "\n" : json
|
32
|
+
else
|
33
|
+
json.strip
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def tfstate_skeleton
|
38
|
+
{
|
22
39
|
"version" => 1,
|
23
|
-
"serial" =>
|
40
|
+
"serial" => 0,
|
24
41
|
"modules" => [
|
25
42
|
{
|
26
43
|
"path" => [
|
27
44
|
"root"
|
28
45
|
],
|
29
46
|
"outputs" => {},
|
30
|
-
"resources" =>
|
47
|
+
"resources" => {},
|
31
48
|
}
|
32
49
|
]
|
33
50
|
}
|
34
|
-
|
35
|
-
JSON.pretty_generate(tfstate)
|
36
51
|
end
|
37
52
|
end
|
38
53
|
end
|
data/lib/terraforming/version.rb
CHANGED
data/terraforming.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.add_dependency "aws-sdk", "~> 2.
|
22
|
+
spec.add_dependency "aws-sdk", "~> 2.1.0"
|
23
23
|
spec.add_dependency "oj"
|
24
24
|
spec.add_dependency "ox"
|
25
25
|
spec.add_dependency "thor"
|