Module: Terraform::DSL

Defined in:
lib/terraform/dsl.rb

Instance Method Summary collapse

Instance Method Details

#create_user(username) ⇒ Object



146
# File 'lib/terraform/dsl.rb', line 146

def create_user(username) shell "useradd -m #{username}" end

#dep(name) ⇒ Object



6
7
8
9
10
11
12
13
14
# File 'lib/terraform/dsl.rb', line 6

def dep(name)
  @dependencies ||= []
  # If a dep gets required or defined twice, only run it once.
  return if @dependencies.find { |dep| dep[:name] == name }
  @dependencies.push(@current_dependency = { :name => name })
  yield
  fail_and_exit "Error: no 'met?' block defined for dep '#{name}'." unless @current_dependency[:met?]
  fail_and_exit "Error: no 'meet' block defined for dep '#{name}'." unless @current_dependency[:meet]
end

#ensure_file(source_path, dest_path, &on_change) ⇒ Object

Ensures the file at dest_path is exactly the same as the one in source_path. Invokes the given block if the file is changed. Use this block to restart a service, for instance.



89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/terraform/dsl.rb', line 89

def ensure_file(source_path, dest_path, &on_change)
  dep "file: #{dest_path}" do
    met? do
      raise "This file does not exist: #{source_path}" unless File.exists?(source_path)
      File.exists?(dest_path) && (Digest::MD5.file(source_path) == Digest::MD5.file(dest_path))
    end
    meet do
      FileUtils.cp(source_path, dest_path)
      on_change.call if on_change
    end
  end
end

#ensure_gem(gem) ⇒ Object



80
81
82
83
84
85
# File 'lib/terraform/dsl.rb', line 80

def ensure_gem(gem)
  dep "gem: #{gem}" do
    met? { gem_installed?(gem) }
    meet { shell "gem install #{gem} --no-ri --no-rdoc" }
  end
end

#ensure_package(package) ⇒ Object



55
56
57
58
59
60
# File 'lib/terraform/dsl.rb', line 55

def ensure_package(package)
  dep "package: #{package}" do
    met? { package_installed?(package) }
    meet { install_package(package) }
  end
end

#ensure_packages(*packages) ⇒ Object



54
# File 'lib/terraform/dsl.rb', line 54

def ensure_packages(*packages) packages.each { |package| ensure_package(package) } end

#ensure_ppa(ppa) ⇒ Object

Ensure an Ubuntu PPA is installed. The argument is the ppa location, in the form ppa:/[NAME]



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/terraform/dsl.rb', line 63

def ensure_ppa(ppa)
  ppa_part, location = ppa.split(":", 2)
  fail_and_exit("PPA location must be of the form ppa:[USER]/[NAME]") unless (ppa_part == "ppa") && location
  # The python-software-properties package provides the add-apt-repository convenience tool for editing
  # the list of apt's source repositories.
  ensure_package("python-software-properties")
  dep "ppa: #{location}" do
    met? { !`apt-cache policy 2> /dev/null | grep ppa.launchpad.net/#{location}/`.empty? }
    meet do
      shell "sudo add-apt-repository #{ppa}"#, :silent => true
      shell "sudo apt-get update"#, :silent => true
    end
  end
end

#ensure_rbenvObject



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/terraform/dsl.rb', line 114

def ensure_rbenv
  ensure_package "git-core"
  dep "rbenv" do
    met? { in_path?("rbenv") }
    meet do
      # These instructions are from https://github.com/sstephenson/rbenv/wiki/Using-rbenv-in-Production
      shell "wget -q -O - https://raw.github.com/fesplugas/rbenv-installer/master/bin/rbenv-installer | bash"
      # We need to run rbenv init after install, which adjusts the path. If exec is causing us problems
      # down the road, we can perhaps simulate running rbenv init without execing.
      unless ARGV.include?("--forked-after-rbenv") # To guard against an infinite forking loop.
        exec "bash -c 'source ~/.bashrc; #{$0} --forked-after-rbenv'" # $0 is the current process's name.
      end
    end
  end
end

#ensure_rbenv_ruby(ruby_version) ⇒ Object

ruby_version is a rbenv ruby version string like “1.9.2-p290”.



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/terraform/dsl.rb', line 131

def ensure_rbenv_ruby(ruby_version)
  ensure_rbenv
  ensure_packages "curl", "build-essential", "libxslt1-dev", "libxml2-dev", "libssl-dev"

  dep "rbenv ruby: #{ruby_version}" do
    met? { `bash -lc 'which ruby'`.include?("rbenv") && `rbenv versions`.include?(ruby_version) }
    meet do
      puts "Compiling Ruby will take a few minutes."
      shell "rbenv install #{ruby_version}"
      shell "rbenv rehash"
    end
  end
end

#ensure_run_once(name, &block) ⇒ Object

A task which must be run once to be ‘met’. For instance, this might be the DB migration script.



103
104
105
106
107
108
109
110
111
112
# File 'lib/terraform/dsl.rb', line 103

def ensure_run_once(name, &block)
  dep "run task once: #{name}" do
    has_run_once = false
    met? { has_run_once }
    meet do
      yield
      has_run_once = true
    end
  end
end

#ensure_user(username) ⇒ Object



148
149
150
151
152
153
# File 'lib/terraform/dsl.rb', line 148

def ensure_user(username)
  dep "user: #{username}" do
    met? { user_exists?(username) }
    meet { create_user(username) }
  end
end

#fail_and_exit(message) ⇒ Object



18
# File 'lib/terraform/dsl.rb', line 18

def fail_and_exit(message) puts message; exit 1 end

#gem_installed?(gem) ⇒ Boolean

Returns:

  • (Boolean)


78
# File 'lib/terraform/dsl.rb', line 78

def gem_installed?(gem) `gem list '#{gem}'`.include?(gem) end

#in_path?(command) ⇒ Boolean

Returns:

  • (Boolean)


17
# File 'lib/terraform/dsl.rb', line 17

def in_path?(command) `which #{command}`.size > 0 end

#install_package(package) ⇒ Object



49
50
51
52
# File 'lib/terraform/dsl.rb', line 49

def install_package(package)
  # Specify a noninteractive frontend, so dpkg won't prompt you for info. -q is quiet; -y is "answer yes".
  shell "sudo DEBIAN_FRONTEND=noninteractive apt-get install -qy #{package}"
end

#meet(&block) ⇒ Object



16
# File 'lib/terraform/dsl.rb', line 16

def meet(&block) @current_dependency[:meet] = block end

#met?(&block) ⇒ Boolean

Returns:

  • (Boolean)


15
# File 'lib/terraform/dsl.rb', line 15

def met?(&block) @current_dependency[:met?] = block end

#package_installed?(package) ⇒ Boolean

These are very common tasks which are needed by almost everyone, and so they’re bundled with this DSL.

Returns:

  • (Boolean)


48
# File 'lib/terraform/dsl.rb', line 48

def package_installed?(package) !!`dpkg -s #{package} 2> /dev/null | grep Status`.match(/\sinstalled/) end

#satisfy_dependenciesObject



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/terraform/dsl.rb', line 32

def satisfy_dependencies
  STDOUT.sync = true # Ensure that we flush logging output as we go along.
  @dependencies.each do |dep|
    unless dep[:met?].call
      puts "* Dependency #{dep[:name]} is not met. Meeting it."
      dep[:meet].call
      fail_and_exit %Q("met?" for #{dep[:name]} is still false after running "meet".) unless dep[:met?].call
    end
  end
  @dependencies = []
end

#shell(command, options = {}) ⇒ Object

Runs a command and raises an exception if its exit status was nonzero. Options:

  • silent: if false, log the command being run and its stdout. False by default.



23
24
25
26
27
28
29
30
# File 'lib/terraform/dsl.rb', line 23

def shell(command, options = {})
  silent = (options[:silent] != false)
  puts command unless silent
  output = `#{command}`
  puts output unless output.empty? || silent
  raise "#{command} had a failure exit status of #{$?.to_i}" unless $?.to_i == 0
  true
end

#user_exists?(username) ⇒ Boolean

Returns:

  • (Boolean)


145
# File 'lib/terraform/dsl.rb', line 145

def user_exists?(username) !!`id #{username} 2> /dev/null`.match(/^uid=\d+/) end