foodcritic 15.0.0 → 15.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/chef_dsl_metadata/{chef_14.7.17.json → chef_14.8.12.json} +61 -1
- data/foodcritic.gemspec +1 -3
- data/lib/foodcritic/linter.rb +1 -1
- data/lib/foodcritic/version.rb +1 -1
- metadata +5 -232
- data/Rakefile +0 -73
- data/features/002_check_string_interpolation.feature +0 -50
- data/features/005_check_for_resource_repetition.feature +0 -64
- data/features/006_check_file_mode.feature +0 -36
- data/features/009_check_for_unrecognised_resource_attributes.feature +0 -55
- data/features/014_check_for_long_ruby_blocks.feature +0 -30
- data/features/018_check_for_old_lwrp_notification_syntax.feature +0 -25
- data/features/019_check_for_consistent_node_access.feature +0 -108
- data/features/021_check_for_dodgy_lwrp_conditions.feature +0 -28
- data/features/022_check_for_dodgy_conditions_within_loop.feature +0 -43
- data/features/024_check_for_missing_platforms.feature +0 -43
- data/features/027_check_for_internal_attribute_use.feature +0 -22
- data/features/030_check_for_debugger_breakpoints.feature +0 -25
- data/features/032_check_for_invalid_notification_timing.feature +0 -24
- data/features/033_check_for_missing_template.feature +0 -39
- data/features/034_check_for_unused_template_variables.feature +0 -80
- data/features/037_check_for_invalid_notification_action.feature +0 -34
- data/features/038_check_for_invalid_action.feature +0 -39
- data/features/039_check_for_key_access_to_node_methods.feature +0 -33
- data/features/044_check_for_bare_attribute_keys.feature +0 -53
- data/features/046_check_for_assign_unless_nil_attributes.feature +0 -21
- data/features/047_check_for_attribute_assignment_without_precedence.feature +0 -49
- data/features/051_check_for_template_partial_loops.feature +0 -40
- data/features/build_framework_support.feature +0 -109
- data/features/checking_all_types_of_file.feature +0 -40
- data/features/choose_rules_to_apply.feature +0 -47
- data/features/command_line_help.feature +0 -58
- data/features/continuous_integration_support.feature +0 -33
- data/features/exclude_paths_to_lint.feature +0 -12
- data/features/ignore_via_line_comments.feature +0 -69
- data/features/include_custom_rules.feature +0 -29
- data/features/individual_file.feature +0 -28
- data/features/limit_rules_to_specific_versions.feature +0 -65
- data/features/multiple_paths.feature +0 -35
- data/features/show_lines_matched.feature +0 -20
- data/features/sort_warnings.feature +0 -10
- data/features/specify_search_grammar.feature +0 -25
- data/features/step_definitions/cookbook_steps.rb +0 -1826
- data/features/support/command_helpers.rb +0 -418
- data/features/support/cookbook_helpers.rb +0 -599
- data/features/support/env.rb +0 -19
- data/man/foodcritic.1.ronn +0 -76
- data/spec/functional/fc001_spec.rb +0 -72
- data/spec/functional/fc004_spec.rb +0 -84
- data/spec/functional/fc007_spec.rb +0 -127
- data/spec/functional/fc008_spec.rb +0 -33
- data/spec/functional/fc009_spec.rb +0 -37
- data/spec/functional/fc010_spec.rb +0 -32
- data/spec/functional/fc011_spec.rb +0 -20
- data/spec/functional/fc013_spec.rb +0 -39
- data/spec/functional/fc015_spec.rb +0 -19
- data/spec/functional/fc016_spec.rb +0 -57
- data/spec/functional/fc025_spec.rb +0 -60
- data/spec/functional/fc026_spec.rb +0 -66
- data/spec/functional/fc028_spec.rb +0 -93
- data/spec/functional/fc029_spec.rb +0 -33
- data/spec/functional/fc031_spec.rb +0 -14
- data/spec/functional/fc037_spec.rb +0 -75
- data/spec/functional/fc038_spec.rb +0 -28
- data/spec/functional/fc040_spec.rb +0 -156
- data/spec/functional/fc041_spec.rb +0 -121
- data/spec/functional/fc042_spec.rb +0 -13
- data/spec/functional/fc043_spec.rb +0 -28
- data/spec/functional/fc045_spec.rb +0 -18
- data/spec/functional/fc048_spec.rb +0 -67
- data/spec/functional/fc049_spec.rb +0 -56
- data/spec/functional/fc050_spec.rb +0 -85
- data/spec/functional/fc052_spec.rb +0 -13
- data/spec/functional/fc053_spec.rb +0 -13
- data/spec/functional/fc055_spec.rb +0 -18
- data/spec/functional/fc056_spec.rb +0 -18
- data/spec/functional/fc058_spec.rb +0 -102
- data/spec/functional/fc060_spec.rb +0 -45
- data/spec/functional/fc061_spec.rb +0 -48
- data/spec/functional/fc062_spec.rb +0 -13
- data/spec/functional/fc063_spec.rb +0 -18
- data/spec/functional/fc064_spec.rb +0 -13
- data/spec/functional/fc065_spec.rb +0 -13
- data/spec/functional/fc066_spec.rb +0 -33
- data/spec/functional/fc067_spec.rb +0 -13
- data/spec/functional/fc068_spec.rb +0 -13
- data/spec/functional/fc069_spec.rb +0 -38
- data/spec/functional/fc070_spec.rb +0 -65
- data/spec/functional/fc071_spec.rb +0 -36
- data/spec/functional/fc072_spec.rb +0 -13
- data/spec/functional/fc073_spec.rb +0 -56
- data/spec/functional/fc074_spec.rb +0 -39
- data/spec/functional/fc075_spec.rb +0 -41
- data/spec/functional/fc076_spec.rb +0 -13
- data/spec/functional/fc077_spec.rb +0 -13
- data/spec/functional/fc078_spec.rb +0 -35
- data/spec/functional/fc079_spec.rb +0 -21
- data/spec/functional/fc080_spec.rb +0 -68
- data/spec/functional/fc081_spec.rb +0 -25
- data/spec/functional/fc082_spec.rb +0 -23
- data/spec/functional/fc083_spec.rb +0 -34
- data/spec/functional/fc084_spec.rb +0 -49
- data/spec/functional/fc085_spec.rb +0 -77
- data/spec/functional/fc086_spec.rb +0 -45
- data/spec/functional/fc087_spec.rb +0 -43
- data/spec/functional/fc088_spec.rb +0 -18
- data/spec/functional/fc089_spec.rb +0 -23
- data/spec/functional/fc091_spec.rb +0 -38
- data/spec/functional/fc092_spec.rb +0 -31
- data/spec/functional/fc093_spec.rb +0 -27
- data/spec/functional/fc094_spec.rb +0 -18
- data/spec/functional/fc095_spec.rb +0 -18
- data/spec/functional/fc096_spec.rb +0 -18
- data/spec/functional/fc097_spec.rb +0 -18
- data/spec/functional/fc098_spec.rb +0 -18
- data/spec/functional/fc099_spec.rb +0 -18
- data/spec/functional/fc100_spec.rb +0 -18
- data/spec/functional/fc101_spec.rb +0 -23
- data/spec/functional/fc102_spec.rb +0 -18
- data/spec/functional/fc103_spec.rb +0 -30
- data/spec/functional/fc104_spec.rb +0 -54
- data/spec/functional/fc105_spec.rb +0 -36
- data/spec/functional/fc106_spec.rb +0 -21
- data/spec/functional/fc107_spec.rb +0 -22
- data/spec/functional/fc108_spec.rb +0 -43
- data/spec/functional/fc109_spec.rb +0 -22
- data/spec/functional/fc110_spec.rb +0 -21
- data/spec/functional/fc111_spec.rb +0 -17
- data/spec/functional/fc112_spec.rb +0 -17
- data/spec/functional/fc113_spec.rb +0 -98
- data/spec/functional/fc114_spec.rb +0 -31
- data/spec/functional/fc115_spec.rb +0 -24
- data/spec/functional/fc116_spec.rb +0 -18
- data/spec/functional/fc117_spec.rb +0 -23
- data/spec/functional/fc118_spec.rb +0 -17
- data/spec/functional/fc119_spec.rb +0 -27
- data/spec/functional/fc120_spec.rb +0 -21
- data/spec/functional/fc121_spec.rb +0 -45
- data/spec/functional/fc122_spec.rb +0 -18
- data/spec/functional/root_aliases_spec.rb +0 -13
- data/spec/regression/cookbooks.txt +0 -83
- data/spec/regression/expected/activemq.txt +0 -6
- data/spec/regression/expected/aix.txt +0 -27
- data/spec/regression/expected/apparmor.txt +0 -9
- data/spec/regression/expected/apt.txt +0 -14
- data/spec/regression/expected/ark.txt +0 -3
- data/spec/regression/expected/auditd.txt +0 -2
- data/spec/regression/expected/aws.txt +0 -16
- data/spec/regression/expected/bluepill.txt +0 -12
- data/spec/regression/expected/boost.txt +0 -8
- data/spec/regression/expected/build-essential.txt +0 -8
- data/spec/regression/expected/chef-client.txt +0 -17
- data/spec/regression/expected/chef-ingredient.txt +0 -6
- data/spec/regression/expected/chef-server.txt +0 -13
- data/spec/regression/expected/chef-vault.txt +0 -7
- data/spec/regression/expected/chef.txt +0 -104
- data/spec/regression/expected/chef_client_updater.txt +0 -2
- data/spec/regression/expected/chef_handler.txt +0 -7
- data/spec/regression/expected/chef_hostname.txt +0 -3
- data/spec/regression/expected/chef_nginx.txt +0 -4
- data/spec/regression/expected/cron.txt +0 -7
- data/spec/regression/expected/database.txt +0 -42
- data/spec/regression/expected/dmg.txt +0 -11
- data/spec/regression/expected/docker.txt +0 -4
- data/spec/regression/expected/drbd.txt +0 -29
- data/spec/regression/expected/dynect.txt +0 -33
- data/spec/regression/expected/erlang.txt +0 -6
- data/spec/regression/expected/fail2ban.txt +0 -5
- data/spec/regression/expected/firewall.txt +0 -11
- data/spec/regression/expected/gecode.txt +0 -10
- data/spec/regression/expected/gems.txt +0 -32
- data/spec/regression/expected/gunicorn.txt +0 -11
- data/spec/regression/expected/heartbeat.txt +0 -8
- data/spec/regression/expected/homebrew.txt +0 -7
- data/spec/regression/expected/iis.txt +0 -22
- data/spec/regression/expected/iptables.txt +0 -9
- data/spec/regression/expected/jetty.txt +0 -13
- data/spec/regression/expected/jpackage.txt +0 -9
- data/spec/regression/expected/keepalived.txt +0 -3
- data/spec/regression/expected/kickstart.txt +0 -15
- data/spec/regression/expected/libarchive.txt +0 -6
- data/spec/regression/expected/logwatch.txt +0 -5
- data/spec/regression/expected/lvm.txt +0 -14
- data/spec/regression/expected/maradns.txt +0 -14
- data/spec/regression/expected/maven.txt +0 -8
- data/spec/regression/expected/memcached.txt +0 -31
- data/spec/regression/expected/motd-tail.txt +0 -5
- data/spec/regression/expected/mysql.txt +0 -19
- data/spec/regression/expected/ohai.txt +0 -9
- data/spec/regression/expected/openldap.txt +0 -12
- data/spec/regression/expected/openssh.txt +0 -6
- data/spec/regression/expected/openssl.txt +0 -6
- data/spec/regression/expected/partial_search.txt +0 -7
- data/spec/regression/expected/passenger_apache2.txt +0 -31
- data/spec/regression/expected/perl.txt +0 -14
- data/spec/regression/expected/php.txt +0 -6
- data/spec/regression/expected/postfix.txt +0 -8
- data/spec/regression/expected/powershell.txt +0 -8
- data/spec/regression/expected/resolver.txt +0 -7
- data/spec/regression/expected/rsync.txt +0 -9
- data/spec/regression/expected/rsyslog.txt +0 -11
- data/spec/regression/expected/runit.txt +0 -4
- data/spec/regression/expected/smokeping.txt +0 -6
- data/spec/regression/expected/sql_server.txt +0 -7
- data/spec/regression/expected/ssh_known_hosts.txt +0 -6
- data/spec/regression/expected/stompserver.txt +0 -6
- data/spec/regression/expected/subversion.txt +0 -6
- data/spec/regression/expected/sudo.txt +0 -10
- data/spec/regression/expected/tar.txt +0 -10
- data/spec/regression/expected/tftp.txt +0 -6
- data/spec/regression/expected/tomcat.txt +0 -18
- data/spec/regression/expected/transmission.txt +0 -13
- data/spec/regression/expected/ubuntu.txt +0 -5
- data/spec/regression/expected/ufw.txt +0 -12
- data/spec/regression/expected/unicorn.txt +0 -7
- data/spec/regression/expected/users.txt +0 -12
- data/spec/regression/expected/vcruntime.txt +0 -8
- data/spec/regression/expected/vim.txt +0 -7
- data/spec/regression/expected/webpi.txt +0 -7
- data/spec/regression/expected/whitelist-node-attrs.txt +0 -7
- data/spec/regression/expected/windows.txt +0 -35
- data/spec/regression/expected/wix.txt +0 -5
- data/spec/regression/expected/xml.txt +0 -7
- data/spec/regression/expected/yum.txt +0 -15
- data/spec/regression/regression_spec.rb +0 -23
- data/spec/spec_helper.rb +0 -132
- data/spec/unit/api_spec.rb +0 -1939
- data/spec/unit/chef_spec.rb +0 -66
- data/spec/unit/command_line_spec.rb +0 -136
- data/spec/unit/domain_spec.rb +0 -78
- data/spec/unit/linter_spec.rb +0 -107
- data/spec/unit/template_spec.rb +0 -53
@@ -1,418 +0,0 @@
|
|
1
|
-
module FoodCritic
|
2
|
-
|
3
|
-
# Helpers for asserting that the correct warnings are displayed.
|
4
|
-
#
|
5
|
-
# Unless the environment variable FC_FORK_PROCESS is set to 'true' then the features will be run in the same process.
|
6
|
-
module CommandHelpers
|
7
|
-
|
8
|
-
require "minitest"
|
9
|
-
include MiniTest::Assertions
|
10
|
-
|
11
|
-
attr_writer :assertions
|
12
|
-
def assertions
|
13
|
-
@assertions ||= 0
|
14
|
-
end
|
15
|
-
|
16
|
-
# The warning codes and messages displayed to the end user.
|
17
|
-
WARNINGS = {
|
18
|
-
"FC001" => "Use strings in preference to symbols to access node attributes",
|
19
|
-
"FC002" => "Avoid string interpolation where not required",
|
20
|
-
"FC004" => "Use a service resource to start and stop services",
|
21
|
-
"FC005" => "Avoid repetition of resource declarations",
|
22
|
-
"FC006" => "Mode should be quoted or fully specified when setting file permissions",
|
23
|
-
"FC007" => "Ensure recipe dependencies are reflected in cookbook metadata",
|
24
|
-
"FC008" => "Generated cookbook metadata needs updating",
|
25
|
-
"FC009" => "Resource attribute not recognised",
|
26
|
-
"FC010" => "Invalid search syntax",
|
27
|
-
"FC011" => "Missing README in markdown format",
|
28
|
-
"FC013" => "Use file_cache_path rather than hard-coding tmp paths",
|
29
|
-
"FC014" => "Consider extracting long ruby_block to library",
|
30
|
-
"FC015" => "Consider converting definition to a Custom Resource",
|
31
|
-
"FC016" => "LWRP does not declare a default action",
|
32
|
-
"FC018" => "LWRP uses deprecated notification syntax",
|
33
|
-
"FC019" => "Access node attributes in a consistent manner",
|
34
|
-
"FC021" => "Resource condition in provider may not behave as expected",
|
35
|
-
"FC022" => "Resource condition within loop may not behave as expected",
|
36
|
-
"FC024" => "Consider adding platform equivalents",
|
37
|
-
"FC027" => "Resource sets internal attribute",
|
38
|
-
"FC028" => "Incorrect #platform? usage",
|
39
|
-
"FC029" => "No leading cookbook name in recipe metadata",
|
40
|
-
"FC030" => "Cookbook contains debugger breakpoints",
|
41
|
-
"FC031" => "Cookbook without metadata.rb file",
|
42
|
-
"FC032" => "Invalid notification timing",
|
43
|
-
"FC033" => "Missing template file",
|
44
|
-
"FC034" => "Unused template variables",
|
45
|
-
"FC037" => "Invalid notification action",
|
46
|
-
"FC038" => "Invalid resource action",
|
47
|
-
"FC039" => "Node method cannot be accessed with key",
|
48
|
-
"FC040" => "Execute resource used to run git commands",
|
49
|
-
"FC041" => "Execute resource used to run curl or wget commands",
|
50
|
-
"FC042" => "Prefer include_recipe to require_recipe",
|
51
|
-
"FC043" => "Prefer new notification syntax",
|
52
|
-
"FC044" => "Avoid bare attribute keys",
|
53
|
-
"FC045" => "Metadata does not contain cookbook name",
|
54
|
-
"FC046" => "Attribute assignment uses assign unless nil",
|
55
|
-
"FC047" => "Attribute assignment does not specify precedence",
|
56
|
-
"FC049" => "Role name does not match containing file name",
|
57
|
-
"FC050" => "Name includes invalid characters",
|
58
|
-
"FC051" => "Template partials loop indefinitely",
|
59
|
-
"FC052" => 'Metadata uses the deprecated "suggests" keyword',
|
60
|
-
"FC053" => 'Metadata uses the deprecated "recommends" keyword',
|
61
|
-
"FC055" => "Ensure maintainer is set in metadata",
|
62
|
-
"FC056" => "Ensure maintainer_email is set in metadata",
|
63
|
-
"FC058" => "Library provider declares use_inline_resources and declares #action_<name> methods",
|
64
|
-
"FC060" => "LWRP provider declares use_inline_resources and declares #action_<name> methods",
|
65
|
-
"FC061" => "Valid cookbook versions are of the form x.y or x.y.z",
|
66
|
-
"FC062" => "Cookbook should have version metadata",
|
67
|
-
"FC063" => "Cookbook incorrectly depends on itself",
|
68
|
-
"FC064" => "Ensure issues_url is set in metadata",
|
69
|
-
"FC065" => "Ensure source_url is set in metadata",
|
70
|
-
"FC066" => "Ensure chef_version is set in metadata",
|
71
|
-
"FC067" => "Ensure at least one platform supported in metadata",
|
72
|
-
"FC068" => "Ensure license is set in metadata",
|
73
|
-
"FC069" => "Ensure standardized license defined in metadata",
|
74
|
-
"FC070" => "Ensure supports metadata defines valid platforms",
|
75
|
-
"FC071" => "Missing LICENSE file",
|
76
|
-
"FCTEST001" => "Test Rule",
|
77
|
-
}
|
78
|
-
|
79
|
-
# If the cucumber features should run foodcritic in the same process or spawn a separate process.
|
80
|
-
def self.running_in_process?
|
81
|
-
! (ENV.has_key?("FC_FORK_PROCESS") && ENV["FC_FORK_PROCESS"] == true.to_s)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Capture an error expected when calling a command.
|
85
|
-
def capture_error
|
86
|
-
yield
|
87
|
-
@error = all_output unless last_exit_status == 0
|
88
|
-
rescue => @error
|
89
|
-
end
|
90
|
-
|
91
|
-
# Return the last error captured
|
92
|
-
#
|
93
|
-
# @return [String] The last error captured
|
94
|
-
def last_error
|
95
|
-
@error.respond_to?(:message) ? @error.message : @error
|
96
|
-
end
|
97
|
-
|
98
|
-
# Expect a line of context
|
99
|
-
#
|
100
|
-
# @param [Number] line_no The line number
|
101
|
-
# @param [String] text The text of the matching line
|
102
|
-
def expect_line_shown(line_no, text)
|
103
|
-
expect_output %r{^ +#{Regexp.escape(line_no.to_s)}\|#{Regexp.escape(text)}$}
|
104
|
-
end
|
105
|
-
|
106
|
-
# Expect a warning to be included in the command output.
|
107
|
-
#
|
108
|
-
# @param [String] code The warning code to check for.
|
109
|
-
# @param [Hash] options The warning options.
|
110
|
-
# @option options [Integer] :line The line number the warning should appear on - nil for any line.
|
111
|
-
# @option options [Boolean] :expect_warning If false then assert that a warning is NOT present
|
112
|
-
# @option options [String] :file The path to the file the warning should be raised against
|
113
|
-
# @option options [Symbol] :file_type Alternative to specifying file name. One of: :attributes, :definition,
|
114
|
-
# :metadata, :provider, :resource
|
115
|
-
def expect_warning(code, options = {})
|
116
|
-
if options.has_key?(:file_type)
|
117
|
-
options[:file] = { :attributes => "attributes/default.rb", :definition => "definitions/apache_site.rb",
|
118
|
-
:metadata => "metadata.rb", :provider => "providers/site.rb",
|
119
|
-
:resource => "resources/site.rb", :libraries => "libraries/lib.rb" }[options[:file_type]]
|
120
|
-
end
|
121
|
-
options = { :line => 1, :expect_warning => true, :file => "recipes/default.rb" }.merge!(options)
|
122
|
-
unless options[:file].include?("roles") ||
|
123
|
-
options[:file].include?("environments")
|
124
|
-
options[:file] = "cookbooks/example/#{options[:file]}"
|
125
|
-
end
|
126
|
-
if options[:warning_only]
|
127
|
-
warning = "#{code}: #{WARNINGS[code]}"
|
128
|
-
else
|
129
|
-
warning = "#{code}: #{WARNINGS[code]}: #{options[:file]}:#{options[:line]}#{"\n" if ! options[:line].nil?}"
|
130
|
-
end
|
131
|
-
options[:expect_warning] ? expect_output(warning) : expect_no_output(warning)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Expect a warning not to be included in the command output.
|
135
|
-
#
|
136
|
-
# @see CommandHelpers#expect_warning
|
137
|
-
def expect_no_warning(code, options = { :expect_warning => false })
|
138
|
-
expect_warning(code, options)
|
139
|
-
end
|
140
|
-
|
141
|
-
# Expect a command line option / switch to be included in the usage.
|
142
|
-
#
|
143
|
-
# @param [String] short_switch The short version of the switch
|
144
|
-
# @param [String] long_switch The long descriptive version of the switch
|
145
|
-
# @param [String] description The description of the switch
|
146
|
-
def expect_usage_option(short_switch, long_switch, description)
|
147
|
-
expected_switch = "-#{Regexp.escape(short_switch)}, --#{Regexp.escape(long_switch)}[ ]+#{Regexp.escape(description)}"
|
148
|
-
expect_output(Regexp.new(expected_switch))
|
149
|
-
end
|
150
|
-
|
151
|
-
def has_test_warnings?(output)
|
152
|
-
output.split("\n").grep(/FC[0-9]+:/).map do |warn|
|
153
|
-
File.basename(File.dirname(warn.split(":").take(3).last.strip))
|
154
|
-
end.include?("test")
|
155
|
-
end
|
156
|
-
|
157
|
-
def man_page_options
|
158
|
-
man_path = Pathname.new(__FILE__) + "../../../man/foodcritic.1.ronn"
|
159
|
-
option_lines = File.read(man_path).split("## ").find do |s|
|
160
|
-
s.start_with?("OPTIONS")
|
161
|
-
end.split("\n").select { |o| o.start_with?(" *") }
|
162
|
-
option_lines.map do |o|
|
163
|
-
o.sub("`[`no-`]`", "").split("`").select { |f| f.include?("-") }
|
164
|
-
end.map do |option|
|
165
|
-
{ :short => option.first.sub(/^-/, ""),
|
166
|
-
:long => option.last.sub(/^--/, "") }
|
167
|
-
end.sort_by { |o| o[:short] }
|
168
|
-
end
|
169
|
-
|
170
|
-
# Assert that the usage message is displayed.
|
171
|
-
#
|
172
|
-
# @param [Boolean] is_exit_zero The exit code to check for.
|
173
|
-
def usage_displayed(is_exit_zero)
|
174
|
-
expect_output "foodcritic [cookbook_paths]"
|
175
|
-
|
176
|
-
usage_options.each do |option|
|
177
|
-
expect_usage_option(option[:short], option[:long], option[:description])
|
178
|
-
end
|
179
|
-
|
180
|
-
if is_exit_zero
|
181
|
-
assert_no_error_occurred
|
182
|
-
else
|
183
|
-
assert_error_occurred
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def usage_options
|
188
|
-
[
|
189
|
-
{ :short => "c", :long => "chef-version VERSION",
|
190
|
-
:description => "Only check against rules valid for this version of Chef." },
|
191
|
-
|
192
|
-
{ :short => "f", :long => "epic-fail TAGS",
|
193
|
-
:description => "Fail the build based on tags. Default of 'any' to fail on all warnings." },
|
194
|
-
|
195
|
-
{ :short => "l", :long => "list",
|
196
|
-
:description => "List all enabled rules and their descriptions." },
|
197
|
-
|
198
|
-
{ :short => "t", :long => "tags TAGS",
|
199
|
-
:description => "Check against (or exclude ~) rules with the specified tags." },
|
200
|
-
|
201
|
-
{ :short => "B", :long => "cookbook-path PATH",
|
202
|
-
:description => "Cookbook path(s) to check." },
|
203
|
-
|
204
|
-
{ :short => "C", :long => "[no-]context",
|
205
|
-
:description => "Show lines matched against rather than the default summary." },
|
206
|
-
|
207
|
-
{ :short => "E", :long => "environment-path PATH",
|
208
|
-
:description => "Environment path(s) to check." },
|
209
|
-
|
210
|
-
{ :short => "I", :long => "include PATH",
|
211
|
-
:description => "Additional rule file path(s) to load." },
|
212
|
-
|
213
|
-
{ :short => "R", :long => "role-path PATH",
|
214
|
-
:description => "Role path(s) to check." },
|
215
|
-
|
216
|
-
{ :short => "S", :long => "search-grammar PATH",
|
217
|
-
:description => "Specify grammar to use when validating search syntax." },
|
218
|
-
|
219
|
-
{ :short => "V", :long => "version",
|
220
|
-
:description => "Display the foodcritic version." },
|
221
|
-
|
222
|
-
{ :short => "X", :long => "exclude PATH",
|
223
|
-
:description => "Exclude path(s) from being linted. PATH is relative to the cookbook, not an absolute PATH. Default test/**/*,spec/**/*,features/**/*" },
|
224
|
-
|
225
|
-
]
|
226
|
-
end
|
227
|
-
|
228
|
-
def usage_options_for_diff
|
229
|
-
usage_options.map do |o|
|
230
|
-
{ :short => o[:short],
|
231
|
-
:long => o[:long].split(" ").first.sub(/^\[no-\]/, "") }
|
232
|
-
end.sort_by { |o| o[:short] }
|
233
|
-
end
|
234
|
-
|
235
|
-
end
|
236
|
-
|
237
|
-
# Helpers used when features are executed in-process.
|
238
|
-
module InProcessHelpers
|
239
|
-
|
240
|
-
# Assert that the output contains the specified warning.
|
241
|
-
#
|
242
|
-
# @param [String] output The warning to check for.
|
243
|
-
def expect_output(output)
|
244
|
-
if output.respond_to?(:~)
|
245
|
-
@review.must_match(output)
|
246
|
-
else
|
247
|
-
@review.must_include(output)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
# Assert that the output does not contain the specified warning.
|
252
|
-
#
|
253
|
-
# @param [String] output The output to check for.
|
254
|
-
def expect_no_output(output)
|
255
|
-
if output.respond_to?(:~)
|
256
|
-
@review.wont_match(output)
|
257
|
-
else
|
258
|
-
@review.wont_include(output)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
# Assert that an error occurred following a lint check.
|
263
|
-
def assert_error_occurred
|
264
|
-
@status.wont_equal 0
|
265
|
-
end
|
266
|
-
|
267
|
-
# Assert that no error occurred following a lint check.
|
268
|
-
def assert_no_error_occurred
|
269
|
-
@status.must_equal 0
|
270
|
-
end
|
271
|
-
|
272
|
-
# Assert that warnings have not been raised against the test code which
|
273
|
-
# should have been excluded from linting.
|
274
|
-
def assert_no_test_warnings
|
275
|
-
refute has_test_warnings?(@review)
|
276
|
-
end
|
277
|
-
|
278
|
-
# Assert that warnings have been raised against the test code which
|
279
|
-
# shouldn't have been excluded from linting.
|
280
|
-
def assert_test_warnings
|
281
|
-
assert has_test_warnings?(@review)
|
282
|
-
end
|
283
|
-
|
284
|
-
# Run a lint check with the provided command line arguments.
|
285
|
-
#
|
286
|
-
# @param [Array] cmd_args The command line arguments.
|
287
|
-
def run_lint(cmd_args)
|
288
|
-
cd "." do
|
289
|
-
show_context = cmd_args.include?("-C")
|
290
|
-
review, @status = FoodCritic::Linter.run(CommandLine.new(cmd_args))
|
291
|
-
@review =
|
292
|
-
if review.nil? || (review.respond_to?(:warnings) && review.warnings.empty?)
|
293
|
-
""
|
294
|
-
elsif show_context
|
295
|
-
ContextOutput.new.output(review)
|
296
|
-
else
|
297
|
-
"#{review}\n"
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
end
|
303
|
-
|
304
|
-
# For use with steps that use bundler and rake. These will always be run
|
305
|
-
# via Aruba.
|
306
|
-
module BuildHelpers
|
307
|
-
|
308
|
-
# Assert the build outcome
|
309
|
-
#
|
310
|
-
# @param [Boolean] success True if the build should succeed
|
311
|
-
# @param [Array] warnings The warnings expected
|
312
|
-
def assert_build_result(success, warnings)
|
313
|
-
success ? assert_no_error_occurred : assert_error_occurred
|
314
|
-
warnings.each do |code|
|
315
|
-
expect_warning(code, :warning_only => true)
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
# Assert that warnings have not been raised against the test code which
|
320
|
-
# should have been excluded from linting.
|
321
|
-
def assert_no_test_warnings
|
322
|
-
refute has_test_warnings?(all_output)
|
323
|
-
end
|
324
|
-
|
325
|
-
# Assert that warnings have been raised against the test code which
|
326
|
-
# shouldn't have been excluded from linting.
|
327
|
-
def assert_test_warnings
|
328
|
-
assert has_test_warnings?(all_output)
|
329
|
-
end
|
330
|
-
|
331
|
-
# The available tasks for this build
|
332
|
-
#
|
333
|
-
# @return [Array] Task name and description
|
334
|
-
def build_tasks
|
335
|
-
all_output.split("\n").map do |task|
|
336
|
-
next unless task.start_with? "rake"
|
337
|
-
task.split("#").map { |t| t.strip.sub(/^rake /, "") }
|
338
|
-
end.compact
|
339
|
-
end
|
340
|
-
|
341
|
-
# List the defined Rake tasks
|
342
|
-
def list_available_build_tasks
|
343
|
-
cd "cookbooks/example"
|
344
|
-
unset_bundler_env_vars
|
345
|
-
run_simple "bundle exec rake -T"
|
346
|
-
end
|
347
|
-
|
348
|
-
# Run a build for a Rakefile that uses the lint rake task
|
349
|
-
def run_build
|
350
|
-
cd "cookbooks/example"
|
351
|
-
run_simple "bundle exec rake", false
|
352
|
-
end
|
353
|
-
|
354
|
-
# We want to avoid traversing vendored gems because of the unnecessary
|
355
|
-
# performance hit and because gems may contain deeply-nested code which
|
356
|
-
# will blow the stack on parsing.
|
357
|
-
def vendor_gems
|
358
|
-
cd "cookbooks/example"
|
359
|
-
unset_bundler_env_vars
|
360
|
-
run_simple "bundle install --path vendor/bundle"
|
361
|
-
cd "../.."
|
362
|
-
end
|
363
|
-
|
364
|
-
end
|
365
|
-
|
366
|
-
# Helpers used when features are executed out of process.
|
367
|
-
module ArubaHelpers
|
368
|
-
|
369
|
-
include BuildHelpers
|
370
|
-
|
371
|
-
# Assert that the output contains the specified warning.
|
372
|
-
#
|
373
|
-
# @param [String] output The output to check for.
|
374
|
-
def expect_output(output)
|
375
|
-
if output.respond_to?(:~)
|
376
|
-
assert_matching_output(output.to_s, all_output)
|
377
|
-
else
|
378
|
-
assert_partial_output(output, all_output)
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
|
-
# Assert that the output does not contain the specified warning.
|
383
|
-
#
|
384
|
-
# @param [String] output The output to check for.
|
385
|
-
def expect_no_output(output)
|
386
|
-
if output.respond_to?(:~)
|
387
|
-
assert_matching_output('^((?!#{output}).)*$', all_output)
|
388
|
-
else
|
389
|
-
assert_no_partial_output(output, all_output)
|
390
|
-
end
|
391
|
-
end
|
392
|
-
|
393
|
-
# Assert that an error occurred following a lint check.
|
394
|
-
def assert_error_occurred
|
395
|
-
assert_not_exit_status 0
|
396
|
-
end
|
397
|
-
|
398
|
-
# Assert that no error occurred following a lint check.
|
399
|
-
def assert_no_error_occurred
|
400
|
-
assert_exit_status(0)
|
401
|
-
end
|
402
|
-
|
403
|
-
# Run a lint check with the provided command line arguments.
|
404
|
-
#
|
405
|
-
# @param [Array] cmd_args The command line arguments.
|
406
|
-
def run_lint(cmd_args)
|
407
|
-
run_simple(unescape("foodcritic #{cmd_args.join(' ')}"), false)
|
408
|
-
end
|
409
|
-
end
|
410
|
-
|
411
|
-
end
|
412
|
-
|
413
|
-
World(FoodCritic::CommandHelpers)
|
414
|
-
if FoodCritic::CommandHelpers.running_in_process?
|
415
|
-
World(FoodCritic::InProcessHelpers)
|
416
|
-
else
|
417
|
-
World(FoodCritic::ArubaHelpers)
|
418
|
-
end
|
@@ -1,599 +0,0 @@
|
|
1
|
-
module FoodCritic
|
2
|
-
|
3
|
-
# Helper cookbook methods for use in your steps.
|
4
|
-
module CookbookHelpers
|
5
|
-
|
6
|
-
# Create an attributes file that references attributes with symbols
|
7
|
-
#
|
8
|
-
# @param [String] type The type of node attribute to write
|
9
|
-
def attributes_with_symbols(type)
|
10
|
-
write_attributes %Q{#{type}[:apache][:dir] = "/etc/apache2"}
|
11
|
-
end
|
12
|
-
|
13
|
-
# Create a Gemfile for a cookbook
|
14
|
-
def buildable_gemfile
|
15
|
-
write_file "cookbooks/example/Gemfile", %q{
|
16
|
-
source 'https://rubygems.org/'
|
17
|
-
gem 'rake'
|
18
|
-
gem 'foodcritic', :path => '../../../..'
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
# Create a cookbook that declares dependencies on external recipes.
|
23
|
-
#
|
24
|
-
# @param [Symbol] declaration_type The type of declaration - :brace or :bracket
|
25
|
-
def cookbook_declares_dependencies(declaration_type)
|
26
|
-
write_recipe %q{
|
27
|
-
include_recipe "foo::default"
|
28
|
-
include_recipe "bar::default"
|
29
|
-
include_recipe "baz::default"
|
30
|
-
}
|
31
|
-
if declaration_type == :brace
|
32
|
-
write_metadata %q{
|
33
|
-
%w{foo bar baz}.each{|cookbook| depends cookbook}
|
34
|
-
}
|
35
|
-
else
|
36
|
-
write_metadata %q{
|
37
|
-
%w{foo bar baz}.each do |cb|
|
38
|
-
depends cb
|
39
|
-
end
|
40
|
-
}
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Create a cookbook that will match the specified rules.
|
45
|
-
#
|
46
|
-
# @param [Array] codes The codes to match. Only FC002, FC004 and FC005 and FC006 are supported.
|
47
|
-
def cookbook_that_matches_rules(codes)
|
48
|
-
recipe = ""
|
49
|
-
codes.each do |code|
|
50
|
-
if code == "FC002"
|
51
|
-
recipe += %q{
|
52
|
-
directory "#{node['base_dir']}" do
|
53
|
-
action :create
|
54
|
-
end
|
55
|
-
}
|
56
|
-
elsif code == "FC004"
|
57
|
-
recipe += %q{
|
58
|
-
execute "stop-jetty" do
|
59
|
-
command "/etc/init.d/jetty6 stop"
|
60
|
-
action :run
|
61
|
-
end
|
62
|
-
}
|
63
|
-
elsif code == "FC005"
|
64
|
-
recipe += %q{
|
65
|
-
package 'erlang-base' do
|
66
|
-
action :upgrade
|
67
|
-
end
|
68
|
-
package 'erlang-corba' do
|
69
|
-
action :upgrade
|
70
|
-
end
|
71
|
-
package 'erlang-another' do
|
72
|
-
action :upgrade
|
73
|
-
end
|
74
|
-
}
|
75
|
-
elsif code == "FC006"
|
76
|
-
recipe += %q{
|
77
|
-
directory "/var/lib/foo" do
|
78
|
-
mode 644
|
79
|
-
action :create
|
80
|
-
end
|
81
|
-
}
|
82
|
-
end
|
83
|
-
end
|
84
|
-
write_recipe(recipe)
|
85
|
-
write_file("cookbooks/example/recipes/server.rb", "")
|
86
|
-
write_readme("Hello World") # Don't trigger FC011
|
87
|
-
write_metadata(%q{
|
88
|
-
name 'example'
|
89
|
-
maintainer 'A Maintainer'
|
90
|
-
maintainer_email 'maintainer@example.com'
|
91
|
-
version '0.0.1'
|
92
|
-
issues_url 'http://github.com/foo/bar_cookbook/issues'
|
93
|
-
source_url 'http://github.com/foo/bar_cookbook'
|
94
|
-
}.strip)
|
95
|
-
end
|
96
|
-
|
97
|
-
# Create a cookbook with a custom resource
|
98
|
-
#
|
99
|
-
# @author Tim Smith - tsmith@chef.io
|
100
|
-
# @since 10.1.1
|
101
|
-
def cookbook_with_custom_resource
|
102
|
-
write_resource("site", %Q{
|
103
|
-
property :name, String, name_property: true
|
104
|
-
property :variables, Hash, default: {}
|
105
|
-
|
106
|
-
action :create do
|
107
|
-
log "Here is where I would create a " + thing
|
108
|
-
end
|
109
|
-
|
110
|
-
action_class do
|
111
|
-
def thing
|
112
|
-
return "site"
|
113
|
-
end
|
114
|
-
end
|
115
|
-
})
|
116
|
-
end
|
117
|
-
|
118
|
-
# Create a cookbook with a LRWP
|
119
|
-
#
|
120
|
-
# @param [Hash] lwrp The options to use for the created LWRP
|
121
|
-
# @option lwrp [Symbol] :default_action One of :no_default_action, :ruby_default_action, :dsl_default_action
|
122
|
-
# @option lwrp [Symbol] :notifies One of :does_not_notify, :does_notify, :does_notify_without_parens, :deprecated_syntax, :class_variable
|
123
|
-
# @option lwrp [Symbol] :use_inline_resources Defaults to false
|
124
|
-
def cookbook_with_lwrp(lwrp)
|
125
|
-
lwrp = { :default_action => false, :notifies => :does_not_notify,
|
126
|
-
:use_inline_resources => false }.merge!(lwrp)
|
127
|
-
ruby_default_action = %q{
|
128
|
-
def initialize(*args)
|
129
|
-
super
|
130
|
-
@action = :create
|
131
|
-
end
|
132
|
-
}.strip
|
133
|
-
write_resource("site", %Q{
|
134
|
-
actions :create
|
135
|
-
attribute :name, :kind_of => String, :name_attribute => true
|
136
|
-
#{ruby_default_action if lwrp[:default_action] == :ruby_default_action}
|
137
|
-
#{'default_action :create' if lwrp[:default_action] == :dsl_default_action}
|
138
|
-
})
|
139
|
-
notifications = { :does_notify => "new_resource.updated_by_last_action(true)",
|
140
|
-
:does_notify_without_parens => "new_resource.updated_by_last_action true",
|
141
|
-
:deprecated_syntax => "new_resource.updated = true",
|
142
|
-
:class_variable => "@updated = true" }
|
143
|
-
write_provider("site", %Q{
|
144
|
-
#{'use_inline_resources' if lwrp[:use_inline_resources]}
|
145
|
-
action :create do
|
146
|
-
log "Here is where I would create a site"
|
147
|
-
#{notifications[lwrp[:notifies]]}
|
148
|
-
end
|
149
|
-
})
|
150
|
-
end
|
151
|
-
|
152
|
-
def cookbook_with_lwrp_actions(actions)
|
153
|
-
write_resource("site", %Q{
|
154
|
-
actions #{actions.map { |a| a[:name].inspect }.join(', ')}
|
155
|
-
attribute :name, :kind_of => String, :name_attribute => true
|
156
|
-
})
|
157
|
-
write_provider("site", actions.map { |a| provider_action(a) }.join("\n"))
|
158
|
-
end
|
159
|
-
|
160
|
-
# Create an cookbook with the maintainer specified in the metadata
|
161
|
-
#
|
162
|
-
# @param [String] name The maintainer name
|
163
|
-
# @param [String] email The maintainer email address
|
164
|
-
def cookbook_with_maintainer(name, email)
|
165
|
-
write_recipe %q{
|
166
|
-
#
|
167
|
-
# Cookbook Name:: example
|
168
|
-
# Recipe:: default
|
169
|
-
#
|
170
|
-
# Copyright 2011, YOUR_COMPANY_NAME
|
171
|
-
#
|
172
|
-
# All rights reserved - Do Not Redistribute
|
173
|
-
#
|
174
|
-
}
|
175
|
-
|
176
|
-
fields = {}
|
177
|
-
fields["maintainer"] = name unless name.nil?
|
178
|
-
fields["maintainer_email"] = email unless email.nil?
|
179
|
-
write_metadata %Q{
|
180
|
-
#{fields.map { |field, value| %Q{#{field}\t"#{value}"} }.join("\n")}
|
181
|
-
license "All rights reserved"
|
182
|
-
description "Installs/Configures example"
|
183
|
-
long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
|
184
|
-
version "0.0.1"
|
185
|
-
}
|
186
|
-
end
|
187
|
-
|
188
|
-
# Create an environment file
|
189
|
-
#
|
190
|
-
# @param [Hash] options The options to use for the environment
|
191
|
-
# @option options [String] :dir The relative directory to write to
|
192
|
-
# @option options [String] :environment_name The name of the environment declared in the file
|
193
|
-
# @option options [String] :file_name The containing file relative to the environments directory
|
194
|
-
def environment(options = {})
|
195
|
-
options = { :dir => "environments" }.merge(options)
|
196
|
-
write_file "#{options[:dir]}/#{options[:file_name]}", %Q{
|
197
|
-
#{Array(options[:environment_name]).map { |r| "name #{r}" }.join("\n")}
|
198
|
-
cookbook "apache2"
|
199
|
-
}.strip
|
200
|
-
end
|
201
|
-
|
202
|
-
# Create a placeholder minitest spec that would be linted due to its path
|
203
|
-
# unless an exclusion is specified.
|
204
|
-
def minitest_spec_attributes
|
205
|
-
write_file "cookbooks/example/test/attributes/default_spec.rb", %q{
|
206
|
-
describe 'Example::Attributes::Default' do
|
207
|
-
end
|
208
|
-
}
|
209
|
-
end
|
210
|
-
|
211
|
-
def provider_action(action)
|
212
|
-
case action[:notify_type]
|
213
|
-
when :none then %Q{
|
214
|
-
action #{action[:name].inspect} do
|
215
|
-
log "Would take action here"
|
216
|
-
end
|
217
|
-
}
|
218
|
-
when :updated_by_last_action then %Q{
|
219
|
-
action #{action[:name].inspect} do
|
220
|
-
log "Would take action here"
|
221
|
-
# Explicitly update
|
222
|
-
new_resource.updated_by_last_action(true)
|
223
|
-
end
|
224
|
-
}
|
225
|
-
when :converge_by then %Q{
|
226
|
-
action #{action[:name].inspect} do
|
227
|
-
converge_by "#{action[:name]} site" do
|
228
|
-
log "Would take action here"
|
229
|
-
end
|
230
|
-
end
|
231
|
-
}
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
# Create a Rakefile that uses the linter rake task
|
236
|
-
#
|
237
|
-
# @param [Symbol] task Type of task
|
238
|
-
# @param [Hash] options Task options
|
239
|
-
# @option options [String] :name Task name
|
240
|
-
# @option options [String] :files Files to process
|
241
|
-
# @option options [String] :options The options to set on the rake task
|
242
|
-
def rakefile(task, options)
|
243
|
-
rakefile_content = "task :default => []"
|
244
|
-
task_def = case task
|
245
|
-
when :no_block then "FoodCritic::Rake::LintTask.new"
|
246
|
-
else %Q{
|
247
|
-
FoodCritic::Rake::LintTask.new do |t|
|
248
|
-
#{"t.name = '#{options[:name]}'" if options[:name]}
|
249
|
-
#{"t.files = #{options[:files]}" if options[:files]}
|
250
|
-
#{"t.options = #{options[:options]}" if options[:options]}
|
251
|
-
end
|
252
|
-
}
|
253
|
-
end
|
254
|
-
if task_def
|
255
|
-
rakefile_content = %Q{
|
256
|
-
require 'foodcritic'
|
257
|
-
task :default => [:#{options[:name] ? options[:name] : 'foodcritic'}]
|
258
|
-
#{task_def}
|
259
|
-
}
|
260
|
-
end
|
261
|
-
write_file "cookbooks/example/Rakefile", rakefile_content
|
262
|
-
end
|
263
|
-
|
264
|
-
# Create a recipe that downloads a file
|
265
|
-
#
|
266
|
-
# @param [Symbol] path_type The type of path, one of: :tmp_dir, :chef_file_cache_dir, :home_dir
|
267
|
-
def recipe_downloads_file(path_type)
|
268
|
-
download_path = { :tmp_dir => "/tmp/large-file.tar.gz",
|
269
|
-
:tmp_dir_expr => '/tmp/#{file}',
|
270
|
-
:home_dir => "/home/ernie/large-file.tar.gz",
|
271
|
-
:chef_file_cache_dir => '#{Chef::Config[:file_cache_path]}/large-file.tar.gz' }[path_type]
|
272
|
-
write_recipe %Q{
|
273
|
-
remote_file "#{download_path}" do
|
274
|
-
source "http://www.example.org/large-file.tar.gz"
|
275
|
-
end
|
276
|
-
}
|
277
|
-
end
|
278
|
-
|
279
|
-
# Install a gem using the specified approach.
|
280
|
-
#
|
281
|
-
# @param [Symbol] type The type of approach, one of :simple, :compile_time,
|
282
|
-
# :compile_time_from_array, :compile_time_from_word_list
|
283
|
-
# @param [Symbol] action Either :install or :upgrade
|
284
|
-
def recipe_installs_gem(type, action = :install)
|
285
|
-
case type
|
286
|
-
when :simple
|
287
|
-
write_recipe %Q{
|
288
|
-
gem_package "bluepill" do
|
289
|
-
action :#{action}
|
290
|
-
end
|
291
|
-
}.strip
|
292
|
-
when :compile_time
|
293
|
-
write_recipe %Q{
|
294
|
-
r = gem_package "mysql" do
|
295
|
-
action :nothing
|
296
|
-
end
|
297
|
-
|
298
|
-
r.run_action(:#{action})
|
299
|
-
Gem.clear_paths
|
300
|
-
}.strip
|
301
|
-
when :compile_time_from_array
|
302
|
-
write_recipe %Q{
|
303
|
-
['foo', 'bar', 'baz'].each do |pkg|
|
304
|
-
r = gem_package pkg do
|
305
|
-
action :nothing
|
306
|
-
end
|
307
|
-
r.run_action(:#{action})
|
308
|
-
end
|
309
|
-
}.strip
|
310
|
-
when :compile_time_from_word_list
|
311
|
-
write_recipe %Q{
|
312
|
-
%w{foo bar baz}.each do |pkg|
|
313
|
-
r = gem_package pkg do
|
314
|
-
action :nothing
|
315
|
-
end
|
316
|
-
r.run_action(:#{action})
|
317
|
-
end
|
318
|
-
}.strip
|
319
|
-
else
|
320
|
-
raise "Unrecognised type: #{type}"
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
# Create a recipe that declares a resource with the specified file mode.
|
325
|
-
#
|
326
|
-
# @param [String] type The type of resource (file, template)
|
327
|
-
# @param [String] mode The file mode as a string
|
328
|
-
# @param [String] comment Comment that may specify to exclude a match
|
329
|
-
def recipe_resource_with_mode(type, mode, comment = "")
|
330
|
-
source_att = type == "template" ? 'source "foo.erb"' : ""
|
331
|
-
write_recipe %Q{
|
332
|
-
#{type} "/tmp/something" do #{comment}
|
333
|
-
#{source_att}
|
334
|
-
owner "root"
|
335
|
-
group "root"
|
336
|
-
mode #{mode}
|
337
|
-
action :create
|
338
|
-
end
|
339
|
-
}
|
340
|
-
end
|
341
|
-
|
342
|
-
# Create a recipe with an external dependency on another cookbook.
|
343
|
-
#
|
344
|
-
# @param [Hash] dep The options to use for dependency
|
345
|
-
# @option dep [Boolean] :is_declared True if this dependency has been declared in the cookbook metadata
|
346
|
-
# @option dep [Boolean] :is_scoped True if the include_recipe references a specific recipe or the cookbook
|
347
|
-
# @option dep [Boolean] :parentheses True if the include_recipe is called with parentheses
|
348
|
-
def recipe_with_dependency(dep)
|
349
|
-
dep = { :is_scoped => true, :is_declared => true,
|
350
|
-
:parentheses => false }.merge!(dep)
|
351
|
-
recipe = "foo#{dep[:is_scoped] ? '::default' : ''}"
|
352
|
-
write_recipe(if dep[:parentheses]
|
353
|
-
"include_recipe('#{recipe}')"
|
354
|
-
else
|
355
|
-
"include_recipe '#{recipe}'"
|
356
|
-
end)
|
357
|
-
write_metadata %Q{
|
358
|
-
version "1.9.0"
|
359
|
-
depends "#{dep[:is_declared] ? 'foo' : 'dogs'}"
|
360
|
-
}
|
361
|
-
end
|
362
|
-
|
363
|
-
# Create a recipe with a directory resource
|
364
|
-
#
|
365
|
-
# @param [Symbol] path_expr_type The type of path expression, one of: :compound_symbols, :interpolated_string,
|
366
|
-
# :interpolated_symbol, :interpolated_symbol_and_literal, :literal_and_interpolated_symbol, :string_literal.
|
367
|
-
def recipe_with_dir_path(path_expr_type)
|
368
|
-
path = { :compound_symbols => '#{node[:base_dir]}#{node[:sub_dir]}', :interpolated_string => %q{#{node['base_dir']}},
|
369
|
-
:interpolated_symbol => '#{node[:base_dir]}', :interpolated_symbol_and_literal => '#{node[:base_dir]}/sub_dir',
|
370
|
-
:literal_and_interpolated_symbol => 'base_dir/#{node[:sub_dir]}', :string_literal => "/var/lib/foo" }[path_expr_type]
|
371
|
-
write_recipe %Q{
|
372
|
-
directory "#{path}" do
|
373
|
-
owner "root"
|
374
|
-
group "root"
|
375
|
-
mode "0755"
|
376
|
-
action :create
|
377
|
-
end
|
378
|
-
}
|
379
|
-
end
|
380
|
-
|
381
|
-
# Create a recipe with the specified resource type and attribute names.
|
382
|
-
#
|
383
|
-
# @param [String] type The type of resource
|
384
|
-
# @param [Array] attribute_names The attributes to declare on this resource
|
385
|
-
def recipe_with_resource(type, attribute_names)
|
386
|
-
write_recipe %Q{
|
387
|
-
#{type} "resource-name" do
|
388
|
-
#{attribute_names.join(" 'foo'\n")} 'bar'
|
389
|
-
end
|
390
|
-
}
|
391
|
-
end
|
392
|
-
|
393
|
-
# Create a recipe with a ruby_block resource.
|
394
|
-
#
|
395
|
-
# @param [Symbol] length A :short or :long block, or :both
|
396
|
-
def recipe_with_ruby_block(length)
|
397
|
-
recipe = ""
|
398
|
-
if length == :short || length == :both
|
399
|
-
recipe << %q{
|
400
|
-
ruby_block "subexpressions" do
|
401
|
-
block do
|
402
|
-
rc = Chef::Util::FileEdit.new("/foo/bar.conf")
|
403
|
-
rc.search_file_replace_line(/^search/, "search #{node["foo"]["bar"]} compute-1.internal")
|
404
|
-
rc.search_file_replace_line(/^domain/, "domain #{node["foo"]["bar"]}")
|
405
|
-
rc.write_file
|
406
|
-
end
|
407
|
-
action :create
|
408
|
-
end
|
409
|
-
}
|
410
|
-
end
|
411
|
-
if length == :long || length == :both
|
412
|
-
recipe << %q{
|
413
|
-
ruby_block "too_long" do
|
414
|
-
block do
|
415
|
-
begin
|
416
|
-
do_something('with argument')
|
417
|
-
do_something_else('with another argument')
|
418
|
-
foo = Foo.new('bar')
|
419
|
-
foo.activate_turbo_boost
|
420
|
-
foo.each do |thing|
|
421
|
-
case thing
|
422
|
-
when "fee"
|
423
|
-
puts 'Fee'
|
424
|
-
when "fi"
|
425
|
-
puts 'Fi'
|
426
|
-
when "fo"
|
427
|
-
puts 'Fo'
|
428
|
-
else
|
429
|
-
puts "Fum"
|
430
|
-
end
|
431
|
-
end
|
432
|
-
rescue Some::Exception
|
433
|
-
Chef::Log.warn "Problem activating the turbo boost"
|
434
|
-
end
|
435
|
-
end
|
436
|
-
action :create
|
437
|
-
end
|
438
|
-
}
|
439
|
-
end
|
440
|
-
write_recipe(recipe)
|
441
|
-
end
|
442
|
-
|
443
|
-
# Create a recipe that performs a search of the specified type.
|
444
|
-
#
|
445
|
-
# @param [Symbol] type The type of search. One of: :invalid_syntax, :valid_syntax, :with_subexpression.
|
446
|
-
def recipe_with_search(type)
|
447
|
-
search = { :invalid_syntax => "run_list:recipe[foo::bar]", :valid_syntax => 'run_list:recipe\[foo\:\:bar\]',
|
448
|
-
:with_subexpression => %q{roles:#{node['foo']['role']}} }[type]
|
449
|
-
write_recipe %Q{
|
450
|
-
search(:node, "#{search}") do |matching_node|
|
451
|
-
puts matching_node.to_s
|
452
|
-
end
|
453
|
-
}
|
454
|
-
end
|
455
|
-
|
456
|
-
# Create a role file
|
457
|
-
#
|
458
|
-
# @param [Hash] options The options to use for the role
|
459
|
-
# @option options [String] :role_name The name of the role declared in the role file
|
460
|
-
# @option options [String] :file_name The containing file relative to the roles directory
|
461
|
-
# @option options [Symbol] :format Either :ruby or :json. Default is :ruby
|
462
|
-
def role(options = {})
|
463
|
-
options = { :format => :ruby, :dir => "roles" }.merge(options)
|
464
|
-
content = if options[:format] == :json
|
465
|
-
%Q{
|
466
|
-
{
|
467
|
-
"chef_type": "role",
|
468
|
-
"json_class": "Chef::Role",
|
469
|
-
#{Array(options[:role_name]).map { |r| "name: #{r}," }.join("\n")}
|
470
|
-
"run_list": [
|
471
|
-
"recipe[apache2]",
|
472
|
-
]
|
473
|
-
}
|
474
|
-
}
|
475
|
-
else
|
476
|
-
%Q{
|
477
|
-
#{Array(options[:role_name]).map { |r| "name #{r}" }.join("\n")}
|
478
|
-
run_list "recipe[apache2]"
|
479
|
-
}
|
480
|
-
end
|
481
|
-
write_file "#{options[:dir]}/#{options[:file_name]}", content.strip
|
482
|
-
end
|
483
|
-
|
484
|
-
# Create a rule with the specified Chef version constraints
|
485
|
-
#
|
486
|
-
# @param [String] from_version The from version
|
487
|
-
# @param [String] to_version The to version
|
488
|
-
def rule_with_version_constraint(from_version, to_version)
|
489
|
-
constraint = if from_version && to_version
|
490
|
-
%Q{
|
491
|
-
applies_to do |version|
|
492
|
-
version >= gem_version("#{from_version}") && version <= gem_version("#{to_version}")
|
493
|
-
end
|
494
|
-
}
|
495
|
-
elsif from_version
|
496
|
-
%Q{
|
497
|
-
applies_to do |version|
|
498
|
-
version >= gem_version("#{from_version}")
|
499
|
-
end
|
500
|
-
}
|
501
|
-
elsif to_version
|
502
|
-
%Q{
|
503
|
-
applies_to do |version|
|
504
|
-
version <= gem_version("#{to_version}")
|
505
|
-
end
|
506
|
-
}
|
507
|
-
end
|
508
|
-
write_rule %Q{
|
509
|
-
rule "FCTEST001", "Test Rule" do
|
510
|
-
#{constraint}
|
511
|
-
recipe do |ast, filename|
|
512
|
-
[file_match(filename)]
|
513
|
-
end
|
514
|
-
end
|
515
|
-
}
|
516
|
-
end
|
517
|
-
|
518
|
-
# Return the provided string or nil if 'unspecified'
|
519
|
-
#
|
520
|
-
# @param [String] str The string
|
521
|
-
# @return [String] The string or nil if 'unspecified'
|
522
|
-
def nil_if_unspecified(str)
|
523
|
-
str == "unspecified" ? nil : str
|
524
|
-
end
|
525
|
-
|
526
|
-
# Create a README with the provided content.
|
527
|
-
#
|
528
|
-
# @param [String] content The recipe content.
|
529
|
-
# @param [String] cookbook_name Optional name of the cookbook.
|
530
|
-
def write_readme(content, cookbook_name = "example")
|
531
|
-
write_file "cookbooks/#{cookbook_name}/README.md", content.strip
|
532
|
-
end
|
533
|
-
|
534
|
-
# Create a recipe with the provided content.
|
535
|
-
#
|
536
|
-
# @param [String] content The recipe content.
|
537
|
-
# @param [String] cookbook_name Optional name of the cookbook.
|
538
|
-
def write_recipe(content, cookbook_name = "example")
|
539
|
-
write_file "cookbooks/#{cookbook_name}/recipes/default.rb", content.strip
|
540
|
-
end
|
541
|
-
|
542
|
-
# Create a rule with the provided content.
|
543
|
-
#
|
544
|
-
# @param [String] content The rule content.
|
545
|
-
def write_rule(content)
|
546
|
-
write_file "rules/test.rb", content.strip
|
547
|
-
end
|
548
|
-
|
549
|
-
# Create attributes with the provided content.
|
550
|
-
#
|
551
|
-
# @param [String] content The attributes content.
|
552
|
-
def write_attributes(content)
|
553
|
-
write_file "cookbooks/example/attributes/default.rb", content.strip
|
554
|
-
end
|
555
|
-
|
556
|
-
# Create a definition with the provided content.
|
557
|
-
#
|
558
|
-
# @param [String] name The definition name.
|
559
|
-
# @param [String] content The definition content.
|
560
|
-
def write_definition(name, content)
|
561
|
-
write_file "cookbooks/example/definitions/#{name}.rb", content.strip
|
562
|
-
end
|
563
|
-
|
564
|
-
# Create a library with the provided content.
|
565
|
-
#
|
566
|
-
# @param [String] name The library name.
|
567
|
-
# @param [String] content The library content.
|
568
|
-
def write_library(name, content)
|
569
|
-
write_file "cookbooks/example/libraries/#{name}.rb", content.strip
|
570
|
-
end
|
571
|
-
|
572
|
-
# Create metdata with the provided content.
|
573
|
-
#
|
574
|
-
# @param [String] content The metadata content.
|
575
|
-
def write_metadata(content)
|
576
|
-
write_file "cookbooks/example/metadata.rb", content.strip
|
577
|
-
end
|
578
|
-
|
579
|
-
# Create a resource with the provided content.
|
580
|
-
#
|
581
|
-
# @param [String] name The resource name.
|
582
|
-
# @param [String] content The resource content.
|
583
|
-
def write_resource(name, content)
|
584
|
-
write_file "cookbooks/example/resources/#{name}.rb", content.strip
|
585
|
-
end
|
586
|
-
|
587
|
-
# Create a provider with the provided content.
|
588
|
-
#
|
589
|
-
# @param [String] name The resource name.
|
590
|
-
# @param [String] content The resource content.
|
591
|
-
def write_provider(name, content)
|
592
|
-
write_file "cookbooks/example/providers/#{name}.rb", content.strip
|
593
|
-
end
|
594
|
-
|
595
|
-
end
|
596
|
-
|
597
|
-
end
|
598
|
-
|
599
|
-
World(FoodCritic::CookbookHelpers)
|