beaker 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.simplecov +14 -0
  5. data/DOCUMENTING.md +167 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +17 -0
  8. data/README.md +332 -0
  9. data/Rakefile +121 -0
  10. data/beaker.gemspec +42 -0
  11. data/beaker.rb +10 -0
  12. data/bin/beaker +9 -0
  13. data/lib/beaker.rb +36 -0
  14. data/lib/beaker/answers.rb +29 -0
  15. data/lib/beaker/answers/version28.rb +104 -0
  16. data/lib/beaker/answers/version30.rb +194 -0
  17. data/lib/beaker/cli.rb +113 -0
  18. data/lib/beaker/command.rb +241 -0
  19. data/lib/beaker/command_factory.rb +21 -0
  20. data/lib/beaker/dsl.rb +85 -0
  21. data/lib/beaker/dsl/assertions.rb +87 -0
  22. data/lib/beaker/dsl/helpers.rb +625 -0
  23. data/lib/beaker/dsl/install_utils.rb +299 -0
  24. data/lib/beaker/dsl/outcomes.rb +99 -0
  25. data/lib/beaker/dsl/roles.rb +97 -0
  26. data/lib/beaker/dsl/structure.rb +63 -0
  27. data/lib/beaker/dsl/wrappers.rb +100 -0
  28. data/lib/beaker/host.rb +193 -0
  29. data/lib/beaker/host/aix.rb +15 -0
  30. data/lib/beaker/host/aix/file.rb +16 -0
  31. data/lib/beaker/host/aix/group.rb +35 -0
  32. data/lib/beaker/host/aix/user.rb +32 -0
  33. data/lib/beaker/host/unix.rb +54 -0
  34. data/lib/beaker/host/unix/exec.rb +15 -0
  35. data/lib/beaker/host/unix/file.rb +16 -0
  36. data/lib/beaker/host/unix/group.rb +40 -0
  37. data/lib/beaker/host/unix/pkg.rb +22 -0
  38. data/lib/beaker/host/unix/user.rb +32 -0
  39. data/lib/beaker/host/windows.rb +44 -0
  40. data/lib/beaker/host/windows/exec.rb +18 -0
  41. data/lib/beaker/host/windows/file.rb +15 -0
  42. data/lib/beaker/host/windows/group.rb +36 -0
  43. data/lib/beaker/host/windows/pkg.rb +26 -0
  44. data/lib/beaker/host/windows/user.rb +32 -0
  45. data/lib/beaker/hypervisor.rb +37 -0
  46. data/lib/beaker/hypervisor/aixer.rb +52 -0
  47. data/lib/beaker/hypervisor/blimper.rb +123 -0
  48. data/lib/beaker/hypervisor/fusion.rb +56 -0
  49. data/lib/beaker/hypervisor/solaris.rb +65 -0
  50. data/lib/beaker/hypervisor/vagrant.rb +118 -0
  51. data/lib/beaker/hypervisor/vcloud.rb +175 -0
  52. data/lib/beaker/hypervisor/vsphere.rb +80 -0
  53. data/lib/beaker/hypervisor/vsphere_helper.rb +200 -0
  54. data/lib/beaker/logger.rb +167 -0
  55. data/lib/beaker/network_manager.rb +73 -0
  56. data/lib/beaker/options_parsing.rb +323 -0
  57. data/lib/beaker/result.rb +55 -0
  58. data/lib/beaker/shared.rb +15 -0
  59. data/lib/beaker/shared/error_handler.rb +17 -0
  60. data/lib/beaker/shared/host_handler.rb +46 -0
  61. data/lib/beaker/shared/repetition.rb +28 -0
  62. data/lib/beaker/ssh_connection.rb +198 -0
  63. data/lib/beaker/test_case.rb +225 -0
  64. data/lib/beaker/test_config.rb +148 -0
  65. data/lib/beaker/test_suite.rb +288 -0
  66. data/lib/beaker/utils.rb +7 -0
  67. data/lib/beaker/utils/ntp_control.rb +42 -0
  68. data/lib/beaker/utils/repo_control.rb +92 -0
  69. data/lib/beaker/utils/setup_helper.rb +77 -0
  70. data/lib/beaker/utils/validator.rb +27 -0
  71. data/spec/beaker/command_spec.rb +94 -0
  72. data/spec/beaker/dsl/assertions_spec.rb +104 -0
  73. data/spec/beaker/dsl/helpers_spec.rb +230 -0
  74. data/spec/beaker/dsl/install_utils_spec.rb +70 -0
  75. data/spec/beaker/dsl/outcomes_spec.rb +43 -0
  76. data/spec/beaker/dsl/roles_spec.rb +86 -0
  77. data/spec/beaker/dsl/structure_spec.rb +60 -0
  78. data/spec/beaker/dsl/wrappers_spec.rb +52 -0
  79. data/spec/beaker/host_spec.rb +95 -0
  80. data/spec/beaker/logger_spec.rb +117 -0
  81. data/spec/beaker/options_parsing_spec.rb +37 -0
  82. data/spec/beaker/puppet_command_spec.rb +128 -0
  83. data/spec/beaker/ssh_connection_spec.rb +39 -0
  84. data/spec/beaker/test_case_spec.rb +6 -0
  85. data/spec/beaker/test_suite_spec.rb +44 -0
  86. data/spec/mocks_and_helpers.rb +34 -0
  87. data/spec/spec_helper.rb +15 -0
  88. metadata +359 -0
@@ -0,0 +1,54 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'host'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'command_factory'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'command'))
4
+
5
+ module Unix
6
+ class Host < Beaker::Host
7
+ require File.expand_path(File.join(File.dirname(__FILE__), 'unix', 'user'))
8
+ require File.expand_path(File.join(File.dirname(__FILE__), 'unix', 'group'))
9
+ require File.expand_path(File.join(File.dirname(__FILE__), 'unix', 'exec'))
10
+ require File.expand_path(File.join(File.dirname(__FILE__), 'unix', 'pkg'))
11
+ require File.expand_path(File.join(File.dirname(__FILE__), 'unix', 'file'))
12
+
13
+ include Unix::User
14
+ include Unix::Group
15
+ include Unix::File
16
+ include Unix::Exec
17
+ include Unix::Pkg
18
+
19
+ def self.pe_defaults
20
+ {
21
+ 'user' => 'root',
22
+ 'group' => 'pe-puppet',
23
+ 'puppetpath' => '/etc/puppetlabs/puppet',
24
+ 'puppetbin' => '/opt/puppet/bin/puppet',
25
+ 'puppetbindir' => '/opt/puppet/bin',
26
+ 'puppetvardir' => '/var/opt/lib/pe-puppet',
27
+ 'hieradatadir' => '/var/lib/hiera',
28
+ 'hieraconf' => '/etc/puppetlabs/puppet/hiera.yaml',
29
+ 'distmoduledir' => '/etc/puppetlabs/puppet/modules',
30
+ 'sitemoduledir' => '/opt/puppet/share/puppet/modules',
31
+ 'pathseparator' => ':',
32
+ }
33
+ end
34
+
35
+ def self.foss_defaults
36
+ {
37
+ 'user' => 'root',
38
+ 'group' => 'puppet',
39
+ 'puppetpath' => '/etc/puppet',
40
+ 'puppetvardir' => '/var/lib/puppet',
41
+ 'puppetbin' => '/usr/bin/puppet',
42
+ 'puppetbindir' => '/usr/bin',
43
+ 'hieralibdir' => '/opt/puppet-git-repos/hiera/lib',
44
+ 'hierapuppetlibdir' => '/opt/puppet-git-repos/hiera-puppet/lib',
45
+ 'hierabindir' => '/opt/puppet-git-repos/hiera/bin',
46
+ 'hieradatadir' => '/etc/puppet/hieradata',
47
+ 'hieraconf' => '/etc/puppet/hiera.yaml',
48
+ 'distmoduledir' => '/etc/puppet/modules',
49
+ 'sitemoduledir' => '/usr/share/puppet/modules',
50
+ 'pathseparator' => ':',
51
+ }
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,15 @@
1
+ module Unix::Exec
2
+ include Beaker::CommandFactory
3
+
4
+ def echo(msg, abs=true)
5
+ (abs ? '/bin/echo' : 'echo') + " #{msg}"
6
+ end
7
+
8
+ def touch(file, abs=true)
9
+ (abs ? '/bin/touch' : 'touch') + " #{file}"
10
+ end
11
+
12
+ def path
13
+ '/bin:/usr/bin'
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Unix::File
2
+ include Beaker::CommandFactory
3
+
4
+ def tmpfile(name)
5
+ execute("mktemp -t #{name}.XXXXXX")
6
+ end
7
+
8
+ def tmpdir(name)
9
+ execute("mktemp -td #{name}.XXXXXX")
10
+ end
11
+
12
+ def path_split(paths)
13
+ paths.split(':')
14
+ end
15
+
16
+ end
@@ -0,0 +1,40 @@
1
+ module Unix::Group
2
+ include Beaker::CommandFactory
3
+
4
+ def group_list(&block)
5
+ execute("getent group") do |result|
6
+ groups = []
7
+ result.stdout.each_line do |line|
8
+ groups << (line.match(/^([^:]+)/) or next)[1]
9
+ end
10
+
11
+ yield result if block_given?
12
+
13
+ groups
14
+ end
15
+ end
16
+
17
+ def group_get(name, &block)
18
+ execute("getent group #{name}") do |result|
19
+ fail_test "failed to get group #{name}" unless result.stdout =~ /^#{name}:.*:[0-9]+:/
20
+
21
+ yield result if block_given?
22
+ end
23
+ end
24
+
25
+ def group_gid(name)
26
+ execute("getent group #{name}") do |result|
27
+ # Format is:
28
+ # wheel:x:10:root
29
+ result.stdout.split(':')[2]
30
+ end
31
+ end
32
+
33
+ def group_present(name, &block)
34
+ execute("if ! getent group #{name}; then groupadd #{name}; fi", {}, &block)
35
+ end
36
+
37
+ def group_absent(name, &block)
38
+ execute("if getent group #{name}; then groupdel #{name}; fi", {}, &block)
39
+ end
40
+ end
@@ -0,0 +1,22 @@
1
+ module Unix::Pkg
2
+ include Beaker::CommandFactory
3
+
4
+ def check_for_package name
5
+ result = exec(Beaker::Command.new("which #{name}"), :acceptable_exit_codes => (0...127))
6
+ result.exit_code == 0
7
+ end
8
+
9
+ def install_package name
10
+ if self['platform'] =~ /el-4/
11
+ @logger.debug("Package installation not supported on rhel4")
12
+ elsif self['platform'] =~ /(fedora)|(centos)|(el)/
13
+ execute("yum -y install #{name}")
14
+ elsif self['platform'] =~ /(ubuntu)|(debian)/
15
+ execute("apt-get update")
16
+ execute("apt-get install -y #{name}")
17
+ else
18
+ raise "Package #{name} cannot be installed on #{host}"
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,32 @@
1
+ module Unix::User
2
+ include Beaker::CommandFactory
3
+
4
+ def user_list(&block)
5
+ execute("getent passwd") do |result|
6
+ users = []
7
+ result.stdout.each_line do |line|
8
+ users << (line.match( /^([^:]+)/) or next)[1]
9
+ end
10
+
11
+ yield result if block_given?
12
+
13
+ users
14
+ end
15
+ end
16
+
17
+ def user_get(name, &block)
18
+ execute("getent passwd #{name}") do |result|
19
+ fail_test "failed to get user #{name}" unless result.stdout =~ /^#{name}:/
20
+
21
+ yield result if block_given?
22
+ end
23
+ end
24
+
25
+ def user_present(name, &block)
26
+ execute("if ! getent passwd #{name}; then useradd #{name}; fi", {}, &block)
27
+ end
28
+
29
+ def user_absent(name, &block)
30
+ execute("if getent passwd #{name}; then userdel #{name}; fi", {}, &block)
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'host'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'command_factory'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'command'))
4
+
5
+ module Windows
6
+ class Host < Beaker::Host
7
+ require File.expand_path(File.join(File.dirname(__FILE__), 'windows', 'user'))
8
+ require File.expand_path(File.join(File.dirname(__FILE__), 'windows', 'group'))
9
+ require File.expand_path(File.join(File.dirname(__FILE__), 'windows', 'exec'))
10
+ require File.expand_path(File.join(File.dirname(__FILE__), 'windows', 'pkg'))
11
+ require File.expand_path(File.join(File.dirname(__FILE__), 'windows', 'file'))
12
+
13
+ include Windows::User
14
+ include Windows::Group
15
+ include Windows::File
16
+ include Windows::Exec
17
+ include Windows::Pkg
18
+
19
+ def self.pe_defaults
20
+ {
21
+ 'user' => 'Administrator',
22
+ 'group' => 'Administrators',
23
+ 'puppetpath' => '`cygpath -smF 35`/PuppetLabs/puppet/etc',
24
+ 'puppetvardir' => '`cygpath -smF 35`/PuppetLabs/puppet/var',
25
+ 'puppetbindir' => '`cygpath -F 38`/Puppet Labs/Puppet Enterprise/bin',
26
+ 'pathseparator' => ';',
27
+ }
28
+ end
29
+
30
+ def self.foss_defaults
31
+ {
32
+ 'user' => 'Administrator',
33
+ 'group' => 'Administrators',
34
+ 'puppetpath' => '`cygpath -smF 35`/PuppetLabs/puppet/etc',
35
+ 'puppetvardir' => '`cygpath -smF 35`/PuppetLabs/puppet/var',
36
+ 'hieralibdir' => '`cygpath -w /opt/puppet-git-repos/hiera/lib`',
37
+ 'hierapuppetlibdir' => '`cygpath -w /opt/puppet-git-repos/hiera-puppet/lib`',
38
+ # PATH related variables need to be Unix, which cygwin converts
39
+ 'hierabindir' => '/opt/puppet-git-repos/hiera/bin',
40
+ 'pathseparator' => ';',
41
+ }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ module Windows::Exec
2
+ include Beaker::CommandFactory
3
+
4
+ ABS_CMD = 'c:\\\\windows\\\\system32\\\\cmd.exe'
5
+ CMD = 'cmd.exe'
6
+
7
+ def echo(msg, abs=true)
8
+ (abs ? ABS_CMD : CMD) + " /c echo #{msg}"
9
+ end
10
+
11
+ def touch(file, abs=true)
12
+ (abs ? ABS_CMD : CMD) + " /c echo. 2> #{file}"
13
+ end
14
+
15
+ def path
16
+ 'c:/windows/system32;c:/windows'
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ module Windows::File
2
+ include Beaker::CommandFactory
3
+
4
+ def tmpfile(name)
5
+ execute("cygpath -m $(mktemp -t #{name}.XXXXXX)")
6
+ end
7
+
8
+ def tmpdir(name)
9
+ execute("cygpath -m $(mktemp -td #{name}.XXXXXX)")
10
+ end
11
+
12
+ def path_split(paths)
13
+ paths.split(';')
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ module Windows::Group
2
+ include Beaker::CommandFactory
3
+
4
+ def group_list(&block)
5
+ execute('cmd /c echo "" | wmic group where localaccount="true" get name /format:value') do |result|
6
+ groups = []
7
+ result.stdout.each_line do |line|
8
+ groups << (line.match(/^Name=([\w ]+)/) or next)[1]
9
+ end
10
+
11
+ yield result if block_given?
12
+
13
+ groups
14
+ end
15
+ end
16
+
17
+ def group_get(name, &block)
18
+ execute("net localgroup \"#{name}\"") do |result|
19
+ fail_test "failed to get group #{name}" unless result.stdout =~ /^Alias name\s+#{name}/
20
+
21
+ yield result if block_given?
22
+ end
23
+ end
24
+
25
+ def group_gid(name)
26
+ raise NotImplementedError, "Can't retrieve group gid on a Windows host"
27
+ end
28
+
29
+ def group_present(name, &block)
30
+ execute("net localgroup /add \"#{name}\"", {:acceptable_exit_codes => [0,2]}, &block)
31
+ end
32
+
33
+ def group_absent(name, &block)
34
+ execute("net localgroup /delete \"#{name}\"", {:acceptable_exit_codes => [0,2]}, &block)
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ module Windows::Pkg
2
+ include Beaker::CommandFactory
3
+
4
+ def check_for_package name
5
+ result = exec(Beaker::Command.new("which #{name}"), :acceptable_exit_codes => (0...127))
6
+ result.exit_code == 0
7
+ end
8
+
9
+ def install_package name
10
+ cygwin = ""
11
+ rootdir = ""
12
+ result = exec(Beaker::Command.new("wmic os get osarchitecture | grep 32"), :acceptable_exit_codes => (0...127))
13
+ if result.exit_code == 0 #32 bit version
14
+ rootdir = "c:\\\\cygwin"
15
+ cygwin = "setup-x86.exe"
16
+ else #64 bit version
17
+ rootdir = "c:\\\\cygwin64"
18
+ cygwin = "setup-x86_64.exe"
19
+ end
20
+ if not check_for_package(cygwin)
21
+ execute("curl --retry 5 http://cygwin.com/#{cygwin} -o /cygdrive/c/Windows/System32/#{cygwin}")
22
+ end
23
+ execute("#{cygwin} -q -n -N -d -R #{rootdir} -s http://cygwin.osuosl.org -P #{name}")
24
+ end
25
+
26
+ end
@@ -0,0 +1,32 @@
1
+ module Windows::User
2
+ include Beaker::CommandFactory
3
+
4
+ def user_list(&block)
5
+ execute('cmd /c echo "" | wmic useraccount where localaccount="true" get name /format:value') do |result|
6
+ users = []
7
+ result.stdout.each_line do |line|
8
+ users << (line.match(/^Name=([\w ]+)/) or next)[1]
9
+ end
10
+
11
+ yield result if block_given?
12
+
13
+ users
14
+ end
15
+ end
16
+
17
+ def user_get(name, &block)
18
+ execute("net user \"#{name}\"") do |result|
19
+ fail_test "failed to get user #{name}" unless result.stdout =~ /^User name\s+#{name}/
20
+
21
+ yield result if block_given?
22
+ end
23
+ end
24
+
25
+ def user_present(name, &block)
26
+ execute("net user /add \"#{name}\"", {:acceptable_exit_codes => [0,2]}, &block)
27
+ end
28
+
29
+ def user_absent(name, &block)
30
+ execute("net user /delete \"#{name}\"", {:acceptable_exit_codes => [0,2]}, &block)
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ module Beaker
2
+ class Hypervisor
3
+
4
+ def configure(hosts)
5
+ @logger.debug "No post-provisioning configuration necessary for #{self.class.name} boxes"
6
+ end
7
+
8
+ def self.create type, hosts_to_provision, options, config
9
+ @logger = options[:logger]
10
+ @logger.notify("Beaker::Hypervisor, found some #{type} boxes to create")
11
+ case type
12
+ when /aix/
13
+ Beaker::Aixer.new hosts_to_provision, options, config
14
+ when /solaris/
15
+ Beaker::Solaris.new hosts_to_provision, options, config
16
+ when /vsphere/
17
+ Beaker::Vsphere.new hosts_to_provision, options, config
18
+ when /fusion/
19
+ Beaker::Fusion.new hosts_to_provision, options, config
20
+ when /blimpy/
21
+ Beaker::Blimper.new hosts_to_provision, options, config
22
+ when /vcloud/
23
+ Beaker::Vcloud.new hosts_to_provision, options, config
24
+ when /vagrant/
25
+ Beaker::Vagrant.new hosts_to_provision, options, config
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ %w( vsphere_helper vagrant fusion blimper vsphere vcloud aixer solaris).each do |lib|
32
+ begin
33
+ require "hypervisor/#{lib}"
34
+ rescue LoadError
35
+ require File.expand_path(File.join(File.dirname(__FILE__), "hypervisor", lib))
36
+ end
37
+ end
@@ -0,0 +1,52 @@
1
+ module Beaker
2
+ class Aixer < Beaker::Hypervisor
3
+
4
+ def initialize(aix_hosts, options, config)
5
+ @options = options
6
+ @config = config['CONFIG'].dup
7
+ @logger = options[:logger]
8
+ @aix_hosts = aix_hosts
9
+ #aix machines are reverted to known state, not a snapshot
10
+ fog_file = nil
11
+ if File.exists?( File.join(ENV['HOME'], '.fog') )
12
+ fog_file = YAML.load_file( File.join(ENV['HOME'], '.fog') )
13
+ end
14
+ raise "Cant load ~/.fog config" unless fog_file
15
+
16
+ # Running the rake task on rpm-builder
17
+ hypername = fog_file[:default][:aix_hypervisor_server]
18
+ hyperconf = {
19
+ 'HOSTS' => {
20
+ hypername => { 'platform' => 'el-6-x86_64' }
21
+ },
22
+ 'CONFIG' => {
23
+ 'user' => fog_file[:default][:aix_hypervisor_username] || ENV['USER'],
24
+ 'ssh' => {
25
+ :keys => fog_file[:default][:aix_hypervisor_keyfile] || "#{ENV['HOME']}/.ssh/id_rsa"
26
+ }
27
+ }
28
+ }
29
+ hyperconfig = Beaker::TestConfig.new( hyperconf, @options )
30
+
31
+ @logger.notify "Connecting to hypervisor at #{hypername}"
32
+ hypervisor = Beaker::Host.create( hypername, @options, hyperconfig )
33
+
34
+ @aix_hosts.each do |host|
35
+ vm_name = host['vmname'] || host.name
36
+
37
+ @logger.notify "Reverting #{vm_name} to aix clean state"
38
+ start = Time.now
39
+ # Restore AIX image, ID'd by the hostname
40
+ hypervisor.exec(Command.new("cd pe-aix && rake restore:#{host.name}"))
41
+ time = Time.now - start
42
+ @logger.notify "Spent %.2f seconds reverting" % time
43
+ end
44
+ hypervisor.close
45
+ end
46
+
47
+ def cleanup
48
+ @logger.notify "No cleanup for aix boxes"
49
+ end
50
+
51
+ end
52
+ end