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 +4 -4
- data/.travis.yml +3 -3
- data/README.md +199 -109
- data/factsets/Windows_Server-2008r2-64.json +1 -0
- data/factsets/Windows_Server-2012r2-64.json +1 -0
- data/factsets/windows-10-64.json +2 -1
- data/features/step_definitions/common.rb +30 -4
- data/features/windows.feature +5 -0
- data/features/zzz_run.feature +21 -2
- data/lib/onceover/controlrepo.rb +34 -37
- data/lib/onceover/deploy.rb +2 -1
- data/lib/onceover/group.rb +1 -1
- data/lib/onceover/runner.rb +7 -6
- data/lib/onceover/test.rb +3 -2
- data/lib/onceover/testconfig.rb +28 -5
- data/onceover.gemspec +2 -2
- data/spec/fixtures/controlrepos/basic/manifests_alternate/site.pp +2 -0
- data/spec/fixtures/controlrepos/custom_puppetfile/Puppetfile.custom +3 -0
- data/spec/fixtures/controlrepos/custom_puppetfile/environment.conf +7 -0
- data/spec/fixtures/controlrepos/windows/Puppetfile +5 -0
- data/spec/fixtures/controlrepos/windows/site-modules/role/manifests/choco.pp +9 -0
- data/templates/test_spec.rb.erb +1 -1
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 065da1fff392e66c26e31597cf1dfa207cd39d9c23414812a290aa6a9acb804a
|
4
|
+
data.tar.gz: 5c40d315ef83d0978a27cd2df2412c121277ddacff1c971440a2d4f8568c116d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ed8538d20762a2f909cdaa5ec328029e828d5c82f6429c065e4b7485e49008372d219a51c42c326c02e920aae4e8bc581cef933c424be86ad904cff44b6820b
|
7
|
+
data.tar.gz: 56b892815655f1176f973e481b864245e833d154dacc856d78352a40ace95bb6a183ab14f7241b51218f429dd38740b5efcfc9a25f5d40184d7f25591416c17d
|
data/.travis.yml
CHANGED
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
|
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
|
-
- [
|
14
|
-
- [Config files](#config-files)
|
15
|
+
- [Configuration](#configuration)
|
15
16
|
- [onceover.yaml](#onceoveryaml)
|
16
|
-
- [
|
17
|
-
- [Hiera
|
18
|
-
- [
|
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
|
47
|
+
**Note:** This assumes you are inside the root of your control-repo.
|
38
48
|
|
39
|
-
|
49
|
+
1. Add `onceover` to your `Gemfile`:
|
40
50
|
|
41
|
-
|
51
|
+
```ruby
|
52
|
+
gem 'onceover'
|
53
|
+
```
|
42
54
|
|
43
|
-
|
55
|
+
1. Run _Bundler_ to install `onceover`
|
44
56
|
|
45
|
-
|
57
|
+
```shell
|
58
|
+
bundle install
|
59
|
+
```
|
46
60
|
|
47
|
-
|
61
|
+
1. Set up your configuration
|
48
62
|
|
49
|
-
|
63
|
+
```shell
|
64
|
+
bundle exec onceover init
|
65
|
+
```
|
66
|
+
1. Run your spec tests!
|
50
67
|
|
51
|
-
|
68
|
+
```shell
|
69
|
+
bundle exec onceover run spec
|
70
|
+
```
|
52
71
|
|
53
|
-
|
54
|
-
gem 'onceover'
|
55
|
-
```
|
72
|
+
## Configuration
|
56
73
|
|
57
|
-
|
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
|
-
|
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
|
-
|
78
|
+
### onceover.yaml
|
62
79
|
|
63
|
-
|
80
|
+
Usually located at `spec/onceover.yaml`, this path could be overrided with environment variable: `ONCEOVER_YAML`.
|
64
81
|
|
65
|
-
|
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
|
-
|
84
|
+
#### Main settings
|
68
85
|
|
69
|
-
|
86
|
+
- `classes`
|
70
87
|
|
71
|
-
|
88
|
+
A list (array) of classes that we want to test
|
72
89
|
|
73
|
-
|
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
|
-
|
93
|
+
- `nodes`
|
76
94
|
|
77
|
-
|
95
|
+
A list (array) of nodes that we want to test against.
|
78
96
|
|
79
|
-
|
97
|
+
The nodes that we list here map directly to a [factset](#factsets), e.g. `Debian-7.8-64`
|
80
98
|
|
81
|
-
|
99
|
+
- `node_groups`
|
82
100
|
|
83
|
-
|
101
|
+
An hash of named node groups.
|
84
102
|
|
85
|
-
|
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
|
-
|
105
|
+
**Note:** A _node group_ named `all_nodes` is automatically created by `onceover`.
|
88
106
|
|
89
|
-
|
107
|
+
**Important:** The names used for the actual `class_groups` and `node_groups` must be unique.
|
90
108
|
|
91
|
-
|
109
|
+
- `class_groups`
|
92
110
|
|
93
|
-
|
111
|
+
An hash of named class groups.
|
94
112
|
|
95
|
-
|
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
|
-
**
|
115
|
+
**Note:** A _class group_ named `all_classes` is automatically created by `onceover`.
|
98
116
|
|
99
|
-
**
|
117
|
+
**Important:** The names used for the actual `class_groups` and `node_groups` must be unique.
|
100
118
|
|
101
|
-
|
119
|
+
- `test_matrix`
|
102
120
|
|
103
|
-
|
121
|
+
An array of hashes with the following format:
|
104
122
|
|
105
|
-
```yaml
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
130
|
+
Valid options:
|
113
131
|
|
114
|
-
|
132
|
+
- `tags`
|
115
133
|
|
116
|
-
|
134
|
+
Default: `nil`
|
117
135
|
|
118
|
-
|
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
|
-
|
139
|
+
#### Advanced settings
|
121
140
|
|
122
|
-
|
123
|
-
before:
|
124
|
-
- "Puppet::Util::Platform.stubs(:'windows?').returns(node_facts['kernel'] == 'windows')"
|
141
|
+
- `functions`
|
125
142
|
|
126
|
-
|
127
|
-
|
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
|
-
|
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
|
-
|
134
|
-
:
|
135
|
-
-
|
136
|
-
|
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
|
-
|
141
|
-
|
142
|
-
:profile_regex: '^(profile|site)::'
|
233
|
+
classes:
|
234
|
+
- /^role::/
|
143
235
|
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
321
|
+
You can, and its a good pratice, add your own factsets by putting them in `spec/factsets/*.json`.
|
231
322
|
|
232
|
-
|
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
|
-
|
235
|
-
|
236
|
-
|
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
|
-
|
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
|
-
|
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
|
352
|
+
### Hiera
|
274
353
|
|
275
|
-
If you have hiera data inside your controlrepo (or somewhere else)
|
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.
|
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
|
-
###
|
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,
|
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
|
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
|
+
|
data/factsets/windows-10-64.json
CHANGED
@@ -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
|
-
|
84
|
-
|
85
|
-
|
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
|
data/features/windows.feature
CHANGED
@@ -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
|
+
|
data/features/zzz_run.feature
CHANGED
@@ -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
|
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
|
data/lib/onceover/controlrepo.rb
CHANGED
@@ -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
|
-
|
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 '
|
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
|
-
|
225
|
+
row = []
|
225
226
|
logger.debug "Loading data for #{mod.full_name}"
|
226
|
-
|
227
|
+
row << mod.full_name
|
227
228
|
if mod.is_a?(R10K::Module::Forge)
|
228
|
-
|
229
|
-
|
230
|
-
|
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
|
-
|
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
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
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 <<
|
254
|
+
output_array << row
|
252
255
|
end
|
253
256
|
end
|
254
257
|
|
255
258
|
threads.map(&:join)
|
256
259
|
|
257
|
-
|
258
|
-
|
259
|
-
|
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
|
-
|
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
|
data/lib/onceover/deploy.rb
CHANGED
@@ -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 <<
|
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
|
data/lib/onceover/group.rb
CHANGED
data/lib/onceover/runner.rb
CHANGED
@@ -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
|
28
|
-
|
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
|
-
|
87
|
-
|
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')
|
data/lib/onceover/test.rb
CHANGED
@@ -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']
|
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)
|
data/lib/onceover/testconfig.rb
CHANGED
@@ -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
|
-
|
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
|
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.
|
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 '
|
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
|
data/templates/test_spec.rb.erb
CHANGED
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.
|
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-
|
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:
|
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.
|
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.
|
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
|