chef-attribute-validator 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGU5Y2Y2ZGFjYWIwNjBjMGVhODFiMTMxYWY0NzY1NzcyMWJlMjk0ZQ==
4
+ MThmOWZjYmNhMzI0ODZiODM4ZmNmMWYzOGVkYjNjZDIyMWMzZGU0OA==
5
5
  data.tar.gz: !binary |-
6
- M2RmYmFjNTFlYTRjZGIyMTY4YTUwNjZmNmIwYTlhNTZkNzI3YTJlOQ==
6
+ ZWU3YmQzMGNkYmQ2Y2ExYTE1NWQ4MWY1MmUzNDVhMTljNjAzNDE0MA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NzM4NjBlNmY1MzdhNTBhNDAyNTc1YmVhMTdlMjExMTdkN2ZlZGNmMGIzZWJm
10
- YmE0NmJkZjhhYzliOTY2ZTI3YzE1OTgyMWQ1NzA3N2NjYzYyNTdiNmRmYTZk
11
- NDYwZmMzOGM5OWViNWVmYzJkNTZlMDM5MjZmZTE2MzQxYWExMTg=
9
+ ZDFiZjFiNmUyZDE2MTljOTI3ZWNiNDI5ZjVjN2ZmNTAyYTVhMDdiMzMwZmU1
10
+ MGZmODUxZDIyNjJhNjJhMmMzODYzMjMwZWFkMDIyNzg3YWU5YWZkYjQ1Mjg3
11
+ YzU5YTJiNjM3NDM0Y2EwM2FlYjdmMGZmNjEzMzU3M2FiYTU2OGI=
12
12
  data.tar.gz: !binary |-
13
- ZWQ4NjdiM2Y3Nzk5NGU1NGZlMDdlODBhMTg5ZDAwOWJiMGE2ZTBhMjQ4MGUy
14
- YzA1MGJjNzZiMDlhYzdiZTQ5MTljODRkMjNmMGFmZWE3ZDZlYWJhZjQ0NWQ5
15
- YTc3ZTcyZTY0YTVkYzQ2Zjk4OWIzZjQwYmRmYjk3NWU2NjU5MDk=
13
+ MmVmZWQ1YzA2M2ZlOTkxMjE2ZDg5ZGE0MmI0NGRkZTcwNDQ3M2I5YWRhYTdk
14
+ OTY3N2E3ZjZhN2I4NTk5YTc2NjBlYjk5ZDViMWI5M2U3NDM4M2NjYjlmNTNi
15
+ NTdjNzJmMzI4MWM5NDNjYWQ0ZmU3MGZmYWU5NmRjY2ZlYmQ0YjU=
data/CHANGES CHANGED
@@ -1,3 +1,7 @@
1
+ 2013-11-12 Clinton Wolfe 0.2.0
2
+ Support for wildcards - *, **, ?
3
+ Crude implementation using brute force and regexes
4
+
1
5
  2013-11-10 Clinton Wolfe 0.1.0
2
6
  Initial release
3
7
  Type, Regex, Min/Max Children, Required, and LooksLike checks
data/Gemfile CHANGED
@@ -1,2 +1,4 @@
1
1
  source 'https://rubygems.org'
2
- gemspec
2
+
3
+ gem "foodcritic"
4
+ gem "rubocop"
data/README.md CHANGED
@@ -68,13 +68,13 @@ Given:
68
68
 
69
69
  ## Bugs, Limitations and Roadmap
70
70
 
71
- #### Wildcard syntax not yet supported
71
+ ### How to Report Bugs
72
72
 
73
- I'd like to have at least this:
73
+ Open a github issue at https://github.com/clintoncwolfe/chef-attribute-validator, ideally with a failing test case, a pull request that fixes the bug, and a unicorn.
74
74
 
75
- /foo/* - Matches node['foo']['bar'], but not node['foo'] or node['foo']['bar']['baz']
76
- /foo/c* - Matches node['foo']['car'], but not node['foo']['bar']
77
- /foo/?ar - Matches node['foo']['bar'] and node['foo']['bar'] but not node['foo']['bleh']
75
+ ### Roadmap
76
+
77
+ #### Some wildcard syntax not yet supported
78
78
 
79
79
  Possibly eventually support for **, [<charclass>], or {<alternatives>}.
80
80
 
@@ -82,18 +82,22 @@ Possibly eventually support for **, [<charclass>], or {<alternatives>}.
82
82
 
83
83
  Simple cookbook named 'attribute-validator' that loads the gem and provides recipes for compile-time and convergence-time violation checking.
84
84
 
85
- ### Lame Exceptions
86
-
87
- No real exception class, just raising a bare string exception, which could certainly be improved upon.
88
-
89
- ### Planned checks:
85
+ #### Planned checks:
90
86
 
91
87
  looks_like/hostname
92
88
  looks_like/email
93
89
  name_regex - Regexp. Applies given regex to the last element in the attribute path ('basename', if you will)
94
90
  present - Boolean. If true, fails if the path matches zero attributes. If false, fails if the path matches nonzero attributes. Does not consider nilness, only existence of attribute key(s). See also required.
95
91
 
96
- #### Probably Slow
92
+ ### Bugs and Defects
93
+
94
+ #### Lame Exceptions
95
+
96
+ No real exception class, just raising a bare string exception, which could certainly be improved upon; hard to catch.
97
+
98
+ #### Wildcard Expander implementation is simplistic and inefficient
99
+
100
+ BrutalRegex is terrible.
97
101
 
98
102
 
99
103
  ## Author
data/Rakefile CHANGED
@@ -11,13 +11,23 @@ task :test
11
11
  task :test => [:syntax]
12
12
  desc "Checks ruby files for syntax errors"
13
13
  task :syntax do |t|
14
+ puts "------------Syntax-----------"
14
15
  Dir.glob('**/*.rb').each do |f|
15
16
  system("/bin/echo -n '#{f}: '; ruby -c #{f}")
16
17
  end
17
18
  end
18
19
 
19
- task :test => [:unit]
20
- desc "Runs unit tests"
20
+
21
+ task :test => [:rubocop]
22
+ desc "Runs rubocop against the code, to enforce style and standards."
23
+ task :rubocop do |t|
24
+ puts "------------Rubocop-----------"
25
+ system("rubocop -c rubocop.yml")
26
+ end
27
+
28
+
29
+ #task :test => [:unit]
30
+ #desc "Runs unit tests"
21
31
  #RSpec::Core::RakeTask.new(:unit) do |t|
22
32
  # t.pattern = 'test/unit/**/*_spec.rb'
23
33
  # t.rspec_opts = "-fd"
@@ -1,6 +1,8 @@
1
1
 
2
2
  require 'forwardable'
3
3
 
4
+ require_relative './wildcard_expander'
5
+
4
6
  class Chef
5
7
  class Attribute
6
8
  class Validator
@@ -19,71 +21,15 @@ class Chef
19
21
  @path = a_path
20
22
  @node = a_node
21
23
 
22
- embowel
23
- end
24
-
25
- private
26
-
27
- def embowel
28
- # Split on /
29
- steps = path.split('/')
30
-
31
- # Since we begin with /, the first element is ""
32
- if steps[0] == "" then steps.shift end
33
-
34
- # Promote integer strings to integers
35
- steps.map! { |s| s.match(/^\d+$/) ? s.to_i : s }
36
-
37
- # TODO: some ckine of wildcard expansion
38
- all_steps = [ steps ]
39
-
40
- all_steps.each do |these_steps|
41
- if path_exists_by_steps?(these_steps) then
42
- guts['/' + these_steps.join('/')] = fetch_val_by_steps(these_steps)
43
- end
44
- end
45
- end
46
-
47
- def path_exists_by_steps? (the_steps)
48
- nv = node
49
- steps = the_steps.dup
50
- while steps.size > 0
51
- step = steps.shift
52
-
53
- # binding.pry
54
- if nv.kind_of?(Chef::Node::ImmutableArray) then
55
- # TODO: what if the step isn't an int?
24
+ expander = Chef::Attribute::Validator::WildcardExpander.choose(path, node)
56
25
 
57
- if nv.size > step then
58
- nv = nv[step]
59
- else
60
- # Array not long enough
61
- return false
62
- end
63
-
64
- elsif nv.respond_to?(:has_key?) then
65
- if nv.has_key?(step) then
66
- nv = nv[step]
67
- else
68
- # No such key
69
- return false
70
- end
71
- else
72
- # Must be a scalar?
73
- return false
74
- end
26
+ # TODO: less dumb thing would be to have wildcard expander just be an enumerator
27
+ # and then call it on each access
28
+ expander.expand_all.each do | slashpath |
29
+ guts[slashpath] = expander.fetch_val_by_slashpath(slashpath)
75
30
  end
76
- return true
77
31
  end
78
32
 
79
- def fetch_val_by_steps(the_steps)
80
- nv = node
81
- steps = the_steps.dup
82
- while steps.size > 0
83
- nv = nv[steps.shift]
84
- end
85
- nv
86
- end
87
33
  end
88
34
  end
89
35
  end
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  class Attribute
3
3
  class Validator
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,76 @@
1
+ class Chef
2
+ class Attribute
3
+ class Validator
4
+ class WildcardExpander
5
+ class BrutalRegex < WildcardExpander
6
+
7
+ register(self)
8
+
9
+ def expand_all
10
+ # Create a massive list of all attribute paths, in slashpath format
11
+ all_slashpaths = find_all_slashpaths
12
+
13
+ # Convert the path_spec into a terrifying regex
14
+ regex_spec = convert_path_spec_to_regex
15
+
16
+ # Filter the list by grepping
17
+ all_slashpaths.grep(regex_spec)
18
+
19
+ end
20
+
21
+ def suitability
22
+ # I can do anything, but I'll do it badly
23
+ 0.1
24
+ end
25
+
26
+
27
+ # TODO: maybe we could cache this on the node, or something?
28
+ def find_all_slashpaths (prefix='', node_cursor = nil)
29
+ node_cursor ||= node
30
+ child_paths = []
31
+
32
+
33
+ if node_cursor.kind_of?(Array)
34
+ node_cursor.each_index do |idx|
35
+ child_paths.push prefix + '/' + idx.to_s
36
+ if node_cursor[idx].kind_of?(Mash) || node_cursor[idx].kind_of?(Array)
37
+ child_paths += find_all_slashpaths(prefix + '/' + idx.to_s, node_cursor[idx])
38
+ end
39
+ end
40
+ else
41
+ node_cursor.keys.each do |key|
42
+ child_paths.push prefix + '/' + key
43
+ if node_cursor[key].kind_of?(Mash) || node_cursor[key].kind_of?(Array)
44
+ child_paths += find_all_slashpaths(prefix + '/' + key, node_cursor[key])
45
+ end
46
+ end
47
+ end
48
+ child_paths
49
+ end
50
+
51
+ def convert_path_spec_to_regex
52
+ re = path_spec.dup
53
+
54
+ # Anchor everything
55
+ re = '^' + re + '$'
56
+
57
+ # * => "anything but a slash"
58
+ re.gsub!(/([^*])\*(?!\*)/, '\1[^\/]*')
59
+
60
+ # ? => "any single char other than a slash"
61
+ re.gsub!(/\?/, '[^\/]')
62
+
63
+ # ** => "anything"
64
+ re.gsub!(/\*\*/, '.*')
65
+
66
+ # {,} => alternatives # TODO
67
+
68
+ Regexp.new(re)
69
+
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,29 @@
1
+ class Chef
2
+ class Attribute
3
+ class Validator
4
+ class WildcardExpander
5
+ class NoWildcards < WildcardExpander
6
+
7
+ register(self)
8
+
9
+ def expand_all
10
+ if path_exists_by_slashpath?(path_spec)
11
+ [ path_spec ]
12
+ else
13
+ [ ]
14
+ end
15
+ end
16
+
17
+ def suitability
18
+ if path_contains_wildcards?(path_spec)
19
+ 0.0
20
+ else
21
+ 1.0
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,103 @@
1
+ class Chef
2
+ class Attribute
3
+ class Validator
4
+ class WildcardExpander
5
+
6
+
7
+ attr_accessor :path_spec
8
+ attr_accessor :node
9
+
10
+ def initialize(a_path_spec, a_node)
11
+ @path_spec = a_path_spec
12
+ @node = a_node
13
+ end
14
+
15
+ def self.choose(path_spec, node)
16
+ # Ruby is an excellent language in which to write Perl
17
+ @@subclasses.map {|k| k.new(path_spec, node) }.map {|e| [e, e.suitability]}.sort { |a,b| b[1] <=> a[1] }.map {|e| e[0]}.first
18
+ end
19
+
20
+ def slashpath_to_steps(slashpath)
21
+ steps = slashpath.split('/')
22
+
23
+ # Since we begin with /, the first element is ""
24
+ if steps[0] == "" then steps.shift end
25
+
26
+ # Promote integer strings to integers
27
+ steps.map! { |s| s.match(/^\d+$/) ? s.to_i : s }
28
+
29
+ steps
30
+ end
31
+
32
+
33
+ # Note: does not handle missing values correctly!
34
+ def fetch_val_by_slashpath(slashpath)
35
+ nv = node
36
+ steps = slashpath_to_steps(slashpath)
37
+ while steps.size > 0
38
+ nv = nv[steps.shift]
39
+ end
40
+ nv
41
+ end
42
+
43
+ def path_exists_by_slashpath? (slashpath)
44
+ nv = node
45
+ steps = slashpath_to_steps(slashpath)
46
+ while steps.size > 0
47
+ step = steps.shift
48
+
49
+ if nv.kind_of?(Chef::Node::ImmutableArray) then
50
+ # TODO: what if the step isn't an int?
51
+
52
+ if nv.size > step then
53
+ nv = nv[step]
54
+ else
55
+ # Array not long enough
56
+ return false
57
+ end
58
+
59
+ elsif nv.respond_to?(:has_key?) then
60
+ if nv.has_key?(step) then
61
+ nv = nv[step]
62
+ else
63
+ # No such key
64
+ return false
65
+ end
66
+ else
67
+ # Must be a scalar?
68
+ return false
69
+ end
70
+ end
71
+ return true
72
+ end
73
+
74
+
75
+ def path_contains_wildcards?(path)
76
+ [
77
+ /\*/,
78
+ /\*\*/,
79
+ /\?/,
80
+ /\[\w+\]/,
81
+ /\{\w+(\s*,\s*\w+)?\}/,
82
+ ].any? { |r| r.match(path) }
83
+ end
84
+
85
+ protected
86
+
87
+ def suitability
88
+ 0.0
89
+ end
90
+
91
+ def self.register(klass)
92
+ @@subclasses ||= []
93
+ @@subclasses.push klass
94
+ end
95
+
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ Dir.glob(File.join(File.dirname(__FILE__), 'wildcard_expander', '*.rb')).each do |expander_implementation|
102
+ require expander_implementation
103
+ end
@@ -0,0 +1,5 @@
1
+ default['childless'] = '1'
2
+ default['parent']['child'] = '2'
3
+ default['grandpappy']['parent']['child'] = '3'
4
+ default['empty_hash'] = {}
5
+ override['parent']['child'] = '4'
@@ -0,0 +1,5 @@
1
+ default['childless'] = '1'
2
+ default['parent'] = [ 'a', 'b' ]
3
+ default['empty_array'] = [ ]
4
+ default['aoh'] = [ { 'foo' => 'bar', 'yep' => 'nope' }, { 'baz' => 'whoomph' } ]
5
+
@@ -0,0 +1,4 @@
1
+ default['foo'] = '1'
2
+ default['bar'] = '2'
3
+ default['baz'] = '3'
4
+ override['foo'] = '4'
@@ -52,4 +52,62 @@ describe Chef::Attribute::Validator::AttributeSet do
52
52
  end
53
53
  end
54
54
 
55
+ describe "basic star wildcard" do
56
+
57
+ context "when we are looking at the root element" do
58
+ it "should be able to run '/*'" do
59
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/*') }.not_to raise_error
60
+ end
61
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/*') }
62
+ it "should be able to list all root elements" do
63
+ expect(ats.size).to eq 6
64
+ end
65
+ end
66
+
67
+ context "when we use a star at the beginning of a two-step path" do
68
+ it "should be able to run '/*/one'" do
69
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/*/one') }.not_to raise_error
70
+ end
71
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/*/one') }
72
+ it "should be able to list all '/*/one'" do
73
+ expect(ats.size).to eq 1
74
+ expect(ats['/deeper/one']).to eq 1
75
+ end
76
+ end
77
+
78
+ context "when we use a star at the end of a two-step path" do
79
+ it "should be able to run '/deeper/*'" do
80
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*') }.not_to raise_error
81
+ end
82
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*') }
83
+ it "should be able to list '/deeper/*'" do
84
+ expect(ats.size).to eq 2
85
+ expect(ats['/deeper/one']).to eq 1
86
+ expect(ats['/deeper/deeper_yet']).to be_a_kind_of(Mash)
87
+ end
88
+ end
89
+
90
+ context "when we use a star at the middle of a three-step path" do
91
+ it "should be able to run '/deeper/*/one'" do
92
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*/one') }.not_to raise_error
93
+ end
94
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*/one') }
95
+ it "should be able to list '/deeper/*/one" do
96
+ expect(ats.size).to eq 1
97
+ expect(ats['/deeper/deeper_yet/one']).to eq 1
98
+ end
99
+ end
100
+
101
+ context "when the wildcarded step does not exist" do
102
+ it "should be able to run '/nope/*'" do
103
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/nope/*') }.not_to raise_error
104
+ end
105
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/nope/*') }
106
+ it "should not be able to find '/nope/*'" do
107
+ expect(ats.size).to eq 0
108
+ end
109
+
110
+ end
111
+ end
112
+
55
113
  end
@@ -0,0 +1,114 @@
1
+ require_relative './spec_helper'
2
+
3
+ describe Chef::Attribute::Validator::AttributeSet do
4
+
5
+ let(:node) { CAVHelper.load_fixture_attributes('attr_set') }
6
+
7
+ describe "non-wildcard, non-array slashpath access" do
8
+ context "when the element exists" do
9
+ it "should be able to run /one" do
10
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/one') }.not_to raise_error
11
+ end
12
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/one') }
13
+ it "should be able to find /one" do
14
+ expect(ats.size).to eq 1
15
+ expect(ats.has_key?('/one')).to be_true
16
+ expect(ats['/one']).to eq 1
17
+ end
18
+ end
19
+
20
+ context "when the element does not exist" do
21
+ it "should be able to run /nope" do
22
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/nope') }.not_to raise_error
23
+ end
24
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/nope') }
25
+ it "should not be able to find /nope" do
26
+ expect(ats.size).to eq 0
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "non-wildcard, array slashpath access" do
32
+ context "when the element exists" do
33
+ it "should be able to run /cats/1" do
34
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/1') }.not_to raise_error
35
+ end
36
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/1') }
37
+ it "should be able to find /cats/1" do
38
+ expect(ats.size).to eq 1
39
+ expect(ats.has_key?('/cats/1')).to be_true
40
+ expect(ats['/cats/1']).to eq 'tabby'
41
+ end
42
+ end
43
+
44
+ context "when the element does not exist" do
45
+ it "should be able to run /cats/23" do
46
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/23') }.not_to raise_error
47
+ end
48
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/cats/23') }
49
+ it "should not be able to find /cats/23" do
50
+ expect(ats.size).to eq 0
51
+ end
52
+ end
53
+ end
54
+
55
+ describe "basic star wildcard" do
56
+
57
+ context "when we are looking at the root element" do
58
+ it "should be able to run '/*'" do
59
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/*') }.not_to raise_error
60
+ end
61
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/*') }
62
+ it "should be able to list all root elements" do
63
+ expect(ats.size).to eq 7
64
+ end
65
+ end
66
+
67
+ context "when we use a star at the beginning of a two-step path" do
68
+ it "should be able to run '/*/one'" do
69
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/*/one') }.not_to raise_error
70
+ end
71
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/*/one') }
72
+ it "should be able to list all '/*/one'" do
73
+ expect(ats.size).to eq 1
74
+ expect(ats['/deeper/one']).to eq 1
75
+ end
76
+ end
77
+
78
+ context "when we use a star at the end of a two-step path" do
79
+ it "should be able to run '/deeper/*'" do
80
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*') }.not_to raise_error
81
+ end
82
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*') }
83
+ it "should be able to list '/deeper/*'" do
84
+ expect(ats.size).to eq 2
85
+ expect(ats['/deeper/one']).to eq 1
86
+ expect(ats['/deeper/deeper_yet']).to be_a_kind_of(Mash)
87
+ end
88
+ end
89
+
90
+ context "when we use a star at the middle of a three-step path" do
91
+ it "should be able to run '/deeper/*/one'" do
92
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*/one') }.not_to raise_error
93
+ end
94
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/deeper/*/one') }
95
+ it "should be able to list '/deeper/*/one" do
96
+ expect(ats.size).to eq 1
97
+ expect(ats['/deeper/deeper_yet/one']).to eq 1
98
+ end
99
+ end
100
+
101
+ context "when the wildcarded step does not exist" do
102
+ it "should be able to run '/nope/*'" do
103
+ expect { Chef::Attribute::Validator::AttributeSet.new(node, '/nope/*') }.not_to raise_error
104
+ end
105
+ let(:ats) { Chef::Attribute::Validator::AttributeSet.new(node, '/nope/*') }
106
+ it "should not be able to find '/nope/*'" do
107
+ expect(ats.size).to eq 0
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,132 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Chef::Attribute::Validator::WildcardExpander::BrutalRegex do
4
+
5
+ context "prior to applying filter" do
6
+
7
+ context "when examining a shallow node" do
8
+ let(:node) { CAVHelper.load_fixture_attributes('expander_brutal_flat') }
9
+ let(:exp) { Chef::Attribute::Validator::WildcardExpander::BrutalRegex.new('/foo', node) }
10
+ let(:result) { exp.find_all_slashpaths }
11
+
12
+ it "should prefix all entries with /" do
13
+ expect(result.all? { |sp| sp.match(/^\//) }).to be_true
14
+ end
15
+
16
+ it "should find the right number of entries" do
17
+ expect(result.size).to eql 3
18
+ end
19
+
20
+ it "should find the /foo entry" do
21
+ expect(result).to include('/foo')
22
+ end
23
+
24
+ end
25
+
26
+ context "when examining a deeper node with no arrays" do
27
+ let(:node) { CAVHelper.load_fixture_attributes('expander_brutal_deep_hash') }
28
+ let(:exp) { Chef::Attribute::Validator::WildcardExpander::BrutalRegex.new('/foo', node) }
29
+ let(:result) { exp.find_all_slashpaths }
30
+
31
+
32
+ it "should prefix all entries with /" do
33
+ expect(result.all? { |sp| sp.match(/^\//) }).to be_true
34
+ end
35
+
36
+ it "should find the right number of entries" do
37
+ expect(result.size).to eql 7
38
+ end
39
+
40
+ it "should find the /childless entry" do
41
+ expect(result).to include('/childless')
42
+ end
43
+ it "should find the /parent entry" do
44
+ expect(result).to include('/parent')
45
+ end
46
+ it "should find the /parent/child entry" do
47
+ expect(result).to include('/parent/child')
48
+ end
49
+ it "should find the /grandpappy entry" do
50
+ expect(result).to include('/grandpappy')
51
+ end
52
+ it "should find the /grandpappy/parent entry" do
53
+ expect(result).to include('/grandpappy/parent')
54
+ end
55
+ it "should find the /grandpappy/parent/child entry" do
56
+ expect(result).to include('/grandpappy/parent/child')
57
+ end
58
+ it "should find the /empty_hash entry" do
59
+ expect(result).to include('/empty_hash')
60
+ end
61
+
62
+
63
+ end
64
+
65
+ context "when examining a deeper node with mixed arrays" do
66
+ let(:node) { CAVHelper.load_fixture_attributes('expander_brutal_deep_mixed') }
67
+ let(:exp) { Chef::Attribute::Validator::WildcardExpander::BrutalRegex.new('/foo', node) }
68
+ let(:result) { exp.find_all_slashpaths }
69
+
70
+
71
+ it "should prefix all entries with /" do
72
+ expect(result.all? { |sp| sp.match(/^\//) }).to be_true
73
+ end
74
+
75
+ it "should find the right number of entries" do
76
+ expect(result.size).to eql 11
77
+ end
78
+
79
+ it "should find the /childless entry" do
80
+ expect(result).to include('/childless')
81
+ end
82
+ it "should find the /parent entry" do
83
+ expect(result).to include('/parent')
84
+ end
85
+ it "should find the /parent/0 entry" do
86
+ expect(result).to include('/parent/0')
87
+ end
88
+ it "should find the /parent/1 entry" do
89
+ expect(result).to include('/parent/1')
90
+ end
91
+ it "should find the /empty_array entry" do
92
+ expect(result).to include('/empty_array')
93
+ end
94
+
95
+ it "should find the /aoh entry" do
96
+ expect(result).to include('/aoh')
97
+ end
98
+
99
+ it "should find the /aoh/0 entry" do
100
+ expect(result).to include('/aoh/0')
101
+ end
102
+
103
+ it "should find the /aoh/0/foo entry" do
104
+ expect(result).to include('/aoh/0/foo')
105
+ end
106
+
107
+ end
108
+ end
109
+
110
+ context "while converting a pathspec to a regex" do
111
+ let(:node) { CAVHelper.load_fixture_attributes('expander_brutal_flat') }
112
+
113
+ {
114
+ '/foo' => '^/foo$',
115
+ '/foo*' => '^/foo[^\/]*$',
116
+ '/foo*/*/bar' => '^/foo[^\/]*/[^\/]*/bar$',
117
+ '/?oo' => '^/[^\/]oo$',
118
+ '/**' => '^/.*$',
119
+ '/foo/**/bar' => '^/foo/.*/bar$',
120
+ }.each do | spec, regex |
121
+ it "should convert '#{spec}' to '#{regex}'" do
122
+ exp = Chef::Attribute::Validator::WildcardExpander::BrutalRegex.new(spec, node)
123
+ expect(exp.convert_path_spec_to_regex).to eql Regexp.new(regex)
124
+ end
125
+ end
126
+
127
+
128
+
129
+ end
130
+
131
+
132
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-attribute-validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clinton Wolfe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-11 00:00:00.000000000 Z
11
+ date: 2013-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,16 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
19
+ version: !binary |-
20
+ MS4z
20
21
  type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - ~>
25
26
  - !ruby/object:Gem::Version
26
- version: '1.3'
27
+ version: !binary |-
28
+ MS4z
27
29
  - !ruby/object:Gem::Dependency
28
30
  name: rake
29
31
  requirement: !ruby/object:Gem::Requirement
@@ -81,6 +83,9 @@ files:
81
83
  - lib/chef-attribute-validator/rule.rb
82
84
  - lib/chef-attribute-validator/version.rb
83
85
  - lib/chef-attribute-validator/violation.rb
86
+ - lib/chef-attribute-validator/wildcard_expander.rb
87
+ - lib/chef-attribute-validator/wildcard_expander/brutal_regex.rb
88
+ - lib/chef-attribute-validator/wildcard_expander/no_wildcards.rb
84
89
  - test/fixtures/attr_set.rb
85
90
  - test/fixtures/check_child_count.rb
86
91
  - test/fixtures/check_looks_like_arg_ip.rb
@@ -99,17 +104,22 @@ files:
99
104
  - test/fixtures/check_required_true.rb
100
105
  - test/fixtures/check_required_zero.rb
101
106
  - test/fixtures/check_type.rb
107
+ - test/fixtures/expander_brutal_deep_hash.rb
108
+ - test/fixtures/expander_brutal_deep_mixed.rb
109
+ - test/fixtures/expander_brutal_flat.rb
102
110
  - test/fixtures/rules_empty.rb
103
111
  - test/fixtures/rules_missing_path.rb
104
112
  - test/fixtures/rules_no_check.rb
105
113
  - test/fixtures/rules_type_and_min_children.rb
106
114
  - test/fixtures/rules_type_check.rb
107
115
  - test/unit/attr_set_spec.rb
116
+ - test/unit/attr_set_spec_wildcard.rb
108
117
  - test/unit/check_child_count_spec.rb
109
118
  - test/unit/check_looks_like_spec.rb
110
119
  - test/unit/check_regex_spec.rb
111
120
  - test/unit/check_required_spec.rb
112
121
  - test/unit/check_type_spec.rb
122
+ - test/unit/expanders/brutal_regex_spec.rb
113
123
  - test/unit/rule_parse_spec.rb
114
124
  - test/unit/spec_helper.rb
115
125
  homepage: https://github.com/clintoncwolfe/chef-attribute-validator
@@ -155,16 +165,21 @@ test_files:
155
165
  - test/fixtures/check_required_true.rb
156
166
  - test/fixtures/check_required_zero.rb
157
167
  - test/fixtures/check_type.rb
168
+ - test/fixtures/expander_brutal_deep_hash.rb
169
+ - test/fixtures/expander_brutal_deep_mixed.rb
170
+ - test/fixtures/expander_brutal_flat.rb
158
171
  - test/fixtures/rules_empty.rb
159
172
  - test/fixtures/rules_missing_path.rb
160
173
  - test/fixtures/rules_no_check.rb
161
174
  - test/fixtures/rules_type_and_min_children.rb
162
175
  - test/fixtures/rules_type_check.rb
163
176
  - test/unit/attr_set_spec.rb
177
+ - test/unit/attr_set_spec_wildcard.rb
164
178
  - test/unit/check_child_count_spec.rb
165
179
  - test/unit/check_looks_like_spec.rb
166
180
  - test/unit/check_regex_spec.rb
167
181
  - test/unit/check_required_spec.rb
168
182
  - test/unit/check_type_spec.rb
183
+ - test/unit/expanders/brutal_regex_spec.rb
169
184
  - test/unit/rule_parse_spec.rb
170
185
  - test/unit/spec_helper.rb