onceover 3.8.0 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 760bc0e986513a337cfe07a8808d5aca8cae1675
4
- data.tar.gz: 7ed6e0c9d5278aef45ddc95f8e136793ff5a1236
3
+ metadata.gz: a37e753c95878c5de3f89a71d73e97b835e3ee54
4
+ data.tar.gz: 5a71d30c65ef86e645110719ef752ad6306c99bd
5
5
  SHA512:
6
- metadata.gz: 88ae6311f20abb1a997cf68e547de5a7d0b62bac25ac07152f035fcb39061e7f31a2fbee1b998f0f1f972429a1765c89af1508a1fa890854b2b49c53b9fc2548
7
- data.tar.gz: 3064ffc747c54d87125feefafb5cb42b031278ad9dd94738c5f0ea750039e97904dc2d7c3df2dee357f338270106badbccf499d5b5faf25c75e1c67a9c892539
6
+ metadata.gz: 61c0d522ccd4864f4bb224a6a60560f8c3852eb2037472d727b73b768132665bf137277248e59bac088ddedcb3eac421af30598e8830db619df9473ee3e69c5d
7
+ data.tar.gz: 56b657a2e74bb3344cb88785024afd4e977d74a04dbd1690c33e497157a2fe6c993b4b720e8c01c1347116e8e8d7e20856157bc9c9c9481241428c09bd4af697
data/.travis.yml CHANGED
@@ -9,12 +9,6 @@ script: bundle exec rake full_tests
9
9
  bundler_args: --path vendor/bundle
10
10
 
11
11
  rvm:
12
- - 2.1.6
13
- - 2.1.7
14
- - 2.1.8
15
- - 2.1.9
16
- - 2.2.7
17
- - 2.3.4
18
- - 2.4.0
19
- - 2.4.1
20
- - 2.4.2
12
+ - 2.3.8
13
+ - 2.4.4
14
+ - 2.5.3
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  *The gateway drug to automated infrastructure testing with Puppet*
4
4
 
5
- Onceover is a tool to automatically run basic tests on an entire Puppet controlrepo. It includes automatic parsing the `Puppetfile`, `environment.conf` and others in order to run both basic compilation tests and also full acceptance tests!
5
+ Onceover is a tool to automatically run basic tests on an entire Puppet controlrepo. It includes automatic parsing of the `Puppetfile`, `environment.conf` and others in order to run stop silly mistakes ever reaching your Puppet Master!
6
6
 
7
7
  ## Table of Contents
8
8
 
@@ -12,11 +12,9 @@ Onceover is a tool to automatically run basic tests on an entire Puppet controlr
12
12
  - [Config files](#config-files)
13
13
  - [onceover.yaml](#onceoveryaml)
14
14
  - [factsets](#factsets)
15
- - [nodesets](#nodesets)
16
15
  - [Hiera Data](#hiera-data)
17
16
  - [Spec testing](#spec-testing)
18
17
  - [Adding your own spec tests](#adding-your-own-spec-tests)
19
- - [Acceptance testing](#acceptance-testing)
20
18
  - [Using Workarounds](#using-workarounds)
21
19
  - [Extra tooling](#extra-tooling)
22
20
  - [Plugins](#plugins)
@@ -66,7 +64,7 @@ Run your spec tests!
66
64
 
67
65
  ## Overview
68
66
 
69
- This gem provides a toolset for testing Puppet Controlrepos (Repos used with r10k). The main purpose of this project is to provide a set of tools to help smooth out the process of setting up and running both spec and acceptance tests for a controlrepo. Due to the fact that controlrepos are fairly standardised in nature it seemed ridiculous that you would need to set up the same testing framework that we would normally use within a module for a controlrepo. This is because at this level we are normally just running very basic tests that cover a lot of code. It would also mean that we would need to essentially duplicated our `Puppetfile` into a `.fixtures.yml` file, along with a few other things.
67
+ This gem provides a toolset for testing Puppet Controlrepos (Repos used with r10k). The main purpose of this project is to provide a set of tools to help smooth out the process of setting up and running rspec-puppet tests for a controlrepo. Due to the fact that controlrepos are fairly standardised in nature it seemed ridiculous that you would need to set up the same testing framework that we would normally use within a module for a controlrepo. This is because at this level we are normally just running very basic tests that cover a lot of code. It would also mean that we would need to essentially duplicated our `Puppetfile` into a `.fixtures.yml` file, along with a few other things.
70
68
 
71
69
  This toolset requires some config before it can be used so definitely read that section before getting started.
72
70
 
@@ -82,17 +80,15 @@ This project uses one main config file to determine what classes we should be te
82
80
 
83
81
  If we are doing spec testing we need sets of facts to compile the puppet code against, these are stored in [factsets](#factsets). (A few are provided out of the box for you)
84
82
 
85
- If we are doing acceptance testing then we need information about how to spin up VMs to do the testing on, these are configured in [nodesets](#nodesets). (Once again these are auto-generated with `onceover init`)
86
-
87
83
  ### onceover.yaml
88
84
 
89
85
  `spec/onceover.yaml` _(override with environment variable: `ONCEOVER_YAML`)_
90
86
 
91
- Hopefully this config file will be fairly self explanatory once you see it, but basically this is the place where we define what classes we want to test and the [factsets](#factsets)/[nodesets](#nodesets) that we want to test them against. The config file must contain the following sections:
87
+ Hopefully this config file will be fairly self explanatory once you see it, but basically this is the place where we define what classes we want to test and the [factsets](#factsets) that we want to test them against. The config file must contain the following sections:
92
88
 
93
89
  **classes:** A list (array) of classes that we want to test, usually this would be your roles, possibly profiles if you want. (If you don't know what roles and profiles are please [READ THIS](http://garylarizza.com/blog/2014/02/17/puppet-workflow-part-2/)). To make life easier you can also specify one or many **regular expressions** in this section. A good one to start with would be `/^role::/`. Regular expressions are just strings that start and end with a forward slash.
94
90
 
95
- **nodes:** The nodes that we want to test against. The nodes that we list here map directly to either a [factset](#factsets) or a [nodeset](#nodesets) depending on weather we are running spec or acceptance tests respectively.
91
+ **nodes:** The nodes that we want to test against. The nodes that we list here map directly to a [factset](#factsets).
96
92
 
97
93
  **node_groups:** The `node_groups` section is just for saving us some typing. Here we can set up groups of nodes which we can then refer to in our test matrix. We can create groups by simply specifying an array of servers to be in the group, or we can use the subtractive *include/exclude* syntax. The names used for the actual `class_groups` and `node_groups` must be unique.
98
94
 
@@ -103,7 +99,7 @@ Hopefully this config file will be fairly self explanatory once you see it, but
103
99
  ```yaml
104
100
  - {nodes_to_test}: # The name of a node or node group
105
101
  classes: '{classes_to_test}' # the name of a class or
106
- tests: '{all_tests|acceptance|spec}' # One of the three
102
+ tests: '{all_tests|acceptance|spec}' # acceptance deprecated/broken, set to spec
107
103
  {valid_option}: {value} # Check the doco for available options
108
104
  ```
109
105
 
@@ -190,10 +186,10 @@ test_matrix:
190
186
  classes: 'non_windows_roles'
191
187
  - ubuntu_servers:
192
188
  classes: 'all_classes'
193
- tests: 'all_tests'
189
+ tests: 'spec'
194
190
  - centos_severs:
195
191
  classes: 'roles::frontend_webserver'
196
- tests: 'acceptance'
192
+ tests: 'spec'
197
193
  runs_before_idempotency: 2
198
194
  tags:
199
195
  - 'frontend'
@@ -224,14 +220,6 @@ It's important to note that in order to reference a group using the *include/exc
224
220
 
225
221
  #### Optional test parameters
226
222
 
227
- **check_idempotency** *Default: true*
228
-
229
- Weather or not to check that puppet will be idempotent (Acceptance testing only)
230
-
231
- **runs_before_idempotency** *Default: 1*
232
-
233
- The number of runs to try before checking that it is idempotent. Required for some things that require restarts of the server or restarts of puppet. (Acceptance testing only)
234
-
235
223
  **tags** *Default: nil*
236
224
 
237
225
  One or many tags that tests in this group should be tagged with. This allows you to run only certain tests using the `--tags` command line parameter. **NOTE:** Custom spec tests will always be run as they are not subject to tags
@@ -258,7 +246,7 @@ Would map to a node named `server2008r2` in `onceover.yaml`
258
246
 
259
247
  #### Trusted Facts
260
248
 
261
- You can add trusted facts to the nodesets by creating a new section called trusted:
249
+ You can add trusted facts to the factsets by creating a new section called trusted:
262
250
 
263
251
  ```
264
252
  {
@@ -276,69 +264,6 @@ You can add trusted facts to the nodesets by creating a new section called trust
276
264
 
277
265
  Notice that the `extensions` part is implied. The first fact in that example translates to `$trusted['extensions']['pp_role']` in Puppet code.
278
266
 
279
- ### nodesets
280
-
281
- `spec/acceptance/nodesets/onceover-nodes.yml`
282
-
283
- Nodesets are used when running acceptance tests. They instruct the onceover gem how to spin up virtual machines to run the code on. Actually, that's a lie... What's really happening with nodesets is that we are using [Beaker](https://github.com/puppetlabs/beaker) to spin up the machines and then a combination of Beaker and RSpec to test them. But you don't need to worry about that too much. Due to the fact that we are using beaker to do the heavy lifting here the nodeset files follow the same format they would for normal Beaker tests, which at the time of writing supports the following hypervisors:
284
-
285
- - [VMWare Fusion](https://github.com/puppetlabs/beaker/blob/master/docs/VMWare-Fusion-Support.md)
286
- - [Amazon EC2](https://github.com/puppetlabs/beaker/blob/master/docs/EC2-Support.md)
287
- - [vSphere](https://github.com/puppetlabs/beaker/blob/master/docs/vSphere-Support.md)
288
- - [Vagrant](https://github.com/puppetlabs/beaker/blob/master/docs/Vagrant-Support.md)
289
- - [Google Compute Engine](https://github.com/puppetlabs/beaker/blob/master/docs/Google-Compute-Engine-Support.md)
290
- - [Docker](https://github.com/puppetlabs/beaker/blob/master/docs/Docker-Support.md)
291
- - [Openstack](https://github.com/puppetlabs/beaker/blob/master/docs/Openstack-Support.md)
292
- - [Solaris](https://github.com/puppetlabs/beaker/blob/master/docs/Solaris-Support.md)
293
-
294
- Before we configure a hypervisor to spin up a node however, we have to make sure that it can clone from a machine which is ready. The onceover gem **requires it's VMs to have puppet pre-installed.** It doesn't matter what version of puppet, as long as it is on the PATH and the `type` setting is configured correctly i.e.
295
-
296
- ```yaml
297
- type: AIO # For machines that have the all-in-one agent installed (>=4.0 or >=2015.2)
298
- # OR
299
- type: pe # For puppet enterprise agents <2015.2
300
- # OR
301
- type: foss # For open source puppet <4.0
302
- ```
303
-
304
- Here is an example of a nodeset file that you can use yourselves. It uses freely available Vagrant boxes from Puppet and Virtualbox as the Vagrant provider. (`onceover init` will generate most of this for you)
305
-
306
- ```yaml
307
- HOSTS:
308
- centos6a:
309
- roles:
310
- - agent
311
- type: aio
312
- platform: el-6-64
313
- box: puppetlabs/centos-6.6-64-puppet
314
- box_url: https://atlas.hashicorp.com/puppetlabs/boxes/centos-6.6-64-puppet
315
- hypervisor: vagrant_virtualbox
316
- centos7b:
317
- roles:
318
- - agent
319
- type: aio
320
- platform: el-7-64
321
- box: puppetlabs/centos-7.0-64-puppet
322
- box_url: https://atlas.hashicorp.com/puppetlabs/boxes/centos-7.0-64-puppet
323
- hypervisor: vagrant_virtualbox
324
- ubuntu1204:
325
- roles:
326
- - agent
327
- type: aio
328
- platform: ubuntu-12.04-32
329
- box: puppetlabs/ubuntu-12.04-32-puppet
330
- box_url: https://atlas.hashicorp.com/puppetlabs/boxes/ubuntu-12.04-32-puppet
331
- hypervisor: vagrant_virtualbox
332
- debian78:
333
- roles:
334
- - agent
335
- type: aio
336
- platform: debian-7.8-64
337
- box: puppetlabs/debian-7.8-64-puppet
338
- box_url: https://atlas.hashicorp.com/puppetlabs/boxes/debian-7.8-64-puppet
339
- hypervisor: vagrant_virtualbox
340
- ```
341
-
342
267
  ### Hiera Data
343
268
 
344
269
  If you have hiera data inside your controlrepo (or somewhere else) Onceover can be configured to use it. It is however worth noting the the `hiera.yaml` file that you currently use may not be applicable for testing right away. For example; if you are using `hiera-eyaml` I recommend creating a `hiera.yaml` purely for testing that simply uses the `yaml` backend, meaning that you don't need to provide the private keys to the testing machines.
@@ -405,26 +330,6 @@ If you want to see Puppet's output, you can set the `SHOW_PUPPET_OUTPUT` environ
405
330
 
406
331
  `SHOW_PUPPET_OUTPUT=true onceover run spec`
407
332
 
408
- ## Acceptance testing
409
-
410
- Acceptance testing works in much the same way as spec testing except that it requires a nodeset file along with `onceover.yaml`
411
-
412
- To run the tests:
413
-
414
- `onceover run acceptance`
415
-
416
- This will do the following things:
417
-
418
- 1. Create a temporary directory under `.onceover`
419
- 2. Clone all repos in the Puppetfile into the temporary directory
420
- 3. Generate tests that use RSpec and Beaker
421
- 4. Run the tests, each test consists of:
422
- - Spin up the VM
423
- - Copy over the code
424
- - Run puppet and catch any errors
425
- - Run puppet again to catch anything that might not be idempotent
426
- - Destroy the VM
427
-
428
333
  ## Using workarounds
429
334
 
430
335
  There may be situations where you cannot test everything that is in your puppet code, some common reasons for this include:
@@ -480,29 +385,9 @@ or
480
385
  }
481
386
  ```
482
387
 
483
- However this is going to pose an issue when we get to acceptance testing. Due to the fact that acceptance tests actually run the code, not just tries to compile a catalog, it will not be able to find the 'pe-pupetserver' service and will fail. One way to get around this is to use some of the optional parameters to the service resource e.g.
484
-
485
- ```puppet
486
- # We are not going to actually have this service anywhere on our servers but
487
- # our code needs to refresh it. This is to trick puppet into doing nothing
488
- service { 'pe-puppetserver':
489
- ensure => 'running',
490
- enable => false,
491
- hasrestart => false, # Force Puppet to use start and stop to restart
492
- start => 'echo "Start"', # This will always exit 0
493
- stop => 'echo "Stop"', # This will also always exit 0
494
- hasstatus => false, # Force puppet to use our command for status
495
- status => 'echo "Status"', # This will always exit 0 and therefore Puppet will think the service is running
496
- provider => 'base',
497
- }
498
- ```
499
-
500
- Here we are specifying custom commands to run for starting, stopping and checking the status of a service. We know what the exit codes of these commands are going to be so we know what puppet will think the service is doing because we have [read the documentation](https://docs.puppetlabs.com/references/latest/type.html#service-attributes). If there are things other than services you need to check then I would recommend checking the documentation to see if you can mock things like we have here. Alternatively you might need to create specific VM images that are pre-prepared.
501
388
 
502
389
  [Resource collectors](https://docs.puppetlabs.com/puppet/latest/reference/lang_resources_advanced.html#amending-attributes-with-a-collector) are likely to come in handy here too. They allow you to override values of resources that match given criteria. This way we can override things for the sake of testing without having to change the code.
503
390
 
504
- **NOTE:** If you need to run some pre_conditions during acceptance tests but not spec tests or vice versa you can check the status of the `$controlrepo_accpetance` variable. It will be `true` when run as an acceptance test and `undef` otherwise. If you want to limit pre_conditions to only certain nodes just use conditional logic based on facts like you normally would.
505
-
506
391
  **NOTE:** If you want to access the class or factset that onceover is running against just use the `$onceover_class` and `$onceover_node` variables respectively.
507
392
 
508
393
  ## Extra Tooling
@@ -0,0 +1,103 @@
1
+ {
2
+ "name": "vagrant-hb9g3rd.lan.asio",
3
+ "values": {
4
+ "puppetversion": "6.0.2",
5
+ "puppet_inventory_metadata": {
6
+ "packages": {
7
+ "collection_enabled": false,
8
+ "last_collection_time": "0.0s"
9
+ }
10
+ },
11
+ "package_provider": "windows",
12
+ "pe_concat_basedir": "C:/ProgramData/PuppetLabs/puppet/cache/pe_concat",
13
+ "is_pe": false,
14
+ "platform_symlink_writable": false,
15
+ "puppet_files_dir_present": false,
16
+ "puppet_vardir": "C:/ProgramData/PuppetLabs/puppet/cache",
17
+ "puppet_environmentpath": "C:/ProgramData/PuppetLabs/code/environments",
18
+ "puppet_server": "pe-puppet.localdomain",
19
+ "service_provider": "windows",
20
+ "staging_http_get": "curl",
21
+ "common_appdata": "C:\\ProgramData",
22
+ "architecture": "x64",
23
+ "kernel": "windows",
24
+ "virtual": "vmware",
25
+ "is_virtual": true,
26
+ "hardwaremodel": "x64",
27
+ "operatingsystem": "windows",
28
+ "os": {
29
+ "name": "windows",
30
+ "family": "windows",
31
+ "release": {
32
+ "major": "10",
33
+ "full": "10"
34
+ }
35
+ },
36
+ "facterversion": "2.5.1",
37
+ "fqdn": "VAGRANT-HB9G3RD",
38
+ "hostname": "VAGRANT-HB9G3RD",
39
+ "id": "vagrant-hb9g3rd\\vagrant",
40
+ "interfaces": "Ethernet0_2",
41
+ "ipaddress_ethernet0_2": "192.168.43.174",
42
+ "ipaddress6_ethernet0_2": "fd72:b3ab:b8dd:0:f563:fac2:928c:6aa",
43
+ "macaddress_ethernet0_2": "00:0C:29:A3:53:54",
44
+ "netmask_ethernet0_2": "255.255.255.0",
45
+ "mtu_ethernet0_2": 0,
46
+ "ipaddress": "192.168.43.174",
47
+ "ipaddress6": "fd72:b3ab:b8dd:0:f563:fac2:928c:6aa",
48
+ "kernelmajversion": "10.0",
49
+ "kernelrelease": "10.0.17134",
50
+ "kernelversion": "10.0.17134",
51
+ "macaddress": "00:0C:29:A3:53:54",
52
+ "manufacturer": "Phoenix Technologies LTD",
53
+ "serialnumber": "VMware-56 4d 36 2e 2e a4 81 f9-0d 05 ae d0 e5 a3 53 54",
54
+ "productname": "VMware Virtual Platform",
55
+ "memorysize": "4.00 GB",
56
+ "memoryfree": "2.30 GB",
57
+ "memorysize_mb": "4095.49",
58
+ "memoryfree_mb": "2360.00",
59
+ "netmask": "255.255.255.0",
60
+ "network_ethernet0_2": "192.168.43.0",
61
+ "operatingsystemmajrelease": "10",
62
+ "operatingsystemrelease": "10",
63
+ "osfamily": "windows",
64
+ "path": "C:\\tools\\ruby24\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files (x86)\\vim\\vim80;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Puppet Labs\\Puppet\\bin;C:\\Users\\vagrant\\AppData\\Local\\Microsoft\\WindowsApps;",
65
+ "physicalprocessorcount": 4,
66
+ "processors": {
67
+ "models": [
68
+ "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
69
+ "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
70
+ "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
71
+ "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz"
72
+ ],
73
+ "count": 4,
74
+ "physicalcount": 4
75
+ },
76
+ "processor0": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
77
+ "processor1": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
78
+ "processor2": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
79
+ "processor3": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
80
+ "processorcount": 4,
81
+ "ps": "tasklist.exe",
82
+ "rubyplatform": "x64-mingw32",
83
+ "rubysitedir": "C:/tools/ruby24/lib/ruby/site_ruby/2.4.0",
84
+ "rubyversion": "2.4.3",
85
+ "system32": "C:\\Windows\\system32",
86
+ "system_uptime": {
87
+ "seconds": 1113359,
88
+ "hours": 309,
89
+ "days": 12,
90
+ "uptime": "12 days"
91
+ },
92
+ "timezone": "GMT Standard Time",
93
+ "uptime": "12 days",
94
+ "uptime_days": 12,
95
+ "uptime_hours": 309,
96
+ "uptime_seconds": 1113359,
97
+ "clientcert": "vagrant-hb9g3rd.lan.asio",
98
+ "clientversion": "6.0.2",
99
+ "clientnoop": false
100
+ },
101
+ "timestamp": "2018-12-10T21:43:07.468533000+00:00",
102
+ "expiration": "2018-12-10T22:13:07.468533000+00:00"
103
+ }
data/features/run.feature CHANGED
@@ -12,6 +12,11 @@ Feature: Run rspec and acceptance test suites
12
12
  When I run onceover command "run spec"
13
13
  Then I should not see any errors
14
14
 
15
+ Scenario: Using regexes to define tests
16
+ Given initialized control repo "caching"
17
+ When I run onceover command "run spec"
18
+ Then I should see message pattern "apache::params"
19
+
15
20
  Scenario: Run spec tests with misspelled module in Puppetfile
16
21
  Given initialized control repo "basic"
17
22
  And in Puppetfile is misspelled module's name
@@ -51,9 +51,13 @@ Then(/^I should see error with message pattern "([^"]*)"$/) do |err_msg_regexp|
51
51
  expect(@cmd.output.match err_msg_regexp).to_not be nil
52
52
  end
53
53
 
54
- Then(/^I should see message pattern "([^"]*)"$/) do |err_msg_regexp|
55
- expect(@cmd.success?).to be true
56
- puts @cmd.output unless @cmd.output =~ Regexp.new(err_msg_regexp)
57
- expect(@cmd.output).to match(err_msg_regexp)
58
- puts @cmd.output.match(err_msg_regexp).to_s
54
+ Then(/^I should see message pattern "([^"]*)"$/) do |msg_regexp|
55
+ output_surround = 30
56
+ match = Regexp.new(msg_regexp).match(@cmd.output)
57
+ expect(@cmd.output).to match(msg_regexp)
58
+ if match
59
+ puts match.pre_match[-output_surround..-1] + match.to_s + match.post_match[0..output_surround]
60
+ else
61
+ puts @cmd.output
62
+ end
59
63
  end
@@ -4,6 +4,7 @@ require 'onceover/cli'
4
4
  require 'onceover/runner'
5
5
  require 'onceover/testconfig'
6
6
  require 'onceover/logger'
7
+ require 'onceover/deploy'
7
8
 
8
9
  class Onceover
9
10
  class CLI
@@ -43,6 +44,7 @@ This includes deploying using r10k and running all custom tests.
43
44
 
44
45
  run do |opts, args, cmd|
45
46
  repo = Onceover::Controlrepo.new(opts)
47
+ Onceover::Deploy.new.deploy_local(repo, opts)
46
48
  runner = Onceover::Runner.new(repo,Onceover::TestConfig.new(repo.onceover_yaml, opts), :spec)
47
49
  runner.prepare!
48
50
  runner.run_spec!
@@ -156,11 +156,17 @@ class Onceover
156
156
  end
157
157
 
158
158
  def classes
159
+ logger.debug('scanning for classes specified in onceover.yaml')
160
+
159
161
  # Get all of the possible places for puppet code and look for classes
160
162
  code_dirs = self.config['modulepath']
161
163
  # Remove interpolated references
162
164
  code_dirs.delete_if { |dir| dir[0] == '$'}
163
165
 
166
+ # Include all r10k-downloaded modules to support vendored and/or separate
167
+ # role and profile classes
168
+ code_dirs << "#{@tempdir}/#{@environmentpath}/production/modules"
169
+
164
170
  # Make sure that the paths are relative to the controlrepo root
165
171
  code_dirs.map! do |dir|
166
172
  File.expand_path(dir, @root)
@@ -0,0 +1,152 @@
1
+ # handle local deployments (run r10k in .onceover dir)
2
+ class Onceover
3
+ class Deploy
4
+ def deploy_local(repo = Onceover::Controlrepo.new, opts = {})
5
+ require 'onceover/controlrepo'
6
+ require 'pathname'
7
+
8
+ logger.debug 'Deploying locally (R10K)...'
9
+
10
+ skip_r10k = opts[:skip_r10k] || false
11
+ force = opts[:force] || false
12
+
13
+ if repo.tempdir == nil
14
+ repo.tempdir = Dir.mktmpdir('r10k')
15
+ else
16
+ logger.debug "Creating #{repo.tempdir}"
17
+ FileUtils.mkdir_p(repo.tempdir)
18
+ end
19
+
20
+ # We need to do the copy to a tempdir then move the tempdir to the
21
+ # destination, just in case we get a recursive copy
22
+ # TODO: Improve this to save I/O
23
+
24
+ # We might need to exclude some files
25
+ #
26
+ # if we are using bundler to install gems below the controlrepo
27
+ # we don't want two copies so exclude those
28
+ #
29
+ # If there are more situations like this we can add them to this array as
30
+ # full paths
31
+ excluded_dirs = []
32
+ excluded_dirs << Pathname.new("#{repo.root}/.onceover")
33
+ excluded_dirs << Pathname.new(ENV['GEM_HOME']) if ENV['GEM_HOME']
34
+
35
+ #
36
+ # A Local modules directory likely means that the user installed r10k folders into their local control repo
37
+ # This conflicts with the step where onceover installs r10k after copying the control repo to the temporary
38
+ # .onceover directory. The following skips copying the modules folder, to not later cause an error.
39
+ #
40
+ if File.directory?("#{repo.root}/modules")
41
+ logger.warn "Found modules directory in your controlrepo, skipping the copy of this directory. If you installed modules locally using r10k, this warning is normal, if you have created modules in a local modules directory, onceover does not support testing these files, please rename this directory to conform with Puppet best practices, as this folder will conflict with Puppet's native installation of modules."
42
+ end
43
+ excluded_dirs << Pathname.new("#{repo.root}/modules")
44
+
45
+ controlrepo_files = get_children_recursive(Pathname.new(repo.root))
46
+
47
+ # Exclude the files that should be skipped
48
+ controlrepo_files.delete_if do |path|
49
+ parents = [path]
50
+ path.ascend do |parent|
51
+ parents << parent
52
+ end
53
+ parents.any? { |x| excluded_dirs.include?(x) }
54
+ end
55
+
56
+ folders_to_copy = controlrepo_files.select { |x| x.directory? }
57
+ files_to_copy = controlrepo_files.select { |x| x.file? }
58
+
59
+ logger.debug "Creating temp dir as a staging directory for copying the controlrepo to #{repo.tempdir}"
60
+ temp_controlrepo = Dir.mktmpdir('controlrepo')
61
+
62
+ logger.debug "Creating directories under #{temp_controlrepo}"
63
+ FileUtils.mkdir_p(folders_to_copy.map { |folder| "#{temp_controlrepo}/#{(folder.relative_path_from(Pathname(repo.root))).to_s}"})
64
+
65
+ logger.debug "Copying files to #{temp_controlrepo}"
66
+ files_to_copy.each do |file|
67
+ FileUtils.cp(file,"#{temp_controlrepo}/#{(file.relative_path_from(Pathname(repo.root))).to_s}")
68
+ end
69
+
70
+ logger.debug "Writing manifest of copied controlrepo files"
71
+ require 'json'
72
+ # Create a manifest of all files that were in the original repo
73
+ manifest = controlrepo_files.map do |file|
74
+ # Make sure the paths are relative so they remain relevant when used later
75
+ file.relative_path_from(Pathname(repo.root)).to_s
76
+ end
77
+ # Write all but the first as this is the root and we don't care about that
78
+ File.write("#{temp_controlrepo}/.onceover_manifest.json",manifest[1..-1].to_json)
79
+
80
+ # When using puppetfile vs deploy with r10k, we want to respect the :control_branch
81
+ # located in the Puppetfile. To accomplish that, we use git and find the current
82
+ # branch name, then replace strings within the staged puppetfile, prior to copying.
83
+
84
+ logger.debug "Checking current working branch"
85
+ git_branch = `git rev-parse --abbrev-ref HEAD`.chomp
86
+
87
+ logger.debug "found #{git_branch} as current working branch"
88
+ puppetfile_contents = File.read("#{temp_controlrepo}/Puppetfile")
89
+
90
+ logger.debug "replacing :control_branch mentions in the Puppetfile with #{git_branch}"
91
+ new_puppetfile_contents = puppetfile_contents.gsub(/:control_branch/, "'#{git_branch}'")
92
+ File.write("#{temp_controlrepo}/Puppetfile", new_puppetfile_contents)
93
+
94
+ # Remove all files written by the laste onceover run, but not the ones
95
+ # added by r10k, because that's what we are trying to cache but we don't
96
+ # know what they are
97
+ old_manifest_path = "#{repo.tempdir}/#{repo.environmentpath}/production/.onceover_manifest.json"
98
+ if File.exist? old_manifest_path
99
+ logger.debug "Found manifest from previous run, parsing..."
100
+ old_manifest = JSON.parse(File.read(old_manifest_path))
101
+ logger.debug "Removing #{old_manifest.count} files"
102
+ old_manifest.reverse.each do |file|
103
+ FileUtils.rm_f(File.join("#{repo.tempdir}/#{repo.environmentpath}/production/",file))
104
+ end
105
+ end
106
+ FileUtils.mkdir_p("#{repo.tempdir}/#{repo.environmentpath}")
107
+
108
+ logger.debug "Copying #{temp_controlrepo} to #{repo.tempdir}/#{repo.environmentpath}/production"
109
+ FileUtils.cp_r("#{temp_controlrepo}/.", "#{repo.tempdir}/#{repo.environmentpath}/production")
110
+ FileUtils.rm_rf(temp_controlrepo)
111
+
112
+ # Pull the trigger! If it's not already been pulled
113
+ if repo.tempdir and not skip_r10k
114
+ if File.directory?(repo.tempdir)
115
+ # TODO: Change this to call out to r10k directly to do this
116
+ # Probably something like:
117
+ # R10K::Settings.global_settings.evaluate(with_overrides)
118
+ # R10K::Action::Deploy::Environment
119
+ prod_dir = "#{repo.tempdir}/#{repo.environmentpath}/production"
120
+ Dir.chdir(prod_dir) do
121
+ install_cmd = []
122
+ install_cmd << "r10k puppetfile install --verbose --color --puppetfile #{repo.puppetfile}"
123
+ install_cmd << "--force" if force
124
+ install_cmd = install_cmd.join(' ')
125
+ logger.debug "Running #{install_cmd} from #{prod_dir}"
126
+ system(install_cmd)
127
+ raise 'r10k could not install all required modules' unless $?.success?
128
+ end
129
+ else
130
+ raise "#{repo.tempdir} is not a directory"
131
+ end
132
+ end
133
+
134
+ # Return repo.tempdir for use
135
+ repo.tempdir
136
+ end
137
+
138
+ private
139
+
140
+ def get_children_recursive(pathname)
141
+ results = []
142
+ results << pathname
143
+ pathname.each_child do |child|
144
+ results << child
145
+ if child.directory?
146
+ results << get_children_recursive(child)
147
+ end
148
+ end
149
+ results.flatten
150
+ end
151
+ end
152
+ end
@@ -11,9 +11,6 @@ class Onceover
11
11
  end
12
12
 
13
13
  def prepare!
14
- # Deploy the control repo
15
- @config.deploy_local(@repo, {:skip_r10k => @config.skip_r10k})
16
-
17
14
  # Remove the entire spec directory to make sure we have
18
15
  # all the latest tests
19
16
  FileUtils.rm_rf("#{@repo.tempdir}/spec")
@@ -167,137 +167,6 @@ class Onceover
167
167
  puppetcode.join("\n")
168
168
  end
169
169
 
170
- def deploy_local(repo = Onceover::Controlrepo.new, opts = {})
171
- require 'onceover/controlrepo'
172
- require 'pathname'
173
-
174
- skip_r10k = opts[:skip_r10k] || false
175
-
176
- if repo.tempdir == nil
177
- repo.tempdir = Dir.mktmpdir('r10k')
178
- else
179
- logger.debug "Creating #{repo.tempdir}"
180
- FileUtils.mkdir_p(repo.tempdir)
181
- end
182
-
183
- # We need to do the copy to a tempdir then move the tempdir to the
184
- # destination, just in case we get a recursive copy
185
- # TODO: Improve this to save I/O
186
-
187
- # We might need to exclude some files
188
- #
189
- # if we are using bundler to install gems below the controlrepo
190
- # we don't want two copies so exclude those
191
- #
192
- # If there are more situations like this we can add them to this array as
193
- # full paths
194
- excluded_dirs = []
195
- excluded_dirs << Pathname.new("#{repo.root}/.onceover")
196
- excluded_dirs << Pathname.new(ENV['GEM_HOME']) if ENV['GEM_HOME']
197
-
198
- #
199
- # A Local modules directory likely means that the user installed r10k folders into their local control repo
200
- # This conflicts with the step where onceover installs r10k after copying the control repo to the temporary
201
- # .onceover directory. The following skips copying the modules folder, to not later cause an error.
202
- #
203
- if File.directory?("#{repo.root}/modules")
204
- logger.warn "Found modules directory in your controlrepo, skipping the copy of this directory. If you installed modules locally using r10k, this warning is normal, if you have created modules in a local modules directory, onceover does not support testing these files, please rename this directory to conform with Puppet best practices, as this folder will conflict with Puppet's native installation of modules."
205
- end
206
- excluded_dirs << Pathname.new("#{repo.root}/modules")
207
-
208
- controlrepo_files = get_children_recursive(Pathname.new(repo.root))
209
-
210
- # Exclude the files that should be skipped
211
- controlrepo_files.delete_if do |path|
212
- parents = [path]
213
- path.ascend do |parent|
214
- parents << parent
215
- end
216
- parents.any? { |x| excluded_dirs.include?(x) }
217
- end
218
-
219
- folders_to_copy = controlrepo_files.select { |x| x.directory? }
220
- files_to_copy = controlrepo_files.select { |x| x.file? }
221
-
222
- logger.debug "Creating temp dir as a staging directory for copying the controlrepo to #{repo.tempdir}"
223
- temp_controlrepo = Dir.mktmpdir('controlrepo')
224
-
225
- logger.debug "Creating directories under #{temp_controlrepo}"
226
- FileUtils.mkdir_p(folders_to_copy.map { |folder| "#{temp_controlrepo}/#{(folder.relative_path_from(Pathname(repo.root))).to_s}"})
227
-
228
- logger.debug "Copying files to #{temp_controlrepo}"
229
- files_to_copy.each do |file|
230
- FileUtils.cp(file,"#{temp_controlrepo}/#{(file.relative_path_from(Pathname(repo.root))).to_s}")
231
- end
232
-
233
- logger.debug "Writing manifest of copied controlrepo files"
234
- require 'json'
235
- # Create a manifest of all files that were in the original repo
236
- manifest = controlrepo_files.map do |file|
237
- # Make sure the paths are relative so they remain relevant when used later
238
- file.relative_path_from(Pathname(repo.root)).to_s
239
- end
240
- # Write all but the first as this is the root and we don't care about that
241
- File.write("#{temp_controlrepo}/.onceover_manifest.json",manifest[1..-1].to_json)
242
-
243
- # When using puppetfile vs deploy with r10k, we want to respect the :control_branch
244
- # located in the Puppetfile. To accomplish that, we use git and find the current
245
- # branch name, then replace strings within the staged puppetfile, prior to copying.
246
-
247
- logger.debug "Checking current working branch"
248
- git_branch = `git rev-parse --abbrev-ref HEAD`.chomp
249
-
250
- logger.debug "found #{git_branch} as current working branch"
251
- puppetfile_contents = File.read("#{temp_controlrepo}/Puppetfile")
252
-
253
- logger.debug "replacing :control_branch mentions in the Puppetfile with #{git_branch}"
254
- new_puppetfile_contents = puppetfile_contents.gsub(/:control_branch/, "'#{git_branch}'")
255
- File.write("#{temp_controlrepo}/Puppetfile", new_puppetfile_contents)
256
-
257
- # Remove all files written by the laste onceover run, but not the ones
258
- # added by r10k, because that's what we are trying to cache but we don't
259
- # know what they are
260
- old_manifest_path = "#{repo.tempdir}/#{repo.environmentpath}/production/.onceover_manifest.json"
261
- if File.exist? old_manifest_path
262
- logger.debug "Found manifest from previous run, parsing..."
263
- old_manifest = JSON.parse(File.read(old_manifest_path))
264
- logger.debug "Removing #{old_manifest.count} files"
265
- old_manifest.reverse.each do |file|
266
- FileUtils.rm_f(File.join("#{repo.tempdir}/#{repo.environmentpath}/production/",file))
267
- end
268
- end
269
- FileUtils.mkdir_p("#{repo.tempdir}/#{repo.environmentpath}")
270
-
271
- logger.debug "Copying #{temp_controlrepo} to #{repo.tempdir}/#{repo.environmentpath}/production"
272
- FileUtils.cp_r("#{temp_controlrepo}/.", "#{repo.tempdir}/#{repo.environmentpath}/production")
273
- FileUtils.rm_rf(temp_controlrepo)
274
-
275
- # Pull the trigger! If it's not already been pulled
276
- if repo.tempdir and not skip_r10k
277
- if File.directory?(repo.tempdir)
278
- # TODO: Change this to call out to r10k directly to do this
279
- # Probably something like:
280
- # R10K::Settings.global_settings.evaluate(with_overrides)
281
- # R10K::Action::Deploy::Environment
282
- prod_dir = "#{repo.tempdir}/#{repo.environmentpath}/production"
283
- Dir.chdir(prod_dir) do
284
- install_cmd = []
285
- install_cmd << "r10k puppetfile install --verbose --color --puppetfile #{repo.puppetfile}"
286
- install_cmd << "--force" if @force
287
- install_cmd = install_cmd.join(' ')
288
- logger.debug "Running #{install_cmd} from #{prod_dir}"
289
- system(install_cmd)
290
- raise 'r10k could not install all required modules' unless $?.success?
291
- end
292
- else
293
- raise "#{repo.tempdir} is not a directory"
294
- end
295
- end
296
-
297
- # Return repo.tempdir for use
298
- repo.tempdir
299
- end
300
-
301
170
  def write_spec_test(location, test)
302
171
  # Use an ERB template to write a spec test
303
172
  File.write("#{location}/#{test.to_s}_spec.rb",
@@ -394,19 +263,5 @@ class Onceover
394
263
  end
395
264
  tests
396
265
  end
397
-
398
- private
399
-
400
- def get_children_recursive(pathname)
401
- results = []
402
- results << pathname
403
- pathname.each_child do |child|
404
- results << child
405
- if child.directory?
406
- results << get_children_recursive(child)
407
- end
408
- end
409
- results.flatten
410
- end
411
266
  end
412
267
  end
data/onceover.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "onceover"
7
- s.version = "3.8.0"
7
+ s.version = "3.9.0"
8
8
  s.authors = ["Dylan Ratcliffe"]
9
9
  s.email = ["dylan.ratcliffe@puppet.com"]
10
10
  s.homepage = "https://github.com/dylanratcliffe/onceover"
@@ -3,9 +3,10 @@ classes:
3
3
  - role::database_server
4
4
  - role::webserver
5
5
  - role::example
6
+ - /apache::params/
6
7
 
7
8
  # Nodes to tests classes on, this refers to a 'factset' or 'nodeset'
8
- # depending on weather you are running 'spec' or 'acceptance' tests
9
+ # depending on whether you are running 'spec' or 'acceptance' tests
9
10
  nodes:
10
11
  - AIX-7.1-powerpc
11
12
  - SLES-12.1-64
@@ -50,4 +51,4 @@ test_matrix:
50
51
  tests: 'spec'
51
52
  - non_windows_nodes:
52
53
  classes: 'all_classes'
53
- tests: 'acceptance'
54
+ tests: 'acceptance'
@@ -3,7 +3,7 @@ classes:
3
3
  - role::test_functions
4
4
 
5
5
  # Nodes to tests classes on, this refers to a 'factset' or 'nodeset'
6
- # depending on weather you are running 'spec' or 'acceptance' tests
6
+ # depending on whether you are running 'spec' or 'acceptance' tests
7
7
  nodes:
8
8
  - CentOS-7.0-64
9
9
 
@@ -5,7 +5,7 @@ classes:
5
5
  <% end -%>
6
6
 
7
7
  # Nodes to tests classes on, this refers to a 'factset' or 'nodeset'
8
- # depending on weather you are running 'spec' or 'acceptance' tests
8
+ # depending on whether you are running 'spec' or 'acceptance' tests
9
9
  nodes:
10
10
  <% repo.facts_files.each do |file| -%>
11
11
  - <%= File.basename(file,'.json') %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onceover
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dylan Ratcliffe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-05 00:00:00.000000000 Z
11
+ date: 2018-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -341,6 +341,7 @@ files:
341
341
  - factsets/Windows_Server-2012r2-64.json
342
342
  - factsets/solaris-10_u9-sparc-64.json
343
343
  - factsets/solaris-11.2-sparc-64.json
344
+ - factsets/windows-10-64.json
344
345
  - features/cache.feature
345
346
  - features/help.feature
346
347
  - features/init.feature
@@ -364,6 +365,7 @@ files:
364
365
  - lib/onceover/cli/show.rb
365
366
  - lib/onceover/cli/update.rb
366
367
  - lib/onceover/controlrepo.rb
368
+ - lib/onceover/deploy.rb
367
369
  - lib/onceover/group.rb
368
370
  - lib/onceover/logger.rb
369
371
  - lib/onceover/node.rb