inspec-core 2.3.10 → 2.3.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -13
  3. data/etc/plugin_filters.json +25 -0
  4. data/inspec-core.gemspec +1 -1
  5. data/lib/bundles/inspec-compliance/api.rb +3 -0
  6. data/lib/bundles/inspec-compliance/configuration.rb +3 -0
  7. data/lib/bundles/inspec-compliance/http.rb +3 -0
  8. data/lib/bundles/inspec-compliance/support.rb +3 -0
  9. data/lib/bundles/inspec-compliance/target.rb +3 -0
  10. data/lib/inspec/objects/attribute.rb +3 -0
  11. data/lib/inspec/plugin/v2.rb +3 -0
  12. data/lib/inspec/plugin/v2/filter.rb +62 -0
  13. data/lib/inspec/plugin/v2/installer.rb +21 -1
  14. data/lib/inspec/plugin/v2/loader.rb +4 -0
  15. data/lib/inspec/profile.rb +3 -1
  16. data/lib/inspec/version.rb +1 -1
  17. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +25 -3
  18. data/lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb +65 -11
  19. data/lib/plugins/inspec-plugin-manager-cli/test/unit/cli_args_test.rb +5 -1
  20. data/lib/resources/package.rb +1 -1
  21. metadata +4 -197
  22. data/docs/.gitignore +0 -2
  23. data/docs/README.md +0 -41
  24. data/docs/dev/control-eval.md +0 -62
  25. data/docs/dev/filtertable-internals.md +0 -353
  26. data/docs/dev/filtertable-usage.md +0 -533
  27. data/docs/dev/integration-testing.md +0 -31
  28. data/docs/dev/plugins.md +0 -323
  29. data/docs/dsl_inspec.md +0 -354
  30. data/docs/dsl_resource.md +0 -100
  31. data/docs/glossary.md +0 -381
  32. data/docs/habitat.md +0 -193
  33. data/docs/inspec_and_friends.md +0 -114
  34. data/docs/matchers.md +0 -161
  35. data/docs/migration.md +0 -293
  36. data/docs/platforms.md +0 -119
  37. data/docs/plugin_kitchen_inspec.md +0 -60
  38. data/docs/plugins.md +0 -57
  39. data/docs/profiles.md +0 -576
  40. data/docs/reporters.md +0 -170
  41. data/docs/resources/aide_conf.md.erb +0 -86
  42. data/docs/resources/apache.md.erb +0 -77
  43. data/docs/resources/apache_conf.md.erb +0 -78
  44. data/docs/resources/apt.md.erb +0 -81
  45. data/docs/resources/audit_policy.md.erb +0 -57
  46. data/docs/resources/auditd.md.erb +0 -89
  47. data/docs/resources/auditd_conf.md.erb +0 -78
  48. data/docs/resources/bash.md.erb +0 -85
  49. data/docs/resources/bond.md.erb +0 -100
  50. data/docs/resources/bridge.md.erb +0 -67
  51. data/docs/resources/bsd_service.md.erb +0 -77
  52. data/docs/resources/chocolatey_package.md.erb +0 -68
  53. data/docs/resources/command.md.erb +0 -176
  54. data/docs/resources/cpan.md.erb +0 -89
  55. data/docs/resources/cran.md.erb +0 -74
  56. data/docs/resources/crontab.md.erb +0 -103
  57. data/docs/resources/csv.md.erb +0 -64
  58. data/docs/resources/dh_params.md.erb +0 -221
  59. data/docs/resources/directory.md.erb +0 -40
  60. data/docs/resources/docker.md.erb +0 -240
  61. data/docs/resources/docker_container.md.erb +0 -113
  62. data/docs/resources/docker_image.md.erb +0 -104
  63. data/docs/resources/docker_plugin.md.erb +0 -80
  64. data/docs/resources/docker_service.md.erb +0 -124
  65. data/docs/resources/elasticsearch.md.erb +0 -252
  66. data/docs/resources/etc_fstab.md.erb +0 -135
  67. data/docs/resources/etc_group.md.erb +0 -85
  68. data/docs/resources/etc_hosts.md.erb +0 -88
  69. data/docs/resources/etc_hosts_allow.md.erb +0 -84
  70. data/docs/resources/etc_hosts_deny.md.erb +0 -84
  71. data/docs/resources/file.md.erb +0 -543
  72. data/docs/resources/filesystem.md.erb +0 -51
  73. data/docs/resources/firewalld.md.erb +0 -117
  74. data/docs/resources/gem.md.erb +0 -108
  75. data/docs/resources/group.md.erb +0 -71
  76. data/docs/resources/grub_conf.md.erb +0 -111
  77. data/docs/resources/host.md.erb +0 -96
  78. data/docs/resources/http.md.erb +0 -207
  79. data/docs/resources/iis_app.md.erb +0 -132
  80. data/docs/resources/iis_site.md.erb +0 -145
  81. data/docs/resources/inetd_conf.md.erb +0 -104
  82. data/docs/resources/ini.md.erb +0 -86
  83. data/docs/resources/interface.md.erb +0 -68
  84. data/docs/resources/iptables.md.erb +0 -74
  85. data/docs/resources/json.md.erb +0 -73
  86. data/docs/resources/kernel_module.md.erb +0 -130
  87. data/docs/resources/kernel_parameter.md.erb +0 -63
  88. data/docs/resources/key_rsa.md.erb +0 -95
  89. data/docs/resources/launchd_service.md.erb +0 -67
  90. data/docs/resources/limits_conf.md.erb +0 -85
  91. data/docs/resources/login_defs.md.erb +0 -81
  92. data/docs/resources/mount.md.erb +0 -79
  93. data/docs/resources/mssql_session.md.erb +0 -78
  94. data/docs/resources/mysql_conf.md.erb +0 -109
  95. data/docs/resources/mysql_session.md.erb +0 -84
  96. data/docs/resources/nginx.md.erb +0 -89
  97. data/docs/resources/nginx_conf.md.erb +0 -148
  98. data/docs/resources/npm.md.erb +0 -78
  99. data/docs/resources/ntp_conf.md.erb +0 -70
  100. data/docs/resources/oneget.md.erb +0 -63
  101. data/docs/resources/oracledb_session.md.erb +0 -103
  102. data/docs/resources/os.md.erb +0 -153
  103. data/docs/resources/os_env.md.erb +0 -101
  104. data/docs/resources/package.md.erb +0 -130
  105. data/docs/resources/packages.md.erb +0 -77
  106. data/docs/resources/parse_config.md.erb +0 -113
  107. data/docs/resources/parse_config_file.md.erb +0 -148
  108. data/docs/resources/passwd.md.erb +0 -151
  109. data/docs/resources/pip.md.erb +0 -77
  110. data/docs/resources/port.md.erb +0 -147
  111. data/docs/resources/postgres_conf.md.erb +0 -89
  112. data/docs/resources/postgres_hba_conf.md.erb +0 -103
  113. data/docs/resources/postgres_ident_conf.md.erb +0 -86
  114. data/docs/resources/postgres_session.md.erb +0 -79
  115. data/docs/resources/powershell.md.erb +0 -112
  116. data/docs/resources/processes.md.erb +0 -119
  117. data/docs/resources/rabbitmq_config.md.erb +0 -51
  118. data/docs/resources/registry_key.md.erb +0 -197
  119. data/docs/resources/runit_service.md.erb +0 -67
  120. data/docs/resources/security_policy.md.erb +0 -57
  121. data/docs/resources/service.md.erb +0 -131
  122. data/docs/resources/shadow.md.erb +0 -267
  123. data/docs/resources/ssh_config.md.erb +0 -83
  124. data/docs/resources/sshd_config.md.erb +0 -93
  125. data/docs/resources/ssl.md.erb +0 -129
  126. data/docs/resources/sys_info.md.erb +0 -52
  127. data/docs/resources/systemd_service.md.erb +0 -67
  128. data/docs/resources/sysv_service.md.erb +0 -67
  129. data/docs/resources/upstart_service.md.erb +0 -67
  130. data/docs/resources/user.md.erb +0 -150
  131. data/docs/resources/users.md.erb +0 -137
  132. data/docs/resources/vbscript.md.erb +0 -65
  133. data/docs/resources/virtualization.md.erb +0 -67
  134. data/docs/resources/windows_feature.md.erb +0 -69
  135. data/docs/resources/windows_hotfix.md.erb +0 -63
  136. data/docs/resources/windows_task.md.erb +0 -95
  137. data/docs/resources/wmi.md.erb +0 -91
  138. data/docs/resources/x509_certificate.md.erb +0 -161
  139. data/docs/resources/xinetd_conf.md.erb +0 -166
  140. data/docs/resources/xml.md.erb +0 -95
  141. data/docs/resources/yaml.md.erb +0 -79
  142. data/docs/resources/yum.md.erb +0 -108
  143. data/docs/resources/zfs_dataset.md.erb +0 -63
  144. data/docs/resources/zfs_pool.md.erb +0 -57
  145. data/docs/shared/matcher_be.md.erb +0 -1
  146. data/docs/shared/matcher_cmp.md.erb +0 -43
  147. data/docs/shared/matcher_eq.md.erb +0 -3
  148. data/docs/shared/matcher_include.md.erb +0 -1
  149. data/docs/shared/matcher_match.md.erb +0 -1
  150. data/docs/shell.md +0 -217
  151. data/docs/style.md +0 -178
  152. data/examples/README.md +0 -8
  153. data/examples/custom-resource/README.md +0 -3
  154. data/examples/custom-resource/controls/example.rb +0 -7
  155. data/examples/custom-resource/inspec.yml +0 -8
  156. data/examples/custom-resource/libraries/batsignal.rb +0 -20
  157. data/examples/custom-resource/libraries/gordon.rb +0 -21
  158. data/examples/inheritance/README.md +0 -65
  159. data/examples/inheritance/controls/example.rb +0 -14
  160. data/examples/inheritance/inspec.yml +0 -16
  161. data/examples/kitchen-ansible/.kitchen.yml +0 -25
  162. data/examples/kitchen-ansible/Gemfile +0 -19
  163. data/examples/kitchen-ansible/README.md +0 -53
  164. data/examples/kitchen-ansible/files/nginx.repo +0 -6
  165. data/examples/kitchen-ansible/tasks/main.yml +0 -16
  166. data/examples/kitchen-ansible/test/integration/default/default.yml +0 -5
  167. data/examples/kitchen-ansible/test/integration/default/web_spec.rb +0 -28
  168. data/examples/kitchen-chef/.kitchen.yml +0 -20
  169. data/examples/kitchen-chef/Berksfile +0 -3
  170. data/examples/kitchen-chef/Gemfile +0 -19
  171. data/examples/kitchen-chef/README.md +0 -27
  172. data/examples/kitchen-chef/metadata.rb +0 -7
  173. data/examples/kitchen-chef/recipes/default.rb +0 -6
  174. data/examples/kitchen-chef/recipes/nginx.rb +0 -30
  175. data/examples/kitchen-chef/test/integration/default/web_spec.rb +0 -28
  176. data/examples/kitchen-puppet/.kitchen.yml +0 -23
  177. data/examples/kitchen-puppet/Gemfile +0 -20
  178. data/examples/kitchen-puppet/Puppetfile +0 -25
  179. data/examples/kitchen-puppet/README.md +0 -53
  180. data/examples/kitchen-puppet/manifests/site.pp +0 -33
  181. data/examples/kitchen-puppet/metadata.json +0 -11
  182. data/examples/kitchen-puppet/modules/.gitkeep +0 -0
  183. data/examples/kitchen-puppet/test/integration/default/web_spec.rb +0 -28
  184. data/examples/meta-profile/README.md +0 -37
  185. data/examples/meta-profile/controls/example.rb +0 -13
  186. data/examples/meta-profile/inspec.yml +0 -13
  187. data/examples/plugins/inspec-resource-lister/Gemfile +0 -12
  188. data/examples/plugins/inspec-resource-lister/LICENSE +0 -13
  189. data/examples/plugins/inspec-resource-lister/README.md +0 -62
  190. data/examples/plugins/inspec-resource-lister/Rakefile +0 -40
  191. data/examples/plugins/inspec-resource-lister/inspec-resource-lister.gemspec +0 -45
  192. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister.rb +0 -16
  193. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/cli_command.rb +0 -70
  194. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/plugin.rb +0 -55
  195. data/examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/version.rb +0 -10
  196. data/examples/plugins/inspec-resource-lister/test/fixtures/README.md +0 -24
  197. data/examples/plugins/inspec-resource-lister/test/functional/README.md +0 -18
  198. data/examples/plugins/inspec-resource-lister/test/functional/inspec_resource_lister_test.rb +0 -110
  199. data/examples/plugins/inspec-resource-lister/test/helper.rb +0 -26
  200. data/examples/plugins/inspec-resource-lister/test/unit/README.md +0 -17
  201. data/examples/plugins/inspec-resource-lister/test/unit/cli_args_test.rb +0 -64
  202. data/examples/plugins/inspec-resource-lister/test/unit/plugin_def_test.rb +0 -51
  203. data/examples/profile-attribute.yml +0 -2
  204. data/examples/profile-attribute/README.md +0 -14
  205. data/examples/profile-attribute/controls/example.rb +0 -11
  206. data/examples/profile-attribute/inspec.yml +0 -8
  207. data/examples/profile-sensitive/README.md +0 -29
  208. data/examples/profile-sensitive/controls/sensitive-failures.rb +0 -9
  209. data/examples/profile-sensitive/controls/sensitive.rb +0 -9
  210. data/examples/profile-sensitive/inspec.yml +0 -8
  211. data/examples/profile/README.md +0 -48
  212. data/examples/profile/controls/example.rb +0 -24
  213. data/examples/profile/controls/gordon.rb +0 -36
  214. data/examples/profile/controls/meta.rb +0 -36
  215. data/examples/profile/inspec.yml +0 -11
  216. data/examples/profile/libraries/gordon_config.rb +0 -59
@@ -26,7 +26,7 @@ class PluginManagerCliOptions < MiniTest::Test
26
26
 
27
27
  def test_search_args
28
28
  arg_config = cli_class.all_commands['search'].options
29
- assert_equal 2, arg_config.count, 'The search command should have 2 options'
29
+ assert_equal 3, arg_config.count, 'The search command should have 3 options'
30
30
 
31
31
  assert_includes arg_config.keys, :all, 'The search command should have an --all option'
32
32
  assert_equal :boolean, arg_config[:all].type, 'The --all option should be boolean'
@@ -40,6 +40,10 @@ class PluginManagerCliOptions < MiniTest::Test
40
40
  refute_nil arg_config[:exact].description, 'The --exact option should have a description'
41
41
  refute arg_config[:exact].required, 'The --exact option should not be required'
42
42
 
43
+ assert_includes arg_config.keys, :'include-test-fixture', 'The search command should have an --include-test-fixture option'
44
+ assert_equal :boolean, arg_config[:'include-test-fixture'].type, 'The --include-test-fixture option should be boolean'
45
+ refute arg_config[:'include-test-fixture'].required, 'The --include-test-fixture option should not be required'
46
+
43
47
  assert_equal 1, cli_class.instance_method(:search).arity, 'The search command should take one argument'
44
48
  end
45
49
 
@@ -258,7 +258,7 @@ module Inspec::Resources
258
258
  cmd = inspec.command("apk info -vv --no-network | grep #{package_name}")
259
259
  return {} if cmd.exit_status.to_i != 0
260
260
 
261
- pkg_info = cmd.stdout.split("\n").reject! { |e| e =~ /^WARNING/i }
261
+ pkg_info = cmd.stdout.split("\n").delete_if { |e| e =~ /^WARNING/i }
262
262
  pkg = pkg_info[0].split(' - ')[0]
263
263
 
264
264
  {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.10
4
+ version: 2.3.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-04 00:00:00.000000000 Z
11
+ date: 2018-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train-core
@@ -297,201 +297,7 @@ files:
297
297
  - MAINTAINERS.toml
298
298
  - README.md
299
299
  - bin/inspec
300
- - docs/.gitignore
301
- - docs/README.md
302
- - docs/dev/control-eval.md
303
- - docs/dev/filtertable-internals.md
304
- - docs/dev/filtertable-usage.md
305
- - docs/dev/integration-testing.md
306
- - docs/dev/plugins.md
307
- - docs/dsl_inspec.md
308
- - docs/dsl_resource.md
309
- - docs/glossary.md
310
- - docs/habitat.md
311
- - docs/inspec_and_friends.md
312
- - docs/matchers.md
313
- - docs/migration.md
314
- - docs/platforms.md
315
- - docs/plugin_kitchen_inspec.md
316
- - docs/plugins.md
317
- - docs/profiles.md
318
- - docs/reporters.md
319
- - docs/resources/aide_conf.md.erb
320
- - docs/resources/apache.md.erb
321
- - docs/resources/apache_conf.md.erb
322
- - docs/resources/apt.md.erb
323
- - docs/resources/audit_policy.md.erb
324
- - docs/resources/auditd.md.erb
325
- - docs/resources/auditd_conf.md.erb
326
- - docs/resources/bash.md.erb
327
- - docs/resources/bond.md.erb
328
- - docs/resources/bridge.md.erb
329
- - docs/resources/bsd_service.md.erb
330
- - docs/resources/chocolatey_package.md.erb
331
- - docs/resources/command.md.erb
332
- - docs/resources/cpan.md.erb
333
- - docs/resources/cran.md.erb
334
- - docs/resources/crontab.md.erb
335
- - docs/resources/csv.md.erb
336
- - docs/resources/dh_params.md.erb
337
- - docs/resources/directory.md.erb
338
- - docs/resources/docker.md.erb
339
- - docs/resources/docker_container.md.erb
340
- - docs/resources/docker_image.md.erb
341
- - docs/resources/docker_plugin.md.erb
342
- - docs/resources/docker_service.md.erb
343
- - docs/resources/elasticsearch.md.erb
344
- - docs/resources/etc_fstab.md.erb
345
- - docs/resources/etc_group.md.erb
346
- - docs/resources/etc_hosts.md.erb
347
- - docs/resources/etc_hosts_allow.md.erb
348
- - docs/resources/etc_hosts_deny.md.erb
349
- - docs/resources/file.md.erb
350
- - docs/resources/filesystem.md.erb
351
- - docs/resources/firewalld.md.erb
352
- - docs/resources/gem.md.erb
353
- - docs/resources/group.md.erb
354
- - docs/resources/grub_conf.md.erb
355
- - docs/resources/host.md.erb
356
- - docs/resources/http.md.erb
357
- - docs/resources/iis_app.md.erb
358
- - docs/resources/iis_site.md.erb
359
- - docs/resources/inetd_conf.md.erb
360
- - docs/resources/ini.md.erb
361
- - docs/resources/interface.md.erb
362
- - docs/resources/iptables.md.erb
363
- - docs/resources/json.md.erb
364
- - docs/resources/kernel_module.md.erb
365
- - docs/resources/kernel_parameter.md.erb
366
- - docs/resources/key_rsa.md.erb
367
- - docs/resources/launchd_service.md.erb
368
- - docs/resources/limits_conf.md.erb
369
- - docs/resources/login_defs.md.erb
370
- - docs/resources/mount.md.erb
371
- - docs/resources/mssql_session.md.erb
372
- - docs/resources/mysql_conf.md.erb
373
- - docs/resources/mysql_session.md.erb
374
- - docs/resources/nginx.md.erb
375
- - docs/resources/nginx_conf.md.erb
376
- - docs/resources/npm.md.erb
377
- - docs/resources/ntp_conf.md.erb
378
- - docs/resources/oneget.md.erb
379
- - docs/resources/oracledb_session.md.erb
380
- - docs/resources/os.md.erb
381
- - docs/resources/os_env.md.erb
382
- - docs/resources/package.md.erb
383
- - docs/resources/packages.md.erb
384
- - docs/resources/parse_config.md.erb
385
- - docs/resources/parse_config_file.md.erb
386
- - docs/resources/passwd.md.erb
387
- - docs/resources/pip.md.erb
388
- - docs/resources/port.md.erb
389
- - docs/resources/postgres_conf.md.erb
390
- - docs/resources/postgres_hba_conf.md.erb
391
- - docs/resources/postgres_ident_conf.md.erb
392
- - docs/resources/postgres_session.md.erb
393
- - docs/resources/powershell.md.erb
394
- - docs/resources/processes.md.erb
395
- - docs/resources/rabbitmq_config.md.erb
396
- - docs/resources/registry_key.md.erb
397
- - docs/resources/runit_service.md.erb
398
- - docs/resources/security_policy.md.erb
399
- - docs/resources/service.md.erb
400
- - docs/resources/shadow.md.erb
401
- - docs/resources/ssh_config.md.erb
402
- - docs/resources/sshd_config.md.erb
403
- - docs/resources/ssl.md.erb
404
- - docs/resources/sys_info.md.erb
405
- - docs/resources/systemd_service.md.erb
406
- - docs/resources/sysv_service.md.erb
407
- - docs/resources/upstart_service.md.erb
408
- - docs/resources/user.md.erb
409
- - docs/resources/users.md.erb
410
- - docs/resources/vbscript.md.erb
411
- - docs/resources/virtualization.md.erb
412
- - docs/resources/windows_feature.md.erb
413
- - docs/resources/windows_hotfix.md.erb
414
- - docs/resources/windows_task.md.erb
415
- - docs/resources/wmi.md.erb
416
- - docs/resources/x509_certificate.md.erb
417
- - docs/resources/xinetd_conf.md.erb
418
- - docs/resources/xml.md.erb
419
- - docs/resources/yaml.md.erb
420
- - docs/resources/yum.md.erb
421
- - docs/resources/zfs_dataset.md.erb
422
- - docs/resources/zfs_pool.md.erb
423
- - docs/shared/matcher_be.md.erb
424
- - docs/shared/matcher_cmp.md.erb
425
- - docs/shared/matcher_eq.md.erb
426
- - docs/shared/matcher_include.md.erb
427
- - docs/shared/matcher_match.md.erb
428
- - docs/shell.md
429
- - docs/style.md
430
- - examples/README.md
431
- - examples/custom-resource/README.md
432
- - examples/custom-resource/controls/example.rb
433
- - examples/custom-resource/inspec.yml
434
- - examples/custom-resource/libraries/batsignal.rb
435
- - examples/custom-resource/libraries/gordon.rb
436
- - examples/inheritance/README.md
437
- - examples/inheritance/controls/example.rb
438
- - examples/inheritance/inspec.yml
439
- - examples/kitchen-ansible/.kitchen.yml
440
- - examples/kitchen-ansible/Gemfile
441
- - examples/kitchen-ansible/README.md
442
- - examples/kitchen-ansible/files/nginx.repo
443
- - examples/kitchen-ansible/tasks/main.yml
444
- - examples/kitchen-ansible/test/integration/default/default.yml
445
- - examples/kitchen-ansible/test/integration/default/web_spec.rb
446
- - examples/kitchen-chef/.kitchen.yml
447
- - examples/kitchen-chef/Berksfile
448
- - examples/kitchen-chef/Gemfile
449
- - examples/kitchen-chef/README.md
450
- - examples/kitchen-chef/metadata.rb
451
- - examples/kitchen-chef/recipes/default.rb
452
- - examples/kitchen-chef/recipes/nginx.rb
453
- - examples/kitchen-chef/test/integration/default/web_spec.rb
454
- - examples/kitchen-puppet/.kitchen.yml
455
- - examples/kitchen-puppet/Gemfile
456
- - examples/kitchen-puppet/Puppetfile
457
- - examples/kitchen-puppet/README.md
458
- - examples/kitchen-puppet/manifests/site.pp
459
- - examples/kitchen-puppet/metadata.json
460
- - examples/kitchen-puppet/modules/.gitkeep
461
- - examples/kitchen-puppet/test/integration/default/web_spec.rb
462
- - examples/meta-profile/README.md
463
- - examples/meta-profile/controls/example.rb
464
- - examples/meta-profile/inspec.yml
465
- - examples/plugins/inspec-resource-lister/Gemfile
466
- - examples/plugins/inspec-resource-lister/LICENSE
467
- - examples/plugins/inspec-resource-lister/README.md
468
- - examples/plugins/inspec-resource-lister/Rakefile
469
- - examples/plugins/inspec-resource-lister/inspec-resource-lister.gemspec
470
- - examples/plugins/inspec-resource-lister/lib/inspec-resource-lister.rb
471
- - examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/cli_command.rb
472
- - examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/plugin.rb
473
- - examples/plugins/inspec-resource-lister/lib/inspec-resource-lister/version.rb
474
- - examples/plugins/inspec-resource-lister/test/fixtures/README.md
475
- - examples/plugins/inspec-resource-lister/test/functional/README.md
476
- - examples/plugins/inspec-resource-lister/test/functional/inspec_resource_lister_test.rb
477
- - examples/plugins/inspec-resource-lister/test/helper.rb
478
- - examples/plugins/inspec-resource-lister/test/unit/README.md
479
- - examples/plugins/inspec-resource-lister/test/unit/cli_args_test.rb
480
- - examples/plugins/inspec-resource-lister/test/unit/plugin_def_test.rb
481
- - examples/profile-attribute.yml
482
- - examples/profile-attribute/README.md
483
- - examples/profile-attribute/controls/example.rb
484
- - examples/profile-attribute/inspec.yml
485
- - examples/profile-sensitive/README.md
486
- - examples/profile-sensitive/controls/sensitive-failures.rb
487
- - examples/profile-sensitive/controls/sensitive.rb
488
- - examples/profile-sensitive/inspec.yml
489
- - examples/profile/README.md
490
- - examples/profile/controls/example.rb
491
- - examples/profile/controls/gordon.rb
492
- - examples/profile/controls/meta.rb
493
- - examples/profile/inspec.yml
494
- - examples/profile/libraries/gordon_config.rb
300
+ - etc/plugin_filters.json
495
301
  - inspec-core.gemspec
496
302
  - lib/bundles/README.md
497
303
  - lib/bundles/inspec-compliance/api.rb
@@ -565,6 +371,7 @@ files:
565
371
  - lib/inspec/plugin/v1/registry.rb
566
372
  - lib/inspec/plugin/v2.rb
567
373
  - lib/inspec/plugin/v2/activator.rb
374
+ - lib/inspec/plugin/v2/filter.rb
568
375
  - lib/inspec/plugin/v2/installer.rb
569
376
  - lib/inspec/plugin/v2/loader.rb
570
377
  - lib/inspec/plugin/v2/plugin_base.rb
data/docs/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- resources.md
2
- cli.md
data/docs/README.md DELETED
@@ -1,41 +0,0 @@
1
- # InSpec documentation
2
-
3
- This is the home of the InSpec documentation. This documentation provides an introduction to this mechanism and shows how to write custom tests.
4
-
5
- The goal of this folder is for any community member to clone these docs, make the changes, check if they are valid, and contribute to the project.
6
-
7
- ## How to build docs
8
-
9
- We build docs by:
10
-
11
- 1. Auto-generating docs from code
12
- 2. Transforming markdown+snippets in this folder into pure markdown in `www/source/docs`
13
- 3. Rendering them to the website via instructions in `www/`
14
-
15
- For development, you **only need step 1**!
16
-
17
- **1 Generate docs**
18
-
19
- To generate all docs run:
20
-
21
- ```
22
- bundle exec rake docs
23
- ```
24
-
25
- You can run tasks individually. For a list of tasks run:
26
-
27
- ```
28
- bundle exec rake --tasks docs
29
- ```
30
-
31
- ## Stability Index
32
-
33
- Every available InSpec resource will indicate its stability. As InSpec matures, certain parts are more reliable than others. Brand new features are likely to be redesigned and marked as such.
34
-
35
- The stability indices are as follows:
36
-
37
- * `Stability: Deprecated` - This features will be removed in future versions, because its known for being problematic. Do not rely on it.
38
- * `Stability: Experimental` - New features may change or are removed in future versions
39
- * `Stability: Stable` - API is well established and proofed. Maintaining compatibility is a high priority
40
- * `Stability: Locked` - Only security and performance fixes are allowed
41
-
@@ -1,62 +0,0 @@
1
- # What happens when a profile file is loaded
2
-
3
- ## Consult with Harry Tuttle
4
-
5
- [He's not from Central Services or anything.](https://youtu.be/VRfoIyx8KfU?t=2m41s)
6
-
7
- ## Tips
8
-
9
- * In the early days of InSpec / ServerSpec, controls were called "rules". Throughout various places in the code, the word "rule" is used to mean "control". Make the mental subsitution.
10
- * InSpec supports reading profiles from tarballs, local files, git repos, etc. So, don't count on local file reading; instead it uses a special source reader to obtain the contents of the files.
11
-
12
- ## The basics of the stack
13
-
14
- #5 Inspec::Profile.collect_tests(include_list#Array) at lib/inspec/profile.rb:167
15
- #4 Hash.each at lib/inspec/profile.rb:167
16
- #3 block in Inspec::Profile.block in collect_tests(include_list#Array) at lib/inspec/profile.rb:170
17
- #2 Inspec::ProfileContext.load_control_file(*args#Array) at lib/inspec/profile_context.rb:141
18
- #1 Inspec::ProfileContext.control_eval_context at lib/inspec/profile_context.rb:58
19
- #0 #<Class:Inspec::ControlEvalContext>.create(profile_context#Inspec::ProfileContext, resources_dsl#Module) at lib/inspec/control_eval_context.rb:41
20
-
21
- ## A profile context is created
22
-
23
- Like many things in InSpec core, a profile context is an anonymous class. (verify)
24
-
25
- Additionally, a control_eval_context is created. It is an instance of an anonymous class; it has a class<->relationship with its profile context. See `lib/inspec/control_eval_context.rb`.
26
-
27
- ## Each file's contents are instance eval'd against the control_eval_context
28
-
29
- ### DSL methods are executed at this time
30
-
31
- So, if you have a control file with `title` in it, that will call the title method that was defined at `lib/inspec/control_eval_context.rb:60`. Importantly, this also includes the `control` DSL keyword, and also the `describe` keyword (used for bare describes).
32
-
33
- ### Each control and their block are wrapped in an anonymous class
34
-
35
- The anonymous class generator is located at `lib/inspec/control_eval_context.rb:24`. At this point, the terminology switches from `control` to `rule`. Each context class inherits from Inspec::Rule, which provides the constructor.
36
-
37
- The control context class also gets extended with the resource DSL, so anything in the source code for the control can use the resource DSL. This includes all resource names, but importantly, the `describe` DSL keyword.
38
-
39
- Finally, Inspec::Rule provides the control DSL - impact, title, desc, ref, and tags.
40
-
41
- ### The block is instance_eval'd against the control context class
42
-
43
- See `lib/inspec/rule.rb:50`. We're now in two levels of instance eval'ing - the file is gradually being eval'd against the profile context anonymous class, and the current control's block is being instance eval'd against a control context anonymous class.
44
-
45
- At this stage, control-level metadata (impact, title, refs, tags, desc) are evaluated and set as instance vars on the control.
46
-
47
- Any "loose" ruby in the control is also executed at this point.
48
-
49
- And, the describe and describe.one blocks are executed.
50
-
51
- ### TODO: describe blocks are *not* instance-evaled
52
-
53
- ### The control is registered with the profile
54
-
55
- Using the method register_control (dynamically defined on the control eval context), we check for various skip conditions. If none of them apply, the control is then registered with the profile context using register_rule.
56
-
57
- ProfileContext.register_rule's main job is to determine the full ID of the control (within the context of the profile) and either add it to the controls list, or (if another control with the same ID exists), merge it. (This is where overriding happens).
58
-
59
- Note: can skip a control with:
60
- Inspec::Rule.set_skip_rule(control, msg)
61
-
62
- ## What else?
@@ -1,353 +0,0 @@
1
- # Internals of FilterTable
2
-
3
- If you just want to _use_ FilterTable, see filtertable-usage.md . Reading this may make you more confused, not less.
4
-
5
- ## What makes this hard?
6
-
7
- FilterTable was created in 2016 in an attempt to consolidate the pluralization features of several resources. They each had slightly different feature-sets, and were all in the wild, so FilterTable exposes some extensive side-effects to provide those features.
8
-
9
- Additionally, the ways in which the classes relate is not straightforward.
10
-
11
- ## Where is the code?
12
-
13
- The main FilterTable code is in [utils/filter.rb](https://github.com/chef/inspec/blob/master/lib/utils/filter.rb).
14
-
15
- Also educational is the unit test for Filtertable, at test/unit/utils/filter_table_test.rb . Recent work has focused on using functional tests to exercise FilterTable; see test/unit/mocks/profiles/filter_table and test/functional/filter_table_test.rb .
16
-
17
- The file utils/filter_array.rb appears to be unrelated.
18
-
19
- ## What are the classes involved?
20
-
21
- ### FilterTable::Factory
22
-
23
- This class is responsible for the definition of the filtertable. It provides the methods that are used by the resource author to configure the filtertable.
24
-
25
- FilterTable::Factory initializes three instance variables:
26
- ```
27
- @filter_methods = []
28
- @custom_properties = {}
29
- @resource = nil # This appears to be unused
30
- ```
31
-
32
- ### FilterTable::Table
33
-
34
- This is the actual innards of the implementation. The Factory's goal is to configure a Table subclass and attach it to the resource you are authoring. The table is a container for the raw data your resource provides, and performs filtration services.
35
-
36
- ### FilterTable::ExceptionCatcher
37
-
38
- TODO
39
-
40
- ## What are the major entry points? (FilterTable::Factory)
41
-
42
- A resource class using FilterTable typically will call a sequence similar to this, in the class body:
43
-
44
- ```
45
- filter = FilterTable.create
46
- .register_column(:thing_ids, field: :thing_id)
47
- .install_filter_methods_on_resource(self, :table)
48
- ```
49
-
50
- Legacy code might look like this:
51
- ```
52
- filter = FilterTable.create
53
- filter.add_accessor(:entries)
54
- .add(:exists?) { |x| !x.entries.empty? }
55
- .add(:count) { |x| x.entries.count }
56
- .add(:thing_ids, field: :thing_id)
57
- .connect(self, :table)
58
- ```
59
-
60
- ### create
61
-
62
- Returns a blank instance of a FilterTable::Factory. It also adds a default implementation of `where` `raw_data`, and `entries` using `register_filter_method`, `count` using `register_custom_property`, and `exist?` using `register_custom_matcher`.
63
-
64
- ### register\_filter\_method
65
-
66
- Legacy name (alias): `add_accessor`
67
-
68
- This simply pushes the provided method name onto the `@filter_methods` instance variable array. See "filter_method" behavior section below for what this does.
69
-
70
- After adding the method name to the array, it returns `self` - the FilterTable::Factory instance - so that method chaining will work.
71
-
72
- ### register\_column
73
-
74
- Legacy name (alias): `add`
75
-
76
- This is currently simply an alias for `register_custom_property`. See it for details. By calling it with a distinctive name, we'll be able to add functionality in the future (especially around introspection).
77
-
78
- ### register\_custom\_matcher
79
-
80
- Legacy name (alias): `add`
81
-
82
- This is currently simply an alias for `register_custom_property`. See it for details. By calling it with a distinctive name, we'll be able to add functionality in the future (especially around introspection).
83
-
84
- ### register\_custom\_property
85
-
86
- Legacy name (alias): `add`
87
-
88
- This method has very complex behavior, ans should likely be split into several use cases. `register_custom_property` requires a symbol (which will be used as a method name _to be added to the resource class_), then also accepts a block and/or additional args. These things - name, block, and opts - are packed into a simple Struct called a CustomPropertyType. The name stored in the Struct will be `opts[:field]` if provided, and the method name if not.
89
-
90
- The CustomPropertyType Struct is then appended to the Hash `@custom_properties`, keyed on the method name provided. `self` is then returned for method chaining.
91
-
92
- The implementation of the custom property method is generated by `create_custom_property_body`, and varies based on whether a block was provided to `register_custom_property`.
93
-
94
- #### Behavior when a block is provided
95
-
96
- This behavior is implemented by lines 398-404.
97
-
98
- If a block is provided, it is turned into a Lambda and used as the method body.
99
-
100
- The block will be provided two arguments (though most users only use the first):
101
- 1. The FilterTable::Table instance that wraps the raw data.
102
- 2. An optional value used as an additional opportunity to filter.
103
-
104
- For example, this is common in legacy code:
105
- ```
106
- filter.add(:exists?) { |x| !x.entries.empty? }
107
- ```
108
-
109
- Here, `x` is the Table instance, which exposes the `entries` method (which returns an array, one entry for each raw data row).
110
-
111
- You could also implement a more sophisticated property, which semantically should re-filter the table based on the candidate value, and return the new table.
112
-
113
- ```
114
- filter.add(:smaller_than) { |table, threshold| table.where { some_field <= threshold } }
115
- ```
116
-
117
- ```
118
- things.smaller_than(12)
119
- ```
120
-
121
- If you provide _both_ a block and opts, only the block is used, and the options are ignored.
122
-
123
- #### Behavior when no block is provided
124
-
125
- If you do not provide a block, you _must_ provide a `:field` option (though that does no appear to be enforced). The behavior is to define a method with the name provided, that has a conditional return type. The method body is defined in lines 306-423.
126
-
127
- If called without arguments, it returns an array of the values in the raw data for that column.
128
- ```
129
- things.thing_ids => [1,2,3,4]
130
- ```
131
-
132
- If called with an argument, it instead calls `where` passing the name of the field and the argument, effectively filtering.
133
- ```
134
- things.thing_ids(2) => FilterTable::Table that only contains a row where thing_id = 2
135
- ```
136
-
137
- If called with a block, it passes the block to where.
138
- ```
139
- things.thing_ids { some_code } => Same as things.where { some_code }
140
- ```
141
-
142
- POSSIBLE BUG: I think this case is broken; it certainly seems ill-advised.
143
-
144
- #### Known Options
145
-
146
- You can provide options to `register_custom_property` / `add`, after the desired method name.
147
-
148
- ##### field
149
-
150
- This is the most common option, and is mandatory if a block is not provided. It selects an implementation in which the desired method will be defined such that it returns an array of the row values using the specified key. In other words, this acts as a "column fetcher", like in SQL: "SELECT some_column FROM some_table"
151
-
152
- Internally, (line 271-278), a Struct type is created to represent a row of raw data. The struct's attribute list is taken from the `field` options passed to `register_custom_property` / `add`. This new type is stored as `row_eval_context_type`. It is used as the evaluation context for block-mode `where` calls.
153
-
154
- * No checking is performed to see if the field name is actually a column in the raw data (the raw data hasn't been fetched yet, so we can't check).
155
- * You can't have two `register_custom_property` / `add` calls that reference the same field, because the Struct would see that as a duplicate attribute.
156
-
157
- POSSIBLE BUG: We could deduplicate the field names when defining the Struct, thus allowing multiple properties to use the same field.
158
-
159
- ##### style
160
-
161
- The `style` option is intended to effect post-processing of the return value from the generated method. To date there is only one recognized value, `:simple`, which `flatten`s, `uniq`s, and `compact`s the array value of the property. This is implemented on line 416.
162
-
163
- No other values for `:style` have been seen.
164
-
165
- ##### lazy
166
-
167
- This option implements column-wise lazy loading. The value of the option is expected to a lambda expecting 3 arguments: row (a Hash representing a row of the raw data), condition (a sought value to filter for), and table (a reference to the FilterTable::Table subclass, which may be used for context).
168
-
169
- See the usage guide for details on the usage of the lazy mechanism; this document will examine the internals.
170
-
171
- ### install_filter_methods_on_resource
172
-
173
- Legacy name (alias): connect
174
-
175
- This method is called like this:
176
-
177
- ```
178
- filter.install_filter_methods_on_resource(self, :data_fetching_method_name)
179
- ```
180
-
181
- `filter` is an instance of FilterTable::Factory. `self` is a reference to the resource class you are authoring. `data_fetching_method_name` is a symbol, the name of a method that will return the actual data to be processed by the FilterTable - as an array of hashes.
182
-
183
- Note that 'connect' does not refer to Connectors.
184
-
185
- `register_custom_property` and `register_filter_method` did nothing other than add register names for methods that we'd like to have added to the resource class. No filtering ability is present, nor are the methods defined, at this point.
186
-
187
- So, `install_filter_methods_on_resource`/`connect`'s job is to actually install everything.
188
-
189
- #### Defines a special Struct type to support block-mode where
190
-
191
- At lines 270-278, a new Struct type `row_eval_context_type` is defined, with attributes for each of the known table fields. We're careful to filter out any fields that have a block implementation, because they cannot be accessed as a row value, and so should not be present on the row context. The motivation for this struct type is to implement the block-mode behavior of `where`. Because each struct represents a row, and it has the attributes (accessors) for the fields, block-mode `where` is implemented by `instance_eval`ing against each row as a struct.
192
-
193
- Additionally, an instance variable, `@criteria_string` is defined, with an accessor. `to_s` is implemented, using `@criteria_string`, or `super` if not defined. I guess we then rely on the `Struct` class to stringify.
194
-
195
- `@criteria_string` is a trace - a string indicating the filter criteria used to create the table. I found no location where this per-row trace data was used.
196
-
197
- Additionally, an instance variable is setup to refer to the filter table later. This is required for lazy-loading columns.
198
-
199
- Table fields are determined by listing the `field_name`s of the CustomProperties.
200
-
201
- BUG: this means that any `register_custom_property` / `add` call that uses a block but not options will end up with an attribute in the row Struct. Thus, `filter.add(:exists?) { ... }` results in a row Struct that includes an attribute named `exists?` which may be undesired. This attribute will never have a value, because when the structs are instantiated, the block for the field is not called.
202
-
203
- #### Re-pack the "connectors"
204
-
205
- On lines 280-282, the list of custom properties ("connectors", registered using the `register_custom_property` / `add` method) are repacked into an array of hashes of two elements - the desired method name and the lambda that will be used as the method body. The lambda is created by the private method `create_custom_property_body`; see `register_custom_property` for discussion about how the implementation behaves.
206
-
207
- #### Subclass FilterTable::Table into an anonymous class
208
-
209
- At line 286, create the local var `table_class`, which refers to an anonymous class that subclasses FilterTable::Table. The class is opened and two groups of methods are defined.
210
-
211
- Lines 288-290 install the "custom_property" methods, using the names and lambdas determined on line 281.
212
-
213
- Lines 292-294 allow the Table subclass to introspect on the CustomProperties by slipping a reference to it in the class body, forming a closure.
214
-
215
- Line 296-303 define a method, `create_eval_context_for_row`. This is used when executing a block-mode `where`; see line 120.
216
-
217
- #### Setup the row context struct for lazy loading
218
-
219
- If you have a lazy field named `color` and it has not yet been populated, we need to trigger it to populate the first time it is read. If a block-mode where is used (`my_resource.where { color == :red }`), then we have to intercept the Struct's default `getter method`, and call the lazy column's lambda.
220
-
221
- Lines 306-329 do exactly that, by defining methods on the Struct subclass we're using for context. We continue to rely on the default Struct setter (`[]=`) and getter at the end (`[]`).
222
-
223
- #### Install methods on the resource
224
-
225
- Lines 337-348 install the "filter_methods" and "custom properties" methods onto the resource that you are authoring.
226
-
227
- Line 337-338 collects the names of the methods to define - by agglomerating the names of the "filter_methods" and "custom properties" methods. They are treated the same.
228
-
229
- Line 339 uses `send` with a block to call `define_method` on the resource class that you're authoring. Using a block with `send` is undocumented, but is treated as an implicit argument (per StackOverflow) , so the end result is that the block is used as the body for the new method being defined.
230
-
231
- The method body is wrapped in an exception-catching facility that catches skipped or failed resource exceptions and wraps them in a specialized exception catcher class. TBD: understand this better.
232
-
233
- Line 342 constructs an instance of the anonymous FilterTable::Table subclass defined at 284. It passes three args:
234
-
235
- 1. `self`. A reference to the resource instance.
236
- 2. The return value of calling the data fetcher method (that is an array of hashes, the raw data).
237
- 3. The string ' with', which is probably informing the criteria stringification. The extra space is intentional, as it follows the resource name: 'my_things with color == :red' might be a result.
238
-
239
- On line 343, we then immediately call a method on that "FilterTable::Table subclass instance". The method name is the same as the one we're defining on the resource - but we're calling it on the Table. Recall we defined all the "custom_property" methods on the Table subclass at line 288-290. The method gets called with any args or block passed, and since it's the last thing, it provides the return value.
240
-
241
- ## What is its behavior? (FilterTable::Table)
242
-
243
- Assume that your resource has a method, `fetch_data`, which returns a fixed array:
244
-
245
- ```
246
- [
247
- { id: 1, name: 'Dani', color: 'blue' },
248
- { id: 2, name: 'Mike', color: 'red' },
249
- { id: 3, name: 'Erika', color: 'green' },
250
- ]
251
- ```
252
-
253
- Assume that you then perform this sequence in your resource class body:
254
-
255
- ```
256
- filter = FilterTable.create
257
- filter.register_filter_method(:entries)
258
- filter.register_filter_method(:where)
259
- filter.register_custom_property(:exists?) { |x| !x.exists.empty? }
260
- filter.register_custom_property(:names, field: :name)
261
- filter.install_filter_methods_on_resource(self, :fetch_data)
262
- ```
263
-
264
- Legacy code equivalent:
265
-
266
- ```
267
- filter = FilterTable.create
268
- filter.add_accessor(:entries)
269
- filter.add_accessor(:where)
270
- filter.add(:exists?) { |x| !x.exists.empty? }
271
- filter.add(:names, field: :name)
272
- filter.connect(self, :fetch_data)
273
- ```
274
-
275
- We know from the above exploration of `install_filter_methods_on_resource` / `connect` that we now have several new methods on the resource class, all of which delegate to the FilterTable::Table implementation.
276
-
277
- ### FilterTable::Table constructor and internals
278
-
279
- Factory calls the FilterTable::Table constructor at 87-93 with three args. Table stores them into instance vars:
280
- * @resource_instance - this was passed in as `self` from line 342
281
- * @raw_data - an array of hashes
282
- * @criteria_string - This looks to be stringification trace data; the string ' with' was passed in by Factory.
283
- * @populated_lazy_columns = a hash, by lazy field name, with boolean values. This is set true if `populate_lazy_field` is called on a field.
284
-
285
- The first three get exposed via `attr_reader`s.
286
-
287
- ### `entries` behavior
288
-
289
- From usage, I expect entries to return a structure that resembles an array of hashes representing the (filtered) data.
290
-
291
- #### A new method `entries` is defined on the resource class
292
-
293
- That is performed by Factory#connect line 339.
294
-
295
- #### It delegates to FilterTable::Table#entries
296
-
297
- This is a real method defined in filter.rb line 155.
298
-
299
- It loops over the provided raw data (@raw_data) and builds an array, calling `create_eval_context_for_row` (see Factory lines 297-303) on each row; also appending a stringification trace to each entry. The array is returned.
300
-
301
- #### `entries` conclusion
302
-
303
- Not Surprising: It does behave as expected - an array of Hash-like structs representing the table. I don't know why it adds in the per-row stringification data - I've never seen that used.
304
-
305
- Surprising: this is a real method with a concrete implementation. That means that you can't call `filter.add_accessor` with arbitrary method names - `:entries` means something very specific.
306
-
307
- Surprising: I would not recommend this method be used for data access; instead I would recommend using `raw_data`.
308
-
309
- ### `where` behavior
310
-
311
- From usage, I expect this to take either method params or a block (both of which are magical), perform filtering, and return some object that contains only the filtered rows.
312
-
313
- So, what happens when you call `register_filter_method(:where)` and then call `resource.where`?
314
-
315
- #### A new method `where` is defined on the resource class
316
-
317
- That is performed by Factory#connect line 339.
318
-
319
- #### It delegates to FilterTable::Table#where
320
-
321
- Like `entries`, this is a real implemented method on FilterTable::Table, at line 98.
322
-
323
- The method accepts all params as the local var `conditions` which defaults to an empty Hash. A block, if any, is also explicitly assigned the name `block`.
324
-
325
- The implementation opens with two guard clauses, both of which will return `self` (which is the FilterTable::Table subclass instance).
326
-
327
- MISFEATURE: The first guard clause simply returns the Table if `conditions` is not a Hash. That would mean that someone called it like: `thing.where(:apples, :bananas, :cantaloupes)`. That misuse is silently ignored; I think we should probably throw a ResourceFailed or something.
328
-
329
- The second guard clause is a sensible degenerate case - return the existing Table if there are no conditions and no block. So `thing.where` is OK.
330
-
331
- Line 103 initializes a local var, `new_criteria_string`, which again is a stringification tracker.
332
-
333
- Line 104 initializes a var to track the `filtered_raw_data`.
334
-
335
- Lines 108-113 loop over the provided Hash `conditions`. If the requested field is lazy, it requests that it be populated (note that `populate_lazy_field` is idempotent - it won't fetch a field twice). Next, it repeatedly down-filters `filtered_raw_data` by calling the private method `filter_raw_data` on it. `filter_raw_data` does some syntactic sugaring for common types, Integers and Floats and Regexp matching. Additionally, the line 108-113 loop builds up the stringification tracker, `new_criteria_string`, by stringifying the field name and target value.
336
-
337
- Line 118-135 begins work if a filtration block has been provided. At this point, `filtered_raw_data` has been initialized with the raw data, and (if method params were provided) has also been filtered down.
338
-
339
- Line 120 filters the rows of the raw data using an interesting approach. Each row is inflated to a Struct using `create_eval_context_for_row` (see line 297). Then the provided block is `instance_eval`'d against the Struct. Because the Struct was defined with attributes (that is, accessor methods) for each declared field name (from FilterTable::Factory#register_custom_property), you can use field names in the block, and each row-as-struct will be able to respond. If the field happened to be lazy, we'll call our custom getter from lines 306-329.
340
-
341
- _That just explained a major spooky side-effect for me._
342
-
343
- Lines 125-134 do something with stringification tracing. TODO.
344
-
345
- Finally, at line 137, the FilterTable::Table anonymous subclass is again used to construct a new instance, passing on the resource reference, the newly filtered raw data table, and the newly adjusted stringification tracer.
346
-
347
- That new Table instance is returned, and thus `where` allows you to chain.
348
-
349
- #### `where` conclusion
350
-
351
- Unsurprising: How where works with method params.
352
- Surprising: How where works in block mode, `instance_eval`'ing against each row-as-Struct.
353
- Surprising: You can use method-mode and block-mode together if you want.