beaker 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MTM0OWZkNGIzNmYyNDhhMjI4Zjk1ODE4M2I5OGZiMTIyMTJlYmJlNg==
4
+ YzczNTY1ZTQ2MDkwOWE2YzhhNDhmMjVlNGVkZGQ0YmY4MTcwYjk2NA==
5
5
  data.tar.gz: !binary |-
6
- MGM1MWNkMDNiMWE1ZWNiNTMzNjE2MTg1MDNjYWRjNzRiMDQ2ZmRjZg==
6
+ ZmEwZWVjOGUwZGMyZjJmMGVjZWMxMWRjYmJkY2ZlYmU4Njc4MDMzYw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NWVkM2ExMzE4MjQzOWQ3MDViZThkMjUzNmFhOWRlMmQ0MTljNzNmY2JlMTkw
10
- MWQ2NjQxNGUyMmUwYmZiNGQ0MzhmYTdjMzA1ODg2ZGQ4OThiOGVmOTMwZGEx
11
- ZjAyM2E2NjhiODJhZDYyOTI1MjMxMzc0NjhlYjNkYWMxYmRiNmQ=
9
+ YWVmNmJjZGFlOTFkN2RiM2FiNjBiZDZlZThmMThkNDQ0NzY3YjE1OTYxMmY1
10
+ Zjg2NTk2NDA3NzkyYjYyNTU4ZDVlYWI5MDBiMWVjMjEyM2E2ZWViNTk0Zjg0
11
+ M2ZiNmVkMzYwNWQ5MDRkNzY2ZGE3YjQ5ZDY1ZDI0YjFkMjdjMzU=
12
12
  data.tar.gz: !binary |-
13
- OGJlNjgxYzk0ZmE1NTQ0MjIxZDVkMDhiMmRlN2ExMTc1ZGYwZDVmODU4MThk
14
- MTA4MjRkNzFlYjIzNzhmMjhlMTNhMmExMzAxYWFjYzg0NWJkZmI5YmJiZTY3
15
- YjMxYmI3ZWVkOTM2ZjY3Y2JjYmU4ODViYTJmODA2NGVhZTkxZDY=
13
+ YzdlM2U2Njk1MjAxYTg5MmMyNWU0Mzg0NGI5OWI2ZTMwMDgyODQwZGM4NDY2
14
+ MWYyY2E0ZDU2ZWQ5MjQwYWMzMzEzY2ViNjllNmQzMTI2YzAwNzFlZDQ0NDE3
15
+ OTJmN2E0NjBhOTczNjc5MGY5ZjkwNTMyZDRkMmNiMDVlY2ZlYzA=
data/README.md CHANGED
@@ -82,6 +82,51 @@ In this case, the host 'ubuntu-1004-32' is now the Puppet Master, while 'ubuntu-
82
82
  Puppet Dashboard host, resulting in a split Master/Dashboard install. Systest will automagically
83
83
  prepare an appropriate answers file for use with the PE Installer.
84
84
 
85
+ ## Required Host Settings ##
86
+ To properly define a host you must provide:
87
+
88
+ * name
89
+ * The string identifying this host
90
+ * platform
91
+ * One of the Beaker supported platforms
92
+
93
+ ## Optional Host Settings ##
94
+ Additionaly, Beaker supports the following host options:
95
+
96
+ * ip
97
+ * the IP address of the SUT
98
+ * hypervisor
99
+ * one of `solaris`, `blimpy`, `vsphere`, `fusion`, `aix`, `vcloud` or `vagrant`
100
+ * additional settings may be required depending on the selected hypervisor (ie, template, box, box_url, etc). Check the documentation below for your hypervisor for details
101
+ * snapshot
102
+ * the name of the snapshot to revert to before testing
103
+ * roles
104
+ * the 'job' of this host, an array of `master`, `agent`, `dashboard`, `database`, `default` or any user-defined string
105
+ * pe_dir
106
+ * the directory where PE builds are located, may be local directory or a URL
107
+ * pe_ver
108
+ * the version number of PE to install
109
+
110
+
111
+ ## Supported Platforms ##
112
+ Beaker depends upon each host in the configuration file having a platform type that is correctly formatted and supported. The platform is used to determine how various operations are carried out internally (such as installing packages using the correct package manager for the given operating system).
113
+
114
+ The platform's format is `/^OSFAMILY-VERSION-ARCH.*$/` where `OSFAMILY` is one of:
115
+
116
+ * centos
117
+ * fedora
118
+ * debian
119
+ * oracle
120
+ * redhat
121
+ * scientific
122
+ * sles
123
+ * ubuntu
124
+ * windows
125
+ * solaris
126
+ * aix
127
+ * el
128
+
129
+ `VERSION`'s format is not enforced, but should reflect the `OSFAMILY` selected (ie, ubuntu-1204-i386-master, scientific-6-i386-agent, etc). `ARCH`'s format is also not enforced, but should be appropriate to the `OSFAMILY` selected (ie, ubuntu-1204-i386-master, sles-11-x86_64-master, debian-7-amd64-master, etc).
85
130
 
86
131
  # Provisioning #
87
132
  Systest has built in capabilites for managing VMs and provisioning SUTs:
@@ -251,6 +296,14 @@ The vm is identified by `box` or `box_url` in the config file. No snapshot name
251
296
  nfs_server: none
252
297
  consoleport: 443
253
298
 
299
+ VagrantFiles are created per host configuration file. They can be found in the `.vagrant/beaker_vagrant_files` directory of the current working directory in a subdirectory named after the host configuration file.
300
+
301
+ > beaker --hosts sample.cfg
302
+ > cd .vagrant/beaker_vagrant_files; ls
303
+ sample.cfg
304
+ > cd sample.cfg; ls
305
+ VagrantFile
306
+
254
307
  # Putting it all together #
255
308
 
256
309
  ## Running FOSS tests ##
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "beaker"
5
- s.version = '1.0.1'
5
+ s.version = '1.1.0'
6
6
  s.authors = ["Puppetlabs"]
7
7
  s.email = ["delivery@puppetlabs.com"]
8
8
  s.homepage = "https://github.com/puppetlabs/beaker"
@@ -212,6 +212,35 @@ module Beaker
212
212
  host.install_package package_name
213
213
  end
214
214
 
215
+ # Upgrade a package on a host. The package must already be installed
216
+ #
217
+ # @param [Host] host A host object
218
+ # @param [String] package_name Name of the package to install
219
+ #
220
+ # @return [Result] An object representing the outcome of *upgrade command*.
221
+ def upgrade_package host, package_name
222
+ host.upgrade_package package_name
223
+ end
224
+
225
+ # Deploy packaging configurations generated by
226
+ # https://github.com/puppetlabs/packaging to a host.
227
+ #
228
+ # @note To ensure the repo configs are available for deployment,
229
+ # you should run `rake pl:jenkins:deb_repo_configs` and
230
+ # `rake pl:jenkins:rpm_repo_configs` on your project checkout
231
+ #
232
+ # @param [Host] host
233
+ # @param [String] path The path to the generated repository config
234
+ # files. ex: /myproject/pkg/repo_configs
235
+ # @param [String] name A human-readable name for the repository
236
+ # @param [String[ version The version of the project, as used by the
237
+ # packaging tools. This can be determined with
238
+ # `rake pl:print_build_params` from the packaging
239
+ # repo.
240
+ def deploy_package_repo host, path, name, version
241
+ host.deploy_package_repo path, name, version
242
+ end
243
+
215
244
  # Create a remote file out of a string
216
245
  # @note This method uses Tempfile in Ruby's STDLIB as well as {#scp_to}.
217
246
  #
@@ -51,6 +51,12 @@ module Beaker
51
51
  # configurations we have for many of our products
52
52
  type = is_pe? ? :pe : :foss
53
53
  @defaults = merge_defaults_for_type @options, type
54
+ pkg_initialize
55
+ end
56
+
57
+ def pkg_initialize
58
+ # This method should be overridden by platform-specific code to
59
+ # handle whatever packaging-related initialization is necessary.
54
60
  end
55
61
 
56
62
  def merge_defaults_for_type options, type
@@ -1,6 +1,12 @@
1
1
  module Unix::Pkg
2
2
  include Beaker::CommandFactory
3
3
 
4
+ # This method overrides {Host::pkg_initialize} to provide
5
+ # unix-specific package management setup
6
+ def pkg_initialize
7
+ @apt_needs_update = true
8
+ end
9
+
4
10
  def check_for_package(name)
5
11
  result = exec(Beaker::Command.new("which #{name}"), :acceptable_exit_codes => (0...127))
6
12
  case self['platform']
@@ -11,6 +17,17 @@ module Unix::Pkg
11
17
  end
12
18
  end
13
19
 
20
+ # If apt has not been updated since the last repo deployment it is
21
+ # updated. Otherwise this is a noop
22
+ def update_apt_if_needed
23
+ if self['platform'] =~ /debian|ubuntu/
24
+ if @apt_needs_update
25
+ execute("apt-get update")
26
+ @apt_needs_update = false
27
+ end
28
+ end
29
+ end
30
+
14
31
  def install_package(name, cmdline_args = '')
15
32
  case self['platform']
16
33
  when /sles-/
@@ -20,7 +37,7 @@ module Unix::Pkg
20
37
  when /fedora|centos|el-/
21
38
  execute("yum -y #{cmdline_args} install #{name}")
22
39
  when /ubuntu|debian/
23
- execute("apt-get update")
40
+ update_apt_if_needed
24
41
  execute("apt-get install #{cmdline_args} -y #{name}")
25
42
  when /solaris-11/
26
43
  execute("pkg #{cmdline_args} install #{name}")
@@ -49,4 +66,111 @@ module Unix::Pkg
49
66
  raise "Package #{name} cannot be installed on #{self}"
50
67
  end
51
68
  end
69
+
70
+ # Upgrade an installed package to the latest available version
71
+ #
72
+ # @param [String] name The name of the package to update
73
+ # @param [String] cmdline_args Additional command line arguments for
74
+ # the package manager
75
+ def upgrade_package(name, cmdline_args = '')
76
+ case self['platform']
77
+ when /sles-/
78
+ execute("zypper --non-interactive --no-gpg-checks up #{name}")
79
+ when /el-4/
80
+ @logger.debug("Package upgrade is not supported on rhel4")
81
+ when /fedora|centos|el-/
82
+ execute("yum -y #{cmdline_args} update #{name}")
83
+ when /ubuntu|debian/
84
+ update_apt_if_needed
85
+ execute("apt-get install -o Dpkg::Options::='--force-confold' #{cmdline_args} -y --force-yes #{name}")
86
+ when /solaris-11/
87
+ execute("pkg #{cmdline_args} update #{name}")
88
+ when /solaris-10/
89
+ execute("pkgutil -u -y #{cmdline_args} ${name}")
90
+ else
91
+ raise "Package #{name} cannot be upgraded on #{self}"
92
+ end
93
+ end
94
+
95
+ # Debian repositories contain packages for all architectures, so we
96
+ # need to map to an architecturless name for each platform
97
+ DEBIAN_PLATFORM_CODENAMES = {
98
+ 'debian-6-amd64' => 'squeeze',
99
+ 'debian-6-i386' => 'squeeze',
100
+ 'debian-7-amd64' => 'wheezy',
101
+ 'debian-7-i386' => 'wheezy',
102
+ 'ubuntu-10.04-amd64' => 'lucid',
103
+ 'ubuntu-10.04-i386' => 'lucid',
104
+ 'ubuntu-12.04-amd64' => 'precise',
105
+ 'ubuntu-12.04-i386' => 'precise',
106
+ }
107
+
108
+ # Deploy apt configuration generated by the packaging tooling
109
+ #
110
+ # @note Due to the debian use of codenames in repos, the
111
+ # DEBIAN_PLATFORM_CODENAMES map must be kept up-to-date as
112
+ # support for new versions is added.
113
+ #
114
+ # @note See {Beaker::DSL::Helpers::deploy_package_repo} for info on
115
+ # params
116
+ def deploy_apt_repo(path, name, version)
117
+ codename = DEBIAN_PLATFORM_CODENAMES[self['platform']]
118
+ if codename.nil?
119
+ @logger.warning "Could not determine codename for debian platform #{self['platform']}. Skipping deployment of repo #{name}"
120
+ return
121
+ end
122
+
123
+ repo_file = "#{path}/deb/pl-#{name}-#{version}-#{codename}.list"
124
+ do_scp_to repo_file, "/etc/apt/sources.list.d/#{name}.list", {}
125
+ @apt_needs_update = true
126
+ end
127
+
128
+ # Deploy yum configuration generated by the packaging tooling
129
+ #
130
+ # @note See {Beaker::DSL::Helpers::deploy_package_repo} for info on
131
+ # params
132
+ def deploy_yum_repo(path, name, version)
133
+ repo_file = "#{path}/rpm/pl-#{name}-#{version}-repos-pe-#{self['platform']}.repo"
134
+ do_scp_to repo_file, "/etc/yum.repos.d/#{name}.repo", {}
135
+ end
136
+
137
+ # Deploy zypper repo configuration generated by the packaging tooling
138
+ #
139
+ # @note See {Beaker::DSL::Helpers::deploy_package_repo} for info on
140
+ # params
141
+ def deploy_zyp_repo(path, name, version)
142
+ repo_file = "#{path}/rpm/pl-#{name}-#{version}-repos-pe-#{self['platform']}.repo"
143
+ repo = IniFile.load(repo_file)
144
+ repo_name = repo.sections[0]
145
+ repo_url = repo[repo_name]["baseurl"]
146
+ execute("zypper ar -t YUM #{repo_url} #{repo_name}")
147
+ end
148
+
149
+ # Deploy configuration generated by the packaging tooling to this host.
150
+ #
151
+ # This method calls one of {deploy_apt_repo}, {deploy_yum_repo}, or
152
+ # {deploy_zyp_repo} depending on the platform of this Host.
153
+ #
154
+ # @note See {Beaker::DSL::Helpers::deploy_package_repo} for info on
155
+ # params
156
+ def deploy_package_repo(path, name, version)
157
+ if not File.exists? path
158
+ @logger.warning "Was asked to deploy package repository from #{path}, but it doesn't exist!"
159
+ return
160
+ end
161
+
162
+ case self['platform']
163
+ when /el-4/
164
+ @logger.debug("Package repo deploy is not supported on rhel4")
165
+ when /fedora|centos|el-/
166
+ deploy_yum_repo(path, name, version)
167
+ when /ubuntu|debian/
168
+ deploy_apt_repo(path, name, version)
169
+ when /sles/
170
+ deploy_zyp_repo(path, name, version)
171
+ else
172
+ # solaris, windows
173
+ raise "Package repo cannot be deployed on #{self}; the platform is not supported"
174
+ end
175
+ end
52
176
  end
@@ -59,17 +59,17 @@ module Beaker
59
59
  end
60
60
  end
61
61
 
62
- # Attempt to start the fleet, we wrap it with some error handling that deals
63
- # with generic Fog errors and retrying in case these errors are transient.
62
+ # Attempt to start the fleet, we wrap it with some error handling that
63
+ # deals with generic Fog errors and retrying in case these errors are
64
+ # transient.
64
65
  fleet_retries = 0
65
66
  begin
66
67
  fleet.start
67
- rescue Fog::Errors::Error => ex
68
+ rescue Fog::Errors::Error, SystemCallError => ex
68
69
  fleet_retries += 1
69
70
  if fleet_retries <= 3
70
71
  sleep_time = rand(10) + 10
71
- @logger.notify("Calling fleet.destroy, sleeping #{sleep_time} seconds and retrying fleet.start due to Fog::Errors::Error (#{
72
- ex.message}), retry attempt #{fleet_retries}.")
72
+ @logger.notify("Calling fleet.destroy, sleeping #{sleep_time} seconds and retrying fleet.start due to exception #{ex.class.to_s} (#{ex.message}), retry attempt #{fleet_retries}.")
73
73
  begin
74
74
  timeout(30) do
75
75
  fleet.destroy
@@ -88,7 +88,7 @@ module Beaker
88
88
  @logger = options[:logger]
89
89
  @temp_files = []
90
90
  @vagrant_hosts = vagrant_hosts
91
- @vagrant_path = File.expand_path(File.join(File.basename(__FILE__), '..', 'vagrant_files', File.basename(options[:hosts_file])))
91
+ @vagrant_path = File.expand_path(File.join(File.basename(__FILE__), '..', '.vagrant', 'beaker_vagrant_files', File.basename(options[:hosts_file])))
92
92
  FileUtils.mkdir_p(@vagrant_path)
93
93
  @vagrant_file = File.expand_path(File.join(@vagrant_path, "Vagrantfile"))
94
94
 
@@ -11,6 +11,8 @@ module Beaker
11
11
  #These options expand out into an array of .rb files
12
12
  RB_FILE_OPTS = [:tests, :pre_suite, :post_suite]
13
13
 
14
+ PLATFORMS = /^(centos|fedora|debian|oracle|redhat|scientific|sles|ubuntu|windows|solaris|aix|el)\-.+\-.+$/
15
+
14
16
  PARSE_ERROR = if RUBY_VERSION > '1.8.7'; then Psych::SyntaxError; else ArgumentError; end
15
17
 
16
18
  #The OptionsHash of all parsed options
@@ -186,6 +188,7 @@ module Beaker
186
188
  #Validate all merged options values for correctness
187
189
  #
188
190
  #Currently checks:
191
+ # - each host has a valid platform
189
192
  # - if a keyfile is provided then use it
190
193
  # - paths provided to --test, --pre-suite, --post-suite provided lists of .rb files for testing
191
194
  # - --type is one of 'pe' or 'git'
@@ -199,6 +202,16 @@ module Beaker
199
202
  #@raise [ArgumentError] Raise if argument/options values are invalid
200
203
  def normalize_args
201
204
 
205
+ @options['HOSTS'].each_key do |name|
206
+ if not @options['HOSTS'][name]['platform']
207
+ parser_error "Host #{name} does not have a platform specified"
208
+ else
209
+ if not @options['HOSTS'][name]['platform'] =~ PLATFORMS
210
+ parser_error "Host #{name} is on unsupported platform #{@options['HOSTS'][name]['platform']}"
211
+ end
212
+ end
213
+ end
214
+
202
215
  #use the keyfile if present
203
216
  if @options.has_key?(:keyfile)
204
217
  @options[:ssh][:keys] = [@options[:keyfile]]
@@ -8,6 +8,16 @@ module Beaker
8
8
  @hosts = make_hosts()
9
9
  end
10
10
 
11
+ it "stores the vagrant file in $WORKINGDIR/.vagrant/beaker_vagrant_files/sample.cfg" do
12
+ FakeFS.activate!
13
+ vagrant.stub( :randmac ).and_return( "0123456789" )
14
+ path = vagrant.instance_variable_get( :@vagrant_path )
15
+
16
+ expect( path ).to be === File.join(Dir.pwd, '.vagrant', 'beaker_vagrant_files', 'sample.cfg')
17
+
18
+ end
19
+
20
+
11
21
  it "can make a Vagranfile for a set of hosts" do
12
22
  FakeFS.activate!
13
23
  path = vagrant.instance_variable_get( :@vagrant_path )
@@ -4,11 +4,12 @@ module Beaker
4
4
  module Options
5
5
 
6
6
  describe Parser do
7
- let(:parser) { Parser.new }
8
- let(:opts_path) { File.join(File.expand_path(File.dirname(__FILE__)), "data", "opts.txt") }
9
- let(:hosts_path) { File.join(File.expand_path(File.dirname(__FILE__)), "data", "hosts.cfg") }
10
- let(:badyaml_path) { File.join(File.expand_path(File.dirname(__FILE__)), "data", "badyaml.cfg") }
11
- let(:home) {ENV['HOME']}
7
+ let(:parser) { Parser.new }
8
+ let(:opts_path) { File.join(File.expand_path(File.dirname(__FILE__)), "data", "opts.txt") }
9
+ let(:hosts_path) { File.join(File.expand_path(File.dirname(__FILE__)), "data", "hosts.cfg") }
10
+ let(:badyaml_path) { File.join(File.expand_path(File.dirname(__FILE__)), "data", "badyaml.cfg") }
11
+ let(:home) { ENV['HOME'] }
12
+ let(:platforms_regex) { Parser::PLATFORMS }
12
13
 
13
14
  it "supports usage function" do
14
15
  expect{parser.usage}.to_not raise_error
@@ -20,6 +21,26 @@ module Beaker
20
21
  expect(parser.repo).to be === "#{repo}"
21
22
  end
22
23
 
24
+ #read through the file of possible platform values, correctly identify the 50 invalid platform values
25
+ describe "recognizes valid platforms" do
26
+
27
+ it "accepts correctly formatted platform values" do
28
+ expect( 'oracle-version-arch' =~ platforms_regex ).to be === 0
29
+ end
30
+
31
+ it "rejects non-supported osfamilies" do
32
+ expect( 'amazon6-version-arch' =~ platforms_regex ).to be === nil
33
+ end
34
+
35
+ it "rejects platforms without version/arch" do
36
+ expect( 'ubuntu-5' =~ platforms_regex ).to be === nil
37
+ end
38
+
39
+ it "rejects platforms that do not have osfamily at start of string" do
40
+ expect( 'oel-r5-u6-x86-64' =~ platforms_regex ).to be === nil
41
+ end
42
+ end
43
+
23
44
  #test parse_install_options
24
45
  it "can transform --install PUPPET/3.1 into #{repo}/puppet.git#3.1" do
25
46
  opts = ["PUPPET/3.1"]
@@ -148,17 +169,17 @@ module Beaker
148
169
  end
149
170
 
150
171
  context "for pe" do
151
- it_should_behave_like(:a_platform_supporting_only_agents, 'solaris', 'pe')
152
- it_should_behave_like(:a_platform_supporting_only_agents, 'windows', 'pe')
153
- it_should_behave_like(:a_platform_supporting_only_agents, 'el-4', 'pe')
172
+ it_should_behave_like(:a_platform_supporting_only_agents, 'solaris-version-arch', 'pe')
173
+ it_should_behave_like(:a_platform_supporting_only_agents, 'windows-version-arch', 'pe')
174
+ it_should_behave_like(:a_platform_supporting_only_agents, 'el-4-arch', 'pe')
154
175
  end
155
176
 
156
177
  context "for foss" do
157
- it_should_behave_like(:a_platform_supporting_only_agents, 'windows', 'git')
158
- it_should_behave_like(:a_platform_supporting_only_agents, 'el-4', 'git')
178
+ it_should_behave_like(:a_platform_supporting_only_agents, 'windows-version-arch', 'git')
179
+ it_should_behave_like(:a_platform_supporting_only_agents, 'el-4-arch', 'git')
159
180
 
160
181
  it "allows master role for solaris" do
161
- hosts_file = fake_hosts_file_for_platform(hosts, 'solaris')
182
+ hosts_file = fake_hosts_file_for_platform(hosts, 'solaris-version-arch')
162
183
  args = ["--type", "git", "--hosts", hosts_file]
163
184
  options_hash = parser.parse_args(args)
164
185
  expect(options_hash[:HOSTS][:master][:platform]).to match(/solaris/)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beaker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppetlabs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-26 00:00:00.000000000 Z
11
+ date: 2013-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec