onceover 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +6 -0
  4. data/Gemfile.lock +17 -0
  5. data/README.md +504 -0
  6. data/Rakefile +2 -0
  7. data/bin/onceover +17 -0
  8. data/controlrepo.gemspec +38 -0
  9. data/factsets/CentOS-5.11-32.json +263 -0
  10. data/factsets/CentOS-5.11-64.json +263 -0
  11. data/factsets/CentOS-6.6-32.json +305 -0
  12. data/factsets/CentOS-6.6-64.json +342 -0
  13. data/factsets/CentOS-7.0-64.json +352 -0
  14. data/factsets/Debian-6.0.10-32.json +322 -0
  15. data/factsets/Debian-6.0.10-64.json +322 -0
  16. data/factsets/Debian-7.8-32.json +338 -0
  17. data/factsets/Debian-7.8-64.json +338 -0
  18. data/factsets/Ubuntu-12.04-32.json +328 -0
  19. data/factsets/Ubuntu-12.04-64.json +328 -0
  20. data/factsets/Ubuntu-14.04-32.json +337 -0
  21. data/factsets/Ubuntu-14.04-64.json +373 -0
  22. data/factsets/Windows_Server-2008r2-64.json +183 -0
  23. data/factsets/Windows_Server-2012r2-64.json +164 -0
  24. data/lib/onceover/beaker.rb +225 -0
  25. data/lib/onceover/beaker/spec_helper.rb +70 -0
  26. data/lib/onceover/class.rb +29 -0
  27. data/lib/onceover/cli.rb +46 -0
  28. data/lib/onceover/cli/init.rb +31 -0
  29. data/lib/onceover/cli/run.rb +72 -0
  30. data/lib/onceover/cli/show.rb +74 -0
  31. data/lib/onceover/cli/update.rb +48 -0
  32. data/lib/onceover/controlrepo.rb +527 -0
  33. data/lib/onceover/group.rb +85 -0
  34. data/lib/onceover/logger.rb +31 -0
  35. data/lib/onceover/node.rb +44 -0
  36. data/lib/onceover/rake_tasks.rb +113 -0
  37. data/lib/onceover/runner.rb +90 -0
  38. data/lib/onceover/test.rb +157 -0
  39. data/lib/onceover/testconfig.rb +233 -0
  40. data/templates/.fixtures.yml.erb +24 -0
  41. data/templates/Rakefile.erb +6 -0
  42. data/templates/acceptance_test_spec.rb.erb +66 -0
  43. data/templates/controlrepo.yaml.erb +38 -0
  44. data/templates/factsets_README.md.erb +7 -0
  45. data/templates/nodeset.yaml.erb +12 -0
  46. data/templates/pre_conditions_README.md.erb +24 -0
  47. data/templates/spec_helper.rb.erb +16 -0
  48. data/templates/spec_helper_acceptance.rb.erb +1 -0
  49. data/templates/test_spec.rb.erb +34 -0
  50. metadata +345 -0
@@ -0,0 +1,164 @@
1
+ {
2
+ "name": "win-e5k8tm30719",
3
+ "values": {
4
+ "agent_specified_environment": "production",
5
+ "architecture": "x64",
6
+ "dhcp_servers": {
7
+ "Ethernet": "10.0.2.2",
8
+ "system": "10.0.2.2"
9
+ },
10
+ "dmi": {
11
+ "manufacturer": "innotek GmbH",
12
+ "product": {
13
+ "name": "VirtualBox",
14
+ "serial_number": "0"
15
+ }
16
+ },
17
+ "env_windows_installdir": "C:\\Program Files\\Puppet Labs\\Puppet",
18
+ "facterversion": "3.1.1",
19
+ "fqdn": "WIN-E5K8TM30719",
20
+ "hardwareisa": "x64",
21
+ "hardwaremodel": "x86_64",
22
+ "hostname": "WIN-E5K8TM30719",
23
+ "id": "WIN-E5K8TM30719\\vagrant",
24
+ "identity": {
25
+ "user": "WIN-E5K8TM30719\\vagrant"
26
+ },
27
+ "interfaces": "Ethernet",
28
+ "ipaddress": "10.0.2.15",
29
+ "ipaddress6": "fe80::a180:36e0:3a6e:1005%12",
30
+ "ipaddress6_Ethernet": "fe80::a180:36e0:3a6e:1005%12",
31
+ "ipaddress_Ethernet": "10.0.2.15",
32
+ "is_virtual": true,
33
+ "kernel": "windows",
34
+ "kernelmajversion": "6.3",
35
+ "kernelrelease": "6.3.9600",
36
+ "kernelversion": "6.3.9600",
37
+ "macaddress": "08:00:27:81:38:FA",
38
+ "macaddress_Ethernet": "08:00:27:81:38:FA",
39
+ "manufacturer": "innotek GmbH",
40
+ "memory": {
41
+ "system": {
42
+ "available": "1.42 GiB",
43
+ "available_bytes": 1521610752,
44
+ "capacity": "29.13%",
45
+ "total": "2.00 GiB",
46
+ "total_bytes": 2147012608,
47
+ "used": "596.43 MiB",
48
+ "used_bytes": 625401856
49
+ }
50
+ },
51
+ "memoryfree": "1.42 GiB",
52
+ "memoryfree_mb": 1451.12109375,
53
+ "memorysize": "2.00 GiB",
54
+ "memorysize_mb": 2047.55078125,
55
+ "mtu_Ethernet": 1500,
56
+ "netmask": "255.255.255.0",
57
+ "netmask6": "ffff:ffff:ffff:ffff::",
58
+ "netmask6_Ethernet": "ffff:ffff:ffff:ffff::",
59
+ "netmask_Ethernet": "255.255.255.0",
60
+ "network": "10.0.2.0",
61
+ "network6": "fe80::%12",
62
+ "network6_Ethernet": "fe80::%12",
63
+ "network_Ethernet": "10.0.2.0",
64
+ "networking": {
65
+ "dhcp": "10.0.2.2",
66
+ "fqdn": "WIN-E5K8TM30719",
67
+ "hostname": "WIN-E5K8TM30719",
68
+ "interfaces": {
69
+ "Ethernet": {
70
+ "bindings": [
71
+ {
72
+ "address": "10.0.2.15",
73
+ "netmask": "255.255.255.0",
74
+ "network": "10.0.2.0"
75
+ }
76
+ ],
77
+ "bindings6": [
78
+ {
79
+ "address": "fe80::a180:36e0:3a6e:1005%12",
80
+ "netmask": "ffff:ffff:ffff:ffff::",
81
+ "network": "fe80::%12"
82
+ }
83
+ ],
84
+ "dhcp": "10.0.2.2",
85
+ "ip": "10.0.2.15",
86
+ "ip6": "fe80::a180:36e0:3a6e:1005%12",
87
+ "mac": "08:00:27:81:38:FA",
88
+ "mtu": 1500,
89
+ "netmask": "255.255.255.0",
90
+ "netmask6": "ffff:ffff:ffff:ffff::",
91
+ "network": "10.0.2.0",
92
+ "network6": "fe80::%12"
93
+ }
94
+ },
95
+ "ip": "10.0.2.15",
96
+ "ip6": "fe80::a180:36e0:3a6e:1005%12",
97
+ "mac": "08:00:27:81:38:FA",
98
+ "mtu": 1500,
99
+ "netmask": "255.255.255.0",
100
+ "netmask6": "ffff:ffff:ffff:ffff::",
101
+ "network": "10.0.2.0",
102
+ "network6": "fe80::%12",
103
+ "primary": "Ethernet"
104
+ },
105
+ "operatingsystem": "windows",
106
+ "operatingsystemmajrelease": "2012 R2",
107
+ "operatingsystemrelease": "2012 R2",
108
+ "os": {
109
+ "architecture": "x64",
110
+ "family": "windows",
111
+ "hardware": "x86_64",
112
+ "name": "windows",
113
+ "release": {
114
+ "full": "2012 R2",
115
+ "major": "2012 R2"
116
+ },
117
+ "windows": {
118
+ "system32": "C:\\Windows\\system32"
119
+ }
120
+ },
121
+ "osfamily": "windows",
122
+ "path": "C:/Program Files/Puppet Labs/Puppet/facter/bin;C:\\Program Files\\Puppet Labs\\Puppet\\puppet\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\facter\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\hiera\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\mcollective\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\sys\\ruby\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\sys\\tools\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Git\\cmd;C:\\Program Files (x86)\\Git\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\bin",
123
+ "physicalprocessorcount": 1,
124
+ "processor0": "Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz",
125
+ "processorcount": 1,
126
+ "processors": {
127
+ "count": 1,
128
+ "isa": "x64",
129
+ "models": [
130
+ "Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz"
131
+ ],
132
+ "physicalcount": 1
133
+ },
134
+ "productname": "VirtualBox",
135
+ "puppetversion": "4.2.3",
136
+ "ruby": {
137
+ "platform": "x64-mingw32",
138
+ "sitedir": "C:/Program Files/Puppet Labs/Puppet/sys/ruby/lib/ruby/site_ruby/2.1.0",
139
+ "version": "2.1.7"
140
+ },
141
+ "rubyplatform": "x64-mingw32",
142
+ "rubysitedir": "C:/Program Files/Puppet Labs/Puppet/sys/ruby/lib/ruby/site_ruby/2.1.0",
143
+ "rubyversion": "2.1.7",
144
+ "serialnumber": "0",
145
+ "system32": "C:\\Windows\\system32",
146
+ "system_uptime": {
147
+ "days": 0,
148
+ "hours": 0,
149
+ "seconds": 287,
150
+ "uptime": "0:04 hours"
151
+ },
152
+ "timezone": "Coordinated Universal Time",
153
+ "uptime": "0:04 hours",
154
+ "uptime_days": 0,
155
+ "uptime_hours": 0,
156
+ "uptime_seconds": 287,
157
+ "virtual": "virtualbox",
158
+ "clientcert": "win-e5k8tm30719",
159
+ "clientversion": "4.2.3",
160
+ "clientnoop": false
161
+ },
162
+ "timestamp": "2015-11-19T01:47:05.215450000+00:00",
163
+ "expiration": "2015-11-19T02:17:05.215450000+00:00"
164
+ }
@@ -0,0 +1,225 @@
1
+ class Onceover
2
+ class Beaker
3
+ def self.facts_to_vagrant_box(facts)
4
+ # Gets the most similar vagrant box to the facts set provided, will accept a single fact
5
+ # se or an array
6
+
7
+ if facts.is_a?(Array)
8
+ returnval = []
9
+ facts.each do |fact|
10
+ returnval << self.facts_to_vagrant_box(fact)
11
+ end
12
+ return returnval
13
+ end
14
+
15
+ begin
16
+ if facts['os']['distro']['id'] == 'Ubuntu'
17
+ os = 'ubuntu'
18
+ version = facts['os']['distro']['release']['major']
19
+ end
20
+ rescue
21
+ # Do nothing, this is the easiest way to handle the hash bing in different formats
22
+ end
23
+
24
+ begin
25
+ if facts['os']['distro']['id'] == 'Debian'
26
+ os = 'Debian'
27
+ version = facts['os']['distro']['release']['full']
28
+ end
29
+ rescue
30
+ # Do nothing
31
+ end
32
+
33
+ begin
34
+ if facts['os']['family'] == "RedHat"
35
+ os = 'centos'
36
+ version = "#{facts['os']['release']['major']}.#{facts['os']['release']['minor']}"
37
+ end
38
+ rescue
39
+ # Do nothing
40
+ end
41
+
42
+ return "UNKNOWN" unless os.is_a?(String)
43
+
44
+ if facts['os']['architecture'] =~ /64/
45
+ arch = '64'
46
+ else
47
+ arch = '32'
48
+ end
49
+
50
+ "puppetlabs/#{os}-#{version}-#{arch}-puppet"
51
+ end
52
+
53
+ # This will take a fact set and return the beaker platform of that machine
54
+ # This is necissary as beaker needs the platform set up correctly to know which
55
+ # commands to run when we do stuff. Personally I would prefer beaker to detect the
56
+ # platform as it would not be that hard, especially once puppet is installed, oh well.
57
+ def self.facts_to_platform(facts)
58
+ if facts.is_a?(Array)
59
+ returnval = []
60
+ facts.each do |fact|
61
+ returnval << self.facts_to_platform(fact)
62
+ end
63
+ return returnval
64
+ end
65
+
66
+ begin
67
+ if facts['os']['family'] == 'RedHat'
68
+ platform = 'el'
69
+ version = facts['os']['release']['major']
70
+ end
71
+ rescue
72
+ # Do nothing, this is the easiest way to handle the hash being in different formats
73
+ end
74
+
75
+ begin
76
+ if facts['os']['distro']['id'] == 'Ubuntu'
77
+ platform = 'ubuntu'
78
+ version = facts['os']['distro']['release']['major']
79
+ end
80
+ rescue
81
+ # Do nothing, this is the easiest way to handle the hash being in different formats
82
+ end
83
+
84
+ begin
85
+ if facts['os']['distro']['id'] == 'Debian'
86
+ platform = 'debian'
87
+ version = facts['os']['distro']['release']['full']
88
+ end
89
+ rescue
90
+ # Do nothing
91
+ end
92
+
93
+ if facts['os']['architecture'] =~ /64/
94
+ arch = '64'
95
+ else
96
+ arch = '32'
97
+ end
98
+
99
+ "#{platform}-#{version}-#{arch}"
100
+ end
101
+
102
+ # This little method will deploy a Controlrepo object to a host, just using r10k deploy
103
+ def self.deploy_controlrepo_on(host, repo = Onceover::Controlrepo.new())
104
+ require 'beaker-rspec'
105
+ require 'onceover/controlrepo'
106
+
107
+ if host.is_a?(Array)
108
+ hosts.each do |single_host|
109
+ deploy_controlrepo_on(single_host)
110
+ end
111
+ end
112
+
113
+ # Use a beaker helper to do the install (*nix only)
114
+ install_r10k_on(host)
115
+
116
+ # Use beaker to install git
117
+ host.install_package('git')
118
+
119
+ # copy the file over to the host (Maybe I should be changing the directory here??)
120
+ scp_to(host,repo.r10k_config_file,'/tmp/r10k.yaml')
121
+
122
+ # Do an r10k deploy
123
+ r10k_deploy(host,{
124
+ :puppetfile => true,
125
+ :configfile => '/tmp/r10k.yaml',
126
+ })
127
+ end
128
+
129
+ # This actually provisions a node and checks that puppet will be able to run and
130
+ # be idempotent. It hacks the beaker NetworkManager object to do this. The reason
131
+ # is that beaker is designed to run in the following order:
132
+ # 1. Spin up nodes
133
+ # 2. Run all tests
134
+ # 3. Kill all nodes
135
+ #
136
+ # This is not helpful for us. We want to be able to test all of our classes on
137
+ # all of our nodes, this could be a lot of vms and having them all running at once
138
+ # would be a real kick in the dick for whatever system was running it.
139
+ def self.provision_and_test(host,puppet_class,opts = {},repo = Onceover::Controlrepo.new)
140
+ opts = {:runs_before_idempotency => 1}.merge(opts)
141
+ opts = {:check_idempotency => true}.merge(opts)
142
+ opts = {:deploy_controlrepo => true}.merge(opts)
143
+
144
+
145
+ raise "Hosts must be a single host object, not an array" if host.is_a?(Array)
146
+ raise "Class must be a single Class [String], not an array" unless puppet_class.is_a?(String)
147
+
148
+ # Create our own NWM object that we are going to interact with
149
+ # Note here that 'options', 'logger' and are exposed within the rspec tests
150
+ # if this is run outside of that context it will fail
151
+ network_manager = ::Beaker::NetworkManager.new(options,logger)
152
+
153
+ # Hack the network manager to smash our host in there without provisioning
154
+ network_manager.instance_variable_set(:@hosts,[host])
155
+
156
+ # Now that we have a working network manager object, we can provision, but only if
157
+ # we need to, ahhh smart...
158
+ unless host.up?
159
+ network_manager.provision
160
+ network_manager.proxy_package_manager
161
+ network_manager.validate
162
+ network_manager.configure
163
+ end
164
+
165
+ # Actually run the tests
166
+ manifest = "include #{puppet_class}"
167
+
168
+ opts[:runs_before_idempotency].times do
169
+ apply_manifest_on(host,manifest,{:catch_failures => true})
170
+ end
171
+
172
+ if opts[:check_idempotency]
173
+ apply_manifest_on(host,manifest,{:catch_changes => true})
174
+ end
175
+
176
+ network_manager.cleanup
177
+ end
178
+
179
+ def self.match_indentation(test,logger)
180
+ logger.line_prefix = ' ' * (test.metadata[:scoped_id].split(':').count - 1)
181
+ end
182
+
183
+ def self.host_create(name, nodes)
184
+ require 'beaker/network_manager'
185
+
186
+ current_opts = {}
187
+ nodes.each do |opt,val|
188
+ if opt == :HOSTS
189
+ val.each do |k,v|
190
+ if k == name
191
+ current_opts[:HOSTS] = {k => v}
192
+ end
193
+ end
194
+ else
195
+ current_opts[opt] = val
196
+ end
197
+ end
198
+
199
+ # I copied this code off the internet, basically it allows us
200
+ # to refer to each key as either a string or an object
201
+ current_opts.default_proc = proc do |h, k|
202
+ case k
203
+ when String then sym = k.to_sym; h[sym] if h.key?(sym)
204
+ when Symbol then str = k.to_s; h[str] if h.key?(str)
205
+ end
206
+ end
207
+
208
+ @nwm = ::Beaker::NetworkManager.new(current_opts,logger)
209
+ @nwm.provision
210
+ @nwm.proxy_package_manager
211
+ @nwm.validate
212
+ @nwm.configure
213
+
214
+ @nwm.instance_variable_get(:@hosts).each do |host|
215
+ host.instance_variable_set(:@nwm,@nwm)
216
+ host.define_singleton_method(:down!) do
217
+ @nwm.cleanup
218
+ end
219
+ end
220
+
221
+ raise "The networkmanager created too many machines! Only expecting one" if hosts.count > 1
222
+ @nwm.instance_variable_get(:@hosts)[0]
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,70 @@
1
+ # This has all been hacked out of the beaker-rspec gem. The reason I have
2
+ # hacked it out instead of just using it the way it was intended is that
3
+ # it is very stuck in its ways around how it spins up all the servers
4
+ # first, then goes ahead and runs the tests. Because I don't want to do this
5
+ # I have had to replicate MOST of the functionality, EXCEPT the stuff I don't
6
+ # want. This is annoying but as far as I can tell this is the only way to do
7
+ # it
8
+
9
+ require 'beaker'
10
+ require 'beaker-rspec/beaker_shim' # This overloads Rspec's methods and provides the interface between beaker and RSpec
11
+ require "beaker-rspec/helpers/serverspec"
12
+ include BeakerRSpec::BeakerShim
13
+ require 'onceover/beaker'
14
+
15
+ #scp_to hosts, '<%= repo.tempdir %>/etc', '/'
16
+
17
+ RSpec.configure do |c|
18
+ # Enable color
19
+ c.color = true
20
+ c.tty = true
21
+
22
+ # Readable test descriptions
23
+ c.formatter = :documentation
24
+
25
+ # Define persistant hosts setting
26
+ c.add_setting :hosts, :default => []
27
+ # Define persistant options setting
28
+ c.add_setting :options, :default => {}
29
+ # Define persistant metadata object
30
+ c.add_setting :metadata, :default => {}
31
+ # Define persistant logger object
32
+ c.add_setting :logger, :default => nil
33
+ # Define persistant default node
34
+ c.add_setting :default_node, :default => nil
35
+
36
+ #default option values
37
+ defaults = {
38
+ :nodeset => 'onceover-nodes',
39
+ }
40
+ #read env vars
41
+ env_vars = {
42
+ :color => ENV['BEAKER_color'] || ENV['RS_COLOR'],
43
+ :nodeset => ENV['BEAKER_set'] || ENV['RS_SET'],
44
+ :nodesetfile => ENV['BEAKER_setfile'] || ENV['RS_SETFILE'],
45
+ :provision => ENV['BEAKER_provision'] || ENV['RS_PROVISION'],
46
+ :keyfile => ENV['BEAKER_keyfile'] || ENV['RS_KEYFILE'],
47
+ :debug => ENV['BEAKER_debug'] || ENV['RS_DEBUG'],
48
+ :destroy => ENV['BEAKER_destroy'] || ENV['RS_DESTROY'],
49
+ }.delete_if {|key, value| value.nil?}
50
+ #combine defaults and env_vars to determine overall options
51
+ options = defaults.merge(env_vars)
52
+
53
+ # process options to construct beaker command string
54
+ nodesetfile = options[:nodesetfile] || File.join('spec/acceptance/nodesets',"#{options[:nodeset]}.yml")
55
+ fresh_nodes = options[:provision] == 'no' ? '--no-provision' : nil
56
+ keyfile = options[:keyfile] ? ['--keyfile', options[:keyfile]] : nil
57
+ debug = options[:debug] ? ['--log-level', 'debug'] : nil
58
+ color = options[:color] == 'no' ? ['--no-color'] : nil
59
+
60
+ # Configure all nodes in nodeset
61
+ c.setup([fresh_nodes, '--hosts', nodesetfile, keyfile, debug, color].flatten.compact)
62
+ #c.provision
63
+ #c.validate
64
+ #c.configure
65
+ end
66
+
67
+ # Set the number of lines it will print
68
+ options[:trace_limit] = 1000
69
+
70
+ OPTIONS = options