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
@@ -1,7 +1,7 @@
1
1
  shared_examples 'provider/provisioner/pe_bootstrap/latest' do |provider, options|
2
- if !File.file?(options[:box])
2
+ if options[:boxes].empty?
3
3
  raise ArgumentError,
4
- "A box file must be downloaded for provider: #{provider}. Try: rake acceptance:setup"
4
+ "Box files must be downloaded for provider: #{provider}. Try: rake acceptance:setup"
5
5
  end
6
6
 
7
7
  include_context 'acceptance'
@@ -19,7 +19,10 @@ shared_examples 'provider/provisioner/pe_bootstrap/latest' do |provider, options
19
19
 
20
20
  before(:each) do
21
21
  environment.skeleton('pe_build')
22
- assert_execute('vagrant', 'box', 'add', 'box', options[:box])
22
+ options[:boxes].each do |box|
23
+ name = File.basename(box).split('-').first
24
+ assert_execute('vagrant', 'box', 'add', name, box)
25
+ end
23
26
  end
24
27
 
25
28
  after(:each) do
@@ -7,88 +7,64 @@ end
7
7
 
8
8
  Vagrant.configure('2') do |config|
9
9
  config.pe_build.download_root = ENV['PE_BUILD_DOWNLOAD_ROOT']
10
- # This is the box name used by the setup helpers in the acceptance tests.
11
- config.vm.box = 'box'
12
- config.vm.provision :shell, :inline => 'service iptables stop'
13
10
 
14
- config.vm.define 'pe-201520-master' do |node|
15
- node.vm.hostname = 'pe-201520-master.pe-bootstrap.vlan'
11
+ config.vm.define 'pe-20152-master' do |node|
12
+ node.vm.hostname = 'pe-20152-master.pe-bootstrap.vlan'
13
+ node.vm.box = 'centos'
16
14
  # All-in-one master nodes need a generous amount of RAM for all the Java.
17
15
  set_resources node, 4096, 1
16
+ node.vm.provision :shell, :inline => 'service iptables stop'
18
17
 
19
18
  node.vm.network 'private_network', :ip => '10.20.1.100'
20
- node.vm.provision :shell, :inline => 'echo "10.20.1.101 pe-201520-agent.pe-bootstrap.vlan" >> /etc/hosts'
21
-
22
- node.vm.provision :pe_bootstrap do |p|
23
- p.version = '2015.2.0'
24
- p.role = :master
25
- end
26
- end
27
-
28
- config.vm.define 'pe-201520-agent' do |node|
29
- node.vm.hostname = 'pe-201520-agent.pe-bootstrap.vlan'
30
-
31
- node.vm.network 'private_network', :ip => '10.20.1.101'
32
- node.vm.provision :shell, :inline => 'echo "10.20.1.100 pe-201520-master.pe-bootstrap.vlan" >> /etc/hosts'
33
-
34
- node.vm.provision :pe_bootstrap do |p|
35
- p.version = '2015.2.0'
36
- p.role = :agent
37
- p.master = 'pe-201520-master.pe-bootstrap.vlan'
38
- end
39
- end
40
-
41
- config.vm.define 'pe-201521-master' do |node|
42
- node.vm.hostname = 'pe-201521-master.pe-bootstrap.vlan'
43
- # All-in-one master nodes need a generous amount of RAM for all the Java.
44
- set_resources node, 4096, 1
45
-
46
- node.vm.network 'private_network', :ip => '10.20.1.102'
47
- node.vm.provision :shell, :inline => 'echo "10.20.1.103 pe-201521-agent.pe-bootstrap.vlan" >> /etc/hosts'
19
+ node.vm.provision :shell, :inline => 'echo "10.20.1.101 pe-20152-agent.pe-bootstrap.vlan" >> /etc/hosts'
48
20
 
49
21
  node.vm.provision :pe_bootstrap do |p|
50
22
  p.version = '2015.2.1'
51
23
  p.role = :master
24
+ # Set autosign to false so that we can test pe_agent functionality.
25
+ p.autosign = false
52
26
  end
53
27
  end
54
28
 
55
- config.vm.define 'pe-201521-agent' do |node|
56
- node.vm.hostname = 'pe-201521-agent.pe-bootstrap.vlan'
29
+ config.vm.define 'pe-20152-agent' do |node|
30
+ node.vm.hostname = 'pe-20152-agent.pe-bootstrap.vlan'
31
+ node.vm.box = 'ubuntu'
57
32
 
58
- node.vm.network 'private_network', :ip => '10.20.1.103'
59
- node.vm.provision :shell, :inline => 'echo "10.20.1.102 pe-201521-master.pe-bootstrap.vlan" >> /etc/hosts'
33
+ node.vm.network 'private_network', :ip => '10.20.1.101'
34
+ node.vm.provision :shell, :inline => 'echo "10.20.1.100 pe-20152-master.pe-bootstrap.vlan" >> /etc/hosts'
60
35
 
61
- node.vm.provision :pe_bootstrap do |p|
62
- p.version = '2015.2.1'
63
- p.role = :agent
64
- p.master = 'pe-201521-master.pe-bootstrap.vlan'
36
+ node.vm.provision :pe_agent do |p|
37
+ p.master_vm = 'pe-20152-master'
65
38
  end
66
39
  end
67
40
 
68
41
  config.vm.define 'pe-2015latest-master' do |node|
69
42
  node.vm.hostname = 'pe-2015latest-master.pe-bootstrap.vlan'
43
+ node.vm.box = 'centos'
70
44
  # All-in-one master nodes need a generous amount of RAM for all the Java.
71
45
  set_resources node, 4096, 1
46
+ node.vm.provision :shell, :inline => 'service iptables stop'
72
47
 
73
- node.vm.network 'private_network', :ip => '10.20.1.104'
74
- node.vm.provision :shell, :inline => 'echo "10.20.1.105 pe-2015latest-agent.pe-bootstrap.vlan" >> /etc/hosts'
48
+ node.vm.network 'private_network', :ip => '10.20.1.102'
49
+ node.vm.provision :shell, :inline => 'echo "10.20.1.103 pe-2015latest-agent.pe-bootstrap.vlan" >> /etc/hosts'
75
50
 
76
51
  node.vm.provision :pe_bootstrap do |p|
77
52
  p.version_file = 'LATEST'
78
53
  p.role = :master
54
+ # Set autosign to false so that we can test pe_agent functionality.
55
+ p.autosign = false
79
56
  end
80
57
  end
81
58
 
82
59
  config.vm.define 'pe-2015latest-agent' do |node|
83
60
  node.vm.hostname = 'pe-2015latest-agent.pe-bootstrap.vlan'
61
+ node.vm.box = 'ubuntu'
84
62
 
85
- node.vm.network 'private_network', :ip => '10.20.1.105'
86
- node.vm.provision :shell, :inline => 'echo "10.20.1.104 pe-2015latest-master.pe-bootstrap.vlan" >> /etc/hosts'
63
+ node.vm.network 'private_network', :ip => '10.20.1.103'
64
+ node.vm.provision :shell, :inline => 'echo "10.20.1.102 pe-2015latest-master.pe-bootstrap.vlan" >> /etc/hosts'
87
65
 
88
- node.vm.provision :pe_bootstrap do |p|
89
- p.version_file = 'LATEST'
90
- p.role = :agent
91
- p.master = 'pe-2015latest-master.pe-bootstrap.vlan'
66
+ node.vm.provision :pe_agent do |p|
67
+ p.master_vm = 'pe-2015latest-master'
92
68
  end
93
69
  end
94
70
  end
@@ -8,7 +8,7 @@ end
8
8
  Vagrant.configure('2') do |config|
9
9
  config.pe_build.download_root = ENV['PE_BUILD_DOWNLOAD_ROOT']
10
10
  # This is the box name used by the setup helpers in the acceptance tests.
11
- config.vm.box = 'box'
11
+ config.vm.box = 'centos'
12
12
 
13
13
  config.vm.define 'pe-3x' do |node|
14
14
  node.vm.hostname = 'pe-3x.pe-bootstrap.vlan'
data/lib/pe_build/cap.rb CHANGED
@@ -17,6 +17,15 @@ module PEBuild
17
17
  require 'pe_build/cap/detect_installer/solaris'
18
18
  end
19
19
 
20
+ module Facts
21
+ require 'pe_build/cap/facts/redhat'
22
+ require 'pe_build/cap/facts/debian'
23
+ require 'pe_build/cap/facts/ubuntu'
24
+ require 'pe_build/cap/facts/suse'
25
+ require 'pe_build/cap/facts/solaris'
26
+ require 'pe_build/cap/facts/windows'
27
+ end
28
+
20
29
  module RunInstall
21
30
  require 'pe_build/cap/run_install/posix'
22
31
  require 'pe_build/cap/run_install/windows'
@@ -12,4 +12,22 @@ class PEBuild::Cap::DetectInstaller::Base
12
12
  # Return the installer for the given operating system
13
13
  # @abstract
14
14
  # @return [String] The installer for the given operating system
15
+
16
+ private
17
+
18
+ # TODO: Consolidate with implementation in Cap::Facts::Base.
19
+ def execute_command(cmd)
20
+ stdout = ''
21
+ stderr = ''
22
+
23
+ retval = @machine.communicate.execute(cmd, :error_check => false) do |type, data|
24
+ if type == :stderr
25
+ stderr << data
26
+ else
27
+ stdout << data
28
+ end
29
+ end
30
+
31
+ {:stdout => stdout.chomp, :stderr => stderr.chomp, :retval => retval}
32
+ end
15
33
  end
@@ -87,19 +87,4 @@ class PEBuild::Cap::DetectInstaller::POSIX < PEBuild::Cap::DetectInstaller::Base
87
87
 
88
88
  matchdata[1]
89
89
  end
90
-
91
- def execute_command(cmd)
92
- stdout = ''
93
- stderr = ''
94
-
95
- retval = @machine.communicate.execute(cmd, :error_check => false) do |type, data|
96
- if type == :stderr
97
- stderr << data
98
- else
99
- stdout << data
100
- end
101
- end
102
-
103
- {:stdout => stdout.chomp, :stderr => stderr.chomp, :retval => retval}
104
- end
105
90
  end
@@ -1,13 +1,31 @@
1
- # Provide an abstract base class for detecting the installer name on
2
- # POSIX systems.
1
+ require 'pe_build/util/version_string'
2
+
3
+ # detect_installer implementation for Windows guests
3
4
  #
4
5
  # @abstract
5
6
  # @api protected
6
7
  class PEBuild::Cap::DetectInstaller::Windows < PEBuild::Cap::DetectInstaller::Base
7
8
 
8
9
  def detect
9
- # Yes, it really is this simple. For Windows anyway.
10
- "puppet-enterprise-#{@version}.msi"
10
+ # Starting with PE 3.7.0, separate 64-bit packages are shipped for Windows.
11
+ if (PEBuild::Util::VersionString.compare(@version, '3.7.0') >= 0) && (arch == 'x64')
12
+ "puppet-enterprise-#{@version}-x64.msi"
13
+ else
14
+ "puppet-enterprise-#{@version}.msi"
15
+ end
16
+ end
17
+
18
+ # @since 0.13.0
19
+ def arch
20
+ results = execute_command('if ([System.IntPtr]::Size -eq 4) { "x86" } else { "x64" }')
21
+
22
+ unless results[:retval] == 0
23
+ raise PEBuild::Cap::DetectInstaller::DetectFailed,
24
+ :name => @machine.name,
25
+ :error => "Could not determine Windows architecture on #{@machine.name}: got #{results[:stderr]}"
26
+ end
27
+
28
+ results[:stdout]
11
29
  end
12
30
 
13
31
  end
@@ -0,0 +1,119 @@
1
+ require 'json'
2
+
3
+ # Base class for retrieving facts from guest VMs
4
+ #
5
+ # This class implements a Guest Capability for Fact retrieval. Puppet will be
6
+ # queried, if installed. Otherwise, a minimal set of base facts willPuppetbe
7
+ # returned by {#basic_facts}.
8
+ #
9
+ # @abstract Subclass and override {#architecture}, {#os_info} and
10
+ # {#release_info} to implement for a particular guest operating system.
11
+ #
12
+ # @since 0.13.0
13
+ class PEBuild::Cap::Facts::Base
14
+
15
+ # Retrieve facts from a guest VM
16
+ #
17
+ # See {#load_facts} for implementation details.
18
+ #
19
+ # @return [Hash] A hash of facts.
20
+ def self.pebuild_facts(machine)
21
+ new(machine).load_facts
22
+ end
23
+
24
+ attr_reader :machine
25
+
26
+ def initialize(machine)
27
+ @machine = machine
28
+ end
29
+
30
+ def puppet_path
31
+ @puppet_path ||= find_puppet
32
+ end
33
+
34
+ # Load Facts from the guest VM
35
+ #
36
+ # @return [Hash] A hash of facts from Puppet, if installed.
37
+ # @return [Hash] A hash containing the results of {#basic_facts} if
38
+ # Facter is not installed.
39
+ def load_facts
40
+ unless puppet_path.nil?
41
+ certname = sudo("#{puppet_path} agent --configprint certname")[:stdout].chomp
42
+ raw_facts = JSON.load(sudo("#{puppet_path} facts find --render-as json --terminus facter #{certname}")[:stdout])
43
+ facts = raw_facts['values']
44
+ # Keep the certname of the agent.
45
+ facts['certname'] = certname
46
+ else
47
+ # Puppet isn't installed yet, so we gather a minimal set of info.
48
+ facts = basic_facts
49
+ end
50
+
51
+ # JSON.load can do funny things. Sort by top-level key.
52
+ Hash[facts.sort]
53
+ end
54
+
55
+ # Determine basic info about a guest
56
+ #
57
+ # This function returns a minimal set of basic facts which should be
58
+ # sufficient to determine what software to install on the guest.
59
+ #
60
+ # @return [Hash] A hash containing the `architecture` and `os` facts.
61
+ def basic_facts
62
+ {
63
+ 'architecture' => architecture,
64
+ 'os' => {
65
+ 'release' => release_info
66
+ }.update(os_info)
67
+ }
68
+ end
69
+
70
+ # Returns the native architecture of the OS
71
+ #
72
+ # @return [String] An architecture, such as `i386` or `x86_64`.
73
+ def architecture
74
+ raise NotImplementedError
75
+ end
76
+
77
+ # Returns info about the OS type
78
+ #
79
+ # @return [Hash] A hash containing the `family` of the operating system and,
80
+ # optionally, the `name`.
81
+ def os_info
82
+ raise NotImplementedError
83
+ end
84
+
85
+ # Returns info about the OS version
86
+ #
87
+ # @return [Hash] A hash containing the `full` version strying of the
88
+ # operating system and, optionally, the `minor` and `major`
89
+ # release versions.
90
+ def release_info
91
+ raise NotImplementedError
92
+ end
93
+
94
+ private
95
+
96
+ # Override this method to implement a more sophisticated search for the
97
+ # Puppet executable.
98
+ def find_puppet
99
+ return 'puppet' if @machine.communicate.test('puppet --version')
100
+ return nil
101
+ end
102
+
103
+ # TODO: Split this out into a shared module.
104
+ def sudo(cmd)
105
+ stdout = ''
106
+ stderr = ''
107
+
108
+ retval = machine.communicate.sudo(cmd) do |type, data|
109
+ if type == :stderr
110
+ stderr << data.chomp
111
+ else
112
+ stdout << data.chomp
113
+ end
114
+ end
115
+
116
+ {:stdout => stdout, :stderr => stderr, :retval => retval}
117
+ end
118
+
119
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'posix'
2
+
3
+ # Facts implementation for Debian guests
4
+ #
5
+ # @since 0.13.0
6
+ class PEBuild::Cap::Facts::Debian < PEBuild::Cap::Facts::POSIX
7
+
8
+ # (see PEBuild::Cap::Facts::Base#os_info)
9
+ #
10
+ # Returns `family` as `Debian` and `name` as `Debian`.
11
+ #
12
+ # @see PEBuild::Cap::Facts::Base#os_info
13
+ def os_info
14
+ {
15
+ 'name' => 'Debian',
16
+ 'family' => 'Debian'
17
+ }
18
+ end
19
+
20
+ # (see PEBuild::Cap::Facts::Base#release_info)
21
+ #
22
+ # Reads `/etc/debian_version` and generates a `full` version along with
23
+ # `major` and `minor` components.
24
+ #
25
+ # @see PEBuild::Cap::Facts::Base#release_info
26
+ def release_info
27
+ release_file = sudo('cat /etc/debian_version')[:stdout]
28
+ version = release_file.match(/(\d+\.\d+)/)[1]
29
+
30
+ {
31
+ 'major' => version.split('.', 2)[0],
32
+ 'minor' => version.split('.', 2)[1],
33
+ 'full' => version
34
+ }
35
+ end
36
+
37
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'base'
2
+
3
+ # Base class for retrieving facts from POSIX
4
+ #
5
+ # @abstract Subclass and override {#os_info} and {#release_info} to implement
6
+ # for a particular POSIX system.
7
+ #
8
+ # @since 0.13.0
9
+ class PEBuild::Cap::Facts::POSIX < PEBuild::Cap::Facts::Base
10
+
11
+ # (see PEBuild::Cap::Facts::Base#architecture)
12
+ #
13
+ # This method is a concrete implementation which uses `uname -m`.
14
+ #
15
+ # @see PEBuild::Cap::Facts::Base#architecture
16
+ def architecture
17
+ sudo('uname -m')[:stdout]
18
+ end
19
+
20
+ private
21
+
22
+ def find_facter
23
+ paths = %w[
24
+ /opt/puppetlabs/bin/puppet
25
+ /opt/puppet/bin/puppet
26
+ /usr/local/bin/puppet
27
+ ]
28
+
29
+ paths.each do |path|
30
+ return path if @machine.communicate.test("#{path} --version")
31
+ end
32
+
33
+ return nil
34
+ end
35
+
36
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'posix'
2
+
3
+ # Facts implementation for RedHat guests
4
+ #
5
+ # @since 0.13.0
6
+ class PEBuild::Cap::Facts::RedHat < PEBuild::Cap::Facts::POSIX
7
+
8
+ # (see PEBuild::Cap::Facts::Base#os_info)
9
+ #
10
+ # Currently returns `family` as `RedHat`.
11
+ # @todo Implement `name` detection (RHEL, CentOS, Sci. Linux, etc.).
12
+ #
13
+ # @see PEBuild::Cap::Facts::Base#os_info
14
+ def os_info
15
+ {
16
+ 'family' => 'RedHat'
17
+ }
18
+ end
19
+
20
+ # (see PEBuild::Cap::Facts::Base#release_info)
21
+ #
22
+ # Reads `/etc/redhat-release` and generates a `full` version along with
23
+ # `major` and `minor` components.
24
+ #
25
+ # @see PEBuild::Cap::Facts::Base#release_info
26
+ def release_info
27
+ release_file = sudo('cat /etc/redhat-release')[:stdout]
28
+ version = release_file.match(/release (\d+\.\d+)/)[1]
29
+
30
+ {
31
+ 'major' => version.split('.', 2)[0],
32
+ 'minor' => version.split('.', 2)[1],
33
+ 'full' => version
34
+ }
35
+ end
36
+
37
+ end