chef-attribute-validator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +20 -0
  3. data/CHANGES +4 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +27 -0
  6. data/README.md +109 -0
  7. data/Rakefile +27 -0
  8. data/chef-attribute-validator.gemspec +25 -0
  9. data/lib/chef-attribute-validator.rb +52 -0
  10. data/lib/chef-attribute-validator/attribute_set.rb +90 -0
  11. data/lib/chef-attribute-validator/check.rb +56 -0
  12. data/lib/chef-attribute-validator/checks/looks_like.rb +52 -0
  13. data/lib/chef-attribute-validator/checks/max_children.rb +37 -0
  14. data/lib/chef-attribute-validator/checks/min_children.rb +37 -0
  15. data/lib/chef-attribute-validator/checks/regex.rb +31 -0
  16. data/lib/chef-attribute-validator/checks/required.rb +42 -0
  17. data/lib/chef-attribute-validator/checks/type.rb +48 -0
  18. data/lib/chef-attribute-validator/rule.rb +54 -0
  19. data/lib/chef-attribute-validator/version.rb +7 -0
  20. data/lib/chef-attribute-validator/violation.rb +17 -0
  21. data/test/fixtures/attr_set.rb +10 -0
  22. data/test/fixtures/check_child_count.rb +104 -0
  23. data/test/fixtures/check_looks_like_arg_ip.rb +6 -0
  24. data/test/fixtures/check_looks_like_arg_regex.rb +6 -0
  25. data/test/fixtures/check_looks_like_arg_url.rb +6 -0
  26. data/test/fixtures/check_looks_like_arg_your_mom.rb +6 -0
  27. data/test/fixtures/check_looks_like_ip.rb +57 -0
  28. data/test/fixtures/check_looks_like_url.rb +39 -0
  29. data/test/fixtures/check_regex_assorted.rb +42 -0
  30. data/test/fixtures/check_regex_literal.rb +5 -0
  31. data/test/fixtures/check_regex_nil.rb +5 -0
  32. data/test/fixtures/check_regex_object.rb +5 -0
  33. data/test/fixtures/check_regex_string.rb +5 -0
  34. data/test/fixtures/check_required_assorted.rb +82 -0
  35. data/test/fixtures/check_required_false.rb +5 -0
  36. data/test/fixtures/check_required_true.rb +5 -0
  37. data/test/fixtures/check_required_zero.rb +5 -0
  38. data/test/fixtures/check_type.rb +270 -0
  39. data/test/fixtures/rules_empty.rb +2 -0
  40. data/test/fixtures/rules_missing_path.rb +1 -0
  41. data/test/fixtures/rules_no_check.rb +1 -0
  42. data/test/fixtures/rules_type_and_min_children.rb +3 -0
  43. data/test/fixtures/rules_type_check.rb +2 -0
  44. data/test/unit/attr_set_spec.rb +55 -0
  45. data/test/unit/check_child_count_spec.rb +109 -0
  46. data/test/unit/check_looks_like_spec.rb +106 -0
  47. data/test/unit/check_regex_spec.rb +62 -0
  48. data/test/unit/check_required_spec.rb +106 -0
  49. data/test/unit/check_type_spec.rb +191 -0
  50. data/test/unit/rule_parse_spec.rb +93 -0
  51. data/test/unit/spec_helper.rb +18 -0
  52. metadata +170 -0
@@ -0,0 +1,2 @@
1
+ # Empty attributes file
2
+ default['attribute-validator']['rules'] = {}
@@ -0,0 +1 @@
1
+ default['attribute-validator']['rules']['test-missing-path']['enabled'] = true
@@ -0,0 +1 @@
1
+ default['attribute-validator']['rules']['test-no-check-rule']['path'] = '/*'
@@ -0,0 +1,3 @@
1
+ default['attribute-validator']['rules']['test-type-and-min-children-rule']['path'] = '/*'
2
+ default['attribute-validator']['rules']['test-type-and-min-children-rule']['type'] = 'array'
3
+ default['attribute-validator']['rules']['test-type-and-min-children-rule']['min_children'] = 1
@@ -0,0 +1,2 @@
1
+ default['attribute-validator']['rules']['test-type-rule']['path'] = '/*'
2
+ default['attribute-validator']['rules']['test-type-rule']['type'] = 'string'
@@ -0,0 +1,55 @@
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
+ end
@@ -0,0 +1,109 @@
1
+ require_relative './spec_helper'
2
+
3
+ # Verify that the 'type' check works correctly
4
+
5
+
6
+ describe "'min_children' check" do
7
+
8
+ let(:node) { CAVHelper.load_fixture_attributes('check_child_count') }
9
+ let(:av) { Chef::Attribute::Validator.new(node) }
10
+
11
+ it "should be present in the Check registry" do
12
+ expect(Chef::Attribute::Validator::Check.list_check_types).to include('min_children')
13
+ end
14
+
15
+ it "should violate on nil" do
16
+ expect(av.validate_rule('min-nil')).not_to be_empty
17
+ end
18
+
19
+ it "should violate on string" do
20
+ expect(av.validate_rule('min-string')).not_to be_empty
21
+ end
22
+
23
+ context "when examining an array" do
24
+ it "should not violate when min is 0 and array is empty" do
25
+ expect(av.validate_rule('min-array-empty-zero')).to be_empty
26
+ end
27
+
28
+ it "should violate when min is 1 and array is empty" do
29
+ expect(av.validate_rule('min-array-empty-one')).not_to be_empty
30
+ end
31
+
32
+ it "should violate when min is 2 and array is 1" do
33
+ expect(av.validate_rule('min-array-one-two')).not_to be_empty
34
+ end
35
+ end
36
+
37
+ context "when examining a hash" do
38
+ it "should not violate when min is 0 and hash is empty" do
39
+ expect(av.validate_rule('min-hash-empty-zero')).to be_empty
40
+ end
41
+
42
+ it "should violate when min is 1 and hash is empty" do
43
+ expect(av.validate_rule('min-hash-empty-one')).not_to be_empty
44
+ end
45
+
46
+ it "should violate when min is 2 and hash is 1" do
47
+ expect(av.validate_rule('min-hash-one-two')).not_to be_empty
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ describe "'max_children' check" do
54
+
55
+ let(:node) { CAVHelper.load_fixture_attributes('check_child_count') }
56
+ let(:av) { Chef::Attribute::Validator.new(node) }
57
+
58
+ it "should be present in the Check registry" do
59
+ expect(Chef::Attribute::Validator::Check.list_check_types).to include('max_children')
60
+ end
61
+
62
+ it "should violate on nil" do
63
+ expect(av.validate_rule('max-nil')).not_to be_empty
64
+ end
65
+
66
+ it "should violate on string" do
67
+ expect(av.validate_rule('max-string')).not_to be_empty
68
+ end
69
+
70
+ context "when examining an array" do
71
+ it "should not violate when max is 0 and array is empty" do
72
+ expect(av.validate_rule('max-array-empty-zero')).to be_empty
73
+ end
74
+
75
+ it "should violate when max is 0 and array is 1" do
76
+ expect(av.validate_rule('max-array-zero-one')).not_to be_empty
77
+ end
78
+
79
+ it "should violate when max is 1 and array is 2" do
80
+ expect(av.validate_rule('max-array-one-two')).not_to be_empty
81
+ end
82
+
83
+ it "should not violate when max is 2 and array is 2" do
84
+ expect(av.validate_rule('max-array-two-two')).to be_empty
85
+ end
86
+
87
+ end
88
+
89
+ context "when examining a hash" do
90
+ it "should not violate when max is 0 and hash is empty" do
91
+ expect(av.validate_rule('max-hash-empty-zero')).to be_empty
92
+ end
93
+
94
+ it "should violate when max is 0 and hash is one" do
95
+ expect(av.validate_rule('max-hash-zero-one')).not_to be_empty
96
+ end
97
+
98
+ it "should violate when max is 1 and hash is 2" do
99
+ expect(av.validate_rule('max-hash-one-two')).not_to be_empty
100
+ end
101
+
102
+ it "should not violate when max is 2 and hash is 2" do
103
+ expect(av.validate_rule('max-hash-two-two')).to be_empty
104
+ end
105
+
106
+ end
107
+
108
+
109
+ end
@@ -0,0 +1,106 @@
1
+ require_relative './spec_helper'
2
+
3
+ # Verify that the 'looks_like' check works correctly
4
+
5
+
6
+ describe "'looks_like' check" do
7
+
8
+ describe "check registry" do
9
+ it "should be present in the Check registry" do
10
+ expect(Chef::Attribute::Validator::Check.list_check_types).to include('looks_like')
11
+ end
12
+ end
13
+
14
+ describe "check_arg checks" do
15
+ it "should accept 'ip'" do
16
+ node = CAVHelper.load_fixture_attributes('check_looks_like_arg_ip')
17
+ expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
18
+ end
19
+ it "should accept 'url'" do
20
+ node = CAVHelper.load_fixture_attributes('check_looks_like_arg_url')
21
+ expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
22
+ end
23
+ it "should reject 'your mom'" do
24
+ node = CAVHelper.load_fixture_attributes('check_looks_like_arg_your_mom')
25
+ expect { Chef::Attribute::Validator.new(node) }.to raise_error
26
+ end
27
+ it "should reject a regex" do
28
+ node = CAVHelper.load_fixture_attributes('check_looks_like_arg_regex')
29
+ expect { Chef::Attribute::Validator.new(node) }.to raise_error
30
+ end
31
+ end
32
+
33
+ context "when the mode is 'ip'" do
34
+ let(:node) { CAVHelper.load_fixture_attributes('check_looks_like_ip') }
35
+ let(:av) { Chef::Attribute::Validator.new(node) }
36
+
37
+ it "should not violate on missing" do
38
+ expect(av.validate_rule('ip-missing')).to be_empty
39
+ end
40
+
41
+ it "should not violate on nil" do
42
+ expect(av.validate_rule('ip-nil')).to be_empty
43
+ end
44
+
45
+ it "should violate on 1234.123.1.1" do
46
+ expect(av.validate_rule('ip-malformed')).not_to be_empty
47
+ end
48
+
49
+ it "should violate on 300.300.300.1" do
50
+ expect(av.validate_rule('ip-deranged')).not_to be_empty
51
+ end
52
+
53
+ it "should violate on 123.123.123" do
54
+ expect(av.validate_rule('ip-3not4')).not_to be_empty
55
+ end
56
+
57
+ it "should not violate on 1.1.1.1" do
58
+ expect(av.validate_rule('ip-allones')).to be_empty
59
+ end
60
+
61
+ it "should not violate on 1.1.1.1/24" do
62
+ expect(av.validate_rule('ip-slash24')).to be_empty
63
+ end
64
+
65
+ it "should not violate on 255.255.255.255" do
66
+ expect(av.validate_rule('ip-merryxmas')).to be_empty
67
+ end
68
+
69
+ it "should not violate on ::" do
70
+ expect(av.validate_rule('ip-emptyv6')).to be_empty
71
+ end
72
+ end
73
+
74
+ context "when the mode is 'url'" do
75
+ let(:node) { CAVHelper.load_fixture_attributes('check_looks_like_url') }
76
+ let(:av) { Chef::Attribute::Validator.new(node) }
77
+
78
+ it "should not violate on missing" do
79
+ expect(av.validate_rule('url-missing')).to be_empty
80
+ end
81
+
82
+ it "should not violate on nil" do
83
+ expect(av.validate_rule('url-nil')).to be_empty
84
+ end
85
+
86
+ it "should not violate on 'http://wwwwwwww.jodi.org'" do
87
+ expect(av.validate_rule('url-http-basic')).to be_empty
88
+ end
89
+
90
+ it "should not violate on 'http://example.com/'" do
91
+ expect(av.validate_rule('url-http-trailing-slash')).to be_empty
92
+ end
93
+
94
+ it "should not violate on 'http://example.com:8080/'" do
95
+ expect(av.validate_rule('url-http-port')).to be_empty
96
+ end
97
+
98
+ it "should not violate on 'http://localhost'" do
99
+ expect(av.validate_rule('url-http-localhost')).to be_empty
100
+ end
101
+
102
+ end
103
+
104
+
105
+
106
+ end
@@ -0,0 +1,62 @@
1
+ require_relative './spec_helper'
2
+
3
+ # Verify that the 'regex' check works correctly
4
+
5
+
6
+ describe "'regex' check" do
7
+
8
+ describe "check registry" do
9
+ it "should be present in the Check registry" do
10
+ expect(Chef::Attribute::Validator::Check.list_check_types).to include('regex')
11
+ end
12
+ end
13
+
14
+ describe "check_arg checks" do
15
+ it "should accept a // literal regex" do
16
+ node = CAVHelper.load_fixture_attributes('check_regex_literal')
17
+ expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
18
+ end
19
+ it "should accept a Regexp object" do
20
+ node = CAVHelper.load_fixture_attributes('check_regex_object')
21
+ expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
22
+ end
23
+ it "should reject a string" do
24
+ node = CAVHelper.load_fixture_attributes('check_regex_string')
25
+ expect { Chef::Attribute::Validator.new(node) }.to raise_error
26
+ end
27
+ it "should reject a nil regex" do
28
+ node = CAVHelper.load_fixture_attributes('check_regex_nil')
29
+ expect { Chef::Attribute::Validator.new(node) }.to raise_error
30
+ end
31
+ end
32
+
33
+ describe "assorted regexes" do
34
+ let(:node) { CAVHelper.load_fixture_attributes('check_regex_assorted') }
35
+ let(:av) { Chef::Attribute::Validator.new(node) }
36
+
37
+ it "/^$/ should not violate on an empty string" do
38
+ expect(av.validate_rule('empty-empty')).to be_empty
39
+ end
40
+
41
+ it "/foo/ should not violate on foo" do
42
+ expect(av.validate_rule('foo-foo')).to be_empty
43
+ end
44
+
45
+ it "/foo/ should not violate on food" do
46
+ expect(av.validate_rule('foo-food')).to be_empty
47
+ end
48
+
49
+ it "/foo/ should violate on victuals" do
50
+ expect(av.validate_rule('foo-victuals')).not_to be_empty
51
+ end
52
+
53
+ it "/^(?!foo)/ should not violate on bar" do
54
+ expect(av.validate_rule('not-foo-bar')).to be_empty
55
+ end
56
+
57
+ it "/^(?!foo)/ should violate on foo" do
58
+ expect(av.validate_rule('not-foo-foo')).not_to be_empty
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,106 @@
1
+ require_relative './spec_helper'
2
+
3
+ # Verify that the 'required' check works correctly
4
+
5
+ describe "'required' check" do
6
+
7
+ describe "check registry" do
8
+ it "should be present in the Check registry" do
9
+ expect(Chef::Attribute::Validator::Check.list_check_types).to include('required')
10
+ end
11
+ end
12
+
13
+ describe "check_arg checks" do
14
+ it "should accept true" do
15
+ node = CAVHelper.load_fixture_attributes('check_required_true')
16
+ expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
17
+ end
18
+ it "should accept false" do
19
+ node = CAVHelper.load_fixture_attributes('check_required_false')
20
+ expect { Chef::Attribute::Validator.new(node) }.not_to raise_error
21
+ end
22
+ it "should reject 0" do
23
+ node = CAVHelper.load_fixture_attributes('check_required_zero')
24
+ expect { Chef::Attribute::Validator.new(node) }.to raise_error
25
+ end
26
+ end
27
+
28
+ context "when required, but the attribute is missing" do
29
+ let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
30
+ let(:av) { Chef::Attribute::Validator.new(node) }
31
+
32
+ it "should violate when the attribute is missing, shallow" do
33
+ expect(av.validate_rule('missing-shallow')).not_to be_empty
34
+ end
35
+
36
+ it "should violate when the attribute is missing, deep" do
37
+ expect(av.validate_rule('missing-deep')).not_to be_empty
38
+ end
39
+ end
40
+
41
+ context "when required, but the value is missing" do
42
+ let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
43
+ let(:av) { Chef::Attribute::Validator.new(node) }
44
+
45
+ it "should violate when the value is nil" do
46
+ expect(av.validate_rule('value-nil')).not_to be_empty
47
+ end
48
+
49
+ it "should violate when the value is an empty string" do
50
+ expect(av.validate_rule('value-empty-string')).not_to be_empty
51
+ end
52
+
53
+ it "should violate when the value is an empty array" do
54
+ expect(av.validate_rule('value-empty-array')).not_to be_empty
55
+ end
56
+
57
+ it "should violate when the value is an empty hash" do
58
+ expect(av.validate_rule('value-empty-hash')).not_to be_empty
59
+ end
60
+ end
61
+
62
+ context "when required, and a value is present" do
63
+ let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
64
+ let(:av) { Chef::Attribute::Validator.new(node) }
65
+
66
+ it "should not violate when the value is a string " do
67
+ expect(av.validate_rule('value-present-string')).to be_empty
68
+ end
69
+
70
+ it "should not violate when the value is false " do
71
+ expect(av.validate_rule('value-present-false')).to be_empty
72
+ end
73
+
74
+ it "should not violate when the value is zero " do
75
+ expect(av.validate_rule('value-present-zero')).to be_empty
76
+ end
77
+
78
+ it "should not violate when the value is a non-empty array " do
79
+ expect(av.validate_rule('value-present-array')).to be_empty
80
+ end
81
+
82
+ it "should not violate when the value is a non-empty hash" do
83
+ expect(av.validate_rule('value-present-hash')).to be_empty
84
+ end
85
+ end
86
+
87
+ context "when not required, but the value is present" do
88
+ let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
89
+ let(:av) { Chef::Attribute::Validator.new(node) }
90
+
91
+ it "should not violate when the value is a string" do
92
+ expect(av.validate_rule('optional-present-string')).to be_empty
93
+ end
94
+ end
95
+
96
+ context "when not required, but the attribute is missing" do
97
+ let(:node) { CAVHelper.load_fixture_attributes('check_required_assorted') }
98
+ let(:av) { Chef::Attribute::Validator.new(node) }
99
+
100
+ it "should not violate when the attribute is missing" do
101
+ expect(av.validate_rule('optional-missing')).to be_empty
102
+ end
103
+ end
104
+
105
+
106
+ end