vagrant-pe_build 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +24 -0
  3. data/README.markdown +152 -71
  4. data/acceptance/pe_build/pe_bootstrap_2015x_spec.rb +61 -13
  5. data/acceptance/pe_build/pe_bootstrap_3x_spec.rb +6 -3
  6. data/acceptance/pe_build/pe_bootstrap_latest_spec.rb +6 -3
  7. data/acceptance/skeletons/2015x_acceptance/Vagrantfile +25 -49
  8. data/acceptance/skeletons/pe_build/Vagrantfile +1 -1
  9. data/lib/pe_build/cap.rb +9 -0
  10. data/lib/pe_build/cap/detect_installer/base.rb +18 -0
  11. data/lib/pe_build/cap/detect_installer/posix.rb +0 -15
  12. data/lib/pe_build/cap/detect_installer/windows.rb +22 -4
  13. data/lib/pe_build/cap/facts/base.rb +119 -0
  14. data/lib/pe_build/cap/facts/debian.rb +37 -0
  15. data/lib/pe_build/cap/facts/posix.rb +36 -0
  16. data/lib/pe_build/cap/facts/redhat.rb +37 -0
  17. data/lib/pe_build/cap/facts/solaris.rb +46 -0
  18. data/lib/pe_build/cap/facts/suse.rb +38 -0
  19. data/lib/pe_build/cap/facts/ubuntu.rb +35 -0
  20. data/lib/pe_build/cap/facts/windows.rb +58 -0
  21. data/lib/pe_build/command.rb +1 -0
  22. data/lib/pe_build/command/base.rb +2 -1
  23. data/lib/pe_build/command/facts.rb +63 -0
  24. data/lib/pe_build/config.rb +1 -0
  25. data/lib/pe_build/config/pe_agent.rb +120 -0
  26. data/lib/pe_build/config_builder.rb +1 -0
  27. data/lib/pe_build/config_builder/pe_agent.rb +44 -0
  28. data/lib/pe_build/plugin.rb +44 -0
  29. data/lib/pe_build/provisioner/pe_agent.rb +262 -0
  30. data/lib/pe_build/release.rb +1 -1
  31. data/lib/pe_build/release/2015_2.rb +1 -0
  32. data/lib/pe_build/util/machine_comms.rb +51 -0
  33. data/lib/pe_build/util/pe_packaging.rb +57 -0
  34. data/lib/pe_build/version.rb +1 -1
  35. data/spec/unit/config/pe_agent_spec.rb +154 -0
  36. data/spec/unit/provisioner/pe_agent_spec.rb +101 -0
  37. data/tasks/acceptance.rake +2 -1
  38. data/templates/locales/en.yml +53 -0
  39. data/vagrant-pe_build.gemspec +4 -4
  40. data/vagrant-spec.config.example.rb +1 -1
  41. metadata +24 -5
@@ -22,6 +22,11 @@ module PEBuild
22
22
  PEBuild::Config::PEBootstrap
23
23
  end
24
24
 
25
+ config(:pe_agent, :provisioner) do
26
+ require_relative 'config'
27
+ PEBuild::Config::PEAgent
28
+ end
29
+
25
30
  config(:pe_build) do
26
31
  require_relative 'config'
27
32
  PEBuild::Config::Global
@@ -32,6 +37,11 @@ module PEBuild
32
37
  PEBuild::Provisioner::PEBootstrap
33
38
  end
34
39
 
40
+ provisioner(:pe_agent) do
41
+ require_relative 'provisioner/pe_agent'
42
+ PEBuild::Provisioner::PEAgent
43
+ end
44
+
35
45
  command(:'pe-build') do
36
46
  require_relative 'command'
37
47
  PEBuild::Command::Base
@@ -92,6 +102,40 @@ module PEBuild
92
102
  PEBuild::Cap::RunInstall::Windows
93
103
  end
94
104
 
105
+ # Retrieve Facts
106
+ guest_capability('redhat', 'pebuild_facts') do
107
+ require_relative 'cap'
108
+ PEBuild::Cap::Facts::RedHat
109
+ end
110
+
111
+ guest_capability('debian', 'pebuild_facts') do
112
+ require_relative 'cap'
113
+ PEBuild::Cap::Facts::Debian
114
+ end
115
+
116
+ guest_capability('ubuntu', 'pebuild_facts') do
117
+ require_relative 'cap'
118
+ PEBuild::Cap::Facts::Ubuntu
119
+ end
120
+
121
+ guest_capability('suse', 'pebuild_facts') do
122
+ require_relative 'cap'
123
+ PEBuild::Cap::Facts::SUSE
124
+ end
125
+
126
+ [:solaris, :solaris11].each do |os|
127
+ guest_capability(os, 'pebuild_facts') do
128
+ require_relative 'cap'
129
+ PEBuild::Cap::Facts::Solaris
130
+ end
131
+ end
132
+
133
+ guest_capability('windows', 'pebuild_facts') do
134
+ require_relative 'cap'
135
+ PEBuild::Cap::Facts::Windows
136
+ end
137
+
138
+
95
139
  # internal action hooks
96
140
 
97
141
  action_hook('PE Build: initialize build dir') do |hook|
@@ -0,0 +1,262 @@
1
+ require 'pe_build/util/pe_packaging'
2
+ require 'pe_build/util/machine_comms'
3
+
4
+ module PEBuild
5
+ module Provisioner
6
+ # Provision PE agents using simplified install
7
+ #
8
+ # @since 0.13.0
9
+ class PEAgent < Vagrant.plugin('2', :provisioner)
10
+ include ::PEBuild::Util::PEPackaging
11
+ include ::PEBuild::Util::MachineComms
12
+
13
+ attr_reader :facts
14
+ attr_reader :agent_version
15
+
16
+ def provision
17
+ provision_init!
18
+
19
+ # As of 2015.x, pe_repo doesn't support windows installation, so skip
20
+ # provisioning the repositories.
21
+ unless config.master_vm.nil? || provision_windows?
22
+ provision_pe_repo
23
+ end
24
+ provision_agent
25
+ provision_agent_cert if config.autosign
26
+ end
27
+
28
+ # This gets run during agent destruction and will remove the agent's
29
+ # certificate from the master, if requested.
30
+ def cleanup
31
+ unless config.master_vm.is_a?(::Vagrant::Machine)
32
+ vm_def = machine.env.active_machines.find {|vm| vm[0].to_s == config.master_vm.to_s}
33
+ if vm_def.nil?
34
+ config.master_vm.ui.warn I18n.t(
35
+ 'pebuild.provisioner.pe_agent.skip_purge_no_master',
36
+ :master => config.master_vm.to_s
37
+ )
38
+ return
39
+ end
40
+ config.master_vm = machine.env.machine(*vm_def)
41
+ end
42
+
43
+ cleanup_agent_cert if config.autopurge
44
+ end
45
+
46
+ private
47
+
48
+ # Set data items that are only available at provision time
49
+ def provision_init!
50
+ @facts = machine.guest.capability(:pebuild_facts)
51
+ @agent_version = facts['puppetversion']
52
+
53
+ # Resolve the master_vm setting to a Vagrant machine reference.
54
+ unless config.master_vm.nil?
55
+ vm_def = machine.env.active_machines.find {|vm| vm[0].to_s == config.master_vm.to_s}
56
+
57
+ unless vm_def.nil?
58
+ config.master_vm = machine.env.machine(*vm_def)
59
+ config.master ||= config.master_vm.config.vm.hostname.to_s
60
+ end
61
+ end
62
+ end
63
+
64
+ # A quick test to determine if we are provisioning a Windows agent
65
+ #
66
+ # This method requires {#provision_init!} to be called.
67
+ def provision_windows?
68
+ facts['os']['family'].downcase == 'windows'
69
+ end
70
+
71
+ def provision_agent
72
+ unless agent_version.nil?
73
+ machine.ui.info I18n.t(
74
+ 'pebuild.provisioner.pe_agent.already_installed',
75
+ :version => agent_version
76
+ )
77
+ return
78
+ end
79
+
80
+ if provision_windows?
81
+ provision_windows_agent
82
+ else
83
+ provision_posix_agent
84
+ end
85
+
86
+ # Refresh agent facts post-installation.
87
+ @facts = machine.guest.capability(:pebuild_facts)
88
+ end
89
+
90
+ # Ensure a master VM is able to serve agent packages
91
+ #
92
+ # This method inspects the master VM and ensures it is configured to
93
+ # serve packages for the agent's architecture.
94
+ def provision_pe_repo
95
+ # This method will raise an error if commands can't be run on the
96
+ # master VM.
97
+ ensure_reachable(config.master_vm)
98
+
99
+ platform = platform_tag(facts)
100
+ # Transform the platform_tag into a Puppet class name.
101
+ pe_repo_platform = platform.gsub('-', '_').gsub('.', '')
102
+ # TODO: Support PE 3.x
103
+ platform_repo = "/opt/puppetlabs/server/data/packages/public/current/#{platform}"
104
+
105
+ # Print a message and return if the agent repositories exist on the
106
+ # master.
107
+ if config.master_vm.communicate.test("[ -e #{platform_repo} ]")
108
+ config.master_vm.ui.info I18n.t(
109
+ 'pebuild.provisioner.pe_agent.pe_repo_present',
110
+ :vm_name => config.master_vm.name,
111
+ :platform_tag => platform
112
+ )
113
+ return
114
+ end
115
+
116
+ config.master_vm.ui.info I18n.t(
117
+ 'pebuild.provisioner.pe_agent.adding_pe_repo',
118
+ :vm_name => config.master_vm.name,
119
+ :platform_tag => platform
120
+ )
121
+
122
+ shell_config = Vagrant.plugin('2').manager.provisioner_configs[:shell].new
123
+ shell_config.privileged = true
124
+ # TODO: Extend to configuring agent repos which are older than the
125
+ # master.
126
+ # TODO: Extend to PE 3.x masters.
127
+ shell_config.inline = <<-EOS
128
+ /opt/puppetlabs/bin/puppet apply -e 'include pe_repo::platform::#{pe_repo_platform}'
129
+ EOS
130
+ shell_config.finalize!
131
+
132
+ shell_provisioner = Vagrant.plugin('2').manager.provisioners[:shell].new(config.master_vm, shell_config)
133
+ shell_provisioner.provision
134
+ end
135
+
136
+ # Execute a Vagrant shell provisioner to provision POSIX agents
137
+ #
138
+ # Performs a `curl | bash` installation.
139
+ def provision_posix_agent
140
+ shell_config = Vagrant.plugin('2').manager.provisioner_configs[:shell].new
141
+ shell_config.privileged = true
142
+ # Installation is split into to components running under set -e so that
143
+ # failures are detected. The curl command uses `sS` so that download
144
+ # progress is silenced, but error messages are still printed.
145
+ #
146
+ # TODO: Extend to allow passing agent install options.
147
+ # TODO: Extend to use `config.version` once {#provision_pe_repo}
148
+ # supports it.
149
+ shell_config.inline = <<-EOS
150
+ set -e
151
+ curl -ksS -tlsv1 https://#{config.master}:8140/packages/current/install.bash -o pe_frictionless_installer.sh
152
+ bash pe_frictionless_installer.sh
153
+ EOS
154
+ shell_config.finalize!
155
+
156
+ machine.ui.info "Running: #{shell_config.inline}"
157
+
158
+ shell_provisioner = Vagrant.plugin('2').manager.provisioners[:shell].new(machine, shell_config)
159
+ shell_provisioner.provision
160
+ end
161
+
162
+ # Install a PE Agent on Windows
163
+ #
164
+ # Executes a `pe_bootstrap` provisioner running in agent mode.
165
+ def provision_windows_agent
166
+ pe_config = ::PEBuild::Config::PEBootstrap.new
167
+ pe_config.role = :agent
168
+ # Windows won't reconize 'current' as a version number, so fall through
169
+ # to the global default by leaving it unset.
170
+ pe_config.version = config.version unless config.version == 'current'
171
+ pe_config.master = config.master
172
+ pe_config.finalize!
173
+
174
+ machine.ui.info "Installing Windows agent with PE Bootstrap"
175
+
176
+ pe_provisioner = Vagrant.plugin('2').manager.provisioners[:pe_bootstrap].new(machine, pe_config)
177
+ pe_provisioner.configure(machine.config)
178
+ pe_provisioner.provision
179
+ end
180
+
181
+ def provision_agent_cert
182
+ # This method will raise an error if commands can't be run on the
183
+ # master VM.
184
+ ensure_reachable(config.master_vm)
185
+
186
+ agent_certname = facts['certname']
187
+
188
+ # Return if the cert has already been signed. The return code is
189
+ # inverted as `grep -q` will exit with 1 if the certificate is not
190
+ # found.
191
+ # TODO: Extend paths to PE 3.x masters.
192
+ if not config.master_vm.communicate.test("/opt/puppetlabs/bin/puppet cert list | grep -q -F #{agent_certname}", :sudo => true)
193
+ config.master_vm.ui.info I18n.t(
194
+ 'pebuild.provisioner.pe_agent.no_csr_pending',
195
+ :certname => agent_certname,
196
+ :master => config.master_vm.name.to_s
197
+ )
198
+ return
199
+ end
200
+
201
+ config.master_vm.ui.info I18n.t(
202
+ 'pebuild.provisioner.pe_agent.signing_agent_cert',
203
+ :certname => agent_certname,
204
+ :master => config.master_vm.name.to_s
205
+ )
206
+
207
+ shell_config = Vagrant.plugin('2').manager.provisioner_configs[:shell].new
208
+ shell_config.privileged = true
209
+ # TODO: Extend paths to PE 3.x masters.
210
+ shell_config.inline = <<-EOS
211
+ /opt/puppetlabs/bin/puppet cert sign #{agent_certname}
212
+ EOS
213
+ shell_config.finalize!
214
+
215
+ shell_provisioner = Vagrant.plugin('2').manager.provisioners[:shell].new(config.master_vm, shell_config)
216
+ shell_provisioner.provision
217
+ end
218
+
219
+ def cleanup_agent_cert
220
+ # TODO: This isn't very flexible. But, the VM is destroyed at this
221
+ # point, so it's the best guess we have available.
222
+ agent_certname = machine.config.vm.hostname
223
+
224
+ unless is_reachable?(config.master_vm)
225
+ config.master_vm.ui.warn I18n.t(
226
+ 'pebuild.provisioner.pe_agent.skip_purge_master_not_reachable',
227
+ :vm_name => config.master_vm.name.to_s
228
+ )
229
+ return
230
+ end
231
+
232
+ # TODO: Extend paths to PE 3.x masters.
233
+ if not config.master_vm.communicate.test("/opt/puppetlabs/bin/puppet cert list #{agent_certname}", :sudo => true)
234
+ config.master_vm.ui.info I18n.t(
235
+ 'pebuild.provisioner.pe_agent.agent_purged',
236
+ :certname => agent_certname,
237
+ :master => config.master_vm.name.to_s
238
+ )
239
+ return
240
+ end
241
+
242
+ config.master_vm.ui.info I18n.t(
243
+ 'pebuild.provisioner.pe_agent.purging_agent',
244
+ :certname => agent_certname,
245
+ :master => config.master_vm.name.to_s
246
+ )
247
+
248
+ shell_config = Vagrant.plugin('2').manager.provisioner_configs[:shell].new
249
+ shell_config.privileged = true
250
+ # TODO: Extend to PE 3.x masters.
251
+ shell_config.inline = <<-EOS
252
+ /opt/puppetlabs/bin/puppet node purge #{agent_certname}
253
+ EOS
254
+ shell_config.finalize!
255
+
256
+ shell_provisioner = Vagrant.plugin('2').manager.provisioners[:shell].new(config.master_vm, shell_config)
257
+ shell_provisioner.provision
258
+ end
259
+
260
+ end
261
+ end
262
+ end
@@ -39,6 +39,6 @@ module PEBuild
39
39
  require 'pe_build/release/3_8'
40
40
  require 'pe_build/release/2015_2'
41
41
 
42
- LATEST_VERSION = '2015.2.1'
42
+ LATEST_VERSION = '2015.2.2'
43
43
  end
44
44
  end
@@ -34,4 +34,5 @@ module PEBuild::Release
34
34
 
35
35
  @releases['2015.2.0'] = twentyfifteen_two_x
36
36
  @releases['2015.2.1'] = twentyfifteen_two_x
37
+ @releases['2015.2.2'] = twentyfifteen_two_x
37
38
  end
@@ -0,0 +1,51 @@
1
+ require 'vagrant/errors'
2
+
3
+ module PEBuild
4
+ module Util
5
+ # Utilities related to Vagrant Machine communications
6
+ #
7
+ # This module provides general-purpose utility functions for communicating
8
+ # with Vagrant machines.
9
+ #
10
+ # @since 0.13.0
11
+ module MachineComms
12
+
13
+ # Determine if commands can be executed on a Vagrant machine
14
+ #
15
+ # @param machine [Vagrant::Machine] A Vagrant machine.
16
+ #
17
+ # @return [true] If the machine can accept communication.
18
+ # @return [false] If the machine cannot accept communication.
19
+ def is_reachable?(machine)
20
+ begin
21
+ machine.communicate.ready?
22
+ rescue Vagrant::Errors::VagrantError
23
+ # WinRM will raise an error if the VM isn't running instead of
24
+ # returning false (GH-6356).
25
+ false
26
+ end
27
+ end
28
+ module_function :is_reachable?
29
+
30
+ class MachineNotReachable < ::Vagrant::Errors::VagrantError
31
+ error_key(:machine_not_reachable, 'pebuild.errors')
32
+ end
33
+
34
+ # Raise an error if Vagrant commands cannot be executed on a machine
35
+ #
36
+ # This function raises an error if a given vagrant machine is not ready
37
+ # for communication.
38
+ #
39
+ # @param machine [Vagrant::Machine] A Vagrant machine.
40
+ #
41
+ # @return [void] If the machine can accept communication.
42
+ # @raise [MachineNotReachable] If the machine cannot accept
43
+ # communication.
44
+ def ensure_reachable(machine)
45
+ raise MachineNotReachable, :vm_name => machine.name.to_s unless is_reachable?(machine)
46
+ end
47
+ module_function :ensure_reachable
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,57 @@
1
+ module PEBuild
2
+ module Util
3
+ # Utilities related to PE Packages
4
+ #
5
+ # This module provides general-purpose utility functions for working with
6
+ # PE packages.
7
+ #
8
+ # @since 0.13.0
9
+ module PEPackaging
10
+
11
+ # Determine package tag from Facts
12
+ #
13
+ # The `platform_tag` is a `os-version-archtecture` value that is used in
14
+ # many PE package filenames and repostiory names.
15
+ #
16
+ # @param facts [Hash] A hash of facts which includes `architecture`
17
+ # and `os` values.
18
+ #
19
+ # @return [String] A string representing the platform tag.
20
+ def platform_tag(facts)
21
+ case facts['os']['family'].downcase
22
+ when 'redhat'
23
+ # TODO: Fedora might be in here.
24
+ os = 'el'
25
+ version = facts['os']['release']['major']
26
+ arch = facts['architecture']
27
+ when 'windows'
28
+ os = 'windows'
29
+ version = nil
30
+ arch = (facts['architecture'] == 'x64' ? 'x86_64' : 'i386')
31
+ when 'debian'
32
+ case os = facts['os']['name'].downcase
33
+ when 'debian'
34
+ version = facts['os']['release']['major']
35
+ when 'ubuntu'
36
+ version = facts['os']['release']['full']
37
+ end
38
+ # TODO: Add "unknown debian" error.
39
+ arch = (facts['architecture'] == 'x86_64' ? 'amd64' : 'i386')
40
+ when 'solaris'
41
+ os = 'solaris'
42
+ version = facts['os']['release']['major']
43
+ arch = (facts['architecture'].match(/^i\d+/) ? 'i386' : 'sparc')
44
+ when 'suse'
45
+ os = 'sles'
46
+ version = facts['os']['release']['major']
47
+ arch = facts['architecture']
48
+ end
49
+ # TODO: Add "unknown os" error.
50
+
51
+ [os, version, arch].join('-').downcase
52
+ end
53
+ module_function :platform_tag
54
+
55
+ end
56
+ end
57
+ end