convection 2.2.12 → 2.2.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 06fa6942996ee32f586741975300cad7ddd11e83
4
- data.tar.gz: f393211f45deac206370eaa9c5c7163547b563da
3
+ metadata.gz: cc4c4bbe225ec33757f900d24c62f5629644e4ae
4
+ data.tar.gz: b3e00e9748782113a6a7491cacb12cdc0b2f71e0
5
5
  SHA512:
6
- metadata.gz: '0801e86aef339edd14e256942d10c641ade985171fca98f15db341a0ef18652230cb0a8c9762dda1f048a68ac47f27164cf08bcbba7397a4fd1aa8ffeac885f7'
7
- data.tar.gz: d110b282f788d2479e8984f3117ed339244019ea51efaa284be93bee0cc021967b07357ff172bb5ba82c4b7d9a113c83147d4cc53b55e3f7aa9a8b38e1149057
6
+ metadata.gz: 731c78af0486d452e249a27c40499bbe4d44d44df7a5fd35c7501c6104ddb4720ccdf60b870574f2b3808510a85870530351e241a20aa6167fe712116a21d09f
7
+ data.tar.gz: 88af87c51fa62ca1be9e73748d90abfe9a0bbb63b0946d028fe3a5a2ae01eb218b6285ae4145faf4fb40acac07cf2cfb864697dad6678a7e156679a6529bc653
data/bin/convection CHANGED
@@ -130,22 +130,19 @@ module Convection
130
130
  m['resources'].reject { |k, _| k.start_with?('data.') }
131
131
  }.reduce({}, &:merge)
132
132
  cf = Aws::CloudFormation::Client.new(region: options[:stack_region])
133
- cf_resources = cf.describe_stack_resources(stack_name: options[:stack_name]).stack_resources
133
+ cf_resources = cf.describe_stack_resources(stack_name: options[:stack_name]).stack_resources.map do |r|
134
+ { logical_resource_id: r.logical_resource_id, physical_resource_id: r.physical_resource_id, type: r.resource_type }
135
+ end
134
136
  cf_resources.each do |cf_resource|
135
- say "Resource '#{cf_resource.physical_resource_id}':"
136
- say " * CloudFormation Logical ID #{cf_resource.logical_resource_id}"
137
-
138
- tf_resource_name, tf_resource = terraform_resources.find do |_, tf_resource|
139
- next true if tf_resource['primary'].key(cf_resource.physical_resource_id)
140
- tf_resource['primary'].values.any? { |v| v.is_a?(String) && v.include?(cf_resource.physical_resource_id) }
141
- end
142
- tf_key = tf_resource && tf_resource['primary'].key(cf_resource.physical_resource_id)
143
- fuzzy_match = tf_key.nil?
144
- tf_key ||= tf_resource && tf_resource['primary'].find { |v| v.include?(cf_resource.physical_resource_id) }
145
- if tf_key && fuzzy_match
146
- say " * Found physical ID included in Terraform resource #{tf_resource_name} under attribute #{tf_key} with value '#{tf_resource['primary'][tf_key]}'. Please validate this resource is included in state and configuration.", :yellow
147
- elsif tf_key && !fuzzy_match
148
- say " * Found physical ID exactly in Terraform resource #{tf_resource_name} under attribute #{tf_key} with value '#{tf_resource['primary'][tf_key]}'.", :cyan
137
+ response = ask_tf_physical_id(cf_resource)
138
+ cf_resource[:physical_resource_id] = response unless response.empty?
139
+ say "Resource #{cf_resource[:physical_resource_id].inspect} #{cf_resource[:logical_resource_id].inspect}:"
140
+
141
+ tf_resource = tf_resource_for(physical_resource_id: cf_resource[:physical_resource_id], resources: terraform_resources)
142
+ if tf_resource[:attribute_key] && tf_resource[:partial]
143
+ say " * Found physical ID included in Terraform resource #{tf_resource[:logical_resource_id].inspect} under attribute #{tf_resource[:attribute_key].inspect} with value #{tf_resource[:value].inspect}. Please validate this resource is included in state and configuration.", :yellow
144
+ elsif tf_resource[:attribute_key] && !tf_resource[:partial]
145
+ say " * Found physical ID exactly in Terraform resource #{tf_resource[:logical_resource_id].inspect} under attribute #{tf_resource[:attribute_key].inspect} with value #{tf_resource[:value].inspect}.", :green
149
146
  else
150
147
  say " * Unable to find physical ID in the provided Terraform state.", :red
151
148
  end
@@ -280,6 +277,18 @@ module Convection
280
277
 
281
278
  private
282
279
 
280
+ def ask_tf_physical_id(cf_resource)
281
+ question = case cf_resource[:type]
282
+ when 'AWS::IAM::Policy'
283
+ "What is the <role-name>:<policy-name> for the #{cf_resource[:logical_resource_id].inspect} IAM policy?"
284
+ when 'AWS::S3::BucketPolicy'
285
+ "What is the name of the bucket that the #{cf_resource[:logical_resource_id].inspect} policy belongs to?"
286
+ end
287
+ return '' unless question
288
+
289
+ ask(question, :yellow).chomp
290
+ end
291
+
283
292
  def load_local_terraform_state(statefile)
284
293
  JSON.load(File.open(statefile))
285
294
  end
@@ -306,6 +315,20 @@ module Convection
306
315
  end
307
316
  end
308
317
 
318
+ def tf_resource_for(physical_resource_id:, resources:)
319
+ logical_id, resource = resources.find do |_, resource|
320
+ next true if resource['primary'].key(physical_resource_id)
321
+ resource['primary'].values.any? { |v| v.is_a?(String) && v.include?(physical_resource_id) }
322
+ end
323
+ return {} unless logical_id && resource
324
+
325
+ key = resource['primary'].key(physical_resource_id)
326
+ return { attribute_key: key, logical_id: logical_id, partial: false, value: physical_resource_id } if key
327
+
328
+ key, value = value['primary'].find { |v| v.include?(physical_resource_id) }
329
+ return { attribute_key: key, logical_id: logical_id, partial: true, value: value }
330
+ end
331
+
309
332
  def import_resources(resource_name, resource)
310
333
  empty_directory options[:output_directory] if resource.respond_to?(:to_hcl_json) || resource.respond_to?(:additional_hcl_files)
311
334
  if resource.respond_to?(:to_hcl_json)
@@ -41,6 +41,22 @@ module Convection
41
41
  @resource_collection_dsl_methods ||= {}
42
42
  end
43
43
  end
44
+
45
+ def _terraform_module_dir_to_flag(dir)
46
+ return 'root' if dir.empty?
47
+
48
+ parts = dir.split('/')
49
+ parts[0] = 'module' if parts[0] == 'modules'
50
+ parts.join('.')
51
+ end
52
+
53
+ def _terraform_module_flag_to_dir(flag)
54
+ return '' if flag == 'root'
55
+
56
+ parts = flag.split('.')
57
+ parts[0] = 'modules'
58
+ parts.join('/')
59
+ end
44
60
  end
45
61
 
46
62
  include DSL::Helpers
@@ -116,6 +116,58 @@ module Convection
116
116
  render_tags(resource)
117
117
  end
118
118
  end
119
+
120
+ def to_hcl_json(*)
121
+ tf_sg_name = name.underscore
122
+ tf_sg_var_id = "${aws_security_group.#{tf_sg_name}.id}"
123
+ tf_resources = []
124
+
125
+ # Define the security group resource.
126
+ tf_resources << {
127
+ aws_security_group: {
128
+ tf_sg_name => {
129
+ vpc_id: vpc,
130
+ description: description,
131
+ tags: tags.reject { |_, v| v.nil? }
132
+ }.reject { |_, v| v.nil? }
133
+ }
134
+ }
135
+
136
+ tf_sg_rules = {}
137
+
138
+ # Define helper functions to map Convection rules to Terraform ones.
139
+ sg_rule_to_tf = lambda do |rule_type, item, index|
140
+ tf_sg_rule_name = "#{tf_sg_name}_#{rule_type}_#{index}"
141
+
142
+ tf_sg_rules[tf_sg_rule_name] = {
143
+ type: rule_type,
144
+ security_group_id: tf_sg_var_id,
145
+ from_port: item.from,
146
+ to_port: item.to,
147
+ protocol: item.protocol,
148
+ cidr_block: item.source,
149
+ # TODO: Missing attribs & checks. Should probably be defined as a
150
+ # seperate function to reuse for egress.
151
+ }.reject { |_, v| v.nil? }
152
+ end
153
+
154
+ # Map the contained rules to TF.
155
+ security_group_ingress.each_with_index { |item, obj| sg_rule_to_tf.call('ingress', item, obj) }
156
+ security_group_egress.each_with_index { |item, obj| sg_rule_to_tf.call('egress', item, obj) }
157
+
158
+ tf_resources << { aws_security_group_rule: tf_sg_rules }
159
+
160
+ # Return the JSON representation of this resource.
161
+ { resource: tf_resources }.to_json
162
+ end
163
+
164
+ def terraform_import_commands(module_path: 'root')
165
+ prefix = "#{module_path}." unless module_path == 'root'
166
+ resource_id = stack.resources[name] && stack.resources[name].physical_resource_id
167
+ commands = ['# Import the security group:']
168
+ commands << "terraform import #{prefix}aws_security_group.#{name.underscore} #{resource_id}"
169
+ commands
170
+ end
119
171
  end
120
172
  end
121
173
  end
@@ -63,6 +63,61 @@ module Convection
63
63
  property :path, 'Path'
64
64
  property :policies, 'Policies', :type => :list
65
65
  property :user_name, 'UserName'
66
+
67
+ def additional_hcl_files(module_path: 'root')
68
+ module_prefix = module_path.tr('.', '-') if module_path == 'root'
69
+ result = {}
70
+
71
+ user = user_name
72
+ user ||= stack.resources[name] && stack.resources[name].physical_resource_id
73
+ result["#{stack._original_region}-#{stack._original_cloud}-#{name.underscore}.tf.json"] = {
74
+ module: [{
75
+ name.underscore => {
76
+ source: _terraform_module_flag_to_dir(module_path),
77
+ managed_policy_arns: managed_policy_arn,
78
+ name: user,
79
+ path: path
80
+ }
81
+ }]
82
+ }
83
+
84
+ result["#{module_prefix}#{name.underscore}-variables.tf.json"] = {
85
+ variable: [
86
+ { managed_policy_arns: { description: 'A list of ARNs for managed policies to attach to this user.', default: [] } },
87
+ { name: { description: 'The name of the user' } },
88
+ { path: { description: 'The path for the IAM user', path: '/' } }
89
+ ]
90
+ }
91
+
92
+ result["#{module_prefix}#{name.underscore}-user.tf.json"] = {
93
+ resource: [
94
+ {
95
+ aws_iam_user: {
96
+ name.underscore => {
97
+ managed_policy_arns: '${var.managed_policy_arns}',
98
+ name: '${var.name}',
99
+ path: '${var.path}'
100
+ }
101
+ }
102
+ }
103
+ ]
104
+ }
105
+
106
+ policy_resources = policies.map do |policy|
107
+ {
108
+ aws_iam_user_policy: {
109
+ policy.name.underscore => {
110
+ name: policy.name,
111
+ policy: policy.render.to_json,
112
+ user: "${aws_iam_user.#{name.underscore}.id}"
113
+ }
114
+ }
115
+ }
116
+ end
117
+ result["#{module_prefix}#{name.underscore}-policy.tf.json"] = { resource: policy_resources }
118
+
119
+ result
120
+ end
66
121
  end
67
122
  end
68
123
  end
@@ -50,6 +50,30 @@ module Convection
50
50
  properties['WebsiteConfiguration'].set(config)
51
51
  end
52
52
 
53
+ def terraform_import_commands(module_path: 'root')
54
+ commands = ['# Run the following commands to import your infrastructure into terraform management.', '# ensure :module_path is set correctly', '']
55
+ module_prefix = "#{module_path}." unless module_path == 'root'
56
+
57
+ commands << '# Import s3 bucket and s3 bucket policy: '
58
+ commands << "terraform import #{module_prefix}aws_s3_bucket.#{name.underscore} #{stack.resources[name].physical_resource_id}"
59
+ commands << ''
60
+ commands
61
+ end
62
+
63
+ def to_hcl_json(*)
64
+ bucket_resource = {
65
+ name.underscore => {
66
+ bucket: stack.resources[name].physical_resource_id,
67
+ acl: 'private',
68
+ force_destroy: false
69
+ }
70
+ }
71
+
72
+ data = [{ aws_region: { current: { current: true } } }]
73
+ vars = [{ cloud: { description: 'The cloud name for this resource.' } }]
74
+ { resource: [{ aws_s3_bucket: bucket_resource }], data: data, variable: vars }.to_json
75
+ end
76
+
53
77
  def render(*args)
54
78
  super.tap do |resource|
55
79
  render_tags(resource)
@@ -30,6 +30,28 @@ module Convection
30
30
  @document = Model::Mixin::Policy.new(:name => false, :template => @template)
31
31
  end
32
32
 
33
+ def terraform_import_commands(*)
34
+ commands = ['# Run the following commands to import your infrastructure into terraform management.', '# ensure :module_path is set correctly', '']
35
+ commands << '# Import s3 bucket and s3 bucket policy: '
36
+ # commands << "terraform import #{module_prefix}aws_s3_bucket.#{name.underscore} #{stack.resources[name].physical_resource_id}"
37
+ commands << ''
38
+ commands
39
+ end
40
+
41
+ def to_hcl_json(*)
42
+ policy_json = resources[name] && resources[name].document.document.to_json.gsub(stack.resources[name].physical_resource_id, bucket)
43
+ policy_resource = {
44
+ name.underscore => {
45
+ bucket: bucket,
46
+ policy: policy_json
47
+ }
48
+ }
49
+
50
+ data = [{ aws_region: { current: { current: true } } }]
51
+ vars = [{ cloud: { description: 'The cloud name for this resource.' } }]
52
+ { resource: { aws_s3_bucket_policy: policy_resource }, data: data, variable: vars }.to_json
53
+ end
54
+
33
55
  def render
34
56
  super.tap do |r|
35
57
  document.render(r['Properties'])
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: convection
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.12
4
+ version: 2.2.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Manero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-10 00:00:00.000000000 Z
11
+ date: 2018-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport