foodcritic 10.4.1 → 11.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -1
- data/Rakefile +7 -1
- data/features/step_definitions/cookbook_steps.rb +0 -96
- data/lib/foodcritic/api.rb +77 -79
- data/lib/foodcritic/rules/fc008.rb +2 -2
- data/lib/foodcritic/rules/fc029.rb +1 -1
- data/lib/foodcritic/rules/fc042.rb +1 -1
- data/lib/foodcritic/rules/fc052.rb +1 -1
- data/lib/foodcritic/rules/fc053.rb +1 -1
- data/lib/foodcritic/rules/fc057.rb +1 -1
- data/lib/foodcritic/rules/fc058.rb +1 -1
- data/lib/foodcritic/rules/fc060.rb +1 -1
- data/lib/foodcritic/rules/fc061.rb +3 -3
- data/lib/foodcritic/rules/fc063.rb +1 -2
- data/lib/foodcritic/rules/fc069.rb +2 -4
- data/lib/foodcritic/rules/fc078.rb +2 -3
- data/lib/foodcritic/rules/fc079.rb +6 -0
- data/lib/foodcritic/rules/fc080.rb +6 -0
- data/lib/foodcritic/rules/fc081.rb +6 -0
- data/lib/foodcritic/rules/fc082.rb +9 -0
- data/lib/foodcritic/rules/fc083.rb +6 -0
- data/lib/foodcritic/rules/fc084.rb +9 -0
- data/lib/foodcritic/rules/fc085.rb +12 -0
- data/lib/foodcritic/version.rb +1 -1
- data/spec/functional/fc007_spec.rb +127 -0
- data/spec/functional/fc049_spec.rb +56 -0
- data/spec/functional/fc050_spec.rb +85 -0
- data/spec/functional/fc066_spec.rb +20 -0
- data/spec/functional/fc069_spec.rb +15 -0
- data/spec/functional/fc070_spec.rb +9 -0
- data/spec/functional/fc076_spec.rb +2 -2
- data/spec/functional/fc077_spec.rb +2 -2
- data/spec/functional/fc078_spec.rb +14 -4
- data/spec/functional/fc079_spec.rb +21 -0
- data/spec/functional/fc080_spec.rb +68 -0
- data/spec/functional/fc081_spec.rb +25 -0
- data/spec/functional/fc082_spec.rb +23 -0
- data/spec/functional/fc083_spec.rb +34 -0
- data/spec/functional/fc084_spec.rb +49 -0
- data/spec/functional/fc085_spec.rb +58 -0
- data/spec/regression/expected/aix.txt +1 -0
- data/spec/regression/expected/aws.txt +3 -0
- data/spec/regression/expected/chef-client.txt +2 -0
- data/spec/regression/expected/chef.txt +67 -0
- data/spec/regression/expected/database.txt +1 -0
- data/spec/regression/expected/drbd.txt +1 -0
- data/spec/regression/expected/jetty.txt +1 -0
- data/spec/regression/expected/mysql.txt +4 -0
- data/spec/regression/expected/openssh.txt +1 -0
- data/spec/regression/expected/postfix.txt +1 -0
- data/spec/regression/expected/rsyslog.txt +1 -0
- data/spec/regression/expected/smokeping.txt +1 -0
- data/spec/regression/expected/sql_server.txt +1 -0
- data/spec/regression/expected/ufw.txt +1 -0
- data/spec/regression/expected/users.txt +2 -0
- data/spec/regression/expected/xml.txt +1 -0
- data/spec/regression/expected/yum.txt +0 -1
- data/spec/regression/regression_spec.rb +2 -2
- data/spec/unit/api_spec.rb +130 -149
- metadata +20 -32
- data/features/007_check_for_undeclared_recipe_dependencies.feature +0 -59
- data/features/049_check_for_role_name_mismatch_with_file_name.feature +0 -31
- data/features/050_check_for_invalid_name.feature +0 -33
- data/man/foodcritic.1 +0 -81
- data/spec/foodcritic/coverage/assets/0.10.0/application.css +0 -799
- data/spec/foodcritic/coverage/assets/0.10.0/application.js +0 -1707
- data/spec/foodcritic/coverage/assets/0.10.0/colorbox/border.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/colorbox/controls.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/colorbox/loading.gif +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/colorbox/loading_background.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/favicon_green.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/favicon_red.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/favicon_yellow.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/loading.gif +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/magnify.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/spec/foodcritic/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/spec/foodcritic/coverage/index.html +0 -72
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5c06e37056b5db3985f94fea5101961eeec4164
|
|
4
|
+
data.tar.gz: 610fe94a45ecd4412e77ac18abcd66129fe3d75d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6471cb860d9e922e4ee238b9b88647cb68c7c161123d7ad223dfec4733b3c741683db9173889a19f524f8269ae223483a3aec21eaaef020ac3681942f890efe4
|
|
7
|
+
data.tar.gz: 31ba9be090cafd5935d660ed91456da49a8efbff002f3301ec5e81466b2c9295a7a07a4982b1b58334adb05da5ed3419de54faaba99ebdd3303173ecdcb6978f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
# Foodcritic Changelog:
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [11.0.0](https://github.com/acrmp/foodcritic/tree/v11.0.0) (2017-04-24)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/acrmp/foodcritic/compare/v10.4.1...v11.0.0)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- Added `FC079` to detect the usage of the easy_install_package resource which is deprecated in Chef 13\. Tags: deprecated, chef13.
|
|
10
|
+
- Added `FC080` to detect user resources that include the supports property, which is deprecated in Chef 13\. Tags: deprecated, chef13.
|
|
11
|
+
- Added `FC081` to detect a cookbook that depends on the partial_search cookbook as partial search functionality is built into Chef 12 and later. Tags: chef12.
|
|
12
|
+
- Added `FC082` to detect the usage of node.set and node.set_unless which will be removed in Chef 14\. Tags: deprecated, chef14.
|
|
13
|
+
- Added `FC083` to detect execute resources that include the path property, which is deprecated in Chef 12\. Tags: deprecated, chef13.
|
|
14
|
+
- Added `FC084` to detect usage of the deprecated Chef::REST class. Tags: deprecated, chef13.
|
|
15
|
+
- Added `FC085` to detect usage of new_resource.updated_by_last_action to converge resources. Tags: deprecated, chef13.
|
|
16
|
+
- Updated and refactored API methods `declared_dependencies`, `supported_platforms`, and `word_list_values`
|
|
17
|
+
- Deprecated API methods `checks_for_chef_solo` and `chef_solo_search_supported?` have been removed.
|
|
18
|
+
- Added a new API method `json_file_to_hash` for loading json files as a hash.
|
|
19
|
+
- Added a new rake command to run the regression test on just a single cookbook
|
|
20
|
+
|
|
21
|
+
**Fixed bugs:**
|
|
22
|
+
|
|
23
|
+
- Multiple rules have been rewritten to use Foodcritic APIs instead of using XPATH queries directly. This avoids false positives created by overly simplistic queries.
|
|
24
|
+
- Fixed FC069 to skip if the license metadata is any formatting of 'All Rights Reserved'.
|
|
25
|
+
- Added the `license` and `supermarket` tag to FC078.
|
|
26
|
+
- Updated the `field` and `field_value` API methods to correctly recognize additional formats of data in the metdata.
|
|
27
|
+
|
|
28
|
+
## [10.4.1](https://github.com/acrmp/foodcritic/tree/v10.4.1) (2017-04-17)
|
|
4
29
|
|
|
5
30
|
[Full Changelog](https://github.com/acrmp/foodcritic/compare/v10.4.0...v10.4.1)
|
|
6
31
|
|
data/Rakefile
CHANGED
|
@@ -10,7 +10,7 @@ RSpec::Core::RakeTask.new(:spec, :tag) do |t, args|
|
|
|
10
10
|
a << "--format #{ENV['CI'] ? 'documentation' : 'Fuubar'}"
|
|
11
11
|
a << "--backtrace" if ENV["DEBUG"]
|
|
12
12
|
a << "--seed #{ENV['SEED']}" if ENV["SEED"]
|
|
13
|
-
a << "--tag ~regression" unless ENV["CI"] || args[:tag]
|
|
13
|
+
a << "--tag ~regression" unless ENV["CI"] || args[:tag].to_s =~ /regression/
|
|
14
14
|
a << "--tag #{args[:tag]}" if args[:tag]
|
|
15
15
|
end.join(" ")
|
|
16
16
|
end
|
|
@@ -65,3 +65,9 @@ task :regen_regression do
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
|
+
|
|
69
|
+
desc "Run one regression test (or all of them)"
|
|
70
|
+
task :regression, [:cookbook] do |t, args|
|
|
71
|
+
tag = args[:cookbook] ? "regression_#{args[:cookbook]}" : "regression"
|
|
72
|
+
Rake::Task["spec"].invoke(tag)
|
|
73
|
+
end
|
|
@@ -409,61 +409,6 @@ Given 'a cookbook recipe that has a confusingly named local variable "default"'
|
|
|
409
409
|
}
|
|
410
410
|
end
|
|
411
411
|
|
|
412
|
-
Given /^a cookbook recipe that includes a local recipe(.*)$/ do |diff_name|
|
|
413
|
-
cookbook = diff_name.empty? ? "example" : "foo"
|
|
414
|
-
write_recipe %Q{
|
|
415
|
-
include_recipe '#{cookbook}::server'
|
|
416
|
-
}
|
|
417
|
-
write_metadata %Q{
|
|
418
|
-
name '#{cookbook}'
|
|
419
|
-
}
|
|
420
|
-
end
|
|
421
|
-
|
|
422
|
-
Given /^a cookbook recipe that includes a recipe name from an( embedded)? expression(.*)$/ do |embedded, expr|
|
|
423
|
-
if embedded
|
|
424
|
-
write_recipe %Q{
|
|
425
|
-
include_recipe "#{expr.strip}"
|
|
426
|
-
}
|
|
427
|
-
else
|
|
428
|
-
write_recipe %q{
|
|
429
|
-
include_recipe node['foo']['bar']
|
|
430
|
-
}
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
write_metadata %q{
|
|
434
|
-
depends "foo"
|
|
435
|
-
}
|
|
436
|
-
end
|
|
437
|
-
|
|
438
|
-
Given /^a cookbook recipe that includes a(n un| )?declared recipe dependency(?: {0,1})(unscoped)?( with parentheses)?$/ do |undeclared, unscoped, parens|
|
|
439
|
-
recipe_with_dependency(:is_declared => undeclared.strip.empty?,
|
|
440
|
-
:is_scoped => unscoped.nil?, :parentheses => parens)
|
|
441
|
-
end
|
|
442
|
-
|
|
443
|
-
Given "a cookbook recipe that includes both declared and undeclared recipe dependencies" do
|
|
444
|
-
write_recipe %q{
|
|
445
|
-
include_recipe "foo::default"
|
|
446
|
-
include_recipe "bar::default"
|
|
447
|
-
file "/tmp/something" do
|
|
448
|
-
action :delete
|
|
449
|
-
end
|
|
450
|
-
include_recipe "baz::default"
|
|
451
|
-
}
|
|
452
|
-
write_metadata %q{
|
|
453
|
-
['foo', 'bar'].each{|cbk| depends cbk}
|
|
454
|
-
}
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
Given "a cookbook that uses the include_recipe shorthand syntax" do
|
|
458
|
-
write_recipe %q{
|
|
459
|
-
include_recipe "::some_recipe"
|
|
460
|
-
}
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
Given /^a cookbook recipe that includes several declared recipe dependencies - (brace|block)$/ do |brace_or_block|
|
|
464
|
-
cookbook_declares_dependencies(brace_or_block.to_sym)
|
|
465
|
-
end
|
|
466
|
-
|
|
467
412
|
Given /a cookbook recipe that (install|upgrade)s (a gem|multiple gems)(.*)$/ do |action, arity, approach|
|
|
468
413
|
if arity == "a gem"
|
|
469
414
|
if approach.empty?
|
|
@@ -942,12 +887,6 @@ Given /^a cookbook that does not contain a definition and has (no|a) definitions
|
|
|
942
887
|
}
|
|
943
888
|
end
|
|
944
889
|
|
|
945
|
-
Given "a cookbook that does not have defined metadata" do
|
|
946
|
-
write_recipe %q{
|
|
947
|
-
include_recipe "foo::default"
|
|
948
|
-
}
|
|
949
|
-
end
|
|
950
|
-
|
|
951
890
|
Given /^a cookbook that has ([^ ]+) problems$/ do |problems|
|
|
952
891
|
cookbook_that_matches_rules(
|
|
953
892
|
problems.split(",").map do |problem|
|
|
@@ -1132,14 +1071,6 @@ Given /^a directory that contains a role file ([^ ]+) in (json|ruby) that define
|
|
|
1132
1071
|
role(:role_name => %Q{"#{role_name}"}, :file_name => file_name, :format => format.to_sym)
|
|
1133
1072
|
end
|
|
1134
1073
|
|
|
1135
|
-
Given "a directory that contains a ruby role that declares the role name more than once" do
|
|
1136
|
-
role(:role_name => ['"webserver"', '"apache"'], :file_name => "webserver.rb")
|
|
1137
|
-
end
|
|
1138
|
-
|
|
1139
|
-
Given "a directory that contains a ruby role with an expression as its name" do
|
|
1140
|
-
role(:role_name => '"#{foo}#{bar}"', :file_name => "webserver.rb")
|
|
1141
|
-
end
|
|
1142
|
-
|
|
1143
1074
|
Given /^a directory that contains an environment file (.*) in ruby that defines environment name (.*)$/ do |file_name, env_name|
|
|
1144
1075
|
environment(:environment_name => %Q{"#{env_name}"}, :file_name => "production.rb")
|
|
1145
1076
|
end
|
|
@@ -1411,10 +1342,6 @@ Given "the gems have been vendored" do
|
|
|
1411
1342
|
vendor_gems
|
|
1412
1343
|
end
|
|
1413
1344
|
|
|
1414
|
-
Given "the last role name declared does not match the containing filename" do
|
|
1415
|
-
|
|
1416
|
-
end
|
|
1417
|
-
|
|
1418
1345
|
Given /^the inferred template contains the expression (.*)$/ do |expr|
|
|
1419
1346
|
write_file "cookbooks/example/templates/default/config.conf.erb", %Q{
|
|
1420
1347
|
<%= #{expr} %>
|
|
@@ -1489,10 +1416,6 @@ Given "a recipe that tries to mask a systemd service" do
|
|
|
1489
1416
|
}
|
|
1490
1417
|
end
|
|
1491
1418
|
|
|
1492
|
-
Given /^a ruby environment file that defines an environment with name (.*)$/ do |env_name|
|
|
1493
|
-
environment(:environment_name => %Q{"#{env_name}"}, :file_name => "production.rb")
|
|
1494
|
-
end
|
|
1495
|
-
|
|
1496
1419
|
Given /^a ruby environment that triggers FC050 with comment (.*)$/ do |comment|
|
|
1497
1420
|
write_file "environments/production.rb", %Q{
|
|
1498
1421
|
name "Production (eu-west-1)" #{comment}
|
|
@@ -1500,10 +1423,6 @@ Given /^a ruby environment that triggers FC050 with comment (.*)$/ do |comment|
|
|
|
1500
1423
|
}.strip
|
|
1501
1424
|
end
|
|
1502
1425
|
|
|
1503
|
-
Given /^a ruby role file that defines a role with name (.*)$/ do |role_name|
|
|
1504
|
-
role(:role_name => [%Q{"#{role_name}"}], :file_name => "webserver.rb")
|
|
1505
|
-
end
|
|
1506
|
-
|
|
1507
1426
|
Given /^a ruby role that triggers FC049 with comment (.*)$/ do |comment|
|
|
1508
1427
|
write_file "roles/webserver.rb", %Q{
|
|
1509
1428
|
name "apache" #{comment}
|
|
@@ -1634,15 +1553,6 @@ When "I check the role directory" do
|
|
|
1634
1553
|
run_lint ["--no-progress", "-R", "roles"]
|
|
1635
1554
|
end
|
|
1636
1555
|
|
|
1637
|
-
When /^I check the role directory as a (default|cookbook|role) path$/ do |path_type|
|
|
1638
|
-
options = case path_type
|
|
1639
|
-
when "default" then ["--no-progress", "roles"]
|
|
1640
|
-
when "cookbook" then ["--no-progress", "-B", "roles"]
|
|
1641
|
-
when "role" then ["--no-progress", "-R", "roles"]
|
|
1642
|
-
end
|
|
1643
|
-
run_lint(options)
|
|
1644
|
-
end
|
|
1645
|
-
|
|
1646
1556
|
When "I check the webserver role only" do
|
|
1647
1557
|
run_lint ["--no-progress", "-R", "roles/webserver.rb"]
|
|
1648
1558
|
end
|
|
@@ -1945,12 +1855,6 @@ Then /^the template partials loop indefinitely warning 051 should (not )?be disp
|
|
|
1945
1855
|
:expect_warning => ! not_shown)
|
|
1946
1856
|
end
|
|
1947
1857
|
|
|
1948
|
-
Then "the undeclared dependency warning 007 should be displayed only for the undeclared dependencies" do
|
|
1949
|
-
expect_warning("FC007", :file => "recipes/default.rb", :line => 1, :expect_warning => false)
|
|
1950
|
-
expect_warning("FC007", :file => "recipes/default.rb", :line => 2, :expect_warning => false)
|
|
1951
|
-
expect_warning("FC007", :file => "recipes/default.rb", :line => 6, :expect_warning => true)
|
|
1952
|
-
end
|
|
1953
|
-
|
|
1954
1858
|
Then /^the unused template variables warning 034 should (not )?be displayed against the (?:inferred )?template(.*)?$/ do |not_shown, ext|
|
|
1955
1859
|
file = if ext.empty?
|
|
1956
1860
|
"templates/default/config.conf.erb"
|
data/lib/foodcritic/api.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require "nokogiri"
|
|
2
2
|
require "rufus-lru"
|
|
3
|
+
require "json"
|
|
3
4
|
|
|
4
5
|
module FoodCritic
|
|
5
6
|
# Helper methods that form part of the Rules DSL.
|
|
@@ -44,56 +45,6 @@ module FoodCritic
|
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
# Does the specified recipe check for Chef Solo?
|
|
48
|
-
#
|
|
49
|
-
# @deprecated chef-solo functionality in Chef has been replaced with local-mode
|
|
50
|
-
# so this helper is no longer necessary and will be removed in Foodcritic 11.0
|
|
51
|
-
def checks_for_chef_solo?(ast)
|
|
52
|
-
$stderr.puts "the checks_for_chef_solo? helper is deprecated and will be removed from the next release of Foodcritic"
|
|
53
|
-
raise_unless_xpath!(ast)
|
|
54
|
-
# TODO: This expression is too loose, but also will fail to match other
|
|
55
|
-
# types of conditionals.
|
|
56
|
-
(!ast.xpath(%q{//*[self::if or self::ifop or self::unless]/
|
|
57
|
-
*[self::aref or child::aref or self::call]
|
|
58
|
-
[count(descendant::const[@value = 'Chef' or @value = 'Config']) = 2
|
|
59
|
-
and
|
|
60
|
-
( count(descendant::ident[@value='solo']) > 0
|
|
61
|
-
or count(descendant::tstring_content[@value='solo']) > 0
|
|
62
|
-
)
|
|
63
|
-
]}).empty?) ||
|
|
64
|
-
ast.xpath('//if_mod[return][aref/descendant::ident/@value="solo"]/aref/
|
|
65
|
-
const_path_ref/descendant::const').map do |c|
|
|
66
|
-
c["value"]
|
|
67
|
-
end == %w{Chef Config}
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Is the chef-solo-search library available?
|
|
71
|
-
#
|
|
72
|
-
# @see https://github.com/edelight/chef-solo-search
|
|
73
|
-
# @deprecated chef-solo functionality in Chef has been replaced with local-mode
|
|
74
|
-
# so this helper is no longer necessary and will be removed in Foodcritic 11.0
|
|
75
|
-
def chef_solo_search_supported?(recipe_path)
|
|
76
|
-
$stderr.puts "the chef_solo_search_supported? helper is deprecated and will be removed from the next release of Foodcritic"
|
|
77
|
-
return false if recipe_path.nil? || !File.exist?(recipe_path)
|
|
78
|
-
|
|
79
|
-
# Look for the chef-solo-search library.
|
|
80
|
-
#
|
|
81
|
-
# TODO: This will not work if the cookbook that contains the library
|
|
82
|
-
# is not under the same `cookbook_path` as the cookbook being checked.
|
|
83
|
-
cbk_tree_path = Pathname.new(File.join(recipe_path, "../../.."))
|
|
84
|
-
search_libs = Dir[File.join(cbk_tree_path.realpath,
|
|
85
|
-
"*/libraries/search.rb")]
|
|
86
|
-
|
|
87
|
-
# True if any of the candidate library files match the signature:
|
|
88
|
-
#
|
|
89
|
-
# class Chef
|
|
90
|
-
# def search
|
|
91
|
-
search_libs.any? do |lib|
|
|
92
|
-
!read_ast(lib).xpath(%q{//class[count(descendant::const[@value='Chef']
|
|
93
|
-
) = 1]/descendant::def/ident[@value='search']}).empty?
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
48
|
# The absolute path of a cookbook from the specified file.
|
|
98
49
|
#
|
|
99
50
|
# @author Tim Smith - tsmith@chef.io
|
|
@@ -113,7 +64,11 @@ module FoodCritic
|
|
|
113
64
|
file
|
|
114
65
|
end
|
|
115
66
|
|
|
116
|
-
#
|
|
67
|
+
# Retrieves a value of a metadata field.
|
|
68
|
+
#
|
|
69
|
+
# @author Miguel Fonseca
|
|
70
|
+
# @since 7.0.0
|
|
71
|
+
# @return [String] the value of the metadata field
|
|
117
72
|
def metadata_field(file, field)
|
|
118
73
|
until (file.split(File::SEPARATOR) & standard_cookbook_subdirs).empty?
|
|
119
74
|
file = File.absolute_path(File.dirname(file.to_s))
|
|
@@ -133,6 +88,9 @@ module FoodCritic
|
|
|
133
88
|
end
|
|
134
89
|
|
|
135
90
|
# The name of the cookbook containing the specified file.
|
|
91
|
+
#
|
|
92
|
+
# @param file [String] file within a cookbook
|
|
93
|
+
# @return [String] name of the cookbook
|
|
136
94
|
def cookbook_name(file)
|
|
137
95
|
raise ArgumentError, "File cannot be nil or empty" if file.to_s.empty?
|
|
138
96
|
|
|
@@ -149,14 +107,20 @@ module FoodCritic
|
|
|
149
107
|
end
|
|
150
108
|
end
|
|
151
109
|
|
|
152
|
-
#
|
|
110
|
+
# Return metadata maintainer property given any file in the cookbook
|
|
111
|
+
#
|
|
112
|
+
# @param file [String] file within a cookbook
|
|
113
|
+
# @return [String] the maintainer of the cookbook
|
|
153
114
|
def cookbook_maintainer(file)
|
|
154
115
|
raise ArgumentError, "File cannot be nil or empty" if file.to_s.empty?
|
|
155
116
|
|
|
156
117
|
metadata_field(file, "maintainer")
|
|
157
118
|
end
|
|
158
119
|
|
|
159
|
-
#
|
|
120
|
+
# Return metadata maintainer_email property given any file in the cookbook
|
|
121
|
+
#
|
|
122
|
+
# @param file [String] file within a cookbook
|
|
123
|
+
# @return [String] email of the maintainer of the cookbook
|
|
160
124
|
def cookbook_maintainer_email(file)
|
|
161
125
|
raise ArgumentError, "File cannot be nil or empty" if file.to_s.empty?
|
|
162
126
|
|
|
@@ -167,33 +131,38 @@ module FoodCritic
|
|
|
167
131
|
def declared_dependencies(ast)
|
|
168
132
|
raise_unless_xpath!(ast)
|
|
169
133
|
|
|
134
|
+
deps = []
|
|
170
135
|
# String literals.
|
|
171
136
|
#
|
|
172
137
|
# depends 'foo'
|
|
173
|
-
deps
|
|
174
|
-
descendant::args_add/descendant::tstring_content[1]})
|
|
138
|
+
deps += field(ast, "depends").xpath("descendant::args_add/descendant::tstring_content[1]")
|
|
175
139
|
|
|
176
140
|
# Quoted word arrays are also common.
|
|
177
141
|
#
|
|
178
142
|
# %w{foo bar baz}.each do |cbk|
|
|
179
143
|
# depends cbk
|
|
180
144
|
# end
|
|
181
|
-
deps
|
|
182
|
-
|
|
183
|
-
deps.
|
|
145
|
+
deps += word_list_values(field(ast, "depends"))
|
|
146
|
+
deps.uniq!
|
|
147
|
+
deps.map! { |dep| dep["value"].strip }
|
|
148
|
+
deps
|
|
184
149
|
end
|
|
185
150
|
|
|
186
|
-
#
|
|
151
|
+
# Look for a method call with a given name.
|
|
152
|
+
#
|
|
153
|
+
# @param ast [Nokogiri::XML::Node] Document to search under
|
|
154
|
+
# @param field_name [String] Method name to search for
|
|
155
|
+
# @return [Nokogiri::XML::NodeSet]
|
|
187
156
|
def field(ast, field_name)
|
|
188
157
|
if field_name.nil? || field_name.to_s.empty?
|
|
189
158
|
raise ArgumentError, "Field name cannot be nil or empty"
|
|
190
159
|
end
|
|
191
|
-
ast.xpath("
|
|
160
|
+
ast.xpath("(.//command[ident/@value='#{field_name}']|.//fcall[ident/@value='#{field_name}']/..)")
|
|
192
161
|
end
|
|
193
162
|
|
|
194
163
|
# The value for a specific key in an environment or role ruby file
|
|
195
164
|
def field_value(ast, field_name)
|
|
196
|
-
field(ast, field_name).xpath('args_add_block
|
|
165
|
+
field(ast, field_name).xpath('.//args_add_block//tstring_content
|
|
197
166
|
[count(ancestor::args_add) = 1][count(ancestor::string_add) = 1]
|
|
198
167
|
/@value').map { |a| a.to_s }.last
|
|
199
168
|
end
|
|
@@ -376,25 +345,33 @@ module FoodCritic
|
|
|
376
345
|
end
|
|
377
346
|
|
|
378
347
|
# The list of standard cookbook sub-directories.
|
|
348
|
+
#
|
|
349
|
+
# @since 1.0.0
|
|
350
|
+
# @return [array] array of all default sub-directories in a cookbook
|
|
379
351
|
def standard_cookbook_subdirs
|
|
380
352
|
%w{attributes definitions files libraries providers recipes resources
|
|
381
353
|
templates}
|
|
382
354
|
end
|
|
383
355
|
|
|
384
|
-
# Platforms declared as supported in cookbook metadata
|
|
356
|
+
# Platforms declared as supported in cookbook metadata. Returns an array
|
|
357
|
+
# of hashes containing the name and version constraints for each platform.
|
|
358
|
+
#
|
|
359
|
+
# @param ast [Nokogiri::XML::Node] Document to search from.
|
|
360
|
+
# @return [Array<Hash>]
|
|
385
361
|
def supported_platforms(ast)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
362
|
+
# Find the supports() method call.
|
|
363
|
+
platforms_ast = field(ast, "supports")
|
|
364
|
+
# Look for the first argument (the node next to the top args_new) and
|
|
365
|
+
# filter out anything with a string_embexpr since that can't be parsed
|
|
366
|
+
# statically. Then grab the static value for both strings and symbols, and
|
|
367
|
+
# finally combine it with the word list (%w{}) analyzer.
|
|
368
|
+
platforms = platforms_ast.xpath("(.//args_new)[1]/../*[not(.//string_embexpr)]").xpath(".//tstring_content|.//symbol/ident") | word_list_values(platforms_ast)
|
|
393
369
|
platforms.map do |platform|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
370
|
+
# For each platform value, look for all arguments after the first, then
|
|
371
|
+
# extract the string literal value.
|
|
372
|
+
versions = platform.xpath("ancestor::args_add[not(args_new)]/*[position()=2]//tstring_content/@value")
|
|
373
|
+
{ platform: platform["value"].lstrip, versions: versions.map(&:to_s) }
|
|
374
|
+
end.sort_by { |p| p[:platform] }
|
|
398
375
|
end
|
|
399
376
|
|
|
400
377
|
# Template filename
|
|
@@ -436,6 +413,23 @@ module FoodCritic
|
|
|
436
413
|
end
|
|
437
414
|
end
|
|
438
415
|
|
|
416
|
+
# Give a filename path it returns the hash of the JSON contents
|
|
417
|
+
#
|
|
418
|
+
# @author Tim Smith - tsmith@chef.io
|
|
419
|
+
# @since 11.0
|
|
420
|
+
# @param filename [String] path to a file in JSON format
|
|
421
|
+
# @return [Hash] hash of JSON content
|
|
422
|
+
def json_file_to_hash(filename)
|
|
423
|
+
raise "File #{filename} not found" unless File.exist?(filename)
|
|
424
|
+
|
|
425
|
+
file = File.read(filename)
|
|
426
|
+
begin
|
|
427
|
+
JSON.parse(file)
|
|
428
|
+
rescue RuntimeError
|
|
429
|
+
raise "File #{filename} does not appear to contain valid JSON"
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
439
433
|
private
|
|
440
434
|
|
|
441
435
|
def block_attributes(resource)
|
|
@@ -642,14 +636,18 @@ module FoodCritic
|
|
|
642
636
|
end.sort
|
|
643
637
|
end
|
|
644
638
|
|
|
645
|
-
def word_list_values(ast, xpath)
|
|
646
|
-
|
|
639
|
+
def word_list_values(ast, xpath = nil)
|
|
640
|
+
# Find the node for the field argument variable. (e.g. given `foo d`, find `d`)
|
|
641
|
+
var_ref = ast.xpath("#{xpath ? xpath + '/' : ''}descendant::var_ref/ident")
|
|
647
642
|
if var_ref.empty?
|
|
648
|
-
|
|
643
|
+
# The field is either a static value, or took no arguments, or something
|
|
644
|
+
# more complex than we care to evaluate.
|
|
645
|
+
Nokogiri::XML::NodeSet.new(ast.document)
|
|
649
646
|
else
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
647
|
+
# Look back out the tree for a method_add_block which contains a block
|
|
648
|
+
# variable matching the field argument variable, and then drill down to
|
|
649
|
+
# all the literal content nodes.
|
|
650
|
+
ast.xpath(%Q{ancestor::method_add_block[//block_var//ident/@value='#{var_ref.first['value']}']/call//tstring_content})
|
|
653
651
|
end
|
|
654
652
|
end
|
|
655
653
|
end
|