inspec 2.2.20 → 2.2.27
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 +29 -12
- data/docs/resources/file.md.erb +10 -3
- data/lib/inspec/base_cli.rb +2 -0
- data/lib/inspec/cli.rb +5 -0
- data/lib/inspec/dependencies/dependency_set.rb +3 -3
- data/lib/inspec/dependencies/requirement.rb +18 -11
- data/lib/inspec/profile.rb +9 -1
- data/lib/inspec/reporters/json.rb +1 -0
- data/lib/inspec/resource.rb +21 -9
- data/lib/inspec/runner_rspec.rb +2 -2
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/aide_conf.rb +3 -5
- data/lib/resources/apache_conf.rb +8 -0
- data/lib/resources/auditd.rb +13 -15
- data/lib/resources/aws/aws_cloudtrail_trails.rb +4 -5
- data/lib/resources/aws/aws_ec2_instances.rb +3 -4
- data/lib/resources/aws/aws_iam_access_keys.rb +16 -18
- data/lib/resources/aws/aws_iam_groups.rb +2 -2
- data/lib/resources/aws/aws_iam_policies.rb +4 -5
- data/lib/resources/aws/aws_iam_users.rb +17 -22
- data/lib/resources/aws/aws_kms_keys.rb +4 -5
- data/lib/resources/aws/aws_route_tables.rb +4 -5
- data/lib/resources/aws/aws_s3_buckets.rb +3 -5
- data/lib/resources/aws/aws_security_groups.rb +3 -5
- data/lib/resources/aws/aws_sns_topics.rb +3 -5
- data/lib/resources/aws/aws_subnets.rb +6 -8
- data/lib/resources/aws/aws_vpcs.rb +6 -8
- data/lib/resources/azure/azure_generic_resource.rb +7 -11
- data/lib/resources/azure/azure_virtual_machine_data_disk.rb +15 -17
- data/lib/resources/crontab.rb +9 -11
- data/lib/resources/docker.rb +32 -38
- data/lib/resources/elasticsearch.rb +24 -26
- data/lib/resources/etc_fstab.rb +8 -10
- data/lib/resources/etc_hosts.rb +4 -6
- data/lib/resources/etc_hosts_allow_deny.rb +4 -6
- data/lib/resources/file.rb +1 -1
- data/lib/resources/firewalld.rb +6 -8
- data/lib/resources/groups.rb +6 -8
- data/lib/resources/nginx_conf.rb +4 -6
- data/lib/resources/packages.rb +5 -7
- data/lib/resources/passwd.rb +9 -11
- data/lib/resources/port.rb +7 -9
- data/lib/resources/postgres_hba_conf.rb +7 -9
- data/lib/resources/postgres_ident_conf.rb +4 -6
- data/lib/resources/processes.rb +13 -15
- data/lib/resources/ssl.rb +5 -7
- data/lib/resources/users.rb +15 -17
- data/lib/resources/xinetd.rb +9 -11
- metadata +2 -2
@@ -19,8 +19,8 @@ class AwsIamGroups < Inspec.resource(1)
|
|
19
19
|
|
20
20
|
# Underlying FilterTable implementation.
|
21
21
|
filter = FilterTable.create
|
22
|
-
filter.
|
23
|
-
filter.
|
22
|
+
filter.register_column(:group_names, field: :group_name)
|
23
|
+
filter.install_filter_methods_on_resource(self, :table)
|
24
24
|
|
25
25
|
def to_s
|
26
26
|
'IAM Groups'
|
@@ -18,11 +18,10 @@ class AwsIamPolicies < Inspec.resource(1)
|
|
18
18
|
|
19
19
|
# Underlying FilterTable implementation.
|
20
20
|
filter = FilterTable.create
|
21
|
-
filter.
|
22
|
-
|
23
|
-
.
|
24
|
-
|
25
|
-
filter.connect(self, :table)
|
21
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
22
|
+
filter.register_column(:policy_names, field: :policy_name)
|
23
|
+
.register_column(:arns, field: :arn)
|
24
|
+
filter.install_filter_methods_on_resource(self, :table)
|
26
25
|
|
27
26
|
def to_s
|
28
27
|
'IAM Policies'
|
@@ -62,35 +62,30 @@ class AwsIamUsers < Inspec.resource(1)
|
|
62
62
|
end
|
63
63
|
|
64
64
|
filter = FilterTable.create
|
65
|
-
filter.add_accessor(:where)
|
66
|
-
.add_accessor(:entries)
|
67
|
-
# Summary methods
|
68
|
-
filter.add(:exists?) { |table| !table.params.empty? }
|
69
|
-
.add(:count) { |table| table.params.count }
|
70
65
|
|
71
66
|
# These are included on the initial fetch
|
72
|
-
filter.
|
73
|
-
.
|
74
|
-
.
|
75
|
-
.
|
76
|
-
.
|
67
|
+
filter.register_column(:usernames, field: :user_name)
|
68
|
+
.register_column(:username) { |res| res.entries.map { |row| row[:user_name] } } # We should deprecate this; plural resources get plural properties
|
69
|
+
.register_column(:password_ever_used?, field: :password_ever_used?)
|
70
|
+
.register_column(:password_never_used?, field: :password_never_used?)
|
71
|
+
.register_column(:password_last_used_days_ago, field: :password_last_used_days_ago)
|
77
72
|
|
78
73
|
# Remaining properties / criteria are handled lazily, grouped by fetcher
|
79
|
-
filter.
|
80
|
-
.
|
74
|
+
filter.register_column(:has_console_password?, field: :has_console_password?, lazy: method(:lazy_get_login_profile))
|
75
|
+
.register_column(:has_console_password, field: :has_console_password, lazy: method(:lazy_get_login_profile))
|
81
76
|
|
82
|
-
filter.
|
83
|
-
.
|
77
|
+
filter.register_column(:has_mfa_enabled?, field: :has_mfa_enabled?, lazy: method(:lazy_list_mfa_devices))
|
78
|
+
.register_column(:has_mfa_enabled, field: :has_mfa_enabled, lazy: method(:lazy_list_mfa_devices))
|
84
79
|
|
85
|
-
filter.
|
86
|
-
.
|
87
|
-
.
|
80
|
+
filter.register_column(:has_inline_policies?, field: :has_inline_policies?, lazy: method(:lazy_list_user_policies))
|
81
|
+
.register_column(:has_inline_policies, field: :has_inline_policies, lazy: method(:lazy_list_user_policies))
|
82
|
+
.register_column(:inline_policy_names, field: :inline_policy_names, style: :simple, lazy: method(:lazy_list_user_policies))
|
88
83
|
|
89
|
-
filter.
|
90
|
-
.
|
91
|
-
.
|
92
|
-
.
|
93
|
-
filter.
|
84
|
+
filter.register_column(:has_attached_policies?, field: :has_attached_policies?, lazy: method(:lazy_list_attached_policies))
|
85
|
+
.register_column(:has_attached_policies, field: :has_attached_policies, lazy: method(:lazy_list_attached_policies))
|
86
|
+
.register_column(:attached_policy_names, field: :attached_policy_names, style: :simple, lazy: method(:lazy_list_attached_policies))
|
87
|
+
.register_column(:attached_policy_arns, field: :attached_policy_arns, style: :simple, lazy: method(:lazy_list_attached_policies))
|
88
|
+
filter.install_filter_methods_on_resource(self, :table)
|
94
89
|
|
95
90
|
def validate_params(raw_params)
|
96
91
|
# No params yet
|
@@ -18,11 +18,10 @@ class AwsKmsKeys < Inspec.resource(1)
|
|
18
18
|
|
19
19
|
# Underlying FilterTable implementation.
|
20
20
|
filter = FilterTable.create
|
21
|
-
filter.
|
22
|
-
|
23
|
-
.
|
24
|
-
|
25
|
-
filter.connect(self, :table)
|
21
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
22
|
+
filter.register_column(:key_arns, field: :key_arn)
|
23
|
+
.register_column(:key_ids, field: :key_id)
|
24
|
+
filter.install_filter_methods_on_resource(self, :table)
|
26
25
|
|
27
26
|
def to_s
|
28
27
|
'KMS Keys'
|
@@ -11,11 +11,10 @@ class AwsRouteTables < Inspec.resource(1)
|
|
11
11
|
include AwsPluralResourceMixin
|
12
12
|
# Underlying FilterTable implementation.
|
13
13
|
filter = FilterTable.create
|
14
|
-
filter.
|
15
|
-
|
16
|
-
.
|
17
|
-
|
18
|
-
filter.connect(self, :routes_data)
|
14
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
15
|
+
filter.register_column(:vpc_ids, field: :vpc_id)
|
16
|
+
.register_column(:route_table_ids, field: :route_table_id)
|
17
|
+
filter.install_filter_methods_on_resource(self, :routes_data)
|
19
18
|
|
20
19
|
def routes_data
|
21
20
|
@table
|
@@ -14,11 +14,9 @@ class AwsS3Buckets < Inspec.resource(1)
|
|
14
14
|
|
15
15
|
# Underlying FilterTable implementation.
|
16
16
|
filter = FilterTable.create
|
17
|
-
filter.
|
18
|
-
|
19
|
-
|
20
|
-
.add(:bucket_names, field: :name)
|
21
|
-
filter.connect(self, :table)
|
17
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
18
|
+
filter.register_column(:bucket_names, field: :name)
|
19
|
+
filter.install_filter_methods_on_resource(self, :table)
|
22
20
|
|
23
21
|
def to_s
|
24
22
|
'S3 Buckets'
|
@@ -18,11 +18,9 @@ EOX
|
|
18
18
|
|
19
19
|
# Underlying FilterTable implementation.
|
20
20
|
filter = FilterTable.create
|
21
|
-
filter.
|
22
|
-
|
23
|
-
|
24
|
-
.add(:group_ids, field: :group_id)
|
25
|
-
filter.connect(self, :table)
|
21
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
22
|
+
filter.register_column(:group_ids, field: :group_id)
|
23
|
+
filter.install_filter_methods_on_resource(self, :table)
|
26
24
|
|
27
25
|
def to_s
|
28
26
|
'EC2 Security Groups'
|
@@ -33,11 +33,9 @@ class AwsSnsTopics < Inspec.resource(1)
|
|
33
33
|
|
34
34
|
# Underlying FilterTable implementation.
|
35
35
|
filter = FilterTable.create
|
36
|
-
filter.
|
37
|
-
|
38
|
-
|
39
|
-
.add(:topic_arns, field: :topic_arn)
|
40
|
-
filter.connect(self, :table)
|
36
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
37
|
+
filter.register_column(:topic_arns, field: :topic_arn)
|
38
|
+
filter.install_filter_methods_on_resource(self, :table)
|
41
39
|
|
42
40
|
def to_s
|
43
41
|
'EC2 SNS Topics'
|
@@ -27,14 +27,12 @@ class AwsSubnets < Inspec.resource(1)
|
|
27
27
|
|
28
28
|
# Underlying FilterTable implementation.
|
29
29
|
filter = FilterTable.create
|
30
|
-
filter.
|
31
|
-
|
32
|
-
.
|
33
|
-
.
|
34
|
-
.
|
35
|
-
|
36
|
-
.add(:states, field: :state)
|
37
|
-
filter.connect(self, :table)
|
30
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
31
|
+
filter.register_column(:vpc_ids, field: :vpc_id)
|
32
|
+
.register_column(:subnet_ids, field: :subnet_id)
|
33
|
+
.register_column(:cidr_blocks, field: :cidr_block)
|
34
|
+
.register_column(:states, field: :state)
|
35
|
+
filter.install_filter_methods_on_resource(self, :table)
|
38
36
|
|
39
37
|
def to_s
|
40
38
|
'EC2 VPC Subnets'
|
@@ -12,15 +12,13 @@ class AwsVpcs < Inspec.resource(1)
|
|
12
12
|
|
13
13
|
# Underlying FilterTable implementation.
|
14
14
|
filter = FilterTable.create
|
15
|
-
filter.
|
16
|
-
|
17
|
-
.
|
18
|
-
.add(:cidr_blocks, field: :cidr_block)
|
19
|
-
.add(:vpc_ids, field: :vpc_id)
|
15
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
16
|
+
filter.register_column(:cidr_blocks, field: :cidr_block)
|
17
|
+
.register_column(:vpc_ids, field: :vpc_id)
|
20
18
|
# We need a dummy here, so FilterTable will define and populate the dhcp_options_id field
|
21
|
-
filter.
|
22
|
-
.
|
23
|
-
filter.
|
19
|
+
filter.register_column(:dummy, field: :dhcp_options_id)
|
20
|
+
.register_column(:dhcp_options_ids) { |obj| obj.entries.map(&:dhcp_options_id).uniq }
|
21
|
+
filter.install_filter_methods_on_resource(self, :table)
|
24
22
|
|
25
23
|
def validate_params(raw_params)
|
26
24
|
# No params yet
|
@@ -33,17 +33,13 @@ module Inspec::Resources
|
|
33
33
|
|
34
34
|
# Define the filter table so that it can be interrogated
|
35
35
|
@filter = FilterTable.create
|
36
|
-
@filter.
|
37
|
-
.
|
38
|
-
.
|
39
|
-
.
|
40
|
-
.
|
41
|
-
|
42
|
-
|
43
|
-
.add(:location, field: 'location')
|
44
|
-
.add(:properties, field: 'properties')
|
45
|
-
|
46
|
-
@filter.connect(self, :probes)
|
36
|
+
@filter.register_filter_method(:contains)
|
37
|
+
.register_column(:type, field: 'type')
|
38
|
+
.register_column(:name, field: 'name')
|
39
|
+
.register_column(:location, field: 'location')
|
40
|
+
.register_column(:properties, field: 'properties')
|
41
|
+
|
42
|
+
@filter.install_filter_methods_on_resource(self, :probes)
|
47
43
|
|
48
44
|
def parse_resource(resource)
|
49
45
|
# return a hash of information
|
@@ -15,23 +15,21 @@ module Inspec::Resources
|
|
15
15
|
|
16
16
|
# Create a filter table so that tests on the disk can be performed
|
17
17
|
filter = FilterTable.create
|
18
|
-
filter.
|
19
|
-
|
20
|
-
.
|
21
|
-
.
|
22
|
-
.
|
23
|
-
.
|
24
|
-
.
|
25
|
-
.
|
26
|
-
.
|
27
|
-
.
|
28
|
-
.
|
29
|
-
.
|
30
|
-
.
|
31
|
-
.
|
32
|
-
|
33
|
-
.add(:resource_group, field: :resource_group)
|
34
|
-
filter.connect(self, :datadisk_details)
|
18
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
19
|
+
filter.register_column(:disk, field: :disk)
|
20
|
+
.register_column(:number, field: :number)
|
21
|
+
.register_column(:name, field: :name)
|
22
|
+
.register_column(:size, field: :size)
|
23
|
+
.register_column(:vhd_uri, field: :vhd_uri)
|
24
|
+
.register_column(:storage_account_name, field: :storage_account_name)
|
25
|
+
.register_column(:lun, field: :lun)
|
26
|
+
.register_column(:caching, field: :caching)
|
27
|
+
.register_column(:create_option, field: :create_option)
|
28
|
+
.register_column(:is_managed_disk?, field: :is_managed_disk?)
|
29
|
+
.register_column(:storage_account_type, field: :storage_account_type)
|
30
|
+
.register_column(:subscription_id, field: :subscription_id)
|
31
|
+
.register_column(:resource_group, field: :resource_group)
|
32
|
+
filter.install_filter_methods_on_resource(self, :datadisk_details)
|
35
33
|
|
36
34
|
# Constructor for the resource. This calls the parent constructor to
|
37
35
|
# get the generic resource for the specified machine. This will provide
|
data/lib/resources/crontab.rb
CHANGED
@@ -65,24 +65,22 @@ module Inspec::Resources
|
|
65
65
|
end
|
66
66
|
|
67
67
|
filter = FilterTable.create
|
68
|
-
filter.
|
69
|
-
.
|
70
|
-
.
|
71
|
-
.
|
72
|
-
.
|
73
|
-
.
|
74
|
-
.
|
75
|
-
.add(:user, field: 'user')
|
76
|
-
.add(:commands, field: 'command')
|
68
|
+
filter.register_column(:minutes, field: 'minute')
|
69
|
+
.register_column(:hours, field: 'hour')
|
70
|
+
.register_column(:days, field: 'day')
|
71
|
+
.register_column(:months, field: 'month')
|
72
|
+
.register_column(:weekdays, field: 'weekday')
|
73
|
+
.register_column(:user, field: 'user')
|
74
|
+
.register_column(:commands, field: 'command')
|
77
75
|
|
78
76
|
# rebuild the crontab line from raw content
|
79
|
-
filter.
|
77
|
+
filter.register_custom_property(:content) { |t, _|
|
80
78
|
t.entries.map do |e|
|
81
79
|
[e.minute, e.hour, e.day, e.month, e.weekday, e.user, e.command].compact.join(' ')
|
82
80
|
end.join("\n")
|
83
81
|
}
|
84
82
|
|
85
|
-
filter.
|
83
|
+
filter.install_filter_methods_on_resource(self, :params)
|
86
84
|
|
87
85
|
def to_s
|
88
86
|
if is_system_crontab?
|
data/lib/resources/docker.rb
CHANGED
@@ -10,25 +10,23 @@ module Inspec::Resources
|
|
10
10
|
class DockerContainerFilter
|
11
11
|
# use filtertable for containers
|
12
12
|
filter = FilterTable.create
|
13
|
-
filter.
|
14
|
-
|
15
|
-
.
|
16
|
-
.
|
17
|
-
.
|
18
|
-
.
|
19
|
-
.
|
20
|
-
.
|
21
|
-
.
|
22
|
-
.
|
23
|
-
.
|
24
|
-
.
|
25
|
-
.
|
26
|
-
.
|
27
|
-
.add(:exists?) { |x| !x.entries.empty? }
|
28
|
-
.add(:running?) { |x|
|
13
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
14
|
+
filter.register_column(:commands, field: 'command')
|
15
|
+
.register_column(:ids, field: 'id')
|
16
|
+
.register_column(:images, field: 'image')
|
17
|
+
.register_column(:labels, field: 'labels')
|
18
|
+
.register_column(:local_volumes, field: 'localvolumes')
|
19
|
+
.register_column(:mounts, field: 'mounts')
|
20
|
+
.register_column(:names, field: 'names')
|
21
|
+
.register_column(:networks, field: 'networks')
|
22
|
+
.register_column(:ports, field: 'ports')
|
23
|
+
.register_column(:running_for, field: 'runningfor')
|
24
|
+
.register_column(:sizes, field: 'size')
|
25
|
+
.register_column(:status, field: 'status')
|
26
|
+
.register_custom_matcher(:running?) { |x|
|
29
27
|
x.where { status.downcase.start_with?('up') }
|
30
28
|
}
|
31
|
-
filter.
|
29
|
+
filter.install_filter_methods_on_resource(self, :containers)
|
32
30
|
|
33
31
|
attr_reader :containers
|
34
32
|
def initialize(containers)
|
@@ -38,17 +36,15 @@ module Inspec::Resources
|
|
38
36
|
|
39
37
|
class DockerImageFilter
|
40
38
|
filter = FilterTable.create
|
41
|
-
filter.
|
42
|
-
|
43
|
-
.
|
44
|
-
.
|
45
|
-
.
|
46
|
-
.
|
47
|
-
.
|
48
|
-
.
|
49
|
-
|
50
|
-
.add(:exists?) { |x| !x.entries.empty? }
|
51
|
-
filter.connect(self, :images)
|
39
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
40
|
+
filter.register_column(:ids, field: 'id')
|
41
|
+
.register_column(:repositories, field: 'repository')
|
42
|
+
.register_column(:tags, field: 'tag')
|
43
|
+
.register_column(:sizes, field: 'size')
|
44
|
+
.register_column(:digests, field: 'digest')
|
45
|
+
.register_column(:created, field: 'createdat')
|
46
|
+
.register_column(:created_since, field: 'createdsize')
|
47
|
+
filter.install_filter_methods_on_resource(self, :images)
|
52
48
|
|
53
49
|
attr_reader :images
|
54
50
|
def initialize(images)
|
@@ -58,16 +54,14 @@ module Inspec::Resources
|
|
58
54
|
|
59
55
|
class DockerServiceFilter
|
60
56
|
filter = FilterTable.create
|
61
|
-
filter.
|
62
|
-
|
63
|
-
.
|
64
|
-
.
|
65
|
-
.
|
66
|
-
.
|
67
|
-
.
|
68
|
-
|
69
|
-
.add(:exists?) { |x| !x.entries.empty? }
|
70
|
-
filter.connect(self, :services)
|
57
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
58
|
+
filter.register_column(:ids, field: 'id')
|
59
|
+
.register_column(:names, field: 'name')
|
60
|
+
.register_column(:modes, field: 'mode')
|
61
|
+
.register_column(:replicas, field: 'replicas')
|
62
|
+
.register_column(:images, field: 'image')
|
63
|
+
.register_column(:ports, field: 'ports')
|
64
|
+
filter.install_filter_methods_on_resource(self, :services)
|
71
65
|
|
72
66
|
attr_reader :services
|
73
67
|
def initialize(services)
|
@@ -24,35 +24,33 @@ module Inspec::Resources
|
|
24
24
|
"
|
25
25
|
|
26
26
|
filter = FilterTable.create
|
27
|
-
filter.
|
28
|
-
|
29
|
-
.
|
30
|
-
.
|
31
|
-
.
|
32
|
-
.
|
33
|
-
.
|
34
|
-
.
|
35
|
-
.
|
36
|
-
.
|
37
|
-
.
|
38
|
-
.
|
39
|
-
.
|
40
|
-
.
|
41
|
-
.
|
42
|
-
.
|
43
|
-
.
|
44
|
-
.
|
45
|
-
.
|
46
|
-
.
|
47
|
-
.
|
48
|
-
.
|
49
|
-
.
|
50
|
-
.add(:exists?) { |x| !x.entries.empty? }
|
51
|
-
.add(:node_count) { |t, _|
|
27
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
28
|
+
filter.register_column(:cluster_name, field: 'cluster_name')
|
29
|
+
.register_column(:node_name, field: 'name')
|
30
|
+
.register_column(:transport_address, field: 'transport_address')
|
31
|
+
.register_column(:host, field: 'host')
|
32
|
+
.register_column(:ip, field: 'ip')
|
33
|
+
.register_column(:version, field: 'version')
|
34
|
+
.register_column(:build_hash, field: 'build_hash')
|
35
|
+
.register_column(:total_indexing_buffer, field: 'total_indexing_buffer')
|
36
|
+
.register_column(:roles, field: 'roles')
|
37
|
+
.register_column(:settings, field: 'settings')
|
38
|
+
.register_column(:os, field: 'os')
|
39
|
+
.register_column(:process, field: 'process')
|
40
|
+
.register_column(:jvm, field: 'jvm')
|
41
|
+
.register_column(:transport, field: 'transport')
|
42
|
+
.register_column(:http, field: 'http')
|
43
|
+
.register_column(:plugins, field: 'plugins')
|
44
|
+
.register_column(:plugin_list, field: 'plugin_list')
|
45
|
+
.register_column(:modules, field: 'modules')
|
46
|
+
.register_column(:module_list, field: 'module_list')
|
47
|
+
.register_column(:node_id, field: 'node_id')
|
48
|
+
.register_column(:ingest, field: 'ingest')
|
49
|
+
.register_custom_property(:node_count) { |t, _|
|
52
50
|
t.entries.length
|
53
51
|
}
|
54
52
|
|
55
|
-
filter.
|
53
|
+
filter.install_filter_methods_on_resource(self, :nodes)
|
56
54
|
|
57
55
|
attr_reader :nodes, :url
|
58
56
|
|