-
Notifications
You must be signed in to change notification settings - Fork 0
/
Rakefile.rb
276 lines (222 loc) · 6 KB
/
Rakefile.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# Provide a Rake-based interface for building & provisioning
# a dev environment based on Ansible & Vagrant.
#
# For Rake, cf.:
# - https://github.com/ruby/rake
# - https://martinfowler.com/articles/rake.html
#
# Make sure to have Rake installed:
# $ gem install rake
#
# Make sure to have all dependencies installed:
# $ gem install bundler
# $ bundle install
#
# Dependencies
#
# stdlib
require 'yaml'
require 'pp'
require 'erb'
require 'ostruct'
# Gems
#
# For Rails' active support extensions, cf.:
# - https://guides.rubyonrails.org/active_support_core_extensions.html
require 'rubygems'
require 'bundler/setup'
require 'rake'
require 'awesome_print'
require 'active_support/core_ext/hash/keys'
require 'active_support/configurable'
#
# Helper functions
#
# Read basic Vagrant config.
def get_vagrant_config
YAML.load_file('./vagrant/config.yml').symbolize_keys
end
# Write ERB template files with given data to given destination.
#
# Used here to write Ansible inventory & config files.
#
# Cf.:
# - https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
# - https://www.stuartellis.name/articles/erb/
# - https://www.rubyguides.com/2018/11/ruby-erb-haml-slim/
# - https://blog.appsignal.com/2019/01/08/ruby-magic-bindings-and-lexical-scope.html
def write_template(template, target, config)
File.write(
target,
ERB.new(File.read(template)).result(binding)
)
end
# Whether or not to generate, or update, Ansible inventory & confg files.
def generate_ansible_files
# Helper to decide whether or not to generate/update a given file
update = Proc.new do |fn, mtime|
!(File.exists?(fn) && File.stat(fn).mtime >= mtime)
end
Dir.glob('./templates/ansible.*').each do |template|
# Get a template's last modified date
source_mtime = File.stat(template).mtime
# Get a destination's potential file name & path
target_file = File.basename(template).split('.').slice(1...-1).join('.')
target_path = target_file.start_with?('inventory') ? 'inventory' : 'plays/*'
# Walk destination path(s)
Dir.glob("./ansible/#{target_path}/").each do |path|
# Build a potential real path
fn = File.join(File.expand_path(path), target_file)
# Yield source (template file) & target if the target needs to be generated/updated
yield template, fn if update.call(fn, source_mtime) && block_given?
end
end
end
#
# Settings
#
# Get some base config structure.
#
# For more options on how to do this, cf.:
# - https://www.cloudbees.com/blog/creating-configuration-objects-in-ruby/
config = OpenStruct.new
config.vm = get_vagrant_config[:hostname]
config.ssh = File.join(__dir__, 'vagrant/.ssh/config')
config.inventory = File.join(__dir__, 'ansible/inventory/inventory.yml')
config.roles = File.join(__dir__, 'ansible/roles')
#
# Bootstrap
#
generate_ansible_files do |template, target|
write_template(template, target, config)
end
# We do our own default help screen when no task was given.
# To get at the task descriptions, however, we need to tell Rake to record them before we load the task definitions in.
Rake::TaskManager.record_task_metadata = true
#
# Tasks
#
namespace :vm do
desc 'Bring dev machine up.'
task :up do
cd('vagrant') do
sh 'vagrant up'
end
end
desc 'Bring dev machine down.'
task :halt do
cd('vagrant') do
sh 'vagrant halt'
end
end
desc 'Bring dev machine down for good.'
task :destroy do
cd('vagrant') do
sh 'vagrant destroy'
end
end
desc 'Pause dev machine.'
task :suspend do
cd('vagrant') do
sh 'vagrant suspend'
end
end
desc 'SSH into dev machine.'
task :conn do
cd('vagrant') do
sh 'vagrant ssh'
end
end
desc 'Reload dev machine after re-configuration.'
task :reload do
cd('vagrant') do
sh 'vagrant reload --provision'
end
end
desc 'Fix issues with non-existing synced folders.'
task :fix_nfs do
sh 'sudo rm /etc/exports'
sh 'sudo touch /etc/exports'
end
desc 'Get status of dev machine.'
task :status do
cd('vagrant') do
sh 'vagrant status'
end
end
end
namespace :ansible do
desc 'Provision dev machine.'
task :provision do
cd('ansible/plays/provision') do
begin
sh "ansible-playbook -v playbook.yml"
rescue RuntimeError; end
end
end
desc 'Perform a provision dry run.'
task :dry do
cd('ansible/plays/provision') do
begin
sh "ansible-playbook --check -v playbook.yml"
rescue RuntimeError; end
end
end
desc 'Update galaxy roles.'
task :galaxy do
cd('ansible') do
sh 'ansible-galaxy install --roles-path=./roles/contrib -r requirements.yml'
end
end
end
namespace :test do
desc 'Try to connect to VM via ssh & custom config file.'
task :ssh do
sh "ssh -F #{config.ssh} #{config.vm}"
end
desc 'Try to ping VM with Ansible, so we know Ansible is able to connect.'
task :ping do
sh "ansible #{config.vm} -i #{config.inventory} -m ping"
end
desc 'Whether or not memcached is running.'
task :memcached do
sh "ssh -F #{config.ssh} #{config.vm} 'echo stats | nc 127.0.0.1 11211'"
sh "ssh -F #{config.ssh} #{config.vm} 'php -i | grep memcached'"
end
end
#
# Help screen
#
task :default do
tasks = Rake.application.tasks
desc = {}
puts
puts '=' * 40
puts '|' << ' ' * 38 << '|'
puts '|' << ' ' * 16 << 'DevOps' << ' ' * 16 << '|'
puts '|' << ' ' * 38 << '|'
puts '=' * 40
puts
puts 'Usage:'
puts 'rake TASK, e.g. rake ' + tasks[0].name
puts
tasks.each do |t|
if t.scope && t.comment && t.full_comment
scope = t.scope.entries[-1] || 'other'
desc[scope] = [] unless desc.has_key?(scope)
desc[scope].push([t.name, t.full_comment])
end
end
desc.sort.each do |ns, tasks|
title = "* #{ns.upcase} *"
puts "-" * title.length
puts title
puts "-" * title.length
puts
tasks.each do |name, desc|
puts sprintf("%s", name)
puts sprintf(" %s", desc)
puts
end
end
end