class Terrafying::Config
Attributes
path[R]
scope[R]
Public Class Methods
new(path, options)
click to toggle source
# File lib/terrafying.rb, line 20 def initialize(path, options) @path = File.expand_path(path) @options = options @scope = options[:scope] || scope_for_path(@path) warn "Scope: #{@scope}" load(path) end
Public Instance Methods
apply()
click to toggle source
# File lib/terrafying.rb, line 68 def apply exit_code = 1 with_config do with_lock do with_state(mode: :update) do exit_code = exec_with_optional_target "apply -auto-approve -backup=- #{@dir}" end end end exit_code end
destroy()
click to toggle source
# File lib/terrafying.rb, line 80 def destroy exit_code = 1 with_config do with_lock do with_state(mode: :update) do exit_code = stream_command("terraform destroy -backup=- #{@dir}") end end end exit_code end
graph()
click to toggle source
# File lib/terrafying.rb, line 48 def graph exit_code = 1 with_config do with_state(mode: :read) do exit_code = exec_with_optional_target 'graph' end end exit_code end
import(addr, id)
click to toggle source
# File lib/terrafying.rb, line 113 def import(addr, id) exit_code = 1 with_config do with_lock do with_state(mode: :update) do exit_code = exec_with_optional_target "import -backup=- #{@dir} #{addr} #{id}" end end end exit_code end
json()
click to toggle source
# File lib/terrafying.rb, line 34 def json Terrafying::Generator.pretty_generate end
list()
click to toggle source
# File lib/terrafying.rb, line 30 def list Terrafying::Generator.resource_names end
plan()
click to toggle source
# File lib/terrafying.rb, line 38 def plan exit_code = 1 with_config do with_state(mode: :read) do exit_code = exec_with_optional_target 'plan' end end exit_code end
show_state()
click to toggle source
# File lib/terrafying.rb, line 92 def show_state puts(State.store(self).get) end
use_local_state()
click to toggle source
# File lib/terrafying.rb, line 105 def use_local_state with_lock do remote = State.remote(self) state = remote.get State.local(self).put(state) if state end end
use_remote_state()
click to toggle source
# File lib/terrafying.rb, line 96 def use_remote_state with_lock do local = State.local(self) state = local.get State.remote(self).put(state) if state local.delete end end
validate()
click to toggle source
# File lib/terrafying.rb, line 58 def validate exit_code = 1 with_config do with_state(mode: :read) do exit_code = exec_with_optional_target 'validate' end end exit_code end
Private Instance Methods
check_version()
click to toggle source
# File lib/terrafying.rb, line 223 def check_version if terraform_version != Terrafying::CLI_VERSION abort("***** ERROR: You must have v#{Terrafying::CLI_VERSION} of terraform installed to run any command (you are running v#{terraform_version}) *****") end end
exec_with_args(command, *args)
click to toggle source
# File lib/terrafying.rb, line 139 def exec_with_args(command, *args) stream_command("terraform #{command} #{args.join(' ')}") end
exec_with_optional_target(command, *args)
click to toggle source
# File lib/terrafying.rb, line 135 def exec_with_optional_target(command, *args) exec_with_args(command, targets, lock_timeout, *args) end
git_toplevel()
click to toggle source
# File lib/terrafying.rb, line 214 def git_toplevel @top_level ||= begin top_level = `git rev-parse --show-toplevel` raise "Unable to find .git directory top level for '#{@path}'" if top_level.empty? File.expand_path(top_level.chomp) end end
lock_timeout()
click to toggle source
# File lib/terrafying.rb, line 127 def lock_timeout "-lock-timeout=#{@options[:lock_timeout]}" if @options[:lock_timeout] end
scope_for_path(_path)
click to toggle source
# File lib/terrafying.rb, line 209 def scope_for_path(_path) top_level_path = Pathname.new(git_toplevel) Pathname.new(@path).relative_path_from(top_level_path).to_s end
stream_command(cmd)
click to toggle source
# File lib/terrafying.rb, line 237 def stream_command(cmd) IO.popen(cmd) do |io| while (line = io.gets) puts line.gsub('\n', "\n").gsub('\\"', '"') end end $CHILD_STATUS.exitstatus end
targets()
click to toggle source
# File lib/terrafying.rb, line 131 def targets @options[:target].split(',').map { |target| "-target=#{target}" }.join(' ') if @options[:target] end
terraform_installed?()
click to toggle source
# File lib/terrafying.rb, line 229 def terraform_installed? which('terraform') end
terraform_version()
click to toggle source
# File lib/terrafying.rb, line 233 def terraform_version `terraform -v`.split("\n").first.split('v').last end
which(cmd)
click to toggle source
Cross-platform way of finding an executable in the $PATH.
which('ruby') #=> /usr/bin/ruby
# File lib/terrafying.rb, line 249 def which(cmd) exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| exts.each do |ext| exe = File.join(path, "#{cmd}#{ext}") return exe if File.executable?(exe) && !File.directory?(exe) end end nil end
with_config() { |block| ... }
click to toggle source
# File lib/terrafying.rb, line 143 def with_config(&block) abort('***** ERROR: You must have terraform installed to run this gem *****') unless terraform_installed? check_version name = File.basename(@path, '.*') dir = File.join(git_toplevel, 'tmp', SecureRandom.uuid) terraform_files = File.join(git_toplevel, '.terraform/') unless Dir.exist?(terraform_files) abort("***** ERROR: No .terraform directory found. Please run 'terraform init' to install plugins *****") end FileUtils.mkdir_p(dir) output_path = File.join(dir, name + '.tf.json') FileUtils.cp_r(terraform_files, dir) Dir.chdir(dir) do File.write(output_path, Terrafying::Generator.pretty_generate) yield block ensure FileUtils.rm_rf(dir) unless @options[:keep] end end
with_lock() { |block| ... }
click to toggle source
# File lib/terrafying.rb, line 163 def with_lock(&block) lock_id = nil begin lock = if @options[:no_lock] Locks.noop else Locks.dynamodb(scope) end lock_id = if @options[:force] lock.steal else lock.acquire end yield block # If block raises any exception we will still hold on to lock # after process exits. This is actually what we want as # terraform may have succeeded in updating some resources, but # not others so we need to manually get into a consistent # state and then re-run. lock.release(lock_id) end end
with_state(opts) { |block| ... }
click to toggle source
# File lib/terrafying.rb, line 188 def with_state(opts, &block) return yield(block) unless @options[:dynamodb] store = State.store(self) begin state = store.get File.write(State::STATE_FILENAME, state) if state rescue StandardError => e raise "Error retrieving state for config #{self}: #{e}" end yield block begin store.put(IO.read(State::STATE_FILENAME)) if opts[:mode] == :update rescue StandardError => e raise "Error updating state for config #{self}: #{e}" end end