Class: Bebox::Provision

Inherits:
Object
  • Object
show all
Includes:
FilesHelper
Defined in:
lib/bebox/provision.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FilesHelper

#file_content_trimmed, #generate_file_from_template, included, #render_erb_template, templates_path, #write_content_to_file

Constructor Details

#initialize(project_root, environment, node, step) ⇒ Provision

Returns a new instance of Provision.



14
15
16
17
18
19
# File 'lib/bebox/provision.rb', line 14

def initialize(project_root, environment, node, step)
  self.project_root = project_root
  self.environment = environment
  self.node = node
  self.step = step
end

Instance Attribute Details

#environmentObject

Returns the value of attribute environment.



12
13
14
# File 'lib/bebox/provision.rb', line 12

def environment
  @environment
end

#finished_atObject

Returns the value of attribute finished_at.



12
13
14
# File 'lib/bebox/provision.rb', line 12

def finished_at
  @finished_at
end

#nodeObject

Returns the value of attribute node.



12
13
14
# File 'lib/bebox/provision.rb', line 12

def node
  @node
end

#project_rootObject

Returns the value of attribute project_root.



12
13
14
# File 'lib/bebox/provision.rb', line 12

def project_root
  @project_root
end

#started_atObject

Returns the value of attribute started_at.



12
13
14
# File 'lib/bebox/provision.rb', line 12

def started_at
  @started_at
end

#stepObject

Returns the value of attribute step.



12
13
14
# File 'lib/bebox/provision.rb', line 12

def step
  @step
end

Class Method Details

.add_node_to_step_manifests(project_root, node) ⇒ Object

Add a node to site.pp



110
111
112
113
114
115
116
117
118
119
# File 'lib/bebox/provision.rb', line 110

def self.add_node_to_step_manifests(project_root, node)
  Bebox::PROVISION_STEPS.each do |step|
    manifest_node = render_erb_template("#{Bebox::FilesHelper::templates_path}/puppet/#{step}/manifests/node.erb", {node: node})
    Bebox::Provision.remove_node(project_root, node.hostname, step)
    manifest_path = "#{project_root}/puppet/steps/#{Bebox::Provision.step_name(step)}/manifests/site.pp"
    content = File.read(manifest_path)
    content += "\n#{manifest_node}\n"
    write_content_to_file(manifest_path, content)
  end
end

.add_role(project_root, node_name, role_name) ⇒ Object

Add a role to a node



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/bebox/provision.rb', line 136

def self.add_role(project_root, node_name, role_name)
  tempfile_path = "#{project_root}/puppet/steps/#{Bebox::Provision.step_name('step-2')}/manifests/site.pp.tmp"
  manifest_path = "#{project_root}/puppet/steps/#{Bebox::Provision.step_name('step-2')}/manifests/site.pp"
  tempfile = File.open(tempfile_path, 'w')
  manifest_file = File.new(manifest_path)
  manifest_file.each do |line|
    line << "\n  include roles::#{role_name}\n" if (line =~ /^\s*node\s+#{node_name}\s+{\s*$/)
    tempfile << line
  end
  manifest_file.close
  tempfile.close
  FileUtils.mv(tempfile_path, manifest_path)
end

.associate_node_role(project_root, environment, node_name, role_name) ⇒ Object

Set a role for a node in the step-2 manifests file



104
105
106
107
# File 'lib/bebox/provision.rb', line 104

def self.associate_node_role(project_root, environment, node_name, role_name)
  Bebox::Provision.remove_role(project_root, node_name, 'step-2')
  Bebox::Provision.add_role(project_root, node_name, role_name)
end

.generate_hiera_for_steps(project_root, template_file, filename, options) ⇒ Object

Generate the hiera templates for each step



46
47
48
49
50
51
# File 'lib/bebox/provision.rb', line 46

def self.generate_hiera_for_steps(project_root, template_file, filename, options)
  Bebox::PROVISION_STEPS.each do |step|
    step_dir = Bebox::Provision.step_name(step)
    generate_file_from_template("#{Bebox::FilesHelper::templates_path}/puppet/#{step}/hiera/data/#{template_file}", "#{project_root}/puppet/steps/#{step_dir}/hiera/data/#{filename}.yaml", options)
  end
end

.generate_puppetfile(project_root, step, profiles) ⇒ Object

Generate the Puppetfile from the role-profiles partial puppetfiles



70
71
72
73
74
75
76
77
78
79
# File 'lib/bebox/provision.rb', line 70

def self.generate_puppetfile(project_root, step, profiles)
  modules = []
  puppetfile_path = "#{project_root}/puppet/steps/#{Bebox::Provision.step_name(step)}/Puppetfile"
  profiles.each do |profile|
    profile_puppetfile_path = "#{project_root}/puppet/profiles/#{profile.gsub('::','/')}/Puppetfile"
    puppetfile_content = File.read(profile_puppetfile_path)
    modules << puppetfile_content.scan(/^\s*(mod\s*.+?)$/).uniq
  end
  generate_file_from_template("#{Bebox::FilesHelper::templates_path}/puppet/#{step}/Puppetfile.erb", "#{project_root}/puppet/steps/#{Bebox::Provision.step_name(step)}/Puppetfile", {profile_modules: modules.flatten})
end

.generate_roles_and_profiles(project_root, step, role, profiles) ⇒ Object

Generate the roles and profiles modules for the step



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/bebox/provision.rb', line 54

def self.generate_roles_and_profiles(project_root, step, role, profiles)
  # Re-create the roles and profiles puppet module directories
  `rm -rf #{project_root}/puppet/steps/#{step_name(step)}/modules/{roles,profiles}`
  `mkdir -p #{project_root}/puppet/steps/#{step_name(step)}/modules/{roles,profiles}/manifests`
  # Copy role to puppet roles module
  `cp #{project_root}/puppet/roles/#{role}/manifests/init.pp #{project_root}/puppet/steps/#{step_name(step)}/modules/roles/manifests/#{role}.pp`
  # Copy profiles to puppet profiles module
  profiles.each do |profile|
    profile_tree = profile.gsub('::','/')
    profile_tree_parent = profile_tree.split('/')[0...-1].join('/')
    `mkdir -p #{project_root}/puppet/steps/#{step_name(step)}/modules/profiles/manifests/#{profile_tree_parent}`
    `cp #{project_root}/puppet/profiles/#{profile_tree}/manifests/init.pp #{project_root}/puppet/steps/#{step_name(step)}/modules/profiles/manifests/#{profile_tree}.pp`
  end
end

.profiles_from_role(project_root, role_name) ⇒ Object

Get the profiles names array associated with a role



94
95
96
97
98
99
100
101
# File 'lib/bebox/provision.rb', line 94

def self.profiles_from_role(project_root, role_name)
  profiles = []
  role_path = "#{project_root}/puppet/roles/#{role_name}/manifests/init.pp"
  role_content = File.read(role_path)
  matching_roles = role_content.match(/^\s*class\s+roles::#{role_name}\s*({.*?}\s*)/m)
  profiles = matching_roles[0].strip.scan(/profiles::(.+?$)/).flatten unless matching_roles.nil?
  profiles
end

.remove_hiera_for_steps(project_root, node_name) ⇒ Object

Remove hiera data file for node



122
123
124
125
126
# File 'lib/bebox/provision.rb', line 122

def self.remove_hiera_for_steps(project_root, node_name)
  Bebox::PROVISION_STEP_NAMES.each do |step|
    `cd #{project_root} && rm -rf #{project_root}/puppet/steps/#{step}/hiera/data/#{node_name}.yaml`
  end
end

.remove_node(project_root, node_name, step) ⇒ Object

Remove the current role in a node



151
152
153
154
155
156
# File 'lib/bebox/provision.rb', line 151

def self.remove_node(project_root, node_name, step)
  manifest_path = "#{project_root}/puppet/steps/#{Bebox::Provision.step_name(step)}/manifests/site.pp"
  regexp = /^\s*node\s+#{node_name}\s*({.*?}\s*)/m
  content = File.read(manifest_path).sub(regexp, '')
  File.open(manifest_path, 'wb') { |file| file.write(content) }
end

.remove_node_for_steps(project_root, node_name) ⇒ Object

Remove node in manifests file for each step



129
130
131
132
133
# File 'lib/bebox/provision.rb', line 129

def self.remove_node_for_steps(project_root, node_name)
  Bebox::PROVISION_STEPS.each do |step|
    Bebox::Provision.remove_node(project_root, node_name, step)
  end
end

.remove_role(project_root, node_name, step) ⇒ Object

Remove the current role in a node



159
160
161
162
163
164
# File 'lib/bebox/provision.rb', line 159

def self.remove_role(project_root, node_name, step)
  manifest_path = "#{project_root}/puppet/steps/#{Bebox::Provision.step_name(step)}/manifests/site.pp"
  regexp = /^\s*node\s+#{node_name}\s*({.*?}\s*)/m
  content = File.read(manifest_path).sub(regexp, "\nnode #{node_name} {\n\n}\n\n")
  File.open(manifest_path, 'wb') { |file| file.write(content) }
end

.role_from_node(project_root, step, node) ⇒ Object

Get the role name associated with a node



82
83
84
85
86
87
88
89
90
91
# File 'lib/bebox/provision.rb', line 82

def self.role_from_node(project_root, step, node)
  manifest_path = "#{project_root}/puppet/steps/#{Bebox::Provision.step_name(step)}/manifests/site.pp"
  manifest_content = File.read(manifest_path)
  matching_nodes = manifest_content.match(/^\s*node\s+#{node}\s*({.*?}\s*)/m)
  unless matching_nodes.nil?
    matching_role = matching_nodes[0].strip.match(/roles::(.+?$)/)
    role = matching_role[1] unless matching_role.nil?
  end
  role
end

.step_name(step) ⇒ Object

Translate step name to directory name



197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/bebox/provision.rb', line 197

def self.step_name(step)
  case step
    when 'step-0'
      '0-fundamental'
    when 'step-1'
      '1-users'
    when 'step-2'
      '2-services'
    when 'step-3'
      '3-security'
  end
end

Instance Method Details

#applyObject

Puppet apply Fundamental step



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/bebox/provision.rb', line 22

def apply
  started_at = DateTime.now.to_s
  # Check if a Puppetfile is neccesary for use/not use librarian-puppet
  check_puppetfile_content
  # Copy static modules that are not downloaded by librarian-puppet
  copy_static_modules
  # Apply step and if the process is succesful create the checkpoint.
  process_status = apply_step
  create_step_checkpoint(started_at) if process_status.success?
  process_status
end

#apply_stepObject

Apply step via capistrano in the machine



167
168
169
170
171
172
173
174
175
176
177
# File 'lib/bebox/provision.rb', line 167

def apply_step
  # Create deploy directories
  cap 'deploy:setup'
  # Deploy the configured step
  $?.success? ? (cap 'deploy') : (return $?)
  # Download dynamic step modules through librarian-puppet
  $?.success? ? (cap 'puppet:bundle_modules') : (return $?)
  # Install the step provision through puppet
  $?.success? ? (cap 'puppet:apply') : (return $?)
  $?
end

#cap(command) ⇒ Object

Executes capistrano commands



180
181
182
# File 'lib/bebox/provision.rb', line 180

def cap(command)
  `cd #{self.project_root} && BUNDLE_GEMFILE=Gemfile bundle exec cap #{self.environment} #{command} -S phase='#{self.step}' -S step_dir='#{step_name}' HOSTS=#{self.node.hostname}`
end

#check_puppetfile_contentObject

Check if it’s necessary a Puppetfile accord to it’s content



35
36
37
38
# File 'lib/bebox/provision.rb', line 35

def check_puppetfile_content
  puppetfile_content = File.read("#{project_root}/puppet/steps/#{step_name}/Puppetfile").strip
  `rm "#{project_root}/puppet/steps/#{step_name}/Puppetfile"` if puppetfile_content.scan(/^\s*(mod\s*.+?)$/).flatten.empty?
end

#copy_static_modulesObject

Copy the static modules to the step-N modules path



41
42
43
# File 'lib/bebox/provision.rb', line 41

def copy_static_modules
  `cp -R #{Bebox::FilesHelper::templates_path}/puppet/#{self.step}/modules/* #{self.project_root}/puppet/steps/#{step_name}/modules/`
end

#create_step_checkpoint(started_at) ⇒ Object

Create checkpoint for step



185
186
187
188
189
# File 'lib/bebox/provision.rb', line 185

def create_step_checkpoint(started_at)
  self.node.started_at = started_at
  self.node.finished_at = DateTime.now.to_s
  generate_file_from_template("#{Bebox::FilesHelper::templates_path}/node/provisioned_node.yml.erb", "#{self.project_root}/.checkpoints/environments/#{self.environment}/steps/#{self.step}/#{self.node.hostname}.yml", {node: self.node})
end

#step_nameObject

Translate step name to directory name



192
193
194
# File 'lib/bebox/provision.rb', line 192

def step_name
  Bebox::Provision.step_name(self.step)
end