Module: Terraform::DSL

Defined in:
lib/terraform/dsl.rb

Instance Method Summary collapse

Instance Method Details

#create_user(username) ⇒ Object



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

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_apt_get_update(oldest_acceptable_time = Time.now - 30*24*60*60) ⇒ Object



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

def ensure_apt_get_update(oldest_acceptable_time = Time.now - 30*24*60*60)
  dep "apt-get update" do
    met? do
      File.exists?("#{ENV['HOME']}/.apt_get_updated") &&
        File.mtime("#{ENV['HOME']}/.apt_get_updated") >= oldest_acceptable_time
    end
    meet { `sudo apt-get update && touch $HOME/.apt_get_updated` }
  end
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.



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

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



91
92
93
94
95
96
# File 'lib/terraform/dsl.rb', line 91

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



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

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

#ensure_packages(*packages) ⇒ Object



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

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]



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/terraform/dsl.rb', line 74

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 --yes #{ppa}"#, :silent => true
      shell "sudo apt-get update"#, :silent => true
    end
  end
end

#ensure_rbenvObject



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/terraform/dsl.rb', line 125

def ensure_rbenv
  # TODO(caleb): The package is 'git-core' in older Ubuntu releases. We should have a mechanism for
  # handling different releases; see https://github.com/philc/terraform/issues/15.
  ensure_packages "git", "curl"
  dep "rbenv" do
    met? { in_path?("rbenv") }
    meet do
      # These instructions are from https://github.com/fesplugas/rbenv-installer
      shell "curl https://raw.githubusercontent.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”.



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/terraform/dsl.rb', line 144

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.



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

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



161
162
163
164
165
166
# File 'lib/terraform/dsl.rb', line 161

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)


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

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



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

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)


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

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
43
# File 'lib/terraform/dsl.rb', line 32

def satisfy_dependencies
  STDOUT.sync = true # Ensure that we flush logging output as we go along.
  @dependencies ||= []
  @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)


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

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