chef-zero 4.3.0 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -201
  3. data/README.md +155 -155
  4. data/Rakefile +31 -31
  5. data/bin/chef-zero +100 -100
  6. data/lib/chef_zero.rb +10 -10
  7. data/lib/chef_zero/chef_data/acl_path.rb +139 -139
  8. data/lib/chef_zero/chef_data/cookbook_data.rb +240 -240
  9. data/lib/chef_zero/chef_data/data_normalizer.rb +208 -207
  10. data/lib/chef_zero/chef_data/default_creator.rb +446 -446
  11. data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
  12. data/lib/chef_zero/data_store/data_error.rb +31 -31
  13. data/lib/chef_zero/data_store/data_not_found_error.rb +28 -28
  14. data/lib/chef_zero/data_store/default_facade.rb +149 -149
  15. data/lib/chef_zero/data_store/interface_v1.rb +67 -67
  16. data/lib/chef_zero/data_store/interface_v2.rb +18 -18
  17. data/lib/chef_zero/data_store/memory_store.rb +33 -33
  18. data/lib/chef_zero/data_store/memory_store_v2.rb +155 -155
  19. data/lib/chef_zero/data_store/raw_file_store.rb +147 -147
  20. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +142 -142
  21. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +107 -107
  22. data/lib/chef_zero/endpoints/acl_endpoint.rb +38 -38
  23. data/lib/chef_zero/endpoints/acls_endpoint.rb +29 -29
  24. data/lib/chef_zero/endpoints/actor_endpoint.rb +94 -94
  25. data/lib/chef_zero/endpoints/actors_endpoint.rb +64 -64
  26. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +31 -31
  27. data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
  28. data/lib/chef_zero/endpoints/containers_endpoint.rb +13 -13
  29. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
  30. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +119 -119
  31. data/lib/chef_zero/endpoints/cookbooks_base.rb +65 -65
  32. data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
  33. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
  34. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
  35. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
  36. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
  37. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +123 -123
  38. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
  39. data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
  40. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
  41. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
  42. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
  43. data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
  44. data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
  45. data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
  46. data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
  47. data/lib/chef_zero/endpoints/node_endpoint.rb +17 -17
  48. data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -22
  49. data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
  50. data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
  51. data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -30
  52. data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
  53. data/lib/chef_zero/endpoints/organization_endpoint.rb +46 -46
  54. data/lib/chef_zero/endpoints/organization_user_base.rb +15 -15
  55. data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -26
  56. data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -43
  57. data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
  58. data/lib/chef_zero/endpoints/organizations_endpoint.rb +62 -62
  59. data/lib/chef_zero/endpoints/policies_endpoint.rb +151 -151
  60. data/lib/chef_zero/endpoints/principal_endpoint.rb +42 -42
  61. data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
  62. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +63 -63
  63. data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
  64. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
  65. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
  66. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +50 -50
  67. data/lib/chef_zero/endpoints/search_endpoint.rb +194 -194
  68. data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
  69. data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -14
  70. data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
  71. data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +40 -40
  72. data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
  73. data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
  74. data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
  75. data/lib/chef_zero/endpoints/version_endpoint.rb +12 -12
  76. data/lib/chef_zero/log.rb +7 -7
  77. data/lib/chef_zero/rest_base.rb +242 -242
  78. data/lib/chef_zero/rest_error_response.rb +11 -11
  79. data/lib/chef_zero/rest_request.rb +69 -69
  80. data/lib/chef_zero/rest_router.rb +45 -45
  81. data/lib/chef_zero/rspec.rb +308 -308
  82. data/lib/chef_zero/server.rb +642 -642
  83. data/lib/chef_zero/socketless_server_map.rb +92 -92
  84. data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
  85. data/lib/chef_zero/solr/query/phrase.rb +23 -23
  86. data/lib/chef_zero/solr/query/range_query.rb +46 -46
  87. data/lib/chef_zero/solr/query/regexpable_query.rb +29 -29
  88. data/lib/chef_zero/solr/query/subquery.rb +37 -37
  89. data/lib/chef_zero/solr/query/term.rb +45 -45
  90. data/lib/chef_zero/solr/query/unary_operator.rb +43 -43
  91. data/lib/chef_zero/solr/solr_doc.rb +53 -53
  92. data/lib/chef_zero/solr/solr_parser.rb +203 -203
  93. data/lib/chef_zero/version.rb +3 -3
  94. data/spec/run_oc_pedant.rb +63 -63
  95. data/spec/search_spec.rb +32 -32
  96. data/spec/server_spec.rb +92 -92
  97. data/spec/socketless_server_map_spec.rb +76 -76
  98. data/spec/support/oc_pedant.rb +132 -132
  99. data/spec/support/stickywicket.pem +27 -27
  100. metadata +3 -3
@@ -1,67 +1,67 @@
1
- module ChefZero
2
- module DataStore
3
- class InterfaceV1
4
- def interface_version
5
- 1
6
- end
7
-
8
- def clear
9
- raise "clear not implemented by class #{self.class}"
10
- end
11
-
12
- # Create a directory.
13
- # options is a list of symbols, including:
14
- # :recursive - create any parents needed
15
- def create_dir(path, name, *options)
16
- raise "create_dir not implemented by class #{self.class}"
17
- end
18
-
19
- # Create a file.
20
- # options is a list of symbols, including:
21
- # :create_dir - create any parents needed
22
- def create(path, name, data, *options)
23
- raise "create not implemented by class #{self.class}"
24
- end
25
-
26
- # Get a file.
27
- def get(path, request=nil)
28
- raise "get not implemented by class #{self.class}"
29
- end
30
-
31
- # Set a file's value.
32
- # options is a list of symbols, including:
33
- # :create - create the file if it does not exist
34
- # :create_dir - create the directory if it does not exist
35
- def set(path, data, *options)
36
- raise "set not implemented by class #{self.class}"
37
- end
38
-
39
- # Delete a file.
40
- def delete(path)
41
- raise "delete not implemented by class #{self.class}"
42
- end
43
-
44
- # Delete a directory.
45
- # options is a list of symbols, including:
46
- # :recursive - delete even if empty
47
- def delete_dir(path, *options)
48
- raise "delete_dir not implemented by class #{self.class}"
49
- end
50
-
51
- # List a directory.
52
- def list(path)
53
- raise "list not implemented by class #{self.class}"
54
- end
55
-
56
- # Check a file's existence.
57
- def exists?(path)
58
- raise "exists? not implemented by class #{self.class}"
59
- end
60
-
61
- # Check a directory's existence.
62
- def exists_dir?(path)
63
- raise "exists_dir? not implemented by class #{self.class}"
64
- end
65
- end
66
- end
67
- end
1
+ module ChefZero
2
+ module DataStore
3
+ class InterfaceV1
4
+ def interface_version
5
+ 1
6
+ end
7
+
8
+ def clear
9
+ raise "clear not implemented by class #{self.class}"
10
+ end
11
+
12
+ # Create a directory.
13
+ # options is a list of symbols, including:
14
+ # :recursive - create any parents needed
15
+ def create_dir(path, name, *options)
16
+ raise "create_dir not implemented by class #{self.class}"
17
+ end
18
+
19
+ # Create a file.
20
+ # options is a list of symbols, including:
21
+ # :create_dir - create any parents needed
22
+ def create(path, name, data, *options)
23
+ raise "create not implemented by class #{self.class}"
24
+ end
25
+
26
+ # Get a file.
27
+ def get(path, request=nil)
28
+ raise "get not implemented by class #{self.class}"
29
+ end
30
+
31
+ # Set a file's value.
32
+ # options is a list of symbols, including:
33
+ # :create - create the file if it does not exist
34
+ # :create_dir - create the directory if it does not exist
35
+ def set(path, data, *options)
36
+ raise "set not implemented by class #{self.class}"
37
+ end
38
+
39
+ # Delete a file.
40
+ def delete(path)
41
+ raise "delete not implemented by class #{self.class}"
42
+ end
43
+
44
+ # Delete a directory.
45
+ # options is a list of symbols, including:
46
+ # :recursive - delete even if empty
47
+ def delete_dir(path, *options)
48
+ raise "delete_dir not implemented by class #{self.class}"
49
+ end
50
+
51
+ # List a directory.
52
+ def list(path)
53
+ raise "list not implemented by class #{self.class}"
54
+ end
55
+
56
+ # Check a file's existence.
57
+ def exists?(path)
58
+ raise "exists? not implemented by class #{self.class}"
59
+ end
60
+
61
+ # Check a directory's existence.
62
+ def exists_dir?(path)
63
+ raise "exists_dir? not implemented by class #{self.class}"
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,18 +1,18 @@
1
- require 'chef_zero/data_store/interface_v1'
2
-
3
- module ChefZero
4
- module DataStore
5
- # V2 assumes paths starting with /organizations/ORGNAME. It also REQUIRES that
6
- # new organizations have these defaults:
7
- # chef-validator client: '{ "validator": true }',
8
- # chef-webui client: '{ "admin": true }'
9
- # _default environment: '{ "description": "The default Chef environment" }'
10
- # admin user: '{ "admin": "true" }'
11
-
12
- class InterfaceV2 < ChefZero::DataStore::InterfaceV1
13
- def interface_version
14
- 2
15
- end
16
- end
17
- end
18
- end
1
+ require 'chef_zero/data_store/interface_v1'
2
+
3
+ module ChefZero
4
+ module DataStore
5
+ # V2 assumes paths starting with /organizations/ORGNAME. It also REQUIRES that
6
+ # new organizations have these defaults:
7
+ # chef-validator client: '{ "validator": true }',
8
+ # chef-webui client: '{ "admin": true }'
9
+ # _default environment: '{ "description": "The default Chef environment" }'
10
+ # admin user: '{ "admin": "true" }'
11
+
12
+ class InterfaceV2 < ChefZero::DataStore::InterfaceV1
13
+ def interface_version
14
+ 2
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,33 +1,33 @@
1
- #
2
- # Author:: John Keiser (<jkeiser@opscode.com>)
3
- # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'chef_zero/data_store/v2_to_v1_adapter'
20
- require 'chef_zero/data_store/memory_store_v2'
21
- require 'chef_zero/data_store/default_facade'
22
-
23
- module ChefZero
24
- module DataStore
25
- class MemoryStore < ChefZero::DataStore::V2ToV1Adapter
26
- def initialize
27
- super
28
- @real_store = ChefZero::DataStore::DefaultFacade.new(ChefZero::DataStore::MemoryStoreV2.new, 'chef', true)
29
- clear
30
- end
31
- end
32
- end
33
- end
1
+ #
2
+ # Author:: John Keiser (<jkeiser@opscode.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef_zero/data_store/v2_to_v1_adapter'
20
+ require 'chef_zero/data_store/memory_store_v2'
21
+ require 'chef_zero/data_store/default_facade'
22
+
23
+ module ChefZero
24
+ module DataStore
25
+ class MemoryStore < ChefZero::DataStore::V2ToV1Adapter
26
+ def initialize
27
+ super
28
+ @real_store = ChefZero::DataStore::DefaultFacade.new(ChefZero::DataStore::MemoryStoreV2.new, 'chef', true)
29
+ clear
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,155 +1,155 @@
1
- #
2
- # Author:: John Keiser (<jkeiser@opscode.com>)
3
- # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'chef_zero/data_store/data_already_exists_error'
20
- require 'chef_zero/data_store/data_not_found_error'
21
- require 'chef_zero/data_store/interface_v2'
22
-
23
- module ChefZero
24
- module DataStore
25
- class MemoryStoreV2 < ChefZero::DataStore::InterfaceV2
26
- def initialize
27
- clear
28
- end
29
-
30
- attr_reader :data
31
-
32
- def clear
33
- @data = {}
34
- end
35
-
36
- def create_dir(path, name, *options)
37
- parent = _get(path, options.include?(:recursive))
38
-
39
- if parent.has_key?(name)
40
- if !options.include?(:recursive)
41
- raise DataAlreadyExistsError.new(path + [name])
42
- end
43
- else
44
- parent[name] = {}
45
- end
46
- end
47
-
48
- def create(path, name, data, *options)
49
- if !data.is_a?(String)
50
- raise "set only works with strings (given data: #{data.inspect})"
51
- end
52
-
53
- parent = _get(path, options.include?(:create_dir))
54
-
55
- if parent.has_key?(name)
56
- raise DataAlreadyExistsError.new(path + [name])
57
- end
58
- parent[name] = data
59
- end
60
-
61
- def get(path, request=nil)
62
- value = _get(path)
63
- if value.is_a?(Hash)
64
- raise "get() called on directory #{path.join('/')}"
65
- end
66
- value
67
- end
68
-
69
- def set(path, data, *options)
70
- if !data.is_a?(String)
71
- raise "set only works with strings: #{path} = #{data.inspect}"
72
- end
73
-
74
- # Get the parent
75
- parent = _get(path[0..-2], options.include?(:create_dir))
76
-
77
- if !options.include?(:create) && !parent[path[-1]]
78
- raise DataNotFoundError.new(path)
79
- end
80
- parent[path[-1]] = data
81
- end
82
-
83
- def delete(path)
84
- parent = _get(path[0,path.length-1])
85
- if !parent.has_key?(path[-1])
86
- raise DataNotFoundError.new(path)
87
- end
88
- if !parent[path[-1]].is_a?(String)
89
- raise "delete only works with strings: #{path}"
90
- end
91
- parent.delete(path[-1])
92
- end
93
-
94
- def delete_dir(path, *options)
95
- parent = _get(path[0,path.length-1])
96
- if !parent.has_key?(path[-1])
97
- raise DataNotFoundError.new(path)
98
- end
99
- if !parent[path[-1]].is_a?(Hash)
100
- raise "delete_dir only works with directories: #{path}"
101
- end
102
- parent.delete(path[-1])
103
- end
104
-
105
- def list(path)
106
- dir = _get(path)
107
- if !dir.is_a? Hash
108
- raise "list only works with directories (#{path} = #{dir.class})"
109
- end
110
- dir.keys.sort
111
- end
112
-
113
- def exists?(path, options = {})
114
- begin
115
- value = _get(path)
116
- if value.is_a?(Hash) && !options[:allow_dirs]
117
- raise "exists? does not work with directories (#{path} = #{value.class})"
118
- end
119
- return true
120
- rescue DataNotFoundError
121
- return false
122
- end
123
- end
124
-
125
- def exists_dir?(path)
126
- begin
127
- dir = _get(path)
128
- if !dir.is_a? Hash
129
- raise "exists_dir? only works with directories (#{path} = #{dir.class})"
130
- end
131
- return true
132
- rescue DataNotFoundError
133
- return false
134
- end
135
- end
136
-
137
- private
138
-
139
- def _get(path, create_dir=false)
140
- value = @data
141
- path.each_with_index do |path_part, index|
142
- if !value.has_key?(path_part)
143
- if create_dir
144
- value[path_part] = {}
145
- else
146
- raise DataNotFoundError.new(path[0,index+1])
147
- end
148
- end
149
- value = value[path_part]
150
- end
151
- value
152
- end
153
- end
154
- end
155
- end
1
+ #
2
+ # Author:: John Keiser (<jkeiser@opscode.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef_zero/data_store/data_already_exists_error'
20
+ require 'chef_zero/data_store/data_not_found_error'
21
+ require 'chef_zero/data_store/interface_v2'
22
+
23
+ module ChefZero
24
+ module DataStore
25
+ class MemoryStoreV2 < ChefZero::DataStore::InterfaceV2
26
+ def initialize
27
+ clear
28
+ end
29
+
30
+ attr_reader :data
31
+
32
+ def clear
33
+ @data = {}
34
+ end
35
+
36
+ def create_dir(path, name, *options)
37
+ parent = _get(path, options.include?(:recursive))
38
+
39
+ if parent.has_key?(name)
40
+ if !options.include?(:recursive)
41
+ raise DataAlreadyExistsError.new(path + [name])
42
+ end
43
+ else
44
+ parent[name] = {}
45
+ end
46
+ end
47
+
48
+ def create(path, name, data, *options)
49
+ if !data.is_a?(String)
50
+ raise "set only works with strings (given data: #{data.inspect})"
51
+ end
52
+
53
+ parent = _get(path, options.include?(:create_dir))
54
+
55
+ if parent.has_key?(name)
56
+ raise DataAlreadyExistsError.new(path + [name])
57
+ end
58
+ parent[name] = data
59
+ end
60
+
61
+ def get(path, request=nil)
62
+ value = _get(path)
63
+ if value.is_a?(Hash)
64
+ raise "get() called on directory #{path.join('/')}"
65
+ end
66
+ value
67
+ end
68
+
69
+ def set(path, data, *options)
70
+ if !data.is_a?(String)
71
+ raise "set only works with strings: #{path} = #{data.inspect}"
72
+ end
73
+
74
+ # Get the parent
75
+ parent = _get(path[0..-2], options.include?(:create_dir))
76
+
77
+ if !options.include?(:create) && !parent[path[-1]]
78
+ raise DataNotFoundError.new(path)
79
+ end
80
+ parent[path[-1]] = data
81
+ end
82
+
83
+ def delete(path)
84
+ parent = _get(path[0,path.length-1])
85
+ if !parent.has_key?(path[-1])
86
+ raise DataNotFoundError.new(path)
87
+ end
88
+ if !parent[path[-1]].is_a?(String)
89
+ raise "delete only works with strings: #{path}"
90
+ end
91
+ parent.delete(path[-1])
92
+ end
93
+
94
+ def delete_dir(path, *options)
95
+ parent = _get(path[0,path.length-1])
96
+ if !parent.has_key?(path[-1])
97
+ raise DataNotFoundError.new(path)
98
+ end
99
+ if !parent[path[-1]].is_a?(Hash)
100
+ raise "delete_dir only works with directories: #{path}"
101
+ end
102
+ parent.delete(path[-1])
103
+ end
104
+
105
+ def list(path)
106
+ dir = _get(path)
107
+ if !dir.is_a? Hash
108
+ raise "list only works with directories (#{path} = #{dir.class})"
109
+ end
110
+ dir.keys.sort
111
+ end
112
+
113
+ def exists?(path, options = {})
114
+ begin
115
+ value = _get(path)
116
+ if value.is_a?(Hash) && !options[:allow_dirs]
117
+ raise "exists? does not work with directories (#{path} = #{value.class})"
118
+ end
119
+ return true
120
+ rescue DataNotFoundError
121
+ return false
122
+ end
123
+ end
124
+
125
+ def exists_dir?(path)
126
+ begin
127
+ dir = _get(path)
128
+ if !dir.is_a? Hash
129
+ raise "exists_dir? only works with directories (#{path} = #{dir.class})"
130
+ end
131
+ return true
132
+ rescue DataNotFoundError
133
+ return false
134
+ end
135
+ end
136
+
137
+ private
138
+
139
+ def _get(path, create_dir=false)
140
+ value = @data
141
+ path.each_with_index do |path_part, index|
142
+ if !value.has_key?(path_part)
143
+ if create_dir
144
+ value[path_part] = {}
145
+ else
146
+ raise DataNotFoundError.new(path[0,index+1])
147
+ end
148
+ end
149
+ value = value[path_part]
150
+ end
151
+ value
152
+ end
153
+ end
154
+ end
155
+ end