terrafying 0.0.1 → 1.1.4

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.
data/lib/terrafying.rb DELETED
@@ -1,270 +0,0 @@
1
- require 'fileutils'
2
- require 'logger'
3
- require 'pathname'
4
- require 'securerandom'
5
- require 'tempfile'
6
-
7
- require 'hash/deep_merge'
8
-
9
- require 'terrafying/aws'
10
- require 'terrafying/cli'
11
- require 'terrafying/generator'
12
- require 'terrafying/lock'
13
- require 'terrafying/version'
14
- require 'terrafying/state'
15
-
16
- module Terrafying
17
-
18
- class Config
19
-
20
- attr_reader :path, :scope
21
-
22
- def initialize(path, options)
23
- @path = File.expand_path(path)
24
- @options = options
25
- @scope = options[:scope] || scope_for_path(@path)
26
-
27
- $stderr.puts "Scope: #{@scope}"
28
-
29
- load(path)
30
- end
31
-
32
- def list
33
- Terrafying::Generator.resource_names
34
- end
35
-
36
- def json
37
- Terrafying::Generator.pretty_generate
38
- end
39
-
40
- def plan
41
- exit_code = 1
42
- with_config do
43
- with_state(mode: :read) do
44
- exit_code = exec_with_optional_target 'plan'
45
- end
46
- end
47
- exit_code
48
- end
49
-
50
- def graph
51
- exit_code = 1
52
- with_config do
53
- with_state(mode: :read) do
54
- exit_code = exec_with_optional_target 'graph'
55
- end
56
- end
57
- exit_code
58
- end
59
-
60
- def validate
61
- exit_code = 1
62
- with_config do
63
- with_state(mode: :read) do
64
- exit_code = exec_with_optional_target 'validate'
65
- end
66
- end
67
- exit_code
68
- end
69
-
70
- def apply
71
- exit_code = 1
72
- with_config do
73
- with_lock do
74
- with_state(mode: :update) do
75
- exit_code = exec_with_optional_target "apply -auto-approve -backup=- #{@dir}"
76
- end
77
- end
78
- end
79
- exit_code
80
- end
81
-
82
- def destroy
83
- exit_code = 1
84
- with_config do
85
- with_lock do
86
- with_state(mode: :update) do
87
- exit_code = stream_command("terraform destroy -backup=- #{@dir}")
88
- end
89
- end
90
- end
91
- exit_code
92
- end
93
-
94
- def show_state
95
- puts(State.store(self).get)
96
- end
97
-
98
- def use_remote_state
99
- with_lock do
100
- local = State.local(self)
101
- state = local.get
102
- if state
103
- State.remote(self).put(state)
104
- end
105
- local.delete
106
- end
107
- end
108
-
109
- def use_local_state
110
- with_lock do
111
- remote = State.remote(self)
112
- state = remote.get
113
- if state
114
- State.local(self).put(state)
115
- end
116
- end
117
- end
118
-
119
- def import(addr, id)
120
- exit_code = 1
121
- with_config do
122
- with_lock do
123
- with_state(mode: :update) do
124
- exit_code = exec_with_optional_target "import -backup=- #{@dir} #{addr} #{id}"
125
- end
126
- end
127
- end
128
- exit_code
129
- end
130
-
131
- private
132
- def lock_timeout
133
- "-lock-timeout=#{@options[:lock_timeout]}" if @options[:lock_timeout]
134
- end
135
-
136
- def targets
137
- @options[:target].split(',').map { |target| "-target=#{target}" }.join(' ') if @options[:target]
138
- end
139
-
140
- def exec_with_optional_target(command, *args)
141
- exec_with_args(command, targets, lock_timeout, *args)
142
- end
143
-
144
- def exec_with_args(command, *args)
145
- stream_command("terraform #{command} #{args.join(' ')}")
146
- end
147
-
148
- def with_config(&block)
149
- abort("***** ERROR: You must have terraform installed to run this gem *****") unless terraform_installed?
150
- check_version
151
- name = File.basename(@path, ".*")
152
- dir = File.join(git_toplevel, 'tmp', SecureRandom.uuid)
153
- terraform_files = File.join(git_toplevel, ".terraform/")
154
- unless Dir.exists?(terraform_files)
155
- abort("***** ERROR: No .terraform directory found. Please run 'terraform init' to install plugins *****")
156
- end
157
- FileUtils.mkdir_p(dir)
158
- output_path = File.join(dir, name + ".tf.json")
159
- FileUtils.cp_r(terraform_files, dir)
160
- Dir.chdir(dir) do
161
- begin
162
- File.write(output_path, Terrafying::Generator.pretty_generate)
163
- yield block
164
- ensure
165
- FileUtils.rm_rf(dir) unless @options[:keep]
166
- end
167
- end
168
- end
169
-
170
- def with_lock(&block)
171
- lock_id = nil
172
- begin
173
- lock = if @options[:no_lock]
174
- Locks.noop
175
- else
176
- Locks.dynamodb(scope)
177
- end
178
-
179
- lock_id = if @options[:force]
180
- lock.steal
181
- else
182
- lock.acquire
183
- end
184
- yield block
185
-
186
- # If block raises any exception we will still hold on to lock
187
- # after process exits. This is actually what we want as
188
- # terraform may have succeeded in updating some resources, but
189
- # not others so we need to manually get into a consistent
190
- # state and then re-run.
191
- lock.release(lock_id)
192
- end
193
- end
194
-
195
- def with_state(opts, &block)
196
- if !@options[:dynamodb]
197
- return yield(block)
198
- end
199
-
200
- store = State.store(self)
201
-
202
- begin
203
- state = store.get
204
- File.write(State::STATE_FILENAME, state) if state
205
- rescue => e
206
- raise "Error retrieving state for config #{self}: #{e}"
207
- end
208
-
209
- yield block
210
-
211
- begin
212
- if opts[:mode] == :update
213
- store.put(IO.read(State::STATE_FILENAME))
214
- end
215
- rescue => e
216
- raise "Error updating state for config #{self}: #{e}"
217
- end
218
- end
219
-
220
- def scope_for_path(path)
221
- top_level_path = Pathname.new(git_toplevel)
222
- Pathname.new(@path).relative_path_from(top_level_path).to_s
223
- end
224
-
225
- def git_toplevel
226
- @top_level ||= begin
227
- top_level = `git rev-parse --show-toplevel`
228
- raise "Unable to find .git directory top level for '#{@path}'" if top_level.empty?
229
- File.expand_path(top_level.chomp)
230
- end
231
- end
232
-
233
- def check_version
234
- if terraform_version != Terrafying::CLI_VERSION
235
- abort("***** ERROR: You must have v#{Terrafying::CLI_VERSION} of terraform installed to run any command (you are running v#{terraform_version}) *****")
236
- end
237
- end
238
-
239
- def terraform_installed?
240
- which('terraform')
241
- end
242
-
243
- def terraform_version
244
- `terraform -v`.split("\n").first.split("v").last
245
- end
246
-
247
- def stream_command(cmd)
248
- IO.popen(cmd) do |io|
249
- while (line = io.gets) do
250
- puts line.gsub('\n', "\n").gsub('\\"', "\"")
251
- end
252
- end
253
- return $?.exitstatus
254
- end
255
-
256
- # Cross-platform way of finding an executable in the $PATH.
257
- #
258
- # which('ruby') #=> /usr/bin/ruby
259
- def which(cmd)
260
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
261
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
262
- exts.each { |ext|
263
- exe = File.join(path, "#{cmd}#{ext}")
264
- return exe if File.executable?(exe) && !File.directory?(exe)
265
- }
266
- end
267
- return nil
268
- end
269
- end
270
- end