onceover 3.17.1 β†’ 3.19.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
  SHA256:
3
- metadata.gz: e6886259693e386c10aaebdd590be798363b38e823e4d7eb266d4f32f303cf2a
4
- data.tar.gz: afdcc34051329c3a584803af4164f42aef9d2ac22e37bf14a35546f5ed8f45e3
3
+ metadata.gz: 065da1fff392e66c26e31597cf1dfa207cd39d9c23414812a290aa6a9acb804a
4
+ data.tar.gz: 5c40d315ef83d0978a27cd2df2412c121277ddacff1c971440a2d4f8568c116d
5
5
  SHA512:
6
- metadata.gz: 6f5b35dfa27bf5b8e6477ffcd3ea985935698d0562cc55ab679e80c501ce15ecb17deb47c81dc276e4bc8634662be7354b0578a122f3258f6f5cb8f00a43dcb5
7
- data.tar.gz: 68c7771cfadc3ef7d9e43569e06e4ce40288a07db464eeaffc4c67b95558dab7b3c76f4e88dcb62ef82f02baf3e8ac13bc17cb988ead6164d96a05e43ef25ebd
6
+ metadata.gz: 4ed8538d20762a2f909cdaa5ec328029e828d5c82f6429c065e4b7485e49008372d219a51c42c326c02e920aae4e8bc581cef933c424be86ad904cff44b6820b
7
+ data.tar.gz: 56b892815655f1176f973e481b864245e833d154dacc856d78352a40ace95bb6a183ab14f7241b51218f429dd38740b5efcfc9a25f5d40184d7f25591416c17d
@@ -11,9 +11,9 @@ bundler_args: --path vendor/bundle
11
11
  matrix:
12
12
  include:
13
13
  # 2017.3 -> 2018.1
14
- - rvm: 2.4.4
14
+ - rvm: 2.4.5
15
15
  env: PUPPET_VERSION="~>5.0"
16
16
 
17
- # 2019.0 -> now
18
- - rvm: 2.5.7
17
+ # 2019.0 -> 2019.8
18
+ - rvm: 2.5.8
19
19
  env: PUPPET_VERSION="~>6.0"
data/README.md CHANGED
@@ -2,7 +2,9 @@
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 of the `Puppetfile`, `environment.conf` and others in order to stop silly mistakes ever reaching your Puppet Master!
5
+ Onceover is a tool to automatically run basic tests on an entire Puppet control repository.
6
+
7
+ It includes automatic parsing of the `Puppetfile`, `environment.conf` and others in order to stop silly mistakes ever reaching your Puppet Master!
6
8
 
7
9
  **🍺πŸ₯³ New in v3.17.1: Heaps more Windows fixes! Windows code is now more likely to compile on Non-Windows.**
8
10
 
@@ -10,13 +12,11 @@ Onceover is a tool to automatically run basic tests on an entire Puppet controlr
10
12
 
11
13
  - [Overview](#overview)
12
14
  - [Quick Start](#quick-start)
13
- - [Installation](#installation)
14
- - [Config files](#config-files)
15
+ - [Configuration](#configuration)
15
16
  - [onceover.yaml](#onceoveryaml)
16
- - [factsets](#factsets)
17
- - [Hiera Data](#hiera-data)
18
- - [r10k](#r10k)
19
- - [r10k Config](#r10k-config)
17
+ - [Factsets](#factsets)
18
+ - [Hiera](#hiera)
19
+ - [Puppetfile](#puppetfile)
20
20
  - [Spec testing](#spec-testing)
21
21
  - [Adding your own spec tests](#adding-your-own-spec-tests)
22
22
  - [Using Workarounds](#using-workarounds)
@@ -32,120 +32,220 @@ Onceover is a tool to automatically run basic tests on an entire Puppet controlr
32
32
  - [Rake tasks](#rake-tasks)
33
33
  - [generate_fixtures](#generate_fixtures)
34
34
 
35
+ ## Overview
36
+
37
+ This gem provides a toolset for testing _Puppet control repository_ (ie. Repos used with r10k).
38
+
39
+ 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.
40
+
41
+ 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.
42
+
43
+ This toolset requires some [configuration](#configuration) before it can be used so definitely read that section before getting started.
44
+
35
45
  ## Quick Start
36
46
 
37
- **Note:** This assumes you are inside the root of your controlrepo.
47
+ **Note:** This assumes you are inside the root of your control-repo.
38
48
 
39
- Install the Gem:
49
+ 1. Add `onceover` to your `Gemfile`:
40
50
 
41
- `gem install onceover`
51
+ ```ruby
52
+ gem 'onceover'
53
+ ```
42
54
 
43
- Set up your config:
55
+ 1. Run _Bundler_ to install `onceover`
44
56
 
45
- `onceover init`
57
+ ```shell
58
+ bundle install
59
+ ```
46
60
 
47
- Run your spec tests!
61
+ 1. Set up your configuration
48
62
 
49
- `onceover run spec`
63
+ ```shell
64
+ bundle exec onceover init
65
+ ```
66
+ 1. Run your spec tests!
50
67
 
51
- **Hint:** Don't forget you can use Bundler to install onceover by adding this to your Gemfile:
68
+ ```shell
69
+ bundle exec onceover run spec
70
+ ```
52
71
 
53
- ```ruby
54
- gem 'onceover'
55
- ```
72
+ ## Configuration
56
73
 
57
- Here is an example using Bundler:
74
+ This project uses one main config file to determine what Puppet classes we should be testing and how: [onceover.yaml](#onceoveryaml).
58
75
 
59
- Install the Gem:
76
+ As `onceover` tests Puppet classes, it need sets of facts to compile the Puppet code against, these are stored in [factsets](#factsets).
60
77
 
61
- `bundle install`
78
+ ### onceover.yaml
62
79
 
63
- Set up your config:
80
+ Usually located at `spec/onceover.yaml`, this path could be overrided with environment variable: `ONCEOVER_YAML`.
64
81
 
65
- `bundle exec onceover init`
82
+ 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.
66
83
 
67
- Run your spec tests!
84
+ #### Main settings
68
85
 
69
- `bundle exec onceover run spec`
86
+ - `classes`
70
87
 
71
- ## Overview
88
+ A list (array) of classes that we want to test
72
89
 
73
- 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.
90
+ Classes are specified as string or **regular expressions**.
91
+ The recommended setting to have a good coverage is `/^role::/` if you use [roles and profiles method](https://puppet.com/docs/pe/latest/the_roles_and_profiles_method.html) and if you dont, you [should](https://puppet.com/docs/pe/2019.8/the_roles_and_profiles_method.html).
74
92
 
75
- This toolset requires some config before it can be used so definitely read that section before getting started.
93
+ - `nodes`
76
94
 
77
- ## Installation
95
+ A list (array) of nodes that we want to test against.
78
96
 
79
- `gem install onceover`
97
+ The nodes that we list here map directly to a [factset](#factsets), e.g. `Debian-7.8-64`
80
98
 
81
- This gem can just be installed using `gem install` however I would recommend using [Bundler](http://bundler.io/) to manage your gems.
99
+ - `node_groups`
82
100
 
83
- ## Config Files
101
+ An hash of named node groups.
84
102
 
85
- This project uses one main config file to determine what classes we should be testing and how, this is [onceover.yaml](#onceoveryaml). The `onceover.yaml` config file provides information about what classes to test when, however it needs more information than that:
103
+ We can create groups by simply specifying an array of nodes to be in the group, or use the subtractive [include/exclude syntax](#includeexclude-syntax).
86
104
 
87
- 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)
105
+ **Note:** A _node group_ named `all_nodes` is automatically created by `onceover`.
88
106
 
89
- ### onceover.yaml
107
+ **Important:** The names used for the actual `class_groups` and `node_groups` must be unique.
90
108
 
91
- `spec/onceover.yaml` _(override with environment variable: `ONCEOVER_YAML`)_
109
+ - `class_groups`
92
110
 
93
- 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:
111
+ An hash of named class groups.
94
112
 
95
- **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.
113
+ We can create groups by simply specifying an array of classes (string or regexp) to be in the group, or use the subtractive [include/exclude syntax](#includeexclude-syntax).
96
114
 
97
- **nodes:** The nodes that we want to test against. The nodes that we list here map directly to a [factset](#factsets).
115
+ **Note:** A _class group_ named `all_classes` is automatically created by `onceover`.
98
116
 
99
- **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.
117
+ **Important:** The names used for the actual `class_groups` and `node_groups` must be unique.
100
118
 
101
- **class_groups:** The `class_groups` section is much the same as the `node_groups` sections, except that it creates groups of classes, not groups of nodes (duh). All the same rules apply and you can also use the *include/exclude* syntax. This, like the classes section can also accept regular expressions. This means that as long as you name your roles according to a naming convention that includes the desired operating system, you should be able to define your class groups once and never touch them again. The names used for the actual `class_groups` and `node_groups` must be unique.
119
+ - `test_matrix`
102
120
 
103
- **test_matrix:** This where the action happens! This is the section where we set up which classes are going to be tested against which nodes. It should be an array of hashes with the following format:
121
+ An array of hashes with the following format:
104
122
 
105
- ```yaml
106
- - {nodes_to_test}: # The name of a node or node group
107
- classes: '{classes_to_test}' # the name of a class or
108
- tests: '{all_tests|acceptance|spec}' # acceptance deprecated/broken, set to spec
109
- {valid_option}: {value} # Check the doco for available options
110
- ```
123
+ ```yaml
124
+ - {nodes_to_test}: # The name of a node or node group
125
+ classes: '{classes_to_test}' # the name of a class or
126
+ tests: '{all_tests|acceptance|spec}' # acceptance deprecated/broken, set to spec
127
+ {valid_option}: {value} # See below
128
+ ```
111
129
 
112
- Why an array of hashes? Well, that is so that we can refer to the same node or node group twice, which we may want/need to do.
130
+ Valid options:
113
131
 
114
- In the example below we have referred to `centos6a` and `centos7b` in all of our tests as they are in `all_nodes`, `non_windows_servers` and `centos_severs`. However we have *left the more specific references to last*. This is because entries in the test_matrix will override entries above them if applicable. Meaning that we are still only testing each class on the two Centos servers once (Because the gem does de-duplication before running the tests), but also making sure we run `roles::frontend_webserver` twice before checking for idempotency.
132
+ - `tags`
115
133
 
116
- **functions** In this section we can add functions that we want to mock when running spec tests. Each function takes the following arguments:
134
+ Default: `nil`
117
135
 
118
- - **returns** *Optional: A value to return*
136
+ One or many tags that tests in this group should be tagged with.
137
+ This allows you to run only certain tests using the `--tags` command line parameter.
119
138
 
120
- **before and after conditions** We can set `before` and `after` blocks before each spec test. These are usually used when the functions to stub are conditional: stub function `x` if the OS is windows, stub function `y` if the fact java_installed is true. The facts are available through the `node_facts` hash and the trusted facts as `trusted_facts`.
139
+ #### Advanced settings
121
140
 
122
- ```yaml
123
- before:
124
- - "Puppet::Util::Platform.stubs(:'windows?').returns(node_facts['kernel'] == 'windows')"
141
+ - `functions`
125
142
 
126
- after:
127
- - "puts 'Test finished running'"
128
- ```
143
+ Default: `nil`
144
+
145
+ In this section we can add functions that we want to mock when running spec tests.
146
+
147
+ Each function takes the `return` arguments, e.g.
148
+
149
+ ```yaml
150
+ functions:
151
+ puppetdb_query:
152
+ returns: []
153
+ ```
154
+
155
+ - `before`
156
+
157
+ Default: `nil`
158
+
159
+ A block to run **before** each spec test.
160
+
161
+ For example, this can be used when the functions to stub are conditional, the following stub function `x` if the OS is windows, stub function `y` if the fact `java_installed` is true.
162
+
163
+ **Note**: The facts are available through the `node_facts` hash and the trusted facts as `trusted_facts`.
164
+
165
+ Example:
166
+ ```yaml
167
+ before:
168
+ - "Puppet::Util::Platform.stubs(:'windows?').returns(node_facts['kernel'] == 'windows')"
169
+ ```
170
+
171
+ - `after`
172
+
173
+ Default: `nil`
174
+
175
+ A block to run **after** each spec test.
176
+
177
+ **Note**: The facts are available through the `node_facts` hash and the trusted facts as `trusted_facts`.
178
+
179
+ Exmaple:
180
+ ```yaml
181
+ after:
182
+ - "puts 'Test finished running'"
183
+ ```
184
+
185
+ - `include_spec_files`
186
+
187
+ Default: `[**/*]`
188
+
189
+ Glob to select additionnal files to be run during `onceover` spec tests.
190
+
191
+ Default is to select all files located in the repo spec directory, usually `spec/`.
192
+ If you have some RSpec tests that depend on a different RSpec configuration than `onceover` or want, for example, to have a different job in your CI to run your own unit tests, you can use this option to select which spec files to run during `onceover` spec tests.
193
+
194
+ - `opts`
195
+
196
+ Default: `{}`
197
+
198
+ This setting overrides defaults for the `Onceover::Controlrepo` class' `opts` hash.
199
+
200
+ Example:
201
+ ```yaml
202
+ opts:
203
+ :facts_dirs: # Remember: `opts` keys are symbols!
204
+ - 'spec/factsets' # Limit factsets to files in this repository
205
+ :debug: true # Set the `logger.level` to debug
206
+ :profile_regex: '^(profile|site)::' # Profiles include a legacy module named `site::`
207
+ :facts_files: # Factset filenames use the extension`.facts` instead of `.json`
208
+ - 'spec/factsets/*.facts'
209
+ :manifest: 'manifests/site.pp' # Manifest to use while compiling (nil by default)
210
+ ```
211
+
212
+ #### Include/Exclude syntax
129
213
 
130
- **opts** The `opts` section overrides defaults for the `Onceover::Controlrepo` class' `opts` hash.
214
+ This can be used with either `node_groups` or `class_groups` and allows us to save some time by using existing groups to create new ones e.g.
131
215
 
132
216
  ```yaml
133
- opts:
134
- :facts_dirs: # Remember: `opts` keys are symbols!
135
- - 'spec/factsets' # Limit factsets to files in this repository
136
- :debug: true # set the `logger.level` to debug
217
+ node_groups:
218
+ windows_nodes: # This has to be defined first
219
+ - sevrer2008r2
220
+ - server2012r2
221
+ non_windows:
222
+ include: 'all_nodes' # Start with all nodes
223
+ exclude: 'windows_nodes' # Then remove the windows ones from that list
137
224
  ```
138
225
 
226
+ It's important to note that in order to reference a group using the *include/exclude* syntax is has to have been defined already i.e. it has to come above the group that references it
227
+
228
+ #### Examples
229
+
230
+ ##### Minimal
231
+
139
232
  ```yaml
140
- opts:
141
- # profiles include a legacy module named `site::`
142
- :profile_regex: '^(profile|site)::'
233
+ classes:
234
+ - /^role::/
143
235
 
144
- # factset filenames use the extension`.facts` instead of `.json`
145
- :facts_files:
146
- - 'spec/factsets/*.facts'
236
+ nodes:
237
+ - Debian-10-amd64
238
+
239
+ test_matrix:
240
+ - all_nodes:
241
+ classes: 'all_classes'
242
+ tests: 'spec'
147
243
  ```
148
244
 
245
+ ##### Advanced
246
+
247
+ In the example below we have referred to `centos6a` and `centos7b` in all of our tests as they are in `all_nodes`, `non_windows_servers` and `centos_severs`. However we have *left the more specific references to last*. This is because entries in the test_matrix will override entries above them if applicable. Meaning that we are still only testing each class on the two Centos servers once (Because the gem does de-duplication before running the tests), but also making sure we run `roles::frontend_webserver` twice before checking for idempotency.
248
+
149
249
  A full example:
150
250
 
151
251
  ```yaml
@@ -155,7 +255,7 @@ classes:
155
255
  - 'roles::load_balancer'
156
256
  - 'roles::syd_f5_load_balancer'
157
257
  - 'roles::windows_server'
158
- - '/^role/'
258
+ - '/^role/' # Note that this regex format requires `/`
159
259
 
160
260
  nodes:
161
261
  - centos6a
@@ -209,47 +309,26 @@ functions:
209
309
  opts:
210
310
  :facts_dirs:
211
311
  - spec/factsets
312
+ :profile_regex: '^(profile|site)::' # Note that this regex _doesn't_ use `/`
212
313
  ```
213
314
 
214
- **Include/Exclude syntax:** This can be used with either `node_groups` or `class_groups` and allows us to save some time by using existing groups to create new ones e.g.
215
-
216
- ```yaml
217
- node_groups:
218
- windows_nodes: # This has to be defined first
219
- - sevrer2008r2
220
- - server2012r2
221
- non_windows:
222
- include: 'all_nodes' # Start with all nodes
223
- exclude: 'windows_nodes' # Then remove the windows ones from that list
224
- ```
315
+ ### Factsets
225
316
 
226
- It's important to note that in order to reference a group using the *include/exclude* syntax is has to have been defined already i.e. it has to come above the group that references it (Makes sense right?)
317
+ Factsets are used by the onceover gem to generate spec tests, which compile a given class against a certain set of facts.
227
318
 
228
- #### Optional test parameters
319
+ This gem comes with a few pre-canned factsets, these are listed under the `nodes` sections of `onceover.yaml` when you run `onceover init`.
229
320
 
230
- **tags** *Default: nil*
321
+ You can, and its a good pratice, add your own factsets by putting them in `spec/factsets/*.json`.
231
322
 
232
- 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
323
+ To generate these factsets all we need to do is log onto a real machine that has puppet installed and run:
233
324
 
234
- ### factsets
235
-
236
- This gem comes with a few pre-canned factsets. These are listed under the `nodes` sections of `onceover.yaml` when you run `onceover init`. You can also add your own factsets by putting them in:
237
-
238
- `spec/factsets/*.json`
239
-
240
- Factsets are used by the onceover gem to generate spec tests, which compile a given class against a certain set of facts. To create these factsets all we need to do is log onto a real machine that has puppet installed and run:
241
-
242
- `puppet facts`
243
-
244
- Which will give raw json output of every fact which puppet knows about. Usually I would recommend running this on each of the types of machines that you run in your infrastructure so that you have good coverage. To make life easier you might want to direct it into a file instead of copying it from the command line:
245
-
246
- `puppet facts > fact_set_name.json`
247
-
248
- Once we have our factset all we need to do is copy it into `spec/factsets/` inside our controlrepo and commit it to version control. Factsets are named based on their filename, not the name of the server they came from (Although you can, if you want). i.e the following factset file:
325
+ ```shell
326
+ puppet facts > fact_set_name.json
327
+ ```
249
328
 
250
- `spec/factsets/server2008r2.json`
329
+ Its recommended to run this on each of the types of nodes that you run in your infrastructure to have good coverage.
251
330
 
252
- Would map to a node named `server2008r2` in `onceover.yaml`
331
+ Factsets are named based on their filename, i.e. `myfactset` in `onceover.yaml` refers `spec/factsets/myfactset.json`
253
332
 
254
333
  #### Trusted Facts
255
334
 
@@ -270,13 +349,17 @@ You can add trusted facts to the factsets by creating a new section called trust
270
349
 
271
350
  Notice that the `extensions` part is implied. The first fact in that example translates to `$trusted['extensions']['pp_role']` in Puppet code.
272
351
 
273
- ### Hiera Data
352
+ ### Hiera
274
353
 
275
- 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.
354
+ If you have hiera data inside your controlrepo (or somewhere else) `onceover` can be configured to use it.
355
+ It is however worth noting the `hiera.yaml` file that you currently use may not be applicable for testing right away.
356
+ 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.
276
357
 
277
- It is also worth noting that any hiera hierarchies that are based on custom facts will not work unless those facts are part of your factsets. Trusted facts will also not work at all as the catalogs are being compiled without the node's certificate. In these instances it may be worth creating a hierarchy level that simply includes dummy data for testing purposes in order to avoid hiera lookup errors.
358
+ It is also worth noting that any hiera hierarchies that are based on custom facts will not work unless those facts are part of your factsets.
359
+ Trusted facts will also not work at all as the catalogs are being compiled without the node's certificate.
360
+ In these instances it may be worth creating a hierarchy level that simply includes dummy data for testing purposes in order to avoid hiera lookup errors.
278
361
 
279
- ### r10k
362
+ ### Puppetfile
280
363
 
281
364
  Organisations often reference modules from their own git servers in the `Puppetfile`, like this:
282
365
 
@@ -286,7 +369,9 @@ mod "puppetlabs-apache",
286
369
  :tag => "v5.4.0"
287
370
  ```
288
371
 
289
- Under the hood, Onceover uses r10k to download the modules in your `Puppetfile`. If you get errors downloading modules from Git, its because `r10k`'s call to your underlying `git` command has failed. Onceover tells you the command that `r10k` tried to run, so if you get an error like this:
372
+ Under the hood, `onceover` uses `r10k` to download the modules in your `Puppetfile`.
373
+ If you get errors downloading modules from `git`, its because `r10k`'s call to your underlying `git` command has failed.
374
+ `onceover` tells you the command that `r10k` tried to run, so if you get an error like this:
290
375
 
291
376
  ```
292
377
  INFO -> Updating module /Users/dylan/control-repo/.onceover/etc/puppetlabs/code/environments
@@ -321,7 +406,7 @@ Warning: Permanently added 'git.megacorp.com,123.456.789.101' (RSA) to the list
321
406
 
322
407
  The other way to resolve this would have been to install the `ssh_askpass` program, but this can spam the screen with modal dialogs on some platforms.
323
408
 
324
- #### r10k Config
409
+ #### r10k configuration
325
410
 
326
411
  If you have custom r10k config that you want to use, place the `r10k.yaml` file in one of the following locations:
327
412
 
@@ -700,3 +785,8 @@ Cheers to all of those who helped out:
700
785
  - @raphink
701
786
  - @tequeter
702
787
  - @alexjfisher
788
+ - @smortex
789
+ - @16c7x
790
+ - @neomilium
791
+ - @chlawren
792
+
@@ -162,6 +162,7 @@
162
162
  "staging_http_get": "powershell",
163
163
  "staging_windir": "C:\\ProgramData\\staging",
164
164
  "system32": "C:\\Windows\\system32",
165
+ "choco_install_path": "C:\\ProgramData\\chocolatey",
165
166
  "system_uptime": {
166
167
  "days": 0,
167
168
  "hours": 0,
@@ -143,6 +143,7 @@
143
143
  "rubyversion": "2.1.7",
144
144
  "serialnumber": "0",
145
145
  "system32": "C:\\Windows\\system32",
146
+ "choco_install_path": "C:\\ProgramData\\chocolatey",
146
147
  "system_uptime": {
147
148
  "days": 0,
148
149
  "hours": 0,
@@ -83,6 +83,7 @@
83
83
  "rubysitedir": "C:/tools/ruby24/lib/ruby/site_ruby/2.4.0",
84
84
  "rubyversion": "2.4.3",
85
85
  "system32": "C:\\Windows\\system32",
86
+ "choco_install_path": "C:\\ProgramData\\chocolatey",
86
87
  "system_uptime": {
87
88
  "seconds": 1113359,
88
89
  "hours": 309,
@@ -100,4 +101,4 @@
100
101
  },
101
102
  "timestamp": "2018-12-10T21:43:07.468533000+00:00",
102
103
  "expiration": "2018-12-10T22:13:07.468533000+00:00"
103
- }
104
+ }
@@ -77,13 +77,39 @@ Then(/^I should see error with message pattern "([^"]*)"$/) do |err_msg_regexp|
77
77
  expect(@cmd.output.match err_msg_regexp).to_not be nil
78
78
  end
79
79
 
80
- Then(/^I should see message pattern "([^"]*)"$/) do |msg_regexp|
80
+ Then(/^I should (not )?see message pattern "([^"]*)"$/) do |notword, msg_regexp|
81
81
  output_surround = 30
82
82
  match = Regexp.new(msg_regexp).match(@cmd.output)
83
- expect(@cmd.output).to match(msg_regexp)
84
- if match
85
- puts match.pre_match[-output_surround..-1] + match.to_s + match.post_match[0..output_surround]
83
+
84
+ # Expect it to match unless we said it shouldn't match
85
+ expected_match = notword.nil?
86
+ does_match = !match.nil?
87
+
88
+ if expected_match
89
+ expect(@cmd.output).to match(msg_regexp)
90
+ else
91
+ expect(@cmd.output).not_to match(msg_regexp)
92
+ end
93
+
94
+ # If the regex matches and that's what we expected then just print a summary
95
+ if does_match == expected_match
96
+ if match
97
+ puts match.pre_match[-output_surround..-1] + match.to_s + match.post_match[0..output_surround]
98
+ end
86
99
  else
87
100
  puts @cmd.output
88
101
  end
89
102
  end
103
+
104
+ When(/^I run onceover command "([^"]*)" with \-\-puppetfile ([^"]*)$/) do |command, puppetfile|
105
+ puppetfile_path = @repo.root_folder + puppetfile
106
+ @cmd.command = "#{command} --puppetfile #{puppetfile_path} --debug"
107
+ puts @cmd
108
+ @cmd.run
109
+ end
110
+
111
+ Then(/^([^"]*) should be copied to Puppetfile$/) do |puppetfile|
112
+ source = @repo.root_folder + puppetfile
113
+ destination = @repo.onceover_temp_puppetfile
114
+ expect(IO.read(source)).to eq(IO.read(destination))
115
+ end
@@ -28,3 +28,8 @@ Feature: Run onceover with windows
28
28
  When I run onceover command "run spec" with class "role::users"
29
29
  Then I should not see any errors
30
30
 
31
+ Scenario: Compiling a windows role with chocolatey that is valid should compile
32
+ Given control repo "windows"
33
+ When I run onceover command "run spec" with class "role::choco"
34
+ Then I should not see any errors
35
+
@@ -1,6 +1,6 @@
1
1
  @run
2
2
  Feature: Run rspec and acceptance test suites
3
- Onceover should allow to run rspec and acceptance test for all profvile and role classes
3
+ Onceover should allow to run rspec and acceptance test for all profile and role classes
4
4
  or for any part of them. Use should set if he wants to see only summary of tests or full
5
5
  log info.
6
6
 
@@ -52,6 +52,11 @@ Feature: Run rspec and acceptance test suites
52
52
  And I run onceover command "run spec --force"
53
53
  Then I should see message pattern "Overwriting local modifications"
54
54
 
55
+ Scenario: When using an alternate manifests directory
56
+ Given initialized control repo "basic"
57
+ When I run onceover command "run spec --manifest manifests_alternate"
58
+ Then I should see error with message pattern "Using alternate site.pp"
59
+
55
60
  Scenario: Check that control_branch functionality works
56
61
  Given initialized control repo "control_branch"
57
62
  When I run onceover command "run spec"
@@ -73,8 +78,22 @@ Feature: Run rspec and acceptance test suites
73
78
  Then I should see message pattern "failed"
74
79
  And Onceover should exit 1
75
80
 
81
+ Scenario: Run with a custom Puppetfile
82
+ Given initialized control repo "custom_puppetfile"
83
+ When I run onceover command "run spec" with --puppetfile Puppetfile.custom
84
+ Then Puppetfile.custom should be copied to Puppetfile
85
+ And I should see message pattern "Using Puppetfile .*Puppetfile"
86
+ And I should see message pattern "Updating module .*extlib"
87
+
88
+ Scenario: Testing that --tags works with native rspec tags
89
+ Given control repo "puppet_controlrepo"
90
+ When I run onceover command "run spec --tags syntax"
91
+ Then I should not see any errors
92
+ And I should see message pattern "When checking Puppet syntax"
93
+ And I should not see message pattern "role::"
94
+
76
95
  # This test is a full test using my controlrepo. It should remain at the end because it takes ages
77
96
  Scenario: Run advanced spec tests
78
97
  Given control repo "puppet_controlrepo"
79
98
  When I run onceover command "run spec -p"
80
- Then I should not see any errors
99
+ Then I should not see any errors
@@ -123,7 +123,8 @@ class Onceover
123
123
  @profile_regex = opts[:profile_regex] ? Regexp.new(opts[:profile_regex]) : /profile[s]?:{2}/
124
124
  @tempdir = opts[:tempdir] || File.expand_path('./.onceover', @root)
125
125
  $temp_modulepath = nil
126
- @manifest = opts[:manifest] || config['manifest'] ? File.expand_path(config['manifest'], @root) : nil
126
+ manifest = opts[:manifest] || config['manifest'] || 'manifests'
127
+ @manifest = File.expand_path(manifest, @root)
127
128
  @opts = opts
128
129
  logger.level = :debug if @opts[:debug]
129
130
  @@existing_controlrepo = self
@@ -206,7 +207,7 @@ class Onceover
206
207
  end
207
208
 
208
209
  def print_puppetfile_table
209
- require 'table_print'
210
+ require 'terminal-table'
210
211
  require 'versionomy'
211
212
  require 'colored'
212
213
  require 'r10k/puppetfile'
@@ -221,48 +222,44 @@ class Onceover
221
222
  threads = []
222
223
  puppetfile.modules.each do |mod|
223
224
  threads << Thread.new do
224
- return_hash = {}
225
+ row = []
225
226
  logger.debug "Loading data for #{mod.full_name}"
226
- return_hash[:full_name] = mod.full_name
227
+ row << mod.full_name
227
228
  if mod.is_a?(R10K::Module::Forge)
228
- return_hash[:current_version] = mod.expected_version
229
- return_hash[:latest_version] = mod.v3_module.current_release.version
230
- return_hash[:endorsement] = mod.v3_module.endorsement
229
+ row << mod.expected_version
230
+ row << mod.v3_module.current_release.version
231
+
232
+ current = Versionomy.parse(mod.expected_version)
233
+ latest = Versionomy.parse(mod.v3_module.current_release.version)
234
+ row << if current.major < latest.major
235
+ "Major".red
236
+ elsif current.minor < latest.minor
237
+ "Minor".yellow
238
+ elsif current.tiny < latest.tiny
239
+ "Tiny".green
240
+ else
241
+ "No".green
242
+ end
243
+
244
+ row << mod.v3_module.endorsement
231
245
  superseded_by = mod.v3_module.superseded_by
232
- return_hash[:superseded_by] = superseded_by.nil? ? '' : superseded_by[:slug]
233
- current = Versionomy.parse(return_hash[:current_version])
234
- latest = Versionomy.parse(return_hash[:latest_version])
235
- if current.major < latest.major
236
- return_hash[:out_of_date] = "Major".red
237
- elsif current.minor < latest.minor
238
- return_hash[:out_of_date] = "Minor".yellow
239
- elsif current.tiny < latest.tiny
240
- return_hash[:out_of_date] = "Tiny".green
241
- else
242
- return_hash[:out_of_date] = "No".green
243
- end
246
+ row << (superseded_by.nil? ? '' : superseded_by[:slug])
244
247
  else
245
- return_hash[:current_version] = "N/A"
246
- return_hash[:latest_version] = "N/A"
247
- return_hash[:out_of_date] = "N/A"
248
- return_hash[:endorsement] = "N/A"
249
- return_hash[:superseded_by] = "N/A"
248
+ row << "N/A"
249
+ row << "N/A"
250
+ row << "N/A"
251
+ row << "N/A"
252
+ row << "N/A"
250
253
  end
251
- output_array << return_hash
254
+ output_array << row
252
255
  end
253
256
  end
254
257
 
255
258
  threads.map(&:join)
256
259
 
257
- tp(
258
- output_array,
259
- {:full_name => {:display_name => "Full Name"}},
260
- {:current_version => {:display_name => "Current Version"}},
261
- {:latest_version => {:display_name => "Latest Version"}},
262
- {:out_of_date => {:display_name => "Out of Date?"}},
263
- {:endorsement => {:display_name => "Endorsement"}},
264
- {:superseded_by => {:display_name => "Superseded by"}}
265
- )
260
+ output_array.sort_by! { |line| line[0] }
261
+
262
+ puts Terminal::Table.new(headings: ["Full Name", "Current Version", "Latest Version", "Out of Date?", "Endorsement", "Superseded by"], rows: output_array)
266
263
  end
267
264
 
268
265
  def update_puppetfile
@@ -424,7 +421,7 @@ class Onceover
424
421
  rescue StandardError
425
422
  raise "modulepath was not found in environment.conf, don't know where to look for roles & profiles"
426
423
  end
427
-
424
+
428
425
  environment_config
429
426
  end
430
427
 
@@ -448,7 +445,7 @@ class Onceover
448
445
  end
449
446
 
450
447
  def temp_manifest
451
- config['manifest'] ? File.expand_path(config['manifest'], @tempdir) : nil
448
+ @manifest
452
449
  end
453
450
 
454
451
  def self.init(repo)
@@ -646,7 +643,7 @@ class Onceover
646
643
  def find_classname(filename)
647
644
  file = File.new(filename, "r")
648
645
  while (line = file.gets)
649
- begin
646
+ begin
650
647
  if line =~ /^class (\w+(?:::\w+)*)/
651
648
  return $1
652
649
  end
@@ -83,6 +83,7 @@ class Onceover
83
83
  logger.debug "found #{git_branch} as current working branch"
84
84
  # Only try to modify Puppetfile if it exists
85
85
  unless skip_r10k
86
+ FileUtils.copy repo.puppetfile, "#{temp_controlrepo}/Puppetfile"
86
87
  puppetfile_contents = File.read("#{temp_controlrepo}/Puppetfile")
87
88
 
88
89
  logger.debug "replacing :control_branch mentions in the Puppetfile with #{git_branch}"
@@ -118,7 +119,7 @@ class Onceover
118
119
  prod_dir = "#{repo.tempdir}/#{repo.environmentpath}/production"
119
120
  Dir.chdir(prod_dir) do
120
121
  install_cmd = []
121
- install_cmd << "r10k puppetfile install --color --puppetfile #{repo.puppetfile}"
122
+ install_cmd << 'r10k puppetfile install --color'
122
123
  install_cmd << "--force" if force
123
124
  install_cmd << "--config #{repo.r10k_config_file}" if repo.r10k_config_file
124
125
  install_cmd << (logger.level > 0 ? "--verbose" : "--verbose debug") # Enable debugging if we're debugging
@@ -71,7 +71,7 @@ class Onceover
71
71
  else
72
72
  return false
73
73
  end
74
- rescue StandardErroor
74
+ rescue StandardError
75
75
  return false
76
76
  end
77
77
  end
@@ -1,4 +1,5 @@
1
1
  require 'backticks'
2
+ require 'io/console'
2
3
 
3
4
  class Onceover
4
5
  class Runner
@@ -24,8 +25,8 @@ class Onceover
24
25
  FileUtils.mkdir_p("#{@repo.tempdir}/spec/classes")
25
26
  FileUtils.mkdir_p("#{@repo.tempdir}/spec/acceptance/nodesets")
26
27
 
27
- # Copy our entire spec directory over
28
- FileUtils.cp_r("#{@repo.spec_dir}", "#{@repo.tempdir}")
28
+ # Copy specified spec files over
29
+ @config.copy_spec_files(@repo)
29
30
 
30
31
  # Create the Rakefile so that we can take advantage of the existing tasks
31
32
  @config.write_rakefile(@repo.tempdir, "spec/classes/**/*_spec.rb")
@@ -36,8 +37,6 @@ class Onceover
36
37
  # Create spec_helper_accpetance.rb
37
38
  @config.write_spec_helper_acceptance("#{@repo.tempdir}/spec", @repo)
38
39
 
39
- # TODO: Remove all tests that do not match set tags
40
-
41
40
  if @mode.include?(:spec)
42
41
  # Verify all of the spec tests
43
42
  @config.spec_tests.each { |test| @config.verify_spec_test(@repo, test) }
@@ -83,8 +82,10 @@ class Onceover
83
82
  ENV['RUBYOPT'] = ENV['RUBYOPT'].to_s + ' -W0'
84
83
  end
85
84
 
86
- #`bundle install --binstubs`
87
- #`bin/rake spec_standalone`
85
+ # NOTE: This is the way to provide options to rspec according to:
86
+ # https://github.com/puppetlabs/puppetlabs_spec_helper/blob/master/lib/puppetlabs_spec_helper/rake_tasks.rb#L51
87
+ ENV['CI_SPEC_OPTIONS'] = ENV['CI_SPEC_OPTIONS'].to_s + @config.filter_tags.map { |tag| " --tag #{tag}" }.join unless @config.filter_tags.nil?
88
+
88
89
  if @config.opts[:parallel]
89
90
  logger.debug "Running #{@command_prefix}rake parallel_spec from #{@repo.tempdir}"
90
91
  result = run_command(@command_prefix.strip.split, 'rake', 'parallel_spec')
@@ -25,10 +25,11 @@ class Onceover
25
25
  @classes = []
26
26
  @test_config = test_config
27
27
  @test_config.delete('classes') # remove classes from the config
28
- @tags = @test_config['tags']
29
28
 
30
29
  # Make sure that tags are an array
31
- @test_config['tags'] = [@test_config['tags']].flatten if @test_config['tags']
30
+ @test_config['tags'] ||= []
31
+ @test_config['tags'] = [@test_config['tags']].flatten
32
+ @tags = @test_config['tags']
32
33
 
33
34
  # Get the nodes we are working on
34
35
  if Onceover::Group.find(on_this)
@@ -50,6 +50,7 @@ class Onceover
50
50
  @before_conditions = config['before'] || []
51
51
  @after_conditions = config['after']
52
52
  @strict_variables = opts[:strict_variables] ? 'yes' : 'no'
53
+ @included_specs = [config['include_spec_files'] || ['**/*']].flatten
53
54
 
54
55
  # Set dynamic defaults for format
55
56
  if Array(opts[:format]) == [:defaults]
@@ -236,6 +237,19 @@ class Onceover
236
237
  )
237
238
  end
238
239
 
240
+ def copy_spec_files(repo)
241
+ source_files = @included_specs.map { |glob| Dir.glob "#{repo.spec_dir}/#{glob}" }.flatten.uniq
242
+ source_files.each do |source_file|
243
+ target_file = File.join(repo.tempdir, 'spec', source_file.sub(/^#{repo.spec_dir}/, ''))
244
+ if File.directory?(source_file)
245
+ FileUtils.cp_r source_file, target_file unless File.exists? target_file
246
+ else
247
+ FileUtils.mkdir_p File.dirname target_file
248
+ FileUtils.cp source_file, target_file
249
+ end
250
+ end
251
+ end
252
+
239
253
  def create_fixtures_symlinks(repo)
240
254
  logger.debug "Creating fixtures symlinks"
241
255
  FileUtils.rm_rf("#{repo.tempdir}/spec/fixtures/modules")
@@ -275,16 +289,25 @@ class Onceover
275
289
  # Remove tests that do not have matching tags
276
290
  tests.keep_if do |test|
277
291
  filter_list.any? do |filter|
278
- if test.send(method)
279
- test.send(method).include?(filter)
280
- else
281
- false
282
- end
292
+ filter_test test, method, filter
283
293
  end
284
294
  end
285
295
  end
286
296
  end
287
297
  tests
288
298
  end
299
+
300
+ def filter_test(test, method, filter)
301
+ if test.send(method)
302
+ if method == 'tags' && filter.start_with?('~')
303
+ filter = filter.sub(/^~/, '')
304
+ ! test.send(method).include?(filter)
305
+ else
306
+ test.send(method).include?(filter)
307
+ end
308
+ else
309
+ false
310
+ end
311
+ end
289
312
  end
290
313
  end
@@ -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.17.1"
7
+ s.version = "3.19.0"
8
8
  s.authors = ["Dylan Ratcliffe"]
9
9
  s.email = ["dylan.ratcliffe@puppet.com"]
10
10
  s.homepage = "https://github.com/dylanratcliffe/onceover"
@@ -34,7 +34,7 @@ Gem::Specification.new do |s|
34
34
  s.add_runtime_dependency 'rspec', '>= 3.0.0'
35
35
  s.add_runtime_dependency 'rspec-puppet', ">= 2.4.0"
36
36
  s.add_runtime_dependency 'rspec_junit_formatter', '>= 0.2.0'
37
- s.add_runtime_dependency 'table_print', '>= 1.0.0'
37
+ s.add_runtime_dependency 'terminal-table', '>= 1.8.0'
38
38
  s.add_runtime_dependency 'versionomy', '>= 0.5.0'
39
39
 
40
40
  end
@@ -0,0 +1,2 @@
1
+ # This will fail all compilations so that we can quickly tell if it's being used
2
+ fail('Using alternate site.pp')
@@ -0,0 +1,3 @@
1
+ forge "http://forge.puppetlabs.com"
2
+
3
+ mod "puppet/extlib"
@@ -0,0 +1,7 @@
1
+ modulepath = site:modules:$basemodulepath
2
+
3
+ # Comments!
4
+
5
+ value_with_equals = 'foo=bar'
6
+
7
+ config_version = 'scripts/config_version.sh $environmentpath $environment'
@@ -1,3 +1,8 @@
1
1
  forge "http://forge.puppetlabs.com"
2
2
 
3
3
  mod 'puppetlabs-acl', '3.1.1'
4
+ mod 'puppetlabs-chocolatey', '5.1.1'
5
+ mod 'puppetlabs-stdlib', '6.5.0'
6
+ mod 'puppetlabs-powershell', '4.0.0'
7
+ mod 'puppetlabs-pwshlib', '0.5.1'
8
+ mod 'puppetlabs-registry', '3.1.1'
@@ -0,0 +1,9 @@
1
+ # Choco
2
+ class role::choco {
3
+ include ::chocolatey
4
+
5
+ package { 'winzip':
6
+ ensure => 'present',
7
+ provider => 'chocolatey',
8
+ }
9
+ }
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  <% test.classes.each do |cls| -%>
4
- describe "<%= cls.name %>" do
4
+ describe "<%= cls.name %>"<%= test.tags.map { |tag| ",#{tag}: true "}.join %> do
5
5
 
6
6
  <% test.nodes.each do |node| -%>
7
7
  context "using fact set <%= node.name %>" do
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.17.1
4
+ version: 3.19.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: 2020-07-01 00:00:00.000000000 Z
11
+ date: 2020-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backticks
@@ -235,19 +235,19 @@ dependencies:
235
235
  - !ruby/object:Gem::Version
236
236
  version: 0.2.0
237
237
  - !ruby/object:Gem::Dependency
238
- name: table_print
238
+ name: terminal-table
239
239
  requirement: !ruby/object:Gem::Requirement
240
240
  requirements:
241
241
  - - ">="
242
242
  - !ruby/object:Gem::Version
243
- version: 1.0.0
243
+ version: 1.8.0
244
244
  type: :runtime
245
245
  prerelease: false
246
246
  version_requirements: !ruby/object:Gem::Requirement
247
247
  requirements:
248
248
  - - ">="
249
249
  - !ruby/object:Gem::Version
250
- version: 1.0.0
250
+ version: 1.8.0
251
251
  - !ruby/object:Gem::Dependency
252
252
  name: versionomy
253
253
  requirement: !ruby/object:Gem::Requirement
@@ -347,6 +347,7 @@ files:
347
347
  - spec/fixtures/controlrepos/basic/hieradata/common.yaml
348
348
  - spec/fixtures/controlrepos/basic/hieradata/nodes/example-node.yaml
349
349
  - spec/fixtures/controlrepos/basic/manifests/site.pp
350
+ - spec/fixtures/controlrepos/basic/manifests_alternate/site.pp
350
351
  - spec/fixtures/controlrepos/basic/site/profile/manifests/base.pp
351
352
  - spec/fixtures/controlrepos/basic/site/profile/manifests/example.pp
352
353
  - spec/fixtures/controlrepos/basic/site/role/manifests/database_server.pp
@@ -374,6 +375,8 @@ files:
374
375
  - spec/fixtures/controlrepos/caching/spec/r10k.yaml
375
376
  - spec/fixtures/controlrepos/control_branch/Puppetfile
376
377
  - spec/fixtures/controlrepos/control_branch/environment.conf
378
+ - spec/fixtures/controlrepos/custom_puppetfile/Puppetfile.custom
379
+ - spec/fixtures/controlrepos/custom_puppetfile/environment.conf
377
380
  - spec/fixtures/controlrepos/factsets/environment.conf
378
381
  - spec/fixtures/controlrepos/factsets/site/profile/manifests/base.pp
379
382
  - spec/fixtures/controlrepos/factsets/site/role/manifests/example.pp
@@ -394,6 +397,7 @@ files:
394
397
  - spec/fixtures/controlrepos/windows/Puppetfile
395
398
  - spec/fixtures/controlrepos/windows/environment.conf
396
399
  - spec/fixtures/controlrepos/windows/site-modules/role/manifests/acl.pp
400
+ - spec/fixtures/controlrepos/windows/site-modules/role/manifests/choco.pp
397
401
  - spec/fixtures/controlrepos/windows/site-modules/role/manifests/groups.pp
398
402
  - spec/fixtures/controlrepos/windows/site-modules/role/manifests/users.pp
399
403
  - spec/fixtures/controlrepos/windows/site/role/manifests/groups.pp