onceover 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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