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
@@ -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