convection 2.2.1 → 2.2.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: 8931d15c79795527491f73c4440eb25decfbf0c1
4
- data.tar.gz: '0318b27b08e66eca49fe8c459a1036ef9d421a3f'
3
+ metadata.gz: ea262d5b5afd735ba927d096ad928f509ba36ebf
4
+ data.tar.gz: 3c44b95e767817b022dcb7ed20dfbfa413882366
5
5
  SHA512:
6
- metadata.gz: c233b5c721e0d9701529748010627cb237d368b247902ef3a3b616fd1060d0e2319bb2d20eec338793604e55a2deb2d7bc16554651c92d6a9ea63df7f4a8d9eb
7
- data.tar.gz: 2bcf5644dd5d20986c96635276fbac598cef484ee4e5d3e670c214272624c95e0dc62e4ec974e0ccf048092c862f306d3ad42ee7dce396dcd0690911fcc4c5cc
6
+ metadata.gz: 3ac71c23b2062b707a5caafceb973de58ccc4ba32436373f6a26ee14ea49350d19078f6de1bc959d0280477412a63db8e03a7de9b53ddfa175cdc0c8d4dc52ab
7
+ data.tar.gz: c2a5cae44fda5935f59c4dea52486ddfc4371b4fe1ad1e294bd3d39f2cdaaab7ff833007e1a492fc8cb0891acc358d9feefffabf5a431b75bbbfcc7c2d30789a
data/README.md CHANGED
@@ -1 +1 @@
1
- ./docs/index.md
1
+ docs/index.md
data/bin/convection CHANGED
@@ -118,36 +118,59 @@ module Convection
118
118
  describe_stack_resources(options[:stack], options[:format], options[:properties], options[:type])
119
119
  end
120
120
 
121
+ # rubocop:disable Style/AsciiComments
122
+
121
123
  desc 'terraform-export STACK', 'Create terraform configuration for a given stack (including `terraform import` commands)'
122
124
  option :module_path, desc: 'The module path prefix for terraform', default: DEFAULT_MODULE_PATH
123
125
  option :output_directory, desc: 'The directory to create configuration files under', aliases: %w(-d --dir), default: '.'.freeze
124
126
  option :cloudfile, desc: 'The cloudfile to load', default: 'Cloudfile'
127
+ option :confirm_root, desc: 'Prompt to confirm module path when --module-path="root"', default: true, type: :boolean
128
+ option :overwrite, desc: 'Overwrite any conflicting tf.json files in --output-directory', default: false, type: :boolean
129
+ option :skip_existing, desc: 'Skip any conflicting tf.json files in --output-directory', default: false, type: :boolean
125
130
  def terraform_export(stack_name)
126
131
  if options[:output_directory].empty?
127
132
  say_status :error, '--output-directory must not be empty.', :red
128
133
  exit 1
129
134
  end
130
135
 
131
- if options[:module_path] == DEFAULT_MODULE_PATH
136
+ if options[:confirm_root] && options[:module_path] == DEFAULT_MODULE_PATH
132
137
  say_status :warning, '--module-path was set to "root".', :yellow
133
138
  exit 0 unless yes?('Are you sure you want to generate terraform import commands in the root namespace?')
134
139
  end
135
140
 
136
141
  init_cloud
137
142
  template = @cloud.stacks.fetch(stack_name).template
143
+ # Beware of 🐲. This patches this Template to include terraform compatible intrinsic functions where possible.
144
+ #
145
+ # This should only be done in single threaded environment in the terraform-export command as it breaks usage of cloudformation psuedo-functions.
146
+ #
147
+ # e.g. #get_att("Bucket", "Arn") returns "aws_s3_bucket.bucket.arn" instead of { "Fn::GetAtt" => ["Bucket", "Arn"] }.
148
+ require 'convection/dsl/terraform_intrinsic_functions'
149
+ template.extend(Convection::DSL::TerraformIntrinsicFunctions)
138
150
  template.resource_collections.each(&method(:import_resources))
139
151
  template.resources.each(&method(:import_resources))
140
152
  end
141
153
 
154
+ # rubocop:enable Style/AsciiComments
155
+
142
156
  no_commands do
143
157
  attr_accessor :last_event
144
158
 
145
159
  private
146
160
 
161
+ # rubocop:disable Style/AsciiComments
162
+
147
163
  def import_resources(_resource_name, resource)
164
+ # Beware of 🐲. This patches this instance to include terraform compatible intrinsic functions where possible.
165
+ #
166
+ # This should only be done in single threaded environment in the terraform-export command as it breaks usage of cloudformation psuedo-functions.
167
+ require 'convection/dsl/terraform_intrinsic_functions'
168
+ resource.extend(Convection::DSL::TerraformIntrinsicFunctions)
169
+
148
170
  if resource.respond_to?(:to_hcl_json)
149
171
  empty_directory options[:output_directory]
150
- create_file File.join(options[:output_directory], "#{resource.name.downcase}.tf.json"), resource.to_hcl_json
172
+ destination = File.join(options[:output_directory], "#{resource.name.downcase}.tf.json")
173
+ create_file destination, resource.to_hcl_json, force: options[:overwrite], skip: options[:skip_existing]
151
174
  else
152
175
  say "# Unable to generate terraform configuration for #{resource.class}. Define #{resource.class}#to_hcl_json to do so.", :yellow
153
176
  end
@@ -169,6 +192,8 @@ module Convection
169
192
  puts # Print an additional new line
170
193
  end
171
194
 
195
+ # rubocop:enable Style/AsciiComments
196
+
172
197
  def operation(task_name, stack)
173
198
  work_q = Queue.new
174
199
  semaphore = Mutex.new
data/convection.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
19
  spec.require_paths = ['lib']
20
20
 
21
+ spec.add_runtime_dependency 'activesupport'
21
22
  spec.add_runtime_dependency 'aws-sdk', '>= 2'
22
23
  spec.add_runtime_dependency 'httparty', '~> 0.13'
23
24
  spec.add_runtime_dependency 'netaddr', '~> 1.5'
@@ -0,0 +1,93 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+
3
+ module Convection
4
+ module DSL
5
+ module TerraformIntrinsicFunctions
6
+ def base64(_content)
7
+ %q(base64(#{content.to_json}))
8
+ end
9
+
10
+ def fn_and(*)
11
+ warn "WARNING: Condition functions cannot be inferred when migrating to terraform. Please set count on migrated resources manually. #{self.class}(#{name})"
12
+ '${todo.fn_and.ATTRIBUTE.set_in_count}'
13
+ end
14
+
15
+ def fn_equals(*)
16
+ warn "WARNING: Condition functions cannot be inferred when migrating to terraform. Please set count on migrated resources manually. #{self.class}(#{name})"
17
+ '${todo.fn_equals.ATTRIBUTE.set_in_count}'
18
+ end
19
+
20
+ def fn_if(*)
21
+ warn "WARNING: Condition functions cannot be inferred when migrating to terraform. Please set count on migrated resources manually. #{self.class}(#{name})"
22
+ '${todo.fn_if.ATTRIBUTE.set_in_count}'
23
+ end
24
+
25
+ def fn_import_value(*)
26
+ warn "WARNING: Fn::ImportValue cannot be inferred when migrated to terraform. Please pull in this input through a variable or local value in your configuration. #{self.class}(#{name})"
27
+ '${todo.fn_import_value.ATTRIBUTE}'
28
+ end
29
+
30
+ def fn_not(*)
31
+ warn "WARNING: Condition functions cannot be inferred when migrating to terraform. Please set count on migrated resources manually. #{self.class}(#{name})"
32
+ '${todo.fn_not.ATTRIBUTE.set_in_count}'
33
+ end
34
+
35
+ def fn_or(*)
36
+ warn "WARNING: Condition functions cannot be inferred when migrating to terraform. Please set count on migrated resources manually. #{self.class}(#{name})"
37
+ '${todo.fn_or.ATTRIBUTE.set_in_count}'
38
+ end
39
+
40
+ def fn_sub(*)
41
+ warn "WARNING: Fn::Sub cannot be inferred when migrating to terraform. Please use ${replace(str, search, replace)} instead. #{self.class}(#{name})"
42
+ '${replace(todo.fn_sub.STRING, todo.fn_sub.SEARCH, todo.fn_sub.REPLACE)}'
43
+ end
44
+
45
+ def find_in_map(*)
46
+ warn "WARNING: Fn::FindInMap cannot be inferred when migrating to terraform. Please consult with the interpolation syntax terraform docs #{self.class}(#{name})"
47
+ '${lookup(lookup(YOUR_MAP, YOUR_TOP_LEVEL_KEY), YOUR_NESTED_KEY)}'
48
+ end
49
+
50
+ def get_att(resource_name, attr_name)
51
+ interpolation_string = "${#{terraform_resource_type(resource_name)}.#{terraform_resource_name(resource_name)}.#{attr_name.underscore}}"
52
+ warn "WARNING: Inferring you want to use #{interpolation_string} in place of Fn::GetAtt. Please consult with the interpolation syntax terraform docs and docs for this resource type in terraform to verify compatablity. #{self.class}(#{name})"
53
+ interpolation_string
54
+ end
55
+
56
+ def get_azs(*)
57
+ warn "WARNING: Inferring you want to use ${var.availability_zones} instead of Fn::GetAZs. Please consult with the interpolation syntax terraform docs to verify compatablity. Additionally you should attempt to use variables in place of a literal list. #{self.class}(#{name})"
58
+ '${var.availability_zones}'
59
+ end
60
+
61
+ def join(delimiter, *values)
62
+ interpolation_string = "${join(\"#{delimiter}\", list(#{values.map { |o| "\"#{o}\"" }.join(', ')}))"
63
+ warn "WARNING: Inferring you want to use #{interpolation_string} in place of Fn::Join. Please consult with the interpolation syntax terraform docs to verify compatablity. Additionally you should attempt to use variables in place of a literal list. #{self.class}(#{name})"
64
+ interpolation_string
65
+ end
66
+
67
+ def select(index, *objects)
68
+ interpolation_string = "${element(list(#{objects.map { |o| "\"#{o}\"" }.join(', ')}), #{index})"
69
+ warn "WARNING: Inferring you want to use #{interpolation_string} in place of Fn::Select. Please consult with the interpolation syntax terraform docs to verify compatablity. Additionally you should attempt to use variables in place of a literal list. #{self.class}(#{name})"
70
+ interpolation_string
71
+ end
72
+
73
+ def fn_ref(resource_name)
74
+ interpolation_string = "${#{terraform_resource_type(resource_name)}.#{terraform_resource_name(resource_name)}.id}"
75
+ warn "WARNING: Inferring you want to use #{interpolation_string} in place of Fn::Ref. Please consult with the interpolation syntax terraform docs and docs for this resource type in terraform to verify compatablity. #{self.class}(#{name})"
76
+ interpolation_string
77
+ end
78
+
79
+ def terraform_resource_name(resource_name)
80
+ resource_name.underscore
81
+ end
82
+
83
+ def terraform_resource_type(resource_name)
84
+ return type.sub(/^AWS::/, 'aws_').underscore if respond_to?(:type)
85
+ return resources[resource_name].type.underscore if respond_to?(:resources) && resources[resource_name]
86
+ return all_resources[resource_name].type.underscore if respond_to?(:all_resources) && all_resources[resource_name]
87
+ return parent.resources[resource_name].type.underscore if respond_to?(:parent) && parent.resources[resource_name]
88
+
89
+ 'todo_fixme_see_resource_type'
90
+ end
91
+ end
92
+ end
93
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: convection
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Manero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-23 00:00:00.000000000 Z
11
+ date: 2017-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: aws-sdk
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -118,6 +132,7 @@ files:
118
132
  - lib/convection/control/stack.rb
119
133
  - lib/convection/dsl/helpers.rb
120
134
  - lib/convection/dsl/intrinsic_functions.rb
135
+ - lib/convection/dsl/terraform_intrinsic_functions.rb
121
136
  - lib/convection/model/attributes.rb
122
137
  - lib/convection/model/cloudfile.rb
123
138
  - lib/convection/model/diff.rb
@@ -363,7 +378,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
363
378
  version: '0'
364
379
  requirements: []
365
380
  rubyforge_project:
366
- rubygems_version: 2.6.13
381
+ rubygems_version: 2.5.1
367
382
  signing_key:
368
383
  specification_version: 4
369
384
  summary: A fully generic, modular DSL for AWS CloudFormation