vagrant-pe_build 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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